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(&regs->phyadr));
> +     printf("offset: smi, value: 0x%x\n", readl(&regs->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(&regs->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)&regs->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, &regs->smi);

Parentheses missing maybe ?

> +
> +     /* now wait for the data to be valid */
> +     if (armdfec_phy_timeout((u32)&regs->smi, SMI_R_VALID, TRUE)) {
> +             val = readl(&regs->smi);
> +             printf("Err (%s) PHY Read timeout, val=0x%x\n", __func__, val);
> +             return -1;
> +     }
> +     val = readl(&regs->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(&regs->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)&regs->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),
> +                     &regs->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, &regs->sdma_cmd);
> +             udelay(100);
> +
> +             delay = 10;
> +             while ((readl(&regs->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

Reply via email to