xref: /openbmc/u-boot/drivers/net/ftgmac100.c (revision 4298c59c)
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