[U-Boot] [PATCH v3 1/3] net: Adds Fast Ethernet Controller driver for Armada100
Marek Vasut
marek.vasut at gmail.com
Fri Aug 26 17:32:58 CEST 2011
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 at 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(®s->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(®s->smi, SMI_BUSY, FALSE)) {
> + printf("Error (%s) PHY busy timeout\n", __func__);
> + return -1;
> + }
> +
> + writel((phy_addr << 16) | (phy_reg << 21) | SMI_OP_R, ®s->smi);
> +
> + /* now wait for the data to be valid */
> + if (armdfec_phy_timeout(®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(®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;
> + 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, ®s->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(®s->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!
More information about the U-Boot
mailing list