X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsunxi_emac.c;h=37685f30f3f6a64728c078bbf034d7fa8ccb726e;hb=f24e482ae0b856fcf18e8e6956ab3f6b59f3693f;hp=038f474d254cfb5992a0106a9aeed96543ca3877;hpb=f9f62d2dac076de247461155f62906e0104259b0;p=oweals%2Fu-boot.git diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index 038f474d25..37685f30f3 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -153,13 +154,16 @@ struct sunxi_sramc_regs { #define EMAC_CRCERR (0x1 << 4) #define EMAC_LENERR (0x3 << 5) -#define DMA_CPU_TRRESHOLD 2000 +#define EMAC_RX_BUFSIZE 2000 struct emac_eth_dev { struct emac_regs *regs; struct mii_dev *bus; struct phy_device *phydev; int link_printed; +#ifdef CONFIG_DM_ETH + uchar rx_buf[EMAC_RX_BUFSIZE]; +#endif }; struct emac_rxhdr { @@ -323,6 +327,20 @@ static void emac_reset(struct emac_eth_dev *priv) udelay(200); } +static int _sunxi_write_hwaddr(struct emac_eth_dev *priv, u8 *enetaddr) +{ + struct emac_regs *regs = priv->regs; + u32 enetaddr_lo, enetaddr_hi; + + enetaddr_lo = enetaddr[2] | (enetaddr[1] << 8) | (enetaddr[0] << 16); + enetaddr_hi = enetaddr[5] | (enetaddr[4] << 8) | (enetaddr[3] << 16); + + writel(enetaddr_hi, ®s->mac_a1); + writel(enetaddr_lo, ®s->mac_a0); + + return 0; +} + static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr) { struct emac_regs *regs = priv->regs; @@ -346,10 +364,7 @@ static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr) /* Set up EMAC */ emac_setup(priv); - writel(enetaddr[0] << 16 | enetaddr[1] << 8 | enetaddr[2], - ®s->mac_a1); - writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5], - ®s->mac_a0); + _sunxi_write_hwaddr(priv, enetaddr); mdelay(1); @@ -455,7 +470,7 @@ static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet) /* Move data from EMAC */ if (good_packet) { - if (rx_len > DMA_CPU_TRRESHOLD) { + if (rx_len > EMAC_RX_BUFSIZE) { printf("Received packet is too big (len=%d)\n", rx_len); return -EMSGSIZE; } @@ -509,67 +524,75 @@ static void sunxi_emac_board_setup(struct emac_eth_dev *priv) clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); } -static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bis) +static int sunxi_emac_eth_start(struct udevice *dev) { - return _sunxi_emac_eth_init(dev->priv, dev->enetaddr); + struct eth_pdata *pdata = dev_get_platdata(dev); + + return _sunxi_emac_eth_init(dev->priv, pdata->enetaddr); } -static void sunxi_emac_eth_halt(struct eth_device *dev) +static int sunxi_emac_eth_send(struct udevice *dev, void *packet, int length) { - /* Nothing to do here */ + struct emac_eth_dev *priv = dev_get_priv(dev); + + return _sunxi_emac_eth_send(priv, packet, length); } -static int sunxi_emac_eth_recv(struct eth_device *dev) +static int sunxi_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp) { + struct emac_eth_dev *priv = dev_get_priv(dev); int rx_len; - rx_len = _sunxi_emac_eth_recv(dev->priv, net_rx_packets[0]); - if (rx_len <= 0) - return 0; - - /* Pass to upper layer */ - net_process_received_packet(net_rx_packets[0], rx_len); + rx_len = _sunxi_emac_eth_recv(priv, priv->rx_buf); + *packetp = priv->rx_buf; return rx_len; } -static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int length) +static void sunxi_emac_eth_stop(struct udevice *dev) { - return _sunxi_emac_eth_send(dev->priv, packet, length); + /* Nothing to do here */ } -int sunxi_emac_initialize(void) +static int sunxi_emac_eth_probe(struct udevice *dev) { - struct emac_regs *regs = - (struct emac_regs *)SUNXI_EMAC_BASE; - struct eth_device *dev; - struct emac_eth_dev *priv; - - dev = malloc(sizeof(*dev)); - if (dev == NULL) - return -ENOMEM; + struct eth_pdata *pdata = dev_get_platdata(dev); + struct emac_eth_dev *priv = dev_get_priv(dev); - priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev)); - if (!priv) { - free(dev); - return -ENOMEM; - } + priv->regs = (struct emac_regs *)pdata->iobase; + sunxi_emac_board_setup(priv); - memset(dev, 0, sizeof(*dev)); - memset(priv, 0, sizeof(struct emac_eth_dev)); + return sunxi_emac_init_phy(priv, dev); +} - priv->regs = regs; - dev->iobase = (int)regs; - dev->priv = priv; - dev->init = sunxi_emac_eth_init; - dev->halt = sunxi_emac_eth_halt; - dev->send = sunxi_emac_eth_send; - dev->recv = sunxi_emac_eth_recv; - strcpy(dev->name, "emac"); +static const struct eth_ops sunxi_emac_eth_ops = { + .start = sunxi_emac_eth_start, + .send = sunxi_emac_eth_send, + .recv = sunxi_emac_eth_recv, + .stop = sunxi_emac_eth_stop, +}; - sunxi_emac_board_setup(priv); +static int sunxi_emac_eth_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); - eth_register(dev); + pdata->iobase = devfdt_get_addr(dev); - return sunxi_emac_init_phy(priv, dev); + return 0; } + +static const struct udevice_id sunxi_emac_eth_ids[] = { + { .compatible = "allwinner,sun4i-a10-emac" }, + { } +}; + +U_BOOT_DRIVER(eth_sunxi_emac) = { + .name = "eth_sunxi_emac", + .id = UCLASS_ETH, + .of_match = sunxi_emac_eth_ids, + .ofdata_to_platdata = sunxi_emac_eth_ofdata_to_platdata, + .probe = sunxi_emac_eth_probe, + .ops = &sunxi_emac_eth_ops, + .priv_auto_alloc_size = sizeof(struct emac_eth_dev), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +};