All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marek.vasut@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 1/3] net: Adds Fast Ethernet Controller driver for Armada100
Date: Fri, 26 Aug 2011 17:32:58 +0200	[thread overview]
Message-ID: <201108261732.59097.marek.vasut@gmail.com> (raw)
In-Reply-To: <1314340613-14098-1-git-send-email-ajay.bhargav@einfochips.com>

On Friday, August 26, 2011 08:36:51 AM Ajay Bhargav wrote:
> This patch adds support for Fast Ethernet Controller driver for
> Armada100 series.
> 
> Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>

Hi, please don't forget to CC me next time ;-)

[...]

> +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);

Do you need this cast?

> +		return 0;
> +	}
> +
> +	/* check parameters */
> +	if (phy_addr > PHY_MASK) {
> +		printf("Err..(%s) Invalid phy address: 0x%X\n",
> +				__func__, phy_addr);

Maybe a firm "A100 FEC: Invalid phy address (address = 0x%x)\n" would be better, 
fix that "Err.." and "Err  " globally please.

> +		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(&regs->smi, SMI_BUSY, FALSE)) {
> +		printf("Error (%s) PHY busy timeout\n",	__func__);
> +		return -1;
> +	}
> +
> +	writel((phy_addr << 16) | (phy_reg << 21) | SMI_OP_R, &regs->smi);
> +
> +	/* now wait for the data to be valid */
> +	if (armdfec_phy_timeout(&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(&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;
> +	u32 tmp;
> +

while (--maxretries) {

That way it won't get negative and you can check below for if (!maxretries)

> +	while (maxretries--) {
> +		writel(SDMA_CMD_AR | SDMA_CMD_AT, &regs->sdma_cmd);
> +		udelay(100);
> +
> +		delay = 10;
> +		while (delay--) {

This will go negative and the check below will be true for -1.Fix this to
while (--delay) {

> +			tmp = readl(&regs->sdma_cmd);
> +			if (!(tmp & (SDMA_CMD_AR | SDMA_CMD_AT)))
> +				break;
> +			udelay(10);
> +		}
> +		if (delay)
> +			break;
> +	}
> +
> +	if (maxretries <= 0)
> +		printf("%s : DMA Stuck\n", __func__);
> +}

See two comments above.

> +
> +static inline u32 nibble_swapping_32_bit(u32 x)
> +{
> +	return (((x) & 0xf0f0f0f0) >> 4) | (((x) & 0x0f0f0f0f) << 4);
> +}
> +
> +static inline u32 nibble_swapping_16_bit(u32 x)
> +{
> +	return (((x) & 0x0000f0f0) >> 4) | (((x) & 0x00000f0f) << 4);
> +}
> +
> +static inline u32 flip_4_bits(u32 x)
> +{
> +	return (((x) & 0x01) << 3) | (((x) & 0x002) << 1)
> +		| (((x) & 0x04) >> 1) | (((x) & 0x008) >> 3);
> +}
> +
> +/*
> + * This function will calculate the hash function of the address.
> + * depends on the hash mode and hash size.
> + * Inputs
> + * mach             - the 2 most significant bytes of the MAC address.
> + * macl             - the 4 least significant bytes of the MAC address.
> + * Outputs
> + * return the calculated entry.
> + */
> +static u32 hash_function(u32 mach, u32 macl)
> +{
> +	u32 hashresult;
> +	u32 addrh;
> +	u32 addrl;
> +	u32 addr0;
> +	u32 addr1;
> +	u32 addr2;
> +	u32 addr3;
> +	u32 addrhswapped;
> +	u32 addrlswapped;
> +
> +	addrh = nibble_swapping_16_bit(mach);
> +	addrl = nibble_swapping_32_bit(macl);
> +
> +	addrhswapped = flip_4_bits(addrh & 0xf)
> +		+ ((flip_4_bits((addrh >> 4) & 0xf)) << 4)
> +		+ ((flip_4_bits((addrh >> 8) & 0xf)) << 8)
> +		+ ((flip_4_bits((addrh >> 12) & 0xf)) << 12);
> +
> +	addrlswapped = flip_4_bits(addrl & 0xf)
> +		+ ((flip_4_bits((addrl >> 4) & 0xf)) << 4)
> +		+ ((flip_4_bits((addrl >> 8) & 0xf)) << 8)
> +		+ ((flip_4_bits((addrl >> 12) & 0xf)) << 12)
> +		+ ((flip_4_bits((addrl >> 16) & 0xf)) << 16)
> +		+ ((flip_4_bits((addrl >> 20) & 0xf)) << 20)
> +		+ ((flip_4_bits((addrl >> 24) & 0xf)) << 24)
> +		+ ((flip_4_bits((addrl >> 28) & 0xf)) << 28);
> +
> +	addrh = addrhswapped;
> +	addrl = addrlswapped;
> +
> +	addr0 = (addrl >> 2) & 0x03f;
> +	addr1 = (addrl & 0x003) | (((addrl >> 8) & 0x7f) << 2);
> +	addr2 = (addrl >> 15) & 0x1ff;
> +	addr3 = ((addrl >> 24) & 0x0ff) | ((addrh & 1) << 8);
> +
> +	hashresult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3);
> +	hashresult = hashresult & 0x07ff;
> +	return hashresult;
> +}
> +
> +/*
> + * This function will add an entry to the address table.
> + * depends on the hash mode and hash size that was initialized.
> + * Inputs
> + * mach - the 2 most significant bytes of the MAC address.
> + * macl - the 4 least significant bytes of the MAC address.
> + * skip - if 1, skip this address.
> + * rd   - the RD field in the address table.
> + * Outputs
> + * address table entry is added.
> + * 0 if success.
> + * -ENOSPC if table full
> + */
> +static int add_del_hash_entry(struct armdfec_device *darmdfec, u32 mach,
> +			      u32 macl, u32 rd, u32 skip, int del)
> +{
> +	struct addr_table_entry_t *entry, *start;
> +	u32 newhi;
> +	u32 newlo;
> +	u32 i;
> +	u8 *last;
> +
> +	newlo = (((mach >> 4) & 0xf) << 15)
> +		| (((mach >> 0) & 0xf) << 11)
> +		| (((mach >> 12) & 0xf) << 7)
> +		| (((mach >> 8) & 0xf) << 3)
> +		| (((macl >> 20) & 0x1) << 31)
> +		| (((macl >> 16) & 0xf) << 27)
> +		| (((macl >> 28) & 0xf) << 23)
> +		| (((macl >> 24) & 0xf) << 19)
> +		| (skip << HTESKIP) | (rd << HTERDBIT)
> +		| HTEVALID;
> +
> +	newhi = (((macl >> 4) & 0xf) << 15)
> +		| (((macl >> 0) & 0xf) << 11)
> +		| (((macl >> 12) & 0xf) << 7)
> +		| (((macl >> 8) & 0xf) << 3)
> +		| (((macl >> 21) & 0x7) << 0);
> +
> +	/*
> +	 * Pick the appropriate table, start scanning for free/reusable
> +	 * entries at the index obtained by hashing the specified MAC address
> +	 */
> +	start = (struct addr_table_entry_t *) (darmdfec->htpr);
> +	entry = start + hash_function(mach, macl);
> +	for (i = 0; i < HOP_NUMBER; i++) {
> +		if (!(entry->lo & HTEVALID)) {
> +			break;
> +		} else {
> +			/* if same address put in same position */
> +			if (((entry->lo & 0xfffffff8) == (newlo & 0xfffffff8))
> +					&& (entry->hi == newhi))
> +				break;
> +		}
> +		if (entry == start + 0x7ff)
> +			entry = start;
> +		else
> +			entry++;
> +	}
> +
> +	if (((entry->lo & 0xfffffff8) != (newlo & 0xfffffff8)) &&
> +		(entry->hi != newhi) && del)
> +		return 0;
> +
> +	if (i == HOP_NUMBER) {
> +		if (!del) {
> +			printf("%s: table section is full\n", __FILE__);

Unify the error reporting please.

It looks good, just a few nits

Cheers!

  reply	other threads:[~2011-08-26 15:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-26  6:36 [U-Boot] [PATCH v3 1/3] net: Adds Fast Ethernet Controller driver for Armada100 Ajay Bhargav
2011-08-26 15:32 ` Marek Vasut [this message]
2011-08-26 20:01 ` Mike Frysinger
     [not found] <706935361.14309.1314594441316.JavaMail.root@ahm.einfochips.com>
2011-08-29  5:10 ` Ajay Bhargav
2011-08-29  5:30   ` Mike Frysinger
2011-08-29  5:39     ` Ajay Bhargav
2011-08-29 10:12       ` Marek Vasut
2011-08-29 19:39       ` Mike Frysinger
2011-08-30  5:15         ` Ajay Bhargav
     [not found] <274121072.14489.1314595589918.JavaMail.root@ahm.einfochips.com>
2011-08-29  5:26 ` Ajay Bhargav

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201108261732.59097.marek.vasut@gmail.com \
    --to=marek.vasut@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.