On Wednesday, August 24, 2011 03:07:18 PM Ajay Bhargav wrote: > This patch adds support for Fast Ethernet Controller driver for > Armada100 series. > > Signed-off-by: Ajay Bhargav <ajay.bhar...@einfochips.com> > ---
[...] > diff --git a/drivers/net/armada100_fec.c b/drivers/net/armada100_fec.c > new file mode 100644 > index 0000000..e36dca6 > --- /dev/null > +++ b/drivers/net/armada100_fec.c > @@ -0,0 +1,761 @@ > +/* > + * (C) Copyright 2011 > + * eInfochips Ltd. <www.einfochips.com> > + * Written-by: Ajay Bhargav <ajay.bhar...@einfochips.com> > + * > + * (C) Copyright 2010 > + * Marvell Semiconductor <www.marvell.com> > + * Contributor: Mahavir Jain <mj...@marvell.com> > + * > + * 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 <common.h> > +#include <net.h> > +#include <malloc.h> > +#include <miiphy.h> > +#include <netdev.h> > +#include <asm/types.h> > +#include <asm/byteorder.h> > +#include <linux/err.h> > +#include <linux/mii.h> > +#include <asm/io.h> > +#include <asm/arch/armada100.h> > +#include "armada100_fec.h" > + > +#define PHY_ADR_REQ 0xFF /* Magic number to read/write PHY > address */ > + > +#ifdef DEBUG > +static int eth_dump_regs(struct eth_device *dev) > +{ > + struct armdfec_device *darmdfec = to_darmdfec(dev); > + struct armdfec_reg *regs = darmdfec->regs; > + unsigned int i = 0; > + > + printf("\noffset: phy_adr, value: 0x%x\n", readl(®s->phyadr)); > + printf("offset: smi, value: 0x%x\n", readl(®s->smi)); > + for (i = 0x400; i <= 0x4e4; i += 4) > + printf("offset: 0x%x, value: 0x%x\n", > + i, readl(ARMD1_FEC_BASE + i)); > + return 0; > +} > +#endif > + > +static int armdfec_phy_timeout(u32 reg, u32 flag, int cond) > +{ > + u32 timeout = PHY_WAIT_ITERATIONS; > + while (--timeout) { > + if (cond && (readl(reg) & flag)) > + break; > + else if (!cond && !(readl(reg) & flag)) You can read the register into some temporary variable so you don't need the readl() at two places. > + break; > + udelay(PHY_WAIT_MICRO_SECONDS); > + } > + return !timeout; > +} > + > +static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg, > + u16 *value) > +{ > + struct eth_device *dev = eth_get_dev_by_name(devname); > + struct armdfec_device *darmdfec = to_darmdfec(dev); > + struct armdfec_reg *regs = darmdfec->regs; > + u32 val, reg_data; > + > + if (phy_addr == PHY_ADR_REQ && phy_reg == PHY_ADR_REQ) { > + reg_data = readl(®s->phyadr); > + *value = (u16) (reg_data & 0x1f); > + return 0; > + } > + > + /* check parameters */ > + if (phy_addr > PHY_MASK) { > + printf("Err..(%s) Invalid phy address: 0x%X\n", > + __func__, phy_addr); > + return -EINVAL; > + } > + if (phy_reg > PHY_MASK) { > + printf("Err..(%s) Invalid register offset: 0x%X\n", > + __func__, phy_reg); > + return -EINVAL; > + } > + > + /* wait for the SMI register to become available */ > + if (armdfec_phy_timeout((u32)®s->smi, SMI_BUSY, FALSE)) { Adjust the function so you don't need the cast. > + printf("Error (%s) PHY busy timeout\n", __func__); > + return -1; > + } > + > + writel(phy_addr << 16 | phy_reg << 21 | SMI_OP_R, ®s->smi); Parentheses missing maybe ? > + > + /* now wait for the data to be valid */ > + if (armdfec_phy_timeout((u32)®s->smi, SMI_R_VALID, TRUE)) { > + val = readl(®s->smi); > + printf("Err (%s) PHY Read timeout, val=0x%x\n", __func__, val); > + return -1; > + } > + val = readl(®s->smi); > + *value = val & 0xffff; > + > + return 0; > +} > + > +static int smi_reg_write(const char *devname, > + u8 phy_addr, u8 phy_reg, u16 value) > +{ > + struct eth_device *dev = eth_get_dev_by_name(devname); > + struct armdfec_device *darmdfec = to_darmdfec(dev); > + struct armdfec_reg *regs = darmdfec->regs; > + > + if (phy_addr == PHY_ADR_REQ && phy_reg == PHY_ADR_REQ) { > + clrsetbits_le32(®s->phyadr, 0x1f, value & 0x1f); > + return 0; > + } > + > + /* check parameters */ > + if (phy_addr > PHY_MASK) { > + printf("Err..(%s) Invalid phy address\n", __func__); > + return -EINVAL; > + } > + if (phy_reg > PHY_MASK) { > + printf("Err..(%s) Invalid register offset\n", __func__); > + return -EINVAL; > + } > + > + /* wait for the SMI register to become available */ > + if (armdfec_phy_timeout((u32)®s->smi, SMI_BUSY, FALSE)) { > + printf("Error (%s) PHY busy timeout\n", __func__); > + return -1; > + } > + > + writel(phy_addr << 16 | phy_reg << 21 | SMI_OP_W | (value & 0xffff), > + ®s->smi); > + return 0; > +} > + > +/* > + * Abort any transmit and receive operations and put DMA > + * in idle state. AT and AR bits are cleared upon entering > + * in IDLE state. So poll those bits to verify operation. > + */ > +static void abortdma(struct eth_device *dev) > +{ > + struct armdfec_device *darmdfec = to_darmdfec(dev); > + struct armdfec_reg *regs = darmdfec->regs; > + int delay; > + int maxretries = 40; > + > + do { > + writel(SDMA_CMD_AR | SDMA_CMD_AT, ®s->sdma_cmd); > + udelay(100); > + > + delay = 10; > + while ((readl(®s->sdma_cmd) & > + (SDMA_CMD_AR | SDMA_CMD_AT)) > + && delay-- > 0) { > + udelay(10); > + } > + } while (maxretries-- > 0 && delay <= 0); Didn't I comment on this one in V1? > + > + if (maxretries <= 0) > + printf("%s : DMA Stuck\n", __func__); > +} [...] > +int armada100_fec_register() > +{ > + struct armdfec_device *darmdfec; > + struct eth_device *dev; > + int phy_adr; > + > + darmdfec = malloc(sizeof(struct armdfec_device)); > + if (!darmdfec) > + goto error; > + > + memset(darmdfec, 0, sizeof(struct armdfec_device)); > + > + darmdfec->htpr = memalign(8, HASH_ADDR_TABLE_SIZE); > + if (!darmdfec->htpr) > + goto error; > + > + darmdfec->p_rxdesc = (struct rx_desc *) memalign(PKTALIGN, > + ARMDFEC_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1); > + > + if (!darmdfec->p_rxdesc) > + goto error; > + > + darmdfec->p_rxbuf = (u8 *) memalign(PKTALIGN, > + RINGSZ * PKTSIZE_ALIGN + 1); Is the cast needed ? You should review your casts, most of them can be solved by using proper type! > + if (!darmdfec->p_rxbuf) > + goto error; > + > + darmdfec->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN); > + if (!darmdfec->p_aligned_txbuf) > + goto error; > + > + darmdfec->p_txdesc = (struct tx_desc *) > + memalign(PKTALIGN, sizeof(struct tx_desc) + 1); > + if (!darmdfec->p_txdesc) > + goto error; > + > + dev = &darmdfec->dev; > + /* Assign ARMADA100 Fast Ethernet Controller Base Address */ > + darmdfec->regs = (void *) ARMD1_FEC_BASE; Cheers! _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot