blob: 4ba9ee1529ec1ee9914597719668b938ec8d633d [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Amit Singh Tomara29710c2016-07-06 17:59:44 +05302/*
3 * (C) Copyright 2016
4 * Author: Amit Singh Tomar, amittomer25@gmail.com
5 *
Amit Singh Tomara29710c2016-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 Glass1eb69ae2019-11-14 12:57:39 -070013#include <cpu_func.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060014#include <log.h>
Simon Glass90526e92020-05-10 11:39:56 -060015#include <asm/cache.h>
Simon Glass401d1c42020-10-30 21:38:53 -060016#include <asm/global_data.h>
Samuel Holland42508462021-09-11 16:50:47 -050017#include <asm/gpio.h>
Amit Singh Tomara29710c2016-07-06 17:59:44 +053018#include <asm/io.h>
Amit Singh Tomara29710c2016-07-06 17:59:44 +053019#include <common.h>
Jagan Tekid3a2c052019-02-28 00:26:58 +053020#include <clk.h>
Amit Singh Tomara29710c2016-07-06 17:59:44 +053021#include <dm.h>
22#include <fdt_support.h>
Simon Glass336d4612020-02-03 07:36:16 -070023#include <dm/device_compat.h>
Simon Glasscd93d622020-05-10 11:40:13 -060024#include <linux/bitops.h>
Simon Glassc05ed002020-05-10 11:40:11 -060025#include <linux/delay.h>
Amit Singh Tomara29710c2016-07-06 17:59:44 +053026#include <linux/err.h>
27#include <malloc.h>
28#include <miiphy.h>
29#include <net.h>
Jagan Tekid3a2c052019-02-28 00:26:58 +053030#include <reset.h>
Andre Przywaraf20f9462020-07-06 01:40:34 +010031#include <wait_bit.h>
Andre Przywara5ad98c52022-06-08 14:56:56 +010032#include <power/regulator.h>
Amit Singh Tomara29710c2016-07-06 17:59:44 +053033
Amit Singh Tomara29710c2016-07-06 17:59:44 +053034#define MDIO_CMD_MII_BUSY BIT(0)
35#define MDIO_CMD_MII_WRITE BIT(1)
36
37#define MDIO_CMD_MII_PHY_REG_ADDR_MASK 0x000001f0
38#define MDIO_CMD_MII_PHY_REG_ADDR_SHIFT 4
39#define MDIO_CMD_MII_PHY_ADDR_MASK 0x0001f000
40#define MDIO_CMD_MII_PHY_ADDR_SHIFT 12
Andre Przywara4f0278d2020-07-06 01:40:45 +010041#define MDIO_CMD_MII_CLK_CSR_DIV_16 0x0
42#define MDIO_CMD_MII_CLK_CSR_DIV_32 0x1
43#define MDIO_CMD_MII_CLK_CSR_DIV_64 0x2
44#define MDIO_CMD_MII_CLK_CSR_DIV_128 0x3
45#define MDIO_CMD_MII_CLK_CSR_SHIFT 20
Amit Singh Tomara29710c2016-07-06 17:59:44 +053046
Tom Rini6e7df1d2023-01-10 11:19:45 -050047#define CFG_TX_DESCR_NUM 32
48#define CFG_RX_DESCR_NUM 32
49#define CFG_ETH_BUFSIZE 2048 /* Note must be dma aligned */
Hans de Goede40694372016-07-27 17:31:17 +020050
51/*
52 * The datasheet says that each descriptor can transfers up to 4096 bytes
53 * But later, the register documentation reduces that value to 2048,
54 * using 2048 cause strange behaviours and even BSP driver use 2047
55 */
Tom Rini6e7df1d2023-01-10 11:19:45 -050056#define CFG_ETH_RXSIZE 2044 /* Note must fit in ETH_BUFSIZE */
Amit Singh Tomara29710c2016-07-06 17:59:44 +053057
Tom Rini6e7df1d2023-01-10 11:19:45 -050058#define TX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_TX_DESCR_NUM)
59#define RX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_RX_DESCR_NUM)
Amit Singh Tomara29710c2016-07-06 17:59:44 +053060
61#define H3_EPHY_DEFAULT_VALUE 0x58000
62#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15)
63#define H3_EPHY_ADDR_SHIFT 20
64#define REG_PHY_ADDR_MASK GENMASK(4, 0)
65#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */
66#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */
67#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */
68
69#define SC_RMII_EN BIT(13)
70#define SC_EPIT BIT(2) /* 1: RGMII, 0: MII */
71#define SC_ETCS_MASK GENMASK(1, 0)
72#define SC_ETCS_EXT_GMII 0x1
73#define SC_ETCS_INT_GMII 0x2
Icenowy Zheng9b16ede2018-11-23 00:37:48 +010074#define SC_ETXDC_MASK GENMASK(12, 10)
75#define SC_ETXDC_OFFSET 10
76#define SC_ERXDC_MASK GENMASK(9, 5)
77#define SC_ERXDC_OFFSET 5
Amit Singh Tomara29710c2016-07-06 17:59:44 +053078
Tom Rini6e7df1d2023-01-10 11:19:45 -050079#define CFG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
Amit Singh Tomara29710c2016-07-06 17:59:44 +053080
81#define AHB_GATE_OFFSET_EPHY 0
82
Amit Singh Tomara29710c2016-07-06 17:59:44 +053083/* H3/A64 EMAC Register's offset */
84#define EMAC_CTL0 0x00
Andre Przywara4fe86412020-07-06 01:40:36 +010085#define EMAC_CTL0_FULL_DUPLEX BIT(0)
86#define EMAC_CTL0_SPEED_MASK GENMASK(3, 2)
87#define EMAC_CTL0_SPEED_10 (0x2 << 2)
88#define EMAC_CTL0_SPEED_100 (0x3 << 2)
89#define EMAC_CTL0_SPEED_1000 (0x0 << 2)
Amit Singh Tomara29710c2016-07-06 17:59:44 +053090#define EMAC_CTL1 0x04
Andre Przywara4fe86412020-07-06 01:40:36 +010091#define EMAC_CTL1_SOFT_RST BIT(0)
92#define EMAC_CTL1_BURST_LEN_SHIFT 24
Amit Singh Tomara29710c2016-07-06 17:59:44 +053093#define EMAC_INT_STA 0x08
94#define EMAC_INT_EN 0x0c
95#define EMAC_TX_CTL0 0x10
Andre Przywara4fe86412020-07-06 01:40:36 +010096#define EMAC_TX_CTL0_TX_EN BIT(31)
Amit Singh Tomara29710c2016-07-06 17:59:44 +053097#define EMAC_TX_CTL1 0x14
Andre Przywara4fe86412020-07-06 01:40:36 +010098#define EMAC_TX_CTL1_TX_MD BIT(1)
99#define EMAC_TX_CTL1_TX_DMA_EN BIT(30)
100#define EMAC_TX_CTL1_TX_DMA_START BIT(31)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530101#define EMAC_TX_FLOW_CTL 0x1c
102#define EMAC_TX_DMA_DESC 0x20
103#define EMAC_RX_CTL0 0x24
Andre Przywara4fe86412020-07-06 01:40:36 +0100104#define EMAC_RX_CTL0_RX_EN BIT(31)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530105#define EMAC_RX_CTL1 0x28
Andre Przywara4fe86412020-07-06 01:40:36 +0100106#define EMAC_RX_CTL1_RX_MD BIT(1)
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100107#define EMAC_RX_CTL1_RX_RUNT_FRM BIT(2)
108#define EMAC_RX_CTL1_RX_ERR_FRM BIT(3)
Andre Przywara4fe86412020-07-06 01:40:36 +0100109#define EMAC_RX_CTL1_RX_DMA_EN BIT(30)
110#define EMAC_RX_CTL1_RX_DMA_START BIT(31)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530111#define EMAC_RX_DMA_DESC 0x34
112#define EMAC_MII_CMD 0x48
113#define EMAC_MII_DATA 0x4c
114#define EMAC_ADDR0_HIGH 0x50
115#define EMAC_ADDR0_LOW 0x54
116#define EMAC_TX_DMA_STA 0xb0
117#define EMAC_TX_CUR_DESC 0xb4
118#define EMAC_TX_CUR_BUF 0xb8
119#define EMAC_RX_DMA_STA 0xc0
120#define EMAC_RX_CUR_DESC 0xc4
121
Andre Przywara4fe86412020-07-06 01:40:36 +0100122#define EMAC_DESC_OWN_DMA BIT(31)
123#define EMAC_DESC_LAST_DESC BIT(30)
124#define EMAC_DESC_FIRST_DESC BIT(29)
125#define EMAC_DESC_CHAIN_SECOND BIT(24)
126
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100127#define EMAC_DESC_RX_ERROR_MASK 0x400068db
128
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530129DECLARE_GLOBAL_DATA_PTR;
130
Samuel Hollandc86d4732023-01-22 16:51:02 -0600131struct emac_variant {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600132 uint syscon_offset;
Samuel Holland0e148342023-01-22 16:51:04 -0600133 bool soc_has_internal_phy;
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600134 bool support_rmii;
Samuel Hollandc86d4732023-01-22 16:51:02 -0600135};
136
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530137struct emac_dma_desc {
138 u32 status;
Andre Przywara4fe86412020-07-06 01:40:36 +0100139 u32 ctl_size;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530140 u32 buf_addr;
141 u32 next;
142} __aligned(ARCH_DMA_MINALIGN);
143
144struct emac_eth_dev {
Tom Rini6e7df1d2023-01-10 11:19:45 -0500145 struct emac_dma_desc rx_chain[CFG_TX_DESCR_NUM];
146 struct emac_dma_desc tx_chain[CFG_RX_DESCR_NUM];
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530147 char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
148 char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
149
150 u32 interface;
151 u32 phyaddr;
152 u32 link;
153 u32 speed;
154 u32 duplex;
155 u32 phy_configured;
156 u32 tx_currdescnum;
157 u32 rx_currdescnum;
158 u32 addr;
159 u32 tx_slot;
160 bool use_internal_phy;
161
Samuel Hollandc86d4732023-01-22 16:51:02 -0600162 const struct emac_variant *variant;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530163 void *mac_reg;
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600164 void *sysctl_reg;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530165 struct phy_device *phydev;
166 struct mii_dev *bus;
Jagan Tekid3a2c052019-02-28 00:26:58 +0530167 struct clk tx_clk;
Jagan Teki23484532019-02-28 00:27:00 +0530168 struct clk ephy_clk;
Jagan Tekid3a2c052019-02-28 00:26:58 +0530169 struct reset_ctl tx_rst;
Jagan Teki23484532019-02-28 00:27:00 +0530170 struct reset_ctl ephy_rst;
Simon Glassbcee8d62019-12-06 21:41:35 -0700171#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100172 struct gpio_desc reset_gpio;
173#endif
Andre Przywara5ad98c52022-06-08 14:56:56 +0100174 struct udevice *phy_reg;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530175};
176
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100177
178struct sun8i_eth_pdata {
179 struct eth_pdata eth_pdata;
180 u32 reset_delays[3];
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100181 int tx_delay_ps;
182 int rx_delay_ps;
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100183};
184
185
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530186static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
187{
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100188 struct udevice *dev = bus->priv;
189 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywaraf20f9462020-07-06 01:40:34 +0100190 u32 mii_cmd;
191 int ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530192
Andre Przywaraf20f9462020-07-06 01:40:34 +0100193 mii_cmd = (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530194 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
Andre Przywaraf20f9462020-07-06 01:40:34 +0100195 mii_cmd |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530196 MDIO_CMD_MII_PHY_ADDR_MASK;
197
Andre Przywara4f0278d2020-07-06 01:40:45 +0100198 /*
199 * The EMAC clock is either 200 or 300 MHz, so we need a divider
200 * of 128 to get the MDIO frequency below the required 2.5 MHz.
201 */
Heinrich Schuchardt02036d92021-06-03 07:52:41 +0000202 if (!priv->use_internal_phy)
203 mii_cmd |= MDIO_CMD_MII_CLK_CSR_DIV_128 <<
204 MDIO_CMD_MII_CLK_CSR_SHIFT;
Andre Przywara4f0278d2020-07-06 01:40:45 +0100205
Andre Przywaraf20f9462020-07-06 01:40:34 +0100206 mii_cmd |= MDIO_CMD_MII_BUSY;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530207
Andre Przywaraf20f9462020-07-06 01:40:34 +0100208 writel(mii_cmd, priv->mac_reg + EMAC_MII_CMD);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530209
Andre Przywaraf20f9462020-07-06 01:40:34 +0100210 ret = wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
211 MDIO_CMD_MII_BUSY, false,
Tom Rini6e7df1d2023-01-10 11:19:45 -0500212 CFG_MDIO_TIMEOUT, true);
Andre Przywaraf20f9462020-07-06 01:40:34 +0100213 if (ret < 0)
214 return ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530215
Andre Przywaraf20f9462020-07-06 01:40:34 +0100216 return readl(priv->mac_reg + EMAC_MII_DATA);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530217}
218
219static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
220 u16 val)
221{
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100222 struct udevice *dev = bus->priv;
223 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywaraf20f9462020-07-06 01:40:34 +0100224 u32 mii_cmd;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530225
Andre Przywaraf20f9462020-07-06 01:40:34 +0100226 mii_cmd = (reg << MDIO_CMD_MII_PHY_REG_ADDR_SHIFT) &
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530227 MDIO_CMD_MII_PHY_REG_ADDR_MASK;
Andre Przywaraf20f9462020-07-06 01:40:34 +0100228 mii_cmd |= (addr << MDIO_CMD_MII_PHY_ADDR_SHIFT) &
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530229 MDIO_CMD_MII_PHY_ADDR_MASK;
230
Andre Przywara4f0278d2020-07-06 01:40:45 +0100231 /*
232 * The EMAC clock is either 200 or 300 MHz, so we need a divider
233 * of 128 to get the MDIO frequency below the required 2.5 MHz.
234 */
Heinrich Schuchardt02036d92021-06-03 07:52:41 +0000235 if (!priv->use_internal_phy)
236 mii_cmd |= MDIO_CMD_MII_CLK_CSR_DIV_128 <<
237 MDIO_CMD_MII_CLK_CSR_SHIFT;
Andre Przywara4f0278d2020-07-06 01:40:45 +0100238
Andre Przywaraf20f9462020-07-06 01:40:34 +0100239 mii_cmd |= MDIO_CMD_MII_WRITE;
240 mii_cmd |= MDIO_CMD_MII_BUSY;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530241
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530242 writel(val, priv->mac_reg + EMAC_MII_DATA);
Andre Przywaraf20f9462020-07-06 01:40:34 +0100243 writel(mii_cmd, priv->mac_reg + EMAC_MII_CMD);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530244
Andre Przywaraf20f9462020-07-06 01:40:34 +0100245 return wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
246 MDIO_CMD_MII_BUSY, false,
Tom Rini6e7df1d2023-01-10 11:19:45 -0500247 CFG_MDIO_TIMEOUT, true);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530248}
249
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530250static int sun8i_eth_write_hwaddr(struct udevice *dev)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530251{
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530252 struct emac_eth_dev *priv = dev_get_priv(dev);
Simon Glassc69cda22020-12-03 16:55:20 -0700253 struct eth_pdata *pdata = dev_get_plat(dev);
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530254 uchar *mac_id = pdata->enetaddr;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530255 u32 macid_lo, macid_hi;
256
257 macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
258 (mac_id[3] << 24);
259 macid_hi = mac_id[4] + (mac_id[5] << 8);
260
261 writel(macid_hi, priv->mac_reg + EMAC_ADDR0_HIGH);
262 writel(macid_lo, priv->mac_reg + EMAC_ADDR0_LOW);
263
264 return 0;
265}
266
267static void sun8i_adjust_link(struct emac_eth_dev *priv,
268 struct phy_device *phydev)
269{
270 u32 v;
271
272 v = readl(priv->mac_reg + EMAC_CTL0);
273
274 if (phydev->duplex)
Andre Przywara4fe86412020-07-06 01:40:36 +0100275 v |= EMAC_CTL0_FULL_DUPLEX;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530276 else
Andre Przywara4fe86412020-07-06 01:40:36 +0100277 v &= ~EMAC_CTL0_FULL_DUPLEX;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530278
Andre Przywara4fe86412020-07-06 01:40:36 +0100279 v &= ~EMAC_CTL0_SPEED_MASK;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530280
281 switch (phydev->speed) {
282 case 1000:
Andre Przywara4fe86412020-07-06 01:40:36 +0100283 v |= EMAC_CTL0_SPEED_1000;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530284 break;
285 case 100:
Andre Przywara4fe86412020-07-06 01:40:36 +0100286 v |= EMAC_CTL0_SPEED_100;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530287 break;
288 case 10:
Andre Przywara4fe86412020-07-06 01:40:36 +0100289 v |= EMAC_CTL0_SPEED_10;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530290 break;
291 }
292 writel(v, priv->mac_reg + EMAC_CTL0);
293}
294
Andre Przywarab14e5202021-01-11 21:11:45 +0100295static u32 sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 reg)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530296{
297 if (priv->use_internal_phy) {
298 /* H3 based SoC's that has an Internal 100MBit PHY
299 * needs to be configured and powered up before use
300 */
Andre Przywarab14e5202021-01-11 21:11:45 +0100301 reg &= ~H3_EPHY_DEFAULT_MASK;
302 reg |= H3_EPHY_DEFAULT_VALUE;
303 reg |= priv->phyaddr << H3_EPHY_ADDR_SHIFT;
304 reg &= ~H3_EPHY_SHUTDOWN;
305 return reg | H3_EPHY_SELECT;
306 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530307
Andre Przywarab14e5202021-01-11 21:11:45 +0100308 /* This is to select External Gigabit PHY on those boards with
309 * an internal PHY. Does not hurt on other SoCs. Linux does
310 * it as well.
311 */
312 return reg & ~H3_EPHY_SELECT;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530313}
314
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100315static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata,
316 struct emac_eth_dev *priv)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530317{
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530318 u32 reg;
319
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600320 reg = readl(priv->sysctl_reg);
Lothar Feltene46d73f2018-07-13 10:45:28 +0200321
Andre Przywarab14e5202021-01-11 21:11:45 +0100322 reg = sun8i_emac_set_syscon_ephy(priv, reg);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530323
324 reg &= ~(SC_ETCS_MASK | SC_EPIT);
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600325 if (priv->variant->support_rmii)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530326 reg &= ~SC_RMII_EN;
327
328 switch (priv->interface) {
329 case PHY_INTERFACE_MODE_MII:
330 /* default */
331 break;
332 case PHY_INTERFACE_MODE_RGMII:
Andre Przywara219a5d52020-11-14 17:37:46 +0000333 case PHY_INTERFACE_MODE_RGMII_ID:
334 case PHY_INTERFACE_MODE_RGMII_RXID:
335 case PHY_INTERFACE_MODE_RGMII_TXID:
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530336 reg |= SC_EPIT | SC_ETCS_INT_GMII;
337 break;
338 case PHY_INTERFACE_MODE_RMII:
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600339 if (priv->variant->support_rmii) {
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530340 reg |= SC_RMII_EN | SC_ETCS_EXT_GMII;
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600341 break;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530342 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530343 default:
344 debug("%s: Invalid PHY interface\n", __func__);
345 return -EINVAL;
346 }
347
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100348 if (pdata->tx_delay_ps)
349 reg |= ((pdata->tx_delay_ps / 100) << SC_ETXDC_OFFSET)
350 & SC_ETXDC_MASK;
351
352 if (pdata->rx_delay_ps)
353 reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET)
354 & SC_ERXDC_MASK;
355
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600356 writel(reg, priv->sysctl_reg);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530357
358 return 0;
359}
360
361static int sun8i_phy_init(struct emac_eth_dev *priv, void *dev)
362{
363 struct phy_device *phydev;
364
365 phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
366 if (!phydev)
367 return -ENODEV;
368
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530369 priv->phydev = phydev;
370 phy_config(priv->phydev);
371
372 return 0;
373}
374
Andre Przywara8c274ec2020-07-06 01:40:40 +0100375#define cache_clean_descriptor(desc) \
Wolfgang Denk0cf207e2021-09-27 17:42:39 +0200376 flush_dcache_range((uintptr_t)(desc), \
Andre Przywara8c274ec2020-07-06 01:40:40 +0100377 (uintptr_t)(desc) + sizeof(struct emac_dma_desc))
378
379#define cache_inv_descriptor(desc) \
380 invalidate_dcache_range((uintptr_t)(desc), \
381 (uintptr_t)(desc) + sizeof(struct emac_dma_desc))
382
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530383static void rx_descs_init(struct emac_eth_dev *priv)
384{
385 struct emac_dma_desc *desc_table_p = &priv->rx_chain[0];
386 char *rxbuffs = &priv->rxbuffer[0];
387 struct emac_dma_desc *desc_p;
Andre Przywara09501ff2020-07-06 01:40:41 +0100388 int i;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530389
Andre Przywara69853122020-07-06 01:40:37 +0100390 /*
391 * Make sure we don't have dirty cache lines around, which could
392 * be cleaned to DRAM *after* the MAC has already written data to it.
393 */
394 invalidate_dcache_range((uintptr_t)desc_table_p,
395 (uintptr_t)desc_table_p + sizeof(priv->rx_chain));
396 invalidate_dcache_range((uintptr_t)rxbuffs,
397 (uintptr_t)rxbuffs + sizeof(priv->rxbuffer));
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530398
Tom Rini6e7df1d2023-01-10 11:19:45 -0500399 for (i = 0; i < CFG_RX_DESCR_NUM; i++) {
Andre Przywara09501ff2020-07-06 01:40:41 +0100400 desc_p = &desc_table_p[i];
Tom Rini6e7df1d2023-01-10 11:19:45 -0500401 desc_p->buf_addr = (uintptr_t)&rxbuffs[i * CFG_ETH_BUFSIZE];
Andre Przywara09501ff2020-07-06 01:40:41 +0100402 desc_p->next = (uintptr_t)&desc_table_p[i + 1];
Tom Rini6e7df1d2023-01-10 11:19:45 -0500403 desc_p->ctl_size = CFG_ETH_RXSIZE;
Andre Przywara4fe86412020-07-06 01:40:36 +0100404 desc_p->status = EMAC_DESC_OWN_DMA;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530405 }
406
407 /* Correcting the last pointer of the chain */
408 desc_p->next = (uintptr_t)&desc_table_p[0];
409
410 flush_dcache_range((uintptr_t)priv->rx_chain,
411 (uintptr_t)priv->rx_chain +
412 sizeof(priv->rx_chain));
413
414 writel((uintptr_t)&desc_table_p[0], (priv->mac_reg + EMAC_RX_DMA_DESC));
415 priv->rx_currdescnum = 0;
416}
417
418static void tx_descs_init(struct emac_eth_dev *priv)
419{
420 struct emac_dma_desc *desc_table_p = &priv->tx_chain[0];
421 char *txbuffs = &priv->txbuffer[0];
422 struct emac_dma_desc *desc_p;
Andre Przywara09501ff2020-07-06 01:40:41 +0100423 int i;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530424
Tom Rini6e7df1d2023-01-10 11:19:45 -0500425 for (i = 0; i < CFG_TX_DESCR_NUM; i++) {
Andre Przywara09501ff2020-07-06 01:40:41 +0100426 desc_p = &desc_table_p[i];
Tom Rini6e7df1d2023-01-10 11:19:45 -0500427 desc_p->buf_addr = (uintptr_t)&txbuffs[i * CFG_ETH_BUFSIZE];
Andre Przywara09501ff2020-07-06 01:40:41 +0100428 desc_p->next = (uintptr_t)&desc_table_p[i + 1];
Andre Przywara4fe86412020-07-06 01:40:36 +0100429 desc_p->ctl_size = 0;
Andre Przywarac35380c2020-07-06 01:40:33 +0100430 desc_p->status = 0;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530431 }
432
433 /* Correcting the last pointer of the chain */
434 desc_p->next = (uintptr_t)&desc_table_p[0];
435
Andre Przywaraed909de2020-07-06 01:40:38 +0100436 /* Flush the first TX buffer descriptor we will tell the MAC about. */
Andre Przywara8c274ec2020-07-06 01:40:40 +0100437 cache_clean_descriptor(desc_table_p);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530438
439 writel((uintptr_t)&desc_table_p[0], priv->mac_reg + EMAC_TX_DMA_DESC);
440 priv->tx_currdescnum = 0;
441}
442
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530443static int sun8i_emac_eth_start(struct udevice *dev)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530444{
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530445 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara2808cf62020-07-06 01:40:32 +0100446 int ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530447
Andre Przywara2c5600c2020-07-06 01:40:42 +0100448 /* Soft reset MAC */
449 writel(EMAC_CTL1_SOFT_RST, priv->mac_reg + EMAC_CTL1);
450 ret = wait_for_bit_le32(priv->mac_reg + EMAC_CTL1,
451 EMAC_CTL1_SOFT_RST, false, 10, true);
452 if (ret) {
453 printf("%s: Timeout\n", __func__);
454 return ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530455 }
456
457 /* Rewrite mac address after reset */
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530458 sun8i_eth_write_hwaddr(dev);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530459
Andre Przywara4fe86412020-07-06 01:40:36 +0100460 /* transmission starts after the full frame arrived in TX DMA FIFO */
461 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_MD);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530462
Andre Przywara4fe86412020-07-06 01:40:36 +0100463 /*
464 * RX DMA reads data from RX DMA FIFO to host memory after a
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530465 * complete frame has been written to RX DMA FIFO
466 */
Andre Przywara4fe86412020-07-06 01:40:36 +0100467 setbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_MD);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530468
Andre Przywara4fe86412020-07-06 01:40:36 +0100469 /* DMA burst length */
470 writel(8 << EMAC_CTL1_BURST_LEN_SHIFT, priv->mac_reg + EMAC_CTL1);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530471
472 /* Initialize rx/tx descriptors */
473 rx_descs_init(priv);
474 tx_descs_init(priv);
475
476 /* PHY Start Up */
Andre Przywara2808cf62020-07-06 01:40:32 +0100477 ret = phy_startup(priv->phydev);
478 if (ret)
479 return ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530480
481 sun8i_adjust_link(priv, priv->phydev);
482
Andre Przywara4fe86412020-07-06 01:40:36 +0100483 /* Start RX/TX DMA */
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100484 setbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_DMA_EN |
485 EMAC_RX_CTL1_RX_ERR_FRM | EMAC_RX_CTL1_RX_RUNT_FRM);
Andre Przywara4fe86412020-07-06 01:40:36 +0100486 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_EN);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530487
488 /* Enable RX/TX */
Andre Przywara4fe86412020-07-06 01:40:36 +0100489 setbits_le32(priv->mac_reg + EMAC_RX_CTL0, EMAC_RX_CTL0_RX_EN);
490 setbits_le32(priv->mac_reg + EMAC_TX_CTL0, EMAC_TX_CTL0_TX_EN);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530491
492 return 0;
493}
494
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530495static int sun8i_emac_eth_recv(struct udevice *dev, int flags, uchar **packetp)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530496{
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530497 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530498 u32 status, desc_num = priv->rx_currdescnum;
499 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100500 uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
501 int length;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530502
503 /* Invalidate entire buffer descriptor */
Andre Przywara8c274ec2020-07-06 01:40:40 +0100504 cache_inv_descriptor(desc_p);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530505
506 status = desc_p->status;
507
508 /* Check for DMA own bit */
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100509 if (status & EMAC_DESC_OWN_DMA)
510 return -EAGAIN;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530511
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100512 length = (status >> 16) & 0x3fff;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530513
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100514 /* make sure we read from DRAM, not our cache */
515 invalidate_dcache_range(data_start,
516 data_start + roundup(length, ARCH_DMA_MINALIGN));
517
518 if (status & EMAC_DESC_RX_ERROR_MASK) {
519 debug("RX: packet error: 0x%x\n",
520 status & EMAC_DESC_RX_ERROR_MASK);
521 return 0;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530522 }
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100523 if (length < 0x40) {
524 debug("RX: Bad Packet (runt)\n");
525 return 0;
526 }
527
Tom Rini6e7df1d2023-01-10 11:19:45 -0500528 if (length > CFG_ETH_RXSIZE) {
Andre Przywara7edcb4e2020-07-06 01:40:43 +0100529 debug("RX: Too large packet (%d bytes)\n", length);
530 return 0;
531 }
532
533 *packetp = (uchar *)(ulong)desc_p->buf_addr;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530534
535 return length;
536}
537
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530538static int sun8i_emac_eth_send(struct udevice *dev, void *packet, int length)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530539{
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530540 struct emac_eth_dev *priv = dev_get_priv(dev);
Andre Przywara4fe86412020-07-06 01:40:36 +0100541 u32 desc_num = priv->tx_currdescnum;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530542 struct emac_dma_desc *desc_p = &priv->tx_chain[desc_num];
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530543 uintptr_t data_start = (uintptr_t)desc_p->buf_addr;
544 uintptr_t data_end = data_start +
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530545 roundup(length, ARCH_DMA_MINALIGN);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530546
Andre Przywara4fe86412020-07-06 01:40:36 +0100547 desc_p->ctl_size = length | EMAC_DESC_CHAIN_SECOND;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530548
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530549 memcpy((void *)data_start, packet, length);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530550
551 /* Flush data to be sent */
552 flush_dcache_range(data_start, data_end);
553
Andre Przywara4fe86412020-07-06 01:40:36 +0100554 /* frame begin and end */
555 desc_p->ctl_size |= EMAC_DESC_LAST_DESC | EMAC_DESC_FIRST_DESC;
556 desc_p->status = EMAC_DESC_OWN_DMA;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530557
Andre Przywara8c274ec2020-07-06 01:40:40 +0100558 /* make sure the MAC reads the actual data from DRAM */
559 cache_clean_descriptor(desc_p);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530560
561 /* Move to next Descriptor and wrap around */
Tom Rini6e7df1d2023-01-10 11:19:45 -0500562 if (++desc_num >= CFG_TX_DESCR_NUM)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530563 desc_num = 0;
564 priv->tx_currdescnum = desc_num;
565
566 /* Start the DMA */
Andre Przywara4fe86412020-07-06 01:40:36 +0100567 setbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_START);
568
569 /*
570 * Since we copied the data above, we return here without waiting
571 * for the packet to be actually send out.
572 */
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530573
574 return 0;
575}
576
Sean Andersonef043692020-09-15 10:45:00 -0400577static int sun8i_emac_board_setup(struct udevice *dev,
578 struct emac_eth_dev *priv)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530579{
Jagan Tekid3a2c052019-02-28 00:26:58 +0530580 int ret;
581
582 ret = clk_enable(&priv->tx_clk);
583 if (ret) {
584 dev_err(dev, "failed to enable TX clock\n");
585 return ret;
586 }
587
588 if (reset_valid(&priv->tx_rst)) {
589 ret = reset_deassert(&priv->tx_rst);
590 if (ret) {
591 dev_err(dev, "failed to deassert TX reset\n");
592 goto err_tx_clk;
593 }
594 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530595
Jagan Teki23484532019-02-28 00:27:00 +0530596 /* Only H3/H5 have clock controls for internal EPHY */
597 if (clk_valid(&priv->ephy_clk)) {
598 ret = clk_enable(&priv->ephy_clk);
599 if (ret) {
600 dev_err(dev, "failed to enable EPHY TX clock\n");
601 return ret;
602 }
603 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530604
Jagan Teki23484532019-02-28 00:27:00 +0530605 if (reset_valid(&priv->ephy_rst)) {
606 ret = reset_deassert(&priv->ephy_rst);
607 if (ret) {
608 dev_err(dev, "failed to deassert EPHY TX clock\n");
609 return ret;
Lothar Feltenc6a21d62018-07-13 10:45:27 +0200610 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530611 }
612
Jagan Tekid3a2c052019-02-28 00:26:58 +0530613 return 0;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530614
Jagan Tekid3a2c052019-02-28 00:26:58 +0530615err_tx_clk:
616 clk_disable(&priv->tx_clk);
617 return ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530618}
619
Simon Glassbcee8d62019-12-06 21:41:35 -0700620#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100621static int sun8i_mdio_reset(struct mii_dev *bus)
622{
623 struct udevice *dev = bus->priv;
624 struct emac_eth_dev *priv = dev_get_priv(dev);
Simon Glassc69cda22020-12-03 16:55:20 -0700625 struct sun8i_eth_pdata *pdata = dev_get_plat(dev);
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100626 int ret;
627
628 if (!dm_gpio_is_valid(&priv->reset_gpio))
629 return 0;
630
631 /* reset the phy */
632 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
633 if (ret)
634 return ret;
635
636 udelay(pdata->reset_delays[0]);
637
638 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
639 if (ret)
640 return ret;
641
642 udelay(pdata->reset_delays[1]);
643
644 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
645 if (ret)
646 return ret;
647
648 udelay(pdata->reset_delays[2]);
649
650 return 0;
651}
652#endif
653
654static int sun8i_mdio_init(const char *name, struct udevice *priv)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530655{
656 struct mii_dev *bus = mdio_alloc();
657
658 if (!bus) {
659 debug("Failed to allocate MDIO bus\n");
660 return -ENOMEM;
661 }
662
663 bus->read = sun8i_mdio_read;
664 bus->write = sun8i_mdio_write;
665 snprintf(bus->name, sizeof(bus->name), name);
666 bus->priv = (void *)priv;
Simon Glassbcee8d62019-12-06 21:41:35 -0700667#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100668 bus->reset = sun8i_mdio_reset;
669#endif
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530670
671 return mdio_register(bus);
672}
673
Andre Przywaraa5b2a992020-10-21 23:21:42 +0530674static int sun8i_eth_free_pkt(struct udevice *dev, uchar *packet,
675 int length)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530676{
677 struct emac_eth_dev *priv = dev_get_priv(dev);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530678 u32 desc_num = priv->rx_currdescnum;
679 struct emac_dma_desc *desc_p = &priv->rx_chain[desc_num];
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530680
Andre Przywara8c274ec2020-07-06 01:40:40 +0100681 /* give the current descriptor back to the MAC */
Andre Przywara4fe86412020-07-06 01:40:36 +0100682 desc_p->status |= EMAC_DESC_OWN_DMA;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530683
684 /* Flush Status field of descriptor */
Andre Przywara8c274ec2020-07-06 01:40:40 +0100685 cache_clean_descriptor(desc_p);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530686
687 /* Move to next desc and wrap-around condition. */
Tom Rini6e7df1d2023-01-10 11:19:45 -0500688 if (++desc_num >= CFG_RX_DESCR_NUM)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530689 desc_num = 0;
690 priv->rx_currdescnum = desc_num;
691
692 return 0;
693}
694
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530695static void sun8i_emac_eth_stop(struct udevice *dev)
696{
697 struct emac_eth_dev *priv = dev_get_priv(dev);
698
699 /* Stop Rx/Tx transmitter */
Andre Przywara4fe86412020-07-06 01:40:36 +0100700 clrbits_le32(priv->mac_reg + EMAC_RX_CTL0, EMAC_RX_CTL0_RX_EN);
701 clrbits_le32(priv->mac_reg + EMAC_TX_CTL0, EMAC_TX_CTL0_TX_EN);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530702
Andre Przywara4fe86412020-07-06 01:40:36 +0100703 /* Stop RX/TX DMA */
704 clrbits_le32(priv->mac_reg + EMAC_TX_CTL1, EMAC_TX_CTL1_TX_DMA_EN);
705 clrbits_le32(priv->mac_reg + EMAC_RX_CTL1, EMAC_RX_CTL1_RX_DMA_EN);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530706
707 phy_shutdown(priv->phydev);
708}
709
710static int sun8i_emac_eth_probe(struct udevice *dev)
711{
Simon Glassc69cda22020-12-03 16:55:20 -0700712 struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100713 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530714 struct emac_eth_dev *priv = dev_get_priv(dev);
Jagan Tekid3a2c052019-02-28 00:26:58 +0530715 int ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530716
717 priv->mac_reg = (void *)pdata->iobase;
718
Sean Andersonef043692020-09-15 10:45:00 -0400719 ret = sun8i_emac_board_setup(dev, priv);
Jagan Tekid3a2c052019-02-28 00:26:58 +0530720 if (ret)
721 return ret;
722
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100723 sun8i_emac_set_syscon(sun8i_pdata, priv);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530724
Andre Przywara5ad98c52022-06-08 14:56:56 +0100725 if (priv->phy_reg)
726 regulator_set_enable(priv->phy_reg, true);
727
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100728 sun8i_mdio_init(dev->name, dev);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530729 priv->bus = miiphy_get_dev_by_name(dev->name);
730
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530731 return sun8i_phy_init(priv, dev);
732}
733
734static const struct eth_ops sun8i_emac_eth_ops = {
735 .start = sun8i_emac_eth_start,
736 .write_hwaddr = sun8i_eth_write_hwaddr,
737 .send = sun8i_emac_eth_send,
738 .recv = sun8i_emac_eth_recv,
739 .free_pkt = sun8i_eth_free_pkt,
740 .stop = sun8i_emac_eth_stop,
741};
742
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530743static int sun8i_handle_internal_phy(struct udevice *dev, struct emac_eth_dev *priv)
Jagan Teki23484532019-02-28 00:27:00 +0530744{
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530745 struct ofnode_phandle_args phandle;
746 int ret;
Emmanuel Vadotd53e5222019-07-19 22:26:38 +0200747
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530748 ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "phy-handle",
749 NULL, 0, 0, &phandle);
750 if (ret)
751 return ret;
Jagan Teki23484532019-02-28 00:27:00 +0530752
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530753 /* If the PHY node is not a child of the internal MDIO bus, we are
754 * using some external PHY.
755 */
756 if (!ofnode_device_is_compatible(ofnode_get_parent(phandle.node),
757 "allwinner,sun8i-h3-mdio-internal"))
Emmanuel Vadotd53e5222019-07-19 22:26:38 +0200758 return 0;
759
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530760 ret = clk_get_by_index_nodev(phandle.node, 0, &priv->ephy_clk);
Jagan Teki23484532019-02-28 00:27:00 +0530761 if (ret) {
762 dev_err(dev, "failed to get EPHY TX clock\n");
763 return ret;
764 }
765
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530766 ret = reset_get_by_index_nodev(phandle.node, 0, &priv->ephy_rst);
Jagan Teki23484532019-02-28 00:27:00 +0530767 if (ret) {
768 dev_err(dev, "failed to get EPHY TX reset\n");
769 return ret;
770 }
771
772 priv->use_internal_phy = true;
773
774 return 0;
775}
776
Simon Glassd1998a92020-12-03 16:55:21 -0700777static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530778{
Simon Glassc69cda22020-12-03 16:55:20 -0700779 struct sun8i_eth_pdata *sun8i_pdata = dev_get_plat(dev);
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100780 struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530781 struct emac_eth_dev *priv = dev_get_priv(dev);
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600782 phys_addr_t syscon_base;
Andre Przywaraecd0cec2018-04-04 01:31:20 +0100783 const fdt32_t *reg;
Simon Glasse160f7d2017-01-17 16:52:55 -0700784 int node = dev_of_offset(dev);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530785 int offset = 0;
Simon Glassbcee8d62019-12-06 21:41:35 -0700786#if CONFIG_IS_ENABLED(DM_GPIO)
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100787 int reset_flags = GPIOD_IS_OUT;
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100788#endif
Jagan Tekid3a2c052019-02-28 00:26:58 +0530789 int ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530790
Masahiro Yamada25484932020-07-17 14:36:48 +0900791 pdata->iobase = dev_read_addr(dev);
Andre Przywara12afd952018-04-04 01:31:16 +0100792 if (pdata->iobase == FDT_ADDR_T_NONE) {
793 debug("%s: Cannot find MAC base address\n", __func__);
794 return -EINVAL;
795 }
796
Samuel Hollandc86d4732023-01-22 16:51:02 -0600797 priv->variant = (const void *)dev_get_driver_data(dev);
Lothar Feltene46d73f2018-07-13 10:45:28 +0200798
799 if (!priv->variant) {
800 printf("%s: Missing variant\n", __func__);
Andre Przywaraecd0cec2018-04-04 01:31:20 +0100801 return -EINVAL;
Andre Przywara12afd952018-04-04 01:31:16 +0100802 }
Lothar Feltene46d73f2018-07-13 10:45:28 +0200803
Jagan Tekid3a2c052019-02-28 00:26:58 +0530804 ret = clk_get_by_name(dev, "stmmaceth", &priv->tx_clk);
805 if (ret) {
806 dev_err(dev, "failed to get TX clock\n");
807 return ret;
808 }
809
810 ret = reset_get_by_name(dev, "stmmaceth", &priv->tx_rst);
811 if (ret && ret != -ENOENT) {
812 dev_err(dev, "failed to get TX reset\n");
813 return ret;
814 }
815
Jagan Teki695f6042019-02-28 00:26:51 +0530816 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "syscon");
817 if (offset < 0) {
818 debug("%s: cannot find syscon node\n", __func__);
819 return -EINVAL;
820 }
821
822 reg = fdt_getprop(gd->fdt_blob, offset, "reg", NULL);
823 if (!reg) {
824 debug("%s: cannot find reg property in syscon node\n",
825 __func__);
826 return -EINVAL;
827 }
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600828
829 syscon_base = fdt_translate_address((void *)gd->fdt_blob, offset, reg);
830 if (syscon_base == FDT_ADDR_T_NONE) {
Jagan Teki695f6042019-02-28 00:26:51 +0530831 debug("%s: Cannot find syscon base address\n", __func__);
832 return -EINVAL;
Andre Przywara12afd952018-04-04 01:31:16 +0100833 }
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530834
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600835 priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
836
Andre Przywara5ad98c52022-06-08 14:56:56 +0100837 device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
838
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530839 pdata->phy_interface = -1;
840 priv->phyaddr = -1;
841 priv->use_internal_phy = false;
842
Andre Przywaraecd0cec2018-04-04 01:31:20 +0100843 offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
Andre Przywara12afd952018-04-04 01:31:16 +0100844 if (offset < 0) {
845 debug("%s: Cannot find PHY address\n", __func__);
846 return -EINVAL;
847 }
848 priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530849
Marek BehĂșn123ca112022-04-07 00:33:01 +0200850 pdata->phy_interface = dev_read_phy_mode(dev);
Samuel Holland62ee0432022-07-15 00:20:56 -0500851 debug("phy interface %d\n", pdata->phy_interface);
Marek BehĂșnffb0f6f2022-04-07 00:33:03 +0200852 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530853 return -EINVAL;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530854
Samuel Holland0e148342023-01-22 16:51:04 -0600855 if (priv->variant->soc_has_internal_phy) {
Andre Przywara88ae8fb2020-10-21 23:27:32 +0530856 ret = sun8i_handle_internal_phy(dev, priv);
Jagan Teki23484532019-02-28 00:27:00 +0530857 if (ret)
858 return ret;
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530859 }
860
861 priv->interface = pdata->phy_interface;
862
Icenowy Zheng9b16ede2018-11-23 00:37:48 +0100863 sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
864 "allwinner,tx-delay-ps", 0);
865 if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700)
866 printf("%s: Invalid TX delay value %d\n", __func__,
867 sun8i_pdata->tx_delay_ps);
868
869 sun8i_pdata->rx_delay_ps = fdtdec_get_int(gd->fdt_blob, node,
870 "allwinner,rx-delay-ps", 0);
871 if (sun8i_pdata->rx_delay_ps < 0 || sun8i_pdata->rx_delay_ps > 3100)
872 printf("%s: Invalid RX delay value %d\n", __func__,
873 sun8i_pdata->rx_delay_ps);
874
Simon Glassbcee8d62019-12-06 21:41:35 -0700875#if CONFIG_IS_ENABLED(DM_GPIO)
Simon Glassda409cc2017-05-17 17:18:09 -0600876 if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100877 "snps,reset-active-low"))
878 reset_flags |= GPIOD_ACTIVE_LOW;
879
880 ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
881 &priv->reset_gpio, reset_flags);
882
883 if (ret == 0) {
Simon Glassda409cc2017-05-17 17:18:09 -0600884 ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
Philipp Tomsich4d555ae2017-02-22 19:46:41 +0100885 "snps,reset-delays-us",
886 sun8i_pdata->reset_delays, 3);
887 } else if (ret == -ENOENT) {
888 ret = 0;
889 }
890#endif
891
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530892 return 0;
893}
894
Samuel Hollandc86d4732023-01-22 16:51:02 -0600895static const struct emac_variant emac_variant_a83t = {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600896 .syscon_offset = 0x30,
Samuel Hollandc86d4732023-01-22 16:51:02 -0600897};
898
899static const struct emac_variant emac_variant_h3 = {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600900 .syscon_offset = 0x30,
Samuel Holland0e148342023-01-22 16:51:04 -0600901 .soc_has_internal_phy = true,
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600902 .support_rmii = true,
Samuel Hollandc86d4732023-01-22 16:51:02 -0600903};
904
905static const struct emac_variant emac_variant_r40 = {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600906 .syscon_offset = 0x164,
Samuel Hollandc86d4732023-01-22 16:51:02 -0600907};
908
909static const struct emac_variant emac_variant_a64 = {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600910 .syscon_offset = 0x30,
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600911 .support_rmii = true,
Samuel Hollandc86d4732023-01-22 16:51:02 -0600912};
913
914static const struct emac_variant emac_variant_h6 = {
Samuel Holland3cfb1e62023-01-22 16:51:05 -0600915 .syscon_offset = 0x30,
Samuel Hollandc5ac4b12023-01-22 16:51:03 -0600916 .support_rmii = true,
Samuel Hollandc86d4732023-01-22 16:51:02 -0600917};
918
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530919static const struct udevice_id sun8i_emac_eth_ids[] = {
Samuel Hollandc86d4732023-01-22 16:51:02 -0600920 { .compatible = "allwinner,sun8i-a83t-emac",
921 .data = (ulong)&emac_variant_a83t },
922 { .compatible = "allwinner,sun8i-h3-emac",
923 .data = (ulong)&emac_variant_h3 },
924 { .compatible = "allwinner,sun8i-r40-gmac",
925 .data = (ulong)&emac_variant_r40 },
926 { .compatible = "allwinner,sun50i-a64-emac",
927 .data = (ulong)&emac_variant_a64 },
928 { .compatible = "allwinner,sun50i-h6-emac",
929 .data = (ulong)&emac_variant_h6 },
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530930 { }
931};
932
933U_BOOT_DRIVER(eth_sun8i_emac) = {
934 .name = "eth_sun8i_emac",
935 .id = UCLASS_ETH,
936 .of_match = sun8i_emac_eth_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700937 .of_to_plat = sun8i_emac_eth_of_to_plat,
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530938 .probe = sun8i_emac_eth_probe,
939 .ops = &sun8i_emac_eth_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700940 .priv_auto = sizeof(struct emac_eth_dev),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700941 .plat_auto = sizeof(struct sun8i_eth_pdata),
Amit Singh Tomara29710c2016-07-06 17:59:44 +0530942 .flags = DM_FLAG_ALLOC_PRIV_DMA,
943};