[PATCH net-next v3 2/2] net: ethernet: socionext: add AVE ethernet driver
Masahiro Yamada
yamada.masahiro at socionext.com
Tue Oct 24 19:52:45 PDT 2017
2017-10-25 10:07 GMT+09:00 Kunihiko Hayashi <hayashi.kunihiko at socionext.com>:
> +
> +/* Descriptor Control Register Group */
> +#define AVE_DESCC 0x300 /* Descriptor Control */
> +#define AVE_TXDC 0x304 /* TX Descriptor Configuration */
> +#define AVE_RXDC0 0x308 /* RX Descriptor Ring0 Configuration */
> +#define AVE_IIRQC 0x34c /* Interval IRQ Control */
> +
> +/* Packet Filter Register Group */
> +#define AVE_PKTF_BASE 0x800 /* PF Base Address */
> +#define AVE_PFMBYTE_BASE 0xd00 /* PF Mask Byte Base Address */
> +#define AVE_PFMBIT_BASE 0xe00 /* PF Mask Bit Base Address */
> +#define AVE_PFSEL_BASE 0xf00 /* PF Selector Base Address */
> +#define AVE_PFEN 0xffc /* Packet Filter Enable */
> +#define AVE_PKTF(ent) (AVE_PKTF_BASE + (ent) * 0x40)
> +#define AVE_PFMBYTE(ent) (AVE_PFMBYTE_BASE + (ent) * 8)
> +#define AVE_PFMBIT(ent) (AVE_PFMBIT_BASE + (ent) * 4)
> +#define AVE_PFSEL(ent) (AVE_PFSEL_BASE + (ent) * 4)
> +
> +/* 64bit descriptor memory */
> +#define AVE_DESC_SIZE_64 12 /* Descriptor Size */
> +
> +#define AVE_TXDM_64 0x1000 /* Tx Descriptor Memory */
> +#define AVE_RXDM_64 0x1c00 /* Rx Descriptor Memory */
> +
> +#define AVE_TXDM_SIZE_64 0x0ba0 /* Tx Descriptor Memory Size 3KB */
> +#define AVE_RXDM_SIZE_64 0x6000 /* Rx Descriptor Memory Size 24KB */
> +
> +/* 32bit descriptor memory */
> +#define AVE_DESC_SIZE_32 8 /* Descriptor Size */
> +
> +#define AVE_TXDM_32 0x1000 /* Tx Descriptor Memory */
> +#define AVE_RXDM_32 0x1800 /* Rx Descriptor Memory */
> +
> +#define AVE_TXDM_SIZE_32 0x07c0 /* Tx Descriptor Memory Size 2KB */
> +#define AVE_RXDM_SIZE_32 0x4000 /* Rx Descriptor Memory Size 16KB */
> +
> +/* RMII Bridge Register Group */
> +#define AVE_RSTCTRL 0x8028 /* Reset control */
> +#define AVE_RSTCTRL_RMIIRST BIT(16)
> +#define AVE_LINKSEL 0x8034 /* Link speed setting */
> +#define AVE_LINKSEL_100M BIT(0)
> +
> +/* AVE_GRR */
> +#define AVE_GRR_RXFFR BIT(5) /* Reset RxFIFO */
> +#define AVE_GRR_PHYRST BIT(4) /* Reset external PHY */
> +#define AVE_GRR_GRST BIT(0) /* Reset all MAC */
> +
> +/* AVE_GISR (common with GIMR) */
> +#define AVE_GI_PHY BIT(24) /* PHY interrupt */
> +#define AVE_GI_TX BIT(16) /* Tx complete */
> +#define AVE_GI_RXERR BIT(8) /* Receive frame more than max size */
> +#define AVE_GI_RXOVF BIT(7) /* Overflow at the RxFIFO */
> +#define AVE_GI_RXDROP BIT(6) /* Drop packet */
> +#define AVE_GI_RXIINT BIT(5) /* Interval interrupt */
> +
> +/* AVE_TXCR */
> +#define AVE_TXCR_FLOCTR BIT(18) /* Flow control */
> +#define AVE_TXCR_TXSPD_1G BIT(17)
> +#define AVE_TXCR_TXSPD_100 BIT(16)
> +
> +/* AVE_RXCR */
> +#define AVE_RXCR_RXEN BIT(30) /* Rx enable */
> +#define AVE_RXCR_FDUPEN BIT(22) /* Interface mode */
> +#define AVE_RXCR_FLOCTR BIT(21) /* Flow control */
> +#define AVE_RXCR_AFEN BIT(19) /* MAC address filter */
> +#define AVE_RXCR_DRPEN BIT(18) /* Drop pause frame */
> +#define AVE_RXCR_MPSIZ_MASK GENMASK(10, 0)
> +
> +/* AVE_MDIOCTR */
> +#define AVE_MDIOCTR_RREQ BIT(3) /* Read request */
> +#define AVE_MDIOCTR_WREQ BIT(2) /* Write request */
BIT() is descending.
> +/* AVE_MDIOSR */
> +#define AVE_MDIOSR_STS BIT(0) /* access status */
> +
> +/* AVE_DESCC */
> +#define AVE_DESCC_TD BIT(0) /* Enable Tx descriptor */
> +#define AVE_DESCC_RDSTP BIT(4) /* Pause Rx descriptor */
> +#define AVE_DESCC_RD0 BIT(8) /* Enable Rx descriptor Ring0 */
> +#define AVE_DESCC_STATUS_MASK GENMASK(31, 16)
BIT() is ascending.
Please be consistent.
> +
> +static void ave_wdesc_addr(struct net_device *ndev, enum desc_id id,
> + int entry, dma_addr_t paddr)
> +{
> + struct ave_private *priv = netdev_priv(ndev);
> +
> + ave_wdesc(ndev, id, entry, AVE_DESC_OFS_ADDRL, lower_32_bits(paddr));
> + if (IS_DESC_64BIT(priv))
> + ave_wdesc(ndev, id,
> + entry, AVE_DESC_OFS_ADDRU, upper_32_bits(paddr));
> + else if ((u64)paddr > (u64)U32_MAX)
> + netdev_warn(ndev, "DMA address exceeds the address space\n");
> +}
Yuk!
Why don't you use dma_set_mask() instead of this?
> +
> +static int ave_mdio_busywait(struct net_device *ndev)
> +{
> + int ret = 0, loop = 100;
> + u32 mdiosr;
> +
> + /* wait until completion */
> + while (--loop) {
> + mdiosr = ave_r32(ndev, AVE_MDIOSR);
> + if (!(mdiosr & AVE_MDIOSR_STS))
> + break;
> +
> + usleep_range(10, 20);
> + }
> +
> + if (!loop) {
> + netdev_err(ndev,
> + "failed to read from MDIO (status:0x%08x)\n",
> + mdiosr);
> + ret = -ETIMEDOUT;
> + }
> +
> + return ret;
> +}
The whole of this function can be replaced with
readl_poll_timeout() unless you stick to ave_r32.
I do not understand why you are such a big fan of
driver-specific accessors like ave_r32/ave_w32.
> +static int ave_mdiobus_read(struct mii_bus *bus, int phyid, int regnum)
> +{
> + struct net_device *ndev = bus->priv;
> + u32 mdioctl;
> + int ret;
> +
> + /* write address */
> + ave_w32(ndev, AVE_MDIOAR, (phyid << 8) | regnum);
> +
> + /* read request */
> + mdioctl = ave_r32(ndev, AVE_MDIOCTR);
> + ave_w32(ndev, AVE_MDIOCTR,
> + (mdioctl | AVE_MDIOCTR_RREQ) & ~AVE_MDIOCTR_WREQ);
> +
> + ret = ave_mdio_busywait(ndev);
> + if (ret) {
> + netdev_err(ndev, "phy-%d reg-%x read failed\n",
> + phyid, regnum);
> + return ret;
> + }
> +
> + return ave_r32(ndev, AVE_MDIORDR) & GENMASK(15, 0);
> +}
> +
> +static int ave_mdiobus_write(struct mii_bus *bus,
> + int phyid, int regnum, u16 val)
> +{
> + struct net_device *ndev = bus->priv;
> + u32 mdioctl;
> + int ret;
> +
> + /* write address */
> + ave_w32(ndev, AVE_MDIOAR, (phyid << 8) | regnum);
> +
> + /* write data */
> + ave_w32(ndev, AVE_MDIOWDR, val);
> +
> + /* write request */
> + mdioctl = ave_r32(ndev, AVE_MDIOCTR);
> + ave_w32(ndev, AVE_MDIOCTR,
> + (mdioctl | AVE_MDIOCTR_WREQ) & ~AVE_MDIOCTR_RREQ);
> +
> + ret = ave_mdio_busywait(ndev);
> + if (ret)
> + netdev_err(ndev, "phy-%d reg-%x write failed\n",
> + phyid, regnum);
> +
> + return ret;
> +}
> +
> +static dma_addr_t ave_dma_map(struct net_device *ndev, struct ave_desc *desc,
> + void *ptr, size_t len,
> + enum dma_data_direction dir)
> +{
> + dma_addr_t paddr;
> +
> + paddr = dma_map_single(ndev->dev.parent, ptr, len, dir);
> + if (unlikely(dma_mapping_error(ndev->dev.parent, paddr))) {
> + paddr = (dma_addr_t)-ENOMEM;
Yuk!
Re-write the code.
> + } else {
> + desc->skbs_dma = paddr;
> + desc->skbs_dmalen = len;
> + }
> +
> + return paddr;
> +}
--
Best Regards
Masahiro Yamada
More information about the linux-arm-kernel
mailing list