Commit 75cc93fad73897896511f08c1529233484ff063c
1 parent
f09854810c
Exists in
v2017.01-smarct4x
and in
30 other branches
net: axi_emac: Move driver to DM
Move driver to DM. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Showing 4 changed files with 122 additions and 79 deletions Side-by-side Diff
board/xilinx/microblaze-generic/microblaze-generic.c
... | ... | @@ -105,11 +105,6 @@ |
105 | 105 | { |
106 | 106 | int ret = 0; |
107 | 107 | |
108 | -#ifdef CONFIG_XILINX_AXIEMAC | |
109 | - ret |= xilinx_axiemac_initialize(bis, XILINX_AXIEMAC_BASEADDR, | |
110 | - XILINX_AXIDMA_BASEADDR); | |
111 | -#endif | |
112 | - | |
113 | 108 | #if defined(CONFIG_XILINX_EMACLITE) && defined(XILINX_EMACLITE_BASEADDR) |
114 | 109 | u32 txpp = 0; |
115 | 110 | u32 rxpp = 0; |
board/xilinx/zynq/board.c
drivers/net/xilinx_axi_emac.c
... | ... | @@ -8,12 +8,15 @@ |
8 | 8 | |
9 | 9 | #include <config.h> |
10 | 10 | #include <common.h> |
11 | +#include <dm.h> | |
11 | 12 | #include <net.h> |
12 | 13 | #include <malloc.h> |
13 | 14 | #include <asm/io.h> |
14 | 15 | #include <phy.h> |
15 | 16 | #include <miiphy.h> |
16 | 17 | |
18 | +DECLARE_GLOBAL_DATA_PTR; | |
19 | + | |
17 | 20 | #if !defined(CONFIG_PHYLIB) |
18 | 21 | # error AXI_ETHERNET requires PHYLIB |
19 | 22 | #endif |
... | ... | @@ -87,6 +90,7 @@ |
87 | 90 | struct axidma_reg *dmarx; |
88 | 91 | int phyaddr; |
89 | 92 | struct axi_regs *iobase; |
93 | + phy_interface_t interface; | |
90 | 94 | struct phy_device *phydev; |
91 | 95 | struct mii_dev *bus; |
92 | 96 | }; |
93 | 97 | |
... | ... | @@ -218,11 +222,11 @@ |
218 | 222 | } |
219 | 223 | |
220 | 224 | /* Setting axi emac and phy to proper setting */ |
221 | -static int setup_phy(struct eth_device *dev) | |
225 | +static int setup_phy(struct udevice *dev) | |
222 | 226 | { |
223 | 227 | u16 phyreg; |
224 | 228 | u32 i, speed, emmc_reg, ret; |
225 | - struct axidma_priv *priv = dev->priv; | |
229 | + struct axidma_priv *priv = dev_get_priv(dev); | |
226 | 230 | struct axi_regs *regs = priv->iobase; |
227 | 231 | struct phy_device *phydev; |
228 | 232 | |
229 | 233 | |
... | ... | @@ -298,9 +302,9 @@ |
298 | 302 | } |
299 | 303 | |
300 | 304 | /* STOP DMA transfers */ |
301 | -static void axiemac_halt(struct eth_device *dev) | |
305 | +static void axiemac_halt(struct udevice *dev) | |
302 | 306 | { |
303 | - struct axidma_priv *priv = dev->priv; | |
307 | + struct axidma_priv *priv = dev_get_priv(dev); | |
304 | 308 | u32 temp; |
305 | 309 | |
306 | 310 | /* Stop the hardware */ |
307 | 311 | |
308 | 312 | |
309 | 313 | |
... | ... | @@ -358,16 +362,18 @@ |
358 | 362 | return 0; |
359 | 363 | } |
360 | 364 | |
361 | -static int axiemac_setup_mac(struct eth_device *dev) | |
365 | +static int axiemac_setup_mac(struct udevice *dev) | |
362 | 366 | { |
363 | - struct axi_regs *regs = (struct axi_regs *)dev->iobase; | |
367 | + struct eth_pdata *pdata = dev_get_platdata(dev); | |
368 | + struct axidma_priv *priv = dev_get_priv(dev); | |
369 | + struct axi_regs *regs = priv->iobase; | |
364 | 370 | |
365 | 371 | /* Set the MAC address */ |
366 | - int val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) | | |
367 | - (dev->enetaddr[1] << 8) | (dev->enetaddr[0])); | |
372 | + int val = ((pdata->enetaddr[3] << 24) | (pdata->enetaddr[2] << 16) | | |
373 | + (pdata->enetaddr[1] << 8) | (pdata->enetaddr[0])); | |
368 | 374 | out_be32(®s->uaw0, val); |
369 | 375 | |
370 | - val = (dev->enetaddr[5] << 8) | dev->enetaddr[4] ; | |
376 | + val = (pdata->enetaddr[5] << 8) | pdata->enetaddr[4]; | |
371 | 377 | val |= in_be32(®s->uaw1) & ~XAE_UAW1_UNICASTADDR_MASK; |
372 | 378 | out_be32(®s->uaw1, val); |
373 | 379 | return 0; |
374 | 380 | |
... | ... | @@ -396,10 +402,10 @@ |
396 | 402 | printf("%s: Timeout\n", __func__); |
397 | 403 | } |
398 | 404 | |
399 | -static int axiemac_init(struct eth_device *dev, bd_t * bis) | |
405 | +static int axiemac_init(struct udevice *dev) | |
400 | 406 | { |
401 | - struct axidma_priv *priv = dev->priv; | |
402 | - struct axi_regs *regs = (struct axi_regs *)dev->iobase; | |
407 | + struct axidma_priv *priv = dev_get_priv(dev); | |
408 | + struct axi_regs *regs = priv->iobase; | |
403 | 409 | u32 temp; |
404 | 410 | |
405 | 411 | debug("axiemac: Init started\n"); |
406 | 412 | |
... | ... | @@ -458,9 +464,9 @@ |
458 | 464 | return 0; |
459 | 465 | } |
460 | 466 | |
461 | -static int axiemac_send(struct eth_device *dev, void *ptr, int len) | |
467 | +static int axiemac_send(struct udevice *dev, void *ptr, int len) | |
462 | 468 | { |
463 | - struct axidma_priv *priv = dev->priv; | |
469 | + struct axidma_priv *priv = dev_get_priv(dev); | |
464 | 470 | u32 timeout; |
465 | 471 | |
466 | 472 | if (len > PKTSIZE_ALIGN) |
467 | 473 | |
468 | 474 | |
... | ... | @@ -530,15 +536,15 @@ |
530 | 536 | return 0; |
531 | 537 | } |
532 | 538 | |
533 | -static int axiemac_recv(struct eth_device *dev) | |
539 | +static int axiemac_recv(struct udevice *dev, int flags, uchar **packetp) | |
534 | 540 | { |
535 | 541 | u32 length; |
536 | - struct axidma_priv *priv = dev->priv; | |
542 | + struct axidma_priv *priv = dev_get_priv(dev); | |
537 | 543 | u32 temp; |
538 | 544 | |
539 | 545 | /* Wait for an incoming packet */ |
540 | 546 | if (!isrxready(priv)) |
541 | - return 0; | |
547 | + return -1; | |
542 | 548 | |
543 | 549 | debug("axiemac: RX data ready\n"); |
544 | 550 | |
545 | 551 | |
546 | 552 | |
547 | 553 | |
548 | 554 | |
549 | 555 | |
550 | 556 | |
551 | 557 | |
552 | 558 | |
553 | 559 | |
554 | 560 | |
555 | 561 | |
556 | 562 | |
557 | 563 | |
558 | 564 | |
559 | 565 | |
560 | 566 | |
561 | 567 | |
562 | 568 | |
563 | 569 | |
... | ... | @@ -578,78 +584,126 @@ |
578 | 584 | |
579 | 585 | debug("axiemac: RX completed, framelength = %d\n", length); |
580 | 586 | |
581 | - return length; | |
587 | + return 0; | |
582 | 588 | } |
583 | 589 | |
584 | -static int axiemac_miiphy_read(const char *devname, uchar addr, | |
585 | - uchar reg, ushort *val) | |
590 | +static int axiemac_miiphy_read(struct mii_dev *bus, int addr, | |
591 | + int devad, int reg) | |
586 | 592 | { |
587 | - struct eth_device *dev = eth_get_dev(); | |
588 | - u32 ret; | |
593 | + int ret; | |
594 | + u16 value; | |
589 | 595 | |
590 | - ret = phyread(dev->priv, addr, reg, val); | |
591 | - debug("axiemac: Read MII 0x%x, 0x%x, 0x%x\n", addr, reg, *val); | |
592 | - return ret; | |
596 | + ret = phyread(bus->priv, addr, reg, &value); | |
597 | + debug("axiemac: Read MII 0x%x, 0x%x, 0x%x, %d\n", addr, reg, | |
598 | + value, ret); | |
599 | + return value; | |
593 | 600 | } |
594 | 601 | |
595 | -static int axiemac_miiphy_write(const char *devname, uchar addr, | |
596 | - uchar reg, ushort val) | |
602 | +static int axiemac_miiphy_write(struct mii_dev *bus, int addr, int devad, | |
603 | + int reg, u16 value) | |
597 | 604 | { |
598 | - struct eth_device *dev = eth_get_dev(); | |
599 | - | |
600 | - debug("axiemac: Write MII 0x%x, 0x%x, 0x%x\n", addr, reg, val); | |
601 | - return phywrite(dev->priv, addr, reg, val); | |
605 | + debug("axiemac: Write MII 0x%x, 0x%x, 0x%x\n", addr, reg, value); | |
606 | + return phywrite(bus->priv, addr, reg, value); | |
602 | 607 | } |
603 | 608 | |
604 | -static int axiemac_bus_reset(struct mii_dev *bus) | |
609 | +static int axi_emac_probe(struct udevice *dev) | |
605 | 610 | { |
606 | - debug("axiemac: Bus reset\n"); | |
611 | + struct axidma_priv *priv = dev_get_priv(dev); | |
612 | + int ret; | |
613 | + | |
614 | + priv->bus = mdio_alloc(); | |
615 | + priv->bus->read = axiemac_miiphy_read; | |
616 | + priv->bus->write = axiemac_miiphy_write; | |
617 | + priv->bus->priv = priv; | |
618 | + strcpy(priv->bus->name, "axi_emac"); | |
619 | + | |
620 | + ret = mdio_register(priv->bus); | |
621 | + if (ret) | |
622 | + return ret; | |
623 | + | |
607 | 624 | return 0; |
608 | 625 | } |
609 | 626 | |
610 | -int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr, | |
611 | - unsigned long dma_addr) | |
627 | +static int axi_emac_remove(struct udevice *dev) | |
612 | 628 | { |
613 | - struct eth_device *dev; | |
614 | - struct axidma_priv *priv; | |
629 | + struct axidma_priv *priv = dev_get_priv(dev); | |
615 | 630 | |
616 | - dev = calloc(1, sizeof(struct eth_device)); | |
617 | - if (dev == NULL) | |
618 | - return -1; | |
631 | + free(priv->phydev); | |
632 | + mdio_unregister(priv->bus); | |
633 | + mdio_free(priv->bus); | |
619 | 634 | |
620 | - dev->priv = calloc(1, sizeof(struct axidma_priv)); | |
621 | - if (dev->priv == NULL) { | |
622 | - free(dev); | |
623 | - return -1; | |
624 | - } | |
625 | - priv = dev->priv; | |
635 | + return 0; | |
636 | +} | |
626 | 637 | |
627 | - sprintf(dev->name, "aximac.%lx", base_addr); | |
638 | +static const struct eth_ops axi_emac_ops = { | |
639 | + .start = axiemac_init, | |
640 | + .send = axiemac_send, | |
641 | + .recv = axiemac_recv, | |
642 | + .stop = axiemac_halt, | |
643 | + .write_hwaddr = axiemac_setup_mac, | |
644 | +}; | |
628 | 645 | |
629 | - dev->iobase = base_addr; | |
630 | - priv->iobase = (struct axi_regs *)base_addr; | |
631 | - priv->dmatx = (struct axidma_reg *)dma_addr; | |
646 | +static int axi_emac_ofdata_to_platdata(struct udevice *dev) | |
647 | +{ | |
648 | + struct eth_pdata *pdata = dev_get_platdata(dev); | |
649 | + struct axidma_priv *priv = dev_get_priv(dev); | |
650 | + int offset = 0; | |
651 | + const char *phy_mode; | |
652 | + | |
653 | + pdata->iobase = (phys_addr_t)dev_get_addr(dev); | |
654 | + priv->iobase = (struct axi_regs *)pdata->iobase; | |
655 | + | |
656 | + offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, | |
657 | + "axistream-connected"); | |
658 | + if (offset <= 0) { | |
659 | + printf("%s: axistream is not found\n", __func__); | |
660 | + return -EINVAL; | |
661 | + } | |
662 | + priv->dmatx = (struct axidma_reg *)fdtdec_get_int(gd->fdt_blob, | |
663 | + offset, "reg", 0); | |
664 | + if (!priv->dmatx) { | |
665 | + printf("%s: axi_dma register space not found\n", __func__); | |
666 | + return -EINVAL; | |
667 | + } | |
632 | 668 | /* RX channel offset is 0x30 */ |
633 | - priv->dmarx = (struct axidma_reg *)(dma_addr + 0x30); | |
634 | - dev->init = axiemac_init; | |
635 | - dev->halt = axiemac_halt; | |
636 | - dev->send = axiemac_send; | |
637 | - dev->recv = axiemac_recv; | |
638 | - dev->write_hwaddr = axiemac_setup_mac; | |
669 | + priv->dmarx = (struct axidma_reg *)((u32)priv->dmatx + 0x30); | |
639 | 670 | |
640 | -#ifdef CONFIG_PHY_ADDR | |
641 | - priv->phyaddr = CONFIG_PHY_ADDR; | |
642 | -#else | |
643 | 671 | priv->phyaddr = -1; |
644 | -#endif | |
645 | 672 | |
646 | - eth_register(dev); | |
673 | + offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, | |
674 | + "phy-handle"); | |
675 | + if (offset > 0) | |
676 | + priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1); | |
647 | 677 | |
648 | -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) | |
649 | - miiphy_register(dev->name, axiemac_miiphy_read, axiemac_miiphy_write); | |
650 | - priv->bus = miiphy_get_dev_by_name(dev->name); | |
651 | - priv->bus->reset = axiemac_bus_reset; | |
652 | -#endif | |
653 | - return 1; | |
678 | + phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); | |
679 | + if (phy_mode) | |
680 | + pdata->phy_interface = phy_get_interface_by_name(phy_mode); | |
681 | + if (pdata->phy_interface == -1) { | |
682 | + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); | |
683 | + return -EINVAL; | |
684 | + } | |
685 | + priv->interface = pdata->phy_interface; | |
686 | + | |
687 | + printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase, | |
688 | + priv->phyaddr, phy_string_for_interface(priv->interface)); | |
689 | + | |
690 | + return 0; | |
654 | 691 | } |
692 | + | |
693 | +static const struct udevice_id axi_emac_ids[] = { | |
694 | + { .compatible = "xlnx,axi-ethernet-1.00.a" }, | |
695 | + { } | |
696 | +}; | |
697 | + | |
698 | +U_BOOT_DRIVER(axi_emac) = { | |
699 | + .name = "axi_emac", | |
700 | + .id = UCLASS_ETH, | |
701 | + .of_match = axi_emac_ids, | |
702 | + .ofdata_to_platdata = axi_emac_ofdata_to_platdata, | |
703 | + .probe = axi_emac_probe, | |
704 | + .remove = axi_emac_remove, | |
705 | + .ops = &axi_emac_ops, | |
706 | + .priv_auto_alloc_size = sizeof(struct axidma_priv), | |
707 | + .platdata_auto_alloc_size = sizeof(struct eth_pdata), | |
708 | +}; |
include/netdev.h
... | ... | @@ -80,8 +80,6 @@ |
80 | 80 | int uec_standard_init(bd_t *bis); |
81 | 81 | int uli526x_initialize(bd_t *bis); |
82 | 82 | int armada100_fec_register(unsigned long base_addr); |
83 | -int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr, | |
84 | - unsigned long dma_addr); | |
85 | 83 | int xilinx_emaclite_of_init(const void *blob); |
86 | 84 | int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr, |
87 | 85 | int txpp, int rxpp); |