From 9b6bcdcb932cf38a2da1b059f661b8ee6b85175f Mon Sep 17 00:00:00 2001 From: Albert Aribaud Date: Mon, 12 Jul 2010 22:24:27 +0200 Subject: net: rename: kirkwood_egiga as mvgbe Rename kirkwood_egiga.* to mvgbe.* and adjust makefile and #include accordingly. Signed-off-by: Albert Aribaud Acked-by: Prafulla Wadaskar Signed-off-by: Ben Warren --- drivers/net/Makefile | 2 +- drivers/net/kirkwood_egiga.c | 736 ------------------------------------------- drivers/net/kirkwood_egiga.h | 505 ----------------------------- drivers/net/mvgbe.c | 736 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/mvgbe.h | 505 +++++++++++++++++++++++++++++ 5 files changed, 1242 insertions(+), 1242 deletions(-) delete mode 100644 drivers/net/kirkwood_egiga.c delete mode 100644 drivers/net/kirkwood_egiga.h create mode 100644 drivers/net/mvgbe.c create mode 100644 drivers/net/mvgbe.h diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7a320fda02..0894822c4c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -47,13 +47,13 @@ COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o COBJS-$(CONFIG_FTMAC100) += ftmac100.o COBJS-$(CONFIG_GRETH) += greth.o COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o -COBJS-$(CONFIG_KIRKWOOD_EGIGA) += kirkwood_egiga.o COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o COBJS-$(CONFIG_LAN91C96) += lan91c96.o COBJS-$(CONFIG_MACB) += macb.o COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o +COBJS-$(CONFIG_KIRKWOOD_EGIGA) += mvgbe.o COBJS-$(CONFIG_NATSEMI) += natsemi.o COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o diff --git a/drivers/net/kirkwood_egiga.c b/drivers/net/kirkwood_egiga.c deleted file mode 100644 index 7aabcefa98..0000000000 --- a/drivers/net/kirkwood_egiga.c +++ /dev/null @@ -1,736 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor - * Written-by: Prafulla Wadaskar - * - * (C) Copyright 2003 - * Ingo Assmus - * - * based on - Driver for MV64360X ethernet ports - * Copyright (C) 2002 rabeeh@galileo.co.il - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "kirkwood_egiga.h" - -DECLARE_GLOBAL_DATA_PTR; - -#define KIRKWOOD_PHY_ADR_REQUEST 0xee -#define KWGBE_SMI_REG (((struct kwgbe_registers *)KW_EGIGA0_BASE)->smi) - -/* - * smi_reg_read - miiphy_read callback function. - * - * Returns 16bit phy register value, or 0xffff on error - */ -static int smi_reg_read(char *devname, u8 phy_adr, u8 reg_ofs, u16 * data) -{ - struct eth_device *dev = eth_get_dev_by_name(devname); - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; - u32 smi_reg; - u32 timeout; - - /* Phyadr read request */ - if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && - reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { - /* */ - *data = (u16) (KWGBEREG_RD(regs->phyadr) & PHYADR_MASK); - return 0; - } - /* check parameters */ - if (phy_adr > PHYADR_MASK) { - printf("Err..(%s) Invalid PHY address %d\n", - __FUNCTION__, phy_adr); - return -EFAULT; - } - if (reg_ofs > PHYREG_MASK) { - printf("Err..(%s) Invalid register offset %d\n", - __FUNCTION__, reg_ofs); - return -EFAULT; - } - - timeout = KWGBE_PHY_SMI_TIMEOUT; - /* wait till the SMI is not busy */ - do { - /* read smi register */ - smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); - if (timeout-- == 0) { - printf("Err..(%s) SMI busy timeout\n", __FUNCTION__); - return -EFAULT; - } - } while (smi_reg & KWGBE_PHY_SMI_BUSY_MASK); - - /* fill the phy address and regiser offset and read opcode */ - smi_reg = (phy_adr << KWGBE_PHY_SMI_DEV_ADDR_OFFS) - | (reg_ofs << KWGBE_SMI_REG_ADDR_OFFS) - | KWGBE_PHY_SMI_OPCODE_READ; - - /* write the smi register */ - KWGBEREG_WR(KWGBE_SMI_REG, smi_reg); - - /*wait till read value is ready */ - timeout = KWGBE_PHY_SMI_TIMEOUT; - - do { - /* read smi register */ - smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); - if (timeout-- == 0) { - printf("Err..(%s) SMI read ready timeout\n", - __FUNCTION__); - return -EFAULT; - } - } while (!(smi_reg & KWGBE_PHY_SMI_READ_VALID_MASK)); - - /* Wait for the data to update in the SMI register */ - for (timeout = 0; timeout < KWGBE_PHY_SMI_TIMEOUT; timeout++) ; - - *data = (u16) (KWGBEREG_RD(KWGBE_SMI_REG) & KWGBE_PHY_SMI_DATA_MASK); - - debug("%s:(adr %d, off %d) value= %04x\n", __FUNCTION__, phy_adr, - reg_ofs, *data); - - return 0; -} - -/* - * smi_reg_write - imiiphy_write callback function. - * - * Returns 0 if write succeed, -EINVAL on bad parameters - * -ETIME on timeout - */ -static int smi_reg_write(char *devname, u8 phy_adr, u8 reg_ofs, u16 data) -{ - struct eth_device *dev = eth_get_dev_by_name(devname); - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; - u32 smi_reg; - u32 timeout; - - /* Phyadr write request*/ - if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && - reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { - KWGBEREG_WR(regs->phyadr, data); - return 0; - } - - /* check parameters */ - if (phy_adr > PHYADR_MASK) { - printf("Err..(%s) Invalid phy address\n", __FUNCTION__); - return -EINVAL; - } - if (reg_ofs > PHYREG_MASK) { - printf("Err..(%s) Invalid register offset\n", __FUNCTION__); - return -EINVAL; - } - - /* wait till the SMI is not busy */ - timeout = KWGBE_PHY_SMI_TIMEOUT; - do { - /* read smi register */ - smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); - if (timeout-- == 0) { - printf("Err..(%s) SMI busy timeout\n", __FUNCTION__); - return -ETIME; - } - } while (smi_reg & KWGBE_PHY_SMI_BUSY_MASK); - - /* fill the phy addr and reg offset and write opcode and data */ - smi_reg = (data << KWGBE_PHY_SMI_DATA_OFFS); - smi_reg |= (phy_adr << KWGBE_PHY_SMI_DEV_ADDR_OFFS) - | (reg_ofs << KWGBE_SMI_REG_ADDR_OFFS); - smi_reg &= ~KWGBE_PHY_SMI_OPCODE_READ; - - /* write the smi register */ - KWGBEREG_WR(KWGBE_SMI_REG, smi_reg); - - return 0; -} - -/* Stop and checks all queues */ -static void stop_queue(u32 * qreg) -{ - u32 reg_data; - - reg_data = readl(qreg); - - if (reg_data & 0xFF) { - /* Issue stop command for active channels only */ - writel((reg_data << 8), qreg); - - /* Wait for all queue activity to terminate. */ - do { - /* - * Check port cause register that all queues - * are stopped - */ - reg_data = readl(qreg); - } - while (reg_data & 0xFF); - } -} - -/* - * set_access_control - Config address decode parameters for Ethernet unit - * - * This function configures the address decode parameters for the Gigabit - * Ethernet Controller according the given parameters struct. - * - * @regs Register struct pointer. - * @param Address decode parameter struct. - */ -static void set_access_control(struct kwgbe_registers *regs, - struct kwgbe_winparam *param) -{ - u32 access_prot_reg; - - /* Set access control register */ - access_prot_reg = KWGBEREG_RD(regs->epap); - /* clear window permission */ - access_prot_reg &= (~(3 << (param->win * 2))); - access_prot_reg |= (param->access_ctrl << (param->win * 2)); - KWGBEREG_WR(regs->epap, access_prot_reg); - - /* Set window Size reg (SR) */ - KWGBEREG_WR(regs->barsz[param->win].size, - (((param->size / 0x10000) - 1) << 16)); - - /* Set window Base address reg (BA) */ - KWGBEREG_WR(regs->barsz[param->win].bar, - (param->target | param->attrib | param->base_addr)); - /* High address remap reg (HARR) */ - if (param->win < 4) - KWGBEREG_WR(regs->ha_remap[param->win], param->high_addr); - - /* Base address enable reg (BARER) */ - if (param->enable == 1) - KWGBEREG_BITS_RESET(regs->bare, (1 << param->win)); - else - KWGBEREG_BITS_SET(regs->bare, (1 << param->win)); -} - -static void set_dram_access(struct kwgbe_registers *regs) -{ - struct kwgbe_winparam win_param; - int i; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - /* Set access parameters for DRAM bank i */ - win_param.win = i; /* Use Ethernet window i */ - /* Window target - DDR */ - win_param.target = KWGBE_TARGET_DRAM; - /* Enable full access */ - win_param.access_ctrl = EWIN_ACCESS_FULL; - win_param.high_addr = 0; - /* Get bank base and size */ - win_param.base_addr = gd->bd->bi_dram[i].start; - win_param.size = gd->bd->bi_dram[i].size; - if (win_param.size == 0) - win_param.enable = 0; - else - win_param.enable = 1; /* Enable the access */ - - /* Enable DRAM bank */ - switch (i) { - case 0: - win_param.attrib = EBAR_DRAM_CS0; - break; - case 1: - win_param.attrib = EBAR_DRAM_CS1; - break; - case 2: - win_param.attrib = EBAR_DRAM_CS2; - break; - case 3: - win_param.attrib = EBAR_DRAM_CS3; - break; - default: - /* invalid bank, disable access */ - win_param.enable = 0; - win_param.attrib = 0; - break; - } - /* Set the access control for address window(EPAPR) RD/WR */ - set_access_control(regs, &win_param); - } -} - -/* - * port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables - * - * Go through all the DA filter tables (Unicast, Special Multicast & Other - * Multicast) and set each entry to 0. - */ -static void port_init_mac_tables(struct kwgbe_registers *regs) -{ - int table_index; - - /* Clear DA filter unicast table (Ex_dFUT) */ - for (table_index = 0; table_index < 4; ++table_index) - KWGBEREG_WR(regs->dfut[table_index], 0); - - for (table_index = 0; table_index < 64; ++table_index) { - /* Clear DA filter special multicast table (Ex_dFSMT) */ - KWGBEREG_WR(regs->dfsmt[table_index], 0); - /* Clear DA filter other multicast table (Ex_dFOMT) */ - KWGBEREG_WR(regs->dfomt[table_index], 0); - } -} - -/* - * port_uc_addr - This function Set the port unicast address table - * - * This function locates the proper entry in the Unicast table for the - * specified MAC nibble and sets its properties according to function - * parameters. - * This function add/removes MAC addresses from the port unicast address - * table. - * - * @uc_nibble Unicast MAC Address last nibble. - * @option 0 = Add, 1 = remove address. - * - * RETURN: 1 if output succeeded. 0 if option parameter is invalid. - */ -static int port_uc_addr(struct kwgbe_registers *regs, u8 uc_nibble, - int option) -{ - u32 unicast_reg; - u32 tbl_offset; - u32 reg_offset; - - /* Locate the Unicast table entry */ - uc_nibble = (0xf & uc_nibble); - /* Register offset from unicast table base */ - tbl_offset = (uc_nibble / 4); - /* Entry offset within the above register */ - reg_offset = uc_nibble % 4; - - switch (option) { - case REJECT_MAC_ADDR: - /* - * Clear accepts frame bit at specified unicast - * DA table entry - */ - unicast_reg = KWGBEREG_RD(regs->dfut[tbl_offset]); - unicast_reg &= (0xFF << (8 * reg_offset)); - KWGBEREG_WR(regs->dfut[tbl_offset], unicast_reg); - break; - case ACCEPT_MAC_ADDR: - /* Set accepts frame bit at unicast DA filter table entry */ - unicast_reg = KWGBEREG_RD(regs->dfut[tbl_offset]); - unicast_reg &= (0xFF << (8 * reg_offset)); - unicast_reg |= ((0x01 | (RXUQ << 1)) << (8 * reg_offset)); - KWGBEREG_WR(regs->dfut[tbl_offset], unicast_reg); - break; - default: - return 0; - } - return 1; -} - -/* - * port_uc_addr_set - This function Set the port Unicast address. - */ -static void port_uc_addr_set(struct kwgbe_registers *regs, u8 * p_addr) -{ - u32 mac_h; - u32 mac_l; - - mac_l = (p_addr[4] << 8) | (p_addr[5]); - mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) | - (p_addr[3] << 0); - - KWGBEREG_WR(regs->macal, mac_l); - KWGBEREG_WR(regs->macah, mac_h); - - /* Accept frames of this address */ - port_uc_addr(regs, p_addr[5], ACCEPT_MAC_ADDR); -} - -/* - * kwgbe_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. - */ -static void kwgbe_init_rx_desc_ring(struct kwgbe_device *dkwgbe) -{ - struct kwgbe_rxdesc *p_rx_desc; - int i; - - /* initialize the Rx descriptors ring */ - p_rx_desc = dkwgbe->p_rxdesc; - for (i = 0; i < RINGSZ; i++) { - p_rx_desc->cmd_sts = - KWGBE_BUFFER_OWNED_BY_DMA | KWGBE_RX_EN_INTERRUPT; - p_rx_desc->buf_size = PKTSIZE_ALIGN; - p_rx_desc->byte_cnt = 0; - p_rx_desc->buf_ptr = dkwgbe->p_rxbuf + i * PKTSIZE_ALIGN; - if (i == (RINGSZ - 1)) - p_rx_desc->nxtdesc_p = dkwgbe->p_rxdesc; - else { - p_rx_desc->nxtdesc_p = (struct kwgbe_rxdesc *) - ((u32) p_rx_desc + KW_RXQ_DESC_ALIGNED_SIZE); - p_rx_desc = p_rx_desc->nxtdesc_p; - } - } - dkwgbe->p_rxdesc_curr = dkwgbe->p_rxdesc; -} - -static int kwgbe_init(struct eth_device *dev) -{ - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; -#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ - && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) - int i; -#endif - /* setup RX rings */ - kwgbe_init_rx_desc_ring(dkwgbe); - - /* Clear the ethernet port interrupts */ - KWGBEREG_WR(regs->ic, 0); - KWGBEREG_WR(regs->ice, 0); - /* Unmask RX buffer and TX end interrupt */ - KWGBEREG_WR(regs->pim, INT_CAUSE_UNMASK_ALL); - /* Unmask phy and link status changes interrupts */ - KWGBEREG_WR(regs->peim, INT_CAUSE_UNMASK_ALL_EXT); - - set_dram_access(regs); - port_init_mac_tables(regs); - port_uc_addr_set(regs, dkwgbe->dev.enetaddr); - - /* Assign port configuration and command. */ - KWGBEREG_WR(regs->pxc, PRT_CFG_VAL); - KWGBEREG_WR(regs->pxcx, PORT_CFG_EXTEND_VALUE); - KWGBEREG_WR(regs->psc0, PORT_SERIAL_CONTROL_VALUE); - - /* Assign port SDMA configuration */ - KWGBEREG_WR(regs->sdc, PORT_SDMA_CFG_VALUE); - KWGBEREG_WR(regs->tqx[0].qxttbc, QTKNBKT_DEF_VAL); - KWGBEREG_WR(regs->tqx[0].tqxtbc, (QMTBS_DEF_VAL << 16) | QTKNRT_DEF_VAL); - /* Turn off the port/RXUQ bandwidth limitation */ - KWGBEREG_WR(regs->pmtu, 0); - - /* Set maximum receive buffer to 9700 bytes */ - KWGBEREG_WR(regs->psc0, KWGBE_MAX_RX_PACKET_9700BYTE - | (KWGBEREG_RD(regs->psc0) & MRU_MASK)); - - /* Enable port initially */ - KWGBEREG_BITS_SET(regs->psc0, KWGBE_SERIAL_PORT_EN); - - /* - * Set ethernet MTU for leaky bucket mechanism to 0 - this will - * disable the leaky bucket mechanism . - */ - KWGBEREG_WR(regs->pmtu, 0); - - /* Assignment of Rx CRDB of given RXUQ */ - KWGBEREG_WR(regs->rxcdp[RXUQ], (u32) dkwgbe->p_rxdesc_curr); - /* ensure previous write is done before enabling Rx DMA */ - isb(); - /* Enable port Rx. */ - KWGBEREG_WR(regs->rqc, (1 << RXUQ)); - -#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ - && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) - /* Wait up to 5s for the link status */ - for (i = 0; i < 5; i++) { - u16 phyadr; - - miiphy_read(dev->name, KIRKWOOD_PHY_ADR_REQUEST, - KIRKWOOD_PHY_ADR_REQUEST, &phyadr); - /* Return if we get link up */ - if (miiphy_link(dev->name, phyadr)) - return 0; - udelay(1000000); - } - - printf("No link on %s\n", dev->name); - return -1; -#endif - return 0; -} - -static int kwgbe_halt(struct eth_device *dev) -{ - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; - - /* Disable all gigE address decoder */ - KWGBEREG_WR(regs->bare, 0x3f); - - stop_queue(®s->tqc); - stop_queue(®s->rqc); - - /* Disable port */ - KWGBEREG_BITS_RESET(regs->psc0, KWGBE_SERIAL_PORT_EN); - /* Set port is not reset */ - KWGBEREG_BITS_RESET(regs->psc1, 1 << 4); -#ifdef CONFIG_SYS_MII_MODE - /* Set MMI interface up */ - KWGBEREG_BITS_RESET(regs->psc1, 1 << 3); -#endif - /* Disable & mask ethernet port interrupts */ - KWGBEREG_WR(regs->ic, 0); - KWGBEREG_WR(regs->ice, 0); - KWGBEREG_WR(regs->pim, 0); - KWGBEREG_WR(regs->peim, 0); - - return 0; -} - -static int kwgbe_write_hwaddr(struct eth_device *dev) -{ - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; - - /* Programs net device MAC address after initialization */ - port_uc_addr_set(regs, dkwgbe->dev.enetaddr); - return 0; -} - -static int kwgbe_send(struct eth_device *dev, volatile void *dataptr, - int datasize) -{ - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_registers *regs = dkwgbe->regs; - struct kwgbe_txdesc *p_txdesc = dkwgbe->p_txdesc; - void *p = (void *)dataptr; - u32 cmd_sts; - - /* Copy buffer if it's misaligned */ - if ((u32) dataptr & 0x07) { - if (datasize > PKTSIZE_ALIGN) { - printf("Non-aligned data too large (%d)\n", - datasize); - return -1; - } - - memcpy(dkwgbe->p_aligned_txbuf, p, datasize); - p = dkwgbe->p_aligned_txbuf; - } - - p_txdesc->cmd_sts = KWGBE_ZERO_PADDING | KWGBE_GEN_CRC; - p_txdesc->cmd_sts |= KWGBE_TX_FIRST_DESC | KWGBE_TX_LAST_DESC; - p_txdesc->cmd_sts |= KWGBE_BUFFER_OWNED_BY_DMA; - p_txdesc->cmd_sts |= KWGBE_TX_EN_INTERRUPT; - p_txdesc->buf_ptr = (u8 *) p; - p_txdesc->byte_cnt = datasize; - - /* Set this tc desc as zeroth TXUQ */ - KWGBEREG_WR(regs->tcqdp[TXUQ], (u32) p_txdesc); - - /* ensure tx desc writes above are performed before we start Tx DMA */ - isb(); - - /* Apply send command using zeroth TXUQ */ - KWGBEREG_WR(regs->tqc, (1 << TXUQ)); - - /* - * wait for packet xmit completion - */ - cmd_sts = readl(&p_txdesc->cmd_sts); - while (cmd_sts & KWGBE_BUFFER_OWNED_BY_DMA) { - /* return fail if error is detected */ - if ((cmd_sts & (KWGBE_ERROR_SUMMARY | KWGBE_TX_LAST_FRAME)) == - (KWGBE_ERROR_SUMMARY | KWGBE_TX_LAST_FRAME) && - cmd_sts & (KWGBE_UR_ERROR | KWGBE_RL_ERROR)) { - printf("Err..(%s) in xmit packet\n", __FUNCTION__); - return -1; - } - cmd_sts = readl(&p_txdesc->cmd_sts); - }; - return 0; -} - -static int kwgbe_recv(struct eth_device *dev) -{ - struct kwgbe_device *dkwgbe = to_dkwgbe(dev); - struct kwgbe_rxdesc *p_rxdesc_curr = dkwgbe->p_rxdesc_curr; - u32 cmd_sts; - u32 timeout = 0; - - /* wait untill rx packet available or timeout */ - do { - if (timeout < KWGBE_PHY_SMI_TIMEOUT) - timeout++; - else { - debug("%s time out...\n", __FUNCTION__); - return -1; - } - } while (readl(&p_rxdesc_curr->cmd_sts) & KWGBE_BUFFER_OWNED_BY_DMA); - - if (p_rxdesc_curr->byte_cnt != 0) { - debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n", - __FUNCTION__, (u32) p_rxdesc_curr->byte_cnt, - (u32) p_rxdesc_curr->buf_ptr, - (u32) p_rxdesc_curr->cmd_sts); - } - - /* - * In case received a packet without first/last bits on - * OR the error summary bit is on, - * the packets needs to be dropeed. - */ - cmd_sts = readl(&p_rxdesc_curr->cmd_sts); - - if ((cmd_sts & - (KWGBE_RX_FIRST_DESC | KWGBE_RX_LAST_DESC)) - != (KWGBE_RX_FIRST_DESC | KWGBE_RX_LAST_DESC)) { - - printf("Err..(%s) Dropping packet spread on" - " multiple descriptors\n", __FUNCTION__); - - } else if (cmd_sts & KWGBE_ERROR_SUMMARY) { - - printf("Err..(%s) Dropping packet with errors\n", - __FUNCTION__); - - } else { - /* !!! call higher layer processing */ - debug("%s: Sending Received packet to" - " upper layer (NetReceive)\n", __FUNCTION__); - - /* let the upper layer handle the packet */ - NetReceive((p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET), - (int)(p_rxdesc_curr->byte_cnt - RX_BUF_OFFSET)); - } - /* - * free these descriptors and point next in the ring - */ - p_rxdesc_curr->cmd_sts = - KWGBE_BUFFER_OWNED_BY_DMA | KWGBE_RX_EN_INTERRUPT; - p_rxdesc_curr->buf_size = PKTSIZE_ALIGN; - p_rxdesc_curr->byte_cnt = 0; - - writel((unsigned)p_rxdesc_curr->nxtdesc_p, (u32) &dkwgbe->p_rxdesc_curr); - - return 0; -} - -int kirkwood_egiga_initialize(bd_t * bis) -{ - struct kwgbe_device *dkwgbe; - struct eth_device *dev; - int devnum; - char *s; - u8 used_ports[MAX_KWGBE_DEVS] = CONFIG_KIRKWOOD_EGIGA_PORTS; - - for (devnum = 0; devnum < MAX_KWGBE_DEVS; devnum++) { - /*skip if port is configured not to use */ - if (used_ports[devnum] == 0) - continue; - - if (!(dkwgbe = malloc(sizeof(struct kwgbe_device)))) - goto error1; - - memset(dkwgbe, 0, sizeof(struct kwgbe_device)); - - if (!(dkwgbe->p_rxdesc = - (struct kwgbe_rxdesc *)memalign(PKTALIGN, - KW_RXQ_DESC_ALIGNED_SIZE - * RINGSZ + 1))) - goto error2; - - if (!(dkwgbe->p_rxbuf = (u8 *) memalign(PKTALIGN, RINGSZ - * PKTSIZE_ALIGN + 1))) - goto error3; - - if (!(dkwgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN))) - goto error4; - - if (!(dkwgbe->p_txdesc = (struct kwgbe_txdesc *) - memalign(PKTALIGN, sizeof(struct kwgbe_txdesc) + 1))) { - free(dkwgbe->p_aligned_txbuf); - error4: - free(dkwgbe->p_rxbuf); - error3: - free(dkwgbe->p_rxdesc); - error2: - free(dkwgbe); - error1: - printf("Err.. %s Failed to allocate memory\n", - __FUNCTION__); - return -1; - } - - dev = &dkwgbe->dev; - - /* must be less than NAMESIZE (16) */ - sprintf(dev->name, "egiga%d", devnum); - - /* Extract the MAC address from the environment */ - switch (devnum) { - case 0: - dkwgbe->regs = (void *)KW_EGIGA0_BASE; - s = "ethaddr"; - break; - case 1: - dkwgbe->regs = (void *)KW_EGIGA1_BASE; - s = "eth1addr"; - break; - default: /* this should never happen */ - printf("Err..(%s) Invalid device number %d\n", - __FUNCTION__, devnum); - return -1; - } - - while (!eth_getenv_enetaddr(s, dev->enetaddr)) { - /* Generate Private MAC addr if not set */ - dev->enetaddr[0] = 0x02; - dev->enetaddr[1] = 0x50; - dev->enetaddr[2] = 0x43; -#if defined (CONFIG_SKIP_LOCAL_MAC_RANDOMIZATION) - /* Generate fixed lower MAC half using devnum */ - dev->enetaddr[3] = 0; - dev->enetaddr[4] = 0; - dev->enetaddr[5] = devnum; -#else - /* Generate random lower MAC half */ - dev->enetaddr[3] = get_random_hex(); - dev->enetaddr[4] = get_random_hex(); - dev->enetaddr[5] = get_random_hex(); -#endif - eth_setenv_enetaddr(s, dev->enetaddr); - } - - dev->init = (void *)kwgbe_init; - dev->halt = (void *)kwgbe_halt; - dev->send = (void *)kwgbe_send; - dev->recv = (void *)kwgbe_recv; - dev->write_hwaddr = (void *)kwgbe_write_hwaddr; - - eth_register(dev); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - miiphy_register(dev->name, smi_reg_read, smi_reg_write); - /* Set phy address of the port */ - miiphy_write(dev->name, KIRKWOOD_PHY_ADR_REQUEST, - KIRKWOOD_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum); -#endif - } - return 0; -} diff --git a/drivers/net/kirkwood_egiga.h b/drivers/net/kirkwood_egiga.h deleted file mode 100644 index 30c773ca5c..0000000000 --- a/drivers/net/kirkwood_egiga.h +++ /dev/null @@ -1,505 +0,0 @@ -/* - * (C) Copyright 2009 - * Marvell Semiconductor - * Written-by: Prafulla Wadaskar - * - * based on - Driver for MV64360X ethernet ports - * Copyright (C) 2002 rabeeh@galileo.co.il - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#ifndef __EGIGA_H__ -#define __EGIGA_H__ - -#define MAX_KWGBE_DEVS 2 /*controller has two ports */ - -/* PHY_BASE_ADR is board specific and can be configured */ -#if defined (CONFIG_PHY_BASE_ADR) -#define PHY_BASE_ADR CONFIG_PHY_BASE_ADR -#else -#define PHY_BASE_ADR 0x08 /* default phy base addr */ -#endif - -/* Constants */ -#define INT_CAUSE_UNMASK_ALL 0x0007ffff -#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff -#define MRU_MASK 0xfff1ffff -#define PHYADR_MASK 0x0000001f -#define PHYREG_MASK 0x0000001f -#define QTKNBKT_DEF_VAL 0x3fffffff -#define QMTBS_DEF_VAL 0x000003ff -#define QTKNRT_DEF_VAL 0x0000fcff -#define RXUQ 0 /* Used Rx queue */ -#define TXUQ 0 /* Used Rx queue */ - -#define to_dkwgbe(_kd) container_of(_kd, struct kwgbe_device, dev) -#define KWGBEREG_WR(adr, val) writel(val, &adr) -#define KWGBEREG_RD(adr) readl(&adr) -#define KWGBEREG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr) -#define KWGBEREG_BITS_SET(adr, val) writel(readl(&adr) | val, &adr) - -/* Default port configuration value */ -#define PRT_CFG_VAL ( \ - KWGBE_UCAST_MOD_NRML | \ - KWGBE_DFLT_RXQ(RXUQ) | \ - KWGBE_DFLT_RX_ARPQ(RXUQ) | \ - KWGBE_RX_BC_IF_NOT_IP_OR_ARP | \ - KWGBE_RX_BC_IF_IP | \ - KWGBE_RX_BC_IF_ARP | \ - KWGBE_CPTR_TCP_FRMS_DIS | \ - KWGBE_CPTR_UDP_FRMS_DIS | \ - KWGBE_DFLT_RX_TCPQ(RXUQ) | \ - KWGBE_DFLT_RX_UDPQ(RXUQ) | \ - KWGBE_DFLT_RX_BPDUQ(RXUQ)) - -/* Default port extend configuration value */ -#define PORT_CFG_EXTEND_VALUE \ - KWGBE_SPAN_BPDU_PACKETS_AS_NORMAL | \ - KWGBE_PARTITION_DIS | \ - KWGBE_TX_CRC_GENERATION_EN - -#define GT_KWGBE_IPG_INT_RX(value) ((value & 0x3fff) << 8) - -/* Default sdma control value */ -#define PORT_SDMA_CFG_VALUE ( \ - KWGBE_RX_BURST_SIZE_16_64BIT | \ - KWGBE_BLM_RX_NO_SWAP | \ - KWGBE_BLM_TX_NO_SWAP | \ - GT_KWGBE_IPG_INT_RX(RXUQ) | \ - KWGBE_TX_BURST_SIZE_16_64BIT) - -/* Default port serial control value */ -#define PORT_SERIAL_CONTROL_VALUE ( \ - KWGBE_FORCE_LINK_PASS | \ - KWGBE_DIS_AUTO_NEG_FOR_DUPLX | \ - KWGBE_DIS_AUTO_NEG_FOR_FLOW_CTRL | \ - KWGBE_ADV_NO_FLOW_CTRL | \ - KWGBE_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ - KWGBE_FORCE_BP_MODE_NO_JAM | \ - (1 << 9) /* Reserved bit has to be 1 */ | \ - KWGBE_DO_NOT_FORCE_LINK_FAIL | \ - KWGBE_EN_AUTO_NEG_SPEED_GMII | \ - KWGBE_DTE_ADV_0 | \ - KWGBE_MIIPHY_MAC_MODE | \ - KWGBE_AUTO_NEG_NO_CHANGE | \ - KWGBE_MAX_RX_PACKET_1552BYTE | \ - KWGBE_CLR_EXT_LOOPBACK | \ - KWGBE_SET_FULL_DUPLEX_MODE | \ - KWGBE_DIS_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX) - -/* Tx WRR confoguration macros */ -#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ -#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_FFFF /* PMTBS reg (default) */ -#define PORT_TOKEN_RATE 1023 /* PTTBRC reg (default) */ -/* MAC accepet/reject macros */ -#define ACCEPT_MAC_ADDR 0 -#define REJECT_MAC_ADDR 1 -/* Size of a Tx/Rx descriptor used in chain list data structure */ -#define KW_RXQ_DESC_ALIGNED_SIZE \ - (((sizeof(struct kwgbe_rxdesc) / PKTALIGN) + 1) * PKTALIGN) -/* Buffer offset from buffer pointer */ -#define RX_BUF_OFFSET 0x2 - -/* Port serial status reg (PSR) */ -#define KWGBE_INTERFACE_GMII_MII 0 -#define KWGBE_INTERFACE_PCM 1 -#define KWGBE_LINK_IS_DOWN 0 -#define KWGBE_LINK_IS_UP (1 << 1) -#define KWGBE_PORT_AT_HALF_DUPLEX 0 -#define KWGBE_PORT_AT_FULL_DUPLEX (1 << 2) -#define KWGBE_RX_FLOW_CTRL_DISD 0 -#define KWGBE_RX_FLOW_CTRL_ENBALED (1 << 3) -#define KWGBE_GMII_SPEED_100_10 0 -#define KWGBE_GMII_SPEED_1000 (1 << 4) -#define KWGBE_MII_SPEED_10 0 -#define KWGBE_MII_SPEED_100 (1 << 5) -#define KWGBE_NO_TX 0 -#define KWGBE_TX_IN_PROGRESS (1 << 7) -#define KWGBE_BYPASS_NO_ACTIVE 0 -#define KWGBE_BYPASS_ACTIVE (1 << 8) -#define KWGBE_PORT_NOT_AT_PARTN_STT 0 -#define KWGBE_PORT_AT_PARTN_STT (1 << 9) -#define KWGBE_PORT_TX_FIFO_NOT_EMPTY 0 -#define KWGBE_PORT_TX_FIFO_EMPTY (1 << 10) - -/* These macros describes the Port configuration reg (Px_cR) bits */ -#define KWGBE_UCAST_MOD_NRML 0 -#define KWGBE_UNICAST_PROMISCUOUS_MODE 1 -#define KWGBE_DFLT_RXQ(_x) (_x << 1) -#define KWGBE_DFLT_RX_ARPQ(_x) (_x << 4) -#define KWGBE_RX_BC_IF_NOT_IP_OR_ARP 0 -#define KWGBE_REJECT_BC_IF_NOT_IP_OR_ARP (1 << 7) -#define KWGBE_RX_BC_IF_IP 0 -#define KWGBE_REJECT_BC_IF_IP (1 << 8) -#define KWGBE_RX_BC_IF_ARP 0 -#define KWGBE_REJECT_BC_IF_ARP (1 << 9) -#define KWGBE_TX_AM_NO_UPDATE_ERR_SMRY (1 << 12) -#define KWGBE_CPTR_TCP_FRMS_DIS 0 -#define KWGBE_CPTR_TCP_FRMS_EN (1 << 14) -#define KWGBE_CPTR_UDP_FRMS_DIS 0 -#define KWGBE_CPTR_UDP_FRMS_EN (1 << 15) -#define KWGBE_DFLT_RX_TCPQ(_x) (_x << 16) -#define KWGBE_DFLT_RX_UDPQ(_x) (_x << 19) -#define KWGBE_DFLT_RX_BPDUQ(_x) (_x << 22) -#define KWGBE_DFLT_RX_TCP_CHKSUM_MODE (1 << 25) - -/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ -#define KWGBE_CLASSIFY_EN 1 -#define KWGBE_SPAN_BPDU_PACKETS_AS_NORMAL 0 -#define KWGBE_SPAN_BPDU_PACKETS_TO_RX_Q7 (1 << 1) -#define KWGBE_PARTITION_DIS 0 -#define KWGBE_PARTITION_EN (1 << 2) -#define KWGBE_TX_CRC_GENERATION_EN 0 -#define KWGBE_TX_CRC_GENERATION_DIS (1 << 3) - -/* These macros describes the Port Sdma configuration reg (SDCR) bits */ -#define KWGBE_RIFB 1 -#define KWGBE_RX_BURST_SIZE_1_64BIT 0 -#define KWGBE_RX_BURST_SIZE_2_64BIT (1 << 1) -#define KWGBE_RX_BURST_SIZE_4_64BIT (1 << 2) -#define KWGBE_RX_BURST_SIZE_8_64BIT ((1 << 2) | (1 << 1)) -#define KWGBE_RX_BURST_SIZE_16_64BIT (1 << 3) -#define KWGBE_BLM_RX_NO_SWAP (1 << 4) -#define KWGBE_BLM_RX_BYTE_SWAP 0 -#define KWGBE_BLM_TX_NO_SWAP (1 << 5) -#define KWGBE_BLM_TX_BYTE_SWAP 0 -#define KWGBE_DESCRIPTORS_BYTE_SWAP (1 << 6) -#define KWGBE_DESCRIPTORS_NO_SWAP 0 -#define KWGBE_TX_BURST_SIZE_1_64BIT 0 -#define KWGBE_TX_BURST_SIZE_2_64BIT (1 << 22) -#define KWGBE_TX_BURST_SIZE_4_64BIT (1 << 23) -#define KWGBE_TX_BURST_SIZE_8_64BIT ((1 << 23) | (1 << 22)) -#define KWGBE_TX_BURST_SIZE_16_64BIT (1 << 24) - -/* These macros describes the Port serial control reg (PSCR) bits */ -#define KWGBE_SERIAL_PORT_DIS 0 -#define KWGBE_SERIAL_PORT_EN 1 -#define KWGBE_FORCE_LINK_PASS (1 << 1) -#define KWGBE_DO_NOT_FORCE_LINK_PASS 0 -#define KWGBE_EN_AUTO_NEG_FOR_DUPLX 0 -#define KWGBE_DIS_AUTO_NEG_FOR_DUPLX (1 << 2) -#define KWGBE_EN_AUTO_NEG_FOR_FLOW_CTRL 0 -#define KWGBE_DIS_AUTO_NEG_FOR_FLOW_CTRL (1 << 3) -#define KWGBE_ADV_NO_FLOW_CTRL 0 -#define KWGBE_ADV_SYMMETRIC_FLOW_CTRL (1 << 4) -#define KWGBE_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 -#define KWGBE_FORCE_FC_MODE_TX_PAUSE_DIS (1 << 5) -#define KWGBE_FORCE_BP_MODE_NO_JAM 0 -#define KWGBE_FORCE_BP_MODE_JAM_TX (1 << 7) -#define KWGBE_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1 << 8) -#define KWGBE_FORCE_LINK_FAIL 0 -#define KWGBE_DO_NOT_FORCE_LINK_FAIL (1 << 10) -#define KWGBE_DIS_AUTO_NEG_SPEED_GMII (1 << 13) -#define KWGBE_EN_AUTO_NEG_SPEED_GMII 0 -#define KWGBE_DTE_ADV_0 0 -#define KWGBE_DTE_ADV_1 (1 << 14) -#define KWGBE_MIIPHY_MAC_MODE 0 -#define KWGBE_MIIPHY_PHY_MODE (1 << 15) -#define KWGBE_AUTO_NEG_NO_CHANGE 0 -#define KWGBE_RESTART_AUTO_NEG (1 << 16) -#define KWGBE_MAX_RX_PACKET_1518BYTE 0 -#define KWGBE_MAX_RX_PACKET_1522BYTE (1 << 17) -#define KWGBE_MAX_RX_PACKET_1552BYTE (1 << 18) -#define KWGBE_MAX_RX_PACKET_9022BYTE ((1 << 18) | (1 << 17)) -#define KWGBE_MAX_RX_PACKET_9192BYTE (1 << 19) -#define KWGBE_MAX_RX_PACKET_9700BYTE ((1 << 19) | (1 << 17)) -#define KWGBE_SET_EXT_LOOPBACK (1 << 20) -#define KWGBE_CLR_EXT_LOOPBACK 0 -#define KWGBE_SET_FULL_DUPLEX_MODE (1 << 21) -#define KWGBE_SET_HALF_DUPLEX_MODE 0 -#define KWGBE_EN_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1 << 22) -#define KWGBE_DIS_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 -#define KWGBE_SET_GMII_SPEED_TO_10_100 0 -#define KWGBE_SET_GMII_SPEED_TO_1000 (1 << 23) -#define KWGBE_SET_MII_SPEED_TO_10 0 -#define KWGBE_SET_MII_SPEED_TO_100 (1 << 24) - -/* SMI register fields */ -#define KWGBE_PHY_SMI_TIMEOUT 10000 -#define KWGBE_PHY_SMI_DATA_OFFS 0 /* Data */ -#define KWGBE_PHY_SMI_DATA_MASK (0xffff << KWGBE_PHY_SMI_DATA_OFFS) -#define KWGBE_PHY_SMI_DEV_ADDR_OFFS 16 /* PHY device address */ -#define KWGBE_PHY_SMI_DEV_ADDR_MASK (PHYADR_MASK << KWGBE_PHY_SMI_DEV_ADDR_OFFS) -#define KWGBE_SMI_REG_ADDR_OFFS 21 /* PHY device reg addr */ -#define KWGBE_SMI_REG_ADDR_MASK (PHYADR_MASK << KWGBE_SMI_REG_ADDR_OFFS) -#define KWGBE_PHY_SMI_OPCODE_OFFS 26 /* Write/Read opcode */ -#define KWGBE_PHY_SMI_OPCODE_MASK (3 << KWGBE_PHY_SMI_OPCODE_OFFS) -#define KWGBE_PHY_SMI_OPCODE_WRITE (0 << KWGBE_PHY_SMI_OPCODE_OFFS) -#define KWGBE_PHY_SMI_OPCODE_READ (1 << KWGBE_PHY_SMI_OPCODE_OFFS) -#define KWGBE_PHY_SMI_READ_VALID_MASK (1 << 27) /* Read Valid */ -#define KWGBE_PHY_SMI_BUSY_MASK (1 << 28) /* Busy */ - -/* SDMA command status fields macros */ -/* Tx & Rx descriptors status */ -#define KWGBE_ERROR_SUMMARY 1 -/* Tx & Rx descriptors command */ -#define KWGBE_BUFFER_OWNED_BY_DMA (1 << 31) -/* Tx descriptors status */ -#define KWGBE_LC_ERROR 0 -#define KWGBE_UR_ERROR (1 << 1) -#define KWGBE_RL_ERROR (1 << 2) -#define KWGBE_LLC_SNAP_FORMAT (1 << 9) -#define KWGBE_TX_LAST_FRAME (1 << 20) - -/* Rx descriptors status */ -#define KWGBE_CRC_ERROR 0 -#define KWGBE_OVERRUN_ERROR (1 << 1) -#define KWGBE_MAX_FRAME_LENGTH_ERROR (1 << 2) -#define KWGBE_RESOURCE_ERROR ((1 << 2) | (1 << 1)) -#define KWGBE_VLAN_TAGGED (1 << 19) -#define KWGBE_BPDU_FRAME (1 << 20) -#define KWGBE_TCP_FRAME_OVER_IP_V_4 0 -#define KWGBE_UDP_FRAME_OVER_IP_V_4 (1 << 21) -#define KWGBE_OTHER_FRAME_TYPE (1 << 22) -#define KWGBE_LAYER_2_IS_KWGBE_V_2 (1 << 23) -#define KWGBE_FRAME_TYPE_IP_V_4 (1 << 24) -#define KWGBE_FRAME_HEADER_OK (1 << 25) -#define KWGBE_RX_LAST_DESC (1 << 26) -#define KWGBE_RX_FIRST_DESC (1 << 27) -#define KWGBE_UNKNOWN_DESTINATION_ADDR (1 << 28) -#define KWGBE_RX_EN_INTERRUPT (1 << 29) -#define KWGBE_LAYER_4_CHECKSUM_OK (1 << 30) - -/* Rx descriptors byte count */ -#define KWGBE_FRAME_FRAGMENTED (1 << 2) - -/* Tx descriptors command */ -#define KWGBE_LAYER_4_CHECKSUM_FIRST_DESC (1 << 10) -#define KWGBE_FRAME_SET_TO_VLAN (1 << 15) -#define KWGBE_TCP_FRAME 0 -#define KWGBE_UDP_FRAME (1 << 16) -#define KWGBE_GEN_TCP_UDP_CHECKSUM (1 << 17) -#define KWGBE_GEN_IP_V_4_CHECKSUM (1 << 18) -#define KWGBE_ZERO_PADDING (1 << 19) -#define KWGBE_TX_LAST_DESC (1 << 20) -#define KWGBE_TX_FIRST_DESC (1 << 21) -#define KWGBE_GEN_CRC (1 << 22) -#define KWGBE_TX_EN_INTERRUPT (1 << 23) -#define KWGBE_AUTO_MODE (1 << 30) - -/* Address decode parameters */ -/* Ethernet Base Address Register bits */ -#define EBAR_TARGET_DRAM 0x00000000 -#define EBAR_TARGET_DEVICE 0x00000001 -#define EBAR_TARGET_CBS 0x00000002 -#define EBAR_TARGET_PCI0 0x00000003 -#define EBAR_TARGET_PCI1 0x00000004 -#define EBAR_TARGET_CUNIT 0x00000005 -#define EBAR_TARGET_AUNIT 0x00000006 -#define EBAR_TARGET_GUNIT 0x00000007 - -/* Window attrib */ -#define EBAR_DRAM_CS0 0x00000E00 -#define EBAR_DRAM_CS1 0x00000D00 -#define EBAR_DRAM_CS2 0x00000B00 -#define EBAR_DRAM_CS3 0x00000700 - -/* DRAM Target interface */ -#define EBAR_DRAM_NO_CACHE_COHERENCY 0x00000000 -#define EBAR_DRAM_CACHE_COHERENCY_WT 0x00001000 -#define EBAR_DRAM_CACHE_COHERENCY_WB 0x00002000 - -/* Device Bus Target interface */ -#define EBAR_DEVICE_DEVCS0 0x00001E00 -#define EBAR_DEVICE_DEVCS1 0x00001D00 -#define EBAR_DEVICE_DEVCS2 0x00001B00 -#define EBAR_DEVICE_DEVCS3 0x00001700 -#define EBAR_DEVICE_BOOTCS3 0x00000F00 - -/* PCI Target interface */ -#define EBAR_PCI_BYTE_SWAP 0x00000000 -#define EBAR_PCI_NO_SWAP 0x00000100 -#define EBAR_PCI_BYTE_WORD_SWAP 0x00000200 -#define EBAR_PCI_WORD_SWAP 0x00000300 -#define EBAR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 -#define EBAR_PCI_NO_SNOOP_ASSERT 0x00000400 -#define EBAR_PCI_IO_SPACE 0x00000000 -#define EBAR_PCI_MEMORY_SPACE 0x00000800 -#define EBAR_PCI_REQ64_FORCE 0x00000000 -#define EBAR_PCI_REQ64_SIZE 0x00001000 - -/* Window access control */ -#define EWIN_ACCESS_NOT_ALLOWED 0 -#define EWIN_ACCESS_READ_ONLY 1 -#define EWIN_ACCESS_FULL ((1 << 1) | 1) - -/* structures represents Controller registers */ -struct kwgbe_barsz { - u32 bar; - u32 size; -}; - -struct kwgbe_rxcdp { - struct kwgbe_rxdesc *rxcdp; - u32 rxcdp_pad[3]; -}; - -struct kwgbe_tqx { - u32 qxttbc; - u32 tqxtbc; - u32 tqxac; - u32 tqxpad; -}; - -struct kwgbe_registers { - u32 phyadr; - u32 smi; - u32 euda; - u32 eudid; - u8 pad1[0x080 - 0x00c - 4]; - u32 euic; - u32 euim; - u8 pad2[0x094 - 0x084 - 4]; - u32 euea; - u32 euiae; - u8 pad3[0x0b0 - 0x098 - 4]; - u32 euc; - u8 pad3a[0x200 - 0x0b0 - 4]; - struct kwgbe_barsz barsz[6]; - u8 pad4[0x280 - 0x22c - 4]; - u32 ha_remap[4]; - u32 bare; - u32 epap; - u8 pad5[0x400 - 0x294 - 4]; - u32 pxc; - u32 pxcx; - u32 mii_ser_params; - u8 pad6[0x410 - 0x408 - 4]; - u32 evlane; - u32 macal; - u32 macah; - u32 sdc; - u32 dscp[7]; - u32 psc0; - u32 vpt2p; - u32 ps0; - u32 tqc; - u32 psc1; - u32 ps1; - u32 mrvl_header; - u8 pad7[0x460 - 0x454 - 4]; - u32 ic; - u32 ice; - u32 pim; - u32 peim; - u8 pad8[0x474 - 0x46c - 4]; - u32 pxtfut; - u32 pad9; - u32 pxmfs; - u32 pad10; - u32 pxdfc; - u32 pxofc; - u8 pad11[0x494 - 0x488 - 4]; - u32 peuiae; - u8 pad12[0x4bc - 0x494 - 4]; - u32 eth_type_prio; - u8 pad13[0x4dc - 0x4bc - 4]; - u32 tqfpc; - u32 pttbrc; - u32 tqc1; - u32 pmtu; - u32 pmtbs; - u8 pad14[0x60c - 0x4ec - 4]; - struct kwgbe_rxcdp rxcdp[7]; - struct kwgbe_rxdesc *rxcdp7; - u32 rqc; - struct kwgbe_txdesc *tcsdp; - u8 pad15[0x6c0 - 0x684 - 4]; - struct kwgbe_txdesc *tcqdp[8]; - u8 pad16[0x700 - 0x6dc - 4]; - struct kwgbe_tqx tqx[8]; - u32 pttbc; - u8 pad17[0x7a8 - 0x780 - 4]; - u32 tqxipg0; - u32 pad18[3]; - u32 tqxipg1; - u8 pad19[0x7c0 - 0x7b8 - 4]; - u32 hitkninlopkt; - u32 hitkninasyncpkt; - u32 lotkninasyncpkt; - u32 pad20; - u32 ts; - u8 pad21[0x3000 - 0x27d0 - 4]; - u32 pad20_1[32]; /* mib counter registes */ - u8 pad22[0x3400 - 0x3000 - sizeof(u32) * 32]; - u32 dfsmt[64]; - u32 dfomt[64]; - u32 dfut[4]; - u8 pad23[0xe20c0 - 0x7360c - 4]; - u32 pmbus_top_arbiter; -}; - -/* structures/enums needed by driver */ -enum kwgbe_adrwin { - KWGBE_WIN0, - KWGBE_WIN1, - KWGBE_WIN2, - KWGBE_WIN3, - KWGBE_WIN4, - KWGBE_WIN5 -}; - -enum kwgbe_target { - KWGBE_TARGET_DRAM, - KWGBE_TARGET_DEV, - KWGBE_TARGET_CBS, - KWGBE_TARGET_PCI0, - KWGBE_TARGET_PCI1 -}; - -struct kwgbe_winparam { - enum kwgbe_adrwin win; /* Window number */ - enum kwgbe_target target; /* System targets */ - u16 attrib; /* BAR attrib. See above macros */ - u32 base_addr; /* Window base address in u32 form */ - u32 high_addr; /* Window high address in u32 form */ - u32 size; /* Size in MBytes. Must be % 64Kbyte. */ - int enable; /* Enable/disable access to the window. */ - u16 access_ctrl; /*Access ctrl register. see above macros */ -}; - -struct kwgbe_rxdesc { - u32 cmd_sts; /* Descriptor command status */ - u16 buf_size; /* Buffer size */ - u16 byte_cnt; /* Descriptor buffer byte count */ - u8 *buf_ptr; /* Descriptor buffer pointer */ - struct kwgbe_rxdesc *nxtdesc_p; /* Next descriptor pointer */ -}; - -struct kwgbe_txdesc { - u32 cmd_sts; /* Descriptor command status */ - u16 l4i_chk; /* CPU provided TCP Checksum */ - u16 byte_cnt; /* Descriptor buffer byte count */ - u8 *buf_ptr; /* Descriptor buffer ptr */ - struct kwgbe_txdesc *nxtdesc_p; /* Next descriptor ptr */ -}; - -/* port device data struct */ -struct kwgbe_device { - struct eth_device dev; - struct kwgbe_registers *regs; - struct kwgbe_txdesc *p_txdesc; - struct kwgbe_rxdesc *p_rxdesc; - struct kwgbe_rxdesc *p_rxdesc_curr; - u8 *p_rxbuf; - u8 *p_aligned_txbuf; -}; - -#endif /* __EGIGA_H__ */ diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c new file mode 100644 index 0000000000..1efca1e9e9 --- /dev/null +++ b/drivers/net/mvgbe.c @@ -0,0 +1,736 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor + * Written-by: Prafulla Wadaskar + * + * (C) Copyright 2003 + * Ingo Assmus + * + * based on - Driver for MV64360X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mvgbe.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define KIRKWOOD_PHY_ADR_REQUEST 0xee +#define KWGBE_SMI_REG (((struct kwgbe_registers *)KW_EGIGA0_BASE)->smi) + +/* + * smi_reg_read - miiphy_read callback function. + * + * Returns 16bit phy register value, or 0xffff on error + */ +static int smi_reg_read(char *devname, u8 phy_adr, u8 reg_ofs, u16 * data) +{ + struct eth_device *dev = eth_get_dev_by_name(devname); + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; + u32 smi_reg; + u32 timeout; + + /* Phyadr read request */ + if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && + reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { + /* */ + *data = (u16) (KWGBEREG_RD(regs->phyadr) & PHYADR_MASK); + return 0; + } + /* check parameters */ + if (phy_adr > PHYADR_MASK) { + printf("Err..(%s) Invalid PHY address %d\n", + __FUNCTION__, phy_adr); + return -EFAULT; + } + if (reg_ofs > PHYREG_MASK) { + printf("Err..(%s) Invalid register offset %d\n", + __FUNCTION__, reg_ofs); + return -EFAULT; + } + + timeout = KWGBE_PHY_SMI_TIMEOUT; + /* wait till the SMI is not busy */ + do { + /* read smi register */ + smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); + if (timeout-- == 0) { + printf("Err..(%s) SMI busy timeout\n", __FUNCTION__); + return -EFAULT; + } + } while (smi_reg & KWGBE_PHY_SMI_BUSY_MASK); + + /* fill the phy address and regiser offset and read opcode */ + smi_reg = (phy_adr << KWGBE_PHY_SMI_DEV_ADDR_OFFS) + | (reg_ofs << KWGBE_SMI_REG_ADDR_OFFS) + | KWGBE_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + KWGBEREG_WR(KWGBE_SMI_REG, smi_reg); + + /*wait till read value is ready */ + timeout = KWGBE_PHY_SMI_TIMEOUT; + + do { + /* read smi register */ + smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); + if (timeout-- == 0) { + printf("Err..(%s) SMI read ready timeout\n", + __FUNCTION__); + return -EFAULT; + } + } while (!(smi_reg & KWGBE_PHY_SMI_READ_VALID_MASK)); + + /* Wait for the data to update in the SMI register */ + for (timeout = 0; timeout < KWGBE_PHY_SMI_TIMEOUT; timeout++) ; + + *data = (u16) (KWGBEREG_RD(KWGBE_SMI_REG) & KWGBE_PHY_SMI_DATA_MASK); + + debug("%s:(adr %d, off %d) value= %04x\n", __FUNCTION__, phy_adr, + reg_ofs, *data); + + return 0; +} + +/* + * smi_reg_write - imiiphy_write callback function. + * + * Returns 0 if write succeed, -EINVAL on bad parameters + * -ETIME on timeout + */ +static int smi_reg_write(char *devname, u8 phy_adr, u8 reg_ofs, u16 data) +{ + struct eth_device *dev = eth_get_dev_by_name(devname); + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; + u32 smi_reg; + u32 timeout; + + /* Phyadr write request*/ + if (phy_adr == KIRKWOOD_PHY_ADR_REQUEST && + reg_ofs == KIRKWOOD_PHY_ADR_REQUEST) { + KWGBEREG_WR(regs->phyadr, data); + return 0; + } + + /* check parameters */ + if (phy_adr > PHYADR_MASK) { + printf("Err..(%s) Invalid phy address\n", __FUNCTION__); + return -EINVAL; + } + if (reg_ofs > PHYREG_MASK) { + printf("Err..(%s) Invalid register offset\n", __FUNCTION__); + return -EINVAL; + } + + /* wait till the SMI is not busy */ + timeout = KWGBE_PHY_SMI_TIMEOUT; + do { + /* read smi register */ + smi_reg = KWGBEREG_RD(KWGBE_SMI_REG); + if (timeout-- == 0) { + printf("Err..(%s) SMI busy timeout\n", __FUNCTION__); + return -ETIME; + } + } while (smi_reg & KWGBE_PHY_SMI_BUSY_MASK); + + /* fill the phy addr and reg offset and write opcode and data */ + smi_reg = (data << KWGBE_PHY_SMI_DATA_OFFS); + smi_reg |= (phy_adr << KWGBE_PHY_SMI_DEV_ADDR_OFFS) + | (reg_ofs << KWGBE_SMI_REG_ADDR_OFFS); + smi_reg &= ~KWGBE_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + KWGBEREG_WR(KWGBE_SMI_REG, smi_reg); + + return 0; +} + +/* Stop and checks all queues */ +static void stop_queue(u32 * qreg) +{ + u32 reg_data; + + reg_data = readl(qreg); + + if (reg_data & 0xFF) { + /* Issue stop command for active channels only */ + writel((reg_data << 8), qreg); + + /* Wait for all queue activity to terminate. */ + do { + /* + * Check port cause register that all queues + * are stopped + */ + reg_data = readl(qreg); + } + while (reg_data & 0xFF); + } +} + +/* + * set_access_control - Config address decode parameters for Ethernet unit + * + * This function configures the address decode parameters for the Gigabit + * Ethernet Controller according the given parameters struct. + * + * @regs Register struct pointer. + * @param Address decode parameter struct. + */ +static void set_access_control(struct kwgbe_registers *regs, + struct kwgbe_winparam *param) +{ + u32 access_prot_reg; + + /* Set access control register */ + access_prot_reg = KWGBEREG_RD(regs->epap); + /* clear window permission */ + access_prot_reg &= (~(3 << (param->win * 2))); + access_prot_reg |= (param->access_ctrl << (param->win * 2)); + KWGBEREG_WR(regs->epap, access_prot_reg); + + /* Set window Size reg (SR) */ + KWGBEREG_WR(regs->barsz[param->win].size, + (((param->size / 0x10000) - 1) << 16)); + + /* Set window Base address reg (BA) */ + KWGBEREG_WR(regs->barsz[param->win].bar, + (param->target | param->attrib | param->base_addr)); + /* High address remap reg (HARR) */ + if (param->win < 4) + KWGBEREG_WR(regs->ha_remap[param->win], param->high_addr); + + /* Base address enable reg (BARER) */ + if (param->enable == 1) + KWGBEREG_BITS_RESET(regs->bare, (1 << param->win)); + else + KWGBEREG_BITS_SET(regs->bare, (1 << param->win)); +} + +static void set_dram_access(struct kwgbe_registers *regs) +{ + struct kwgbe_winparam win_param; + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + /* Set access parameters for DRAM bank i */ + win_param.win = i; /* Use Ethernet window i */ + /* Window target - DDR */ + win_param.target = KWGBE_TARGET_DRAM; + /* Enable full access */ + win_param.access_ctrl = EWIN_ACCESS_FULL; + win_param.high_addr = 0; + /* Get bank base and size */ + win_param.base_addr = gd->bd->bi_dram[i].start; + win_param.size = gd->bd->bi_dram[i].size; + if (win_param.size == 0) + win_param.enable = 0; + else + win_param.enable = 1; /* Enable the access */ + + /* Enable DRAM bank */ + switch (i) { + case 0: + win_param.attrib = EBAR_DRAM_CS0; + break; + case 1: + win_param.attrib = EBAR_DRAM_CS1; + break; + case 2: + win_param.attrib = EBAR_DRAM_CS2; + break; + case 3: + win_param.attrib = EBAR_DRAM_CS3; + break; + default: + /* invalid bank, disable access */ + win_param.enable = 0; + win_param.attrib = 0; + break; + } + /* Set the access control for address window(EPAPR) RD/WR */ + set_access_control(regs, &win_param); + } +} + +/* + * port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables + * + * Go through all the DA filter tables (Unicast, Special Multicast & Other + * Multicast) and set each entry to 0. + */ +static void port_init_mac_tables(struct kwgbe_registers *regs) +{ + int table_index; + + /* Clear DA filter unicast table (Ex_dFUT) */ + for (table_index = 0; table_index < 4; ++table_index) + KWGBEREG_WR(regs->dfut[table_index], 0); + + for (table_index = 0; table_index < 64; ++table_index) { + /* Clear DA filter special multicast table (Ex_dFSMT) */ + KWGBEREG_WR(regs->dfsmt[table_index], 0); + /* Clear DA filter other multicast table (Ex_dFOMT) */ + KWGBEREG_WR(regs->dfomt[table_index], 0); + } +} + +/* + * port_uc_addr - This function Set the port unicast address table + * + * This function locates the proper entry in the Unicast table for the + * specified MAC nibble and sets its properties according to function + * parameters. + * This function add/removes MAC addresses from the port unicast address + * table. + * + * @uc_nibble Unicast MAC Address last nibble. + * @option 0 = Add, 1 = remove address. + * + * RETURN: 1 if output succeeded. 0 if option parameter is invalid. + */ +static int port_uc_addr(struct kwgbe_registers *regs, u8 uc_nibble, + int option) +{ + u32 unicast_reg; + u32 tbl_offset; + u32 reg_offset; + + /* Locate the Unicast table entry */ + uc_nibble = (0xf & uc_nibble); + /* Register offset from unicast table base */ + tbl_offset = (uc_nibble / 4); + /* Entry offset within the above register */ + reg_offset = uc_nibble % 4; + + switch (option) { + case REJECT_MAC_ADDR: + /* + * Clear accepts frame bit at specified unicast + * DA table entry + */ + unicast_reg = KWGBEREG_RD(regs->dfut[tbl_offset]); + unicast_reg &= (0xFF << (8 * reg_offset)); + KWGBEREG_WR(regs->dfut[tbl_offset], unicast_reg); + break; + case ACCEPT_MAC_ADDR: + /* Set accepts frame bit at unicast DA filter table entry */ + unicast_reg = KWGBEREG_RD(regs->dfut[tbl_offset]); + unicast_reg &= (0xFF << (8 * reg_offset)); + unicast_reg |= ((0x01 | (RXUQ << 1)) << (8 * reg_offset)); + KWGBEREG_WR(regs->dfut[tbl_offset], unicast_reg); + break; + default: + return 0; + } + return 1; +} + +/* + * port_uc_addr_set - This function Set the port Unicast address. + */ +static void port_uc_addr_set(struct kwgbe_registers *regs, u8 * p_addr) +{ + u32 mac_h; + u32 mac_l; + + mac_l = (p_addr[4] << 8) | (p_addr[5]); + mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) | + (p_addr[3] << 0); + + KWGBEREG_WR(regs->macal, mac_l); + KWGBEREG_WR(regs->macah, mac_h); + + /* Accept frames of this address */ + port_uc_addr(regs, p_addr[5], ACCEPT_MAC_ADDR); +} + +/* + * kwgbe_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory. + */ +static void kwgbe_init_rx_desc_ring(struct kwgbe_device *dkwgbe) +{ + struct kwgbe_rxdesc *p_rx_desc; + int i; + + /* initialize the Rx descriptors ring */ + p_rx_desc = dkwgbe->p_rxdesc; + for (i = 0; i < RINGSZ; i++) { + p_rx_desc->cmd_sts = + KWGBE_BUFFER_OWNED_BY_DMA | KWGBE_RX_EN_INTERRUPT; + p_rx_desc->buf_size = PKTSIZE_ALIGN; + p_rx_desc->byte_cnt = 0; + p_rx_desc->buf_ptr = dkwgbe->p_rxbuf + i * PKTSIZE_ALIGN; + if (i == (RINGSZ - 1)) + p_rx_desc->nxtdesc_p = dkwgbe->p_rxdesc; + else { + p_rx_desc->nxtdesc_p = (struct kwgbe_rxdesc *) + ((u32) p_rx_desc + KW_RXQ_DESC_ALIGNED_SIZE); + p_rx_desc = p_rx_desc->nxtdesc_p; + } + } + dkwgbe->p_rxdesc_curr = dkwgbe->p_rxdesc; +} + +static int kwgbe_init(struct eth_device *dev) +{ + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; +#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ + && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) + int i; +#endif + /* setup RX rings */ + kwgbe_init_rx_desc_ring(dkwgbe); + + /* Clear the ethernet port interrupts */ + KWGBEREG_WR(regs->ic, 0); + KWGBEREG_WR(regs->ice, 0); + /* Unmask RX buffer and TX end interrupt */ + KWGBEREG_WR(regs->pim, INT_CAUSE_UNMASK_ALL); + /* Unmask phy and link status changes interrupts */ + KWGBEREG_WR(regs->peim, INT_CAUSE_UNMASK_ALL_EXT); + + set_dram_access(regs); + port_init_mac_tables(regs); + port_uc_addr_set(regs, dkwgbe->dev.enetaddr); + + /* Assign port configuration and command. */ + KWGBEREG_WR(regs->pxc, PRT_CFG_VAL); + KWGBEREG_WR(regs->pxcx, PORT_CFG_EXTEND_VALUE); + KWGBEREG_WR(regs->psc0, PORT_SERIAL_CONTROL_VALUE); + + /* Assign port SDMA configuration */ + KWGBEREG_WR(regs->sdc, PORT_SDMA_CFG_VALUE); + KWGBEREG_WR(regs->tqx[0].qxttbc, QTKNBKT_DEF_VAL); + KWGBEREG_WR(regs->tqx[0].tqxtbc, (QMTBS_DEF_VAL << 16) | QTKNRT_DEF_VAL); + /* Turn off the port/RXUQ bandwidth limitation */ + KWGBEREG_WR(regs->pmtu, 0); + + /* Set maximum receive buffer to 9700 bytes */ + KWGBEREG_WR(regs->psc0, KWGBE_MAX_RX_PACKET_9700BYTE + | (KWGBEREG_RD(regs->psc0) & MRU_MASK)); + + /* Enable port initially */ + KWGBEREG_BITS_SET(regs->psc0, KWGBE_SERIAL_PORT_EN); + + /* + * Set ethernet MTU for leaky bucket mechanism to 0 - this will + * disable the leaky bucket mechanism . + */ + KWGBEREG_WR(regs->pmtu, 0); + + /* Assignment of Rx CRDB of given RXUQ */ + KWGBEREG_WR(regs->rxcdp[RXUQ], (u32) dkwgbe->p_rxdesc_curr); + /* ensure previous write is done before enabling Rx DMA */ + isb(); + /* Enable port Rx. */ + KWGBEREG_WR(regs->rqc, (1 << RXUQ)); + +#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \ + && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN) + /* Wait up to 5s for the link status */ + for (i = 0; i < 5; i++) { + u16 phyadr; + + miiphy_read(dev->name, KIRKWOOD_PHY_ADR_REQUEST, + KIRKWOOD_PHY_ADR_REQUEST, &phyadr); + /* Return if we get link up */ + if (miiphy_link(dev->name, phyadr)) + return 0; + udelay(1000000); + } + + printf("No link on %s\n", dev->name); + return -1; +#endif + return 0; +} + +static int kwgbe_halt(struct eth_device *dev) +{ + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; + + /* Disable all gigE address decoder */ + KWGBEREG_WR(regs->bare, 0x3f); + + stop_queue(®s->tqc); + stop_queue(®s->rqc); + + /* Disable port */ + KWGBEREG_BITS_RESET(regs->psc0, KWGBE_SERIAL_PORT_EN); + /* Set port is not reset */ + KWGBEREG_BITS_RESET(regs->psc1, 1 << 4); +#ifdef CONFIG_SYS_MII_MODE + /* Set MMI interface up */ + KWGBEREG_BITS_RESET(regs->psc1, 1 << 3); +#endif + /* Disable & mask ethernet port interrupts */ + KWGBEREG_WR(regs->ic, 0); + KWGBEREG_WR(regs->ice, 0); + KWGBEREG_WR(regs->pim, 0); + KWGBEREG_WR(regs->peim, 0); + + return 0; +} + +static int kwgbe_write_hwaddr(struct eth_device *dev) +{ + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; + + /* Programs net device MAC address after initialization */ + port_uc_addr_set(regs, dkwgbe->dev.enetaddr); + return 0; +} + +static int kwgbe_send(struct eth_device *dev, volatile void *dataptr, + int datasize) +{ + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_registers *regs = dkwgbe->regs; + struct kwgbe_txdesc *p_txdesc = dkwgbe->p_txdesc; + void *p = (void *)dataptr; + u32 cmd_sts; + + /* Copy buffer if it's misaligned */ + if ((u32) dataptr & 0x07) { + if (datasize > PKTSIZE_ALIGN) { + printf("Non-aligned data too large (%d)\n", + datasize); + return -1; + } + + memcpy(dkwgbe->p_aligned_txbuf, p, datasize); + p = dkwgbe->p_aligned_txbuf; + } + + p_txdesc->cmd_sts = KWGBE_ZERO_PADDING | KWGBE_GEN_CRC; + p_txdesc->cmd_sts |= KWGBE_TX_FIRST_DESC | KWGBE_TX_LAST_DESC; + p_txdesc->cmd_sts |= KWGBE_BUFFER_OWNED_BY_DMA; + p_txdesc->cmd_sts |= KWGBE_TX_EN_INTERRUPT; + p_txdesc->buf_ptr = (u8 *) p; + p_txdesc->byte_cnt = datasize; + + /* Set this tc desc as zeroth TXUQ */ + KWGBEREG_WR(regs->tcqdp[TXUQ], (u32) p_txdesc); + + /* ensure tx desc writes above are performed before we start Tx DMA */ + isb(); + + /* Apply send command using zeroth TXUQ */ + KWGBEREG_WR(regs->tqc, (1 << TXUQ)); + + /* + * wait for packet xmit completion + */ + cmd_sts = readl(&p_txdesc->cmd_sts); + while (cmd_sts & KWGBE_BUFFER_OWNED_BY_DMA) { + /* return fail if error is detected */ + if ((cmd_sts & (KWGBE_ERROR_SUMMARY | KWGBE_TX_LAST_FRAME)) == + (KWGBE_ERROR_SUMMARY | KWGBE_TX_LAST_FRAME) && + cmd_sts & (KWGBE_UR_ERROR | KWGBE_RL_ERROR)) { + printf("Err..(%s) in xmit packet\n", __FUNCTION__); + return -1; + } + cmd_sts = readl(&p_txdesc->cmd_sts); + }; + return 0; +} + +static int kwgbe_recv(struct eth_device *dev) +{ + struct kwgbe_device *dkwgbe = to_dkwgbe(dev); + struct kwgbe_rxdesc *p_rxdesc_curr = dkwgbe->p_rxdesc_curr; + u32 cmd_sts; + u32 timeout = 0; + + /* wait untill rx packet available or timeout */ + do { + if (timeout < KWGBE_PHY_SMI_TIMEOUT) + timeout++; + else { + debug("%s time out...\n", __FUNCTION__); + return -1; + } + } while (readl(&p_rxdesc_curr->cmd_sts) & KWGBE_BUFFER_OWNED_BY_DMA); + + if (p_rxdesc_curr->byte_cnt != 0) { + debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n", + __FUNCTION__, (u32) p_rxdesc_curr->byte_cnt, + (u32) p_rxdesc_curr->buf_ptr, + (u32) p_rxdesc_curr->cmd_sts); + } + + /* + * In case received a packet without first/last bits on + * OR the error summary bit is on, + * the packets needs to be dropeed. + */ + cmd_sts = readl(&p_rxdesc_curr->cmd_sts); + + if ((cmd_sts & + (KWGBE_RX_FIRST_DESC | KWGBE_RX_LAST_DESC)) + != (KWGBE_RX_FIRST_DESC | KWGBE_RX_LAST_DESC)) { + + printf("Err..(%s) Dropping packet spread on" + " multiple descriptors\n", __FUNCTION__); + + } else if (cmd_sts & KWGBE_ERROR_SUMMARY) { + + printf("Err..(%s) Dropping packet with errors\n", + __FUNCTION__); + + } else { + /* !!! call higher layer processing */ + debug("%s: Sending Received packet to" + " upper layer (NetReceive)\n", __FUNCTION__); + + /* let the upper layer handle the packet */ + NetReceive((p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET), + (int)(p_rxdesc_curr->byte_cnt - RX_BUF_OFFSET)); + } + /* + * free these descriptors and point next in the ring + */ + p_rxdesc_curr->cmd_sts = + KWGBE_BUFFER_OWNED_BY_DMA | KWGBE_RX_EN_INTERRUPT; + p_rxdesc_curr->buf_size = PKTSIZE_ALIGN; + p_rxdesc_curr->byte_cnt = 0; + + writel((unsigned)p_rxdesc_curr->nxtdesc_p, (u32) &dkwgbe->p_rxdesc_curr); + + return 0; +} + +int kirkwood_egiga_initialize(bd_t * bis) +{ + struct kwgbe_device *dkwgbe; + struct eth_device *dev; + int devnum; + char *s; + u8 used_ports[MAX_KWGBE_DEVS] = CONFIG_KIRKWOOD_EGIGA_PORTS; + + for (devnum = 0; devnum < MAX_KWGBE_DEVS; devnum++) { + /*skip if port is configured not to use */ + if (used_ports[devnum] == 0) + continue; + + if (!(dkwgbe = malloc(sizeof(struct kwgbe_device)))) + goto error1; + + memset(dkwgbe, 0, sizeof(struct kwgbe_device)); + + if (!(dkwgbe->p_rxdesc = + (struct kwgbe_rxdesc *)memalign(PKTALIGN, + KW_RXQ_DESC_ALIGNED_SIZE + * RINGSZ + 1))) + goto error2; + + if (!(dkwgbe->p_rxbuf = (u8 *) memalign(PKTALIGN, RINGSZ + * PKTSIZE_ALIGN + 1))) + goto error3; + + if (!(dkwgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN))) + goto error4; + + if (!(dkwgbe->p_txdesc = (struct kwgbe_txdesc *) + memalign(PKTALIGN, sizeof(struct kwgbe_txdesc) + 1))) { + free(dkwgbe->p_aligned_txbuf); + error4: + free(dkwgbe->p_rxbuf); + error3: + free(dkwgbe->p_rxdesc); + error2: + free(dkwgbe); + error1: + printf("Err.. %s Failed to allocate memory\n", + __FUNCTION__); + return -1; + } + + dev = &dkwgbe->dev; + + /* must be less than NAMESIZE (16) */ + sprintf(dev->name, "egiga%d", devnum); + + /* Extract the MAC address from the environment */ + switch (devnum) { + case 0: + dkwgbe->regs = (void *)KW_EGIGA0_BASE; + s = "ethaddr"; + break; + case 1: + dkwgbe->regs = (void *)KW_EGIGA1_BASE; + s = "eth1addr"; + break; + default: /* this should never happen */ + printf("Err..(%s) Invalid device number %d\n", + __FUNCTION__, devnum); + return -1; + } + + while (!eth_getenv_enetaddr(s, dev->enetaddr)) { + /* Generate Private MAC addr if not set */ + dev->enetaddr[0] = 0x02; + dev->enetaddr[1] = 0x50; + dev->enetaddr[2] = 0x43; +#if defined (CONFIG_SKIP_LOCAL_MAC_RANDOMIZATION) + /* Generate fixed lower MAC half using devnum */ + dev->enetaddr[3] = 0; + dev->enetaddr[4] = 0; + dev->enetaddr[5] = devnum; +#else + /* Generate random lower MAC half */ + dev->enetaddr[3] = get_random_hex(); + dev->enetaddr[4] = get_random_hex(); + dev->enetaddr[5] = get_random_hex(); +#endif + eth_setenv_enetaddr(s, dev->enetaddr); + } + + dev->init = (void *)kwgbe_init; + dev->halt = (void *)kwgbe_halt; + dev->send = (void *)kwgbe_send; + dev->recv = (void *)kwgbe_recv; + dev->write_hwaddr = (void *)kwgbe_write_hwaddr; + + eth_register(dev); + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + miiphy_register(dev->name, smi_reg_read, smi_reg_write); + /* Set phy address of the port */ + miiphy_write(dev->name, KIRKWOOD_PHY_ADR_REQUEST, + KIRKWOOD_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum); +#endif + } + return 0; +} diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h new file mode 100644 index 0000000000..30c773ca5c --- /dev/null +++ b/drivers/net/mvgbe.h @@ -0,0 +1,505 @@ +/* + * (C) Copyright 2009 + * Marvell Semiconductor + * Written-by: Prafulla Wadaskar + * + * based on - Driver for MV64360X ethernet ports + * Copyright (C) 2002 rabeeh@galileo.co.il + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef __EGIGA_H__ +#define __EGIGA_H__ + +#define MAX_KWGBE_DEVS 2 /*controller has two ports */ + +/* PHY_BASE_ADR is board specific and can be configured */ +#if defined (CONFIG_PHY_BASE_ADR) +#define PHY_BASE_ADR CONFIG_PHY_BASE_ADR +#else +#define PHY_BASE_ADR 0x08 /* default phy base addr */ +#endif + +/* Constants */ +#define INT_CAUSE_UNMASK_ALL 0x0007ffff +#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff +#define MRU_MASK 0xfff1ffff +#define PHYADR_MASK 0x0000001f +#define PHYREG_MASK 0x0000001f +#define QTKNBKT_DEF_VAL 0x3fffffff +#define QMTBS_DEF_VAL 0x000003ff +#define QTKNRT_DEF_VAL 0x0000fcff +#define RXUQ 0 /* Used Rx queue */ +#define TXUQ 0 /* Used Rx queue */ + +#define to_dkwgbe(_kd) container_of(_kd, struct kwgbe_device, dev) +#define KWGBEREG_WR(adr, val) writel(val, &adr) +#define KWGBEREG_RD(adr) readl(&adr) +#define KWGBEREG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr) +#define KWGBEREG_BITS_SET(adr, val) writel(readl(&adr) | val, &adr) + +/* Default port configuration value */ +#define PRT_CFG_VAL ( \ + KWGBE_UCAST_MOD_NRML | \ + KWGBE_DFLT_RXQ(RXUQ) | \ + KWGBE_DFLT_RX_ARPQ(RXUQ) | \ + KWGBE_RX_BC_IF_NOT_IP_OR_ARP | \ + KWGBE_RX_BC_IF_IP | \ + KWGBE_RX_BC_IF_ARP | \ + KWGBE_CPTR_TCP_FRMS_DIS | \ + KWGBE_CPTR_UDP_FRMS_DIS | \ + KWGBE_DFLT_RX_TCPQ(RXUQ) | \ + KWGBE_DFLT_RX_UDPQ(RXUQ) | \ + KWGBE_DFLT_RX_BPDUQ(RXUQ)) + +/* Default port extend configuration value */ +#define PORT_CFG_EXTEND_VALUE \ + KWGBE_SPAN_BPDU_PACKETS_AS_NORMAL | \ + KWGBE_PARTITION_DIS | \ + KWGBE_TX_CRC_GENERATION_EN + +#define GT_KWGBE_IPG_INT_RX(value) ((value & 0x3fff) << 8) + +/* Default sdma control value */ +#define PORT_SDMA_CFG_VALUE ( \ + KWGBE_RX_BURST_SIZE_16_64BIT | \ + KWGBE_BLM_RX_NO_SWAP | \ + KWGBE_BLM_TX_NO_SWAP | \ + GT_KWGBE_IPG_INT_RX(RXUQ) | \ + KWGBE_TX_BURST_SIZE_16_64BIT) + +/* Default port serial control value */ +#define PORT_SERIAL_CONTROL_VALUE ( \ + KWGBE_FORCE_LINK_PASS | \ + KWGBE_DIS_AUTO_NEG_FOR_DUPLX | \ + KWGBE_DIS_AUTO_NEG_FOR_FLOW_CTRL | \ + KWGBE_ADV_NO_FLOW_CTRL | \ + KWGBE_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ + KWGBE_FORCE_BP_MODE_NO_JAM | \ + (1 << 9) /* Reserved bit has to be 1 */ | \ + KWGBE_DO_NOT_FORCE_LINK_FAIL | \ + KWGBE_EN_AUTO_NEG_SPEED_GMII | \ + KWGBE_DTE_ADV_0 | \ + KWGBE_MIIPHY_MAC_MODE | \ + KWGBE_AUTO_NEG_NO_CHANGE | \ + KWGBE_MAX_RX_PACKET_1552BYTE | \ + KWGBE_CLR_EXT_LOOPBACK | \ + KWGBE_SET_FULL_DUPLEX_MODE | \ + KWGBE_DIS_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX) + +/* Tx WRR confoguration macros */ +#define PORT_MAX_TRAN_UNIT 0x24 /* MTU register (default) 9KByte */ +#define PORT_MAX_TOKEN_BUCKET_SIZE 0x_FFFF /* PMTBS reg (default) */ +#define PORT_TOKEN_RATE 1023 /* PTTBRC reg (default) */ +/* MAC accepet/reject macros */ +#define ACCEPT_MAC_ADDR 0 +#define REJECT_MAC_ADDR 1 +/* Size of a Tx/Rx descriptor used in chain list data structure */ +#define KW_RXQ_DESC_ALIGNED_SIZE \ + (((sizeof(struct kwgbe_rxdesc) / PKTALIGN) + 1) * PKTALIGN) +/* Buffer offset from buffer pointer */ +#define RX_BUF_OFFSET 0x2 + +/* Port serial status reg (PSR) */ +#define KWGBE_INTERFACE_GMII_MII 0 +#define KWGBE_INTERFACE_PCM 1 +#define KWGBE_LINK_IS_DOWN 0 +#define KWGBE_LINK_IS_UP (1 << 1) +#define KWGBE_PORT_AT_HALF_DUPLEX 0 +#define KWGBE_PORT_AT_FULL_DUPLEX (1 << 2) +#define KWGBE_RX_FLOW_CTRL_DISD 0 +#define KWGBE_RX_FLOW_CTRL_ENBALED (1 << 3) +#define KWGBE_GMII_SPEED_100_10 0 +#define KWGBE_GMII_SPEED_1000 (1 << 4) +#define KWGBE_MII_SPEED_10 0 +#define KWGBE_MII_SPEED_100 (1 << 5) +#define KWGBE_NO_TX 0 +#define KWGBE_TX_IN_PROGRESS (1 << 7) +#define KWGBE_BYPASS_NO_ACTIVE 0 +#define KWGBE_BYPASS_ACTIVE (1 << 8) +#define KWGBE_PORT_NOT_AT_PARTN_STT 0 +#define KWGBE_PORT_AT_PARTN_STT (1 << 9) +#define KWGBE_PORT_TX_FIFO_NOT_EMPTY 0 +#define KWGBE_PORT_TX_FIFO_EMPTY (1 << 10) + +/* These macros describes the Port configuration reg (Px_cR) bits */ +#define KWGBE_UCAST_MOD_NRML 0 +#define KWGBE_UNICAST_PROMISCUOUS_MODE 1 +#define KWGBE_DFLT_RXQ(_x) (_x << 1) +#define KWGBE_DFLT_RX_ARPQ(_x) (_x << 4) +#define KWGBE_RX_BC_IF_NOT_IP_OR_ARP 0 +#define KWGBE_REJECT_BC_IF_NOT_IP_OR_ARP (1 << 7) +#define KWGBE_RX_BC_IF_IP 0 +#define KWGBE_REJECT_BC_IF_IP (1 << 8) +#define KWGBE_RX_BC_IF_ARP 0 +#define KWGBE_REJECT_BC_IF_ARP (1 << 9) +#define KWGBE_TX_AM_NO_UPDATE_ERR_SMRY (1 << 12) +#define KWGBE_CPTR_TCP_FRMS_DIS 0 +#define KWGBE_CPTR_TCP_FRMS_EN (1 << 14) +#define KWGBE_CPTR_UDP_FRMS_DIS 0 +#define KWGBE_CPTR_UDP_FRMS_EN (1 << 15) +#define KWGBE_DFLT_RX_TCPQ(_x) (_x << 16) +#define KWGBE_DFLT_RX_UDPQ(_x) (_x << 19) +#define KWGBE_DFLT_RX_BPDUQ(_x) (_x << 22) +#define KWGBE_DFLT_RX_TCP_CHKSUM_MODE (1 << 25) + +/* These macros describes the Port configuration extend reg (Px_cXR) bits*/ +#define KWGBE_CLASSIFY_EN 1 +#define KWGBE_SPAN_BPDU_PACKETS_AS_NORMAL 0 +#define KWGBE_SPAN_BPDU_PACKETS_TO_RX_Q7 (1 << 1) +#define KWGBE_PARTITION_DIS 0 +#define KWGBE_PARTITION_EN (1 << 2) +#define KWGBE_TX_CRC_GENERATION_EN 0 +#define KWGBE_TX_CRC_GENERATION_DIS (1 << 3) + +/* These macros describes the Port Sdma configuration reg (SDCR) bits */ +#define KWGBE_RIFB 1 +#define KWGBE_RX_BURST_SIZE_1_64BIT 0 +#define KWGBE_RX_BURST_SIZE_2_64BIT (1 << 1) +#define KWGBE_RX_BURST_SIZE_4_64BIT (1 << 2) +#define KWGBE_RX_BURST_SIZE_8_64BIT ((1 << 2) | (1 << 1)) +#define KWGBE_RX_BURST_SIZE_16_64BIT (1 << 3) +#define KWGBE_BLM_RX_NO_SWAP (1 << 4) +#define KWGBE_BLM_RX_BYTE_SWAP 0 +#define KWGBE_BLM_TX_NO_SWAP (1 << 5) +#define KWGBE_BLM_TX_BYTE_SWAP 0 +#define KWGBE_DESCRIPTORS_BYTE_SWAP (1 << 6) +#define KWGBE_DESCRIPTORS_NO_SWAP 0 +#define KWGBE_TX_BURST_SIZE_1_64BIT 0 +#define KWGBE_TX_BURST_SIZE_2_64BIT (1 << 22) +#define KWGBE_TX_BURST_SIZE_4_64BIT (1 << 23) +#define KWGBE_TX_BURST_SIZE_8_64BIT ((1 << 23) | (1 << 22)) +#define KWGBE_TX_BURST_SIZE_16_64BIT (1 << 24) + +/* These macros describes the Port serial control reg (PSCR) bits */ +#define KWGBE_SERIAL_PORT_DIS 0 +#define KWGBE_SERIAL_PORT_EN 1 +#define KWGBE_FORCE_LINK_PASS (1 << 1) +#define KWGBE_DO_NOT_FORCE_LINK_PASS 0 +#define KWGBE_EN_AUTO_NEG_FOR_DUPLX 0 +#define KWGBE_DIS_AUTO_NEG_FOR_DUPLX (1 << 2) +#define KWGBE_EN_AUTO_NEG_FOR_FLOW_CTRL 0 +#define KWGBE_DIS_AUTO_NEG_FOR_FLOW_CTRL (1 << 3) +#define KWGBE_ADV_NO_FLOW_CTRL 0 +#define KWGBE_ADV_SYMMETRIC_FLOW_CTRL (1 << 4) +#define KWGBE_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0 +#define KWGBE_FORCE_FC_MODE_TX_PAUSE_DIS (1 << 5) +#define KWGBE_FORCE_BP_MODE_NO_JAM 0 +#define KWGBE_FORCE_BP_MODE_JAM_TX (1 << 7) +#define KWGBE_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1 << 8) +#define KWGBE_FORCE_LINK_FAIL 0 +#define KWGBE_DO_NOT_FORCE_LINK_FAIL (1 << 10) +#define KWGBE_DIS_AUTO_NEG_SPEED_GMII (1 << 13) +#define KWGBE_EN_AUTO_NEG_SPEED_GMII 0 +#define KWGBE_DTE_ADV_0 0 +#define KWGBE_DTE_ADV_1 (1 << 14) +#define KWGBE_MIIPHY_MAC_MODE 0 +#define KWGBE_MIIPHY_PHY_MODE (1 << 15) +#define KWGBE_AUTO_NEG_NO_CHANGE 0 +#define KWGBE_RESTART_AUTO_NEG (1 << 16) +#define KWGBE_MAX_RX_PACKET_1518BYTE 0 +#define KWGBE_MAX_RX_PACKET_1522BYTE (1 << 17) +#define KWGBE_MAX_RX_PACKET_1552BYTE (1 << 18) +#define KWGBE_MAX_RX_PACKET_9022BYTE ((1 << 18) | (1 << 17)) +#define KWGBE_MAX_RX_PACKET_9192BYTE (1 << 19) +#define KWGBE_MAX_RX_PACKET_9700BYTE ((1 << 19) | (1 << 17)) +#define KWGBE_SET_EXT_LOOPBACK (1 << 20) +#define KWGBE_CLR_EXT_LOOPBACK 0 +#define KWGBE_SET_FULL_DUPLEX_MODE (1 << 21) +#define KWGBE_SET_HALF_DUPLEX_MODE 0 +#define KWGBE_EN_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1 << 22) +#define KWGBE_DIS_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0 +#define KWGBE_SET_GMII_SPEED_TO_10_100 0 +#define KWGBE_SET_GMII_SPEED_TO_1000 (1 << 23) +#define KWGBE_SET_MII_SPEED_TO_10 0 +#define KWGBE_SET_MII_SPEED_TO_100 (1 << 24) + +/* SMI register fields */ +#define KWGBE_PHY_SMI_TIMEOUT 10000 +#define KWGBE_PHY_SMI_DATA_OFFS 0 /* Data */ +#define KWGBE_PHY_SMI_DATA_MASK (0xffff << KWGBE_PHY_SMI_DATA_OFFS) +#define KWGBE_PHY_SMI_DEV_ADDR_OFFS 16 /* PHY device address */ +#define KWGBE_PHY_SMI_DEV_ADDR_MASK (PHYADR_MASK << KWGBE_PHY_SMI_DEV_ADDR_OFFS) +#define KWGBE_SMI_REG_ADDR_OFFS 21 /* PHY device reg addr */ +#define KWGBE_SMI_REG_ADDR_MASK (PHYADR_MASK << KWGBE_SMI_REG_ADDR_OFFS) +#define KWGBE_PHY_SMI_OPCODE_OFFS 26 /* Write/Read opcode */ +#define KWGBE_PHY_SMI_OPCODE_MASK (3 << KWGBE_PHY_SMI_OPCODE_OFFS) +#define KWGBE_PHY_SMI_OPCODE_WRITE (0 << KWGBE_PHY_SMI_OPCODE_OFFS) +#define KWGBE_PHY_SMI_OPCODE_READ (1 << KWGBE_PHY_SMI_OPCODE_OFFS) +#define KWGBE_PHY_SMI_READ_VALID_MASK (1 << 27) /* Read Valid */ +#define KWGBE_PHY_SMI_BUSY_MASK (1 << 28) /* Busy */ + +/* SDMA command status fields macros */ +/* Tx & Rx descriptors status */ +#define KWGBE_ERROR_SUMMARY 1 +/* Tx & Rx descriptors command */ +#define KWGBE_BUFFER_OWNED_BY_DMA (1 << 31) +/* Tx descriptors status */ +#define KWGBE_LC_ERROR 0 +#define KWGBE_UR_ERROR (1 << 1) +#define KWGBE_RL_ERROR (1 << 2) +#define KWGBE_LLC_SNAP_FORMAT (1 << 9) +#define KWGBE_TX_LAST_FRAME (1 << 20) + +/* Rx descriptors status */ +#define KWGBE_CRC_ERROR 0 +#define KWGBE_OVERRUN_ERROR (1 << 1) +#define KWGBE_MAX_FRAME_LENGTH_ERROR (1 << 2) +#define KWGBE_RESOURCE_ERROR ((1 << 2) | (1 << 1)) +#define KWGBE_VLAN_TAGGED (1 << 19) +#define KWGBE_BPDU_FRAME (1 << 20) +#define KWGBE_TCP_FRAME_OVER_IP_V_4 0 +#define KWGBE_UDP_FRAME_OVER_IP_V_4 (1 << 21) +#define KWGBE_OTHER_FRAME_TYPE (1 << 22) +#define KWGBE_LAYER_2_IS_KWGBE_V_2 (1 << 23) +#define KWGBE_FRAME_TYPE_IP_V_4 (1 << 24) +#define KWGBE_FRAME_HEADER_OK (1 << 25) +#define KWGBE_RX_LAST_DESC (1 << 26) +#define KWGBE_RX_FIRST_DESC (1 << 27) +#define KWGBE_UNKNOWN_DESTINATION_ADDR (1 << 28) +#define KWGBE_RX_EN_INTERRUPT (1 << 29) +#define KWGBE_LAYER_4_CHECKSUM_OK (1 << 30) + +/* Rx descriptors byte count */ +#define KWGBE_FRAME_FRAGMENTED (1 << 2) + +/* Tx descriptors command */ +#define KWGBE_LAYER_4_CHECKSUM_FIRST_DESC (1 << 10) +#define KWGBE_FRAME_SET_TO_VLAN (1 << 15) +#define KWGBE_TCP_FRAME 0 +#define KWGBE_UDP_FRAME (1 << 16) +#define KWGBE_GEN_TCP_UDP_CHECKSUM (1 << 17) +#define KWGBE_GEN_IP_V_4_CHECKSUM (1 << 18) +#define KWGBE_ZERO_PADDING (1 << 19) +#define KWGBE_TX_LAST_DESC (1 << 20) +#define KWGBE_TX_FIRST_DESC (1 << 21) +#define KWGBE_GEN_CRC (1 << 22) +#define KWGBE_TX_EN_INTERRUPT (1 << 23) +#define KWGBE_AUTO_MODE (1 << 30) + +/* Address decode parameters */ +/* Ethernet Base Address Register bits */ +#define EBAR_TARGET_DRAM 0x00000000 +#define EBAR_TARGET_DEVICE 0x00000001 +#define EBAR_TARGET_CBS 0x00000002 +#define EBAR_TARGET_PCI0 0x00000003 +#define EBAR_TARGET_PCI1 0x00000004 +#define EBAR_TARGET_CUNIT 0x00000005 +#define EBAR_TARGET_AUNIT 0x00000006 +#define EBAR_TARGET_GUNIT 0x00000007 + +/* Window attrib */ +#define EBAR_DRAM_CS0 0x00000E00 +#define EBAR_DRAM_CS1 0x00000D00 +#define EBAR_DRAM_CS2 0x00000B00 +#define EBAR_DRAM_CS3 0x00000700 + +/* DRAM Target interface */ +#define EBAR_DRAM_NO_CACHE_COHERENCY 0x00000000 +#define EBAR_DRAM_CACHE_COHERENCY_WT 0x00001000 +#define EBAR_DRAM_CACHE_COHERENCY_WB 0x00002000 + +/* Device Bus Target interface */ +#define EBAR_DEVICE_DEVCS0 0x00001E00 +#define EBAR_DEVICE_DEVCS1 0x00001D00 +#define EBAR_DEVICE_DEVCS2 0x00001B00 +#define EBAR_DEVICE_DEVCS3 0x00001700 +#define EBAR_DEVICE_BOOTCS3 0x00000F00 + +/* PCI Target interface */ +#define EBAR_PCI_BYTE_SWAP 0x00000000 +#define EBAR_PCI_NO_SWAP 0x00000100 +#define EBAR_PCI_BYTE_WORD_SWAP 0x00000200 +#define EBAR_PCI_WORD_SWAP 0x00000300 +#define EBAR_PCI_NO_SNOOP_NOT_ASSERT 0x00000000 +#define EBAR_PCI_NO_SNOOP_ASSERT 0x00000400 +#define EBAR_PCI_IO_SPACE 0x00000000 +#define EBAR_PCI_MEMORY_SPACE 0x00000800 +#define EBAR_PCI_REQ64_FORCE 0x00000000 +#define EBAR_PCI_REQ64_SIZE 0x00001000 + +/* Window access control */ +#define EWIN_ACCESS_NOT_ALLOWED 0 +#define EWIN_ACCESS_READ_ONLY 1 +#define EWIN_ACCESS_FULL ((1 << 1) | 1) + +/* structures represents Controller registers */ +struct kwgbe_barsz { + u32 bar; + u32 size; +}; + +struct kwgbe_rxcdp { + struct kwgbe_rxdesc *rxcdp; + u32 rxcdp_pad[3]; +}; + +struct kwgbe_tqx { + u32 qxttbc; + u32 tqxtbc; + u32 tqxac; + u32 tqxpad; +}; + +struct kwgbe_registers { + u32 phyadr; + u32 smi; + u32 euda; + u32 eudid; + u8 pad1[0x080 - 0x00c - 4]; + u32 euic; + u32 euim; + u8 pad2[0x094 - 0x084 - 4]; + u32 euea; + u32 euiae; + u8 pad3[0x0b0 - 0x098 - 4]; + u32 euc; + u8 pad3a[0x200 - 0x0b0 - 4]; + struct kwgbe_barsz barsz[6]; + u8 pad4[0x280 - 0x22c - 4]; + u32 ha_remap[4]; + u32 bare; + u32 epap; + u8 pad5[0x400 - 0x294 - 4]; + u32 pxc; + u32 pxcx; + u32 mii_ser_params; + u8 pad6[0x410 - 0x408 - 4]; + u32 evlane; + u32 macal; + u32 macah; + u32 sdc; + u32 dscp[7]; + u32 psc0; + u32 vpt2p; + u32 ps0; + u32 tqc; + u32 psc1; + u32 ps1; + u32 mrvl_header; + u8 pad7[0x460 - 0x454 - 4]; + u32 ic; + u32 ice; + u32 pim; + u32 peim; + u8 pad8[0x474 - 0x46c - 4]; + u32 pxtfut; + u32 pad9; + u32 pxmfs; + u32 pad10; + u32 pxdfc; + u32 pxofc; + u8 pad11[0x494 - 0x488 - 4]; + u32 peuiae; + u8 pad12[0x4bc - 0x494 - 4]; + u32 eth_type_prio; + u8 pad13[0x4dc - 0x4bc - 4]; + u32 tqfpc; + u32 pttbrc; + u32 tqc1; + u32 pmtu; + u32 pmtbs; + u8 pad14[0x60c - 0x4ec - 4]; + struct kwgbe_rxcdp rxcdp[7]; + struct kwgbe_rxdesc *rxcdp7; + u32 rqc; + struct kwgbe_txdesc *tcsdp; + u8 pad15[0x6c0 - 0x684 - 4]; + struct kwgbe_txdesc *tcqdp[8]; + u8 pad16[0x700 - 0x6dc - 4]; + struct kwgbe_tqx tqx[8]; + u32 pttbc; + u8 pad17[0x7a8 - 0x780 - 4]; + u32 tqxipg0; + u32 pad18[3]; + u32 tqxipg1; + u8 pad19[0x7c0 - 0x7b8 - 4]; + u32 hitkninlopkt; + u32 hitkninasyncpkt; + u32 lotkninasyncpkt; + u32 pad20; + u32 ts; + u8 pad21[0x3000 - 0x27d0 - 4]; + u32 pad20_1[32]; /* mib counter registes */ + u8 pad22[0x3400 - 0x3000 - sizeof(u32) * 32]; + u32 dfsmt[64]; + u32 dfomt[64]; + u32 dfut[4]; + u8 pad23[0xe20c0 - 0x7360c - 4]; + u32 pmbus_top_arbiter; +}; + +/* structures/enums needed by driver */ +enum kwgbe_adrwin { + KWGBE_WIN0, + KWGBE_WIN1, + KWGBE_WIN2, + KWGBE_WIN3, + KWGBE_WIN4, + KWGBE_WIN5 +}; + +enum kwgbe_target { + KWGBE_TARGET_DRAM, + KWGBE_TARGET_DEV, + KWGBE_TARGET_CBS, + KWGBE_TARGET_PCI0, + KWGBE_TARGET_PCI1 +}; + +struct kwgbe_winparam { + enum kwgbe_adrwin win; /* Window number */ + enum kwgbe_target target; /* System targets */ + u16 attrib; /* BAR attrib. See above macros */ + u32 base_addr; /* Window base address in u32 form */ + u32 high_addr; /* Window high address in u32 form */ + u32 size; /* Size in MBytes. Must be % 64Kbyte. */ + int enable; /* Enable/disable access to the window. */ + u16 access_ctrl; /*Access ctrl register. see above macros */ +}; + +struct kwgbe_rxdesc { + u32 cmd_sts; /* Descriptor command status */ + u16 buf_size; /* Buffer size */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u8 *buf_ptr; /* Descriptor buffer pointer */ + struct kwgbe_rxdesc *nxtdesc_p; /* Next descriptor pointer */ +}; + +struct kwgbe_txdesc { + u32 cmd_sts; /* Descriptor command status */ + u16 l4i_chk; /* CPU provided TCP Checksum */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u8 *buf_ptr; /* Descriptor buffer ptr */ + struct kwgbe_txdesc *nxtdesc_p; /* Next descriptor ptr */ +}; + +/* port device data struct */ +struct kwgbe_device { + struct eth_device dev; + struct kwgbe_registers *regs; + struct kwgbe_txdesc *p_txdesc; + struct kwgbe_rxdesc *p_rxdesc; + struct kwgbe_rxdesc *p_rxdesc_curr; + u8 *p_rxbuf; + u8 *p_aligned_txbuf; +}; + +#endif /* __EGIGA_H__ */ -- cgit