use alloc::boxed::Box;
use core::sync::atomic::Ordering;
use crate::{fxmac_const::*, fxmac_dma::*, fxmac_intr::*, fxmac_phy::*, utils::*};
pub const FXMAC_HANDLER_DMASEND: u32 = 1;
pub const FXMAC_HANDLER_DMARECV: u32 = 2;
pub const FXMAC_HANDLER_ERROR: u32 = 3;
pub const FXMAC_HANDLER_LINKCHANGE: u32 = 4;
pub const FXMAC_HANDLER_RESTART: u32 = 5;
pub const FXMAC_LINKDOWN: u32 = 0;
pub const FXMAC_LINKUP: u32 = 1;
pub const FXMAC_NEGOTIATING: u32 = 2;
pub const FXMAC0_PCLK: u32 = 50000000;
pub const FXMAC0_HOTPLUG_IRQ_NUM: u32 = 53 + 30;
pub const FXMAC_QUEUE_MAX_NUM: u32 = 4;
pub const ULONG64_HI_MASK: u64 = 0xFFFFFFFF00000000;
pub const ULONG64_LO_MASK: u64 = !ULONG64_HI_MASK;
pub const FT_COMPONENT_IS_READY: u32 = 0x11111111;
pub const FT_COMPONENT_IS_STARTED: u32 = 0x22222222;
pub const PAGE_SIZE: usize = 4096;
pub(crate) const FXMAC_IOBASE: u64 = 0x3200c000;
pub struct FXmac {
pub config: FXmacConfig,
pub is_ready: u32,
pub is_started: u32,
pub link_status: u32,
pub options: u32,
pub mask: u32,
pub caps: u32,
pub lwipport: FXmacLwipPort,
pub tx_bd_queue: FXmacQueue,
pub rx_bd_queue: FXmacQueue,
pub moudle_id: u32,
pub max_mtu_size: u32,
pub max_frame_size: u32,
pub phy_address: u32,
pub rxbuf_mask: u32,
}
unsafe impl Send for FXmac {}
unsafe impl Sync for FXmac {}
pub struct FXmacConfig {
pub instance_id: u32,
pub base_address: u64,
pub extral_mode_base: u64,
pub extral_loopback_base: u64,
pub interface: FXmacPhyInterface,
pub speed: u32,
pub duplex: u32,
pub auto_neg: u32,
pub pclk_hz: u32,
pub max_queue_num: u32,
pub tx_queue_id: u32,
pub rx_queue_id: u32,
pub hotplug_irq_num: u32,
pub dma_brust_length: u32,
pub network_default_config: u32,
pub queue_irq_num: [u32; FXMAC_QUEUE_MAX_NUM as usize],
pub caps: u32,
pub mac: [u8; 6],
}
pub struct FXmacQueue {
pub queue_id: u32,
pub bdring: FXmacBdRing,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FXmacPhyInterface {
FXMAC_PHY_INTERFACE_MODE_SGMII = 0,
FXMAC_PHY_INTERFACE_MODE_RMII = 1,
FXMAC_PHY_INTERFACE_MODE_RGMII = 2,
FXMAC_PHY_INTERFACE_MODE_XGMII = 3,
FXMAC_PHY_INTERFACE_MODE_USXGMII = 4,
FXMAC_PHY_INTERFACE_MODE_5GBASER = 5,
FXMAC_PHY_INTERFACE_MODE_2500BASEX = 6,
}
pub fn read_reg<T>(src: *const T) -> T {
unsafe {
core::ptr::read_volatile(ax_crate_interface::call_interface!(
crate::KernelFunc::phys_to_virt(src as usize)
) as *const T)
}
}
pub fn write_reg<T>(dst: *mut T, value: T) {
unsafe {
core::ptr::write_volatile(
ax_crate_interface::call_interface!(crate::KernelFunc::phys_to_virt(dst as usize))
as *mut T,
value,
);
}
}
pub fn xmac_init(hwaddr: &[u8; 6]) -> &'static mut FXmac {
let mut mac_config: FXmacConfig = FXmacConfig {
instance_id: FXMAC0_ID,
base_address: FXMAC0_BASE_ADDR as u64,
extral_mode_base: FXMAC0_MODE_SEL_BASE_ADDR as u64,
extral_loopback_base: FXMAC0_LOOPBACK_SEL_BASE_ADDR as u64,
interface: FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_SGMII,
speed: 100,
duplex: 1,
auto_neg: 0,
pclk_hz: FXMAC0_PCLK,
max_queue_num: 4, tx_queue_id: 0,
rx_queue_id: 0,
hotplug_irq_num: FXMAC0_HOTPLUG_IRQ_NUM,
dma_brust_length: 16,
network_default_config: FXMAC_DEFAULT_OPTIONS,
queue_irq_num: [
FXMAC0_QUEUE0_IRQ_NUM,
FXMAC0_QUEUE1_IRQ_NUM,
FXMAC0_QUEUE2_IRQ_NUM,
FXMAC0_QUEUE3_IRQ_NUM,
],
caps: 0,
mac: *hwaddr,
};
let mut xmac = FXmac {
config: mac_config,
is_ready: FT_COMPONENT_IS_READY,
is_started: 0,
link_status: FXMAC_LINKDOWN,
options: 0,
mask: 0,
caps: 0,
lwipport: FXmacLwipPort {
buffer: FXmacNetifBuffer::default(),
feature: FXMAC_LWIP_PORT_CONFIG_MULTICAST_ADDRESS_FILITER,
hwaddr: *hwaddr,
recv_flg: 0,
},
tx_bd_queue: FXmacQueue {
queue_id: 0,
bdring: FXmacBdRing::default(),
},
rx_bd_queue: FXmacQueue {
queue_id: 0,
bdring: FXmacBdRing::default(),
},
moudle_id: 0,
max_mtu_size: 0,
max_frame_size: 0,
phy_address: 0,
rxbuf_mask: 0,
};
let mut status: u32 = 0;
FXmacReset(&mut xmac);
xmac.mask = FXMAC_IXR_LINKCHANGE_MASK
| FXMAC_IXR_TX_ERR_MASK
| FXMAC_IXR_RX_ERR_MASK
| FXMAC_IXR_RXCOMPL_MASK;
if (xmac.config.caps & FXMAC_CAPS_TAILPTR) != 0 {
FXmacSetOptions(&mut xmac, FXMAC_TAIL_PTR_OPTION, 0);
xmac.mask &= !FXMAC_IXR_TXUSED_MASK;
}
FxmacFeatureSetOptions(xmac.lwipport.feature, &mut xmac);
status = FXmacSetMacAddress(&xmac.lwipport.hwaddr, 0);
if xmac.config.interface != FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_USXGMII {
status = FXmacPhyInit(&mut xmac, XMAC_PHY_RESET_ENABLE);
if status != 0 {
warn!("FXmacPhyInit is error");
}
} else {
info!("interface == FXMAC_PHY_INTERFACE_MODE_USXGMII");
}
FXmacSelectClk(&mut xmac);
FXmacInitInterface(&mut xmac);
let mut dmacrreg: u32 = read_reg((xmac.config.base_address + FXMAC_DMACR_OFFSET) as *const u32);
dmacrreg &= !(FXMAC_DMACR_BLENGTH_MASK);
dmacrreg |= FXMAC_DMACR_INCR16_AHB_AXI_BURST;
write_reg(
(xmac.config.base_address + FXMAC_DMACR_OFFSET) as *mut u32,
dmacrreg,
);
FXmacInitDma(&mut xmac);
FXmacSetupIsr(&mut xmac);
if (xmac.lwipport.feature & FXMAC_LWIP_PORT_CONFIG_UNICAST_ADDRESS_FILITER) != 0 {
debug!("Set unicast hash table");
FXmac_SetHash(&mut xmac, hwaddr);
}
FXmacStart(&mut xmac);
let xmac_ref = Box::leak(Box::new(xmac));
XMAC.store(xmac_ref as *mut FXmac, Ordering::Relaxed);
xmac_ref
}
pub fn FXmacStart(instance_p: &mut FXmac) {
assert!(instance_p.is_ready == FT_COMPONENT_IS_READY);
write_reg(
(instance_p.config.base_address + FXMAC_ISR_OFFSET) as *mut u32,
FXMAC_IXR_ALL_MASK,
);
if (instance_p.config.network_default_config & FXMAC_TRANSMITTER_ENABLE_OPTION) != 0 {
let reg_val =
read_reg((instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *const u32);
if (reg_val & FXMAC_NWCTRL_TXEN_MASK) == 0 {
write_reg(
(instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *mut u32,
reg_val | FXMAC_NWCTRL_TXEN_MASK,
);
}
}
if (instance_p.config.network_default_config & FXMAC_RECEIVER_ENABLE_OPTION) != 0 {
let reg_val =
read_reg((instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *const u32);
info!("Enable receiver, FXMAC_NWCTRL_OFFSET = {:#x}", reg_val);
if (reg_val & FXMAC_NWCTRL_RXEN_MASK) == 0 {
write_reg(
(instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *mut u32,
reg_val | FXMAC_NWCTRL_RXEN_MASK,
);
}
}
info!(
"FXMAC_NWCTRL_OFFSET = {:#x}",
read_reg((instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *const u32)
);
info!("Enable TX and RX by Mask={:#x}", instance_p.mask);
write_reg(
(instance_p.config.base_address + FXMAC_IER_OFFSET) as *mut u32,
instance_p.mask & FXMAC_IXR_ALL_MASK,
);
instance_p.is_started = FT_COMPONENT_IS_STARTED;
}
pub fn FXmacStop(instance_p: &mut FXmac) {
assert!(instance_p.is_ready == FT_COMPONENT_IS_READY);
write_reg(
(instance_p.config.base_address + FXMAC_IDR_OFFSET) as *mut u32,
FXMAC_IXR_ALL_MASK,
);
let mut reg_val: u32 =
read_reg((instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *const u32);
reg_val &= !FXMAC_NWCTRL_RXEN_MASK;
reg_val &= !FXMAC_NWCTRL_TXEN_MASK;
write_reg(
(instance_p.config.base_address + FXMAC_NWCTRL_OFFSET) as *mut u32,
reg_val,
);
instance_p.is_started = 0;
}
fn FXmacReset(instance_p: &mut FXmac) {
let mut mac_addr: [u8; 6] = [0; 6];
FXmacStop(instance_p);
instance_p.moudle_id = (read_reg((FXMAC_IOBASE + FXMAC_REVISION_REG_OFFSET) as *const u32)
& FXMAC_IDENTIFICATION_MASK)
>> 16;
info!(
"FXmacReset, Got Moudle IDENTIFICATION: {}",
instance_p.moudle_id
);
instance_p.max_mtu_size = FXMAC_MTU;
instance_p.max_frame_size = FXMAC_MAX_FRAME_SIZE;
instance_p.config.max_queue_num = 16;
instance_p.config.dma_brust_length = 16;
instance_p.config.network_default_config = FXMAC_DEFAULT_OPTIONS;
instance_p.config.pclk_hz = FXMAC0_PCLK;
let netctrl =
(FXMAC_NWCTRL_STATCLR_MASK & !FXMAC_NWCTRL_LOOPBACK_LOCAL_MASK) | FXMAC_NWCTRL_MDEN_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, netctrl);
FXmacConfigureCaps(instance_p);
let mut w_reg: u32 = FXmacClkDivGet(instance_p);
w_reg |= FXmacDmaWidth(instance_p.moudle_id);
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, w_reg);
FXmacDmaReset(instance_p);
write_reg(
(FXMAC_IOBASE + FXMAC_RXSR_OFFSET) as *mut u32,
FXMAC_SR_ALL_MASK,
);
write_reg(
(FXMAC_IOBASE + FXMAC_IDR_OFFSET) as *mut u32,
FXMAC_IXR_ALL_MASK,
);
let reg_val: u32 = read_reg((FXMAC_IOBASE + FXMAC_ISR_OFFSET) as *const u32);
write_reg((FXMAC_IOBASE + FXMAC_ISR_OFFSET) as *mut u32, reg_val);
write_reg(
(FXMAC_IOBASE + FXMAC_TXSR_OFFSET) as *mut u32,
FXMAC_SR_ALL_MASK,
);
FXmacClearHash();
for i in 0..4 {
FXmacSetMacAddress(&mac_addr, i);
FXmacGetMacAddress(&mut mac_addr, i);
FXmacSetTypeIdCheck(0, i);
}
for i in 0..((FXMAC_LAST_OFFSET - FXMAC_OCTTXL_OFFSET) / 4) {
read_reg((FXMAC_IOBASE + FXMAC_OCTTXL_OFFSET + (i * 4)) as *mut u32);
}
let options = instance_p.config.network_default_config
& !(FXMAC_TRANSMITTER_ENABLE_OPTION | FXMAC_RECEIVER_ENABLE_OPTION);
FXmacSetOptions(instance_p, options, 0);
let options = !instance_p.config.network_default_config;
FXmacClearOptions(instance_p, options, 0);
}
fn FXmacDmaReset(instance_p: &mut FXmac) {
let max_frame_size: u32 = instance_p.max_frame_size;
let mut dmacfg: u32 = 0;
let mut rx_buf_size: u32 = max_frame_size / FXMAC_RX_BUF_UNIT;
rx_buf_size += if (max_frame_size % FXMAC_RX_BUF_UNIT) != 0 {
1
} else {
0
};
if (instance_p.moudle_id >= 2) {
for queue in 0..instance_p.config.max_queue_num {
dmacfg = 0;
FXmacSetQueuePtr(0, queue as u8, FXMAC_SEND);
FXmacSetQueuePtr(0, queue as u8, FXMAC_RECV);
if queue != 0 {
write_reg(
(FXMAC_IOBASE + FXMAC_RXBUFQX_SIZE_OFFSET(queue as u64)) as *mut u32,
rx_buf_size,
);
} else
{
dmacfg |= (FXMAC_DMACR_RXBUF_MASK & (rx_buf_size << FXMAC_DMACR_RXBUF_SHIFT));
}
}
dmacfg |= (instance_p.config.dma_brust_length & FXMAC_DMACR_BLENGTH_MASK);
dmacfg &= !FXMAC_DMACR_ENDIAN_MASK;
dmacfg &= !FXMAC_DMACR_SWAP_MANAGEMENT_MASK;
dmacfg &= !FXMAC_DMACR_TCPCKSUM_MASK;
dmacfg &= !FXMAC_DMACR_ADDR_WIDTH_64;
dmacfg |= FXMAC_DMACR_RXSIZE_MASK | FXMAC_DMACR_TXSIZE_MASK;
dmacfg |= FXMAC_DMACR_ORCE_DISCARD_ON_ERR_MASK;
dmacfg |= FXMAC_DMACR_ADDR_WIDTH_64; } else {
FXmacSetQueuePtr(0, 0, FXMAC_SEND);
FXmacSetQueuePtr(0, 0, FXMAC_RECV);
dmacfg |= (FXMAC_DMACR_RXBUF_MASK & (rx_buf_size << FXMAC_DMACR_RXBUF_SHIFT));
dmacfg |= (instance_p.config.dma_brust_length & FXMAC_DMACR_BLENGTH_MASK);
dmacfg &= !FXMAC_DMACR_ENDIAN_MASK;
dmacfg &= !FXMAC_DMACR_SWAP_MANAGEMENT_MASK;
dmacfg &= !FXMAC_DMACR_TCPCKSUM_MASK;
dmacfg &= !FXMAC_DMACR_ADDR_WIDTH_64;
dmacfg |= FXMAC_DMACR_RXSIZE_MASK | FXMAC_DMACR_TXSIZE_MASK;
dmacfg |= FXMAC_DMACR_ORCE_DISCARD_ON_ERR_MASK;
dmacfg |= FXMAC_DMACR_ADDR_WIDTH_64; }
write_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *mut u32, dmacfg);
}
fn FXmacDmaWidth(moudle_id: u32) -> u32 {
if moudle_id < 2 {
return FXMAC_NWCFG_BUS_WIDTH_32_MASK;
}
let read_regs = read_reg((FXMAC_IOBASE + FXMAC_DESIGNCFG_DEBUG1_OFFSET) as *const u32);
match ((read_regs & FXMAC_DESIGNCFG_DEBUG1_BUS_WIDTH_MASK) >> 25) {
4 => {
info!("bus width is 128");
FXMAC_NWCFG_BUS_WIDTH_128_MASK
}
2 => {
info!("bus width is 64");
FXMAC_NWCFG_BUS_WIDTH_64_MASK
}
_ => {
info!("bus width is 32");
FXMAC_NWCFG_BUS_WIDTH_32_MASK
}
}
}
fn FxmacFeatureSetOptions(feature: u32, xmac_p: &mut FXmac) {
let mut options: u32 = 0;
if (feature & FXMAC_LWIP_PORT_CONFIG_JUMBO) != 0 {
info!("FXMAC_JUMBO_ENABLE_OPTION is ok");
options |= FXMAC_JUMBO_ENABLE_OPTION;
}
if (feature & FXMAC_LWIP_PORT_CONFIG_UNICAST_ADDRESS_FILITER) != 0 {
info!("FXMAC_UNICAST_OPTION is ok");
options |= FXMAC_UNICAST_OPTION;
}
if (feature & FXMAC_LWIP_PORT_CONFIG_MULTICAST_ADDRESS_FILITER) != 0 {
info!("FXMAC_MULTICAST_OPTION is ok");
options |= FXMAC_MULTICAST_OPTION;
}
if (feature & FXMAC_LWIP_PORT_CONFIG_COPY_ALL_FRAMES) != 0 {
info!("FXMAC_PROMISC_OPTION is ok");
options |= FXMAC_PROMISC_OPTION;
}
if (feature & FXMAC_LWIP_PORT_CONFIG_CLOSE_FCS_CHECK) != 0 {
info!("FXMAC_FCS_STRIP_OPTION is ok");
options |= FXMAC_FCS_STRIP_OPTION;
}
FXmacSetOptions(xmac_p, options, 0);
}
pub fn FXmacSetQueuePtr(queue_p: u64, queue_num: u8, direction: u32) {
let flag_queue_p = if queue_p == 0 { 1 } else { 0 };
let FXMAC_QUEUE_REGISTER_OFFSET =
|base_addr: u64, queue_id: u64| (base_addr + (queue_id - 1) * 4);
if queue_num == 0 {
if direction == FXMAC_SEND {
write_reg(
(FXMAC_IOBASE + FXMAC_TXQBASE_OFFSET) as *mut u32,
((queue_p & ULONG64_LO_MASK) | flag_queue_p) as u32,
);
} else {
write_reg(
(FXMAC_IOBASE + FXMAC_RXQBASE_OFFSET) as *mut u32,
((queue_p & ULONG64_LO_MASK) | flag_queue_p) as u32,
);
}
} else if direction == FXMAC_SEND {
write_reg(
(FXMAC_IOBASE + FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_TXQ1BASE_OFFSET, queue_num as u64))
as *mut u32,
((queue_p & ULONG64_LO_MASK) | flag_queue_p) as u32,
);
} else {
write_reg(
(FXMAC_IOBASE + FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_RXQ1BASE_OFFSET, queue_num as u64))
as *mut u32,
((queue_p & ULONG64_LO_MASK) | flag_queue_p) as u32,
);
}
if direction == FXMAC_SEND
{
write_reg(
(FXMAC_IOBASE + FXMAC_MSBBUF_TXQBASE_OFFSET) as *mut u32,
((queue_p & ULONG64_HI_MASK) >> 32) as u32,
);
} else {
write_reg(
(FXMAC_IOBASE + FXMAC_MSBBUF_RXQBASE_OFFSET) as *mut u32,
((queue_p & ULONG64_HI_MASK) >> 32) as u32,
);
}
}
fn FXmacConfigureCaps(instance_p: &mut FXmac) {
instance_p.caps = 0;
let read_regs = read_reg((FXMAC_IOBASE + FXMAC_DESIGNCFG_DEBUG1_OFFSET) as *const u32);
if (read_regs & FXMAC_DESIGNCFG_DEBUG1_BUS_IRQCOR_MASK) == 0 {
instance_p.caps |= FXMAC_CAPS_ISR_CLEAR_ON_WRITE;
info!(
"Design ConfigReg1: {:#x} Has FXMAC_CAPS_ISR_CLEAR_ON_WRITE feature",
read_regs
);
}
}
fn FXmacClkDivGet(instance_p: &mut FXmac) -> u32 {
let pclk_hz = instance_p.config.pclk_hz;
if (pclk_hz <= 20000000) {
FXMAC_NWCFG_CLOCK_DIV8_MASK
} else if (pclk_hz <= 40000000) {
FXMAC_NWCFG_CLOCK_DIV16_MASK
} else if (pclk_hz <= 80000000) {
FXMAC_NWCFG_CLOCK_DIV32_MASK
} else if (instance_p.moudle_id >= 2) {
if (pclk_hz <= 120000000) {
FXMAC_NWCFG_CLOCK_DIV48_MASK
} else if (pclk_hz <= 160000000) {
FXMAC_NWCFG_CLOCK_DIV64_MASK
} else if (pclk_hz <= 240000000) {
FXMAC_NWCFG_CLOCK_DIV96_MASK
} else if (pclk_hz <= 320000000) {
FXMAC_NWCFG_CLOCK_DIV128_MASK
} else {
FXMAC_NWCFG_CLOCK_DIV224_MASK
}
} else {
FXMAC_NWCFG_CLOCK_DIV64_MASK
}
}
fn FXmacSetOptions(instance_p: &mut FXmac, options: u32, queue_num: u32) -> u32 {
let mut reg: u32 = 0;
let mut reg_netcfg: u32 = 0;
let mut reg_new_netcfg: u32 = 0;
let mut status: u32 = 0;
info!(
"FXmacSetOptions, is_started={}, options={}, queue_num={}, max_queue_num={}",
instance_p.is_started, options, queue_num, instance_p.config.max_queue_num
);
if instance_p.is_started == FT_COMPONENT_IS_STARTED {
status = 9; error!("FXMAC is processing when calling FXmacSetOptions function");
} else {
reg_netcfg = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
reg_new_netcfg = reg_netcfg;
if (options & FXMAC_FRAME1536_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_1536RXEN_MASK;
}
if (options & FXMAC_VLAN_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_NVLANDISC_MASK;
}
if (options & FXMAC_FCS_STRIP_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_FCS_REMOVE_MASK;
}
if (options & FXMAC_LENTYPE_ERR_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_LENGTH_FIELD_ERROR_FRAME_DISCARD_MASK;
}
if (options & FXMAC_FLOW_CONTROL_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_PAUSE_ENABLE_MASK;
}
if (options & FXMAC_PROMISC_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_COPYALLEN_MASK;
}
if (options & FXMAC_BROADCAST_OPTION) != 0 {
reg_new_netcfg &= !FXMAC_NWCFG_BCASTDI_MASK;
}
if (options & FXMAC_MULTICAST_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_MCASTHASHEN_MASK;
}
if (options & FXMAC_UNICAST_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_UCASTHASHEN_MASK;
}
if (options & FXMAC_TAIL_PTR_OPTION) != 0 {
write_reg((FXMAC_IOBASE + FXMAC_TAIL_ENABLE) as *mut u32, 0x80000001);
}
if (options & FXMAC_RX_CHKSUM_ENABLE_OPTION) != 0 {
reg_new_netcfg |= FXMAC_NWCFG_RXCHKSUMEN_MASK;
}
if (options & FXMAC_JUMBO_ENABLE_OPTION) != 0 {
instance_p.max_mtu_size = FXMAC_MTU_JUMBO;
instance_p.max_frame_size = FXMAC_MAX_FRAME_SIZE_JUMBO;
reg_new_netcfg |= FXMAC_NWCFG_JUMBO_MASK;
write_reg(
(FXMAC_IOBASE + FXMAC_JUMBOMAXLEN_OFFSET) as *mut u32,
FXMAC_MAX_FRAME_SIZE_JUMBO,
);
write_reg(
(FXMAC_IOBASE + FXMAC_TXQSEGALLOC_QLOWER_OFFSET) as *mut u32,
FXMAC_TXQSEGALLOC_QLOWER_JUMBO_MASK,
);
if queue_num == 0 {
let mut rx_buf_size: u32 = 0;
reg = read_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *const u32);
reg &= !FXMAC_DMACR_RXBUF_MASK;
rx_buf_size = instance_p.max_frame_size / FXMAC_RX_BUF_UNIT;
rx_buf_size += if (instance_p.max_frame_size % FXMAC_RX_BUF_UNIT) != 0 {
1
} else {
0
};
reg |= (rx_buf_size << FXMAC_DMACR_RXBUF_SHIFT) & FXMAC_DMACR_RXBUF_MASK;
write_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *mut u32, reg);
} else if queue_num < instance_p.config.max_queue_num {
let mut rx_buf_size: u32 = 0;
rx_buf_size = instance_p.max_frame_size / FXMAC_RX_BUF_UNIT;
rx_buf_size += if (instance_p.max_frame_size % FXMAC_RX_BUF_UNIT) != 0 {
1
} else {
0
};
write_reg(
(FXMAC_IOBASE + FXMAC_RXBUFQX_SIZE_OFFSET(queue_num as u64)) as *mut u32,
rx_buf_size & FXMAC_RXBUFQX_SIZE_MASK,
);
}
}
if (options & FXMAC_SGMII_ENABLE_OPTION) != 0 {
reg_new_netcfg |= (FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK | FXMAC_NWCFG_PCSSEL_MASK);
}
if (options & FXMAC_LOOPBACK_NO_MII_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg |= FXMAC_NWCTRL_LOOPBACK_LOCAL_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_LOOPBACK_USXGMII_OPTION) != 0 {
write_reg((FXMAC_IOBASE + FXMAC_TEST_CONTROL_OFFSET) as *mut u32, 2);
}
if (reg_netcfg != reg_new_netcfg) {
write_reg(
(FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32,
reg_new_netcfg,
);
}
if (options & FXMAC_TX_CHKSUM_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *const u32);
reg |= FXMAC_DMACR_TCPCKSUM_MASK;
write_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_TRANSMITTER_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg |= FXMAC_NWCTRL_TXEN_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_RECEIVER_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg |= FXMAC_NWCTRL_RXEN_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
instance_p.options |= options;
status = 0; }
status
}
fn FXmacClearOptions(instance_p: &mut FXmac, options: u32, queue_num: u32) -> u32 {
let mut reg: u32 = 0;
let mut reg_net_cfg: u32 = 0;
let mut reg_new_net_cfg: u32 = 0;
let mut status: u32 = 0;
if (instance_p.is_started == FT_COMPONENT_IS_STARTED) {
status = 9; error!("FXMAC is processing when calling FXmacClearOptions function");
} else {
reg_net_cfg = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
reg_new_net_cfg = reg_net_cfg;
if (options & FXMAC_FRAME1536_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_1536RXEN_MASK;
}
if (options & FXMAC_VLAN_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_NVLANDISC_MASK;
}
if (options & FXMAC_FCS_STRIP_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_FCS_REMOVE_MASK;
}
if (options & FXMAC_LENTYPE_ERR_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_LENGTH_FIELD_ERROR_FRAME_DISCARD_MASK;
}
if (options & FXMAC_FLOW_CONTROL_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_PAUSE_ENABLE_MASK;
}
if (options & FXMAC_PROMISC_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_COPYALLEN_MASK;
}
if (options & FXMAC_BROADCAST_OPTION) != 0 {
reg_new_net_cfg |= FXMAC_NWCFG_BCASTDI_MASK;
}
if (options & FXMAC_UNICAST_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_UCASTHASHEN_MASK;
}
if (options & FXMAC_MULTICAST_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_MCASTHASHEN_MASK;
}
if (options & FXMAC_TAIL_PTR_OPTION) != 0 {
write_reg((FXMAC_IOBASE + FXMAC_TAIL_ENABLE) as *mut u32, 0);
}
if (options & FXMAC_RX_CHKSUM_ENABLE_OPTION) != 0 {
reg_new_net_cfg &= !FXMAC_NWCFG_RXCHKSUMEN_MASK;
}
if (options & FXMAC_JUMBO_ENABLE_OPTION) != 0
{
instance_p.max_mtu_size = FXMAC_MTU;
instance_p.max_frame_size = FXMAC_MAX_FRAME_SIZE;
reg_new_net_cfg &= !FXMAC_NWCFG_JUMBO_MASK;
reg = read_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *const u32);
reg &= !FXMAC_DMACR_RXBUF_MASK;
if queue_num == 0 {
let mut rx_buf_size: u32 = 0;
reg = read_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *const u32);
reg &= !FXMAC_DMACR_RXBUF_MASK;
rx_buf_size = instance_p.max_frame_size / FXMAC_RX_BUF_UNIT;
rx_buf_size += if instance_p.max_frame_size % FXMAC_RX_BUF_UNIT != 0 {
1
} else {
0
};
reg |= (rx_buf_size << FXMAC_DMACR_RXBUF_SHIFT) & FXMAC_DMACR_RXBUF_MASK;
write_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *mut u32, reg);
} else if (queue_num < instance_p.config.max_queue_num) {
let mut rx_buf_size: u32 = 0;
rx_buf_size = instance_p.max_frame_size / FXMAC_RX_BUF_UNIT;
rx_buf_size += if (instance_p.max_frame_size % FXMAC_RX_BUF_UNIT) != 0 {
1
} else {
0
};
write_reg(
(FXMAC_IOBASE + FXMAC_RXBUFQX_SIZE_OFFSET(queue_num as u64)) as *mut u32,
rx_buf_size & FXMAC_RXBUFQX_SIZE_MASK,
);
}
}
if (options & FXMAC_SGMII_ENABLE_OPTION) != 0 {
reg_new_net_cfg &= !(FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK | FXMAC_NWCFG_PCSSEL_MASK);
}
if (options & FXMAC_LOOPBACK_NO_MII_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg &= !FXMAC_NWCTRL_LOOPBACK_LOCAL_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_LOOPBACK_USXGMII_OPTION) != 0 {
write_reg(
(FXMAC_IOBASE + FXMAC_TEST_CONTROL_OFFSET) as *mut u32,
read_reg((FXMAC_IOBASE + FXMAC_TEST_CONTROL_OFFSET) as *const u32) & !2,
);
}
if reg_net_cfg != reg_new_net_cfg {
write_reg(
(FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32,
reg_new_net_cfg,
);
}
if (options & FXMAC_TX_CHKSUM_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *const u32);
reg &= !FXMAC_DMACR_TCPCKSUM_MASK;
write_reg((FXMAC_IOBASE + FXMAC_DMACR_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_TRANSMITTER_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg &= !FXMAC_NWCTRL_TXEN_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
if (options & FXMAC_RECEIVER_ENABLE_OPTION) != 0 {
reg = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
reg &= !FXMAC_NWCTRL_RXEN_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, reg);
}
instance_p.options &= !options;
status = 0; }
status
}
fn FXmacClearHash() {
write_reg((FXMAC_IOBASE + FXMAC_HASHL_OFFSET) as *mut u32, 0);
write_reg((FXMAC_IOBASE + FXMAC_HASHH_OFFSET) as *mut u32, 0);
}
pub fn FXmacSetMacAddress(address_ptr: &[u8; 6], index: u8) -> u32 {
let mut mac_addr: u32 = 0;
let aptr = address_ptr;
let index_loc: u8 = index;
let mut status: u32 = 0;
assert!(
(index_loc < FXMAC_MAX_MAC_ADDR as u8),
"index of Mac Address exceed {}",
FXMAC_MAX_MAC_ADDR
);
let is_started = 0;
if is_started == FT_COMPONENT_IS_STARTED {
status = 9;
error!("FXMAC is processing when calling FXmacSetMacAddress function");
} else {
mac_addr = aptr[0] as u32
| ((aptr[1] as u32) << 8)
| ((aptr[2] as u32) << 16)
| ((aptr[3] as u32) << 24);
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_SA1B as u64 + (index_loc * 8) as u64) as *mut u32,
mac_addr,
);
mac_addr =
read_reg((FXMAC_IOBASE + FXMAC_GEM_SA1T as u64 + (index_loc * 8) as u64) as *const u32);
mac_addr &= !FXMAC_GEM_SAB_MASK;
mac_addr |= aptr[4] as u32;
mac_addr |= (aptr[5] as u32) << 8;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_SA1T as u64 + (index_loc * 8) as u64) as *mut u32,
mac_addr,
);
status = 0; }
status
}
pub fn FXmacGetMacAddress(address_ptr: &mut [u8; 6], index: u8) {
assert!((index as u32) < FXMAC_MAX_MAC_ADDR);
let mut reg_value: u32 =
read_reg((FXMAC_IOBASE + FXMAC_GEM_SA1B as u64 + (index as u64 * 8)) as *const u32);
address_ptr[0] = reg_value as u8;
address_ptr[1] = (reg_value >> 8) as u8;
address_ptr[2] = (reg_value >> 16) as u8;
address_ptr[3] = (reg_value >> 24) as u8;
reg_value = read_reg((FXMAC_IOBASE + FXMAC_GEM_SA1T as u64 + (index as u64 * 8)) as *const u32);
address_ptr[4] = (reg_value) as u8;
address_ptr[5] = (reg_value >> 8) as u8;
}
pub fn FXmac_SetHash(intance_p: &mut FXmac, mac_address: &[u8; 6]) -> u32 {
let mut HashAddr: u32 = 0;
let mut Status: u32 = 0;
debug!("Set MAC: {:x?} in hash table", mac_address);
assert!(!((mac_address[0] == 0) && (mac_address[5] == 0)));
assert!(intance_p.is_ready == FT_COMPONENT_IS_READY);
if (intance_p.is_started == FT_COMPONENT_IS_STARTED) {
error!("FXmac_SetHash failed: FXMAC_ERR_MAC_IS_PROCESSING");
Status = 9; } else {
let Temp1: u8 = (mac_address[0]) & 0x3F;
let Temp2: u8 = ((mac_address[0] >> 6) & 0x03) | ((mac_address[1] & 0x0F) << 2);
let Temp3: u8 = ((mac_address[1] >> 4) & 0x0F) | ((mac_address[2] & 0x3) << 4);
let Temp4: u8 = ((mac_address[2] >> 2) & 0x3F);
let Temp5: u8 = mac_address[3] & 0x3F;
let Temp6: u8 = ((mac_address[3] >> 6) & 0x03) | ((mac_address[4] & 0x0F) << 2);
let Temp7: u8 = ((mac_address[4] >> 4) & 0x0F) | ((mac_address[5] & 0x03) << 4);
let Temp8: u8 = ((mac_address[5] >> 2) & 0x3F);
let Result: u32 = (Temp1 as u32)
^ (Temp2 as u32)
^ (Temp3 as u32)
^ (Temp4 as u32)
^ (Temp5 as u32)
^ (Temp6 as u32)
^ (Temp7 as u32)
^ (Temp8 as u32);
if (Result >= FXMAC_MAX_HASH_BITS) {
Status = 1; } else {
if (Result < 32) {
HashAddr =
read_reg((intance_p.config.base_address + FXMAC_HASHL_OFFSET) as *const u32);
HashAddr |= 1 << Result;
write_reg(
(intance_p.config.base_address + FXMAC_HASHL_OFFSET) as *mut u32,
HashAddr,
);
} else {
HashAddr =
read_reg((intance_p.config.base_address + FXMAC_HASHH_OFFSET) as *const u32);
HashAddr |= 1 << (Result - 32);
write_reg(
(intance_p.config.base_address + FXMAC_HASHH_OFFSET) as *mut u32,
HashAddr,
);
}
Status = 0;
}
}
Status
}
pub fn FXmac_DeleteHash(intance_p: &mut FXmac, mac_address: &[u8; 6]) -> u32 {
let mut HashAddr: u32 = 0;
let mut Status: u32 = 0;
assert!(intance_p.is_ready == FT_COMPONENT_IS_READY);
if (intance_p.is_started == FT_COMPONENT_IS_STARTED) {
Status = 9; } else {
let mut Temp1: u8 = (mac_address[0]) & 0x3F;
let mut Temp2: u8 = ((mac_address[0] >> 6) & 0x03) | ((mac_address[1] & 0x0F) << 2);
let mut Temp3: u8 = ((mac_address[1] >> 4) & 0x0F) | ((mac_address[2] & 0x03) << 4);
let mut Temp4: u8 = ((mac_address[2] >> 2) & 0x3F);
let mut Temp5: u8 = (mac_address[3]) & 0x3F;
let mut Temp6: u8 = ((mac_address[3] >> 6) & 0x03) | ((mac_address[4] & 0x0F) << 2);
let mut Temp7: u8 = ((mac_address[4] >> 4) & 0x0F) | ((mac_address[5] & 0x03) << 4);
let mut Temp8: u8 = ((mac_address[5] >> 2) & 0x3F);
let Result: u32 = (Temp1 as u32)
^ (Temp2 as u32)
^ (Temp3 as u32)
^ (Temp4 as u32)
^ (Temp5 as u32)
^ (Temp6 as u32)
^ (Temp7 as u32)
^ (Temp8 as u32);
if Result >= FXMAC_MAX_HASH_BITS {
Status = 1; } else {
if Result < 32 {
HashAddr =
read_reg((intance_p.config.base_address + FXMAC_HASHL_OFFSET) as *const u32);
HashAddr &= !((1 << Result) as u32);
write_reg(
(intance_p.config.base_address + FXMAC_HASHL_OFFSET) as *mut u32,
HashAddr,
);
} else {
HashAddr =
read_reg((intance_p.config.base_address + FXMAC_HASHH_OFFSET) as *const u32);
HashAddr &= !((1 << (Result - 32)) as u32);
write_reg(
(intance_p.config.base_address + FXMAC_HASHH_OFFSET) as *mut u32,
HashAddr,
);
}
Status = 0;
}
}
Status
}
fn FXmacSetTypeIdCheck(id_check: u32, index: u8) -> u32 {
let mut status: u32 = 0;
assert!(
(index < FXMAC_MAX_TYPE_ID as u8),
"index of Type ID exceed {}",
FXMAC_MAX_TYPE_ID
);
let is_started = 0;
if is_started == FT_COMPONENT_IS_STARTED {
status = 9; error!("FXMAC is processing when calling FXmacSetTypeIdCheck function");
} else {
write_reg(
(FXMAC_IOBASE + FXMAC_MATCH1_OFFSET + (index * 4) as u64) as *mut u32,
id_check,
);
status = FT_SUCCESS;
}
status
}
fn FXmacSelectClk(instance_p: &mut FXmac) {
let speed: u32 = instance_p.config.speed;
let FXMAC_WRITEREG32 = |base_address: u64, offset: u32, reg_value: u32| {
write_reg((base_address + offset as u64) as *mut u32, reg_value)
};
assert!(
(speed == FXMAC_SPEED_10)
|| (speed == FXMAC_SPEED_100)
|| (speed == FXMAC_SPEED_1000)
|| (speed == FXMAC_SPEED_2500)
|| (speed == FXMAC_SPEED_10000)
);
if (instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_USXGMII)
|| (instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_XGMII)
{
if speed == FXMAC_SPEED_10000 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x4);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x1,
);
} else if speed == FXMAC_SPEED_5000 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x8);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x2);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0,
);
}
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_5GBASER {
if speed == FXMAC_SPEED_5000 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x8);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x2);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x0,
);
}
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_2500BASEX {
if speed == FXMAC_SPEED_25000 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x2);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x1,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL4_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL4_0, 0x0);
}
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_SGMII {
info!("FXMAC_PHY_INTERFACE_MODE_SGMII init");
if speed == FXMAC_SPEED_2500 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x2);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x1,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL4_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL4_0, 0x0);
} else if speed == FXMAC_SPEED_1000 {
info!("sgmii FXMAC_SPEED_1000");
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x4);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x8);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x1,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL4_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL4_0, 0x0);
} else if (speed == FXMAC_SPEED_100) || (speed == FXMAC_SPEED_10) {
info!("sgmii FXMAC_SPEED_{}", speed);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_SRC_SEL_LN, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL0_LN, 0x4);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_DIV_SEL1_LN, 0x8);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_PMA_XCVR_POWER_STATE,
0x1,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3_0, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL4_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL3_0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL4_0, 0x1);
}
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_RGMII {
info!("FXMAC_PHY_INTERFACE_MODE_RGMII init");
if speed == FXMAC_SPEED_1000 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_MII_SELECT, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_SEL_MII_ON_RGMII,
0x0,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_CLK_250M_DIV10_DIV100_SEL,
0x0,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL5, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL0,
0x1,
);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL1,
0x0,
);
} else if speed == FXMAC_SPEED_100 {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_MII_SELECT, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_SEL_MII_ON_RGMII,
0x0,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_CLK_250M_DIV10_DIV100_SEL,
0x0,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL5, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL0,
0x0,
);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL1,
0x0,
);
} else {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_MII_SELECT, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_SEL_MII_ON_RGMII,
0x0,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL2, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_TX_CLK_SEL3, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL0, 0x0);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL1, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_CLK_250M_DIV10_DIV100_SEL,
0x1,
);
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL5, 0x1);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL0,
0x0,
);
FXMAC_WRITEREG32(
instance_p.config.base_address,
FXMAC_GEM_RGMII_TX_CLK_SEL1,
0x0,
);
}
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_RMII {
FXMAC_WRITEREG32(instance_p.config.base_address, FXMAC_GEM_RX_CLK_SEL5, 0x1);
}
FXmacHighSpeedConfiguration(instance_p, speed);
}
fn FXmacHighSpeedConfiguration(instance_p: &mut FXmac, speed: u32) {
let mut reg_value: u32 = 0;
let mut set_speed: i32 = 0;
match speed {
FXMAC_SPEED_25000 => {
set_speed = 2;
}
FXMAC_SPEED_10000 => {
set_speed = 4;
}
FXMAC_SPEED_5000 => {
set_speed = 3;
}
FXMAC_SPEED_2500 => {
set_speed = 2;
}
FXMAC_SPEED_1000 => {
set_speed = 1;
}
_ => {
set_speed = 0;
}
}
reg_value = read_reg((FXMAC_IOBASE + FXMAC_GEM_HSMAC as u64) as *const u32);
reg_value &= !FXMAC_GEM_HSMACSPEED_MASK;
reg_value |= (set_speed as u32) & FXMAC_GEM_HSMACSPEED_MASK;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_HSMAC as u64) as *mut u32,
reg_value,
);
reg_value = read_reg((FXMAC_IOBASE + FXMAC_GEM_HSMAC as u64) as *const u32);
info!("FXMAC_GEM_HSMAC is {:#x}", reg_value);
}
fn FXmacInitInterface(instance_p: &mut FXmac) {
let mut config: u32 = 0;
let mut control: u32 = 0;
info!(
"FXmacInitInterface, PHY MODE:{:?}",
instance_p.config.interface
);
if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_XGMII {
config = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
config &= !FXMAC_NWCFG_PCSSEL_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, config);
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control |= FXMAC_NWCTRL_ENABLE_HS_MAC_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
instance_p.config.duplex = 1;
} else if (instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_USXGMII)
|| (instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_5GBASER)
{
info!("usx interface is {:?}", instance_p.config.interface);
instance_p.config.duplex = 1;
config = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
config |= FXMAC_NWCFG_PCSSEL_MASK;
config &= !FXMAC_NWCFG_100_MASK;
config &= !FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK;
if (instance_p.config.duplex == 1) {
info!("is duplex");
config |= FXMAC_NWCFG_FDEN_MASK;
}
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, config);
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control |= FXMAC_NWCTRL_ENABLE_HS_MAC_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
control = read_reg((FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *const u32);
if (instance_p.config.speed == FXMAC_SPEED_10000) {
info!("is 10G");
control |= FXMAC_GEM_USX_HS_MAC_SPEED_10G;
control |= FXMAC_GEM_USX_SERDES_RATE_10G;
} else if (instance_p.config.speed == FXMAC_SPEED_25000) {
control |= FXMAC_GEM_USX_HS_MAC_SPEED_2_5G;
} else if (instance_p.config.speed == FXMAC_SPEED_1000) {
control |= FXMAC_GEM_USX_HS_MAC_SPEED_1G;
} else if (instance_p.config.speed == FXMAC_SPEED_100) {
control |= FXMAC_GEM_USX_HS_MAC_SPEED_100M;
} else if (instance_p.config.speed == FXMAC_SPEED_5000) {
control |= FXMAC_GEM_USX_HS_MAC_SPEED_5G;
control |= FXMAC_GEM_USX_SERDES_RATE_5G;
}
control &= !(FXMAC_GEM_USX_TX_SCR_BYPASS | FXMAC_GEM_USX_RX_SCR_BYPASS);
control |= FXMAC_GEM_USX_RX_SYNC_RESET;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *mut u32,
control,
);
control = read_reg((FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *const u32);
control &= !FXMAC_GEM_USX_RX_SYNC_RESET;
control |= FXMAC_GEM_USX_TX_DATAPATH_EN;
control |= FXMAC_GEM_USX_SIGNAL_OK;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *mut u32,
control,
);
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_2500BASEX {
instance_p.config.duplex = 1;
config = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
config |= FXMAC_NWCFG_PCSSEL_MASK | FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK;
config &= !FXMAC_NWCFG_100_MASK;
if (instance_p.config.duplex == 1) {
config |= FXMAC_NWCFG_FDEN_MASK;
}
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, config);
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control &= !FXMAC_NWCTRL_ENABLE_HS_MAC_MASK;
control |= FXMAC_NWCTRL_TWO_PT_FIVE_GIG_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
control = read_reg((FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *const u32);
if (instance_p.config.speed == FXMAC_SPEED_25000) {
control |= FXMAC_GEM_USX_HS_MAC_SPEED_2_5G;
}
control &= !(FXMAC_GEM_USX_TX_SCR_BYPASS | FXMAC_GEM_USX_RX_SCR_BYPASS);
control |= FXMAC_GEM_USX_RX_SYNC_RESET;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *mut u32,
control,
);
control = read_reg((FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *const u32);
control &= !FXMAC_GEM_USX_RX_SYNC_RESET;
control |= FXMAC_GEM_USX_TX_DATAPATH_EN;
control |= FXMAC_GEM_USX_SIGNAL_OK;
write_reg(
(FXMAC_IOBASE + FXMAC_GEM_USX_CONTROL_OFFSET) as *mut u32,
control,
);
} else if instance_p.config.interface == FXmacPhyInterface::FXMAC_PHY_INTERFACE_MODE_SGMII {
config = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
config |= FXMAC_NWCFG_PCSSEL_MASK | FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK;
config &= !(FXMAC_NWCFG_100_MASK
| FXMAC_NWCFG_FDEN_MASK
| FXMAC_NWCFG_LENGTH_FIELD_ERROR_FRAME_DISCARD_MASK);
if instance_p.moudle_id >= 2 {
config &= !FXMAC_NWCFG_1000_MASK;
}
if instance_p.config.duplex != 0 {
config |= FXMAC_NWCFG_FDEN_MASK;
}
if instance_p.config.speed == FXMAC_SPEED_100 {
config |= FXMAC_NWCFG_100_MASK;
} else if instance_p.config.speed == FXMAC_SPEED_1000 {
config |= FXMAC_NWCFG_1000_MASK;
}
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, config);
if instance_p.config.speed == FXMAC_SPEED_2500 {
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control |= FXMAC_NWCTRL_TWO_PT_FIVE_GIG_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
} else {
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control &= !FXMAC_NWCTRL_TWO_PT_FIVE_GIG_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
}
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control &= !FXMAC_NWCTRL_ENABLE_HS_MAC_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
control = read_reg((FXMAC_IOBASE + FXMAC_PCS_CONTROL_OFFSET) as *const u32);
control |= FXMAC_PCS_CONTROL_ENABLE_AUTO_NEG;
write_reg(
(FXMAC_IOBASE + FXMAC_PCS_CONTROL_OFFSET) as *mut u32,
control,
);
} else {
config = read_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *const u32);
info!("select rgmii");
config &= !FXMAC_NWCFG_PCSSEL_MASK;
config &= !(FXMAC_NWCFG_100_MASK | FXMAC_NWCFG_FDEN_MASK);
if instance_p.moudle_id >= 2 {
config &= !FXMAC_NWCFG_1000_MASK;
}
if instance_p.config.duplex != 0 {
config |= FXMAC_NWCFG_FDEN_MASK;
}
if instance_p.config.speed == FXMAC_SPEED_100 {
config |= FXMAC_NWCFG_100_MASK;
} else if instance_p.config.speed == FXMAC_SPEED_1000 {
config |= FXMAC_NWCFG_1000_MASK;
}
write_reg((FXMAC_IOBASE + FXMAC_NWCFG_OFFSET) as *mut u32, config);
control = read_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *const u32);
control &= !FXMAC_NWCTRL_ENABLE_HS_MAC_MASK;
write_reg((FXMAC_IOBASE + FXMAC_NWCTRL_OFFSET) as *mut u32, control);
}
}