blob: cde681a62da7b236e4be556dc6ea1f95c527b91a [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Weijie Gao <weijie.gao@mediatek.com>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/device.h>
11#include <linux/delay.h>
12#include <linux/reset.h>
13#include <linux/hrtimer.h>
14#include <linux/mii.h>
15#include <linux/of_mdio.h>
16#include <linux/of_platform.h>
17#include <linux/of_gpio.h>
18#include <linux/of_net.h>
19#include <linux/of_irq.h>
20#include <linux/phy.h>
21
22#include "mt753x.h"
23#include "mt753x_swconfig.h"
24#include "mt753x_regs.h"
25#include "mt753x_nl.h"
26#include "mt7530.h"
27#include "mt7531.h"
28
29static u32 mt753x_id;
30struct list_head mt753x_devs;
31static DEFINE_MUTEX(mt753x_devs_lock);
32
33static struct mt753x_sw_id *mt753x_sw_ids[] = {
34 &mt7530_id,
35 &mt7531_id,
developer2cdaeb12022-10-04 20:25:05 +080036 &mt7988_id,
developerfd40db22021-04-29 10:08:25 +080037};
38
39u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg)
40{
41 u32 high, low;
42
developer2cdaeb12022-10-04 20:25:05 +080043 if (gsw->direct_access)
44 return __raw_readl(gsw->base + reg);
developerfd40db22021-04-29 10:08:25 +080045
developer2cdaeb12022-10-04 20:25:05 +080046 mutex_lock(&gsw->host_bus->mdio_lock);
developerfd40db22021-04-29 10:08:25 +080047 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
developer2cdaeb12022-10-04 20:25:05 +080048 (reg & MT753X_REG_PAGE_ADDR_M) >>
49 MT753X_REG_PAGE_ADDR_S);
developerfd40db22021-04-29 10:08:25 +080050
51 low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr,
developer2cdaeb12022-10-04 20:25:05 +080052 (reg & MT753X_REG_ADDR_M) >>
53 MT753X_REG_ADDR_S);
developerfd40db22021-04-29 10:08:25 +080054
55 high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x10);
56
57 mutex_unlock(&gsw->host_bus->mdio_lock);
58
59 return (high << 16) | (low & 0xffff);
60}
61
62void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
63{
developer2cdaeb12022-10-04 20:25:05 +080064 if (gsw->direct_access) {
65 __raw_writel(val, gsw->base + reg);
66 } else {
67 mutex_lock(&gsw->host_bus->mdio_lock);
68 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f,
69 (reg & MT753X_REG_PAGE_ADDR_M) >>
70 MT753X_REG_PAGE_ADDR_S);
developerfd40db22021-04-29 10:08:25 +080071
developer2cdaeb12022-10-04 20:25:05 +080072 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr,
73 (reg & MT753X_REG_ADDR_M) >>
74 MT753X_REG_ADDR_S,
75 val & 0xffff);
developerfd40db22021-04-29 10:08:25 +080076
developer2cdaeb12022-10-04 20:25:05 +080077 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10,
78 val >> 16);
developerfd40db22021-04-29 10:08:25 +080079
developer2cdaeb12022-10-04 20:25:05 +080080 mutex_unlock(&gsw->host_bus->mdio_lock);
81 }
developerfd40db22021-04-29 10:08:25 +080082}
83
84/* Indirect MDIO clause 22/45 access */
85static int mt753x_mii_rw(struct gsw_mt753x *gsw, int phy, int reg, u16 data,
86 u32 cmd, u32 st)
87{
88 ktime_t timeout;
89 u32 val, timeout_us;
90 int ret = 0;
91
92 timeout_us = 100000;
93 timeout = ktime_add_us(ktime_get(), timeout_us);
94 while (1) {
95 val = mt753x_reg_read(gsw, PHY_IAC);
96
97 if ((val & PHY_ACS_ST) == 0)
98 break;
99
100 if (ktime_compare(ktime_get(), timeout) > 0)
101 return -ETIMEDOUT;
102 }
103
developer2cdaeb12022-10-04 20:25:05 +0800104 val = (st << MDIO_ST_S) | ((cmd << MDIO_CMD_S) & MDIO_CMD_M) |
developerfd40db22021-04-29 10:08:25 +0800105 ((phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) |
106 ((reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M);
107
108 if (cmd == MDIO_CMD_WRITE || cmd == MDIO_CMD_ADDR)
109 val |= data & MDIO_RW_DATA_M;
110
111 mt753x_reg_write(gsw, PHY_IAC, val | PHY_ACS_ST);
112
113 timeout_us = 100000;
114 timeout = ktime_add_us(ktime_get(), timeout_us);
115 while (1) {
116 val = mt753x_reg_read(gsw, PHY_IAC);
117
118 if ((val & PHY_ACS_ST) == 0)
119 break;
120
121 if (ktime_compare(ktime_get(), timeout) > 0)
122 return -ETIMEDOUT;
123 }
124
125 if (cmd == MDIO_CMD_READ || cmd == MDIO_CMD_READ_C45) {
126 val = mt753x_reg_read(gsw, PHY_IAC);
127 ret = val & MDIO_RW_DATA_M;
128 }
129
130 return ret;
131}
132
133int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg)
134{
135 int val;
136
137 if (phy < MT753X_NUM_PHYS)
138 phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
139
140 mutex_lock(&gsw->mii_lock);
141 val = mt753x_mii_rw(gsw, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22);
142 mutex_unlock(&gsw->mii_lock);
143
144 return val;
145}
146
147void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val)
148{
149 if (phy < MT753X_NUM_PHYS)
150 phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK;
151
152 mutex_lock(&gsw->mii_lock);
153 mt753x_mii_rw(gsw, phy, reg, val, MDIO_CMD_WRITE, MDIO_ST_C22);
154 mutex_unlock(&gsw->mii_lock);
155}
156
157int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg)
158{
159 int val;
160
161 if (addr < MT753X_NUM_PHYS)
162 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
163
164 mutex_lock(&gsw->mii_lock);
165 mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
166 val = mt753x_mii_rw(gsw, addr, devad, 0, MDIO_CMD_READ_C45,
167 MDIO_ST_C45);
168 mutex_unlock(&gsw->mii_lock);
169
170 return val;
171}
172
173void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
174 u16 val)
175{
176 if (addr < MT753X_NUM_PHYS)
177 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
178
179 mutex_lock(&gsw->mii_lock);
180 mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45);
181 mt753x_mii_rw(gsw, addr, devad, val, MDIO_CMD_WRITE, MDIO_ST_C45);
182 mutex_unlock(&gsw->mii_lock);
183}
184
185int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg)
186{
187 u16 val;
188
189 if (addr < MT753X_NUM_PHYS)
190 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
191
192 mutex_lock(&gsw->mii_lock);
193
194 mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
195 (MMD_ADDR << MMD_CMD_S) |
developer2cdaeb12022-10-04 20:25:05 +0800196 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
developerfd40db22021-04-29 10:08:25 +0800197 MDIO_CMD_WRITE, MDIO_ST_C22);
198
developer2cdaeb12022-10-04 20:25:05 +0800199 mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, MDIO_CMD_WRITE,
200 MDIO_ST_C22);
developerfd40db22021-04-29 10:08:25 +0800201
202 mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
203 (MMD_DATA << MMD_CMD_S) |
developer2cdaeb12022-10-04 20:25:05 +0800204 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
developerfd40db22021-04-29 10:08:25 +0800205 MDIO_CMD_WRITE, MDIO_ST_C22);
206
developer2cdaeb12022-10-04 20:25:05 +0800207 val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0, MDIO_CMD_READ,
208 MDIO_ST_C22);
developerfd40db22021-04-29 10:08:25 +0800209
210 mutex_unlock(&gsw->mii_lock);
211
212 return val;
213}
214
215void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
216 u16 val)
217{
218 if (addr < MT753X_NUM_PHYS)
219 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
220
221 mutex_lock(&gsw->mii_lock);
222
223 mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
224 (MMD_ADDR << MMD_CMD_S) |
developer2cdaeb12022-10-04 20:25:05 +0800225 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
developerfd40db22021-04-29 10:08:25 +0800226 MDIO_CMD_WRITE, MDIO_ST_C22);
227
developer2cdaeb12022-10-04 20:25:05 +0800228 mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, MDIO_CMD_WRITE,
229 MDIO_ST_C22);
developerfd40db22021-04-29 10:08:25 +0800230
231 mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG,
232 (MMD_DATA << MMD_CMD_S) |
developer2cdaeb12022-10-04 20:25:05 +0800233 ((devad << MMD_DEVAD_S) & MMD_DEVAD_M),
developerfd40db22021-04-29 10:08:25 +0800234 MDIO_CMD_WRITE, MDIO_ST_C22);
235
developer2cdaeb12022-10-04 20:25:05 +0800236 mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val, MDIO_CMD_WRITE,
237 MDIO_ST_C22);
developerfd40db22021-04-29 10:08:25 +0800238
239 mutex_unlock(&gsw->mii_lock);
240}
241
242static inline int mt753x_get_duplex(const struct device_node *np)
243{
244 return of_property_read_bool(np, "full-duplex");
245}
246
247static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
248{
249 struct device_node *port_np;
250 struct device_node *fixed_link_node;
251 struct mt753x_port_cfg *port_cfg;
252 u32 port;
253
254 for_each_child_of_node(gsw->dev->of_node, port_np) {
255 if (!of_device_is_compatible(port_np, "mediatek,mt753x-port"))
256 continue;
257
258 if (!of_device_is_available(port_np))
259 continue;
260
261 if (of_property_read_u32(port_np, "reg", &port))
262 continue;
263
264 switch (port) {
265 case 5:
266 port_cfg = &gsw->port5_cfg;
267 break;
268 case 6:
269 port_cfg = &gsw->port6_cfg;
270 break;
271 default:
272 continue;
273 }
274
275 if (port_cfg->enabled) {
276 dev_info(gsw->dev, "duplicated node for port%d\n",
277 port_cfg->phy_mode);
278 continue;
279 }
280
281 port_cfg->np = port_np;
282
developer070a3372022-11-11 16:55:46 +0800283 port_cfg->phy_mode = of_get_phy_mode(port_np);
284 if (port_cfg->phy_mode < 0) {
developerfd40db22021-04-29 10:08:25 +0800285 dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
286 continue;
287 }
288
289 fixed_link_node = of_get_child_by_name(port_np, "fixed-link");
290 if (fixed_link_node) {
291 u32 speed;
292
293 port_cfg->force_link = 1;
294 port_cfg->duplex = mt753x_get_duplex(fixed_link_node);
295
296 if (of_property_read_u32(fixed_link_node, "speed",
297 &speed)) {
298 speed = 0;
299 continue;
300 }
301
302 of_node_put(fixed_link_node);
303
304 switch (speed) {
305 case 10:
306 port_cfg->speed = MAC_SPD_10;
307 break;
308 case 100:
309 port_cfg->speed = MAC_SPD_100;
310 break;
311 case 1000:
312 port_cfg->speed = MAC_SPD_1000;
313 break;
314 case 2500:
315 port_cfg->speed = MAC_SPD_2500;
316 break;
developer2cdaeb12022-10-04 20:25:05 +0800317
developerfd40db22021-04-29 10:08:25 +0800318 default:
319 dev_info(gsw->dev, "incorrect speed %d\n",
320 speed);
321 continue;
322 }
323 }
324
developer2cdaeb12022-10-04 20:25:05 +0800325 port_cfg->ssc_on =
326 of_property_read_bool(port_cfg->np, "mediatek,ssc-on");
327 port_cfg->stag_on =
328 of_property_read_bool(port_cfg->np, "mediatek,stag-on");
developerfd40db22021-04-29 10:08:25 +0800329 port_cfg->enabled = 1;
330 }
331}
332
333void mt753x_tr_write(struct gsw_mt753x *gsw, int addr, u8 ch, u8 node, u8 daddr,
334 u32 data)
335{
336 ktime_t timeout;
337 u32 timeout_us;
338 u32 val;
339
340 if (addr < MT753X_NUM_PHYS)
341 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
342
343 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
344
345 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
346
347 timeout_us = 100000;
348 timeout = ktime_add_us(ktime_get(), timeout_us);
349 while (1) {
350 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
351
352 if (!!(val & PHY_TR_PKT_XMT_STA))
353 break;
354
355 if (ktime_compare(ktime_get(), timeout) > 0)
356 goto out;
357 }
358
359 gsw->mii_write(gsw, addr, PHY_TR_LOW_DATA, PHY_TR_LOW_VAL(data));
360 gsw->mii_write(gsw, addr, PHY_TR_HIGH_DATA, PHY_TR_HIGH_VAL(data));
361 val = PHY_TR_PKT_XMT_STA | (PHY_TR_WRITE << PHY_TR_WR_S) |
362 (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
363 (daddr << PHY_TR_DATA_ADDR_S);
364 gsw->mii_write(gsw, addr, PHY_TR_CTRL, val);
365
366 timeout_us = 100000;
367 timeout = ktime_add_us(ktime_get(), timeout_us);
368 while (1) {
369 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
370
371 if (!!(val & PHY_TR_PKT_XMT_STA))
372 break;
373
374 if (ktime_compare(ktime_get(), timeout) > 0)
375 goto out;
376 }
377out:
378 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
379}
380
381int mt753x_tr_read(struct gsw_mt753x *gsw, int addr, u8 ch, u8 node, u8 daddr)
382{
383 ktime_t timeout;
384 u32 timeout_us;
385 u32 val;
386 u8 val_h;
387
388 if (addr < MT753X_NUM_PHYS)
389 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
390
391 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
392
393 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
394
395 timeout_us = 100000;
396 timeout = ktime_add_us(ktime_get(), timeout_us);
397 while (1) {
398 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
399
400 if (!!(val & PHY_TR_PKT_XMT_STA))
401 break;
402
403 if (ktime_compare(ktime_get(), timeout) > 0) {
404 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
405 return -ETIMEDOUT;
406 }
407 }
408
409 val = PHY_TR_PKT_XMT_STA | (PHY_TR_READ << PHY_TR_WR_S) |
410 (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
411 (daddr << PHY_TR_DATA_ADDR_S);
412 gsw->mii_write(gsw, addr, PHY_TR_CTRL, val);
413
414 timeout_us = 100000;
415 timeout = ktime_add_us(ktime_get(), timeout_us);
416 while (1) {
417 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
418
419 if (!!(val & PHY_TR_PKT_XMT_STA))
420 break;
421
422 if (ktime_compare(ktime_get(), timeout) > 0) {
423 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
424 return -ETIMEDOUT;
425 }
426 }
427
428 val = gsw->mii_read(gsw, addr, PHY_TR_LOW_DATA);
429 val_h = gsw->mii_read(gsw, addr, PHY_TR_HIGH_DATA);
430 val |= (val_h << 16);
431
432 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
433
434 return val;
435}
436
437static void mt753x_add_gsw(struct gsw_mt753x *gsw)
438{
439 mutex_lock(&mt753x_devs_lock);
440 gsw->id = mt753x_id++;
441 INIT_LIST_HEAD(&gsw->list);
442 list_add_tail(&gsw->list, &mt753x_devs);
443 mutex_unlock(&mt753x_devs_lock);
444}
445
446static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
447{
448 mutex_lock(&mt753x_devs_lock);
449 list_del(&gsw->list);
450 mutex_unlock(&mt753x_devs_lock);
451}
452
developerfd40db22021-04-29 10:08:25 +0800453struct gsw_mt753x *mt753x_get_gsw(u32 id)
454{
455 struct gsw_mt753x *dev;
456
457 mutex_lock(&mt753x_devs_lock);
458
459 list_for_each_entry(dev, &mt753x_devs, list) {
460 if (dev->id == id)
461 return dev;
462 }
463
464 mutex_unlock(&mt753x_devs_lock);
465
466 return NULL;
467}
468
469struct gsw_mt753x *mt753x_get_first_gsw(void)
470{
471 struct gsw_mt753x *dev;
472
473 mutex_lock(&mt753x_devs_lock);
474
475 list_for_each_entry(dev, &mt753x_devs, list)
476 return dev;
477
478 mutex_unlock(&mt753x_devs_lock);
479
480 return NULL;
481}
482
483void mt753x_put_gsw(void)
484{
485 mutex_unlock(&mt753x_devs_lock);
486}
487
488void mt753x_lock_gsw(void)
489{
490 mutex_lock(&mt753x_devs_lock);
491}
492
493static int mt753x_hw_reset(struct gsw_mt753x *gsw)
494{
495 struct device_node *np = gsw->dev->of_node;
496 struct reset_control *rstc;
497 int mcm;
developera48549f2022-12-29 17:34:13 +0800498 int ret;
developerfd40db22021-04-29 10:08:25 +0800499
500 mcm = of_property_read_bool(np, "mediatek,mcm");
501 if (mcm) {
502 rstc = devm_reset_control_get(gsw->dev, "mcm");
503 ret = IS_ERR(rstc);
504 if (IS_ERR(rstc)) {
505 dev_err(gsw->dev, "Missing reset ctrl of switch\n");
506 return ret;
507 }
508
509 reset_control_assert(rstc);
510 msleep(30);
511 reset_control_deassert(rstc);
512
513 gsw->reset_pin = -1;
514 return 0;
515 }
516
517 gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
518 if (gsw->reset_pin < 0) {
developer2cdaeb12022-10-04 20:25:05 +0800519 dev_info(gsw->dev, "No reset pin of switch\n");
520 return 0;
developerfd40db22021-04-29 10:08:25 +0800521 }
522
523 ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset");
524 if (ret) {
525 dev_info(gsw->dev, "Failed to request gpio %d\n",
526 gsw->reset_pin);
527 return ret;
528 }
529
530 gpio_direction_output(gsw->reset_pin, 0);
531 msleep(30);
532 gpio_set_value(gsw->reset_pin, 1);
533 msleep(500);
534
535 return 0;
536}
developer2cdaeb12022-10-04 20:25:05 +0800537
developerfd40db22021-04-29 10:08:25 +0800538static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
539{
540 struct gsw_mt753x *gsw = bus->priv;
541
542 return gsw->mii_read(gsw, addr, reg);
543}
544
545static int mt753x_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
546{
547 struct gsw_mt753x *gsw = bus->priv;
548
549 gsw->mii_write(gsw, addr, reg, val);
550
551 return 0;
552}
553
developer2cdaeb12022-10-04 20:25:05 +0800554static const struct net_device_ops mt753x_dummy_netdev_ops = {};
developerfd40db22021-04-29 10:08:25 +0800555
556static void mt753x_phy_link_handler(struct net_device *dev)
557{
558 struct mt753x_phy *phy = container_of(dev, struct mt753x_phy, netdev);
559 struct phy_device *phydev = phy->phydev;
560 struct gsw_mt753x *gsw = phy->gsw;
561 u32 port = phy - gsw->phys;
562
563 if (phydev->link) {
564 dev_info(gsw->dev,
developer2cdaeb12022-10-04 20:25:05 +0800565 "Port %d Link is Up - %s/%s - flow control %s\n", port,
566 phy_speed_to_str(phydev->speed),
developerfd40db22021-04-29 10:08:25 +0800567 (phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
568 phydev->pause ? "rx/tx" : "off");
569 } else {
570 dev_info(gsw->dev, "Port %d Link is Down\n", port);
571 }
572}
573
574static void mt753x_connect_internal_phys(struct gsw_mt753x *gsw,
575 struct device_node *mii_np)
576{
577 struct device_node *phy_np;
578 struct mt753x_phy *phy;
developer2cdaeb12022-10-04 20:25:05 +0800579 phy_interface_t iface;
developerfd40db22021-04-29 10:08:25 +0800580 u32 phyad;
581
582 if (!mii_np)
583 return;
584
585 for_each_child_of_node(mii_np, phy_np) {
586 if (of_property_read_u32(phy_np, "reg", &phyad))
587 continue;
588
589 if (phyad >= MT753X_NUM_PHYS)
590 continue;
591
developer070a3372022-11-11 16:55:46 +0800592 iface = of_get_phy_mode(phy_np);
593 if (iface < 0) {
developerfd40db22021-04-29 10:08:25 +0800594 dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
developer2cdaeb12022-10-04 20:25:05 +0800595 iface, phyad);
developerfd40db22021-04-29 10:08:25 +0800596 continue;
597 }
598
599 phy = &gsw->phys[phyad];
600 phy->gsw = gsw;
601
602 init_dummy_netdev(&phy->netdev);
603 phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
604
605 phy->phydev = of_phy_connect(&phy->netdev, phy_np,
developer070a3372022-11-11 16:55:46 +0800606 mt753x_phy_link_handler, 0, iface);
developerfd40db22021-04-29 10:08:25 +0800607 if (!phy->phydev) {
608 dev_info(gsw->dev, "could not connect to PHY %d\n",
609 phyad);
610 continue;
611 }
612
613 phy_start(phy->phydev);
614 }
615}
616
617static void mt753x_disconnect_internal_phys(struct gsw_mt753x *gsw)
618{
619 int i;
620
621 for (i = 0; i < ARRAY_SIZE(gsw->phys); i++) {
622 if (gsw->phys[i].phydev) {
623 phy_stop(gsw->phys[i].phydev);
624 phy_disconnect(gsw->phys[i].phydev);
625 gsw->phys[i].phydev = NULL;
626 }
627 }
628}
629
630static int mt753x_mdio_register(struct gsw_mt753x *gsw)
631{
632 struct device_node *mii_np;
633 int i, ret;
634
635 mii_np = of_get_child_by_name(gsw->dev->of_node, "mdio-bus");
636 if (mii_np && !of_device_is_available(mii_np)) {
637 ret = -ENODEV;
638 goto err_put_node;
639 }
640
641 gsw->gphy_bus = devm_mdiobus_alloc(gsw->dev);
642 if (!gsw->gphy_bus) {
643 ret = -ENOMEM;
644 goto err_put_node;
645 }
646
647 gsw->gphy_bus->name = "mt753x_mdio";
648 gsw->gphy_bus->read = mt753x_mdio_read;
649 gsw->gphy_bus->write = mt753x_mdio_write;
650 gsw->gphy_bus->priv = gsw;
651 gsw->gphy_bus->parent = gsw->dev;
652 gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
developer2cdaeb12022-10-04 20:25:05 +0800653 // gsw->gphy_bus->irq = gsw->phy_irqs;
developerfd40db22021-04-29 10:08:25 +0800654
655 for (i = 0; i < PHY_MAX_ADDR; i++)
656 gsw->gphy_bus->irq[i] = PHY_POLL;
657
658 if (mii_np)
659 snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "%s@%s",
660 mii_np->name, gsw->dev->of_node->name);
661 else
662 snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "mdio@%s",
663 gsw->dev->of_node->name);
664
665 ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
666
667 if (ret) {
developerfd40db22021-04-29 10:08:25 +0800668 gsw->gphy_bus = NULL;
669 } else {
670 if (gsw->phy_status_poll)
671 mt753x_connect_internal_phys(gsw, mii_np);
672 }
673
674err_put_node:
675 if (mii_np)
676 of_node_put(mii_np);
677
678 return ret;
679}
developerfd40db22021-04-29 10:08:25 +0800680
681static irqreturn_t mt753x_irq_handler(int irq, void *dev)
682{
683 struct gsw_mt753x *gsw = dev;
684
685 disable_irq_nosync(gsw->irq);
686
687 schedule_work(&gsw->irq_worker);
688
689 return IRQ_HANDLED;
690}
691
692static int mt753x_probe(struct platform_device *pdev)
693{
694 struct gsw_mt753x *gsw;
695 struct mt753x_sw_id *sw;
696 struct device_node *np = pdev->dev.of_node;
697 struct device_node *mdio;
698 struct mii_bus *mdio_bus;
699 int ret = -EINVAL;
700 struct chip_rev rev;
701 struct mt753x_mapping *map;
702 int i;
703
704 mdio = of_parse_phandle(np, "mediatek,mdio", 0);
705 if (!mdio)
706 return -EINVAL;
707
708 mdio_bus = of_mdio_find_bus(mdio);
709 if (!mdio_bus)
710 return -EPROBE_DEFER;
711
712 gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_mt753x), GFP_KERNEL);
713 if (!gsw)
714 return -ENOMEM;
715
716 gsw->host_bus = mdio_bus;
717 gsw->dev = &pdev->dev;
718 mutex_init(&gsw->mii_lock);
719
720 /* Switch hard reset */
developer2cdaeb12022-10-04 20:25:05 +0800721 if (mt753x_hw_reset(gsw)) {
722 dev_info(&pdev->dev, "reset switch fail.\n");
developerfd40db22021-04-29 10:08:25 +0800723 goto fail;
developer2cdaeb12022-10-04 20:25:05 +0800724 }
developerfd40db22021-04-29 10:08:25 +0800725
726 /* Fetch the SMI address dirst */
727 if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
728 gsw->smi_addr = MT753X_DFL_SMI_ADDR;
729
730 /* Get LAN/WAN port mapping */
731 map = mt753x_find_mapping(np);
732 if (map) {
733 mt753x_apply_mapping(gsw, map);
734 gsw->global_vlan_enable = 1;
735 dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
736 }
737
738 /* Load MAC port configurations */
739 mt753x_load_port_cfg(gsw);
740
741 /* Check for valid switch and then initialize */
742 for (i = 0; i < ARRAY_SIZE(mt753x_sw_ids); i++) {
743 if (!mt753x_sw_ids[i]->detect(gsw, &rev)) {
744 sw = mt753x_sw_ids[i];
745
746 gsw->name = rev.name;
747 gsw->model = sw->model;
748
749 dev_info(gsw->dev, "Switch is MediaTek %s rev %d",
750 gsw->name, rev.rev);
751
752 /* Initialize the switch */
753 ret = sw->init(gsw);
754 if (ret)
755 goto fail;
756
757 break;
758 }
759 }
760
761 if (i >= ARRAY_SIZE(mt753x_sw_ids)) {
762 dev_err(gsw->dev, "No mt753x switch found\n");
763 goto fail;
764 }
765
766 gsw->irq = platform_get_irq(pdev, 0);
767 if (gsw->irq >= 0) {
768 ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler,
769 0, dev_name(gsw->dev), gsw);
770 if (ret) {
771 dev_err(gsw->dev, "Failed to request irq %d\n",
772 gsw->irq);
773 goto fail;
774 }
775
776 INIT_WORK(&gsw->irq_worker, mt753x_irq_worker);
777 }
778
779 platform_set_drvdata(pdev, gsw);
780
developer2cdaeb12022-10-04 20:25:05 +0800781 gsw->phy_status_poll =
782 of_property_read_bool(gsw->dev->of_node, "mediatek,phy-poll");
developerfd40db22021-04-29 10:08:25 +0800783
784 mt753x_add_gsw(gsw);
785#if 1 //XDXD
786 mt753x_mdio_register(gsw);
787#endif
788
developer5145ebb2022-07-14 15:16:24 +0800789 mt753x_nl_init();
790
developerfd40db22021-04-29 10:08:25 +0800791 mt753x_swconfig_init(gsw);
792
793 if (sw->post_init)
794 sw->post_init(gsw);
795
796 if (gsw->irq >= 0)
797 mt753x_irq_enable(gsw);
798
799 return 0;
800
801fail:
802 devm_kfree(&pdev->dev, gsw);
803
804 return ret;
805}
806
807static int mt753x_remove(struct platform_device *pdev)
808{
809 struct gsw_mt753x *gsw = platform_get_drvdata(pdev);
810
811 if (gsw->irq >= 0)
812 cancel_work_sync(&gsw->irq_worker);
813
814 if (gsw->reset_pin >= 0)
815 devm_gpio_free(&pdev->dev, gsw->reset_pin);
816
817#ifdef CONFIG_SWCONFIG
818 mt753x_swconfig_destroy(gsw);
819#endif
820
821#if 1 //XDXD
822 mt753x_disconnect_internal_phys(gsw);
823
824 mdiobus_unregister(gsw->gphy_bus);
825#endif
826
developer5145ebb2022-07-14 15:16:24 +0800827 mt753x_nl_exit();
828
developerfd40db22021-04-29 10:08:25 +0800829 mt753x_remove_gsw(gsw);
830
831 platform_set_drvdata(pdev, NULL);
832
833 return 0;
834}
835
836static const struct of_device_id mt753x_ids[] = {
837 { .compatible = "mediatek,mt753x" },
developer2cdaeb12022-10-04 20:25:05 +0800838 {},
developerfd40db22021-04-29 10:08:25 +0800839};
840
841MODULE_DEVICE_TABLE(of, mt753x_ids);
842
843static struct platform_driver mt753x_driver = {
844 .probe = mt753x_probe,
845 .remove = mt753x_remove,
846 .driver = {
847 .name = "mt753x",
848 .of_match_table = mt753x_ids,
849 },
850};
851
852static int __init mt753x_init(void)
853{
854 int ret;
855
856 INIT_LIST_HEAD(&mt753x_devs);
857 ret = platform_driver_register(&mt753x_driver);
858
developerfd40db22021-04-29 10:08:25 +0800859 return ret;
860}
861module_init(mt753x_init);
862
863static void __exit mt753x_exit(void)
864{
developerfd40db22021-04-29 10:08:25 +0800865 platform_driver_unregister(&mt753x_driver);
866}
867module_exit(mt753x_exit);
868
869MODULE_LICENSE("GPL");
870MODULE_AUTHOR("Weijie Gao <weijie.gao@mediatek.com>");
871MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");