blob: 7f1dee4b3e4d5b9e6a5b35cf34dde9f6136f05a0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasut0a3d0e12016-05-24 23:29:09 +02002/*
3 * Atheros AR71xx / AR9xxx GMAC driver
4 *
5 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
Rosy Song51ef2e72019-03-16 09:24:50 +08006 * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
Marek Vasut0a3d0e12016-05-24 23:29:09 +02007 */
8
9#include <common.h>
10#include <dm.h>
11#include <errno.h>
12#include <miiphy.h>
13#include <malloc.h>
14#include <linux/compiler.h>
15#include <linux/err.h>
16#include <linux/mii.h>
17#include <wait_bit.h>
18#include <asm/io.h>
19
20#include <mach/ath79.h>
21
22DECLARE_GLOBAL_DATA_PTR;
23
24enum ag7xxx_model {
25 AG7XXX_MODEL_AG933X,
26 AG7XXX_MODEL_AG934X,
Rosy Song51ef2e72019-03-16 09:24:50 +080027 AG7XXX_MODEL_AG953X,
28 AG7XXX_MODEL_AG956X
Marek Vasut0a3d0e12016-05-24 23:29:09 +020029};
30
Joe Hershbergera1a837d2017-06-26 14:40:08 -050031/* MAC Configuration 1 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020032#define AG7XXX_ETH_CFG1 0x00
33#define AG7XXX_ETH_CFG1_SOFT_RST BIT(31)
34#define AG7XXX_ETH_CFG1_RX_RST BIT(19)
35#define AG7XXX_ETH_CFG1_TX_RST BIT(18)
36#define AG7XXX_ETH_CFG1_LOOPBACK BIT(8)
37#define AG7XXX_ETH_CFG1_RX_EN BIT(2)
38#define AG7XXX_ETH_CFG1_TX_EN BIT(0)
39
Joe Hershbergera1a837d2017-06-26 14:40:08 -050040/* MAC Configuration 2 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020041#define AG7XXX_ETH_CFG2 0x04
42#define AG7XXX_ETH_CFG2_IF_1000 BIT(9)
43#define AG7XXX_ETH_CFG2_IF_10_100 BIT(8)
44#define AG7XXX_ETH_CFG2_IF_SPEED_MASK (3 << 8)
45#define AG7XXX_ETH_CFG2_HUGE_FRAME_EN BIT(5)
46#define AG7XXX_ETH_CFG2_LEN_CHECK BIT(4)
47#define AG7XXX_ETH_CFG2_PAD_CRC_EN BIT(2)
48#define AG7XXX_ETH_CFG2_FDX BIT(0)
49
Joe Hershbergera1a837d2017-06-26 14:40:08 -050050/* MII Configuration */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020051#define AG7XXX_ETH_MII_MGMT_CFG 0x20
52#define AG7XXX_ETH_MII_MGMT_CFG_RESET BIT(31)
53
Joe Hershbergera1a837d2017-06-26 14:40:08 -050054/* MII Command */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020055#define AG7XXX_ETH_MII_MGMT_CMD 0x24
56#define AG7XXX_ETH_MII_MGMT_CMD_READ 0x1
57
Joe Hershbergera1a837d2017-06-26 14:40:08 -050058/* MII Address */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020059#define AG7XXX_ETH_MII_MGMT_ADDRESS 0x28
60#define AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT 8
61
Joe Hershbergera1a837d2017-06-26 14:40:08 -050062/* MII Control */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020063#define AG7XXX_ETH_MII_MGMT_CTRL 0x2c
64
Joe Hershbergera1a837d2017-06-26 14:40:08 -050065/* MII Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020066#define AG7XXX_ETH_MII_MGMT_STATUS 0x30
67
Joe Hershbergera1a837d2017-06-26 14:40:08 -050068/* MII Indicators */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020069#define AG7XXX_ETH_MII_MGMT_IND 0x34
70#define AG7XXX_ETH_MII_MGMT_IND_INVALID BIT(2)
71#define AG7XXX_ETH_MII_MGMT_IND_BUSY BIT(0)
72
Joe Hershbergera1a837d2017-06-26 14:40:08 -050073/* STA Address 1 & 2 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020074#define AG7XXX_ETH_ADDR1 0x40
75#define AG7XXX_ETH_ADDR2 0x44
76
Joe Hershbergera1a837d2017-06-26 14:40:08 -050077/* ETH Configuration 0 - 5 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020078#define AG7XXX_ETH_FIFO_CFG_0 0x48
79#define AG7XXX_ETH_FIFO_CFG_1 0x4c
80#define AG7XXX_ETH_FIFO_CFG_2 0x50
81#define AG7XXX_ETH_FIFO_CFG_3 0x54
82#define AG7XXX_ETH_FIFO_CFG_4 0x58
83#define AG7XXX_ETH_FIFO_CFG_5 0x5c
84
Joe Hershbergera1a837d2017-06-26 14:40:08 -050085/* DMA Transfer Control for Queue 0 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020086#define AG7XXX_ETH_DMA_TX_CTRL 0x180
87#define AG7XXX_ETH_DMA_TX_CTRL_TXE BIT(0)
88
Joe Hershbergera1a837d2017-06-26 14:40:08 -050089/* Descriptor Address for Queue 0 Tx */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020090#define AG7XXX_ETH_DMA_TX_DESC 0x184
91
Joe Hershbergera1a837d2017-06-26 14:40:08 -050092/* DMA Tx Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020093#define AG7XXX_ETH_DMA_TX_STATUS 0x188
94
Joe Hershbergera1a837d2017-06-26 14:40:08 -050095/* Rx Control */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020096#define AG7XXX_ETH_DMA_RX_CTRL 0x18c
97#define AG7XXX_ETH_DMA_RX_CTRL_RXE BIT(0)
98
Joe Hershbergera1a837d2017-06-26 14:40:08 -050099/* Pointer to Rx Descriptor */
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200100#define AG7XXX_ETH_DMA_RX_DESC 0x190
101
Joe Hershbergera1a837d2017-06-26 14:40:08 -0500102/* Rx Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200103#define AG7XXX_ETH_DMA_RX_STATUS 0x194
104
Rosy Song361c69e2019-02-05 17:50:44 +0800105/* Custom register at 0x1805002C */
106#define AG7XXX_ETH_XMII 0x2C
107#define AG7XXX_ETH_XMII_TX_INVERT BIT(31)
108#define AG7XXX_ETH_XMII_RX_DELAY_LSB 28
109#define AG7XXX_ETH_XMII_RX_DELAY_MASK 0x30000000
110#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \
111 (((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK)
112#define AG7XXX_ETH_XMII_TX_DELAY_LSB 26
113#define AG7XXX_ETH_XMII_TX_DELAY_MASK 0x0c000000
114#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \
115 (((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK)
116#define AG7XXX_ETH_XMII_GIGE BIT(25)
117
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200118/* Custom register at 0x18070000 */
119#define AG7XXX_GMAC_ETH_CFG 0x00
Rosy Song361c69e2019-02-05 17:50:44 +0800120#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB 16
121#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK 0x00030000
122#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \
123 (((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK)
124#define AG7XXX_ETH_CFG_RXD_DELAY_LSB 14
125#define AG7XXX_ETH_CFG_RXD_DELAY_MASK 0x0000c000
126#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x) \
127 (((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200128#define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8)
129#define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7)
130#define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6)
131#define AG7XXX_ETH_CFG_GE0_ERR_EN BIT(5)
132#define AG7XXX_ETH_CFG_MII_GE0_SLAVE BIT(4)
133#define AG7XXX_ETH_CFG_MII_GE0_MASTER BIT(3)
134#define AG7XXX_ETH_CFG_GMII_GE0 BIT(2)
135#define AG7XXX_ETH_CFG_MII_GE0 BIT(1)
136#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0)
137
138#define CONFIG_TX_DESCR_NUM 8
139#define CONFIG_RX_DESCR_NUM 8
140#define CONFIG_ETH_BUFSIZE 2048
141#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
142#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
143
144/* DMA descriptor. */
145struct ag7xxx_dma_desc {
146 u32 data_addr;
147#define AG7XXX_DMADESC_IS_EMPTY BIT(31)
148#define AG7XXX_DMADESC_FTPP_OVERRIDE_OFFSET 16
149#define AG7XXX_DMADESC_PKT_SIZE_OFFSET 0
150#define AG7XXX_DMADESC_PKT_SIZE_MASK 0xfff
151 u32 config;
152 u32 next_desc;
153 u32 _pad[5];
154};
155
156struct ar7xxx_eth_priv {
157 struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
158 struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
159 char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
160 char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
161
162 void __iomem *regs;
163 void __iomem *phyregs;
164
165 struct eth_device *dev;
166 struct phy_device *phydev;
167 struct mii_dev *bus;
168
169 u32 interface;
170 u32 tx_currdescnum;
171 u32 rx_currdescnum;
172 enum ag7xxx_model model;
173};
174
175/*
176 * Switch and MDIO access
177 */
178static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
179{
180 struct ar7xxx_eth_priv *priv = bus->priv;
181 void __iomem *regs = priv->phyregs;
182 int ret;
183
184 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
185 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
186 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
187 writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
188 regs + AG7XXX_ETH_MII_MGMT_CMD);
189
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100190 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
191 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200192 if (ret)
193 return ret;
194
195 *val = readl(regs + AG7XXX_ETH_MII_MGMT_STATUS) & 0xffff;
196 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
197
198 return 0;
199}
200
201static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
202{
203 struct ar7xxx_eth_priv *priv = bus->priv;
204 void __iomem *regs = priv->phyregs;
205 int ret;
206
207 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
208 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
209 writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
210
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100211 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
212 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200213
214 return ret;
215}
216
217static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
218{
219 struct ar7xxx_eth_priv *priv = bus->priv;
220 u32 phy_addr;
221 u32 reg_addr;
222 u32 phy_temp;
223 u32 reg_temp;
Rosy Song51ef2e72019-03-16 09:24:50 +0800224 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200225 u16 rv = 0;
226 int ret;
227
Rosy Song361c69e2019-02-05 17:50:44 +0800228 if (priv->model == AG7XXX_MODEL_AG933X ||
229 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200230 phy_addr = 0x1f;
231 reg_addr = 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800232 } else if (priv->model == AG7XXX_MODEL_AG934X ||
233 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200234 phy_addr = 0x18;
235 reg_addr = 0x00;
236 } else
237 return -EINVAL;
238
Rosy Song51ef2e72019-03-16 09:24:50 +0800239 if (priv->model == AG7XXX_MODEL_AG956X)
240 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
241 else
242 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200243 if (ret)
244 return ret;
245
246 phy_temp = ((reg >> 6) & 0x7) | 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800247 if (priv->model == AG7XXX_MODEL_AG956X)
248 reg_temp = reg_temp_w & 0x1f;
249 else
250 reg_temp = (reg >> 1) & 0x1e;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200251 *val = 0;
252
253 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
254 if (ret < 0)
255 return ret;
256 *val |= rv;
257
Rosy Song51ef2e72019-03-16 09:24:50 +0800258 if (priv->model == AG7XXX_MODEL_AG956X) {
259 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
260 reg_temp = (reg_temp_w + 1) & 0x1f;
261 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv);
262 } else {
263 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
264 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200265 if (ret < 0)
266 return ret;
267 *val |= (rv << 16);
268
269 return 0;
270}
271
272static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
273{
274 struct ar7xxx_eth_priv *priv = bus->priv;
275 u32 phy_addr;
276 u32 reg_addr;
277 u32 phy_temp;
278 u32 reg_temp;
Rosy Song51ef2e72019-03-16 09:24:50 +0800279 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200280 int ret;
281
Rosy Song361c69e2019-02-05 17:50:44 +0800282 if (priv->model == AG7XXX_MODEL_AG933X ||
283 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200284 phy_addr = 0x1f;
285 reg_addr = 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800286 } else if (priv->model == AG7XXX_MODEL_AG934X ||
287 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200288 phy_addr = 0x18;
289 reg_addr = 0x00;
290 } else
291 return -EINVAL;
292
Rosy Song51ef2e72019-03-16 09:24:50 +0800293 if (priv->model == AG7XXX_MODEL_AG956X)
294 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
295 else
296 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200297 if (ret)
298 return ret;
299
Rosy Song51ef2e72019-03-16 09:24:50 +0800300 if (priv->model == AG7XXX_MODEL_AG956X) {
301 reg_temp = (reg_temp_w + 1) & 0x1f;
302 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
303 } else {
304 phy_temp = ((reg >> 6) & 0x7) | 0x10;
305 reg_temp = (reg >> 1) & 0x1e;
306 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200307
308 /*
309 * The switch on AR933x has some special register behavior, which
310 * expects particular write order of their nibbles:
311 * 0x40 ..... MSB first, LSB second
312 * 0x50 ..... MSB first, LSB second
313 * 0x98 ..... LSB first, MSB second
314 * others ... don't care
315 */
316 if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) {
317 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
318 if (ret < 0)
319 return ret;
320
321 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
322 if (ret < 0)
323 return ret;
324 } else {
Rosy Song51ef2e72019-03-16 09:24:50 +0800325 if (priv->model == AG7XXX_MODEL_AG956X)
326 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16);
327 else
328 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200329 if (ret < 0)
330 return ret;
331
Rosy Song51ef2e72019-03-16 09:24:50 +0800332 if (priv->model == AG7XXX_MODEL_AG956X) {
333 phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10;
334 reg_temp = reg_temp_w & 0x1f;
335 }
336
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200337 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
338 if (ret < 0)
339 return ret;
340 }
341
342 return 0;
343}
344
Joe Hershberger5a41d662017-06-26 14:40:09 -0500345static int ag7xxx_mdio_rw(struct mii_dev *bus, int addr, int reg, u32 val)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200346{
347 u32 data;
Joe Hershberger5a41d662017-06-26 14:40:09 -0500348 unsigned long start;
349 int ret;
350 /* No idea if this is long enough or too long */
351 int timeout_ms = 1000;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200352
353 /* Dummy read followed by PHY read/write command. */
Joe Hershberger5a41d662017-06-26 14:40:09 -0500354 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
355 if (ret < 0)
356 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200357 data = val | (reg << 16) | (addr << 21) | BIT(30) | BIT(31);
Joe Hershberger5a41d662017-06-26 14:40:09 -0500358 ret = ag7xxx_switch_reg_write(bus, 0x98, data);
359 if (ret < 0)
360 return ret;
361
362 start = get_timer(0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200363
364 /* Wait for operation to finish */
365 do {
Joe Hershberger5a41d662017-06-26 14:40:09 -0500366 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
367 if (ret < 0)
368 return ret;
369
370 if (get_timer(start) > timeout_ms)
371 return -ETIMEDOUT;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200372 } while (data & BIT(31));
373
374 return data & 0xffff;
375}
376
377static int ag7xxx_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
378{
379 return ag7xxx_mdio_rw(bus, addr, reg, BIT(27));
380}
381
382static int ag7xxx_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
383 u16 val)
384{
Joe Hershberger5a41d662017-06-26 14:40:09 -0500385 int ret;
386
387 ret = ag7xxx_mdio_rw(bus, addr, reg, val);
388 if (ret < 0)
389 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200390 return 0;
391}
392
393/*
394 * DMA ring handlers
395 */
396static void ag7xxx_dma_clean_tx(struct udevice *dev)
397{
398 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
399 struct ag7xxx_dma_desc *curr, *next;
400 u32 start, end;
401 int i;
402
403 for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
404 curr = &priv->tx_mac_descrtable[i];
405 next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM];
406
407 curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]);
408 curr->config = AG7XXX_DMADESC_IS_EMPTY;
409 curr->next_desc = virt_to_phys(next);
410 }
411
412 priv->tx_currdescnum = 0;
413
414 /* Cache: Flush descriptors, don't care about buffers. */
415 start = (u32)(&priv->tx_mac_descrtable[0]);
416 end = start + sizeof(priv->tx_mac_descrtable);
417 flush_dcache_range(start, end);
418}
419
420static void ag7xxx_dma_clean_rx(struct udevice *dev)
421{
422 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
423 struct ag7xxx_dma_desc *curr, *next;
424 u32 start, end;
425 int i;
426
427 for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
428 curr = &priv->rx_mac_descrtable[i];
429 next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM];
430
431 curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]);
432 curr->config = AG7XXX_DMADESC_IS_EMPTY;
433 curr->next_desc = virt_to_phys(next);
434 }
435
436 priv->rx_currdescnum = 0;
437
438 /* Cache: Flush+Invalidate descriptors, Invalidate buffers. */
439 start = (u32)(&priv->rx_mac_descrtable[0]);
440 end = start + sizeof(priv->rx_mac_descrtable);
441 flush_dcache_range(start, end);
442 invalidate_dcache_range(start, end);
443
444 start = (u32)&priv->rxbuffs;
445 end = start + sizeof(priv->rxbuffs);
446 invalidate_dcache_range(start, end);
447}
448
449/*
450 * Ethernet I/O
451 */
452static int ag7xxx_eth_send(struct udevice *dev, void *packet, int length)
453{
454 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
455 struct ag7xxx_dma_desc *curr;
456 u32 start, end;
457
458 curr = &priv->tx_mac_descrtable[priv->tx_currdescnum];
459
460 /* Cache: Invalidate descriptor. */
461 start = (u32)curr;
462 end = start + sizeof(*curr);
463 invalidate_dcache_range(start, end);
464
465 if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) {
466 printf("ag7xxx: Out of TX DMA descriptors!\n");
467 return -EPERM;
468 }
469
470 /* Copy the packet into the data buffer. */
471 memcpy(phys_to_virt(curr->data_addr), packet, length);
472 curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK;
473
474 /* Cache: Flush descriptor, Flush buffer. */
475 start = (u32)curr;
476 end = start + sizeof(*curr);
477 flush_dcache_range(start, end);
478 start = (u32)phys_to_virt(curr->data_addr);
479 end = start + length;
480 flush_dcache_range(start, end);
481
482 /* Load the DMA descriptor and start TX DMA. */
483 writel(AG7XXX_ETH_DMA_TX_CTRL_TXE,
484 priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
485
486 /* Switch to next TX descriptor. */
487 priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM;
488
489 return 0;
490}
491
492static int ag7xxx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
493{
494 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
495 struct ag7xxx_dma_desc *curr;
496 u32 start, end, length;
497
498 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
499
500 /* Cache: Invalidate descriptor. */
501 start = (u32)curr;
502 end = start + sizeof(*curr);
503 invalidate_dcache_range(start, end);
504
505 /* No packets received. */
506 if (curr->config & AG7XXX_DMADESC_IS_EMPTY)
507 return -EAGAIN;
508
509 length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK;
510
511 /* Cache: Invalidate buffer. */
512 start = (u32)phys_to_virt(curr->data_addr);
513 end = start + length;
514 invalidate_dcache_range(start, end);
515
516 /* Receive one packet and return length. */
517 *packetp = phys_to_virt(curr->data_addr);
518 return length;
519}
520
521static int ag7xxx_eth_free_pkt(struct udevice *dev, uchar *packet,
522 int length)
523{
524 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
525 struct ag7xxx_dma_desc *curr;
526 u32 start, end;
527
528 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
529
530 curr->config = AG7XXX_DMADESC_IS_EMPTY;
531
532 /* Cache: Flush descriptor. */
533 start = (u32)curr;
534 end = start + sizeof(*curr);
535 flush_dcache_range(start, end);
536
537 /* Switch to next RX descriptor. */
538 priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM;
539
540 return 0;
541}
542
543static int ag7xxx_eth_start(struct udevice *dev)
544{
545 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
546
547 /* FIXME: Check if link up */
548
549 /* Clear the DMA rings. */
550 ag7xxx_dma_clean_tx(dev);
551 ag7xxx_dma_clean_rx(dev);
552
553 /* Load DMA descriptors and start the RX DMA. */
554 writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]),
555 priv->regs + AG7XXX_ETH_DMA_TX_DESC);
556 writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]),
557 priv->regs + AG7XXX_ETH_DMA_RX_DESC);
558 writel(AG7XXX_ETH_DMA_RX_CTRL_RXE,
559 priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
560
561 return 0;
562}
563
564static void ag7xxx_eth_stop(struct udevice *dev)
565{
566 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
567
568 /* Stop the TX DMA. */
569 writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100570 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
571 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200572
573 /* Stop the RX DMA. */
574 writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100575 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
576 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200577}
578
579/*
580 * Hardware setup
581 */
582static int ag7xxx_eth_write_hwaddr(struct udevice *dev)
583{
584 struct eth_pdata *pdata = dev_get_platdata(dev);
585 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
586 unsigned char *mac = pdata->enetaddr;
587 u32 macid_lo, macid_hi;
588
589 macid_hi = mac[3] | (mac[2] << 8) | (mac[1] << 16) | (mac[0] << 24);
590 macid_lo = (mac[5] << 16) | (mac[4] << 24);
591
592 writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1);
593 writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2);
594
595 return 0;
596}
597
598static void ag7xxx_hw_setup(struct udevice *dev)
599{
600 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
601 u32 speed;
602
603 setbits_be32(priv->regs + AG7XXX_ETH_CFG1,
604 AG7XXX_ETH_CFG1_RX_RST | AG7XXX_ETH_CFG1_TX_RST |
605 AG7XXX_ETH_CFG1_SOFT_RST);
606
607 mdelay(10);
608
609 writel(AG7XXX_ETH_CFG1_RX_EN | AG7XXX_ETH_CFG1_TX_EN,
610 priv->regs + AG7XXX_ETH_CFG1);
611
612 if (priv->interface == PHY_INTERFACE_MODE_RMII)
613 speed = AG7XXX_ETH_CFG2_IF_10_100;
614 else
615 speed = AG7XXX_ETH_CFG2_IF_1000;
616
617 clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2,
618 AG7XXX_ETH_CFG2_IF_SPEED_MASK,
619 speed | AG7XXX_ETH_CFG2_PAD_CRC_EN |
620 AG7XXX_ETH_CFG2_LEN_CHECK);
621
622 writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
623 writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
624
625 writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0);
626 setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff);
627 writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
628 writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
629 writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5);
630 writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3);
631}
632
633static int ag7xxx_mii_get_div(void)
634{
635 ulong freq = get_bus_freq(0);
636
637 switch (freq / 1000000) {
638 case 150: return 0x7;
639 case 175: return 0x5;
640 case 200: return 0x4;
641 case 210: return 0x9;
642 case 220: return 0x9;
643 default: return 0x7;
644 }
645}
646
647static int ag7xxx_mii_setup(struct udevice *dev)
648{
649 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
650 int i, ret, div = ag7xxx_mii_get_div();
651 u32 reg;
652
653 if (priv->model == AG7XXX_MODEL_AG933X) {
654 /* Unit 0 is PHY-less on AR9331, see datasheet Figure 2-3 */
655 if (priv->interface == PHY_INTERFACE_MODE_RMII)
656 return 0;
657 }
658
Rosy Song361c69e2019-02-05 17:50:44 +0800659 if (priv->model == AG7XXX_MODEL_AG934X)
660 reg = 0x4;
661 else if (priv->model == AG7XXX_MODEL_AG953X)
662 reg = 0x2;
Rosy Song51ef2e72019-03-16 09:24:50 +0800663 else if (priv->model == AG7XXX_MODEL_AG956X)
664 reg = 0x7;
Rosy Song361c69e2019-02-05 17:50:44 +0800665
666 if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song51ef2e72019-03-16 09:24:50 +0800667 priv->model == AG7XXX_MODEL_AG953X ||
668 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800669 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg,
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200670 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Rosy Song361c69e2019-02-05 17:50:44 +0800671 writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200672 return 0;
673 }
674
675 for (i = 0; i < 10; i++) {
676 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | div,
677 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
678 writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
679
680 /* Check the switch */
681 ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, &reg);
682 if (ret)
683 continue;
684
685 if (reg != 0x18007fff)
686 continue;
687
688 return 0;
689 }
690
691 return -EINVAL;
692}
693
694static int ag933x_phy_setup_wan(struct udevice *dev)
695{
696 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
697
698 /* Configure switch port 4 (GMAC0) */
699 return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000);
700}
701
702static int ag933x_phy_setup_lan(struct udevice *dev)
703{
704 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
705 int i, ret;
706 u32 reg;
707
708 /* Reset the switch */
709 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
710 if (ret)
711 return ret;
712 reg |= BIT(31);
713 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg);
714 if (ret)
715 return ret;
716
717 do {
718 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
719 if (ret)
720 return ret;
721 } while (reg & BIT(31));
722
723 /* Configure switch ports 0...3 (GMAC1) */
724 for (i = 0; i < 4; i++) {
725 ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000);
726 if (ret)
727 return ret;
728 }
729
730 /* Enable CPU port */
731 ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8));
732 if (ret)
733 return ret;
734
735 for (i = 0; i < 4; i++) {
736 ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9));
737 if (ret)
738 return ret;
739 }
740
741 /* QM Control */
742 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
743 if (ret)
744 return ret;
745
746 /* Disable Atheros header */
747 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
748 if (ret)
749 return ret;
750
751 /* Tag priority mapping */
752 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
753 if (ret)
754 return ret;
755
756 /* Enable ARP packets to the CPU */
757 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
758 if (ret)
759 return ret;
760 reg |= 0x100000;
761 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg);
762 if (ret)
763 return ret;
764
Rosy Song361c69e2019-02-05 17:50:44 +0800765 return 0;
766}
767
768static int ag953x_phy_setup_wan(struct udevice *dev)
769{
770 int ret;
771 u32 reg = 0;
772 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
773
774 /* Set wan port connect to GE0 */
775 ret = ag7xxx_switch_reg_read(priv->bus, 0x8, &reg);
776 if (ret)
777 return ret;
778
779 ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28));
780 if (ret)
781 return ret;
782
783 /* Configure switch port 4 (GMAC0) */
784 ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000);
785 if (ret)
786 return ret;
787
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200788 return 0;
789}
790
Rosy Song361c69e2019-02-05 17:50:44 +0800791static int ag953x_phy_setup_lan(struct udevice *dev)
792{
793 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
794 int i, ret;
795 u32 reg = 0;
796
797 /* Reset the switch */
798 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
799 if (ret)
800 return ret;
801
802 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31));
803 if (ret)
804 return ret;
805
806 do {
807 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
808 if (ret)
809 return ret;
810 } while (reg & BIT(31));
811
812 ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e);
813 if (ret)
814 return ret;
815
816 /* Set GMII mode */
817 ret = ag7xxx_switch_reg_read(priv->bus, 0x4, &reg);
818 if (ret)
819 return ret;
820
821 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6));
822 if (ret)
823 return ret;
824
825 /* Configure switch ports 0...4 (GMAC1) */
826 for (i = 0; i < 5; i++) {
827 ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000);
828 if (ret)
829 return ret;
830 }
831
832 for (i = 0; i < 5; i++) {
833 ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9));
834 if (ret)
835 return ret;
836 }
837
838 /* QM Control */
839 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
840 if (ret)
841 return ret;
842
843 /* Disable Atheros header */
844 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
845 if (ret)
846 return ret;
847
848 /* Tag priority mapping */
849 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
850 if (ret)
851 return ret;
852
853 /* Enable ARP packets to the CPU */
854 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
855 if (ret)
856 return ret;
857
858 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000);
859 if (ret)
860 return ret;
861
862 /* Enable broadcast packets to the CPU */
863 ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, &reg);
864 if (ret)
865 return ret;
866
867 ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26));
868 if (ret)
869 return ret;
870
871 return 0;
872}
873
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200874static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
875{
876 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
877 int ret;
878
Rosy Song51ef2e72019-03-16 09:24:50 +0800879 if (priv->model == AG7XXX_MODEL_AG953X ||
880 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800881 ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE,
882 ADVERTISE_ALL);
883 } else {
884 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
885 ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
886 ADVERTISE_PAUSE_ASYM);
887 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200888 if (ret)
889 return ret;
890
891 if (priv->model == AG7XXX_MODEL_AG934X) {
892 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000,
893 ADVERTISE_1000FULL);
894 if (ret)
895 return ret;
Rosy Song51ef2e72019-03-16 09:24:50 +0800896 } else if (priv->model == AG7XXX_MODEL_AG956X) {
897 ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000,
898 ADVERTISE_1000FULL);
899 if (ret)
900 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200901 }
902
Rosy Song51ef2e72019-03-16 09:24:50 +0800903 if (priv->model == AG7XXX_MODEL_AG953X ||
904 priv->model == AG7XXX_MODEL_AG956X)
Rosy Song361c69e2019-02-05 17:50:44 +0800905 return ag7xxx_switch_write(priv->bus, port, MII_BMCR,
906 BMCR_ANENABLE | BMCR_RESET);
907
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200908 return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
909 BMCR_ANENABLE | BMCR_RESET);
910}
911
912static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port)
913{
914 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
915 int ret;
Rosy Song361c69e2019-02-05 17:50:44 +0800916 u16 reg;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200917
Rosy Song51ef2e72019-03-16 09:24:50 +0800918 if (priv->model == AG7XXX_MODEL_AG953X ||
919 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800920 do {
921 ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, &reg);
922 if (ret < 0)
923 return ret;
924 mdelay(10);
925 } while (reg & BMCR_RESET);
926 } else {
927 do {
928 ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
929 if (ret < 0)
930 return ret;
931 mdelay(10);
932 } while (ret & BMCR_RESET);
933 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200934
935 return 0;
936}
937
938static int ag933x_phy_setup_common(struct udevice *dev)
939{
940 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
941 int i, ret, phymax;
Rosy Song361c69e2019-02-05 17:50:44 +0800942 u16 reg;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200943
944 if (priv->model == AG7XXX_MODEL_AG933X)
945 phymax = 4;
Rosy Song361c69e2019-02-05 17:50:44 +0800946 else if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song51ef2e72019-03-16 09:24:50 +0800947 priv->model == AG7XXX_MODEL_AG953X ||
948 priv->model == AG7XXX_MODEL_AG956X)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200949 phymax = 5;
950 else
951 return -EINVAL;
952
953 if (priv->interface == PHY_INTERFACE_MODE_RMII) {
954 ret = ag933x_phy_setup_reset_set(dev, phymax);
955 if (ret)
956 return ret;
957
958 ret = ag933x_phy_setup_reset_fin(dev, phymax);
959 if (ret)
960 return ret;
961
962 /* Read out link status */
Rosy Song361c69e2019-02-05 17:50:44 +0800963 if (priv->model == AG7XXX_MODEL_AG953X)
964 ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, &reg);
965 else
966 ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200967 if (ret < 0)
968 return ret;
969
970 return 0;
971 }
972
973 /* Switch ports */
974 for (i = 0; i < phymax; i++) {
975 ret = ag933x_phy_setup_reset_set(dev, i);
976 if (ret)
977 return ret;
978 }
979
980 for (i = 0; i < phymax; i++) {
981 ret = ag933x_phy_setup_reset_fin(dev, i);
982 if (ret)
983 return ret;
984 }
985
986 for (i = 0; i < phymax; i++) {
987 /* Read out link status */
Rosy Song51ef2e72019-03-16 09:24:50 +0800988 if (priv->model == AG7XXX_MODEL_AG953X ||
989 priv->model == AG7XXX_MODEL_AG956X)
Rosy Song361c69e2019-02-05 17:50:44 +0800990 ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, &reg);
991 else
992 ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200993 if (ret < 0)
994 return ret;
995 }
996
997 return 0;
998}
999
1000static int ag934x_phy_setup(struct udevice *dev)
1001{
1002 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1003 int i, ret;
1004 u32 reg;
1005
1006 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1007 if (ret)
1008 return ret;
1009 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000);
1010 if (ret)
1011 return ret;
1012 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000);
1013 if (ret)
1014 return ret;
1015 ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000);
1016 if (ret)
1017 return ret;
1018 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1019 if (ret)
1020 return ret;
1021
1022 /* AR8327/AR8328 v1.0 fixup */
1023 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1024 if (ret)
1025 return ret;
1026 if ((reg & 0xffff) == 0x1201) {
1027 for (i = 0; i < 5; i++) {
1028 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0);
1029 if (ret)
1030 return ret;
1031 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea);
1032 if (ret)
1033 return ret;
1034 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d);
1035 if (ret)
1036 return ret;
1037 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0);
1038 if (ret)
1039 return ret;
1040 }
1041 }
1042
1043 ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, &reg);
1044 if (ret)
1045 return ret;
1046 reg &= ~0x70000;
1047 ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg);
1048 if (ret)
1049 return ret;
1050
1051 return 0;
1052}
1053
Rosy Song51ef2e72019-03-16 09:24:50 +08001054static int ag956x_phy_setup(struct udevice *dev)
1055{
1056 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1057 int i, ret;
1058 u32 reg, ctrl;
1059
1060 ret = ag7xxx_switch_reg_read(priv->bus, 0x0, &reg);
1061 if (ret)
1062 return ret;
1063 if ((reg & 0xffff) >= 0x1301)
1064 ctrl = 0xc74164de;
1065 else
1066 ctrl = 0xc74164d0;
1067
1068 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7));
1069 if (ret)
1070 return ret;
1071
1072 ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl);
1073 if (ret)
1074 return ret;
1075
1076 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1077 if (ret)
1078 return ret;
1079
1080 /*
1081 * Values suggested by the switch team when s17 in sgmii
1082 * configuration. 0x10(S17_PWS_REG) = 0x602613a0
1083 */
1084 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0);
1085 if (ret)
1086 return ret;
1087
1088 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1089 if (ret)
1090 return ret;
1091
1092 /* AR8337/AR8334 v1.0 fixup */
1093 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1094 if (ret)
1095 return ret;
1096 if ((reg & 0xffff) == 0x1301) {
1097 for (i = 0; i < 5; i++) {
1098 /* Turn on Gigabit clock */
1099 ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d);
1100 if (ret)
1101 return ret;
1102 ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820);
1103 if (ret)
1104 return ret;
1105 }
1106 }
1107
1108 return 0;
1109}
1110
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001111static int ag7xxx_mac_probe(struct udevice *dev)
1112{
1113 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1114 int ret;
1115
1116 ag7xxx_hw_setup(dev);
1117 ret = ag7xxx_mii_setup(dev);
1118 if (ret)
1119 return ret;
1120
1121 ag7xxx_eth_write_hwaddr(dev);
1122
1123 if (priv->model == AG7XXX_MODEL_AG933X) {
1124 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1125 ret = ag933x_phy_setup_wan(dev);
1126 else
1127 ret = ag933x_phy_setup_lan(dev);
Rosy Song361c69e2019-02-05 17:50:44 +08001128 } else if (priv->model == AG7XXX_MODEL_AG953X) {
1129 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1130 ret = ag953x_phy_setup_wan(dev);
1131 else
1132 ret = ag953x_phy_setup_lan(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001133 } else if (priv->model == AG7XXX_MODEL_AG934X) {
1134 ret = ag934x_phy_setup(dev);
Rosy Song51ef2e72019-03-16 09:24:50 +08001135 } else if (priv->model == AG7XXX_MODEL_AG956X) {
1136 ret = ag956x_phy_setup(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001137 } else {
1138 return -EINVAL;
1139 }
1140
1141 if (ret)
1142 return ret;
1143
1144 return ag933x_phy_setup_common(dev);
1145}
1146
1147static int ag7xxx_mdio_probe(struct udevice *dev)
1148{
1149 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1150 struct mii_dev *bus = mdio_alloc();
1151
1152 if (!bus)
1153 return -ENOMEM;
1154
1155 bus->read = ag7xxx_mdio_read;
1156 bus->write = ag7xxx_mdio_write;
1157 snprintf(bus->name, sizeof(bus->name), dev->name);
1158
1159 bus->priv = (void *)priv;
1160
1161 return mdio_register(bus);
1162}
1163
1164static int ag7xxx_get_phy_iface_offset(struct udevice *dev)
1165{
1166 int offset;
1167
Simon Glassdd79d6e2017-01-17 16:52:55 -07001168 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), "phy");
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001169 if (offset <= 0) {
1170 debug("%s: PHY OF node not found (ret=%i)\n", __func__, offset);
1171 return -EINVAL;
1172 }
1173
1174 offset = fdt_parent_offset(gd->fdt_blob, offset);
1175 if (offset <= 0) {
1176 debug("%s: PHY OF node parent MDIO bus not found (ret=%i)\n",
1177 __func__, offset);
1178 return -EINVAL;
1179 }
1180
1181 offset = fdt_parent_offset(gd->fdt_blob, offset);
1182 if (offset <= 0) {
1183 debug("%s: PHY MDIO OF node parent MAC not found (ret=%i)\n",
1184 __func__, offset);
1185 return -EINVAL;
1186 }
1187
1188 return offset;
1189}
1190
1191static int ag7xxx_eth_probe(struct udevice *dev)
1192{
1193 struct eth_pdata *pdata = dev_get_platdata(dev);
1194 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1195 void __iomem *iobase, *phyiobase;
1196 int ret, phyreg;
1197
1198 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1199 ret = ag7xxx_get_phy_iface_offset(dev);
1200 if (ret <= 0)
1201 return ret;
1202 phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1);
1203
1204 iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE);
1205 phyiobase = map_physmem(phyreg, 0x200, MAP_NOCACHE);
1206
1207 debug("%s, iobase=%p, phyiobase=%p, priv=%p\n",
1208 __func__, iobase, phyiobase, priv);
1209 priv->regs = iobase;
1210 priv->phyregs = phyiobase;
1211 priv->interface = pdata->phy_interface;
1212 priv->model = dev_get_driver_data(dev);
1213
1214 ret = ag7xxx_mdio_probe(dev);
1215 if (ret)
1216 return ret;
1217
1218 priv->bus = miiphy_get_dev_by_name(dev->name);
1219
1220 ret = ag7xxx_mac_probe(dev);
1221 debug("%s, ret=%d\n", __func__, ret);
1222
1223 return ret;
1224}
1225
1226static int ag7xxx_eth_remove(struct udevice *dev)
1227{
1228 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1229
1230 free(priv->phydev);
1231 mdio_unregister(priv->bus);
1232 mdio_free(priv->bus);
1233
1234 return 0;
1235}
1236
1237static const struct eth_ops ag7xxx_eth_ops = {
1238 .start = ag7xxx_eth_start,
1239 .send = ag7xxx_eth_send,
1240 .recv = ag7xxx_eth_recv,
1241 .free_pkt = ag7xxx_eth_free_pkt,
1242 .stop = ag7xxx_eth_stop,
1243 .write_hwaddr = ag7xxx_eth_write_hwaddr,
1244};
1245
1246static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev)
1247{
1248 struct eth_pdata *pdata = dev_get_platdata(dev);
1249 const char *phy_mode;
1250 int ret;
1251
Simon Glassba1dea42017-05-17 17:18:05 -06001252 pdata->iobase = devfdt_get_addr(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001253 pdata->phy_interface = -1;
1254
1255 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1256 ret = ag7xxx_get_phy_iface_offset(dev);
1257 if (ret <= 0)
1258 return ret;
1259
1260 phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL);
1261 if (phy_mode)
1262 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
1263 if (pdata->phy_interface == -1) {
1264 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1265 return -EINVAL;
1266 }
1267
1268 return 0;
1269}
1270
1271static const struct udevice_id ag7xxx_eth_ids[] = {
1272 { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
1273 { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
Rosy Song361c69e2019-02-05 17:50:44 +08001274 { .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X },
Rosy Song51ef2e72019-03-16 09:24:50 +08001275 { .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X },
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001276 { }
1277};
1278
1279U_BOOT_DRIVER(eth_ag7xxx) = {
1280 .name = "eth_ag7xxx",
1281 .id = UCLASS_ETH,
1282 .of_match = ag7xxx_eth_ids,
1283 .ofdata_to_platdata = ag7xxx_eth_ofdata_to_platdata,
1284 .probe = ag7xxx_eth_probe,
1285 .remove = ag7xxx_eth_remove,
1286 .ops = &ag7xxx_eth_ops,
1287 .priv_auto_alloc_size = sizeof(struct ar7xxx_eth_priv),
1288 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
1289 .flags = DM_FLAG_ALLOC_PRIV_DMA,
1290};