blob: 38f3cbac734ade53d94e321d094fa937b6804800 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasute40095f2016-05-24 23:29:09 +02002/*
3 * Atheros AR71xx / AR9xxx GMAC driver
4 *
5 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
Rosy Song84265232019-03-16 09:24:50 +08006 * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
Marek Vasute40095f2016-05-24 23:29:09 +02007 */
8
9#include <common.h>
Simon Glassd96c2602019-12-28 10:44:58 -070010#include <clock_legacy.h>
Simon Glass1eb69ae2019-11-14 12:57:39 -070011#include <cpu_func.h>
Marek Vasute40095f2016-05-24 23:29:09 +020012#include <dm.h>
13#include <errno.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060014#include <log.h>
Marek Vasute40095f2016-05-24 23:29:09 +020015#include <miiphy.h>
16#include <malloc.h>
Simon Glass90526e92020-05-10 11:39:56 -060017#include <net.h>
18#include <asm/cache.h>
Marek Vasute40095f2016-05-24 23:29:09 +020019#include <linux/compiler.h>
20#include <linux/err.h>
21#include <linux/mii.h>
22#include <wait_bit.h>
23#include <asm/io.h>
24
25#include <mach/ath79.h>
26
27DECLARE_GLOBAL_DATA_PTR;
28
29enum ag7xxx_model {
30 AG7XXX_MODEL_AG933X,
31 AG7XXX_MODEL_AG934X,
Rosy Song84265232019-03-16 09:24:50 +080032 AG7XXX_MODEL_AG953X,
33 AG7XXX_MODEL_AG956X
Marek Vasute40095f2016-05-24 23:29:09 +020034};
35
Joe Hershberger9240a2f2017-06-26 14:40:08 -050036/* MAC Configuration 1 */
Marek Vasute40095f2016-05-24 23:29:09 +020037#define AG7XXX_ETH_CFG1 0x00
38#define AG7XXX_ETH_CFG1_SOFT_RST BIT(31)
39#define AG7XXX_ETH_CFG1_RX_RST BIT(19)
40#define AG7XXX_ETH_CFG1_TX_RST BIT(18)
41#define AG7XXX_ETH_CFG1_LOOPBACK BIT(8)
42#define AG7XXX_ETH_CFG1_RX_EN BIT(2)
43#define AG7XXX_ETH_CFG1_TX_EN BIT(0)
44
Joe Hershberger9240a2f2017-06-26 14:40:08 -050045/* MAC Configuration 2 */
Marek Vasute40095f2016-05-24 23:29:09 +020046#define AG7XXX_ETH_CFG2 0x04
47#define AG7XXX_ETH_CFG2_IF_1000 BIT(9)
48#define AG7XXX_ETH_CFG2_IF_10_100 BIT(8)
49#define AG7XXX_ETH_CFG2_IF_SPEED_MASK (3 << 8)
50#define AG7XXX_ETH_CFG2_HUGE_FRAME_EN BIT(5)
51#define AG7XXX_ETH_CFG2_LEN_CHECK BIT(4)
52#define AG7XXX_ETH_CFG2_PAD_CRC_EN BIT(2)
53#define AG7XXX_ETH_CFG2_FDX BIT(0)
54
Joe Hershberger9240a2f2017-06-26 14:40:08 -050055/* MII Configuration */
Marek Vasute40095f2016-05-24 23:29:09 +020056#define AG7XXX_ETH_MII_MGMT_CFG 0x20
57#define AG7XXX_ETH_MII_MGMT_CFG_RESET BIT(31)
58
Joe Hershberger9240a2f2017-06-26 14:40:08 -050059/* MII Command */
Marek Vasute40095f2016-05-24 23:29:09 +020060#define AG7XXX_ETH_MII_MGMT_CMD 0x24
61#define AG7XXX_ETH_MII_MGMT_CMD_READ 0x1
62
Joe Hershberger9240a2f2017-06-26 14:40:08 -050063/* MII Address */
Marek Vasute40095f2016-05-24 23:29:09 +020064#define AG7XXX_ETH_MII_MGMT_ADDRESS 0x28
65#define AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT 8
66
Joe Hershberger9240a2f2017-06-26 14:40:08 -050067/* MII Control */
Marek Vasute40095f2016-05-24 23:29:09 +020068#define AG7XXX_ETH_MII_MGMT_CTRL 0x2c
69
Joe Hershberger9240a2f2017-06-26 14:40:08 -050070/* MII Status */
Marek Vasute40095f2016-05-24 23:29:09 +020071#define AG7XXX_ETH_MII_MGMT_STATUS 0x30
72
Joe Hershberger9240a2f2017-06-26 14:40:08 -050073/* MII Indicators */
Marek Vasute40095f2016-05-24 23:29:09 +020074#define AG7XXX_ETH_MII_MGMT_IND 0x34
75#define AG7XXX_ETH_MII_MGMT_IND_INVALID BIT(2)
76#define AG7XXX_ETH_MII_MGMT_IND_BUSY BIT(0)
77
Joe Hershberger9240a2f2017-06-26 14:40:08 -050078/* STA Address 1 & 2 */
Marek Vasute40095f2016-05-24 23:29:09 +020079#define AG7XXX_ETH_ADDR1 0x40
80#define AG7XXX_ETH_ADDR2 0x44
81
Joe Hershberger9240a2f2017-06-26 14:40:08 -050082/* ETH Configuration 0 - 5 */
Marek Vasute40095f2016-05-24 23:29:09 +020083#define AG7XXX_ETH_FIFO_CFG_0 0x48
84#define AG7XXX_ETH_FIFO_CFG_1 0x4c
85#define AG7XXX_ETH_FIFO_CFG_2 0x50
86#define AG7XXX_ETH_FIFO_CFG_3 0x54
87#define AG7XXX_ETH_FIFO_CFG_4 0x58
88#define AG7XXX_ETH_FIFO_CFG_5 0x5c
89
Joe Hershberger9240a2f2017-06-26 14:40:08 -050090/* DMA Transfer Control for Queue 0 */
Marek Vasute40095f2016-05-24 23:29:09 +020091#define AG7XXX_ETH_DMA_TX_CTRL 0x180
92#define AG7XXX_ETH_DMA_TX_CTRL_TXE BIT(0)
93
Joe Hershberger9240a2f2017-06-26 14:40:08 -050094/* Descriptor Address for Queue 0 Tx */
Marek Vasute40095f2016-05-24 23:29:09 +020095#define AG7XXX_ETH_DMA_TX_DESC 0x184
96
Joe Hershberger9240a2f2017-06-26 14:40:08 -050097/* DMA Tx Status */
Marek Vasute40095f2016-05-24 23:29:09 +020098#define AG7XXX_ETH_DMA_TX_STATUS 0x188
99
Joe Hershberger9240a2f2017-06-26 14:40:08 -0500100/* Rx Control */
Marek Vasute40095f2016-05-24 23:29:09 +0200101#define AG7XXX_ETH_DMA_RX_CTRL 0x18c
102#define AG7XXX_ETH_DMA_RX_CTRL_RXE BIT(0)
103
Joe Hershberger9240a2f2017-06-26 14:40:08 -0500104/* Pointer to Rx Descriptor */
Marek Vasute40095f2016-05-24 23:29:09 +0200105#define AG7XXX_ETH_DMA_RX_DESC 0x190
106
Joe Hershberger9240a2f2017-06-26 14:40:08 -0500107/* Rx Status */
Marek Vasute40095f2016-05-24 23:29:09 +0200108#define AG7XXX_ETH_DMA_RX_STATUS 0x194
109
Rosy Songf1f943e2019-02-05 17:50:44 +0800110/* Custom register at 0x1805002C */
111#define AG7XXX_ETH_XMII 0x2C
112#define AG7XXX_ETH_XMII_TX_INVERT BIT(31)
113#define AG7XXX_ETH_XMII_RX_DELAY_LSB 28
114#define AG7XXX_ETH_XMII_RX_DELAY_MASK 0x30000000
115#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \
116 (((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK)
117#define AG7XXX_ETH_XMII_TX_DELAY_LSB 26
118#define AG7XXX_ETH_XMII_TX_DELAY_MASK 0x0c000000
119#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \
120 (((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK)
121#define AG7XXX_ETH_XMII_GIGE BIT(25)
122
Marek Vasute40095f2016-05-24 23:29:09 +0200123/* Custom register at 0x18070000 */
124#define AG7XXX_GMAC_ETH_CFG 0x00
Rosy Songf1f943e2019-02-05 17:50:44 +0800125#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB 16
126#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK 0x00030000
127#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \
128 (((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK)
129#define AG7XXX_ETH_CFG_RXD_DELAY_LSB 14
130#define AG7XXX_ETH_CFG_RXD_DELAY_MASK 0x0000c000
131#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x) \
132 (((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK)
Marek Vasute40095f2016-05-24 23:29:09 +0200133#define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8)
134#define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7)
135#define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6)
136#define AG7XXX_ETH_CFG_GE0_ERR_EN BIT(5)
137#define AG7XXX_ETH_CFG_MII_GE0_SLAVE BIT(4)
138#define AG7XXX_ETH_CFG_MII_GE0_MASTER BIT(3)
139#define AG7XXX_ETH_CFG_GMII_GE0 BIT(2)
140#define AG7XXX_ETH_CFG_MII_GE0 BIT(1)
141#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0)
142
143#define CONFIG_TX_DESCR_NUM 8
144#define CONFIG_RX_DESCR_NUM 8
145#define CONFIG_ETH_BUFSIZE 2048
146#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
147#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
148
149/* DMA descriptor. */
150struct ag7xxx_dma_desc {
151 u32 data_addr;
152#define AG7XXX_DMADESC_IS_EMPTY BIT(31)
153#define AG7XXX_DMADESC_FTPP_OVERRIDE_OFFSET 16
154#define AG7XXX_DMADESC_PKT_SIZE_OFFSET 0
155#define AG7XXX_DMADESC_PKT_SIZE_MASK 0xfff
156 u32 config;
157 u32 next_desc;
158 u32 _pad[5];
159};
160
161struct ar7xxx_eth_priv {
162 struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
163 struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
164 char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
165 char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
166
167 void __iomem *regs;
168 void __iomem *phyregs;
169
170 struct eth_device *dev;
171 struct phy_device *phydev;
172 struct mii_dev *bus;
173
174 u32 interface;
175 u32 tx_currdescnum;
176 u32 rx_currdescnum;
177 enum ag7xxx_model model;
178};
179
180/*
181 * Switch and MDIO access
182 */
183static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
184{
185 struct ar7xxx_eth_priv *priv = bus->priv;
186 void __iomem *regs = priv->phyregs;
187 int ret;
188
189 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
190 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
191 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
192 writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
193 regs + AG7XXX_ETH_MII_MGMT_CMD);
194
Álvaro Fernández Rojas48263502018-01-23 17:14:55 +0100195 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
196 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasute40095f2016-05-24 23:29:09 +0200197 if (ret)
198 return ret;
199
200 *val = readl(regs + AG7XXX_ETH_MII_MGMT_STATUS) & 0xffff;
201 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
202
203 return 0;
204}
205
206static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
207{
208 struct ar7xxx_eth_priv *priv = bus->priv;
209 void __iomem *regs = priv->phyregs;
210 int ret;
211
212 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
213 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
214 writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
215
Álvaro Fernández Rojas48263502018-01-23 17:14:55 +0100216 ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
217 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
Marek Vasute40095f2016-05-24 23:29:09 +0200218
219 return ret;
220}
221
222static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
223{
224 struct ar7xxx_eth_priv *priv = bus->priv;
225 u32 phy_addr;
226 u32 reg_addr;
227 u32 phy_temp;
228 u32 reg_temp;
Rosy Song84265232019-03-16 09:24:50 +0800229 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasute40095f2016-05-24 23:29:09 +0200230 u16 rv = 0;
231 int ret;
232
Rosy Songf1f943e2019-02-05 17:50:44 +0800233 if (priv->model == AG7XXX_MODEL_AG933X ||
234 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasute40095f2016-05-24 23:29:09 +0200235 phy_addr = 0x1f;
236 reg_addr = 0x10;
Rosy Song84265232019-03-16 09:24:50 +0800237 } else if (priv->model == AG7XXX_MODEL_AG934X ||
238 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasute40095f2016-05-24 23:29:09 +0200239 phy_addr = 0x18;
240 reg_addr = 0x00;
241 } else
242 return -EINVAL;
243
Rosy Song84265232019-03-16 09:24:50 +0800244 if (priv->model == AG7XXX_MODEL_AG956X)
245 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
246 else
247 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasute40095f2016-05-24 23:29:09 +0200248 if (ret)
249 return ret;
250
251 phy_temp = ((reg >> 6) & 0x7) | 0x10;
Rosy Song84265232019-03-16 09:24:50 +0800252 if (priv->model == AG7XXX_MODEL_AG956X)
253 reg_temp = reg_temp_w & 0x1f;
254 else
255 reg_temp = (reg >> 1) & 0x1e;
Marek Vasute40095f2016-05-24 23:29:09 +0200256 *val = 0;
257
258 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
259 if (ret < 0)
260 return ret;
261 *val |= rv;
262
Rosy Song84265232019-03-16 09:24:50 +0800263 if (priv->model == AG7XXX_MODEL_AG956X) {
264 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
265 reg_temp = (reg_temp_w + 1) & 0x1f;
266 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv);
267 } else {
268 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
269 }
Marek Vasute40095f2016-05-24 23:29:09 +0200270 if (ret < 0)
271 return ret;
272 *val |= (rv << 16);
273
274 return 0;
275}
276
277static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
278{
279 struct ar7xxx_eth_priv *priv = bus->priv;
280 u32 phy_addr;
281 u32 reg_addr;
282 u32 phy_temp;
283 u32 reg_temp;
Rosy Song84265232019-03-16 09:24:50 +0800284 u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
Marek Vasute40095f2016-05-24 23:29:09 +0200285 int ret;
286
Rosy Songf1f943e2019-02-05 17:50:44 +0800287 if (priv->model == AG7XXX_MODEL_AG933X ||
288 priv->model == AG7XXX_MODEL_AG953X) {
Marek Vasute40095f2016-05-24 23:29:09 +0200289 phy_addr = 0x1f;
290 reg_addr = 0x10;
Rosy Song84265232019-03-16 09:24:50 +0800291 } else if (priv->model == AG7XXX_MODEL_AG934X ||
292 priv->model == AG7XXX_MODEL_AG956X) {
Marek Vasute40095f2016-05-24 23:29:09 +0200293 phy_addr = 0x18;
294 reg_addr = 0x00;
295 } else
296 return -EINVAL;
297
Rosy Song84265232019-03-16 09:24:50 +0800298 if (priv->model == AG7XXX_MODEL_AG956X)
299 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
300 else
301 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
Marek Vasute40095f2016-05-24 23:29:09 +0200302 if (ret)
303 return ret;
304
Rosy Song84265232019-03-16 09:24:50 +0800305 if (priv->model == AG7XXX_MODEL_AG956X) {
306 reg_temp = (reg_temp_w + 1) & 0x1f;
307 phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
308 } else {
309 phy_temp = ((reg >> 6) & 0x7) | 0x10;
310 reg_temp = (reg >> 1) & 0x1e;
311 }
Marek Vasute40095f2016-05-24 23:29:09 +0200312
313 /*
314 * The switch on AR933x has some special register behavior, which
315 * expects particular write order of their nibbles:
316 * 0x40 ..... MSB first, LSB second
317 * 0x50 ..... MSB first, LSB second
318 * 0x98 ..... LSB first, MSB second
319 * others ... don't care
320 */
321 if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) {
322 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
323 if (ret < 0)
324 return ret;
325
326 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
327 if (ret < 0)
328 return ret;
329 } else {
Rosy Song84265232019-03-16 09:24:50 +0800330 if (priv->model == AG7XXX_MODEL_AG956X)
331 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16);
332 else
333 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
Marek Vasute40095f2016-05-24 23:29:09 +0200334 if (ret < 0)
335 return ret;
336
Rosy Song84265232019-03-16 09:24:50 +0800337 if (priv->model == AG7XXX_MODEL_AG956X) {
338 phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10;
339 reg_temp = reg_temp_w & 0x1f;
340 }
341
Marek Vasute40095f2016-05-24 23:29:09 +0200342 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
343 if (ret < 0)
344 return ret;
345 }
346
347 return 0;
348}
349
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500350static int ag7xxx_mdio_rw(struct mii_dev *bus, int addr, int reg, u32 val)
Marek Vasute40095f2016-05-24 23:29:09 +0200351{
352 u32 data;
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500353 unsigned long start;
354 int ret;
355 /* No idea if this is long enough or too long */
356 int timeout_ms = 1000;
Marek Vasute40095f2016-05-24 23:29:09 +0200357
358 /* Dummy read followed by PHY read/write command. */
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500359 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
360 if (ret < 0)
361 return ret;
Marek Vasute40095f2016-05-24 23:29:09 +0200362 data = val | (reg << 16) | (addr << 21) | BIT(30) | BIT(31);
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500363 ret = ag7xxx_switch_reg_write(bus, 0x98, data);
364 if (ret < 0)
365 return ret;
366
367 start = get_timer(0);
Marek Vasute40095f2016-05-24 23:29:09 +0200368
369 /* Wait for operation to finish */
370 do {
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500371 ret = ag7xxx_switch_reg_read(bus, 0x98, &data);
372 if (ret < 0)
373 return ret;
374
375 if (get_timer(start) > timeout_ms)
376 return -ETIMEDOUT;
Marek Vasute40095f2016-05-24 23:29:09 +0200377 } while (data & BIT(31));
378
379 return data & 0xffff;
380}
381
382static int ag7xxx_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
383{
384 return ag7xxx_mdio_rw(bus, addr, reg, BIT(27));
385}
386
387static int ag7xxx_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
388 u16 val)
389{
Joe Hershberger2fd519f2017-06-26 14:40:09 -0500390 int ret;
391
392 ret = ag7xxx_mdio_rw(bus, addr, reg, val);
393 if (ret < 0)
394 return ret;
Marek Vasute40095f2016-05-24 23:29:09 +0200395 return 0;
396}
397
398/*
399 * DMA ring handlers
400 */
401static void ag7xxx_dma_clean_tx(struct udevice *dev)
402{
403 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
404 struct ag7xxx_dma_desc *curr, *next;
405 u32 start, end;
406 int i;
407
408 for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
409 curr = &priv->tx_mac_descrtable[i];
410 next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM];
411
412 curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]);
413 curr->config = AG7XXX_DMADESC_IS_EMPTY;
414 curr->next_desc = virt_to_phys(next);
415 }
416
417 priv->tx_currdescnum = 0;
418
419 /* Cache: Flush descriptors, don't care about buffers. */
420 start = (u32)(&priv->tx_mac_descrtable[0]);
421 end = start + sizeof(priv->tx_mac_descrtable);
422 flush_dcache_range(start, end);
423}
424
425static void ag7xxx_dma_clean_rx(struct udevice *dev)
426{
427 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
428 struct ag7xxx_dma_desc *curr, *next;
429 u32 start, end;
430 int i;
431
432 for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
433 curr = &priv->rx_mac_descrtable[i];
434 next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM];
435
436 curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]);
437 curr->config = AG7XXX_DMADESC_IS_EMPTY;
438 curr->next_desc = virt_to_phys(next);
439 }
440
441 priv->rx_currdescnum = 0;
442
443 /* Cache: Flush+Invalidate descriptors, Invalidate buffers. */
444 start = (u32)(&priv->rx_mac_descrtable[0]);
445 end = start + sizeof(priv->rx_mac_descrtable);
446 flush_dcache_range(start, end);
447 invalidate_dcache_range(start, end);
448
449 start = (u32)&priv->rxbuffs;
450 end = start + sizeof(priv->rxbuffs);
451 invalidate_dcache_range(start, end);
452}
453
454/*
455 * Ethernet I/O
456 */
457static int ag7xxx_eth_send(struct udevice *dev, void *packet, int length)
458{
459 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
460 struct ag7xxx_dma_desc *curr;
461 u32 start, end;
462
463 curr = &priv->tx_mac_descrtable[priv->tx_currdescnum];
464
465 /* Cache: Invalidate descriptor. */
466 start = (u32)curr;
467 end = start + sizeof(*curr);
468 invalidate_dcache_range(start, end);
469
470 if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) {
471 printf("ag7xxx: Out of TX DMA descriptors!\n");
472 return -EPERM;
473 }
474
475 /* Copy the packet into the data buffer. */
476 memcpy(phys_to_virt(curr->data_addr), packet, length);
477 curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK;
478
479 /* Cache: Flush descriptor, Flush buffer. */
480 start = (u32)curr;
481 end = start + sizeof(*curr);
482 flush_dcache_range(start, end);
483 start = (u32)phys_to_virt(curr->data_addr);
484 end = start + length;
485 flush_dcache_range(start, end);
486
487 /* Load the DMA descriptor and start TX DMA. */
488 writel(AG7XXX_ETH_DMA_TX_CTRL_TXE,
489 priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
490
491 /* Switch to next TX descriptor. */
492 priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM;
493
494 return 0;
495}
496
497static int ag7xxx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
498{
499 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
500 struct ag7xxx_dma_desc *curr;
501 u32 start, end, length;
502
503 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
504
505 /* Cache: Invalidate descriptor. */
506 start = (u32)curr;
507 end = start + sizeof(*curr);
508 invalidate_dcache_range(start, end);
509
510 /* No packets received. */
511 if (curr->config & AG7XXX_DMADESC_IS_EMPTY)
512 return -EAGAIN;
513
514 length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK;
515
516 /* Cache: Invalidate buffer. */
517 start = (u32)phys_to_virt(curr->data_addr);
518 end = start + length;
519 invalidate_dcache_range(start, end);
520
521 /* Receive one packet and return length. */
522 *packetp = phys_to_virt(curr->data_addr);
523 return length;
524}
525
526static int ag7xxx_eth_free_pkt(struct udevice *dev, uchar *packet,
527 int length)
528{
529 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
530 struct ag7xxx_dma_desc *curr;
531 u32 start, end;
532
533 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
534
535 curr->config = AG7XXX_DMADESC_IS_EMPTY;
536
537 /* Cache: Flush descriptor. */
538 start = (u32)curr;
539 end = start + sizeof(*curr);
540 flush_dcache_range(start, end);
541
542 /* Switch to next RX descriptor. */
543 priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM;
544
545 return 0;
546}
547
548static int ag7xxx_eth_start(struct udevice *dev)
549{
550 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
551
552 /* FIXME: Check if link up */
553
554 /* Clear the DMA rings. */
555 ag7xxx_dma_clean_tx(dev);
556 ag7xxx_dma_clean_rx(dev);
557
558 /* Load DMA descriptors and start the RX DMA. */
559 writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]),
560 priv->regs + AG7XXX_ETH_DMA_TX_DESC);
561 writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]),
562 priv->regs + AG7XXX_ETH_DMA_RX_DESC);
563 writel(AG7XXX_ETH_DMA_RX_CTRL_RXE,
564 priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
565
566 return 0;
567}
568
569static void ag7xxx_eth_stop(struct udevice *dev)
570{
571 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
572
573 /* Stop the TX DMA. */
574 writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
Álvaro Fernández Rojas48263502018-01-23 17:14:55 +0100575 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
576 1000, 0);
Marek Vasute40095f2016-05-24 23:29:09 +0200577
578 /* Stop the RX DMA. */
579 writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
Álvaro Fernández Rojas48263502018-01-23 17:14:55 +0100580 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
581 1000, 0);
Marek Vasute40095f2016-05-24 23:29:09 +0200582}
583
584/*
585 * Hardware setup
586 */
587static int ag7xxx_eth_write_hwaddr(struct udevice *dev)
588{
589 struct eth_pdata *pdata = dev_get_platdata(dev);
590 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
591 unsigned char *mac = pdata->enetaddr;
592 u32 macid_lo, macid_hi;
593
594 macid_hi = mac[3] | (mac[2] << 8) | (mac[1] << 16) | (mac[0] << 24);
595 macid_lo = (mac[5] << 16) | (mac[4] << 24);
596
597 writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1);
598 writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2);
599
600 return 0;
601}
602
603static void ag7xxx_hw_setup(struct udevice *dev)
604{
605 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
606 u32 speed;
607
608 setbits_be32(priv->regs + AG7XXX_ETH_CFG1,
609 AG7XXX_ETH_CFG1_RX_RST | AG7XXX_ETH_CFG1_TX_RST |
610 AG7XXX_ETH_CFG1_SOFT_RST);
611
612 mdelay(10);
613
614 writel(AG7XXX_ETH_CFG1_RX_EN | AG7XXX_ETH_CFG1_TX_EN,
615 priv->regs + AG7XXX_ETH_CFG1);
616
617 if (priv->interface == PHY_INTERFACE_MODE_RMII)
618 speed = AG7XXX_ETH_CFG2_IF_10_100;
619 else
620 speed = AG7XXX_ETH_CFG2_IF_1000;
621
622 clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2,
623 AG7XXX_ETH_CFG2_IF_SPEED_MASK,
624 speed | AG7XXX_ETH_CFG2_PAD_CRC_EN |
625 AG7XXX_ETH_CFG2_LEN_CHECK);
626
627 writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
628 writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
629
630 writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0);
631 setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff);
632 writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
633 writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
634 writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5);
635 writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3);
636}
637
638static int ag7xxx_mii_get_div(void)
639{
640 ulong freq = get_bus_freq(0);
641
642 switch (freq / 1000000) {
643 case 150: return 0x7;
644 case 175: return 0x5;
645 case 200: return 0x4;
646 case 210: return 0x9;
647 case 220: return 0x9;
648 default: return 0x7;
649 }
650}
651
652static int ag7xxx_mii_setup(struct udevice *dev)
653{
654 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
655 int i, ret, div = ag7xxx_mii_get_div();
656 u32 reg;
657
658 if (priv->model == AG7XXX_MODEL_AG933X) {
659 /* Unit 0 is PHY-less on AR9331, see datasheet Figure 2-3 */
660 if (priv->interface == PHY_INTERFACE_MODE_RMII)
661 return 0;
662 }
663
Rosy Songf1f943e2019-02-05 17:50:44 +0800664 if (priv->model == AG7XXX_MODEL_AG934X)
665 reg = 0x4;
666 else if (priv->model == AG7XXX_MODEL_AG953X)
667 reg = 0x2;
Rosy Song84265232019-03-16 09:24:50 +0800668 else if (priv->model == AG7XXX_MODEL_AG956X)
669 reg = 0x7;
Rosy Songf1f943e2019-02-05 17:50:44 +0800670
671 if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song84265232019-03-16 09:24:50 +0800672 priv->model == AG7XXX_MODEL_AG953X ||
673 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Songf1f943e2019-02-05 17:50:44 +0800674 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg,
Marek Vasute40095f2016-05-24 23:29:09 +0200675 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Rosy Songf1f943e2019-02-05 17:50:44 +0800676 writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
Marek Vasute40095f2016-05-24 23:29:09 +0200677 return 0;
678 }
679
680 for (i = 0; i < 10; i++) {
681 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | div,
682 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
683 writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
684
685 /* Check the switch */
686 ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, &reg);
687 if (ret)
688 continue;
689
690 if (reg != 0x18007fff)
691 continue;
692
693 return 0;
694 }
695
696 return -EINVAL;
697}
698
699static int ag933x_phy_setup_wan(struct udevice *dev)
700{
701 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
702
703 /* Configure switch port 4 (GMAC0) */
704 return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000);
705}
706
707static int ag933x_phy_setup_lan(struct udevice *dev)
708{
709 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
710 int i, ret;
711 u32 reg;
712
713 /* Reset the switch */
714 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
715 if (ret)
716 return ret;
717 reg |= BIT(31);
718 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg);
719 if (ret)
720 return ret;
721
722 do {
723 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
724 if (ret)
725 return ret;
726 } while (reg & BIT(31));
727
728 /* Configure switch ports 0...3 (GMAC1) */
729 for (i = 0; i < 4; i++) {
730 ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000);
731 if (ret)
732 return ret;
733 }
734
735 /* Enable CPU port */
736 ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8));
737 if (ret)
738 return ret;
739
740 for (i = 0; i < 4; i++) {
741 ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9));
742 if (ret)
743 return ret;
744 }
745
746 /* QM Control */
747 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
748 if (ret)
749 return ret;
750
751 /* Disable Atheros header */
752 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
753 if (ret)
754 return ret;
755
756 /* Tag priority mapping */
757 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
758 if (ret)
759 return ret;
760
761 /* Enable ARP packets to the CPU */
762 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
763 if (ret)
764 return ret;
765 reg |= 0x100000;
766 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg);
767 if (ret)
768 return ret;
769
770 return 0;
771}
772
Rosy Songf1f943e2019-02-05 17:50:44 +0800773static int ag953x_phy_setup_wan(struct udevice *dev)
774{
775 int ret;
776 u32 reg = 0;
777 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
778
779 /* Set wan port connect to GE0 */
780 ret = ag7xxx_switch_reg_read(priv->bus, 0x8, &reg);
781 if (ret)
782 return ret;
783
784 ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28));
785 if (ret)
786 return ret;
787
788 /* Configure switch port 4 (GMAC0) */
789 ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000);
790 if (ret)
791 return ret;
792
793 return 0;
794}
795
796static int ag953x_phy_setup_lan(struct udevice *dev)
797{
798 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
799 int i, ret;
800 u32 reg = 0;
801
802 /* Reset the switch */
803 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
804 if (ret)
805 return ret;
806
807 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31));
808 if (ret)
809 return ret;
810
811 do {
812 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
813 if (ret)
814 return ret;
815 } while (reg & BIT(31));
816
817 ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e);
818 if (ret)
819 return ret;
820
821 /* Set GMII mode */
822 ret = ag7xxx_switch_reg_read(priv->bus, 0x4, &reg);
823 if (ret)
824 return ret;
825
826 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6));
827 if (ret)
828 return ret;
829
830 /* Configure switch ports 0...4 (GMAC1) */
831 for (i = 0; i < 5; i++) {
832 ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000);
833 if (ret)
834 return ret;
835 }
836
837 for (i = 0; i < 5; i++) {
838 ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9));
839 if (ret)
840 return ret;
841 }
842
843 /* QM Control */
844 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
845 if (ret)
846 return ret;
847
848 /* Disable Atheros header */
849 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
850 if (ret)
851 return ret;
852
853 /* Tag priority mapping */
854 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
855 if (ret)
856 return ret;
857
858 /* Enable ARP packets to the CPU */
859 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
860 if (ret)
861 return ret;
862
863 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000);
864 if (ret)
865 return ret;
866
867 /* Enable broadcast packets to the CPU */
868 ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, &reg);
869 if (ret)
870 return ret;
871
872 ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26));
873 if (ret)
874 return ret;
875
876 return 0;
877}
878
Marek Vasute40095f2016-05-24 23:29:09 +0200879static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
880{
881 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
882 int ret;
883
Rosy Song84265232019-03-16 09:24:50 +0800884 if (priv->model == AG7XXX_MODEL_AG953X ||
885 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Songf1f943e2019-02-05 17:50:44 +0800886 ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE,
887 ADVERTISE_ALL);
888 } else {
889 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
890 ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
891 ADVERTISE_PAUSE_ASYM);
892 }
Marek Vasute40095f2016-05-24 23:29:09 +0200893 if (ret)
894 return ret;
895
896 if (priv->model == AG7XXX_MODEL_AG934X) {
897 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000,
898 ADVERTISE_1000FULL);
899 if (ret)
900 return ret;
Rosy Song84265232019-03-16 09:24:50 +0800901 } else if (priv->model == AG7XXX_MODEL_AG956X) {
902 ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000,
903 ADVERTISE_1000FULL);
904 if (ret)
905 return ret;
Marek Vasute40095f2016-05-24 23:29:09 +0200906 }
907
Rosy Song84265232019-03-16 09:24:50 +0800908 if (priv->model == AG7XXX_MODEL_AG953X ||
909 priv->model == AG7XXX_MODEL_AG956X)
Rosy Songf1f943e2019-02-05 17:50:44 +0800910 return ag7xxx_switch_write(priv->bus, port, MII_BMCR,
911 BMCR_ANENABLE | BMCR_RESET);
912
Marek Vasute40095f2016-05-24 23:29:09 +0200913 return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
914 BMCR_ANENABLE | BMCR_RESET);
915}
916
917static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port)
918{
919 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
920 int ret;
Rosy Songf1f943e2019-02-05 17:50:44 +0800921 u16 reg;
Marek Vasute40095f2016-05-24 23:29:09 +0200922
Rosy Song84265232019-03-16 09:24:50 +0800923 if (priv->model == AG7XXX_MODEL_AG953X ||
924 priv->model == AG7XXX_MODEL_AG956X) {
Rosy Songf1f943e2019-02-05 17:50:44 +0800925 do {
926 ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, &reg);
927 if (ret < 0)
928 return ret;
929 mdelay(10);
930 } while (reg & BMCR_RESET);
931 } else {
932 do {
933 ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
934 if (ret < 0)
935 return ret;
936 mdelay(10);
937 } while (ret & BMCR_RESET);
938 }
Marek Vasute40095f2016-05-24 23:29:09 +0200939
940 return 0;
941}
942
943static int ag933x_phy_setup_common(struct udevice *dev)
944{
945 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
946 int i, ret, phymax;
Rosy Songf1f943e2019-02-05 17:50:44 +0800947 u16 reg;
Marek Vasute40095f2016-05-24 23:29:09 +0200948
949 if (priv->model == AG7XXX_MODEL_AG933X)
950 phymax = 4;
Rosy Songf1f943e2019-02-05 17:50:44 +0800951 else if (priv->model == AG7XXX_MODEL_AG934X ||
Rosy Song84265232019-03-16 09:24:50 +0800952 priv->model == AG7XXX_MODEL_AG953X ||
953 priv->model == AG7XXX_MODEL_AG956X)
Marek Vasute40095f2016-05-24 23:29:09 +0200954 phymax = 5;
955 else
956 return -EINVAL;
957
958 if (priv->interface == PHY_INTERFACE_MODE_RMII) {
959 ret = ag933x_phy_setup_reset_set(dev, phymax);
960 if (ret)
961 return ret;
962
963 ret = ag933x_phy_setup_reset_fin(dev, phymax);
964 if (ret)
965 return ret;
966
967 /* Read out link status */
Rosy Songf1f943e2019-02-05 17:50:44 +0800968 if (priv->model == AG7XXX_MODEL_AG953X)
969 ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, &reg);
970 else
971 ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
Marek Vasute40095f2016-05-24 23:29:09 +0200972 if (ret < 0)
973 return ret;
974
975 return 0;
976 }
977
978 /* Switch ports */
979 for (i = 0; i < phymax; i++) {
980 ret = ag933x_phy_setup_reset_set(dev, i);
981 if (ret)
982 return ret;
983 }
984
985 for (i = 0; i < phymax; i++) {
986 ret = ag933x_phy_setup_reset_fin(dev, i);
987 if (ret)
988 return ret;
989 }
990
991 for (i = 0; i < phymax; i++) {
992 /* Read out link status */
Rosy Song84265232019-03-16 09:24:50 +0800993 if (priv->model == AG7XXX_MODEL_AG953X ||
994 priv->model == AG7XXX_MODEL_AG956X)
Rosy Songf1f943e2019-02-05 17:50:44 +0800995 ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, &reg);
996 else
997 ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
Marek Vasute40095f2016-05-24 23:29:09 +0200998 if (ret < 0)
999 return ret;
1000 }
1001
1002 return 0;
1003}
1004
1005static int ag934x_phy_setup(struct udevice *dev)
1006{
1007 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1008 int i, ret;
1009 u32 reg;
1010
1011 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1012 if (ret)
1013 return ret;
1014 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000);
1015 if (ret)
1016 return ret;
1017 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000);
1018 if (ret)
1019 return ret;
1020 ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000);
1021 if (ret)
1022 return ret;
1023 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1024 if (ret)
1025 return ret;
1026
1027 /* AR8327/AR8328 v1.0 fixup */
1028 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1029 if (ret)
1030 return ret;
1031 if ((reg & 0xffff) == 0x1201) {
1032 for (i = 0; i < 5; i++) {
1033 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0);
1034 if (ret)
1035 return ret;
1036 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea);
1037 if (ret)
1038 return ret;
1039 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d);
1040 if (ret)
1041 return ret;
1042 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0);
1043 if (ret)
1044 return ret;
1045 }
1046 }
1047
1048 ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, &reg);
1049 if (ret)
1050 return ret;
1051 reg &= ~0x70000;
1052 ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg);
1053 if (ret)
1054 return ret;
1055
1056 return 0;
1057}
1058
Rosy Song84265232019-03-16 09:24:50 +08001059static int ag956x_phy_setup(struct udevice *dev)
1060{
1061 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1062 int i, ret;
1063 u32 reg, ctrl;
1064
1065 ret = ag7xxx_switch_reg_read(priv->bus, 0x0, &reg);
1066 if (ret)
1067 return ret;
1068 if ((reg & 0xffff) >= 0x1301)
1069 ctrl = 0xc74164de;
1070 else
1071 ctrl = 0xc74164d0;
1072
1073 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7));
1074 if (ret)
1075 return ret;
1076
1077 ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl);
1078 if (ret)
1079 return ret;
1080
1081 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
1082 if (ret)
1083 return ret;
1084
1085 /*
1086 * Values suggested by the switch team when s17 in sgmii
1087 * configuration. 0x10(S17_PWS_REG) = 0x602613a0
1088 */
1089 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0);
1090 if (ret)
1091 return ret;
1092
1093 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
1094 if (ret)
1095 return ret;
1096
1097 /* AR8337/AR8334 v1.0 fixup */
1098 ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
1099 if (ret)
1100 return ret;
1101 if ((reg & 0xffff) == 0x1301) {
1102 for (i = 0; i < 5; i++) {
1103 /* Turn on Gigabit clock */
1104 ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d);
1105 if (ret)
1106 return ret;
1107 ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820);
1108 if (ret)
1109 return ret;
1110 }
1111 }
1112
1113 return 0;
1114}
1115
Marek Vasute40095f2016-05-24 23:29:09 +02001116static int ag7xxx_mac_probe(struct udevice *dev)
1117{
1118 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1119 int ret;
1120
1121 ag7xxx_hw_setup(dev);
1122 ret = ag7xxx_mii_setup(dev);
1123 if (ret)
1124 return ret;
1125
1126 ag7xxx_eth_write_hwaddr(dev);
1127
1128 if (priv->model == AG7XXX_MODEL_AG933X) {
1129 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1130 ret = ag933x_phy_setup_wan(dev);
1131 else
1132 ret = ag933x_phy_setup_lan(dev);
Rosy Songf1f943e2019-02-05 17:50:44 +08001133 } else if (priv->model == AG7XXX_MODEL_AG953X) {
1134 if (priv->interface == PHY_INTERFACE_MODE_RMII)
1135 ret = ag953x_phy_setup_wan(dev);
1136 else
1137 ret = ag953x_phy_setup_lan(dev);
Marek Vasute40095f2016-05-24 23:29:09 +02001138 } else if (priv->model == AG7XXX_MODEL_AG934X) {
1139 ret = ag934x_phy_setup(dev);
Rosy Song84265232019-03-16 09:24:50 +08001140 } else if (priv->model == AG7XXX_MODEL_AG956X) {
1141 ret = ag956x_phy_setup(dev);
Marek Vasute40095f2016-05-24 23:29:09 +02001142 } else {
1143 return -EINVAL;
1144 }
1145
1146 if (ret)
1147 return ret;
1148
1149 return ag933x_phy_setup_common(dev);
1150}
1151
1152static int ag7xxx_mdio_probe(struct udevice *dev)
1153{
1154 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1155 struct mii_dev *bus = mdio_alloc();
1156
1157 if (!bus)
1158 return -ENOMEM;
1159
1160 bus->read = ag7xxx_mdio_read;
1161 bus->write = ag7xxx_mdio_write;
1162 snprintf(bus->name, sizeof(bus->name), dev->name);
1163
1164 bus->priv = (void *)priv;
1165
1166 return mdio_register(bus);
1167}
1168
1169static int ag7xxx_get_phy_iface_offset(struct udevice *dev)
1170{
1171 int offset;
1172
Simon Glasse160f7d2017-01-17 16:52:55 -07001173 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), "phy");
Marek Vasute40095f2016-05-24 23:29:09 +02001174 if (offset <= 0) {
1175 debug("%s: PHY OF node not found (ret=%i)\n", __func__, offset);
1176 return -EINVAL;
1177 }
1178
1179 offset = fdt_parent_offset(gd->fdt_blob, offset);
1180 if (offset <= 0) {
1181 debug("%s: PHY OF node parent MDIO bus not found (ret=%i)\n",
1182 __func__, offset);
1183 return -EINVAL;
1184 }
1185
1186 offset = fdt_parent_offset(gd->fdt_blob, offset);
1187 if (offset <= 0) {
1188 debug("%s: PHY MDIO OF node parent MAC not found (ret=%i)\n",
1189 __func__, offset);
1190 return -EINVAL;
1191 }
1192
1193 return offset;
1194}
1195
1196static int ag7xxx_eth_probe(struct udevice *dev)
1197{
1198 struct eth_pdata *pdata = dev_get_platdata(dev);
1199 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1200 void __iomem *iobase, *phyiobase;
1201 int ret, phyreg;
1202
1203 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1204 ret = ag7xxx_get_phy_iface_offset(dev);
1205 if (ret <= 0)
1206 return ret;
1207 phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1);
1208
1209 iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE);
1210 phyiobase = map_physmem(phyreg, 0x200, MAP_NOCACHE);
1211
1212 debug("%s, iobase=%p, phyiobase=%p, priv=%p\n",
1213 __func__, iobase, phyiobase, priv);
1214 priv->regs = iobase;
1215 priv->phyregs = phyiobase;
1216 priv->interface = pdata->phy_interface;
1217 priv->model = dev_get_driver_data(dev);
1218
1219 ret = ag7xxx_mdio_probe(dev);
1220 if (ret)
1221 return ret;
1222
1223 priv->bus = miiphy_get_dev_by_name(dev->name);
1224
1225 ret = ag7xxx_mac_probe(dev);
1226 debug("%s, ret=%d\n", __func__, ret);
1227
1228 return ret;
1229}
1230
1231static int ag7xxx_eth_remove(struct udevice *dev)
1232{
1233 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
1234
1235 free(priv->phydev);
1236 mdio_unregister(priv->bus);
1237 mdio_free(priv->bus);
1238
1239 return 0;
1240}
1241
1242static const struct eth_ops ag7xxx_eth_ops = {
1243 .start = ag7xxx_eth_start,
1244 .send = ag7xxx_eth_send,
1245 .recv = ag7xxx_eth_recv,
1246 .free_pkt = ag7xxx_eth_free_pkt,
1247 .stop = ag7xxx_eth_stop,
1248 .write_hwaddr = ag7xxx_eth_write_hwaddr,
1249};
1250
1251static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev)
1252{
1253 struct eth_pdata *pdata = dev_get_platdata(dev);
1254 const char *phy_mode;
1255 int ret;
1256
Simon Glassa821c4a2017-05-17 17:18:05 -06001257 pdata->iobase = devfdt_get_addr(dev);
Marek Vasute40095f2016-05-24 23:29:09 +02001258 pdata->phy_interface = -1;
1259
1260 /* Decoding of convoluted PHY wiring on Atheros MIPS. */
1261 ret = ag7xxx_get_phy_iface_offset(dev);
1262 if (ret <= 0)
1263 return ret;
1264
1265 phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL);
1266 if (phy_mode)
1267 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
1268 if (pdata->phy_interface == -1) {
1269 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1270 return -EINVAL;
1271 }
1272
1273 return 0;
1274}
1275
1276static const struct udevice_id ag7xxx_eth_ids[] = {
1277 { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
1278 { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
Rosy Songf1f943e2019-02-05 17:50:44 +08001279 { .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X },
Rosy Song84265232019-03-16 09:24:50 +08001280 { .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X },
Marek Vasute40095f2016-05-24 23:29:09 +02001281 { }
1282};
1283
1284U_BOOT_DRIVER(eth_ag7xxx) = {
1285 .name = "eth_ag7xxx",
1286 .id = UCLASS_ETH,
1287 .of_match = ag7xxx_eth_ids,
1288 .ofdata_to_platdata = ag7xxx_eth_ofdata_to_platdata,
1289 .probe = ag7xxx_eth_probe,
1290 .remove = ag7xxx_eth_remove,
1291 .ops = &ag7xxx_eth_ops,
1292 .priv_auto_alloc_size = sizeof(struct ar7xxx_eth_priv),
1293 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
1294 .flags = DM_FLAG_ALLOC_PRIV_DMA,
1295};