blob: f232b8f087c9fd5bd40dbef6a5ad5d1811f42499 [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 Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Simon Glass274e0b02020-05-10 11:39:56 -060015#include <asm/cache.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060016#include <asm/global_data.h>
Samuel Holland06feb812021-09-11 16:50:47 -050017#include <asm/gpio.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053018#include <asm/io.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053019#include <common.h>
Jagan Tekicb63d282019-02-28 00:26:58 +053020#include <clk.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053021#include <dm.h>
22#include <fdt_support.h>
Simon Glass9bc15642020-02-03 07:36:16 -070023#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060024#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060025#include <linux/delay.h>
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053026#include <linux/err.h>
27#include <malloc.h>
28#include <miiphy.h>
29#include <net.h>
Jagan Tekicb63d282019-02-28 00:26:58 +053030#include <reset.h>
Andre Przywara0dd619b2020-07-06 01:40:34 +010031#include <wait_bit.h>
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
Andre Przywarab41f2472020-07-06 01:40:45 +010040#define MDIO_CMD_MII_CLK_CSR_DIV_16 0x0
41#define MDIO_CMD_MII_CLK_CSR_DIV_32 0x1
42#define MDIO_CMD_MII_CLK_CSR_DIV_64 0x2
43#define MDIO_CMD_MII_CLK_CSR_DIV_128 0x3
44#define MDIO_CMD_MII_CLK_CSR_SHIFT 20
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053045
Tom Rini364d0022023-01-10 11:19:45 -050046#define CFG_TX_DESCR_NUM 32
47#define CFG_RX_DESCR_NUM 32
48#define CFG_ETH_BUFSIZE 2048 /* Note must be dma aligned */
Hans de Goedefcdb3b32016-07-27 17:31:17 +020049
50/*
51 * The datasheet says that each descriptor can transfers up to 4096 bytes
52 * But later, the register documentation reduces that value to 2048,
53 * using 2048 cause strange behaviours and even BSP driver use 2047
54 */
Tom Rini364d0022023-01-10 11:19:45 -050055#define CFG_ETH_RXSIZE 2044 /* Note must fit in ETH_BUFSIZE */
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053056
Tom Rini364d0022023-01-10 11:19:45 -050057#define TX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_TX_DESCR_NUM)
58#define RX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_RX_DESCR_NUM)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053059
60#define H3_EPHY_DEFAULT_VALUE 0x58000
61#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15)
62#define H3_EPHY_ADDR_SHIFT 20
63#define REG_PHY_ADDR_MASK GENMASK(4, 0)
64#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */
65#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */
66#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */
67
68#define SC_RMII_EN BIT(13)
69#define SC_EPIT BIT(2) /* 1: RGMII, 0: MII */
70#define SC_ETCS_MASK GENMASK(1, 0)
71#define SC_ETCS_EXT_GMII 0x1
72#define SC_ETCS_INT_GMII 0x2
Icenowy Zheng525dc442018-11-23 00:37:48 +010073#define SC_ETXDC_MASK GENMASK(12, 10)
74#define SC_ETXDC_OFFSET 10
75#define SC_ERXDC_MASK GENMASK(9, 5)
76#define SC_ERXDC_OFFSET 5
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053077
Tom Rini364d0022023-01-10 11:19:45 -050078#define CFG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053079
80#define AHB_GATE_OFFSET_EPHY 0
81
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053082/* H3/A64 EMAC Register's offset */
83#define EMAC_CTL0 0x00
Andre Przywarae6e29cc2020-07-06 01:40:36 +010084#define EMAC_CTL0_FULL_DUPLEX BIT(0)
85#define EMAC_CTL0_SPEED_MASK GENMASK(3, 2)
86#define EMAC_CTL0_SPEED_10 (0x2 << 2)
87#define EMAC_CTL0_SPEED_100 (0x3 << 2)
88#define EMAC_CTL0_SPEED_1000 (0x0 << 2)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053089#define EMAC_CTL1 0x04
Andre Przywarae6e29cc2020-07-06 01:40:36 +010090#define EMAC_CTL1_SOFT_RST BIT(0)
91#define EMAC_CTL1_BURST_LEN_SHIFT 24
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053092#define EMAC_INT_STA 0x08
93#define EMAC_INT_EN 0x0c
94#define EMAC_TX_CTL0 0x10
Andre Przywarae6e29cc2020-07-06 01:40:36 +010095#define EMAC_TX_CTL0_TX_EN BIT(31)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +053096#define EMAC_TX_CTL1 0x14
Andre Przywarae6e29cc2020-07-06 01:40:36 +010097#define EMAC_TX_CTL1_TX_MD BIT(1)
98#define EMAC_TX_CTL1_TX_DMA_EN BIT(30)
99#define EMAC_TX_CTL1_TX_DMA_START BIT(31)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530100#define EMAC_TX_FLOW_CTL 0x1c
101#define EMAC_TX_DMA_DESC 0x20
102#define EMAC_RX_CTL0 0x24
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100103#define EMAC_RX_CTL0_RX_EN BIT(31)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530104#define EMAC_RX_CTL1 0x28
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100105#define EMAC_RX_CTL1_RX_MD BIT(1)
Andre Przywara59422822020-07-06 01:40:43 +0100106#define EMAC_RX_CTL1_RX_RUNT_FRM BIT(2)
107#define EMAC_RX_CTL1_RX_ERR_FRM BIT(3)
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100108#define EMAC_RX_CTL1_RX_DMA_EN BIT(30)
109#define EMAC_RX_CTL1_RX_DMA_START BIT(31)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530110#define EMAC_RX_DMA_DESC 0x34
111#define EMAC_MII_CMD 0x48
112#define EMAC_MII_DATA 0x4c
113#define EMAC_ADDR0_HIGH 0x50
114#define EMAC_ADDR0_LOW 0x54
115#define EMAC_TX_DMA_STA 0xb0
116#define EMAC_TX_CUR_DESC 0xb4
117#define EMAC_TX_CUR_BUF 0xb8
118#define EMAC_RX_DMA_STA 0xc0
119#define EMAC_RX_CUR_DESC 0xc4
120
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100121#define EMAC_DESC_OWN_DMA BIT(31)
122#define EMAC_DESC_LAST_DESC BIT(30)
123#define EMAC_DESC_FIRST_DESC BIT(29)
124#define EMAC_DESC_CHAIN_SECOND BIT(24)
125
Andre Przywara59422822020-07-06 01:40:43 +0100126#define EMAC_DESC_RX_ERROR_MASK 0x400068db
127
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530128DECLARE_GLOBAL_DATA_PTR;
129
Samuel Hollanda8791622023-01-22 16:51:02 -0600130enum emac_variant_id {
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530131 A83T_EMAC = 1,
132 H3_EMAC,
133 A64_EMAC,
Lothar Feltene8cbced2018-07-13 10:45:28 +0200134 R40_GMAC,
Samuel Holland3386e9a2020-05-07 18:10:51 -0500135 H6_EMAC,
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530136};
137
Samuel Hollanda8791622023-01-22 16:51:02 -0600138struct emac_variant {
139 enum emac_variant_id variant;
Samuel Holland62a2a682023-01-22 16:51:03 -0600140 bool support_rmii;
Samuel Hollanda8791622023-01-22 16:51:02 -0600141};
142
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530143struct emac_dma_desc {
144 u32 status;
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100145 u32 ctl_size;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530146 u32 buf_addr;
147 u32 next;
148} __aligned(ARCH_DMA_MINALIGN);
149
150struct emac_eth_dev {
Tom Rini364d0022023-01-10 11:19:45 -0500151 struct emac_dma_desc rx_chain[CFG_TX_DESCR_NUM];
152 struct emac_dma_desc tx_chain[CFG_RX_DESCR_NUM];
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530153 char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
154 char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
155
156 u32 interface;
157 u32 phyaddr;
158 u32 link;
159 u32 speed;
160 u32 duplex;
161 u32 phy_configured;
162 u32 tx_currdescnum;
163 u32 rx_currdescnum;
164 u32 addr;
165 u32 tx_slot;
166 bool use_internal_phy;
167
Samuel Hollanda8791622023-01-22 16:51:02 -0600168 const struct emac_variant *variant;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530169 void *mac_reg;
170 phys_addr_t sysctl_reg;
171 struct phy_device *phydev;
172 struct mii_dev *bus;
Jagan Tekicb63d282019-02-28 00:26:58 +0530173 struct clk tx_clk;
Jagan Teki727ed792019-02-28 00:27:00 +0530174 struct clk ephy_clk;
Jagan Tekicb63d282019-02-28 00:26:58 +0530175 struct reset_ctl tx_rst;
Jagan Teki727ed792019-02-28 00:27:00 +0530176 struct reset_ctl ephy_rst;
Simon Glassfa4689a2019-12-06 21:41:35 -0700177#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100178 struct gpio_desc reset_gpio;
179#endif
180};
181
182
183struct sun8i_eth_pdata {
184 struct eth_pdata eth_pdata;
185 u32 reset_delays[3];
Icenowy Zheng525dc442018-11-23 00:37:48 +0100186 int tx_delay_ps;
187 int rx_delay_ps;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530188};
189
Philipp Tomsich3297b552017-02-22 19:46:41 +0100190
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530191static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
192{
Philipp Tomsich3297b552017-02-22 19:46:41 +0100193 struct udevice *dev = bus->priv;
194 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara0dd619b2020-07-06 01:40:34 +0100195 u32 mii_cmd;
196 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530197
Andre Przywara0dd619b2020-07-06 01:40:34 +0100198 mii_cmd = (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530199 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
Andre Przywara0dd619b2020-07-06 01:40:34 +0100200 mii_cmd |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530201 MDIO_CMD_MII_PHY_ADDR_MASK;
202
Andre Przywarab41f2472020-07-06 01:40:45 +0100203 /*
204 * The EMAC clock is either 200 or 300 MHz, so we need a divider
205 * of 128 to get the MDIO frequency below the required 2.5 MHz.
206 */
Heinrich Schuchardt6ffc0232021-06-03 07:52:41 +0000207 if (!priv->use_internal_phy)
208 mii_cmd |= MDIO_CMD_MII_CLK_CSR_DIV_128 <<
209 MDIO_CMD_MII_CLK_CSR_SHIFT;
Andre Przywarab41f2472020-07-06 01:40:45 +0100210
Andre Przywara0dd619b2020-07-06 01:40:34 +0100211 mii_cmd |= MDIO_CMD_MII_BUSY;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530212
Andre Przywara0dd619b2020-07-06 01:40:34 +0100213 writel(mii_cmd, priv->mac_reg + EMAC_MII_CMD);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530214
Andre Przywara0dd619b2020-07-06 01:40:34 +0100215 ret = wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
216 MDIO_CMD_MII_BUSY, false,
Tom Rini364d0022023-01-10 11:19:45 -0500217 CFG_MDIO_TIMEOUT, true);
Andre Przywara0dd619b2020-07-06 01:40:34 +0100218 if (ret < 0)
219 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530220
Andre Przywara0dd619b2020-07-06 01:40:34 +0100221 return readl(priv->mac_reg + EMAC_MII_DATA);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530222}
223
224static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
225 u16 val)
226{
Philipp Tomsich3297b552017-02-22 19:46:41 +0100227 struct udevice *dev = bus->priv;
228 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara0dd619b2020-07-06 01:40:34 +0100229 u32 mii_cmd;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530230
Andre Przywara0dd619b2020-07-06 01:40:34 +0100231 mii_cmd = (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530232 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
Andre Przywara0dd619b2020-07-06 01:40:34 +0100233 mii_cmd |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530234 MDIO_CMD_MII_PHY_ADDR_MASK;
235
Andre Przywarab41f2472020-07-06 01:40:45 +0100236 /*
237 * The EMAC clock is either 200 or 300 MHz, so we need a divider
238 * of 128 to get the MDIO frequency below the required 2.5 MHz.
239 */
Heinrich Schuchardt6ffc0232021-06-03 07:52:41 +0000240 if (!priv->use_internal_phy)
241 mii_cmd |= MDIO_CMD_MII_CLK_CSR_DIV_128 <<
242 MDIO_CMD_MII_CLK_CSR_SHIFT;
Andre Przywarab41f2472020-07-06 01:40:45 +0100243
Andre Przywara0dd619b2020-07-06 01:40:34 +0100244 mii_cmd |= MDIO_CMD_MII_WRITE;
245 mii_cmd |= MDIO_CMD_MII_BUSY;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530246
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530247 writel(val, priv->mac_reg + EMAC_MII_DATA);
Andre Przywara0dd619b2020-07-06 01:40:34 +0100248 writel(mii_cmd, priv->mac_reg + EMAC_MII_CMD);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530249
Andre Przywara0dd619b2020-07-06 01:40:34 +0100250 return wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
251 MDIO_CMD_MII_BUSY, false,
Tom Rini364d0022023-01-10 11:19:45 -0500252 CFG_MDIO_TIMEOUT, true);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530253}
254
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530255static int sun8i_eth_write_hwaddr(struct udevice *dev)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530256{
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530257 struct emac_eth_dev *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700258 struct eth_pdata *pdata = dev_get_plat(dev);
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530259 uchar *mac_id = pdata->enetaddr;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530260 u32 macid_lo, macid_hi;
261
262 macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
263 (mac_id[3] << 24);
264 macid_hi = mac_id[4] + (mac_id[5] << 8);
265
266 writel(macid_hi, priv->mac_reg + EMAC_ADDR0_HIGH);
267 writel(macid_lo, priv->mac_reg + EMAC_ADDR0_LOW);
268
269 return 0;
270}
271
272static void sun8i_adjust_link(struct emac_eth_dev *priv,
273 struct phy_device *phydev)
274{
275 u32 v;
276
277 v = readl(priv->mac_reg + EMAC_CTL0);
278
279 if (phydev->duplex)
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100280 v |= EMAC_CTL0_FULL_DUPLEX;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530281 else
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100282 v &= ~EMAC_CTL0_FULL_DUPLEX;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530283
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100284 v &= ~EMAC_CTL0_SPEED_MASK;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530285
286 switch (phydev->speed) {
287 case 1000:
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100288 v |= EMAC_CTL0_SPEED_1000;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530289 break;
290 case 100:
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100291 v |= EMAC_CTL0_SPEED_100;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530292 break;
293 case 10:
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100294 v |= EMAC_CTL0_SPEED_10;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530295 break;
296 }
297 writel(v, priv->mac_reg + EMAC_CTL0);
298}
299
Andre Przywara15651d82021-01-11 21:11:45 +0100300static u32 sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 reg)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530301{
302 if (priv->use_internal_phy) {
303 /* H3 based SoC's that has an Internal 100MBit PHY
304 * needs to be configured and powered up before use
305 */
Andre Przywara15651d82021-01-11 21:11:45 +0100306 reg &= ~H3_EPHY_DEFAULT_MASK;
307 reg |= H3_EPHY_DEFAULT_VALUE;
308 reg |= priv->phyaddr << H3_EPHY_ADDR_SHIFT;
309 reg &= ~H3_EPHY_SHUTDOWN;
310 return reg | H3_EPHY_SELECT;
311 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530312
Andre Przywara15651d82021-01-11 21:11:45 +0100313 /* This is to select External Gigabit PHY on those boards with
314 * an internal PHY. Does not hurt on other SoCs. Linux does
315 * it as well.
316 */
317 return reg & ~H3_EPHY_SELECT;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530318}
319
Icenowy Zheng525dc442018-11-23 00:37:48 +0100320static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
321 struct emac_eth_dev *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530322{
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530323 u32 reg;
324
Samuel Hollanda8791622023-01-22 16:51:02 -0600325 if (priv->variant->variant == R40_GMAC) {
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530326 /* Select RGMII for R40 */
327 reg = readl(priv->sysctl_reg + 0x164);
Samuel Holland97f2cf12020-05-07 18:10:50 -0500328 reg |= SC_ETCS_INT_GMII |
329 SC_EPIT |
330 (CONFIG_GMAC_TX_DELAY << SC_ETXDC_OFFSET);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530331
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530332 writel(reg, priv->sysctl_reg + 0x164);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200333 return 0;
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530334 }
335
336 reg = readl(priv->sysctl_reg + 0x30);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200337
Andre Przywara15651d82021-01-11 21:11:45 +0100338 reg = sun8i_emac_set_syscon_ephy(priv, reg);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530339
340 reg &= ~(SC_ETCS_MASK | SC_EPIT);
Samuel Holland62a2a682023-01-22 16:51:03 -0600341 if (priv->variant->support_rmii)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530342 reg &= ~SC_RMII_EN;
343
344 switch (priv->interface) {
345 case PHY_INTERFACE_MODE_MII:
346 /* default */
347 break;
348 case PHY_INTERFACE_MODE_RGMII:
Andre Przywara43bb1582020-11-14 17:37:46 +0000349 case PHY_INTERFACE_MODE_RGMII_ID:
350 case PHY_INTERFACE_MODE_RGMII_RXID:
351 case PHY_INTERFACE_MODE_RGMII_TXID:
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530352 reg |= SC_EPIT | SC_ETCS_INT_GMII;
353 break;
354 case PHY_INTERFACE_MODE_RMII:
Samuel Holland62a2a682023-01-22 16:51:03 -0600355 if (priv->variant->support_rmii) {
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530356 reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
Samuel Holland62a2a682023-01-22 16:51:03 -0600357 break;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530358 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530359 default:
360 debug("%s: Invalid PHY interface\n", __func__);
361 return -EINVAL;
362 }
363
Icenowy Zheng525dc442018-11-23 00:37:48 +0100364 if (pdata->tx_delay_ps)
365 reg |= ((pdata->tx_delay_ps / 100) << SC_ETXDC_OFFSET)
366 & SC_ETXDC_MASK;
367
368 if (pdata->rx_delay_ps)
369 reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
370 & SC_ERXDC_MASK;
371
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100372 writel(reg, priv->sysctl_reg + 0x30);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530373
374 return 0;
375}
376
377static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev)
378{
379 struct phy_device *phydev;
380
381 phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
382 if (!phydev)
383 return -ENODEV;
384
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530385 priv->phydev = phydev;
386 phy_config(priv->phydev);
387
388 return 0;
389}
390
Andre Przywara2e7dd262020-07-06 01:40:40 +0100391#define cache_clean_descriptor(desc) \
Wolfgang Denk62fb2b42021-09-27 17:42:39 +0200392 flush_dcache_range((uintptr_t)(desc), \
Andre Przywara2e7dd262020-07-06 01:40:40 +0100393 (uintptr_t)(desc) + sizeof(struct emac_dma_desc))
394
395#define cache_inv_descriptor(desc) \
396 invalidate_dcache_range((uintptr_t)(desc), \
397 (uintptr_t)(desc) + sizeof(struct emac_dma_desc))
398
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530399static void rx_descs_init(struct emac_eth_dev *priv)
400{
401 struct emac_dma_desc *desc_table_p = &priv->rx_chain[0];
402 char *rxbuffs = &priv->rxbuffer[0];
403 struct emac_dma_desc *desc_p;
Andre Przywara4ab675e2020-07-06 01:40:41 +0100404 int i;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530405
Andre Przywara7408b092020-07-06 01:40:37 +0100406 /*
407 * Make sure we don't have dirty cache lines around, which could
408 * be cleaned to DRAM *after* the MAC has already written data to it.
409 */
410 invalidate_dcache_range((uintptr_t)desc_table_p,
411 (uintptr_t)desc_table_p + sizeof(priv->rx_chain));
412 invalidate_dcache_range((uintptr_t)rxbuffs,
413 (uintptr_t)rxbuffs + sizeof(priv->rxbuffer));
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530414
Tom Rini364d0022023-01-10 11:19:45 -0500415 for (i = 0; i < CFG_RX_DESCR_NUM; i++) {
Andre Przywara4ab675e2020-07-06 01:40:41 +0100416 desc_p = &desc_table_p[i];
Tom Rini364d0022023-01-10 11:19:45 -0500417 desc_p->buf_addr = (uintptr_t)&rxbuffs[i * CFG_ETH_BUFSIZE];
Andre Przywara4ab675e2020-07-06 01:40:41 +0100418 desc_p->next = (uintptr_t)&desc_table_p[i + 1];
Tom Rini364d0022023-01-10 11:19:45 -0500419 desc_p->ctl_size = CFG_ETH_RXSIZE;
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100420 desc_p->status = EMAC_DESC_OWN_DMA;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530421 }
422
423 /* Correcting the last pointer of the chain */
424 desc_p->next = (uintptr_t)&desc_table_p[0];
425
426 flush_dcache_range((uintptr_t)priv->rx_chain,
427 (uintptr_t)priv->rx_chain +
428 sizeof(priv->rx_chain));
429
430 writel((uintptr_t)&desc_table_p[0], (priv->mac_reg + EMAC_RX_DMA_DESC));
431 priv->rx_currdescnum = 0;
432}
433
434static void tx_descs_init(struct emac_eth_dev *priv)
435{
436 struct emac_dma_desc *desc_table_p = &priv->tx_chain[0];
437 char *txbuffs = &priv->txbuffer[0];
438 struct emac_dma_desc *desc_p;
Andre Przywara4ab675e2020-07-06 01:40:41 +0100439 int i;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530440
Tom Rini364d0022023-01-10 11:19:45 -0500441 for (i = 0; i < CFG_TX_DESCR_NUM; i++) {
Andre Przywara4ab675e2020-07-06 01:40:41 +0100442 desc_p = &desc_table_p[i];
Tom Rini364d0022023-01-10 11:19:45 -0500443 desc_p->buf_addr = (uintptr_t)&txbuffs[i * CFG_ETH_BUFSIZE];
Andre Przywara4ab675e2020-07-06 01:40:41 +0100444 desc_p->next = (uintptr_t)&desc_table_p[i + 1];
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100445 desc_p->ctl_size = 0;
Andre Przywaradf6f2712020-07-06 01:40:33 +0100446 desc_p->status = 0;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530447 }
448
449 /* Correcting the last pointer of the chain */
450 desc_p->next = (uintptr_t)&desc_table_p[0];
451
Andre Przywara8cd89602020-07-06 01:40:38 +0100452 /* Flush the first TX buffer descriptor we will tell the MAC about. */
Andre Przywara2e7dd262020-07-06 01:40:40 +0100453 cache_clean_descriptor(desc_table_p);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530454
455 writel((uintptr_t)&desc_table_p[0], priv->mac_reg + EMAC_TX_DMA_DESC);
456 priv->tx_currdescnum = 0;
457}
458
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530459static int sun8i_emac_eth_start(struct udevice *dev)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530460{
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530461 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara874145f2020-07-06 01:40:32 +0100462 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530463
Andre Przywara6bdc70e2020-07-06 01:40:42 +0100464 /* Soft reset MAC */
465 writel(EMAC_CTL1_SOFT_RST, priv->mac_reg + EMAC_CTL1);
466 ret = wait_for_bit_le32(priv->mac_reg + EMAC_CTL1,
467 EMAC_CTL1_SOFT_RST, false, 10, true);
468 if (ret) {
469 printf("%s: Timeout\n", __func__);
470 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530471 }
472
473 /* Rewrite mac address after reset */
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530474 sun8i_eth_write_hwaddr(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530475
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100476 /* transmission starts after the full frame arrived in TX DMA FIFO */
477 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_MD);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530478
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100479 /*
480 * RX DMA reads data from RX DMA FIFO to host memory after a
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530481 * complete frame has been written to RX DMA FIFO
482 */
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100483 setbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_MD);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530484
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100485 /* DMA burst length */
486 writel(8 << EMAC_CTL1_BURST_LEN_SHIFT, priv->mac_reg + EMAC_CTL1);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530487
488 /* Initialize rx/tx descriptors */
489 rx_descs_init(priv);
490 tx_descs_init(priv);
491
492 /* PHY Start Up */
Andre Przywara874145f2020-07-06 01:40:32 +0100493 ret = phy_startup(priv->phydev);
494 if (ret)
495 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530496
497 sun8i_adjust_link(priv, priv->phydev);
498
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100499 /* Start RX/TX DMA */
Andre Przywara59422822020-07-06 01:40:43 +0100500 setbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_DMA_EN |
501 EMAC_RX_CTL1_RX_ERR_FRM | EMAC_RX_CTL1_RX_RUNT_FRM);
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100502 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_EN);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530503
504 /* Enable RX/TX */
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100505 setbits_le32(priv->mac_reg + EMAC_RX_CTL0, EMAC_RX_CTL0_RX_EN);
506 setbits_le32(priv->mac_reg + EMAC_TX_CTL0, EMAC_TX_CTL0_TX_EN);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530507
508 return 0;
509}
510
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530511static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530512{
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530513 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530514 u32 status, desc_num = priv->rx_currdescnum;
515 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
Andre Przywara59422822020-07-06 01:40:43 +0100516 uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
517 int length;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530518
519 /* Invalidate entire buffer descriptor */
Andre Przywara2e7dd262020-07-06 01:40:40 +0100520 cache_inv_descriptor(desc_p);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530521
522 status = desc_p->status;
523
524 /* Check for DMA own bit */
Andre Przywara59422822020-07-06 01:40:43 +0100525 if (status & EMAC_DESC_OWN_DMA)
526 return -EAGAIN;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530527
Andre Przywara59422822020-07-06 01:40:43 +0100528 length = (status >> 16) & 0x3fff;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530529
Andre Przywara59422822020-07-06 01:40:43 +0100530 /* make sure we read from DRAM, not our cache */
531 invalidate_dcache_range(data_start,
532 data_start + roundup(length, ARCH_DMA_MINALIGN));
533
534 if (status & EMAC_DESC_RX_ERROR_MASK) {
535 debug("RX: packet error: 0x%x\n",
536 status & EMAC_DESC_RX_ERROR_MASK);
537 return 0;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530538 }
Andre Przywara59422822020-07-06 01:40:43 +0100539 if (length < 0x40) {
540 debug("RX: Bad Packet (runt)\n");
541 return 0;
542 }
543
Tom Rini364d0022023-01-10 11:19:45 -0500544 if (length > CFG_ETH_RXSIZE) {
Andre Przywara59422822020-07-06 01:40:43 +0100545 debug("RX: Too large packet (%d bytes)\n", length);
546 return 0;
547 }
548
549 *packetp = (uchar *)(ulong)desc_p->buf_addr;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530550
551 return length;
552}
553
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530554static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530555{
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530556 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100557 u32 desc_num = priv->tx_currdescnum;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530558 struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num];
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530559 uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
560 uintptr_t data_end = data_start +
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530561 roundup(length, ARCH_DMA_MINALIGN);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530562
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100563 desc_p->ctl_size = length | EMAC_DESC_CHAIN_SECOND;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530564
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530565 memcpy((void *)data_start, packet, length);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530566
567 /* Flush data to be sent */
568 flush_dcache_range(data_start, data_end);
569
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100570 /* frame begin and end */
571 desc_p->ctl_size |= EMAC_DESC_LAST_DESC | EMAC_DESC_FIRST_DESC;
572 desc_p->status = EMAC_DESC_OWN_DMA;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530573
Andre Przywara2e7dd262020-07-06 01:40:40 +0100574 /* make sure the MAC reads the actual data from DRAM */
575 cache_clean_descriptor(desc_p);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530576
577 /* Move to next Descriptor and wrap around */
Tom Rini364d0022023-01-10 11:19:45 -0500578 if (++desc_num >= CFG_TX_DESCR_NUM)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530579 desc_num = 0;
580 priv->tx_currdescnum = desc_num;
581
582 /* Start the DMA */
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100583 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_START);
584
585 /*
586 * Since we copied the data above, we return here without waiting
587 * for the packet to be actually send out.
588 */
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530589
590 return 0;
591}
592
Sean Anderson4702aa22020-09-15 10:45:00 -0400593static int sun8i_emac_board_setup(struct udevice *dev,
594 struct emac_eth_dev *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530595{
Jagan Tekicb63d282019-02-28 00:26:58 +0530596 int ret;
597
598 ret = clk_enable(&priv->tx_clk);
599 if (ret) {
600 dev_err(dev, "failed to enable TX clock\n");
601 return ret;
602 }
603
604 if (reset_valid(&priv->tx_rst)) {
605 ret = reset_deassert(&priv->tx_rst);
606 if (ret) {
607 dev_err(dev, "failed to deassert TX reset\n");
608 goto err_tx_clk;
609 }
610 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530611
Jagan Teki727ed792019-02-28 00:27:00 +0530612 /* Only H3/H5 have clock controls for internal EPHY */
613 if (clk_valid(&priv->ephy_clk)) {
614 ret = clk_enable(&priv->ephy_clk);
615 if (ret) {
616 dev_err(dev, "failed to enable EPHY TX clock\n");
617 return ret;
618 }
619 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530620
Jagan Teki727ed792019-02-28 00:27:00 +0530621 if (reset_valid(&priv->ephy_rst)) {
622 ret = reset_deassert(&priv->ephy_rst);
623 if (ret) {
624 dev_err(dev, "failed to deassert EPHY TX clock\n");
625 return ret;
Lothar Feltenacb9a5b2018-07-13 10:45:27 +0200626 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530627 }
628
Jagan Tekicb63d282019-02-28 00:26:58 +0530629 return 0;
Lothar Feltene8cbced2018-07-13 10:45:28 +0200630
Jagan Tekicb63d282019-02-28 00:26:58 +0530631err_tx_clk:
632 clk_disable(&priv->tx_clk);
633 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530634}
635
Simon Glassfa4689a2019-12-06 21:41:35 -0700636#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100637static int sun8i_mdio_reset(struct mii_dev *bus)
638{
639 struct udevice *dev = bus->priv;
640 struct emac_eth_dev *priv = dev_get_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700641 struct sun8i_eth_pdata *pdata = dev_get_plat(dev);
Philipp Tomsich3297b552017-02-22 19:46:41 +0100642 int ret;
643
644 if (!dm_gpio_is_valid(&priv->reset_gpio))
645 return 0;
646
647 /* reset the phy */
648 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
649 if (ret)
650 return ret;
651
652 udelay(pdata->reset_delays[0]);
653
654 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
655 if (ret)
656 return ret;
657
658 udelay(pdata->reset_delays[1]);
659
660 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
661 if (ret)
662 return ret;
663
664 udelay(pdata->reset_delays[2]);
665
666 return 0;
667}
668#endif
669
670static int sun8i_mdio_init(const char *name, struct udevice *priv)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530671{
672 struct mii_dev *bus = mdio_alloc();
673
674 if (!bus) {
675 debug("Failed to allocate MDIO bus\n");
676 return -ENOMEM;
677 }
678
679 bus->read = sun8i_mdio_read;
680 bus->write = sun8i_mdio_write;
681 snprintf(bus->name, sizeof(bus->name), name);
682 bus->priv = (void *)priv;
Simon Glassfa4689a2019-12-06 21:41:35 -0700683#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100684 bus->reset = sun8i_mdio_reset;
685#endif
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530686
687 return mdio_register(bus);
688}
689
Andre Przywaraf58d83c2020-10-21 23:21:42 +0530690static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet,
691 int length)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530692{
693 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530694 u32 desc_num = priv->rx_currdescnum;
695 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530696
Andre Przywara2e7dd262020-07-06 01:40:40 +0100697 /* give the current descriptor back to the MAC */
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100698 desc_p->status |= EMAC_DESC_OWN_DMA;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530699
700 /* Flush Status field of descriptor */
Andre Przywara2e7dd262020-07-06 01:40:40 +0100701 cache_clean_descriptor(desc_p);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530702
703 /* Move to next desc and wrap-around condition. */
Tom Rini364d0022023-01-10 11:19:45 -0500704 if (++desc_num >= CFG_RX_DESCR_NUM)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530705 desc_num = 0;
706 priv->rx_currdescnum = desc_num;
707
708 return 0;
709}
710
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530711static void sun8i_emac_eth_stop(struct udevice *dev)
712{
713 struct emac_eth_dev *priv = dev_get_priv(dev);
714
715 /* Stop Rx/Tx transmitter */
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100716 clrbits_le32(priv->mac_reg + EMAC_RX_CTL0, EMAC_RX_CTL0_RX_EN);
717 clrbits_le32(priv->mac_reg + EMAC_TX_CTL0, EMAC_TX_CTL0_TX_EN);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530718
Andre Przywarae6e29cc2020-07-06 01:40:36 +0100719 /* Stop RX/TX DMA */
720 clrbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_EN);
721 clrbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_DMA_EN);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530722
723 phy_shutdown(priv->phydev);
724}
725
726static int sun8i_emac_eth_probe(struct udevice *dev)
727{
Simon Glassfa20e932020-12-03 16:55:20 -0700728 struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
Icenowy Zheng525dc442018-11-23 00:37:48 +0100729 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530730 struct emac_eth_dev *priv = dev_get_priv(dev);
Jagan Tekicb63d282019-02-28 00:26:58 +0530731 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530732
733 priv->mac_reg = (void *)pdata->iobase;
734
Sean Anderson4702aa22020-09-15 10:45:00 -0400735 ret = sun8i_emac_board_setup(dev, priv);
Jagan Tekicb63d282019-02-28 00:26:58 +0530736 if (ret)
737 return ret;
738
Icenowy Zheng525dc442018-11-23 00:37:48 +0100739 sun8i_emac_set_syscon(sun8i_pdata, priv);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530740
Philipp Tomsich3297b552017-02-22 19:46:41 +0100741 sun8i_mdio_init(dev->name, dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530742 priv->bus = miiphy_get_dev_by_name(dev->name);
743
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530744 return sun8i_phy_init(priv, dev);
745}
746
747static const struct eth_ops sun8i_emac_eth_ops = {
748 .start = sun8i_emac_eth_start,
749 .write_hwaddr = sun8i_eth_write_hwaddr,
750 .send = sun8i_emac_eth_send,
751 .recv = sun8i_emac_eth_recv,
752 .free_pkt = sun8i_eth_free_pkt,
753 .stop = sun8i_emac_eth_stop,
754};
755
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530756static int sun8i_handle_internal_phy(struct udevice *dev, struct emac_eth_dev *priv)
Jagan Teki727ed792019-02-28 00:27:00 +0530757{
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530758 struct ofnode_phandle_args phandle;
759 int ret;
Jagan Teki727ed792019-02-28 00:27:00 +0530760
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530761 ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "phy-handle",
762 NULL, 0, 0, &phandle);
763 if (ret)
764 return ret;
Jagan Teki727ed792019-02-28 00:27:00 +0530765
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530766 /* If the PHY node is not a child of the internal MDIO bus, we are
767 * using some external PHY.
768 */
769 if (!ofnode_device_is_compatible(ofnode_get_parent(phandle.node),
770 "allwinner,sun8i-h3-mdio-internal"))
Emmanuel Vadot98be8be2019-07-19 22:26:38 +0200771 return 0;
772
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530773 ret = clk_get_by_index_nodev(phandle.node, 0, &priv->ephy_clk);
Jagan Teki727ed792019-02-28 00:27:00 +0530774 if (ret) {
775 dev_err(dev, "failed to get EPHY TX clock\n");
776 return ret;
777 }
778
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530779 ret = reset_get_by_index_nodev(phandle.node, 0, &priv->ephy_rst);
Jagan Teki727ed792019-02-28 00:27:00 +0530780 if (ret) {
781 dev_err(dev, "failed to get EPHY TX reset\n");
782 return ret;
783 }
784
785 priv->use_internal_phy = true;
786
787 return 0;
788}
789
Simon Glassaad29ae2020-12-03 16:55:21 -0700790static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530791{
Simon Glassfa20e932020-12-03 16:55:20 -0700792 struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
Philipp Tomsich3297b552017-02-22 19:46:41 +0100793 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530794 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100795 const fdt32_t *reg;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700796 int node = dev_of_offset(dev);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530797 int offset = 0;
Simon Glassfa4689a2019-12-06 21:41:35 -0700798#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich3297b552017-02-22 19:46:41 +0100799 int reset_flags = GPIOD_IS_OUT;
Philipp Tomsich3297b552017-02-22 19:46:41 +0100800#endif
Jagan Tekicb63d282019-02-28 00:26:58 +0530801 int ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530802
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900803 pdata->iobase = dev_read_addr(dev);
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100804 if (pdata->iobase == FDT_ADDR_T_NONE) {
805 debug("%s: Cannot find MAC base address\n", __func__);
806 return -EINVAL;
807 }
808
Samuel Hollanda8791622023-01-22 16:51:02 -0600809 priv->variant = (const void *)dev_get_driver_data(dev);
Lothar Feltene8cbced2018-07-13 10:45:28 +0200810
811 if (!priv->variant) {
812 printf("%s: Missing variant\n", __func__);
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100813 return -EINVAL;
814 }
Lothar Feltene8cbced2018-07-13 10:45:28 +0200815
Jagan Tekicb63d282019-02-28 00:26:58 +0530816 ret = clk_get_by_name(dev, "stmmaceth", &priv->tx_clk);
817 if (ret) {
818 dev_err(dev, "failed to get TX clock\n");
819 return ret;
820 }
821
822 ret = reset_get_by_name(dev, "stmmaceth", &priv->tx_rst);
823 if (ret && ret != -ENOENT) {
824 dev_err(dev, "failed to get TX reset\n");
825 return ret;
826 }
827
Jagan Teki1cfc64c2019-02-28 00:26:51 +0530828 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "syscon");
829 if (offset < 0) {
830 debug("%s: cannot find syscon node\n", __func__);
831 return -EINVAL;
832 }
833
834 reg = fdt_getprop(gd->fdt_blob, offset, "reg", NULL);
835 if (!reg) {
836 debug("%s: cannot find reg property in syscon node\n",
837 __func__);
838 return -EINVAL;
839 }
840 priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob,
841 offset, reg);
842 if (priv->sysctl_reg == FDT_ADDR_T_NONE) {
843 debug("%s: Cannot find syscon base address\n", __func__);
844 return -EINVAL;
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100845 }
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530846
847 pdata->phy_interface = -1;
848 priv->phyaddr = -1;
849 priv->use_internal_phy = false;
850
Andre Przywara94f3bbd2018-04-04 01:31:20 +0100851 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
Andre Przywaraba3a96d2018-04-04 01:31:16 +0100852 if (offset < 0) {
853 debug("%s: Cannot find PHY address\n", __func__);
854 return -EINVAL;
855 }
856 priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530857
Marek BehĂșnbc194772022-04-07 00:33:01 +0200858 pdata->phy_interface = dev_read_phy_mode(dev);
Samuel Holland712cc892022-07-15 00:20:56 -0500859 debug("phy interface %d\n", pdata->phy_interface);
Marek BehĂșn48631e42022-04-07 00:33:03 +0200860 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530861 return -EINVAL;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530862
Samuel Hollanda8791622023-01-22 16:51:02 -0600863 if (priv->variant->variant == H3_EMAC) {
Andre Przywarab3ce85c2020-10-21 23:27:32 +0530864 ret = sun8i_handle_internal_phy(dev, priv);
Jagan Teki727ed792019-02-28 00:27:00 +0530865 if (ret)
866 return ret;
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530867 }
868
869 priv->interface = pdata->phy_interface;
870
Icenowy Zheng525dc442018-11-23 00:37:48 +0100871 sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
872 "allwinner,tx-delay-ps", 0);
873 if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700)
874 printf("%s: Invalid TX delay value %d\n", __func__,
875 sun8i_pdata->tx_delay_ps);
876
877 sun8i_pdata->rx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
878 "allwinner,rx-delay-ps", 0);
879 if (sun8i_pdata->rx_delay_ps < 0 || sun8i_pdata->rx_delay_ps > 3100)
880 printf("%s: Invalid RX delay value %d\n", __func__,
881 sun8i_pdata->rx_delay_ps);
882
Simon Glassfa4689a2019-12-06 21:41:35 -0700883#if CONFIG_IS_ENABLED(DM_GPIO)
Simon Glass7a494432017-05-17 17:18:09 -0600884 if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich3297b552017-02-22 19:46:41 +0100885 "snps,reset-active-low"))
886 reset_flags |= GPIOD_ACTIVE_LOW;
887
888 ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
889 &priv->reset_gpio, reset_flags);
890
891 if (ret == 0) {
Simon Glass7a494432017-05-17 17:18:09 -0600892 ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich3297b552017-02-22 19:46:41 +0100893 "snps,reset-delays-us",
894 sun8i_pdata->reset_delays, 3);
895 } else if (ret == -ENOENT) {
896 ret = 0;
897 }
898#endif
899
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530900 return 0;
901}
902
Samuel Hollanda8791622023-01-22 16:51:02 -0600903static const struct emac_variant emac_variant_a83t = {
904 .variant = A83T_EMAC,
905};
906
907static const struct emac_variant emac_variant_h3 = {
908 .variant = H3_EMAC,
Samuel Holland62a2a682023-01-22 16:51:03 -0600909 .support_rmii = true,
Samuel Hollanda8791622023-01-22 16:51:02 -0600910};
911
912static const struct emac_variant emac_variant_r40 = {
913 .variant = R40_GMAC,
914};
915
916static const struct emac_variant emac_variant_a64 = {
917 .variant = A64_EMAC,
Samuel Holland62a2a682023-01-22 16:51:03 -0600918 .support_rmii = true,
Samuel Hollanda8791622023-01-22 16:51:02 -0600919};
920
921static const struct emac_variant emac_variant_h6 = {
922 .variant = H6_EMAC,
Samuel Holland62a2a682023-01-22 16:51:03 -0600923 .support_rmii = true,
Samuel Hollanda8791622023-01-22 16:51:02 -0600924};
925
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530926static const struct udevice_id sun8i_emac_eth_ids[] = {
Samuel Hollanda8791622023-01-22 16:51:02 -0600927 { .compatible = "allwinner,sun8i-a83t-emac",
928 .data = (ulong)&emac_variant_a83t },
929 { .compatible = "allwinner,sun8i-h3-emac",
930 .data = (ulong)&emac_variant_h3 },
931 { .compatible = "allwinner,sun8i-r40-gmac",
932 .data = (ulong)&emac_variant_r40 },
933 { .compatible = "allwinner,sun50i-a64-emac",
934 .data = (ulong)&emac_variant_a64 },
935 { .compatible = "allwinner,sun50i-h6-emac",
936 .data = (ulong)&emac_variant_h6 },
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530937 { }
938};
939
940U_BOOT_DRIVER(eth_sun8i_emac) = {
941 .name = "eth_sun8i_emac",
942 .id = UCLASS_ETH,
943 .of_match = sun8i_emac_eth_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700944 .of_to_plat = sun8i_emac_eth_of_to_plat,
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530945 .probe = sun8i_emac_eth_probe,
946 .ops = &sun8i_emac_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700947 .priv_auto = sizeof(struct emac_eth_dev),
Simon Glass71fa5b42020-12-03 16:55:18 -0700948 .plat_auto = sizeof(struct sun8i_eth_pdata),
Amit Singh Tomard194c0e2016-07-06 17:59:44 +0530949 .flags = DM_FLAG_ALLOC_PRIV_DMA,
950};