blob: 74cc956785f787c0c9e89471f003459dbecda465 [file] [log] [blame]
Grygorii Strashkocf56fb72018-10-31 16:21:43 -05001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
4 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05005 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
Grygorii Strashkocf56fb72018-10-31 16:21:43 -05006 */
7
8#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070010#include <malloc.h>
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050011#include <asm/io.h>
12#include <miiphy.h>
13#include <wait_bit.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060014#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060015#include <linux/delay.h>
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050016
17struct cpsw_mdio_regs {
18 u32 version;
19 u32 control;
20#define CONTROL_IDLE BIT(31)
21#define CONTROL_ENABLE BIT(30)
22#define CONTROL_FAULT BIT(19)
23#define CONTROL_FAULT_ENABLE BIT(18)
24#define CONTROL_DIV_MASK GENMASK(15, 0)
25
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053026#define MDIO_MAN_MDCLK_O BIT(2)
27#define MDIO_MAN_OE BIT(1)
28#define MDIO_MAN_PIN BIT(0)
29#define MDIO_MANUALMODE BIT(31)
30
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050031 u32 alive;
32 u32 link;
33 u32 linkintraw;
34 u32 linkintmasked;
35 u32 __reserved_0[2];
36 u32 userintraw;
37 u32 userintmasked;
38 u32 userintmaskset;
39 u32 userintmaskclr;
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053040 u32 manualif;
41 u32 poll;
42 u32 __reserved_1[18];
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050043
44 struct {
45 u32 access;
46 u32 physel;
47#define USERACCESS_GO BIT(31)
48#define USERACCESS_WRITE BIT(30)
49#define USERACCESS_ACK BIT(29)
50#define USERACCESS_READ (0)
51#define USERACCESS_PHY_REG_SHIFT (21)
52#define USERACCESS_PHY_ADDR_SHIFT (16)
53#define USERACCESS_DATA GENMASK(15, 0)
Ulf Samuelssonfaa537a2023-02-07 09:25:27 +010054 } user[2];
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050055};
56
57#define CPSW_MDIO_DIV_DEF 0xff
58#define PHY_REG_MASK 0x1f
59#define PHY_ID_MASK 0x1f
60
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053061#define MDIO_BITRANGE 0x8000
62#define C22_READ_PATTERN 0x6
63#define C22_WRITE_PATTERN 0x5
64#define C22_BITRANGE 0x8
65#define PHY_BITRANGE 0x10
66#define PHY_DATA_BITRANGE 0x8000
67
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050068/*
69 * This timeout definition is a worst-case ultra defensive measure against
70 * unexpected controller lock ups. Ideally, we should never ever hit this
71 * scenario in practice.
72 */
73#define CPSW_MDIO_TIMEOUT 100 /* msecs */
74
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053075enum cpsw_mdio_manual {
76 MDIO_PIN = 0,
77 MDIO_OE,
78 MDIO_MDCLK,
79};
80
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050081struct cpsw_mdio {
82 struct cpsw_mdio_regs *regs;
83 struct mii_dev *bus;
84 int div;
85};
86
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053087static void cpsw_mdio_disable(struct cpsw_mdio *mdio)
88{
89 u32 reg;
90 /* Disable MDIO state machine */
91 reg = readl(&mdio->regs->control);
92 reg &= ~CONTROL_ENABLE;
93
94 writel(reg, &mdio->regs->control);
95}
96
97static void cpsw_mdio_enable_manual_mode(struct cpsw_mdio *mdio)
98{
99 u32 reg;
100
101 /* set manual mode */
102 reg = readl(&mdio->regs->poll);
103 reg |= MDIO_MANUALMODE;
104
105 writel(reg, &mdio->regs->poll);
106}
107
108static void cpsw_mdio_sw_set_bit(struct cpsw_mdio *mdio,
109 enum cpsw_mdio_manual bit)
110{
111 u32 reg;
112
113 reg = readl(&mdio->regs->manualif);
114
115 switch (bit) {
116 case MDIO_OE:
117 reg |= MDIO_MAN_OE;
118 writel(reg, &mdio->regs->manualif);
119 break;
120 case MDIO_PIN:
121 reg |= MDIO_MAN_PIN;
122 writel(reg, &mdio->regs->manualif);
123 break;
124 case MDIO_MDCLK:
125 reg |= MDIO_MAN_MDCLK_O;
126 writel(reg, &mdio->regs->manualif);
127 break;
128 default:
129 break;
130 };
131}
132
133static void cpsw_mdio_sw_clr_bit(struct cpsw_mdio *mdio,
134 enum cpsw_mdio_manual bit)
135{
136 u32 reg;
137
138 reg = readl(&mdio->regs->manualif);
139
140 switch (bit) {
141 case MDIO_OE:
142 reg &= ~MDIO_MAN_OE;
143 writel(reg, &mdio->regs->manualif);
144 break;
145 case MDIO_PIN:
146 reg &= ~MDIO_MAN_PIN;
147 writel(reg, &mdio->regs->manualif);
148 break;
149 case MDIO_MDCLK:
150 reg = readl(&mdio->regs->manualif);
151 reg &= ~MDIO_MAN_MDCLK_O;
152 writel(reg, &mdio->regs->manualif);
153 break;
154 default:
155 break;
156 };
157}
158
159static int cpsw_mdio_test_man_bit(struct cpsw_mdio *mdio,
160 enum cpsw_mdio_manual bit)
161{
162 u32 reg;
163
164 reg = readl(&mdio->regs->manualif);
165 return test_bit(bit, &reg);
166}
167
168static void cpsw_mdio_toggle_man_bit(struct cpsw_mdio *mdio,
169 enum cpsw_mdio_manual bit)
170{
171 cpsw_mdio_sw_clr_bit(mdio, bit);
172 cpsw_mdio_sw_set_bit(mdio, bit);
173}
174
175static void cpsw_mdio_man_send_pattern(struct cpsw_mdio *mdio,
176 u32 bitrange, u32 val)
177{
178 u32 i;
179
180 for (i = bitrange; i; i = i >> 1) {
181 if (i & val)
182 cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
183 else
184 cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
185
186 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
187 }
188}
189
190static void cpsw_mdio_sw_preamble(struct cpsw_mdio *mdio)
191{
192 u32 i;
193
194 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
195
196 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
197 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
198 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
199 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
200
201 for (i = 0; i < 32; i++) {
202 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
203 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
204 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
205 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
206 }
207}
208
209static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id,
210 int dev_addr, int phy_reg)
211{
212 struct cpsw_mdio *mdio = bus->priv;
213 u32 reg, i;
214 u8 ack;
215
216 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
217 return -EINVAL;
218
219 cpsw_mdio_disable(mdio);
220 cpsw_mdio_enable_manual_mode(mdio);
221 cpsw_mdio_sw_preamble(mdio);
222
223 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
224 cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
225
226 /* Issue clause 22 MII read function {0,1,1,0} */
227 cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_READ_PATTERN);
228
229 /* Send the device number MSB first */
230 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
231
232 /* Send the register number MSB first */
233 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
234
235 /* Send turn around cycles */
236 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
237
238 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
239
240 ack = cpsw_mdio_test_man_bit(mdio, MDIO_PIN);
241 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
242
243 reg = 0;
244 if (ack == 0) {
245 for (i = MDIO_BITRANGE; i; i = i >> 1) {
246 if (cpsw_mdio_test_man_bit(mdio, MDIO_PIN))
247 reg |= i;
248
249 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
250 }
251 } else {
252 for (i = MDIO_BITRANGE; i; i = i >> 1)
253 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
254
255 reg = 0xFFFF;
256 }
257
258 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
259 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
260 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
261 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
262
263 return reg;
264}
265
266static int cpsw_mdio_sw_write(struct mii_dev *bus, int phy_id,
267 int dev_addr, int phy_reg, u16 phy_data)
268{
269 struct cpsw_mdio *mdio = bus->priv;
270
271 if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK))
272 return -EINVAL;
273
274 cpsw_mdio_disable(mdio);
275 cpsw_mdio_enable_manual_mode(mdio);
276 cpsw_mdio_sw_preamble(mdio);
277
278 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
279 cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
280
281 /* Issue clause 22 MII write function {0,1,0,1} */
282 cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_WRITE_PATTERN);
283
284 /* Send the device number MSB first */
285 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
286
287 /* Send the register number MSB first */
288 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
289
290 /* set turn-around cycles */
291 cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
292 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
293 cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
294 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
295
296 /* Send Register data MSB first */
297 cpsw_mdio_man_send_pattern(mdio, PHY_DATA_BITRANGE, phy_data);
298 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
299
300 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
301 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
302 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
303 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
304
305 return 0;
306}
307
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500308/* wait until hardware is ready for another user access */
309static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
310{
311 return wait_for_bit_le32(&mdio->regs->user[0].access,
312 USERACCESS_GO, false,
313 CPSW_MDIO_TIMEOUT, false);
314}
315
316static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
317 int dev_addr, int phy_reg)
318{
319 struct cpsw_mdio *mdio = bus->priv;
320 int data, ret;
321 u32 reg;
322
323 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
324 return -EINVAL;
325
326 ret = cpsw_mdio_wait_for_user_access(mdio);
327 if (ret)
328 return ret;
329 reg = (USERACCESS_GO | USERACCESS_READ |
330 (phy_reg << USERACCESS_PHY_REG_SHIFT) |
331 (phy_id << USERACCESS_PHY_ADDR_SHIFT));
332 writel(reg, &mdio->regs->user[0].access);
333 ret = cpsw_mdio_wait_for_user_access(mdio);
334 if (ret)
335 return ret;
336
337 reg = readl(&mdio->regs->user[0].access);
338 data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
339 return data;
340}
341
342static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
343 int phy_reg, u16 data)
344{
345 struct cpsw_mdio *mdio = bus->priv;
346 u32 reg;
347 int ret;
348
349 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
350 return -EINVAL;
351
352 ret = cpsw_mdio_wait_for_user_access(mdio);
353 if (ret)
354 return ret;
355 reg = (USERACCESS_GO | USERACCESS_WRITE |
356 (phy_reg << USERACCESS_PHY_REG_SHIFT) |
357 (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
358 (data & USERACCESS_DATA));
359 writel(reg, &mdio->regs->user[0].access);
360
361 return cpsw_mdio_wait_for_user_access(mdio);
362}
363
364u32 cpsw_mdio_get_alive(struct mii_dev *bus)
365{
366 struct cpsw_mdio *mdio = bus->priv;
367 u32 val;
368
Ulf Samuelssonfaa537a2023-02-07 09:25:27 +0100369 val = readl(&mdio->regs->alive);
370 return val & GENMASK(7, 0);
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500371}
372
Keerthy21deb9b2019-07-09 10:30:33 +0530373struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530374 u32 bus_freq, int fck_freq, bool manual_mode)
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500375{
376 struct cpsw_mdio *cpsw_mdio;
377 int ret;
378
379 cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
380 if (!cpsw_mdio) {
381 debug("failed to alloc cpsw_mdio\n");
382 return NULL;
383 }
384
385 cpsw_mdio->bus = mdio_alloc();
386 if (!cpsw_mdio->bus) {
387 debug("failed to alloc mii bus\n");
388 free(cpsw_mdio);
389 return NULL;
390 }
391
Keerthy21deb9b2019-07-09 10:30:33 +0530392 cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500393
394 if (!bus_freq || !fck_freq)
395 cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
396 else
397 cpsw_mdio->div = (fck_freq / bus_freq) - 1;
398 cpsw_mdio->div &= CONTROL_DIV_MASK;
399
400 /* set enable and clock divider */
401 writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
402 CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
403 wait_for_bit_le32(&cpsw_mdio->regs->control,
404 CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
405
406 /*
407 * wait for scan logic to settle:
408 * the scan time consists of (a) a large fixed component, and (b) a
409 * small component that varies with the mii bus frequency. These
410 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
411 * silicon. Since the effect of (b) was found to be largely
412 * negligible, we keep things simple here.
413 */
414 mdelay(1);
415
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530416 if (manual_mode) {
417 cpsw_mdio->bus->read = cpsw_mdio_sw_read;
418 cpsw_mdio->bus->write = cpsw_mdio_sw_write;
419 } else {
420 cpsw_mdio->bus->read = cpsw_mdio_read;
421 cpsw_mdio->bus->write = cpsw_mdio_write;
422 }
423
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500424 cpsw_mdio->bus->priv = cpsw_mdio;
425 snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
426
427 ret = mdio_register(cpsw_mdio->bus);
428 if (ret < 0) {
429 debug("failed to register mii bus\n");
430 goto free_bus;
431 }
432
433 return cpsw_mdio->bus;
434
435free_bus:
436 mdio_free(cpsw_mdio->bus);
437 free(cpsw_mdio);
438 return NULL;
439}
440
441void cpsw_mdio_free(struct mii_dev *bus)
442{
443 struct cpsw_mdio *mdio = bus->priv;
444 u32 reg;
445
446 /* disable mdio */
447 reg = readl(&mdio->regs->control);
448 reg &= ~CONTROL_ENABLE;
449 writel(reg, &mdio->regs->control);
450
451 mdio_unregister(bus);
452 mdio_free(bus);
453 free(mdio);
454}