Lines Matching +full:sun7i +full:- +full:a20 +full:- +full:gmac +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0+
8 * Designware ethernet IP driver for U-Boot
12 #include <clk.h>
29 struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv); in dw_mdio_read()
30 struct eth_mac_regs *mac_p = priv->mac_regs_p; in dw_mdio_read()
32 struct eth_mac_regs *mac_p = bus->priv; in dw_mdio_read()
41 writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); in dw_mdio_read()
45 if (!(readl(&mac_p->miiaddr) & MII_BUSY)) in dw_mdio_read()
46 return readl(&mac_p->miidata); in dw_mdio_read()
50 return -ETIMEDOUT; in dw_mdio_read()
57 struct dw_eth_dev *priv = dev_get_priv((struct udevice *)bus->priv); in dw_mdio_write()
58 struct eth_mac_regs *mac_p = priv->mac_regs_p; in dw_mdio_write()
60 struct eth_mac_regs *mac_p = bus->priv; in dw_mdio_write()
64 int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT; in dw_mdio_write()
66 writel(val, &mac_p->miidata); in dw_mdio_write()
70 writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); in dw_mdio_write()
74 if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { in dw_mdio_write()
87 struct udevice *dev = bus->priv; in dw_mdio_reset()
92 if (!dm_gpio_is_valid(&priv->reset_gpio)) in dw_mdio_reset()
96 ret = dm_gpio_set_value(&priv->reset_gpio, 0); in dw_mdio_reset()
100 udelay(pdata->reset_delays[0]); in dw_mdio_reset()
102 ret = dm_gpio_set_value(&priv->reset_gpio, 1); in dw_mdio_reset()
106 udelay(pdata->reset_delays[1]); in dw_mdio_reset()
108 ret = dm_gpio_set_value(&priv->reset_gpio, 0); in dw_mdio_reset()
112 udelay(pdata->reset_delays[2]); in dw_mdio_reset()
124 return -ENOMEM; in dw_mdio_init()
127 bus->read = dw_mdio_read; in dw_mdio_init()
128 bus->write = dw_mdio_write; in dw_mdio_init()
129 snprintf(bus->name, sizeof(bus->name), "%s", name); in dw_mdio_init()
131 bus->reset = dw_mdio_reset; in dw_mdio_init()
134 bus->priv = priv; in dw_mdio_init()
141 struct eth_dma_regs *dma_p = priv->dma_regs_p; in tx_descs_init()
142 struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0]; in tx_descs_init()
143 char *txbuffs = &priv->txbuffs[0]; in tx_descs_init()
149 desc_p->dmamac_addr = (ulong)&txbuffs[idx * CONFIG_ETH_BUFSIZE]; in tx_descs_init()
150 desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1]; in tx_descs_init()
153 desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST | in tx_descs_init()
158 desc_p->txrx_status |= DESC_TXSTS_TXCHAIN; in tx_descs_init()
159 desc_p->dmamac_cntl = 0; in tx_descs_init()
160 desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA); in tx_descs_init()
162 desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN; in tx_descs_init()
163 desc_p->txrx_status = 0; in tx_descs_init()
168 desc_p->dmamac_next = (ulong)&desc_table_p[0]; in tx_descs_init()
171 flush_dcache_range((ulong)priv->tx_mac_descrtable, in tx_descs_init()
172 (ulong)priv->tx_mac_descrtable + in tx_descs_init()
173 sizeof(priv->tx_mac_descrtable)); in tx_descs_init()
175 writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); in tx_descs_init()
176 priv->tx_currdescnum = 0; in tx_descs_init()
181 struct eth_dma_regs *dma_p = priv->dma_regs_p; in rx_descs_init()
182 struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0]; in rx_descs_init()
183 char *rxbuffs = &priv->rxbuffs[0]; in rx_descs_init()
187 /* Before passing buffers to GMAC we need to make sure zeros in rx_descs_init()
191 * GMAC is already pushing data to RAM via DMA. This way incoming from in rx_descs_init()
192 * GMAC data will be corrupted. */ in rx_descs_init()
197 desc_p->dmamac_addr = (ulong)&rxbuffs[idx * CONFIG_ETH_BUFSIZE]; in rx_descs_init()
198 desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1]; in rx_descs_init()
200 desc_p->dmamac_cntl = in rx_descs_init()
204 desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; in rx_descs_init()
208 desc_p->dmamac_next = (ulong)&desc_table_p[0]; in rx_descs_init()
211 flush_dcache_range((ulong)priv->rx_mac_descrtable, in rx_descs_init()
212 (ulong)priv->rx_mac_descrtable + in rx_descs_init()
213 sizeof(priv->rx_mac_descrtable)); in rx_descs_init()
215 writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); in rx_descs_init()
216 priv->rx_currdescnum = 0; in rx_descs_init()
221 struct eth_mac_regs *mac_p = priv->mac_regs_p; in _dw_write_hwaddr()
228 writel(macid_hi, &mac_p->macaddr0hi); in _dw_write_hwaddr()
229 writel(macid_lo, &mac_p->macaddr0lo); in _dw_write_hwaddr()
237 u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN; in dw_adjust_link()
239 if (!phydev->link) { in dw_adjust_link()
240 printf("%s: No link.\n", phydev->dev->name); in dw_adjust_link()
244 if (phydev->speed != 1000) in dw_adjust_link()
249 if (phydev->speed == 100) in dw_adjust_link()
252 if (phydev->duplex) in dw_adjust_link()
255 writel(conf, &mac_p->conf); in dw_adjust_link()
257 printf("Speed: %d, %s duplex%s\n", phydev->speed, in dw_adjust_link()
258 (phydev->duplex) ? "full" : "half", in dw_adjust_link()
259 (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); in dw_adjust_link()
266 struct eth_mac_regs *mac_p = priv->mac_regs_p; in _dw_eth_halt()
267 struct eth_dma_regs *dma_p = priv->dma_regs_p; in _dw_eth_halt()
269 writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf); in _dw_eth_halt()
270 writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode); in _dw_eth_halt()
272 phy_shutdown(priv->phydev); in _dw_eth_halt()
277 struct eth_mac_regs *mac_p = priv->mac_regs_p; in designware_eth_init()
278 struct eth_dma_regs *dma_p = priv->dma_regs_p; in designware_eth_init()
282 writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); in designware_eth_init()
288 if (priv->phydev->interface == PHY_INTERFACE_MODE_MII) in designware_eth_init()
289 writel(readl(&mac_p->conf) | MII_PORTSELECT, &mac_p->conf); in designware_eth_init()
291 writel(readl(&mac_p->conf) & ~MII_PORTSELECT, &mac_p->conf); in designware_eth_init()
294 while (readl(&dma_p->busmode) & DMAMAC_SRST) { in designware_eth_init()
297 return -ETIMEDOUT; in designware_eth_init()
312 writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode); in designware_eth_init()
315 writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD, in designware_eth_init()
316 &dma_p->opmode); in designware_eth_init()
318 writel(readl(&dma_p->opmode) | FLUSHTXFIFO, in designware_eth_init()
319 &dma_p->opmode); in designware_eth_init()
322 writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode); in designware_eth_init()
325 writel((CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1), &dma_p->axibus); in designware_eth_init()
329 ret = phy_startup(priv->phydev); in designware_eth_init()
332 priv->phydev->dev->name); in designware_eth_init()
336 ret = dw_adjust_link(priv, mac_p, priv->phydev); in designware_eth_init()
345 struct eth_mac_regs *mac_p = priv->mac_regs_p; in designware_eth_enable()
347 if (!priv->phydev->link) in designware_eth_enable()
348 return -EIO; in designware_eth_enable()
350 writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); in designware_eth_enable()
359 struct eth_dma_regs *dma_p = priv->dma_regs_p; in _dw_eth_send()
360 u32 desc_num = priv->tx_currdescnum; in _dw_eth_send()
361 struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; in _dw_eth_send()
365 ulong data_start = desc_p->dmamac_addr; in _dw_eth_send()
378 if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { in _dw_eth_send()
380 return -EPERM; in _dw_eth_send()
385 memset(&((char *)data_start)[length], 0, ETH_ZLEN - length); in _dw_eth_send()
393 desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; in _dw_eth_send()
394 desc_p->dmamac_cntl = (desc_p->dmamac_cntl & ~DESC_TXCTRL_SIZE1MASK) | in _dw_eth_send()
398 desc_p->txrx_status &= ~(DESC_TXSTS_MSK); in _dw_eth_send()
399 desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA; in _dw_eth_send()
401 desc_p->dmamac_cntl = (desc_p->dmamac_cntl & ~DESC_TXCTRL_SIZE1MASK) | in _dw_eth_send()
406 desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; in _dw_eth_send()
412 /* Test the wrap-around condition. */ in _dw_eth_send()
416 priv->tx_currdescnum = desc_num; in _dw_eth_send()
419 writel(POLL_DATA, &dma_p->txpolldemand); in _dw_eth_send()
426 u32 status, desc_num = priv->rx_currdescnum; in _dw_eth_recv()
427 struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; in _dw_eth_recv()
428 int length = -EAGAIN; in _dw_eth_recv()
432 ulong data_start = desc_p->dmamac_addr; in _dw_eth_recv()
438 status = desc_p->txrx_status; in _dw_eth_recv()
449 *packetp = (uchar *)(ulong)desc_p->dmamac_addr; in _dw_eth_recv()
457 u32 desc_num = priv->rx_currdescnum; in _dw_free_pkt()
458 struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; in _dw_free_pkt()
467 desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; in _dw_free_pkt()
469 /* Flush only status field - others weren't changed */ in _dw_free_pkt()
472 /* Test the wrap-around condition. */ in _dw_free_pkt()
475 priv->rx_currdescnum = desc_num; in _dw_free_pkt()
489 phydev = phy_find_by_mask(priv->bus, mask, priv->interface); in dw_phy_init()
491 return -ENODEV; in dw_phy_init()
495 phydev->supported &= PHY_GBIT_FEATURES; in dw_phy_init()
496 if (priv->max_speed) { in dw_phy_init()
497 ret = phy_set_supported(phydev, priv->max_speed); in dw_phy_init()
501 phydev->advertising = phydev->supported; in dw_phy_init()
503 priv->phydev = phydev; in dw_phy_init()
514 ret = designware_eth_init(dev->priv, dev->enetaddr); in dw_eth_init()
516 ret = designware_eth_enable(dev->priv); in dw_eth_init()
523 return _dw_eth_send(dev->priv, packet, length); in dw_eth_send()
531 length = _dw_eth_recv(dev->priv, &packet); in dw_eth_recv()
532 if (length == -EAGAIN) in dw_eth_recv()
536 _dw_free_pkt(dev->priv); in dw_eth_recv()
543 return _dw_eth_halt(dev->priv); in dw_eth_halt()
548 return _dw_write_hwaddr(dev->priv, dev->enetaddr); in dw_write_hwaddr()
558 return -ENOMEM; in designware_initialize()
568 return -ENOMEM; in designware_initialize()
573 return -EINVAL; in designware_initialize()
579 sprintf(dev->name, "dwmac.%lx", base_addr); in designware_initialize()
580 dev->iobase = (int)base_addr; in designware_initialize()
581 dev->priv = priv; in designware_initialize()
583 priv->dev = dev; in designware_initialize()
584 priv->mac_regs_p = (struct eth_mac_regs *)base_addr; in designware_initialize()
585 priv->dma_regs_p = (struct eth_dma_regs *)(base_addr + in designware_initialize()
588 dev->init = dw_eth_init; in designware_initialize()
589 dev->send = dw_eth_send; in designware_initialize()
590 dev->recv = dw_eth_recv; in designware_initialize()
591 dev->halt = dw_eth_halt; in designware_initialize()
592 dev->write_hwaddr = dw_write_hwaddr; in designware_initialize()
596 priv->interface = interface; in designware_initialize()
598 dw_mdio_init(dev->name, priv->mac_regs_p); in designware_initialize()
599 priv->bus = miiphy_get_dev_by_name(dev->name); in designware_initialize()
612 ret = designware_eth_init(priv, pdata->enetaddr); in designware_eth_start()
655 return _dw_write_hwaddr(priv, pdata->enetaddr); in designware_eth_write_hwaddr()
678 u32 iobase = pdata->iobase; in designware_eth_probe()
685 priv->clock_count = 0; in designware_eth_probe()
686 clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); in designware_eth_probe()
688 priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), in designware_eth_probe()
690 if (!priv->clocks) in designware_eth_probe()
691 return -ENOMEM; in designware_eth_probe()
694 err = clk_get_by_index(dev, i, &priv->clocks[i]); in designware_eth_probe()
698 err = clk_enable(&priv->clocks[i]); in designware_eth_probe()
699 if (err && err != -ENOSYS && err != -ENOTSUPP) { in designware_eth_probe()
701 clk_free(&priv->clocks[i]); in designware_eth_probe()
704 priv->clock_count++; in designware_eth_probe()
706 } else if (clock_nb != -ENOENT) { in designware_eth_probe()
715 ret = device_get_supply_regulator(dev, "phy-supply", in designware_eth_probe()
718 debug("%s: No phy supply\n", dev->name); in designware_eth_probe()
744 pdata->iobase = iobase; in designware_eth_probe()
745 pdata->phy_interface = PHY_INTERFACE_MODE_RMII; in designware_eth_probe()
751 priv->mac_regs_p = (struct eth_mac_regs *)ioaddr; in designware_eth_probe()
752 priv->dma_regs_p = (struct eth_dma_regs *)(ioaddr + DW_DMA_BASE_OFFSET); in designware_eth_probe()
753 priv->interface = pdata->phy_interface; in designware_eth_probe()
754 priv->max_speed = pdata->max_speed; in designware_eth_probe()
756 dw_mdio_init(dev->name, dev); in designware_eth_probe()
757 priv->bus = miiphy_get_dev_by_name(dev->name); in designware_eth_probe()
766 ret = clk_release_all(priv->clocks, priv->clock_count); in designware_eth_probe()
778 free(priv->phydev); in designware_eth_remove()
779 mdio_unregister(priv->bus); in designware_eth_remove()
780 mdio_free(priv->bus); in designware_eth_remove()
783 return clk_release_all(priv->clocks, priv->clock_count); in designware_eth_remove()
804 struct eth_pdata *pdata = &dw_pdata->eth_pdata; in designware_eth_ofdata_to_platdata()
811 pdata->iobase = dev_read_addr(dev); in designware_eth_ofdata_to_platdata()
812 pdata->phy_interface = -1; in designware_eth_ofdata_to_platdata()
813 phy_mode = dev_read_string(dev, "phy-mode"); in designware_eth_ofdata_to_platdata()
815 pdata->phy_interface = phy_get_interface_by_name(phy_mode); in designware_eth_ofdata_to_platdata()
816 if (pdata->phy_interface == -1) { in designware_eth_ofdata_to_platdata()
818 return -EINVAL; in designware_eth_ofdata_to_platdata()
821 pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0); in designware_eth_ofdata_to_platdata()
824 if (dev_read_bool(dev, "snps,reset-active-low")) in designware_eth_ofdata_to_platdata()
827 ret = gpio_request_by_name(dev, "snps,reset-gpio", 0, in designware_eth_ofdata_to_platdata()
828 &priv->reset_gpio, reset_flags); in designware_eth_ofdata_to_platdata()
830 ret = dev_read_u32_array(dev, "snps,reset-delays-us", in designware_eth_ofdata_to_platdata()
831 dw_pdata->reset_delays, 3); in designware_eth_ofdata_to_platdata()
832 } else if (ret == -ENOENT) { in designware_eth_ofdata_to_platdata()
841 { .compatible = "allwinner,sun7i-a20-gmac" },
842 { .compatible = "altr,socfpga-stmmac" },
843 { .compatible = "amlogic,meson6-dwmac" },
844 { .compatible = "amlogic,meson-gx-dwmac" },
845 { .compatible = "amlogic,meson-gxbb-dwmac" },
846 { .compatible = "amlogic,meson-axg-dwmac" },
847 { .compatible = "st,stm32-dwmac" },