blob: e3a7222efba94ae14fe6a2d1fd15ed24ad7fef45 [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>
Simon Glass85d65312019-12-28 10:44:58 -070010#include <clock_legacy.h>
Simon Glass63334482019-11-14 12:57:39 -070011#include <cpu_func.h>
Marek Vasut0a3d0e12016-05-24 23:29:09 +020012#include <dm.h>
13#include <errno.h>
14#include <miiphy.h>
15#include <malloc.h>
16#include <linux/compiler.h>
17#include <linux/err.h>
18#include <linux/mii.h>
19#include <wait_bit.h>
20#include <asm/io.h>
21
22#include <mach/ath79.h>
23
24DECLARE_GLOBAL_DATA_PTR;
25
26enum ag7xxx_model {
27 AG7XXX_MODEL_AG933X,
28 AG7XXX_MODEL_AG934X,
Rosy Song51ef2e72019-03-16 09:24:50 +080029 AG7XXX_MODEL_AG953X,
30 AG7XXX_MODEL_AG956X
Marek Vasut0a3d0e12016-05-24 23:29:09 +020031};
32
Joe Hershbergera1a837d2017-06-26 14:40:08 -050033/* MAC Configuration 1 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020034#define AG7XXX_ETH_CFG1 0x00
35#define AG7XXX_ETH_CFG1_SOFT_RST BIT(31)
36#define AG7XXX_ETH_CFG1_RX_RST BIT(19)
37#define AG7XXX_ETH_CFG1_TX_RST BIT(18)
38#define AG7XXX_ETH_CFG1_LOOPBACK BIT(8)
39#define AG7XXX_ETH_CFG1_RX_EN BIT(2)
40#define AG7XXX_ETH_CFG1_TX_EN BIT(0)
41
Joe Hershbergera1a837d2017-06-26 14:40:08 -050042/* MAC Configuration 2 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020043#define AG7XXX_ETH_CFG2 0x04
44#define AG7XXX_ETH_CFG2_IF_1000 BIT(9)
45#define AG7XXX_ETH_CFG2_IF_10_100 BIT(8)
46#define AG7XXX_ETH_CFG2_IF_SPEED_MASK (3 << 8)
47#define AG7XXX_ETH_CFG2_HUGE_FRAME_EN BIT(5)
48#define AG7XXX_ETH_CFG2_LEN_CHECK BIT(4)
49#define AG7XXX_ETH_CFG2_PAD_CRC_EN BIT(2)
50#define AG7XXX_ETH_CFG2_FDX BIT(0)
51
Joe Hershbergera1a837d2017-06-26 14:40:08 -050052/* MII Configuration */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020053#define AG7XXX_ETH_MII_MGMT_CFG 0x20
54#define AG7XXX_ETH_MII_MGMT_CFG_RESET BIT(31)
55
Joe Hershbergera1a837d2017-06-26 14:40:08 -050056/* MII Command */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020057#define AG7XXX_ETH_MII_MGMT_CMD 0x24
58#define AG7XXX_ETH_MII_MGMT_CMD_READ 0x1
59
Joe Hershbergera1a837d2017-06-26 14:40:08 -050060/* MII Address */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020061#define AG7XXX_ETH_MII_MGMT_ADDRESS 0x28
62#define AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT 8
63
Joe Hershbergera1a837d2017-06-26 14:40:08 -050064/* MII Control */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020065#define AG7XXX_ETH_MII_MGMT_CTRL 0x2c
66
Joe Hershbergera1a837d2017-06-26 14:40:08 -050067/* MII Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020068#define AG7XXX_ETH_MII_MGMT_STATUS 0x30
69
Joe Hershbergera1a837d2017-06-26 14:40:08 -050070/* MII Indicators */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020071#define AG7XXX_ETH_MII_MGMT_IND 0x34
72#define AG7XXX_ETH_MII_MGMT_IND_INVALID BIT(2)
73#define AG7XXX_ETH_MII_MGMT_IND_BUSY BIT(0)
74
Joe Hershbergera1a837d2017-06-26 14:40:08 -050075/* STA Address 1 & 2 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020076#define AG7XXX_ETH_ADDR1 0x40
77#define AG7XXX_ETH_ADDR2 0x44
78
Joe Hershbergera1a837d2017-06-26 14:40:08 -050079/* ETH Configuration 0 - 5 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020080#define AG7XXX_ETH_FIFO_CFG_0 0x48
81#define AG7XXX_ETH_FIFO_CFG_1 0x4c
82#define AG7XXX_ETH_FIFO_CFG_2 0x50
83#define AG7XXX_ETH_FIFO_CFG_3 0x54
84#define AG7XXX_ETH_FIFO_CFG_4 0x58
85#define AG7XXX_ETH_FIFO_CFG_5 0x5c
86
Joe Hershbergera1a837d2017-06-26 14:40:08 -050087/* DMA Transfer Control for Queue 0 */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020088#define AG7XXX_ETH_DMA_TX_CTRL 0x180
89#define AG7XXX_ETH_DMA_TX_CTRL_TXE BIT(0)
90
Joe Hershbergera1a837d2017-06-26 14:40:08 -050091/* Descriptor Address for Queue 0 Tx */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020092#define AG7XXX_ETH_DMA_TX_DESC 0x184
93
Joe Hershbergera1a837d2017-06-26 14:40:08 -050094/* DMA Tx Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020095#define AG7XXX_ETH_DMA_TX_STATUS 0x188
96
Joe Hershbergera1a837d2017-06-26 14:40:08 -050097/* Rx Control */
Marek Vasut0a3d0e12016-05-24 23:29:09 +020098#define AG7XXX_ETH_DMA_RX_CTRL 0x18c
99#define AG7XXX_ETH_DMA_RX_CTRL_RXE BIT(0)
100
Joe Hershbergera1a837d2017-06-26 14:40:08 -0500101/* Pointer to Rx Descriptor */
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200102#define AG7XXX_ETH_DMA_RX_DESC 0x190
103
Joe Hershbergera1a837d2017-06-26 14:40:08 -0500104/* Rx Status */
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200105#define AG7XXX_ETH_DMA_RX_STATUS 0x194
106
Rosy Song361c69e2019-02-05 17:50:44 +0800107/* Custom register at 0x1805002C */
108#define AG7XXX_ETH_XMII 0x2C
109#define AG7XXX_ETH_XMII_TX_INVERT BIT(31)
110#define AG7XXX_ETH_XMII_RX_DELAY_LSB 28
111#define AG7XXX_ETH_XMII_RX_DELAY_MASK 0x30000000
112#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \
113 (((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK)
114#define AG7XXX_ETH_XMII_TX_DELAY_LSB 26
115#define AG7XXX_ETH_XMII_TX_DELAY_MASK 0x0c000000
116#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \
117 (((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK)
118#define AG7XXX_ETH_XMII_GIGE BIT(25)
119
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200120/* Custom register at 0x18070000 */
121#define AG7XXX_GMAC_ETH_CFG 0x00
Rosy Song361c69e2019-02-05 17:50:44 +0800122#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB 16
123#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK 0x00030000
124#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \
125 (((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK)
126#define AG7XXX_ETH_CFG_RXD_DELAY_LSB 14
127#define AG7XXX_ETH_CFG_RXD_DELAY_MASK 0x0000c000
128#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x) \
129 (((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200130#define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8)
131#define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7)
132#define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6)
133#define AG7XXX_ETH_CFG_GE0_ERR_EN BIT(5)
134#define AG7XXX_ETH_CFG_MII_GE0_SLAVE BIT(4)
135#define AG7XXX_ETH_CFG_MII_GE0_MASTER BIT(3)
136#define AG7XXX_ETH_CFG_GMII_GE0 BIT(2)
137#define AG7XXX_ETH_CFG_MII_GE0 BIT(1)
138#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0)
139
140#define CONFIG_TX_DESCR_NUM 8
141#define CONFIG_RX_DESCR_NUM 8
142#define CONFIG_ETH_BUFSIZE 2048
143#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
144#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
145
146/* DMA descriptor. */
147struct ag7xxx_dma_desc {
148 u32 data_addr;
149#define AG7XXX_DMADESC_IS_EMPTY BIT(31)
150#define AG7XXX_DMADESC_FTPP_OVERRIDE_OFFSET 16
151#define AG7XXX_DMADESC_PKT_SIZE_OFFSET 0
152#define AG7XXX_DMADESC_PKT_SIZE_MASK 0xfff
153 u32 config;
154 u32 next_desc;
155 u32 _pad[5];
156};
157
158struct ar7xxx_eth_priv {
159 struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
160 struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
161 char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
162 char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
163
164 void __iomem *regs;
165 void __iomem *phyregs;
166
167 struct eth_device *dev;
168 struct phy_device *phydev;
169 struct mii_dev *bus;
170
171 u32 interface;
172 u32 tx_currdescnum;
173 u32 rx_currdescnum;
174 enum ag7xxx_model model;
175};
176
177/*
178 * Switch and MDIO access
179 */
180static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
181{
182 struct ar7xxx_eth_priv *priv = bus->priv;
183 void __iomem *regs = priv->phyregs;
184 int ret;
185
186 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
187 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
188 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
189 writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
190 regs + AG7XXX_ETH_MII_MGMT_CMD);
191
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100192 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
193 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200194 if (ret)
195 return ret;
196
197 *val = readl(regs + AG7XXX_ETH_MII_MGMT_STATUS) & 0xffff;
198 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
199
200 return 0;
201}
202
203static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
204{
205 struct ar7xxx_eth_priv *priv = bus->priv;
206 void __iomem *regs = priv->phyregs;
207 int ret;
208
209 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
210 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
211 writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
212
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100213 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
214 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200215
216 return ret;
217}
218
219static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
220{
221 struct ar7xxx_eth_priv *priv = bus->priv;
222 u32 phy_addr;
223 u32 reg_addr;
224 u32 phy_temp;
225 u32 reg_temp;
Rosy Song51ef2e72019-03-16 09:24:50 +0800226 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200227 u16 rv = 0;
228 int ret;
229
Rosy Song361c69e2019-02-05 17:50:44 +0800230 if (priv->model == AG7XXX_MODEL_AG933X ||
231 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200232 phy_addr = 0x1f;
233 reg_addr = 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800234 } else if (priv->model == AG7XXX_MODEL_AG934X ||
235 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200236 phy_addr = 0x18;
237 reg_addr = 0x00;
238 } else
239 return -EINVAL;
240
Rosy Song51ef2e72019-03-16 09:24:50 +0800241 if (priv->model == AG7XXX_MODEL_AG956X)
242 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
243 else
244 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200245 if (ret)
246 return ret;
247
248 phy_temp = ((reg >> 6) & 0x7) | 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800249 if (priv->model == AG7XXX_MODEL_AG956X)
250 reg_temp = reg_temp_w & 0x1f;
251 else
252 reg_temp = (reg >> 1) & 0x1e;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200253 *val = 0;
254
255 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
256 if (ret < 0)
257 return ret;
258 *val |= rv;
259
Rosy Song51ef2e72019-03-16 09:24:50 +0800260 if (priv->model == AG7XXX_MODEL_AG956X) {
261 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
262 reg_temp = (reg_temp_w + 1) & 0x1f;
263 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv);
264 } else {
265 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
266 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200267 if (ret < 0)
268 return ret;
269 *val |= (rv << 16);
270
271 return 0;
272}
273
274static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
275{
276 struct ar7xxx_eth_priv *priv = bus->priv;
277 u32 phy_addr;
278 u32 reg_addr;
279 u32 phy_temp;
280 u32 reg_temp;
Rosy Song51ef2e72019-03-16 09:24:50 +0800281 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200282 int ret;
283
Rosy Song361c69e2019-02-05 17:50:44 +0800284 if (priv->model == AG7XXX_MODEL_AG933X ||
285 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200286 phy_addr = 0x1f;
287 reg_addr = 0x10;
Rosy Song51ef2e72019-03-16 09:24:50 +0800288 } else if (priv->model == AG7XXX_MODEL_AG934X ||
289 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200290 phy_addr = 0x18;
291 reg_addr = 0x00;
292 } else
293 return -EINVAL;
294
Rosy Song51ef2e72019-03-16 09:24:50 +0800295 if (priv->model == AG7XXX_MODEL_AG956X)
296 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
297 else
298 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200299 if (ret)
300 return ret;
301
Rosy Song51ef2e72019-03-16 09:24:50 +0800302 if (priv->model == AG7XXX_MODEL_AG956X) {
303 reg_temp = (reg_temp_w + 1) & 0x1f;
304 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
305 } else {
306 phy_temp = ((reg >> 6) & 0x7) | 0x10;
307 reg_temp = (reg >> 1) & 0x1e;
308 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200309
310 /*
311 * The switch on AR933x has some special register behavior, which
312 * expects particular write order of their nibbles:
313 * 0x40 ..... MSB first, LSB second
314 * 0x50 ..... MSB first, LSB second
315 * 0x98 ..... LSB first, MSB second
316 * others ... don't care
317 */
318 if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) {
319 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
320 if (ret < 0)
321 return ret;
322
323 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
324 if (ret < 0)
325 return ret;
326 } else {
Rosy Song51ef2e72019-03-16 09:24:50 +0800327 if (priv->model == AG7XXX_MODEL_AG956X)
328 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16);
329 else
330 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200331 if (ret < 0)
332 return ret;
333
Rosy Song51ef2e72019-03-16 09:24:50 +0800334 if (priv->model == AG7XXX_MODEL_AG956X) {
335 phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10;
336 reg_temp = reg_temp_w & 0x1f;
337 }
338
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200339 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
340 if (ret < 0)
341 return ret;
342 }
343
344 return 0;
345}
346
Joe Hershberger5a41d662017-06-26 14:40:09 -0500347static int ag7xxx_mdio_rw(struct mii_dev *bus, int addr, int reg, u32 val)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200348{
349 u32 data;
Joe Hershberger5a41d662017-06-26 14:40:09 -0500350 unsigned long start;
351 int ret;
352 /* No idea if this is long enough or too long */
353 int timeout_ms = 1000;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200354
355 /* Dummy read followed by PHY read/write command. */
Joe Hershberger5a41d662017-06-26 14:40:09 -0500356 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
357 if (ret < 0)
358 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200359 data = val | (reg << 16) | (addr << 21) | BIT(30) | BIT(31);
Joe Hershberger5a41d662017-06-26 14:40:09 -0500360 ret = ag7xxx_switch_reg_write(bus, 0x98, data);
361 if (ret < 0)
362 return ret;
363
364 start = get_timer(0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200365
366 /* Wait for operation to finish */
367 do {
Joe Hershberger5a41d662017-06-26 14:40:09 -0500368 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
369 if (ret < 0)
370 return ret;
371
372 if (get_timer(start) > timeout_ms)
373 return -ETIMEDOUT;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200374 } while (data & BIT(31));
375
376 return data & 0xffff;
377}
378
379static int ag7xxx_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
380{
381 return ag7xxx_mdio_rw(bus, addr, reg, BIT(27));
382}
383
384static int ag7xxx_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
385 u16 val)
386{
Joe Hershberger5a41d662017-06-26 14:40:09 -0500387 int ret;
388
389 ret = ag7xxx_mdio_rw(bus, addr, reg, val);
390 if (ret < 0)
391 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200392 return 0;
393}
394
395/*
396 * DMA ring handlers
397 */
398static void ag7xxx_dma_clean_tx(struct udevice *dev)
399{
400 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
401 struct ag7xxx_dma_desc *curr, *next;
402 u32 start, end;
403 int i;
404
405 for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
406 curr = &priv->tx_mac_descrtable[i];
407 next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM];
408
409 curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]);
410 curr->config = AG7XXX_DMADESC_IS_EMPTY;
411 curr->next_desc = virt_to_phys(next);
412 }
413
414 priv->tx_currdescnum = 0;
415
416 /* Cache: Flush descriptors, don't care about buffers. */
417 start = (u32)(&priv->tx_mac_descrtable[0]);
418 end = start + sizeof(priv->tx_mac_descrtable);
419 flush_dcache_range(start, end);
420}
421
422static void ag7xxx_dma_clean_rx(struct udevice *dev)
423{
424 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
425 struct ag7xxx_dma_desc *curr, *next;
426 u32 start, end;
427 int i;
428
429 for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
430 curr = &priv->rx_mac_descrtable[i];
431 next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM];
432
433 curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]);
434 curr->config = AG7XXX_DMADESC_IS_EMPTY;
435 curr->next_desc = virt_to_phys(next);
436 }
437
438 priv->rx_currdescnum = 0;
439
440 /* Cache: Flush+Invalidate descriptors, Invalidate buffers. */
441 start = (u32)(&priv->rx_mac_descrtable[0]);
442 end = start + sizeof(priv->rx_mac_descrtable);
443 flush_dcache_range(start, end);
444 invalidate_dcache_range(start, end);
445
446 start = (u32)&priv->rxbuffs;
447 end = start + sizeof(priv->rxbuffs);
448 invalidate_dcache_range(start, end);
449}
450
451/*
452 * Ethernet I/O
453 */
454static int ag7xxx_eth_send(struct udevice *dev, void *packet, int length)
455{
456 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
457 struct ag7xxx_dma_desc *curr;
458 u32 start, end;
459
460 curr = &priv->tx_mac_descrtable[priv->tx_currdescnum];
461
462 /* Cache: Invalidate descriptor. */
463 start = (u32)curr;
464 end = start + sizeof(*curr);
465 invalidate_dcache_range(start, end);
466
467 if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) {
468 printf("ag7xxx: Out of TX DMA descriptors!\n");
469 return -EPERM;
470 }
471
472 /* Copy the packet into the data buffer. */
473 memcpy(phys_to_virt(curr->data_addr), packet, length);
474 curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK;
475
476 /* Cache: Flush descriptor, Flush buffer. */
477 start = (u32)curr;
478 end = start + sizeof(*curr);
479 flush_dcache_range(start, end);
480 start = (u32)phys_to_virt(curr->data_addr);
481 end = start + length;
482 flush_dcache_range(start, end);
483
484 /* Load the DMA descriptor and start TX DMA. */
485 writel(AG7XXX_ETH_DMA_TX_CTRL_TXE,
486 priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
487
488 /* Switch to next TX descriptor. */
489 priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM;
490
491 return 0;
492}
493
494static int ag7xxx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
495{
496 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
497 struct ag7xxx_dma_desc *curr;
498 u32 start, end, length;
499
500 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
501
502 /* Cache: Invalidate descriptor. */
503 start = (u32)curr;
504 end = start + sizeof(*curr);
505 invalidate_dcache_range(start, end);
506
507 /* No packets received. */
508 if (curr->config & AG7XXX_DMADESC_IS_EMPTY)
509 return -EAGAIN;
510
511 length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK;
512
513 /* Cache: Invalidate buffer. */
514 start = (u32)phys_to_virt(curr->data_addr);
515 end = start + length;
516 invalidate_dcache_range(start, end);
517
518 /* Receive one packet and return length. */
519 *packetp = phys_to_virt(curr->data_addr);
520 return length;
521}
522
523static int ag7xxx_eth_free_pkt(struct udevice *dev, uchar *packet,
524 int length)
525{
526 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
527 struct ag7xxx_dma_desc *curr;
528 u32 start, end;
529
530 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
531
532 curr->config = AG7XXX_DMADESC_IS_EMPTY;
533
534 /* Cache: Flush descriptor. */
535 start = (u32)curr;
536 end = start + sizeof(*curr);
537 flush_dcache_range(start, end);
538
539 /* Switch to next RX descriptor. */
540 priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM;
541
542 return 0;
543}
544
545static int ag7xxx_eth_start(struct udevice *dev)
546{
547 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
548
549 /* FIXME: Check if link up */
550
551 /* Clear the DMA rings. */
552 ag7xxx_dma_clean_tx(dev);
553 ag7xxx_dma_clean_rx(dev);
554
555 /* Load DMA descriptors and start the RX DMA. */
556 writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]),
557 priv->regs + AG7XXX_ETH_DMA_TX_DESC);
558 writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]),
559 priv->regs + AG7XXX_ETH_DMA_RX_DESC);
560 writel(AG7XXX_ETH_DMA_RX_CTRL_RXE,
561 priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
562
563 return 0;
564}
565
566static void ag7xxx_eth_stop(struct udevice *dev)
567{
568 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
569
570 /* Stop the TX DMA. */
571 writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100572 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
573 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200574
575 /* Stop the RX DMA. */
576 writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
Álvaro Fernández Rojas918de032018-01-23 17:14:55 +0100577 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
578 1000, 0);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200579}
580
581/*
582 * Hardware setup
583 */
584static int ag7xxx_eth_write_hwaddr(struct udevice *dev)
585{
586 struct eth_pdata *pdata = dev_get_platdata(dev);
587 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
588 unsigned char *mac = pdata->enetaddr;
589 u32 macid_lo, macid_hi;
590
591 macid_hi = mac[3] | (mac[2] << 8) | (mac[1] << 16) | (mac[0] << 24);
592 macid_lo = (mac[5] << 16) | (mac[4] << 24);
593
594 writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1);
595 writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2);
596
597 return 0;
598}
599
600static void ag7xxx_hw_setup(struct udevice *dev)
601{
602 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
603 u32 speed;
604
605 setbits_be32(priv->regs + AG7XXX_ETH_CFG1,
606 AG7XXX_ETH_CFG1_RX_RST | AG7XXX_ETH_CFG1_TX_RST |
607 AG7XXX_ETH_CFG1_SOFT_RST);
608
609 mdelay(10);
610
611 writel(AG7XXX_ETH_CFG1_RX_EN | AG7XXX_ETH_CFG1_TX_EN,
612 priv->regs + AG7XXX_ETH_CFG1);
613
614 if (priv->interface == PHY_INTERFACE_MODE_RMII)
615 speed = AG7XXX_ETH_CFG2_IF_10_100;
616 else
617 speed = AG7XXX_ETH_CFG2_IF_1000;
618
619 clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2,
620 AG7XXX_ETH_CFG2_IF_SPEED_MASK,
621 speed | AG7XXX_ETH_CFG2_PAD_CRC_EN |
622 AG7XXX_ETH_CFG2_LEN_CHECK);
623
624 writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
625 writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
626
627 writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0);
628 setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff);
629 writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
630 writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
631 writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5);
632 writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3);
633}
634
635static int ag7xxx_mii_get_div(void)
636{
637 ulong freq = get_bus_freq(0);
638
639 switch (freq / 1000000) {
640 case 150: return 0x7;
641 case 175: return 0x5;
642 case 200: return 0x4;
643 case 210: return 0x9;
644 case 220: return 0x9;
645 default: return 0x7;
646 }
647}
648
649static int ag7xxx_mii_setup(struct udevice *dev)
650{
651 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
652 int i, ret, div = ag7xxx_mii_get_div();
653 u32 reg;
654
655 if (priv->model == AG7XXX_MODEL_AG933X) {
656 /* Unit 0 is PHY-less on AR9331, see datasheet Figure 2-3 */
657 if (priv->interface == PHY_INTERFACE_MODE_RMII)
658 return 0;
659 }
660
Rosy Song361c69e2019-02-05 17:50:44 +0800661 if (priv->model == AG7XXX_MODEL_AG934X)
662 reg = 0x4;
663 else if (priv->model == AG7XXX_MODEL_AG953X)
664 reg = 0x2;
Rosy Song51ef2e72019-03-16 09:24:50 +0800665 else if (priv->model == AG7XXX_MODEL_AG956X)
666 reg = 0x7;
Rosy Song361c69e2019-02-05 17:50:44 +0800667
668 if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song51ef2e72019-03-16 09:24:50 +0800669 priv->model == AG7XXX_MODEL_AG953X ||
670 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800671 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg,
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200672 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Rosy Song361c69e2019-02-05 17:50:44 +0800673 writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200674 return 0;
675 }
676
677 for (i = 0; i < 10; i++) {
678 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | div,
679 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
680 writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
681
682 /* Check the switch */
683 ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, &reg);
684 if (ret)
685 continue;
686
687 if (reg != 0x18007fff)
688 continue;
689
690 return 0;
691 }
692
693 return -EINVAL;
694}
695
696static int ag933x_phy_setup_wan(struct udevice *dev)
697{
698 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
699
700 /* Configure switch port 4 (GMAC0) */
701 return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000);
702}
703
704static int ag933x_phy_setup_lan(struct udevice *dev)
705{
706 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
707 int i, ret;
708 u32 reg;
709
710 /* Reset the switch */
711 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
712 if (ret)
713 return ret;
714 reg |= BIT(31);
715 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg);
716 if (ret)
717 return ret;
718
719 do {
720 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
721 if (ret)
722 return ret;
723 } while (reg & BIT(31));
724
725 /* Configure switch ports 0...3 (GMAC1) */
726 for (i = 0; i < 4; i++) {
727 ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000);
728 if (ret)
729 return ret;
730 }
731
732 /* Enable CPU port */
733 ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8));
734 if (ret)
735 return ret;
736
737 for (i = 0; i < 4; i++) {
738 ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9));
739 if (ret)
740 return ret;
741 }
742
743 /* QM Control */
744 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
745 if (ret)
746 return ret;
747
748 /* Disable Atheros header */
749 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
750 if (ret)
751 return ret;
752
753 /* Tag priority mapping */
754 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
755 if (ret)
756 return ret;
757
758 /* Enable ARP packets to the CPU */
759 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
760 if (ret)
761 return ret;
762 reg |= 0x100000;
763 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg);
764 if (ret)
765 return ret;
766
Rosy Song361c69e2019-02-05 17:50:44 +0800767 return 0;
768}
769
770static int ag953x_phy_setup_wan(struct udevice *dev)
771{
772 int ret;
773 u32 reg = 0;
774 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
775
776 /* Set wan port connect to GE0 */
777 ret = ag7xxx_switch_reg_read(priv->bus, 0x8, &reg);
778 if (ret)
779 return ret;
780
781 ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28));
782 if (ret)
783 return ret;
784
785 /* Configure switch port 4 (GMAC0) */
786 ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000);
787 if (ret)
788 return ret;
789
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200790 return 0;
791}
792
Rosy Song361c69e2019-02-05 17:50:44 +0800793static int ag953x_phy_setup_lan(struct udevice *dev)
794{
795 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
796 int i, ret;
797 u32 reg = 0;
798
799 /* Reset the switch */
800 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
801 if (ret)
802 return ret;
803
804 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31));
805 if (ret)
806 return ret;
807
808 do {
809 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
810 if (ret)
811 return ret;
812 } while (reg & BIT(31));
813
814 ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e);
815 if (ret)
816 return ret;
817
818 /* Set GMII mode */
819 ret = ag7xxx_switch_reg_read(priv->bus, 0x4, &reg);
820 if (ret)
821 return ret;
822
823 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6));
824 if (ret)
825 return ret;
826
827 /* Configure switch ports 0...4 (GMAC1) */
828 for (i = 0; i < 5; i++) {
829 ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000);
830 if (ret)
831 return ret;
832 }
833
834 for (i = 0; i < 5; i++) {
835 ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9));
836 if (ret)
837 return ret;
838 }
839
840 /* QM Control */
841 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
842 if (ret)
843 return ret;
844
845 /* Disable Atheros header */
846 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
847 if (ret)
848 return ret;
849
850 /* Tag priority mapping */
851 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
852 if (ret)
853 return ret;
854
855 /* Enable ARP packets to the CPU */
856 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
857 if (ret)
858 return ret;
859
860 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000);
861 if (ret)
862 return ret;
863
864 /* Enable broadcast packets to the CPU */
865 ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, &reg);
866 if (ret)
867 return ret;
868
869 ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26));
870 if (ret)
871 return ret;
872
873 return 0;
874}
875
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200876static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
877{
878 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
879 int ret;
880
Rosy Song51ef2e72019-03-16 09:24:50 +0800881 if (priv->model == AG7XXX_MODEL_AG953X ||
882 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800883 ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE,
884 ADVERTISE_ALL);
885 } else {
886 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
887 ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
888 ADVERTISE_PAUSE_ASYM);
889 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200890 if (ret)
891 return ret;
892
893 if (priv->model == AG7XXX_MODEL_AG934X) {
894 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000,
895 ADVERTISE_1000FULL);
896 if (ret)
897 return ret;
Rosy Song51ef2e72019-03-16 09:24:50 +0800898 } else if (priv->model == AG7XXX_MODEL_AG956X) {
899 ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000,
900 ADVERTISE_1000FULL);
901 if (ret)
902 return ret;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200903 }
904
Rosy Song51ef2e72019-03-16 09:24:50 +0800905 if (priv->model == AG7XXX_MODEL_AG953X ||
906 priv->model == AG7XXX_MODEL_AG956X)
Rosy Song361c69e2019-02-05 17:50:44 +0800907 return ag7xxx_switch_write(priv->bus, port, MII_BMCR,
908 BMCR_ANENABLE | BMCR_RESET);
909
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200910 return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
911 BMCR_ANENABLE | BMCR_RESET);
912}
913
914static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port)
915{
916 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
917 int ret;
Rosy Song361c69e2019-02-05 17:50:44 +0800918 u16 reg;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200919
Rosy Song51ef2e72019-03-16 09:24:50 +0800920 if (priv->model == AG7XXX_MODEL_AG953X ||
921 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Song361c69e2019-02-05 17:50:44 +0800922 do {
923 ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, &reg);
924 if (ret < 0)
925 return ret;
926 mdelay(10);
927 } while (reg & BMCR_RESET);
928 } else {
929 do {
930 ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
931 if (ret < 0)
932 return ret;
933 mdelay(10);
934 } while (ret & BMCR_RESET);
935 }
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200936
937 return 0;
938}
939
940static int ag933x_phy_setup_common(struct udevice *dev)
941{
942 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
943 int i, ret, phymax;
Rosy Song361c69e2019-02-05 17:50:44 +0800944 u16 reg;
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200945
946 if (priv->model == AG7XXX_MODEL_AG933X)
947 phymax = 4;
Rosy Song361c69e2019-02-05 17:50:44 +0800948 else if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song51ef2e72019-03-16 09:24:50 +0800949 priv->model == AG7XXX_MODEL_AG953X ||
950 priv->model == AG7XXX_MODEL_AG956X)
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200951 phymax = 5;
952 else
953 return -EINVAL;
954
955 if (priv->interface == PHY_INTERFACE_MODE_RMII) {
956 ret = ag933x_phy_setup_reset_set(dev, phymax);
957 if (ret)
958 return ret;
959
960 ret = ag933x_phy_setup_reset_fin(dev, phymax);
961 if (ret)
962 return ret;
963
964 /* Read out link status */
Rosy Song361c69e2019-02-05 17:50:44 +0800965 if (priv->model == AG7XXX_MODEL_AG953X)
966 ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, &reg);
967 else
968 ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200969 if (ret < 0)
970 return ret;
971
972 return 0;
973 }
974
975 /* Switch ports */
976 for (i = 0; i < phymax; i++) {
977 ret = ag933x_phy_setup_reset_set(dev, i);
978 if (ret)
979 return ret;
980 }
981
982 for (i = 0; i < phymax; i++) {
983 ret = ag933x_phy_setup_reset_fin(dev, i);
984 if (ret)
985 return ret;
986 }
987
988 for (i = 0; i < phymax; i++) {
989 /* Read out link status */
Rosy Song51ef2e72019-03-16 09:24:50 +0800990 if (priv->model == AG7XXX_MODEL_AG953X ||
991 priv->model == AG7XXX_MODEL_AG956X)
Rosy Song361c69e2019-02-05 17:50:44 +0800992 ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, &reg);
993 else
994 ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
Marek Vasut0a3d0e12016-05-24 23:29:09 +0200995 if (ret < 0)
996 return ret;
997 }
998
999 return 0;
1000}
1001
1002static int ag934x_phy_setup(struct udevice *dev)
1003{
1004 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1005 int i, ret;
1006 u32 reg;
1007
1008 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1009 if (ret)
1010 return ret;
1011 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000);
1012 if (ret)
1013 return ret;
1014 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000);
1015 if (ret)
1016 return ret;
1017 ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000);
1018 if (ret)
1019 return ret;
1020 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1021 if (ret)
1022 return ret;
1023
1024 /* AR8327/AR8328 v1.0 fixup */
1025 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1026 if (ret)
1027 return ret;
1028 if ((reg & 0xffff) == 0x1201) {
1029 for (i = 0; i < 5; i++) {
1030 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0);
1031 if (ret)
1032 return ret;
1033 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea);
1034 if (ret)
1035 return ret;
1036 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d);
1037 if (ret)
1038 return ret;
1039 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0);
1040 if (ret)
1041 return ret;
1042 }
1043 }
1044
1045 ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, &reg);
1046 if (ret)
1047 return ret;
1048 reg &= ~0x70000;
1049 ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg);
1050 if (ret)
1051 return ret;
1052
1053 return 0;
1054}
1055
Rosy Song51ef2e72019-03-16 09:24:50 +08001056static int ag956x_phy_setup(struct udevice *dev)
1057{
1058 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1059 int i, ret;
1060 u32 reg, ctrl;
1061
1062 ret = ag7xxx_switch_reg_read(priv->bus, 0x0, &reg);
1063 if (ret)
1064 return ret;
1065 if ((reg & 0xffff) >= 0x1301)
1066 ctrl = 0xc74164de;
1067 else
1068 ctrl = 0xc74164d0;
1069
1070 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7));
1071 if (ret)
1072 return ret;
1073
1074 ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl);
1075 if (ret)
1076 return ret;
1077
1078 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1079 if (ret)
1080 return ret;
1081
1082 /*
1083 * Values suggested by the switch team when s17 in sgmii
1084 * configuration. 0x10(S17_PWS_REG) = 0x602613a0
1085 */
1086 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0);
1087 if (ret)
1088 return ret;
1089
1090 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1091 if (ret)
1092 return ret;
1093
1094 /* AR8337/AR8334 v1.0 fixup */
1095 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1096 if (ret)
1097 return ret;
1098 if ((reg & 0xffff) == 0x1301) {
1099 for (i = 0; i < 5; i++) {
1100 /* Turn on Gigabit clock */
1101 ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d);
1102 if (ret)
1103 return ret;
1104 ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820);
1105 if (ret)
1106 return ret;
1107 }
1108 }
1109
1110 return 0;
1111}
1112
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001113static int ag7xxx_mac_probe(struct udevice *dev)
1114{
1115 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1116 int ret;
1117
1118 ag7xxx_hw_setup(dev);
1119 ret = ag7xxx_mii_setup(dev);
1120 if (ret)
1121 return ret;
1122
1123 ag7xxx_eth_write_hwaddr(dev);
1124
1125 if (priv->model == AG7XXX_MODEL_AG933X) {
1126 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1127 ret = ag933x_phy_setup_wan(dev);
1128 else
1129 ret = ag933x_phy_setup_lan(dev);
Rosy Song361c69e2019-02-05 17:50:44 +08001130 } else if (priv->model == AG7XXX_MODEL_AG953X) {
1131 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1132 ret = ag953x_phy_setup_wan(dev);
1133 else
1134 ret = ag953x_phy_setup_lan(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001135 } else if (priv->model == AG7XXX_MODEL_AG934X) {
1136 ret = ag934x_phy_setup(dev);
Rosy Song51ef2e72019-03-16 09:24:50 +08001137 } else if (priv->model == AG7XXX_MODEL_AG956X) {
1138 ret = ag956x_phy_setup(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001139 } else {
1140 return -EINVAL;
1141 }
1142
1143 if (ret)
1144 return ret;
1145
1146 return ag933x_phy_setup_common(dev);
1147}
1148
1149static int ag7xxx_mdio_probe(struct udevice *dev)
1150{
1151 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1152 struct mii_dev *bus = mdio_alloc();
1153
1154 if (!bus)
1155 return -ENOMEM;
1156
1157 bus->read = ag7xxx_mdio_read;
1158 bus->write = ag7xxx_mdio_write;
1159 snprintf(bus->name, sizeof(bus->name), dev->name);
1160
1161 bus->priv = (void *)priv;
1162
1163 return mdio_register(bus);
1164}
1165
1166static int ag7xxx_get_phy_iface_offset(struct udevice *dev)
1167{
1168 int offset;
1169
Simon Glassdd79d6e2017-01-17 16:52:55 -07001170 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), "phy");
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001171 if (offset <= 0) {
1172 debug("%s: PHY OF node not found (ret=%i)\n", __func__, offset);
1173 return -EINVAL;
1174 }
1175
1176 offset = fdt_parent_offset(gd->fdt_blob, offset);
1177 if (offset <= 0) {
1178 debug("%s: PHY OF node parent MDIO bus not found (ret=%i)\n",
1179 __func__, offset);
1180 return -EINVAL;
1181 }
1182
1183 offset = fdt_parent_offset(gd->fdt_blob, offset);
1184 if (offset <= 0) {
1185 debug("%s: PHY MDIO OF node parent MAC not found (ret=%i)\n",
1186 __func__, offset);
1187 return -EINVAL;
1188 }
1189
1190 return offset;
1191}
1192
1193static int ag7xxx_eth_probe(struct udevice *dev)
1194{
1195 struct eth_pdata *pdata = dev_get_platdata(dev);
1196 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1197 void __iomem *iobase, *phyiobase;
1198 int ret, phyreg;
1199
1200 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1201 ret = ag7xxx_get_phy_iface_offset(dev);
1202 if (ret <= 0)
1203 return ret;
1204 phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1);
1205
1206 iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE);
1207 phyiobase = map_physmem(phyreg, 0x200, MAP_NOCACHE);
1208
1209 debug("%s, iobase=%p, phyiobase=%p, priv=%p\n",
1210 __func__, iobase, phyiobase, priv);
1211 priv->regs = iobase;
1212 priv->phyregs = phyiobase;
1213 priv->interface = pdata->phy_interface;
1214 priv->model = dev_get_driver_data(dev);
1215
1216 ret = ag7xxx_mdio_probe(dev);
1217 if (ret)
1218 return ret;
1219
1220 priv->bus = miiphy_get_dev_by_name(dev->name);
1221
1222 ret = ag7xxx_mac_probe(dev);
1223 debug("%s, ret=%d\n", __func__, ret);
1224
1225 return ret;
1226}
1227
1228static int ag7xxx_eth_remove(struct udevice *dev)
1229{
1230 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1231
1232 free(priv->phydev);
1233 mdio_unregister(priv->bus);
1234 mdio_free(priv->bus);
1235
1236 return 0;
1237}
1238
1239static const struct eth_ops ag7xxx_eth_ops = {
1240 .start = ag7xxx_eth_start,
1241 .send = ag7xxx_eth_send,
1242 .recv = ag7xxx_eth_recv,
1243 .free_pkt = ag7xxx_eth_free_pkt,
1244 .stop = ag7xxx_eth_stop,
1245 .write_hwaddr = ag7xxx_eth_write_hwaddr,
1246};
1247
1248static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev)
1249{
1250 struct eth_pdata *pdata = dev_get_platdata(dev);
1251 const char *phy_mode;
1252 int ret;
1253
Simon Glassba1dea42017-05-17 17:18:05 -06001254 pdata->iobase = devfdt_get_addr(dev);
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001255 pdata->phy_interface = -1;
1256
1257 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1258 ret = ag7xxx_get_phy_iface_offset(dev);
1259 if (ret <= 0)
1260 return ret;
1261
1262 phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL);
1263 if (phy_mode)
1264 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
1265 if (pdata->phy_interface == -1) {
1266 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1267 return -EINVAL;
1268 }
1269
1270 return 0;
1271}
1272
1273static const struct udevice_id ag7xxx_eth_ids[] = {
1274 { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
1275 { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
Rosy Song361c69e2019-02-05 17:50:44 +08001276 { .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X },
Rosy Song51ef2e72019-03-16 09:24:50 +08001277 { .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X },
Marek Vasut0a3d0e12016-05-24 23:29:09 +02001278 { }
1279};
1280
1281U_BOOT_DRIVER(eth_ag7xxx) = {
1282 .name = "eth_ag7xxx",
1283 .id = UCLASS_ETH,
1284 .of_match = ag7xxx_eth_ids,
1285 .ofdata_to_platdata = ag7xxx_eth_ofdata_to_platdata,
1286 .probe = ag7xxx_eth_probe,
1287 .remove = ag7xxx_eth_remove,
1288 .ops = &ag7xxx_eth_ops,
1289 .priv_auto_alloc_size = sizeof(struct ar7xxx_eth_priv),
1290 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
1291 .flags = DM_FLAG_ALLOC_PRIV_DMA,
1292};