blob: 09ea586e071e66e93ee85763a4e2c0ee35042e98 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Amit Singh Tomard194c0e2016-07-06 17:59:44 +05302/*
3 * (C) Copyright 2016
4 * Author: Amit Singh Tomar, amittomer25@gmail.com
5 *
Amit Singh Tomard194c0e2016-07-06 17:59:44 +05306 * Ethernet driver for H3/A64/A83T based SoC's
7 *
8 * It is derived from the work done by
9 * LABBE Corentin & Chen-Yu Tsai for Linux, THANKS!
10 *
11*/
12
Simon Glass63334482019-11-14 12:57:39 -070013#include <cpu_func.h>
Simon Glass274e0b02020-05-10 11:39:56 -060014#include <asm/cache.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053015#include <asm/io.h>
16#include <asm/arch/clock.h>
17#include <asm/arch/gpio.h>
18#include <common.h>
Jagan Tekicb63d282019-02-28 00:26:58 +053019#include <clk.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053020#include <dm.h>
21#include <fdt_support.h>
Simon Glass9bc15642020-02-03 07:36:16 -070022#include <dm/device_compat.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053023#include <linux/err.h>
24#include <malloc.h>
25#include <miiphy.h>
26#include <net.h>
Jagan Tekicb63d282019-02-28 00:26:58 +053027#include <reset.h>
Andre Przywara26e549b2018-04-04 01:31:15 +010028#include <dt-bindings/pinctrl/sun4i-a10.h>
Simon Glassfa4689a2019-12-06 21:41:35 -070029#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +010030#include <asm-generic/gpio.h>
31#endif
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053032
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053033#define MDIO_CMD_MII_BUSY BIT(0)
34#define MDIO_CMD_MII_WRITE BIT(1)
35
36#define MDIO_CMD_MII_PHY_REG_ADDR_MASK 0x000001f0
37#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4
38#define MDIO_CMD_MII_PHY_ADDR_MASK 0x0001f000
39#define MDIO_CMD_MII_PHY_ADDR_SHIFT 12
40
41#define CONFIG_TX_DESCR_NUM 32
42#define CONFIG_RX_DESCR_NUM 32
Hans de Goedefcdb3b32016-07-27 17:31:17 +020043#define CONFIG_ETH_BUFSIZE 2048 /* Note must be dma aligned */
44
45/*
46 * The datasheet says that each descriptor can transfers up to 4096 bytes
47 * But later, the register documentation reduces that value to 2048,
48 * using 2048 cause strange behaviours and even BSP driver use 2047
49 */
50#define CONFIG_ETH_RXSIZE 2044 /* Note must fit in ETH_BUFSIZE */
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053051
52#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
53#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
54
55#define H3_EPHY_DEFAULT_VALUE 0x58000
56#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15)
57#define H3_EPHY_ADDR_SHIFT 20
58#define REG_PHY_ADDR_MASK GENMASK(4, 0)
59#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */
60#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */
61#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */
62
63#define SC_RMII_EN BIT(13)
64#define SC_EPIT BIT(2) /* 1: RGMII, 0: MII */
65#define SC_ETCS_MASK GENMASK(1, 0)
66#define SC_ETCS_EXT_GMII 0x1
67#define SC_ETCS_INT_GMII 0x2
Icenowy Zheng525dc442018-11-23 00:37:48 +010068#define SC_ETXDC_MASK GENMASK(12, 10)
69#define SC_ETXDC_OFFSET 10
70#define SC_ERXDC_MASK GENMASK(9, 5)
71#define SC_ERXDC_OFFSET 5
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053072
73#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
74
75#define AHB_GATE_OFFSET_EPHY 0
76
Lothar Feltenacb9a5b2018-07-13 10:45:27 +020077/* IO mux settings */
78#define SUN8I_IOMUX_H3 2
Lothar Feltene8cbced2018-07-13 10:45:28 +020079#define SUN8I_IOMUX_R40 5
Lothar Feltenacb9a5b2018-07-13 10:45:27 +020080#define SUN8I_IOMUX 4
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053081
82/* H3/A64 EMAC Register's offset */
83#define EMAC_CTL0 0x00
84#define EMAC_CTL1 0x04
85#define EMAC_INT_STA 0x08
86#define EMAC_INT_EN 0x0c
87#define EMAC_TX_CTL0 0x10
88#define EMAC_TX_CTL1 0x14
89#define EMAC_TX_FLOW_CTL 0x1c
90#define EMAC_TX_DMA_DESC 0x20
91#define EMAC_RX_CTL0 0x24
92#define EMAC_RX_CTL1 0x28
93#define EMAC_RX_DMA_DESC 0x34
94#define EMAC_MII_CMD 0x48
95#define EMAC_MII_DATA 0x4c
96#define EMAC_ADDR0_HIGH 0x50
97#define EMAC_ADDR0_LOW 0x54
98#define EMAC_TX_DMA_STA 0xb0
99#define EMAC_TX_CUR_DESC 0xb4
100#define EMAC_TX_CUR_BUF 0xb8
101#define EMAC_RX_DMA_STA 0xc0
102#define EMAC_RX_CUR_DESC 0xc4
103
104DECLARE_GLOBAL_DATA_PTR;
105
106enum emac_variant {
107 A83T_EMAC = 1,
108 H3_EMAC,
109 A64_EMAC,
Lothar Feltene8cbced2018-07-13 10:45:28 +0200110 R40_GMAC,
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530111};
112
113struct emac_dma_desc {
114 u32 status;
115 u32 st;
116 u32 buf_addr;
117 u32 next;
118} __aligned(ARCH_DMA_MINALIGN);
119
120struct emac_eth_dev {
121 struct emac_dma_desc rx_chain[CONFIG_TX_DESCR_NUM];
122 struct emac_dma_desc tx_chain[CONFIG_RX_DESCR_NUM];
123 char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
124 char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
125
126 u32 interface;
127 u32 phyaddr;
128 u32 link;
129 u32 speed;
130 u32 duplex;
131 u32 phy_configured;
132 u32 tx_currdescnum;
133 u32 rx_currdescnum;
134 u32 addr;
135 u32 tx_slot;
136 bool use_internal_phy;
137
138 enum emac_variant variant;
139 void *mac_reg;
140 phys_addr_t sysctl_reg;
141 struct phy_device *phydev;
142 struct mii_dev *bus;
Jagan Tekicb63d282019-02-28 00:26:58 +0530143 struct clk tx_clk;
Jagan Teki727ed792019-02-28 00:27:00 +0530144 struct clk ephy_clk;
Jagan Tekicb63d282019-02-28 00:26:58 +0530145 struct reset_ctl tx_rst;
Jagan Teki727ed792019-02-28 00:27:00 +0530146 struct reset_ctl ephy_rst;
Simon Glassfa4689a2019-12-06 21:41:35 -0700147#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100148 struct gpio_desc reset_gpio;
149#endif
150};
151
152
153struct sun8i_eth_pdata {
154 struct eth_pdata eth_pdata;
155 u32 reset_delays[3];
Icenowy Zheng525dc442018-11-23 00:37:48 +0100156 int tx_delay_ps;
157 int rx_delay_ps;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530158};
159
Philipp Tomsich3297b552017-02-22 19:46:41 +0100160
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530161static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
162{
Philipp Tomsich3297b552017-02-22 19:46:41 +0100163 struct udevice *dev = bus->priv;
164 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530165 ulong start;
166 u32 miiaddr = 0;
167 int timeout = CONFIG_MDIO_TIMEOUT;
168
169 miiaddr &= ~MDIO_CMD_MII_WRITE;
170 miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
171 miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
172 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
173
174 miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
175
176 miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
177 MDIO_CMD_MII_PHY_ADDR_MASK;
178
179 miiaddr |= MDIO_CMD_MII_BUSY;
180
181 writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
182
183 start = get_timer(0);
184 while (get_timer(start) < timeout) {
185 if (!(readl(priv->mac_reg + EMAC_MII_CMD) & MDIO_CMD_MII_BUSY))
186 return readl(priv->mac_reg + EMAC_MII_DATA);
187 udelay(10);
188 };
189
190 return -1;
191}
192
193static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
194 u16 val)
195{
Philipp Tomsich3297b552017-02-22 19:46:41 +0100196 struct udevice *dev = bus->priv;
197 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530198 ulong start;
199 u32 miiaddr = 0;
200 int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
201
202 miiaddr &= ~MDIO_CMD_MII_PHY_REG_ADDR_MASK;
203 miiaddr |= (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
204 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
205
206 miiaddr &= ~MDIO_CMD_MII_PHY_ADDR_MASK;
207 miiaddr |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
208 MDIO_CMD_MII_PHY_ADDR_MASK;
209
210 miiaddr |= MDIO_CMD_MII_WRITE;
211 miiaddr |= MDIO_CMD_MII_BUSY;
212
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530213 writel(val, priv->mac_reg + EMAC_MII_DATA);
Philipp Tomsich2b6dee12016-11-16 01:40:27 +0000214 writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530215
216 start = get_timer(0);
217 while (get_timer(start) < timeout) {
218 if (!(readl(priv->mac_reg + EMAC_MII_CMD) &
219 MDIO_CMD_MII_BUSY)) {
220 ret = 0;
221 break;
222 }
223 udelay(10);
224 };
225
226 return ret;
227}
228
229static int _sun8i_write_hwaddr(struct emac_eth_dev *priv, u8 *mac_id)
230{
231 u32 macid_lo, macid_hi;
232
233 macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
234 (mac_id[3] << 24);
235 macid_hi = mac_id[4] + (mac_id[5] << 8);
236
237 writel(macid_hi, priv->mac_reg + EMAC_ADDR0_HIGH);
238 writel(macid_lo, priv->mac_reg + EMAC_ADDR0_LOW);
239
240 return 0;
241}
242
243static void sun8i_adjust_link(struct emac_eth_dev *priv,
244 struct phy_device *phydev)
245{
246 u32 v;
247
248 v = readl(priv->mac_reg + EMAC_CTL0);
249
250 if (phydev->duplex)
251 v |= BIT(0);
252 else
253 v &= ~BIT(0);
254
255 v &= ~0x0C;
256
257 switch (phydev->speed) {
258 case 1000:
259 break;
260 case 100:
261 v |= BIT(2);
262 v |= BIT(3);
263 break;
264 case 10:
265 v |= BIT(3);
266 break;
267 }
268 writel(v, priv->mac_reg + EMAC_CTL0);
269}
270
271static int sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 *reg)
272{
273 if (priv->use_internal_phy) {
274 /* H3 based SoC's that has an Internal 100MBit PHY
275 * needs to be configured and powered up before use
276 */
277 *reg &= ~H3_EPHY_DEFAULT_MASK;
278 *reg |= H3_EPHY_DEFAULT_VALUE;
279 *reg |= priv->phyaddr << H3_EPHY_ADDR_SHIFT;
280 *reg &= ~H3_EPHY_SHUTDOWN;
281 *reg |= H3_EPHY_SELECT;
282 } else
283 /* This is to select External Gigabit PHY on
284 * the boards with H3 SoC.
285 */
286 *reg &= ~H3_EPHY_SELECT;
287
288 return 0;
289}
290
Icenowy Zheng525dc442018-11-23 00:37:48 +0100291static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
292 struct emac_eth_dev *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530293{
294 int ret;
295 u32 reg;
296
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530297 if (priv->variant == R40_GMAC) {
298 /* Select RGMII for R40 */
299 reg = readl(priv->sysctl_reg + 0x164);
300 reg |= CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII |
301 CCM_GMAC_CTRL_GPIT_RGMII |
302 CCM_GMAC_CTRL_TX_CLK_DELAY(CONFIG_GMAC_TX_DELAY);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530303
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530304 writel(reg, priv->sysctl_reg + 0x164);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200305 return 0;
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530306 }
307
308 reg = readl(priv->sysctl_reg + 0x30);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200309
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530310 if (priv->variant == H3_EMAC) {
311 ret = sun8i_emac_set_syscon_ephy(priv, &reg);
312 if (ret)
313 return ret;
314 }
315
316 reg &= ~(SC_ETCS_MASK | SC_EPIT);
317 if (priv->variant == H3_EMAC || priv->variant == A64_EMAC)
318 reg &= ~SC_RMII_EN;
319
320 switch (priv->interface) {
321 case PHY_INTERFACE_MODE_MII:
322 /* default */
323 break;
324 case PHY_INTERFACE_MODE_RGMII:
325 reg |= SC_EPIT | SC_ETCS_INT_GMII;
326 break;
327 case PHY_INTERFACE_MODE_RMII:
328 if (priv->variant == H3_EMAC ||
329 priv->variant == A64_EMAC) {
330 reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
331 break;
332 }
333 /* RMII not supported on A83T */
334 default:
335 debug("%s: Invalid PHY interface\n", __func__);
336 return -EINVAL;
337 }
338
Icenowy Zheng525dc442018-11-23 00:37:48 +0100339 if (pdata->tx_delay_ps)
340 reg |= ((pdata->tx_delay_ps / 100) << SC_ETXDC_OFFSET)
341 & SC_ETXDC_MASK;
342
343 if (pdata->rx_delay_ps)
344 reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
345 & SC_ERXDC_MASK;
346
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100347 writel(reg, priv->sysctl_reg + 0x30);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530348
349 return 0;
350}
351
352static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev)
353{
354 struct phy_device *phydev;
355
356 phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
357 if (!phydev)
358 return -ENODEV;
359
360 phy_connect_dev(phydev, dev);
361
362 priv->phydev = phydev;
363 phy_config(priv->phydev);
364
365 return 0;
366}
367
368static void rx_descs_init(struct emac_eth_dev *priv)
369{
370 struct emac_dma_desc *desc_table_p = &priv->rx_chain[0];
371 char *rxbuffs = &priv->rxbuffer[0];
372 struct emac_dma_desc *desc_p;
373 u32 idx;
374
375 /* flush Rx buffers */
376 flush_dcache_range((uintptr_t)rxbuffs, (ulong)rxbuffs +
377 RX_TOTAL_BUFSIZE);
378
379 for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
380 desc_p = &desc_table_p[idx];
381 desc_p->buf_addr = (uintptr_t)&rxbuffs[idx * CONFIG_ETH_BUFSIZE]
382 ;
383 desc_p->next = (uintptr_t)&desc_table_p[idx + 1];
Hans de Goedefcdb3b32016-07-27 17:31:17 +0200384 desc_p->st |= CONFIG_ETH_RXSIZE;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530385 desc_p->status = BIT(31);
386 }
387
388 /* Correcting the last pointer of the chain */
389 desc_p->next = (uintptr_t)&desc_table_p[0];
390
391 flush_dcache_range((uintptr_t)priv->rx_chain,
392 (uintptr_t)priv->rx_chain +
393 sizeof(priv->rx_chain));
394
395 writel((uintptr_t)&desc_table_p[0], (priv->mac_reg + EMAC_RX_DMA_DESC));
396 priv->rx_currdescnum = 0;
397}
398
399static void tx_descs_init(struct emac_eth_dev *priv)
400{
401 struct emac_dma_desc *desc_table_p = &priv->tx_chain[0];
402 char *txbuffs = &priv->txbuffer[0];
403 struct emac_dma_desc *desc_p;
404 u32 idx;
405
406 for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
407 desc_p = &desc_table_p[idx];
408 desc_p->buf_addr = (uintptr_t)&txbuffs[idx * CONFIG_ETH_BUFSIZE]
409 ;
410 desc_p->next = (uintptr_t)&desc_table_p[idx + 1];
411 desc_p->status = (1 << 31);
412 desc_p->st = 0;
413 }
414
415 /* Correcting the last pointer of the chain */
416 desc_p->next = (uintptr_t)&desc_table_p[0];
417
418 /* Flush all Tx buffer descriptors */
419 flush_dcache_range((uintptr_t)priv->tx_chain,
420 (uintptr_t)priv->tx_chain +
421 sizeof(priv->tx_chain));
422
423 writel((uintptr_t)&desc_table_p[0], priv->mac_reg + EMAC_TX_DMA_DESC);
424 priv->tx_currdescnum = 0;
425}
426
427static int _sun8i_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
428{
429 u32 reg, v;
430 int timeout = 100;
431
432 reg = readl((priv->mac_reg + EMAC_CTL1));
433
434 if (!(reg & 0x1)) {
435 /* Soft reset MAC */
436 setbits_le32((priv->mac_reg + EMAC_CTL1), 0x1);
437 do {
438 reg = readl(priv->mac_reg + EMAC_CTL1);
439 } while ((reg & 0x01) != 0 && (--timeout));
440 if (!timeout) {
441 printf("%s: Timeout\n", __func__);
442 return -1;
443 }
444 }
445
446 /* Rewrite mac address after reset */
447 _sun8i_write_hwaddr(priv, enetaddr);
448
449 v = readl(priv->mac_reg + EMAC_TX_CTL1);
450 /* TX_MD Transmission starts after a full frame located in TX DMA FIFO*/
451 v |= BIT(1);
452 writel(v, priv->mac_reg + EMAC_TX_CTL1);
453
454 v = readl(priv->mac_reg + EMAC_RX_CTL1);
455 /* RX_MD RX DMA reads data from RX DMA FIFO to host memory after a
456 * complete frame has been written to RX DMA FIFO
457 */
458 v |= BIT(1);
459 writel(v, priv->mac_reg + EMAC_RX_CTL1);
460
461 /* DMA */
462 writel(8 << 24, priv->mac_reg + EMAC_CTL1);
463
464 /* Initialize rx/tx descriptors */
465 rx_descs_init(priv);
466 tx_descs_init(priv);
467
468 /* PHY Start Up */
Samuel Holland6a4d7992018-01-27 23:53:20 -0600469 phy_startup(priv->phydev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530470
471 sun8i_adjust_link(priv, priv->phydev);
472
473 /* Start RX DMA */
474 v = readl(priv->mac_reg + EMAC_RX_CTL1);
475 v |= BIT(30);
476 writel(v, priv->mac_reg + EMAC_RX_CTL1);
477 /* Start TX DMA */
478 v = readl(priv->mac_reg + EMAC_TX_CTL1);
479 v |= BIT(30);
480 writel(v, priv->mac_reg + EMAC_TX_CTL1);
481
482 /* Enable RX/TX */
483 setbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31));
484 setbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31));
485
486 return 0;
487}
488
489static int parse_phy_pins(struct udevice *dev)
490{
Lothar Feltenacb9a5b2018-07-13 10:45:27 +0200491 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530492 int offset;
493 const char *pin_name;
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100494 int drive, pull = SUN4I_PINCTRL_NO_PULL, i;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530495
Simon Glassdd79d6e2017-01-17 16:52:55 -0700496 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530497 "pinctrl-0");
498 if (offset < 0) {
499 printf("WARNING: emac: cannot find pinctrl-0 node\n");
500 return offset;
501 }
502
503 drive = fdt_getprop_u32_default_node(gd->fdt_blob, offset, 0,
Andre Przywara26e549b2018-04-04 01:31:15 +0100504 "drive-strength", ~0);
505 if (drive != ~0) {
506 if (drive <= 10)
507 drive = SUN4I_PINCTRL_10_MA;
508 else if (drive <= 20)
509 drive = SUN4I_PINCTRL_20_MA;
510 else if (drive <= 30)
511 drive = SUN4I_PINCTRL_30_MA;
512 else
513 drive = SUN4I_PINCTRL_40_MA;
Andre Przywara26e549b2018-04-04 01:31:15 +0100514 }
515
516 if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-up", NULL))
517 pull = SUN4I_PINCTRL_PULL_UP;
Andre Przywara26e549b2018-04-04 01:31:15 +0100518 else if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-down", NULL))
519 pull = SUN4I_PINCTRL_PULL_DOWN;
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100520
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530521 for (i = 0; ; i++) {
522 int pin;
523
Simon Glassb0ea7402016-10-02 17:59:28 -0600524 pin_name = fdt_stringlist_get(gd->fdt_blob, offset,
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100525 "pins", i, NULL);
526 if (!pin_name)
527 break;
Andre Przywara26e549b2018-04-04 01:31:15 +0100528
529 pin = sunxi_name_to_gpio(pin_name);
530 if (pin < 0)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530531 continue;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530532
Lothar Feltenacb9a5b2018-07-13 10:45:27 +0200533 if (priv->variant == H3_EMAC)
534 sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX_H3);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200535 else if (priv->variant == R40_GMAC)
536 sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX_R40);
Lothar Feltenacb9a5b2018-07-13 10:45:27 +0200537 else
538 sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX);
539
Andre Przywara26e549b2018-04-04 01:31:15 +0100540 if (drive != ~0)
541 sunxi_gpio_set_drv(pin, drive);
542 if (pull != ~0)
543 sunxi_gpio_set_pull(pin, pull);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530544 }
545
546 if (!i) {
Andre Przywara26e549b2018-04-04 01:31:15 +0100547 printf("WARNING: emac: cannot find pins property\n");
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530548 return -2;
549 }
550
551 return 0;
552}
553
554static int _sun8i_eth_recv(struct emac_eth_dev *priv, uchar **packetp)
555{
556 u32 status, desc_num = priv->rx_currdescnum;
557 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
558 int length = -EAGAIN;
559 int good_packet = 1;
560 uintptr_t desc_start = (uintptr_t)desc_p;
561 uintptr_t desc_end = desc_start +
562 roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
563
564 ulong data_start = (uintptr_t)desc_p->buf_addr;
565 ulong data_end;
566
567 /* Invalidate entire buffer descriptor */
568 invalidate_dcache_range(desc_start, desc_end);
569
570 status = desc_p->status;
571
572 /* Check for DMA own bit */
573 if (!(status & BIT(31))) {
574 length = (desc_p->status >> 16) & 0x3FFF;
575
576 if (length < 0x40) {
577 good_packet = 0;
578 debug("RX: Bad Packet (runt)\n");
579 }
580
581 data_end = data_start + length;
582 /* Invalidate received data */
583 invalidate_dcache_range(rounddown(data_start,
584 ARCH_DMA_MINALIGN),
585 roundup(data_end,
586 ARCH_DMA_MINALIGN));
587 if (good_packet) {
Hans de Goedefcdb3b32016-07-27 17:31:17 +0200588 if (length > CONFIG_ETH_RXSIZE) {
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530589 printf("Received packet is too big (len=%d)\n",
590 length);
591 return -EMSGSIZE;
592 }
593 *packetp = (uchar *)(ulong)desc_p->buf_addr;
594 return length;
595 }
596 }
597
598 return length;
599}
600
601static int _sun8i_emac_eth_send(struct emac_eth_dev *priv, void *packet,
602 int len)
603{
604 u32 v, desc_num = priv->tx_currdescnum;
605 struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num];
606 uintptr_t desc_start = (uintptr_t)desc_p;
607 uintptr_t desc_end = desc_start +
608 roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
609
610 uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
611 uintptr_t data_end = data_start +
612 roundup(len, ARCH_DMA_MINALIGN);
613
614 /* Invalidate entire buffer descriptor */
615 invalidate_dcache_range(desc_start, desc_end);
616
617 desc_p->st = len;
618 /* Mandatory undocumented bit */
619 desc_p->st |= BIT(24);
620
621 memcpy((void *)data_start, packet, len);
622
623 /* Flush data to be sent */
624 flush_dcache_range(data_start, data_end);
625
626 /* frame end */
627 desc_p->st |= BIT(30);
628 desc_p->st |= BIT(31);
629
630 /*frame begin */
631 desc_p->st |= BIT(29);
632 desc_p->status = BIT(31);
633
634 /*Descriptors st and status field has changed, so FLUSH it */
635 flush_dcache_range(desc_start, desc_end);
636
637 /* Move to next Descriptor and wrap around */
638 if (++desc_num >= CONFIG_TX_DESCR_NUM)
639 desc_num = 0;
640 priv->tx_currdescnum = desc_num;
641
642 /* Start the DMA */
643 v = readl(priv->mac_reg + EMAC_TX_CTL1);
644 v |= BIT(31);/* mandatory */
645 v |= BIT(30);/* mandatory */
646 writel(v, priv->mac_reg + EMAC_TX_CTL1);
647
648 return 0;
649}
650
651static int sun8i_eth_write_hwaddr(struct udevice *dev)
652{
653 struct eth_pdata *pdata = dev_get_platdata(dev);
654 struct emac_eth_dev *priv = dev_get_priv(dev);
655
656 return _sun8i_write_hwaddr(priv, pdata->enetaddr);
657}
658
Jagan Tekicb63d282019-02-28 00:26:58 +0530659static int sun8i_emac_board_setup(struct emac_eth_dev *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530660{
Jagan Tekicb63d282019-02-28 00:26:58 +0530661 int ret;
662
663 ret = clk_enable(&priv->tx_clk);
664 if (ret) {
665 dev_err(dev, "failed to enable TX clock\n");
666 return ret;
667 }
668
669 if (reset_valid(&priv->tx_rst)) {
670 ret = reset_deassert(&priv->tx_rst);
671 if (ret) {
672 dev_err(dev, "failed to deassert TX reset\n");
673 goto err_tx_clk;
674 }
675 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530676
Jagan Teki727ed792019-02-28 00:27:00 +0530677 /* Only H3/H5 have clock controls for internal EPHY */
678 if (clk_valid(&priv->ephy_clk)) {
679 ret = clk_enable(&priv->ephy_clk);
680 if (ret) {
681 dev_err(dev, "failed to enable EPHY TX clock\n");
682 return ret;
683 }
684 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530685
Jagan Teki727ed792019-02-28 00:27:00 +0530686 if (reset_valid(&priv->ephy_rst)) {
687 ret = reset_deassert(&priv->ephy_rst);
688 if (ret) {
689 dev_err(dev, "failed to deassert EPHY TX clock\n");
690 return ret;
Lothar Feltenacb9a5b2018-07-13 10:45:27 +0200691 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530692 }
693
Jagan Tekicb63d282019-02-28 00:26:58 +0530694 return 0;
Lothar Feltene8cbced2018-07-13 10:45:28 +0200695
Jagan Tekicb63d282019-02-28 00:26:58 +0530696err_tx_clk:
697 clk_disable(&priv->tx_clk);
698 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530699}
700
Simon Glassfa4689a2019-12-06 21:41:35 -0700701#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100702static int sun8i_mdio_reset(struct mii_dev *bus)
703{
704 struct udevice *dev = bus->priv;
705 struct emac_eth_dev *priv = dev_get_priv(dev);
706 struct sun8i_eth_pdata *pdata = dev_get_platdata(dev);
707 int ret;
708
709 if (!dm_gpio_is_valid(&priv->reset_gpio))
710 return 0;
711
712 /* reset the phy */
713 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
714 if (ret)
715 return ret;
716
717 udelay(pdata->reset_delays[0]);
718
719 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
720 if (ret)
721 return ret;
722
723 udelay(pdata->reset_delays[1]);
724
725 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
726 if (ret)
727 return ret;
728
729 udelay(pdata->reset_delays[2]);
730
731 return 0;
732}
733#endif
734
735static int sun8i_mdio_init(const char *name, struct udevice *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530736{
737 struct mii_dev *bus = mdio_alloc();
738
739 if (!bus) {
740 debug("Failed to allocate MDIO bus\n");
741 return -ENOMEM;
742 }
743
744 bus->read = sun8i_mdio_read;
745 bus->write = sun8i_mdio_write;
746 snprintf(bus->name, sizeof(bus->name), name);
747 bus->priv = (void *)priv;
Simon Glassfa4689a2019-12-06 21:41:35 -0700748#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100749 bus->reset = sun8i_mdio_reset;
750#endif
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530751
752 return mdio_register(bus);
753}
754
755static int sun8i_emac_eth_start(struct udevice *dev)
756{
757 struct eth_pdata *pdata = dev_get_platdata(dev);
758
759 return _sun8i_emac_eth_init(dev->priv, pdata->enetaddr);
760}
761
762static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length)
763{
764 struct emac_eth_dev *priv = dev_get_priv(dev);
765
766 return _sun8i_emac_eth_send(priv, packet, length);
767}
768
769static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
770{
771 struct emac_eth_dev *priv = dev_get_priv(dev);
772
773 return _sun8i_eth_recv(priv, packetp);
774}
775
776static int _sun8i_free_pkt(struct emac_eth_dev *priv)
777{
778 u32 desc_num = priv->rx_currdescnum;
779 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
780 uintptr_t desc_start = (uintptr_t)desc_p;
781 uintptr_t desc_end = desc_start +
782 roundup(sizeof(u32), ARCH_DMA_MINALIGN);
783
784 /* Make the current descriptor valid again */
785 desc_p->status |= BIT(31);
786
787 /* Flush Status field of descriptor */
788 flush_dcache_range(desc_start, desc_end);
789
790 /* Move to next desc and wrap-around condition. */
791 if (++desc_num >= CONFIG_RX_DESCR_NUM)
792 desc_num = 0;
793 priv->rx_currdescnum = desc_num;
794
795 return 0;
796}
797
798static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet,
799 int length)
800{
801 struct emac_eth_dev *priv = dev_get_priv(dev);
802
803 return _sun8i_free_pkt(priv);
804}
805
806static void sun8i_emac_eth_stop(struct udevice *dev)
807{
808 struct emac_eth_dev *priv = dev_get_priv(dev);
809
810 /* Stop Rx/Tx transmitter */
811 clrbits_le32(priv->mac_reg + EMAC_RX_CTL0, BIT(31));
812 clrbits_le32(priv->mac_reg + EMAC_TX_CTL0, BIT(31));
813
814 /* Stop TX DMA */
815 clrbits_le32(priv->mac_reg + EMAC_TX_CTL1, BIT(30));
816
817 phy_shutdown(priv->phydev);
818}
819
820static int sun8i_emac_eth_probe(struct udevice *dev)
821{
Icenowy Zheng525dc442018-11-23 00:37:48 +0100822 struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
823 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530824 struct emac_eth_dev *priv = dev_get_priv(dev);
Jagan Tekicb63d282019-02-28 00:26:58 +0530825 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530826
827 priv->mac_reg = (void *)pdata->iobase;
828
Jagan Tekicb63d282019-02-28 00:26:58 +0530829 ret = sun8i_emac_board_setup(priv);
830 if (ret)
831 return ret;
832
Icenowy Zheng525dc442018-11-23 00:37:48 +0100833 sun8i_emac_set_syscon(sun8i_pdata, priv);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530834
Philipp Tomsich3297b552017-02-22 19:46:41 +0100835 sun8i_mdio_init(dev->name, dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530836 priv->bus = miiphy_get_dev_by_name(dev->name);
837
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530838 return sun8i_phy_init(priv, dev);
839}
840
841static const struct eth_ops sun8i_emac_eth_ops = {
842 .start = sun8i_emac_eth_start,
843 .write_hwaddr = sun8i_eth_write_hwaddr,
844 .send = sun8i_emac_eth_send,
845 .recv = sun8i_emac_eth_recv,
846 .free_pkt = sun8i_eth_free_pkt,
847 .stop = sun8i_emac_eth_stop,
848};
849
Jagan Teki727ed792019-02-28 00:27:00 +0530850static int sun8i_get_ephy_nodes(struct emac_eth_dev *priv)
851{
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200852 int emac_node, ephy_node, ret, ephy_handle;
853
854 emac_node = fdt_path_offset(gd->fdt_blob,
855 "/soc/ethernet@1c30000");
856 if (emac_node < 0) {
857 debug("failed to get emac node\n");
858 return emac_node;
859 }
860 ephy_handle = fdtdec_lookup_phandle(gd->fdt_blob,
861 emac_node, "phy-handle");
Jagan Teki727ed792019-02-28 00:27:00 +0530862
863 /* look for mdio-mux node for internal PHY node */
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200864 ephy_node = fdt_path_offset(gd->fdt_blob,
865 "/soc/ethernet@1c30000/mdio-mux/mdio@1/ethernet-phy@1");
866 if (ephy_node < 0) {
Jagan Teki727ed792019-02-28 00:27:00 +0530867 debug("failed to get mdio-mux with internal PHY\n");
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200868 return ephy_node;
Jagan Teki727ed792019-02-28 00:27:00 +0530869 }
870
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200871 /* This is not the phy we are looking for */
872 if (ephy_node != ephy_handle)
873 return 0;
874
875 ret = fdt_node_check_compatible(gd->fdt_blob, ephy_node,
Jagan Teki727ed792019-02-28 00:27:00 +0530876 "allwinner,sun8i-h3-mdio-internal");
877 if (ret < 0) {
878 debug("failed to find mdio-internal node\n");
879 return ret;
880 }
881
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200882 ret = clk_get_by_index_nodev(offset_to_ofnode(ephy_node), 0,
Jagan Teki727ed792019-02-28 00:27:00 +0530883 &priv->ephy_clk);
884 if (ret) {
885 dev_err(dev, "failed to get EPHY TX clock\n");
886 return ret;
887 }
888
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200889 ret = reset_get_by_index_nodev(offset_to_ofnode(ephy_node), 0,
Jagan Teki727ed792019-02-28 00:27:00 +0530890 &priv->ephy_rst);
891 if (ret) {
892 dev_err(dev, "failed to get EPHY TX reset\n");
893 return ret;
894 }
895
896 priv->use_internal_phy = true;
897
898 return 0;
899}
900
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530901static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
902{
Philipp Tomsich3297b552017-02-22 19:46:41 +0100903 struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
904 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530905 struct emac_eth_dev *priv = dev_get_priv(dev);
906 const char *phy_mode;
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100907 const fdt32_t *reg;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700908 int node = dev_of_offset(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530909 int offset = 0;
Simon Glassfa4689a2019-12-06 21:41:35 -0700910#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100911 int reset_flags = GPIOD_IS_OUT;
Philipp Tomsich3297b552017-02-22 19:46:41 +0100912#endif
Jagan Tekicb63d282019-02-28 00:26:58 +0530913 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530914
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100915 pdata->iobase = devfdt_get_addr(dev);
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100916 if (pdata->iobase == FDT_ADDR_T_NONE) {
917 debug("%s: Cannot find MAC base address\n", __func__);
918 return -EINVAL;
919 }
920
Lothar Feltene8cbced2018-07-13 10:45:28 +0200921 priv->variant = dev_get_driver_data(dev);
922
923 if (!priv->variant) {
924 printf("%s: Missing variant\n", __func__);
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100925 return -EINVAL;
926 }
Lothar Feltene8cbced2018-07-13 10:45:28 +0200927
Jagan Tekicb63d282019-02-28 00:26:58 +0530928 ret = clk_get_by_name(dev, "stmmaceth", &priv->tx_clk);
929 if (ret) {
930 dev_err(dev, "failed to get TX clock\n");
931 return ret;
932 }
933
934 ret = reset_get_by_name(dev, "stmmaceth", &priv->tx_rst);
935 if (ret && ret != -ENOENT) {
936 dev_err(dev, "failed to get TX reset\n");
937 return ret;
938 }
939
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530940 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "syscon");
941 if (offset < 0) {
942 debug("%s: cannot find syscon node\n", __func__);
943 return -EINVAL;
944 }
945
946 reg = fdt_getprop(gd->fdt_blob, offset, "reg", NULL);
947 if (!reg) {
948 debug("%s: cannot find reg property in syscon node\n",
949 __func__);
950 return -EINVAL;
951 }
952 priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob,
953 offset, reg);
954 if (priv->sysctl_reg == FDT_ADDR_T_NONE) {
955 debug("%s: Cannot find syscon base address\n", __func__);
956 return -EINVAL;
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100957 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530958
959 pdata->phy_interface = -1;
960 priv->phyaddr = -1;
961 priv->use_internal_phy = false;
962
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100963 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100964 if (offset < 0) {
965 debug("%s: Cannot find PHY address\n", __func__);
966 return -EINVAL;
967 }
968 priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530969
Simon Glassdd79d6e2017-01-17 16:52:55 -0700970 phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530971
972 if (phy_mode)
973 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
974 printf("phy interface%d\n", pdata->phy_interface);
975
976 if (pdata->phy_interface == -1) {
977 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
978 return -EINVAL;
979 }
980
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530981 if (priv->variant == H3_EMAC) {
Jagan Teki727ed792019-02-28 00:27:00 +0530982 ret = sun8i_get_ephy_nodes(priv);
983 if (ret)
984 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530985 }
986
987 priv->interface = pdata->phy_interface;
988
989 if (!priv->use_internal_phy)
990 parse_phy_pins(dev);
991
Icenowy Zheng525dc442018-11-23 00:37:48 +0100992 sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
993 "allwinner,tx-delay-ps", 0);
994 if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700)
995 printf("%s: Invalid TX delay value %d\n", __func__,
996 sun8i_pdata->tx_delay_ps);
997
998 sun8i_pdata->rx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
999 "allwinner,rx-delay-ps", 0);
1000 if (sun8i_pdata->rx_delay_ps < 0 || sun8i_pdata->rx_delay_ps > 3100)
1001 printf("%s: Invalid RX delay value %d\n", __func__,
1002 sun8i_pdata->rx_delay_ps);
1003
Simon Glassfa4689a2019-12-06 21:41:35 -07001004#if CONFIG_IS_ENABLED(DM_GPIO)
Simon Glass7a494432017-05-17 17:18:09 -06001005 if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich3297b552017-02-22 19:46:41 +01001006 "snps,reset-active-low"))
1007 reset_flags |= GPIOD_ACTIVE_LOW;
1008
1009 ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
1010 &priv->reset_gpio, reset_flags);
1011
1012 if (ret == 0) {
Simon Glass7a494432017-05-17 17:18:09 -06001013 ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich3297b552017-02-22 19:46:41 +01001014 "snps,reset-delays-us",
1015 sun8i_pdata->reset_delays, 3);
1016 } else if (ret == -ENOENT) {
1017 ret = 0;
1018 }
1019#endif
1020
Amit Singh Tomard194c0e2016-07-06 17:59:44 +05301021 return 0;
1022}
1023
1024static const struct udevice_id sun8i_emac_eth_ids[] = {
1025 {.compatible = "allwinner,sun8i-h3-emac", .data = (uintptr_t)H3_EMAC },
1026 {.compatible = "allwinner,sun50i-a64-emac",
1027 .data = (uintptr_t)A64_EMAC },
1028 {.compatible = "allwinner,sun8i-a83t-emac",
1029 .data = (uintptr_t)A83T_EMAC },
Lothar Feltene8cbced2018-07-13 10:45:28 +02001030 {.compatible = "allwinner,sun8i-r40-gmac",
1031 .data = (uintptr_t)R40_GMAC },
Amit Singh Tomard194c0e2016-07-06 17:59:44 +05301032 { }
1033};
1034
1035U_BOOT_DRIVER(eth_sun8i_emac) = {
1036 .name = "eth_sun8i_emac",
1037 .id = UCLASS_ETH,
1038 .of_match = sun8i_emac_eth_ids,
1039 .ofdata_to_platdata = sun8i_emac_eth_ofdata_to_platdata,
1040 .probe = sun8i_emac_eth_probe,
1041 .ops = &sun8i_emac_eth_ops,
1042 .priv_auto_alloc_size = sizeof(struct emac_eth_dev),
Philipp Tomsich3297b552017-02-22 19:46:41 +01001043 .platdata_auto_alloc_size = sizeof(struct sun8i_eth_pdata),
Amit Singh Tomard194c0e2016-07-06 17:59:44 +05301044 .flags = DM_FLAG_ALLOC_PRIV_DMA,
1045};