183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2b3dbf4a5SMacpaul Lin /*
3b3dbf4a5SMacpaul Lin * Faraday FTGMAC100 Ethernet
4b3dbf4a5SMacpaul Lin *
5b3dbf4a5SMacpaul Lin * (C) Copyright 2009 Faraday Technology
6b3dbf4a5SMacpaul Lin * Po-Yu Chuang <ratbert@faraday-tech.com>
7b3dbf4a5SMacpaul Lin *
8b3dbf4a5SMacpaul Lin * (C) Copyright 2010 Andes Technology
9b3dbf4a5SMacpaul Lin * Macpaul Lin <macpaul@andestech.com>
10f95de0bdSCédric Le Goater *
11f95de0bdSCédric Le Goater * Copyright (C) 2018, IBM Corporation.
12b3dbf4a5SMacpaul Lin */
13b3dbf4a5SMacpaul Lin
141c0c61e9SCédric Le Goater #include <clk.h>
15f95de0bdSCédric Le Goater #include <dm.h>
16f95de0bdSCédric Le Goater #include <miiphy.h>
17b3dbf4a5SMacpaul Lin #include <net.h>
18d0e0b84cSCédric Le Goater #include <wait_bit.h>
19f95de0bdSCédric Le Goater #include <linux/io.h>
20538e75d3SCédric Le Goater #include <linux/iopoll.h>
219ab23354SDylan Hung #include <net/ncsi.h>
22b3dbf4a5SMacpaul Lin
23b3dbf4a5SMacpaul Lin #include "ftgmac100.h"
24176338f1Sryan_chen #include "aspeed_mdio.h"
25b3dbf4a5SMacpaul Lin
26e7668497SCédric Le Goater /* Min frame ethernet frame size without FCS */
27b3dbf4a5SMacpaul Lin #define ETH_ZLEN 60
28b3dbf4a5SMacpaul Lin
29e7668497SCédric Le Goater /* Receive Buffer Size Register - HW default is 0x640 */
30e7668497SCédric Le Goater #define FTGMAC100_RBSR_DEFAULT 0x640
31b3dbf4a5SMacpaul Lin
32b3dbf4a5SMacpaul Lin /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
33b3dbf4a5SMacpaul Lin #define PKTBUFSTX 4 /* must be power of 2 */
34b3dbf4a5SMacpaul Lin
35d0e0b84cSCédric Le Goater /* Timeout for transmit */
36d0e0b84cSCédric Le Goater #define FTGMAC100_TX_TIMEOUT_MS 1000
37d0e0b84cSCédric Le Goater
38538e75d3SCédric Le Goater /* Timeout for a mdio read/write operation */
39538e75d3SCédric Le Goater #define FTGMAC100_MDIO_TIMEOUT_USEC 10000
40538e75d3SCédric Le Goater
41538e75d3SCédric Le Goater /*
42538e75d3SCédric Le Goater * MDC clock cycle threshold
43538e75d3SCédric Le Goater *
44538e75d3SCédric Le Goater * 20us * 100 = 2ms > (1 / 2.5Mhz) * 0x34
45538e75d3SCédric Le Goater */
46538e75d3SCédric Le Goater #define MDC_CYCTHR 0x34
47538e75d3SCédric Le Goater
48e6ddacc2SCédric Le Goater /*
49e6ddacc2SCédric Le Goater * ftgmac100 model variants
50e6ddacc2SCédric Le Goater */
51e6ddacc2SCédric Le Goater enum ftgmac100_model {
52e6ddacc2SCédric Le Goater FTGMAC100_MODEL_FARADAY,
53e6ddacc2SCédric Le Goater FTGMAC100_MODEL_ASPEED,
54176338f1Sryan_chen FTGMAC100_MODEL_NEW_ASPEED,
55e6ddacc2SCédric Le Goater };
56e6ddacc2SCédric Le Goater
57f95de0bdSCédric Le Goater /**
58f95de0bdSCédric Le Goater * struct ftgmac100_data - private data for the FTGMAC100 driver
59f95de0bdSCédric Le Goater *
60f95de0bdSCédric Le Goater * @iobase: The base address of the hardware registers
61f95de0bdSCédric Le Goater * @txdes: The array of transmit descriptors
62f95de0bdSCédric Le Goater * @rxdes: The array of receive descriptors
63f95de0bdSCédric Le Goater * @tx_index: Transmit descriptor index in @txdes
64f95de0bdSCédric Le Goater * @rx_index: Receive descriptor index in @rxdes
65f95de0bdSCédric Le Goater * @phy_addr: The PHY interface address to use
66538e75d3SCédric Le Goater * @phydev: The PHY device backing the MAC
67538e75d3SCédric Le Goater * @bus: The mdio bus
68538e75d3SCédric Le Goater * @phy_mode: The mode of the PHY interface (rgmii, rmii, ...)
69538e75d3SCédric Le Goater * @max_speed: Maximum speed of Ethernet connection supported by MAC
701c0c61e9SCédric Le Goater * @clks: The bulk of clocks assigned to the device in the DT
71e6ddacc2SCédric Le Goater * @rxdes0_edorr_mask: The bit number identifying the end of the RX ring buffer
72e6ddacc2SCédric Le Goater * @txdes0_edotr_mask: The bit number identifying the end of the TX ring buffer
73f95de0bdSCédric Le Goater */
74b3dbf4a5SMacpaul Lin struct ftgmac100_data {
75f95de0bdSCédric Le Goater struct ftgmac100 *iobase;
76176338f1Sryan_chen fdt_addr_t mdio_addr; //for aspeed ast2600 new mdio
77f95de0bdSCédric Le Goater
78e7668497SCédric Le Goater struct ftgmac100_txdes txdes[PKTBUFSTX];
79e7668497SCédric Le Goater struct ftgmac100_rxdes rxdes[PKTBUFSRX];
80b3dbf4a5SMacpaul Lin int tx_index;
81b3dbf4a5SMacpaul Lin int rx_index;
82538e75d3SCédric Le Goater
83538e75d3SCédric Le Goater u32 phy_addr;
84538e75d3SCédric Le Goater struct phy_device *phydev;
85538e75d3SCédric Le Goater struct mii_dev *bus;
86538e75d3SCédric Le Goater u32 phy_mode;
87538e75d3SCédric Le Goater u32 max_speed;
889ab23354SDylan Hung bool ncsi_mode;
891c0c61e9SCédric Le Goater
901c0c61e9SCédric Le Goater struct clk_bulk clks;
91e6ddacc2SCédric Le Goater
92e6ddacc2SCédric Le Goater /* End of RX/TX ring buffer bits. Depend on model */
93e6ddacc2SCédric Le Goater u32 rxdes0_edorr_mask;
94e6ddacc2SCédric Le Goater u32 txdes0_edotr_mask;
95b3dbf4a5SMacpaul Lin };
96b3dbf4a5SMacpaul Lin
97b3dbf4a5SMacpaul Lin /*
98b3dbf4a5SMacpaul Lin * struct mii_bus functions
99b3dbf4a5SMacpaul Lin */
ftgmac100_mdio_read(struct mii_dev * bus,int phy_addr,int dev_addr,int reg_addr)100538e75d3SCédric Le Goater static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
101538e75d3SCédric Le Goater int reg_addr)
102b3dbf4a5SMacpaul Lin {
103538e75d3SCédric Le Goater struct ftgmac100_data *priv = bus->priv;
104f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
105b3dbf4a5SMacpaul Lin int phycr;
106538e75d3SCédric Le Goater int data;
107538e75d3SCédric Le Goater int ret;
108b3dbf4a5SMacpaul Lin
109538e75d3SCédric Le Goater phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
110538e75d3SCédric Le Goater FTGMAC100_PHYCR_PHYAD(phy_addr) |
111538e75d3SCédric Le Goater FTGMAC100_PHYCR_REGAD(reg_addr) |
112538e75d3SCédric Le Goater FTGMAC100_PHYCR_MIIRD;
113b3dbf4a5SMacpaul Lin writel(phycr, &ftgmac100->phycr);
114b3dbf4a5SMacpaul Lin
115538e75d3SCédric Le Goater ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
116538e75d3SCédric Le Goater !(phycr & FTGMAC100_PHYCR_MIIRD),
117538e75d3SCédric Le Goater FTGMAC100_MDIO_TIMEOUT_USEC);
118538e75d3SCédric Le Goater if (ret) {
119538e75d3SCédric Le Goater pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
12079c77598SZev Weiss bus->name, phy_addr, reg_addr);
121538e75d3SCédric Le Goater return ret;
122538e75d3SCédric Le Goater }
123b3dbf4a5SMacpaul Lin
124b3dbf4a5SMacpaul Lin data = readl(&ftgmac100->phydata);
125538e75d3SCédric Le Goater
126b3dbf4a5SMacpaul Lin return FTGMAC100_PHYDATA_MIIRDATA(data);
127b3dbf4a5SMacpaul Lin }
128b3dbf4a5SMacpaul Lin
ftgmac100_mdio_write(struct mii_dev * bus,int phy_addr,int dev_addr,int reg_addr,u16 value)129538e75d3SCédric Le Goater static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
130538e75d3SCédric Le Goater int reg_addr, u16 value)
131b3dbf4a5SMacpaul Lin {
132538e75d3SCédric Le Goater struct ftgmac100_data *priv = bus->priv;
133f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
134b3dbf4a5SMacpaul Lin int phycr;
135b3dbf4a5SMacpaul Lin int data;
136538e75d3SCédric Le Goater int ret;
137b3dbf4a5SMacpaul Lin
138538e75d3SCédric Le Goater phycr = FTGMAC100_PHYCR_MDC_CYCTHR(MDC_CYCTHR) |
139538e75d3SCédric Le Goater FTGMAC100_PHYCR_PHYAD(phy_addr) |
140538e75d3SCédric Le Goater FTGMAC100_PHYCR_REGAD(reg_addr) |
141538e75d3SCédric Le Goater FTGMAC100_PHYCR_MIIWR;
142b3dbf4a5SMacpaul Lin data = FTGMAC100_PHYDATA_MIIWDATA(value);
143b3dbf4a5SMacpaul Lin
144b3dbf4a5SMacpaul Lin writel(data, &ftgmac100->phydata);
145b3dbf4a5SMacpaul Lin writel(phycr, &ftgmac100->phycr);
146b3dbf4a5SMacpaul Lin
147538e75d3SCédric Le Goater ret = readl_poll_timeout(&ftgmac100->phycr, phycr,
148538e75d3SCédric Le Goater !(phycr & FTGMAC100_PHYCR_MIIWR),
149538e75d3SCédric Le Goater FTGMAC100_MDIO_TIMEOUT_USEC);
150538e75d3SCédric Le Goater if (ret) {
151538e75d3SCédric Le Goater pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
15279c77598SZev Weiss bus->name, phy_addr, reg_addr);
153b3dbf4a5SMacpaul Lin }
154b3dbf4a5SMacpaul Lin
155538e75d3SCédric Le Goater return ret;
156b3dbf4a5SMacpaul Lin }
157b3dbf4a5SMacpaul Lin
ftgmac100_mdio_init(struct udevice * dev)158538e75d3SCédric Le Goater static int ftgmac100_mdio_init(struct udevice *dev)
159b3dbf4a5SMacpaul Lin {
160538e75d3SCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
161538e75d3SCédric Le Goater struct mii_dev *bus;
162538e75d3SCédric Le Goater int ret;
163b3dbf4a5SMacpaul Lin
164538e75d3SCédric Le Goater bus = mdio_alloc();
165538e75d3SCédric Le Goater if (!bus)
166538e75d3SCédric Le Goater return -ENOMEM;
167538e75d3SCédric Le Goater
168176338f1Sryan_chen if(priv->mdio_addr) {
169176338f1Sryan_chen bus->read = aspeed_mdio_read;
170176338f1Sryan_chen bus->write = aspeed_mdio_write;
171516d4ba9Sryan_chen bus->priv = (void *)priv->mdio_addr;
172176338f1Sryan_chen } else {
173538e75d3SCédric Le Goater bus->read = ftgmac100_mdio_read;
174538e75d3SCédric Le Goater bus->write = ftgmac100_mdio_write;
175538e75d3SCédric Le Goater bus->priv = priv;
176516d4ba9Sryan_chen }
177538e75d3SCédric Le Goater
178538e75d3SCédric Le Goater ret = mdio_register_seq(bus, dev->seq);
179538e75d3SCédric Le Goater if (ret) {
180538e75d3SCédric Le Goater free(bus);
181538e75d3SCédric Le Goater return ret;
182538e75d3SCédric Le Goater }
183538e75d3SCédric Le Goater
184538e75d3SCédric Le Goater priv->bus = bus;
185b3dbf4a5SMacpaul Lin
186b3dbf4a5SMacpaul Lin return 0;
187b3dbf4a5SMacpaul Lin }
188b3dbf4a5SMacpaul Lin
ftgmac100_phy_adjust_link(struct ftgmac100_data * priv)189538e75d3SCédric Le Goater static int ftgmac100_phy_adjust_link(struct ftgmac100_data *priv)
190b3dbf4a5SMacpaul Lin {
191f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
192538e75d3SCédric Le Goater struct phy_device *phydev = priv->phydev;
193538e75d3SCédric Le Goater u32 maccr;
194b3dbf4a5SMacpaul Lin
1959ab23354SDylan Hung if (!phydev->link && !priv->ncsi_mode) {
196538e75d3SCédric Le Goater dev_err(phydev->dev, "No link\n");
197538e75d3SCédric Le Goater return -EREMOTEIO;
198538e75d3SCédric Le Goater }
199b3dbf4a5SMacpaul Lin
200b3dbf4a5SMacpaul Lin /* read MAC control register and clear related bits */
201b3dbf4a5SMacpaul Lin maccr = readl(&ftgmac100->maccr) &
202b3dbf4a5SMacpaul Lin ~(FTGMAC100_MACCR_GIGA_MODE |
203b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_FAST_MODE |
204b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_FULLDUP);
205b3dbf4a5SMacpaul Lin
206538e75d3SCédric Le Goater if (phy_interface_is_rgmii(phydev) && phydev->speed == 1000)
207b3dbf4a5SMacpaul Lin maccr |= FTGMAC100_MACCR_GIGA_MODE;
208b3dbf4a5SMacpaul Lin
209538e75d3SCédric Le Goater if (phydev->speed == 100)
210b3dbf4a5SMacpaul Lin maccr |= FTGMAC100_MACCR_FAST_MODE;
211b3dbf4a5SMacpaul Lin
212538e75d3SCédric Le Goater if (phydev->duplex)
213538e75d3SCédric Le Goater maccr |= FTGMAC100_MACCR_FULLDUP;
214b3dbf4a5SMacpaul Lin
215b3dbf4a5SMacpaul Lin /* update MII config into maccr */
216b3dbf4a5SMacpaul Lin writel(maccr, &ftgmac100->maccr);
217b3dbf4a5SMacpaul Lin
218538e75d3SCédric Le Goater return 0;
219538e75d3SCédric Le Goater }
220538e75d3SCédric Le Goater
ftgmac100_phy_init(struct udevice * dev)221538e75d3SCédric Le Goater static int ftgmac100_phy_init(struct udevice *dev)
222538e75d3SCédric Le Goater {
223538e75d3SCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
224538e75d3SCédric Le Goater struct phy_device *phydev;
225538e75d3SCédric Le Goater int ret;
226538e75d3SCédric Le Goater
227538e75d3SCédric Le Goater phydev = phy_connect(priv->bus, priv->phy_addr, dev, priv->phy_mode);
228538e75d3SCédric Le Goater if (!phydev)
229538e75d3SCédric Le Goater return -ENODEV;
230538e75d3SCédric Le Goater
2319ab23354SDylan Hung if (!priv->ncsi_mode)
232538e75d3SCédric Le Goater phydev->supported &= PHY_GBIT_FEATURES;
233538e75d3SCédric Le Goater if (priv->max_speed) {
234538e75d3SCédric Le Goater ret = phy_set_supported(phydev, priv->max_speed);
235538e75d3SCédric Le Goater if (ret)
236538e75d3SCédric Le Goater return ret;
237538e75d3SCédric Le Goater }
238538e75d3SCédric Le Goater phydev->advertising = phydev->supported;
239538e75d3SCédric Le Goater priv->phydev = phydev;
240538e75d3SCédric Le Goater phy_config(phydev);
241538e75d3SCédric Le Goater
242538e75d3SCédric Le Goater return 0;
243b3dbf4a5SMacpaul Lin }
244b3dbf4a5SMacpaul Lin
245b3dbf4a5SMacpaul Lin /*
246b3dbf4a5SMacpaul Lin * Reset MAC
247b3dbf4a5SMacpaul Lin */
ftgmac100_reset(struct ftgmac100_data * priv)248f95de0bdSCédric Le Goater static void ftgmac100_reset(struct ftgmac100_data *priv)
249b3dbf4a5SMacpaul Lin {
250f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
251b3dbf4a5SMacpaul Lin
252b3dbf4a5SMacpaul Lin debug("%s()\n", __func__);
253b3dbf4a5SMacpaul Lin
254591ffd98SCédric Le Goater setbits_le32(&ftgmac100->maccr, FTGMAC100_MACCR_SW_RST);
255b3dbf4a5SMacpaul Lin
256b3dbf4a5SMacpaul Lin while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
257b3dbf4a5SMacpaul Lin ;
258b3dbf4a5SMacpaul Lin }
259b3dbf4a5SMacpaul Lin
260b3dbf4a5SMacpaul Lin /*
261b3dbf4a5SMacpaul Lin * Set MAC address
262b3dbf4a5SMacpaul Lin */
ftgmac100_set_mac(struct ftgmac100_data * priv,const unsigned char * mac)263f95de0bdSCédric Le Goater static int ftgmac100_set_mac(struct ftgmac100_data *priv,
264b3dbf4a5SMacpaul Lin const unsigned char *mac)
265b3dbf4a5SMacpaul Lin {
266f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
267b3dbf4a5SMacpaul Lin unsigned int maddr = mac[0] << 8 | mac[1];
268b3dbf4a5SMacpaul Lin unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
269b3dbf4a5SMacpaul Lin
270b3dbf4a5SMacpaul Lin debug("%s(%x %x)\n", __func__, maddr, laddr);
271b3dbf4a5SMacpaul Lin
272b3dbf4a5SMacpaul Lin writel(maddr, &ftgmac100->mac_madr);
273b3dbf4a5SMacpaul Lin writel(laddr, &ftgmac100->mac_ladr);
274b3dbf4a5SMacpaul Lin
275f95de0bdSCédric Le Goater return 0;
276b3dbf4a5SMacpaul Lin }
277b3dbf4a5SMacpaul Lin
278b3dbf4a5SMacpaul Lin /*
279b3dbf4a5SMacpaul Lin * disable transmitter, receiver
280b3dbf4a5SMacpaul Lin */
ftgmac100_stop(struct udevice * dev)281f95de0bdSCédric Le Goater static void ftgmac100_stop(struct udevice *dev)
282b3dbf4a5SMacpaul Lin {
283f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
284f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
285b3dbf4a5SMacpaul Lin
286b3dbf4a5SMacpaul Lin debug("%s()\n", __func__);
287b3dbf4a5SMacpaul Lin
288b3dbf4a5SMacpaul Lin writel(0, &ftgmac100->maccr);
289538e75d3SCédric Le Goater
2909ab23354SDylan Hung if (!priv->ncsi_mode)
291538e75d3SCédric Le Goater phy_shutdown(priv->phydev);
292b3dbf4a5SMacpaul Lin }
293b3dbf4a5SMacpaul Lin
ftgmac100_start(struct udevice * dev)294f95de0bdSCédric Le Goater static int ftgmac100_start(struct udevice *dev)
295b3dbf4a5SMacpaul Lin {
296f95de0bdSCédric Le Goater struct eth_pdata *plat = dev_get_platdata(dev);
297f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
298f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
299538e75d3SCédric Le Goater struct phy_device *phydev = priv->phydev;
300b3dbf4a5SMacpaul Lin unsigned int maccr;
301813df3e2SChia-Wei, Wang unsigned int dblac;
302e7668497SCédric Le Goater ulong start, end;
303813df3e2SChia-Wei, Wang size_t sz_txdes, sz_rxdes;
304538e75d3SCédric Le Goater int ret;
305b3dbf4a5SMacpaul Lin int i;
306b3dbf4a5SMacpaul Lin
307b3dbf4a5SMacpaul Lin debug("%s()\n", __func__);
308b3dbf4a5SMacpaul Lin
309f95de0bdSCédric Le Goater ftgmac100_reset(priv);
310f95de0bdSCédric Le Goater
311b3dbf4a5SMacpaul Lin /* set the ethernet address */
312f95de0bdSCédric Le Goater ftgmac100_set_mac(priv, plat->enetaddr);
313b3dbf4a5SMacpaul Lin
314b3dbf4a5SMacpaul Lin /* disable all interrupts */
315b3dbf4a5SMacpaul Lin writel(0, &ftgmac100->ier);
316b3dbf4a5SMacpaul Lin
317b3dbf4a5SMacpaul Lin /* initialize descriptors */
318b3dbf4a5SMacpaul Lin priv->tx_index = 0;
319b3dbf4a5SMacpaul Lin priv->rx_index = 0;
320b3dbf4a5SMacpaul Lin
321b3dbf4a5SMacpaul Lin for (i = 0; i < PKTBUFSTX; i++) {
322e7668497SCédric Le Goater priv->txdes[i].txdes3 = 0;
323e7668497SCédric Le Goater priv->txdes[i].txdes0 = 0;
324a8f9cd18SKuo-Jung Su }
325e6ddacc2SCédric Le Goater priv->txdes[PKTBUFSTX - 1].txdes0 = priv->txdes0_edotr_mask;
326e7668497SCédric Le Goater
327e7668497SCédric Le Goater start = (ulong)&priv->txdes[0];
328e7668497SCédric Le Goater end = start + roundup(sizeof(priv->txdes), ARCH_DMA_MINALIGN);
329e7668497SCédric Le Goater flush_dcache_range(start, end);
330b3dbf4a5SMacpaul Lin
331b3dbf4a5SMacpaul Lin for (i = 0; i < PKTBUFSRX; i++) {
332e7668497SCédric Le Goater priv->rxdes[i].rxdes3 = (unsigned int)net_rx_packets[i];
333e7668497SCédric Le Goater priv->rxdes[i].rxdes0 = 0;
334a8f9cd18SKuo-Jung Su }
335e6ddacc2SCédric Le Goater priv->rxdes[PKTBUFSRX - 1].rxdes0 = priv->rxdes0_edorr_mask;
336e7668497SCédric Le Goater
337e7668497SCédric Le Goater start = (ulong)&priv->rxdes[0];
338e7668497SCédric Le Goater end = start + roundup(sizeof(priv->rxdes), ARCH_DMA_MINALIGN);
339e7668497SCédric Le Goater flush_dcache_range(start, end);
340b3dbf4a5SMacpaul Lin
341b3dbf4a5SMacpaul Lin /* transmit ring */
342e7668497SCédric Le Goater writel((u32)priv->txdes, &ftgmac100->txr_badr);
343b3dbf4a5SMacpaul Lin
344b3dbf4a5SMacpaul Lin /* receive ring */
345e7668497SCédric Le Goater writel((u32)priv->rxdes, &ftgmac100->rxr_badr);
346b3dbf4a5SMacpaul Lin
347b3dbf4a5SMacpaul Lin /* poll receive descriptor automatically */
348b3dbf4a5SMacpaul Lin writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
349b3dbf4a5SMacpaul Lin
350b3dbf4a5SMacpaul Lin /* config receive buffer size register */
351e7668497SCédric Le Goater writel(FTGMAC100_RBSR_SIZE(FTGMAC100_RBSR_DEFAULT), &ftgmac100->rbsr);
352b3dbf4a5SMacpaul Lin
353813df3e2SChia-Wei, Wang /* config TX/RX descriptor size */
354813df3e2SChia-Wei, Wang sz_txdes = sizeof(struct ftgmac100_txdes);
355813df3e2SChia-Wei, Wang sz_rxdes = sizeof(struct ftgmac100_rxdes);
356813df3e2SChia-Wei, Wang if ((sz_txdes & 0xF) || (sz_rxdes & 0xF)) {
357813df3e2SChia-Wei, Wang dev_err(phydev->dev, "Descriptor size must be 16 bytes aligned\n");
358813df3e2SChia-Wei, Wang return -1;
359813df3e2SChia-Wei, Wang }
360813df3e2SChia-Wei, Wang dblac = ftgmac100->dblac;
361813df3e2SChia-Wei, Wang dblac &= ~(0xFF << 12);
362813df3e2SChia-Wei, Wang dblac |= ((sz_txdes >> 3) << 16);
363813df3e2SChia-Wei, Wang dblac |= ((sz_txdes >> 3) << 12);
364813df3e2SChia-Wei, Wang writel(dblac, &ftgmac100->dblac);
365813df3e2SChia-Wei, Wang
366b3dbf4a5SMacpaul Lin /* enable transmitter, receiver */
367b3dbf4a5SMacpaul Lin maccr = FTGMAC100_MACCR_TXMAC_EN |
368b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_RXMAC_EN |
369b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_TXDMA_EN |
370b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_RXDMA_EN |
371b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_CRC_APD |
372b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_FULLDUP |
373b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_RX_RUNT |
374b3dbf4a5SMacpaul Lin FTGMAC100_MACCR_RX_BROADPKT;
375b3dbf4a5SMacpaul Lin
376b3dbf4a5SMacpaul Lin writel(maccr, &ftgmac100->maccr);
377b3dbf4a5SMacpaul Lin
378538e75d3SCédric Le Goater ret = phy_startup(phydev);
379538e75d3SCédric Le Goater if (ret) {
380538e75d3SCédric Le Goater dev_err(phydev->dev, "Could not start PHY\n");
381538e75d3SCédric Le Goater return ret;
382b3dbf4a5SMacpaul Lin }
383b3dbf4a5SMacpaul Lin
384538e75d3SCédric Le Goater ret = ftgmac100_phy_adjust_link(priv);
385538e75d3SCédric Le Goater if (ret) {
386538e75d3SCédric Le Goater dev_err(phydev->dev, "Could not adjust link\n");
387538e75d3SCédric Le Goater return ret;
388538e75d3SCédric Le Goater }
389538e75d3SCédric Le Goater
390538e75d3SCédric Le Goater printf("%s: link up, %d Mbps %s-duplex mac:%pM\n", phydev->dev->name,
391538e75d3SCédric Le Goater phydev->speed, phydev->duplex ? "full" : "half", plat->enetaddr);
392538e75d3SCédric Le Goater
393b3dbf4a5SMacpaul Lin return 0;
394b3dbf4a5SMacpaul Lin }
395b3dbf4a5SMacpaul Lin
ftgmac100_free_pkt(struct udevice * dev,uchar * packet,int length)396f95de0bdSCédric Le Goater static int ftgmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
397f95de0bdSCédric Le Goater {
398f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
399f95de0bdSCédric Le Goater struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
400e7668497SCédric Le Goater ulong des_start = (ulong)curr_des;
401e7668497SCédric Le Goater ulong des_end = des_start +
402e7668497SCédric Le Goater roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
403f95de0bdSCédric Le Goater
404e7668497SCédric Le Goater /* Release buffer to DMA and flush descriptor */
405f95de0bdSCédric Le Goater curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
406e7668497SCédric Le Goater flush_dcache_range(des_start, des_end);
407f95de0bdSCédric Le Goater
408f95de0bdSCédric Le Goater /* Move to next descriptor */
409f95de0bdSCédric Le Goater priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
410f95de0bdSCédric Le Goater
411f95de0bdSCédric Le Goater return 0;
412f95de0bdSCédric Le Goater }
413f95de0bdSCédric Le Goater
414b3dbf4a5SMacpaul Lin /*
415b3dbf4a5SMacpaul Lin * Get a data block via Ethernet
416b3dbf4a5SMacpaul Lin */
ftgmac100_recv(struct udevice * dev,int flags,uchar ** packetp)417f95de0bdSCédric Le Goater static int ftgmac100_recv(struct udevice *dev, int flags, uchar **packetp)
418b3dbf4a5SMacpaul Lin {
419f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
420e7668497SCédric Le Goater struct ftgmac100_rxdes *curr_des = &priv->rxdes[priv->rx_index];
421b3dbf4a5SMacpaul Lin unsigned short rxlen;
422e7668497SCédric Le Goater ulong des_start = (ulong)curr_des;
423e7668497SCédric Le Goater ulong des_end = des_start +
424e7668497SCédric Le Goater roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
425e7668497SCédric Le Goater ulong data_start = curr_des->rxdes3;
426e7668497SCédric Le Goater ulong data_end;
427b3dbf4a5SMacpaul Lin
428e7668497SCédric Le Goater invalidate_dcache_range(des_start, des_end);
429b3dbf4a5SMacpaul Lin
430b3dbf4a5SMacpaul Lin if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
431e7668497SCédric Le Goater return -EAGAIN;
432b3dbf4a5SMacpaul Lin
433b3dbf4a5SMacpaul Lin if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
434b3dbf4a5SMacpaul Lin FTGMAC100_RXDES0_CRC_ERR |
435b3dbf4a5SMacpaul Lin FTGMAC100_RXDES0_FTL |
436b3dbf4a5SMacpaul Lin FTGMAC100_RXDES0_RUNT |
437b3dbf4a5SMacpaul Lin FTGMAC100_RXDES0_RX_ODD_NB)) {
438e7668497SCédric Le Goater return -EAGAIN;
439b3dbf4a5SMacpaul Lin }
440b3dbf4a5SMacpaul Lin
441b3dbf4a5SMacpaul Lin rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
442b3dbf4a5SMacpaul Lin
443b3dbf4a5SMacpaul Lin debug("%s(): RX buffer %d, %x received\n",
444b3dbf4a5SMacpaul Lin __func__, priv->rx_index, rxlen);
445b3dbf4a5SMacpaul Lin
446e7668497SCédric Le Goater /* Invalidate received data */
447e7668497SCédric Le Goater data_end = data_start + roundup(rxlen, ARCH_DMA_MINALIGN);
448e7668497SCédric Le Goater invalidate_dcache_range(data_start, data_end);
449e7668497SCédric Le Goater *packetp = (uchar *)data_start;
450a8f9cd18SKuo-Jung Su
451e7668497SCédric Le Goater return rxlen;
452b3dbf4a5SMacpaul Lin }
453b3dbf4a5SMacpaul Lin
ftgmac100_read_txdesc(const void * desc)454d0e0b84cSCédric Le Goater static u32 ftgmac100_read_txdesc(const void *desc)
455d0e0b84cSCédric Le Goater {
456d0e0b84cSCédric Le Goater const struct ftgmac100_txdes *txdes = desc;
457d0e0b84cSCédric Le Goater ulong des_start = (ulong)txdes;
458d0e0b84cSCédric Le Goater ulong des_end = des_start + roundup(sizeof(*txdes), ARCH_DMA_MINALIGN);
459d0e0b84cSCédric Le Goater
460d0e0b84cSCédric Le Goater invalidate_dcache_range(des_start, des_end);
461d0e0b84cSCédric Le Goater
462d0e0b84cSCédric Le Goater return txdes->txdes0;
463d0e0b84cSCédric Le Goater }
464d0e0b84cSCédric Le Goater
BUILD_WAIT_FOR_BIT(ftgmac100_txdone,u32,ftgmac100_read_txdesc)465d0e0b84cSCédric Le Goater BUILD_WAIT_FOR_BIT(ftgmac100_txdone, u32, ftgmac100_read_txdesc)
466d0e0b84cSCédric Le Goater
467b3dbf4a5SMacpaul Lin /*
468b3dbf4a5SMacpaul Lin * Send a data block via Ethernet
469b3dbf4a5SMacpaul Lin */
470f95de0bdSCédric Le Goater static int ftgmac100_send(struct udevice *dev, void *packet, int length)
471b3dbf4a5SMacpaul Lin {
472f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
473f95de0bdSCédric Le Goater struct ftgmac100 *ftgmac100 = priv->iobase;
474b3dbf4a5SMacpaul Lin struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
475e7668497SCédric Le Goater ulong des_start = (ulong)curr_des;
476e7668497SCédric Le Goater ulong des_end = des_start +
477e7668497SCédric Le Goater roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
478e7668497SCédric Le Goater ulong data_start;
479e7668497SCédric Le Goater ulong data_end;
480d0e0b84cSCédric Le Goater int rc;
481e7668497SCédric Le Goater
482e7668497SCédric Le Goater invalidate_dcache_range(des_start, des_end);
483b3dbf4a5SMacpaul Lin
484b3dbf4a5SMacpaul Lin if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
485e7668497SCédric Le Goater dev_err(dev, "no TX descriptor available\n");
486e7668497SCédric Le Goater return -EPERM;
487b3dbf4a5SMacpaul Lin }
488b3dbf4a5SMacpaul Lin
489*4298c59cSDylan Hung debug("%s(%p, %x)\n", __func__, packet, length);
490b3dbf4a5SMacpaul Lin
491b3dbf4a5SMacpaul Lin length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
492b3dbf4a5SMacpaul Lin
493e7668497SCédric Le Goater curr_des->txdes3 = (unsigned int)packet;
494b3dbf4a5SMacpaul Lin
495e7668497SCédric Le Goater /* Flush data to be sent */
496e7668497SCédric Le Goater data_start = curr_des->txdes3;
497e7668497SCédric Le Goater data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
498e7668497SCédric Le Goater flush_dcache_range(data_start, data_end);
499e7668497SCédric Le Goater
500e7668497SCédric Le Goater /* Only one segment on TXBUF */
501e6ddacc2SCédric Le Goater curr_des->txdes0 &= priv->txdes0_edotr_mask;
502b3dbf4a5SMacpaul Lin curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
503b3dbf4a5SMacpaul Lin FTGMAC100_TXDES0_LTS |
504b3dbf4a5SMacpaul Lin FTGMAC100_TXDES0_TXBUF_SIZE(length) |
505b3dbf4a5SMacpaul Lin FTGMAC100_TXDES0_TXDMA_OWN ;
506b3dbf4a5SMacpaul Lin
507e7668497SCédric Le Goater /* Flush modified buffer descriptor */
508e7668497SCédric Le Goater flush_dcache_range(des_start, des_end);
509e7668497SCédric Le Goater
510e7668497SCédric Le Goater /* Start transmit */
511b3dbf4a5SMacpaul Lin writel(1, &ftgmac100->txpd);
512b3dbf4a5SMacpaul Lin
513d0e0b84cSCédric Le Goater rc = wait_for_bit_ftgmac100_txdone(curr_des,
514d0e0b84cSCédric Le Goater FTGMAC100_TXDES0_TXDMA_OWN, false,
515d0e0b84cSCédric Le Goater FTGMAC100_TX_TIMEOUT_MS, true);
516d0e0b84cSCédric Le Goater if (rc)
517d0e0b84cSCédric Le Goater return rc;
518d0e0b84cSCédric Le Goater
519b3dbf4a5SMacpaul Lin debug("%s(): packet sent\n", __func__);
520b3dbf4a5SMacpaul Lin
521e7668497SCédric Le Goater /* Move to next descriptor */
522b3dbf4a5SMacpaul Lin priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
523b3dbf4a5SMacpaul Lin
524b3dbf4a5SMacpaul Lin return 0;
525b3dbf4a5SMacpaul Lin }
526b3dbf4a5SMacpaul Lin
ftgmac100_write_hwaddr(struct udevice * dev)527f95de0bdSCédric Le Goater static int ftgmac100_write_hwaddr(struct udevice *dev)
528b3dbf4a5SMacpaul Lin {
529f95de0bdSCédric Le Goater struct eth_pdata *pdata = dev_get_platdata(dev);
530f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
531b3dbf4a5SMacpaul Lin
532f95de0bdSCédric Le Goater return ftgmac100_set_mac(priv, pdata->enetaddr);
533b3dbf4a5SMacpaul Lin }
534b3dbf4a5SMacpaul Lin
ftgmac100_ofdata_to_platdata(struct udevice * dev)535f95de0bdSCédric Le Goater static int ftgmac100_ofdata_to_platdata(struct udevice *dev)
536f95de0bdSCédric Le Goater {
537f95de0bdSCédric Le Goater struct eth_pdata *pdata = dev_get_platdata(dev);
5381c0c61e9SCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
539538e75d3SCédric Le Goater const char *phy_mode;
540785eb4e9SDylan Hung int offset = 0;
541b3dbf4a5SMacpaul Lin
542f95de0bdSCédric Le Goater pdata->iobase = devfdt_get_addr(dev);
543538e75d3SCédric Le Goater pdata->phy_interface = -1;
544538e75d3SCédric Le Goater phy_mode = dev_read_string(dev, "phy-mode");
5459ab23354SDylan Hung
546538e75d3SCédric Le Goater if (phy_mode)
547538e75d3SCédric Le Goater pdata->phy_interface = phy_get_interface_by_name(phy_mode);
548538e75d3SCédric Le Goater if (pdata->phy_interface == -1) {
549538e75d3SCédric Le Goater dev_err(dev, "Invalid PHY interface '%s'\n", phy_mode);
550538e75d3SCédric Le Goater return -EINVAL;
551538e75d3SCédric Le Goater }
552538e75d3SCédric Le Goater
553785eb4e9SDylan Hung offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
554785eb4e9SDylan Hung "phy-handle");
555785eb4e9SDylan Hung if (offset > 0) {
556785eb4e9SDylan Hung priv->phy_addr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
557785eb4e9SDylan Hung } else {
558785eb4e9SDylan Hung priv->phy_addr = 0;
559785eb4e9SDylan Hung }
560785eb4e9SDylan Hung
561538e75d3SCédric Le Goater pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
562538e75d3SCédric Le Goater
563176338f1Sryan_chen if (dev_get_driver_data(dev) == FTGMAC100_MODEL_NEW_ASPEED) {
564176338f1Sryan_chen priv->mdio_addr = devfdt_get_addr_index(dev, 1);
565516d4ba9Sryan_chen debug("priv->mdio_addr %x \n", (u32)priv->mdio_addr);
566176338f1Sryan_chen
567176338f1Sryan_chen }
568176338f1Sryan_chen if ((dev_get_driver_data(dev) == FTGMAC100_MODEL_ASPEED) ||
569176338f1Sryan_chen (dev_get_driver_data(dev) == FTGMAC100_MODEL_NEW_ASPEED)){
570e6ddacc2SCédric Le Goater priv->rxdes0_edorr_mask = BIT(30);
571e6ddacc2SCédric Le Goater priv->txdes0_edotr_mask = BIT(30);
572e6ddacc2SCédric Le Goater } else {
573e6ddacc2SCédric Le Goater priv->rxdes0_edorr_mask = BIT(15);
574e6ddacc2SCédric Le Goater priv->txdes0_edotr_mask = BIT(15);
575e6ddacc2SCédric Le Goater }
576e6ddacc2SCédric Le Goater
5771c0c61e9SCédric Le Goater return clk_get_bulk(dev, &priv->clks);
578b3dbf4a5SMacpaul Lin }
579f95de0bdSCédric Le Goater
ftgmac100_probe(struct udevice * dev)580f95de0bdSCédric Le Goater static int ftgmac100_probe(struct udevice *dev)
581f95de0bdSCédric Le Goater {
582f95de0bdSCédric Le Goater struct eth_pdata *pdata = dev_get_platdata(dev);
583f95de0bdSCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
5849ab23354SDylan Hung const char *phy_mode;
585538e75d3SCédric Le Goater int ret;
586f95de0bdSCédric Le Goater
5879ab23354SDylan Hung phy_mode = dev_read_string(dev, "phy-mode");
5889ab23354SDylan Hung priv->ncsi_mode = dev_read_bool(dev, "use-ncsi") ||
5899ab23354SDylan Hung (phy_mode && strcmp(phy_mode, "NC-SI") == 0);
5909ab23354SDylan Hung
591f95de0bdSCédric Le Goater priv->iobase = (struct ftgmac100 *)pdata->iobase;
592538e75d3SCédric Le Goater priv->phy_mode = pdata->phy_interface;
593538e75d3SCédric Le Goater priv->max_speed = pdata->max_speed;
594538e75d3SCédric Le Goater
5951c0c61e9SCédric Le Goater ret = clk_enable_bulk(&priv->clks);
5961c0c61e9SCédric Le Goater if (ret)
5971c0c61e9SCédric Le Goater goto out;
5981c0c61e9SCédric Le Goater
5999ab23354SDylan Hung if (priv->ncsi_mode) {
600c2963734SJoel Stanley if (!IS_ENABLED(CONFIG_PHY_NCSI)) {
601c2963734SJoel Stanley dev_err(dev,
602c2963734SJoel Stanley "ftgmac100: NCSI in dts but CONFIG_PHY_NCSI missing. Please fix config\n");
603c2963734SJoel Stanley return -EINVAL;
604c2963734SJoel Stanley }
605c2963734SJoel Stanley
6069ab23354SDylan Hung printf("%s - NCSI detected\n", __func__);
6079ab23354SDylan Hung } else {
608538e75d3SCédric Le Goater ret = ftgmac100_mdio_init(dev);
609538e75d3SCédric Le Goater if (ret) {
610538e75d3SCédric Le Goater dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
611538e75d3SCédric Le Goater goto out;
612538e75d3SCédric Le Goater }
613538e75d3SCédric Le Goater
6149ab23354SDylan Hung }
6159ab23354SDylan Hung
616538e75d3SCédric Le Goater ret = ftgmac100_phy_init(dev);
617538e75d3SCédric Le Goater if (ret) {
618538e75d3SCédric Le Goater dev_err(dev, "Failed to initialize PHY: %d\n", ret);
619538e75d3SCédric Le Goater goto out;
620538e75d3SCédric Le Goater }
621538e75d3SCédric Le Goater
622538e75d3SCédric Le Goater out:
6231c0c61e9SCédric Le Goater if (ret)
6241c0c61e9SCédric Le Goater clk_release_bulk(&priv->clks);
6251c0c61e9SCédric Le Goater
626538e75d3SCédric Le Goater return ret;
627f95de0bdSCédric Le Goater }
628f95de0bdSCédric Le Goater
ftgmac100_remove(struct udevice * dev)629f95de0bdSCédric Le Goater static int ftgmac100_remove(struct udevice *dev)
630f95de0bdSCédric Le Goater {
631538e75d3SCédric Le Goater struct ftgmac100_data *priv = dev_get_priv(dev);
632538e75d3SCédric Le Goater
6339ab23354SDylan Hung if (!priv->ncsi_mode) {
634538e75d3SCédric Le Goater free(priv->phydev);
635538e75d3SCédric Le Goater mdio_unregister(priv->bus);
636538e75d3SCédric Le Goater mdio_free(priv->bus);
6379ab23354SDylan Hung } else {
6389ab23354SDylan Hung free(priv->phydev);
6399ab23354SDylan Hung }
6401c0c61e9SCédric Le Goater clk_release_bulk(&priv->clks);
641538e75d3SCédric Le Goater
642f95de0bdSCédric Le Goater return 0;
643f95de0bdSCédric Le Goater }
644f95de0bdSCédric Le Goater
645f95de0bdSCédric Le Goater static const struct eth_ops ftgmac100_ops = {
646f95de0bdSCédric Le Goater .start = ftgmac100_start,
647f95de0bdSCédric Le Goater .send = ftgmac100_send,
648f95de0bdSCédric Le Goater .recv = ftgmac100_recv,
649f95de0bdSCédric Le Goater .stop = ftgmac100_stop,
650f95de0bdSCédric Le Goater .free_pkt = ftgmac100_free_pkt,
651f95de0bdSCédric Le Goater .write_hwaddr = ftgmac100_write_hwaddr,
652f95de0bdSCédric Le Goater };
653f95de0bdSCédric Le Goater
654f95de0bdSCédric Le Goater static const struct udevice_id ftgmac100_ids[] = {
655e6ddacc2SCédric Le Goater { .compatible = "faraday,ftgmac100", .data = FTGMAC100_MODEL_FARADAY },
656468f3913Sryan_chen { .compatible = "aspeed,ast2400-mac", .data = FTGMAC100_MODEL_ASPEED },
657e6ddacc2SCédric Le Goater { .compatible = "aspeed,ast2500-mac", .data = FTGMAC100_MODEL_ASPEED },
658176338f1Sryan_chen { .compatible = "aspeed,ast2600-mac", .data = FTGMAC100_MODEL_NEW_ASPEED },
659f95de0bdSCédric Le Goater { }
660f95de0bdSCédric Le Goater };
661f95de0bdSCédric Le Goater
662f95de0bdSCédric Le Goater U_BOOT_DRIVER(ftgmac100) = {
663f95de0bdSCédric Le Goater .name = "ftgmac100",
664f95de0bdSCédric Le Goater .id = UCLASS_ETH,
665f95de0bdSCédric Le Goater .of_match = ftgmac100_ids,
666f95de0bdSCédric Le Goater .ofdata_to_platdata = ftgmac100_ofdata_to_platdata,
667f95de0bdSCédric Le Goater .probe = ftgmac100_probe,
668f95de0bdSCédric Le Goater .remove = ftgmac100_remove,
669f95de0bdSCédric Le Goater .ops = &ftgmac100_ops,
670f95de0bdSCédric Le Goater .priv_auto_alloc_size = sizeof(struct ftgmac100_data),
671f95de0bdSCédric Le Goater .platdata_auto_alloc_size = sizeof(struct eth_pdata),
672f95de0bdSCédric Le Goater .flags = DM_FLAG_ALLOC_PRIV_DMA,
673f95de0bdSCédric Le Goater };
674