[U-Boot] [PATCH v2 1/3] net: Adds Fast Ethernet Controller driver for Armada100

Ajay Bhargav ajay.bhargav at einfochips.com
Thu Aug 25 07:21:25 CEST 2011


----- "Marek Vasut" <marek.vasut at gmail.com> wrote:

> 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.bhargav at einfochips.com>
> > ---
> 
> [...]
> 
[...]
> > +
> > +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.
> 

readl will be called only once... do i really need a temp var?

> > +			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.
> 
okay...

> > +		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 ?
> 

:) okay..

> > +
> > +	/* 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?
> 

Yes you did... 

> > +
> > +	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!
> 
Thats a serious issue with me I guess :)

> > +	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!
> 
Thanks,
Ajay Bhargav


More information about the U-Boot mailing list