blob: c57a5a24b6894d7700766323dba901e9853a9fd6 [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;
developer2cdaeb12022-10-04 20:25:05 +0800253 int ret;
developerfd40db22021-04-29 10:08:25 +0800254
255 for_each_child_of_node(gsw->dev->of_node, port_np) {
256 if (!of_device_is_compatible(port_np, "mediatek,mt753x-port"))
257 continue;
258
259 if (!of_device_is_available(port_np))
260 continue;
261
262 if (of_property_read_u32(port_np, "reg", &port))
263 continue;
264
265 switch (port) {
266 case 5:
267 port_cfg = &gsw->port5_cfg;
268 break;
269 case 6:
270 port_cfg = &gsw->port6_cfg;
271 break;
272 default:
273 continue;
274 }
275
276 if (port_cfg->enabled) {
277 dev_info(gsw->dev, "duplicated node for port%d\n",
278 port_cfg->phy_mode);
279 continue;
280 }
281
282 port_cfg->np = port_np;
283
developer2cdaeb12022-10-04 20:25:05 +0800284 ret = of_get_phy_mode(port_cfg->np);
285 if (ret < 0) {
developerfd40db22021-04-29 10:08:25 +0800286 dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
287 continue;
288 }
289
290 fixed_link_node = of_get_child_by_name(port_np, "fixed-link");
291 if (fixed_link_node) {
292 u32 speed;
293
294 port_cfg->force_link = 1;
295 port_cfg->duplex = mt753x_get_duplex(fixed_link_node);
296
297 if (of_property_read_u32(fixed_link_node, "speed",
298 &speed)) {
299 speed = 0;
300 continue;
301 }
302
303 of_node_put(fixed_link_node);
304
305 switch (speed) {
306 case 10:
307 port_cfg->speed = MAC_SPD_10;
308 break;
309 case 100:
310 port_cfg->speed = MAC_SPD_100;
311 break;
312 case 1000:
313 port_cfg->speed = MAC_SPD_1000;
314 break;
315 case 2500:
316 port_cfg->speed = MAC_SPD_2500;
317 break;
developer2cdaeb12022-10-04 20:25:05 +0800318
developerfd40db22021-04-29 10:08:25 +0800319 default:
320 dev_info(gsw->dev, "incorrect speed %d\n",
321 speed);
322 continue;
323 }
324 }
325
developer2cdaeb12022-10-04 20:25:05 +0800326 port_cfg->ssc_on =
327 of_property_read_bool(port_cfg->np, "mediatek,ssc-on");
328 port_cfg->stag_on =
329 of_property_read_bool(port_cfg->np, "mediatek,stag-on");
developerfd40db22021-04-29 10:08:25 +0800330 port_cfg->enabled = 1;
331 }
332}
333
334void mt753x_tr_write(struct gsw_mt753x *gsw, int addr, u8 ch, u8 node, u8 daddr,
335 u32 data)
336{
337 ktime_t timeout;
338 u32 timeout_us;
339 u32 val;
340
341 if (addr < MT753X_NUM_PHYS)
342 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
343
344 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
345
346 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
347
348 timeout_us = 100000;
349 timeout = ktime_add_us(ktime_get(), timeout_us);
350 while (1) {
351 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
352
353 if (!!(val & PHY_TR_PKT_XMT_STA))
354 break;
355
356 if (ktime_compare(ktime_get(), timeout) > 0)
357 goto out;
358 }
359
360 gsw->mii_write(gsw, addr, PHY_TR_LOW_DATA, PHY_TR_LOW_VAL(data));
361 gsw->mii_write(gsw, addr, PHY_TR_HIGH_DATA, PHY_TR_HIGH_VAL(data));
362 val = PHY_TR_PKT_XMT_STA | (PHY_TR_WRITE << PHY_TR_WR_S) |
363 (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
364 (daddr << PHY_TR_DATA_ADDR_S);
365 gsw->mii_write(gsw, addr, PHY_TR_CTRL, val);
366
367 timeout_us = 100000;
368 timeout = ktime_add_us(ktime_get(), timeout_us);
369 while (1) {
370 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
371
372 if (!!(val & PHY_TR_PKT_XMT_STA))
373 break;
374
375 if (ktime_compare(ktime_get(), timeout) > 0)
376 goto out;
377 }
378out:
379 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
380}
381
382int mt753x_tr_read(struct gsw_mt753x *gsw, int addr, u8 ch, u8 node, u8 daddr)
383{
384 ktime_t timeout;
385 u32 timeout_us;
386 u32 val;
387 u8 val_h;
388
389 if (addr < MT753X_NUM_PHYS)
390 addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK;
391
392 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, PHY_TR_PAGE);
393
394 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
395
396 timeout_us = 100000;
397 timeout = ktime_add_us(ktime_get(), timeout_us);
398 while (1) {
399 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
400
401 if (!!(val & PHY_TR_PKT_XMT_STA))
402 break;
403
404 if (ktime_compare(ktime_get(), timeout) > 0) {
405 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
406 return -ETIMEDOUT;
407 }
408 }
409
410 val = PHY_TR_PKT_XMT_STA | (PHY_TR_READ << PHY_TR_WR_S) |
411 (ch << PHY_TR_CH_ADDR_S) | (node << PHY_TR_NODE_ADDR_S) |
412 (daddr << PHY_TR_DATA_ADDR_S);
413 gsw->mii_write(gsw, addr, PHY_TR_CTRL, val);
414
415 timeout_us = 100000;
416 timeout = ktime_add_us(ktime_get(), timeout_us);
417 while (1) {
418 val = gsw->mii_read(gsw, addr, PHY_TR_CTRL);
419
420 if (!!(val & PHY_TR_PKT_XMT_STA))
421 break;
422
423 if (ktime_compare(ktime_get(), timeout) > 0) {
424 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
425 return -ETIMEDOUT;
426 }
427 }
428
429 val = gsw->mii_read(gsw, addr, PHY_TR_LOW_DATA);
430 val_h = gsw->mii_read(gsw, addr, PHY_TR_HIGH_DATA);
431 val |= (val_h << 16);
432
433 gsw->mii_write(gsw, addr, PHY_CL22_PAGE_CTRL, 0);
434
435 return val;
436}
437
438static void mt753x_add_gsw(struct gsw_mt753x *gsw)
439{
440 mutex_lock(&mt753x_devs_lock);
441 gsw->id = mt753x_id++;
442 INIT_LIST_HEAD(&gsw->list);
443 list_add_tail(&gsw->list, &mt753x_devs);
444 mutex_unlock(&mt753x_devs_lock);
445}
446
447static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
448{
449 mutex_lock(&mt753x_devs_lock);
450 list_del(&gsw->list);
451 mutex_unlock(&mt753x_devs_lock);
452}
453
developerfd40db22021-04-29 10:08:25 +0800454struct gsw_mt753x *mt753x_get_gsw(u32 id)
455{
456 struct gsw_mt753x *dev;
457
458 mutex_lock(&mt753x_devs_lock);
459
460 list_for_each_entry(dev, &mt753x_devs, list) {
461 if (dev->id == id)
462 return dev;
463 }
464
465 mutex_unlock(&mt753x_devs_lock);
466
467 return NULL;
468}
469
470struct gsw_mt753x *mt753x_get_first_gsw(void)
471{
472 struct gsw_mt753x *dev;
473
474 mutex_lock(&mt753x_devs_lock);
475
476 list_for_each_entry(dev, &mt753x_devs, list)
477 return dev;
478
479 mutex_unlock(&mt753x_devs_lock);
480
481 return NULL;
482}
483
484void mt753x_put_gsw(void)
485{
486 mutex_unlock(&mt753x_devs_lock);
487}
488
489void mt753x_lock_gsw(void)
490{
491 mutex_lock(&mt753x_devs_lock);
492}
493
494static int mt753x_hw_reset(struct gsw_mt753x *gsw)
495{
496 struct device_node *np = gsw->dev->of_node;
497 struct reset_control *rstc;
498 int mcm;
499 int ret = -EINVAL;
500
501 mcm = of_property_read_bool(np, "mediatek,mcm");
502 if (mcm) {
503 rstc = devm_reset_control_get(gsw->dev, "mcm");
504 ret = IS_ERR(rstc);
505 if (IS_ERR(rstc)) {
506 dev_err(gsw->dev, "Missing reset ctrl of switch\n");
507 return ret;
508 }
509
510 reset_control_assert(rstc);
511 msleep(30);
512 reset_control_deassert(rstc);
513
514 gsw->reset_pin = -1;
515 return 0;
516 }
517
518 gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
519 if (gsw->reset_pin < 0) {
developer2cdaeb12022-10-04 20:25:05 +0800520 dev_info(gsw->dev, "No reset pin of switch\n");
521 return 0;
developerfd40db22021-04-29 10:08:25 +0800522 }
523
524 ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset");
525 if (ret) {
526 dev_info(gsw->dev, "Failed to request gpio %d\n",
527 gsw->reset_pin);
528 return ret;
529 }
530
531 gpio_direction_output(gsw->reset_pin, 0);
532 msleep(30);
533 gpio_set_value(gsw->reset_pin, 1);
534 msleep(500);
535
536 return 0;
537}
developer2cdaeb12022-10-04 20:25:05 +0800538
developerfd40db22021-04-29 10:08:25 +0800539static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
540{
541 struct gsw_mt753x *gsw = bus->priv;
542
543 return gsw->mii_read(gsw, addr, reg);
544}
545
546static int mt753x_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
547{
548 struct gsw_mt753x *gsw = bus->priv;
549
550 gsw->mii_write(gsw, addr, reg, val);
551
552 return 0;
553}
554
developer2cdaeb12022-10-04 20:25:05 +0800555static const struct net_device_ops mt753x_dummy_netdev_ops = {};
developerfd40db22021-04-29 10:08:25 +0800556
557static void mt753x_phy_link_handler(struct net_device *dev)
558{
559 struct mt753x_phy *phy = container_of(dev, struct mt753x_phy, netdev);
560 struct phy_device *phydev = phy->phydev;
561 struct gsw_mt753x *gsw = phy->gsw;
562 u32 port = phy - gsw->phys;
563
564 if (phydev->link) {
565 dev_info(gsw->dev,
developer2cdaeb12022-10-04 20:25:05 +0800566 "Port %d Link is Up - %s/%s - flow control %s\n", port,
567 phy_speed_to_str(phydev->speed),
developerfd40db22021-04-29 10:08:25 +0800568 (phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
569 phydev->pause ? "rx/tx" : "off");
570 } else {
571 dev_info(gsw->dev, "Port %d Link is Down\n", port);
572 }
573}
574
575static void mt753x_connect_internal_phys(struct gsw_mt753x *gsw,
576 struct device_node *mii_np)
577{
578 struct device_node *phy_np;
579 struct mt753x_phy *phy;
developer2cdaeb12022-10-04 20:25:05 +0800580 phy_interface_t iface;
581 int ret;
developerfd40db22021-04-29 10:08:25 +0800582 u32 phyad;
583
584 if (!mii_np)
585 return;
586
587 for_each_child_of_node(mii_np, phy_np) {
588 if (of_property_read_u32(phy_np, "reg", &phyad))
589 continue;
590
591 if (phyad >= MT753X_NUM_PHYS)
592 continue;
593
developer2cdaeb12022-10-04 20:25:05 +0800594 ret = of_get_phy_mode(phy_np);
595 if (ret < 0) {
developerfd40db22021-04-29 10:08:25 +0800596 dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
developer2cdaeb12022-10-04 20:25:05 +0800597 iface, phyad);
developerfd40db22021-04-29 10:08:25 +0800598 continue;
599 }
600
601 phy = &gsw->phys[phyad];
602 phy->gsw = gsw;
603
604 init_dummy_netdev(&phy->netdev);
605 phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
606
607 phy->phydev = of_phy_connect(&phy->netdev, phy_np,
developer2cdaeb12022-10-04 20:25:05 +0800608 mt753x_phy_link_handler, 0, iface);
developerfd40db22021-04-29 10:08:25 +0800609 if (!phy->phydev) {
610 dev_info(gsw->dev, "could not connect to PHY %d\n",
611 phyad);
612 continue;
613 }
614
615 phy_start(phy->phydev);
616 }
617}
618
619static void mt753x_disconnect_internal_phys(struct gsw_mt753x *gsw)
620{
621 int i;
622
623 for (i = 0; i < ARRAY_SIZE(gsw->phys); i++) {
624 if (gsw->phys[i].phydev) {
625 phy_stop(gsw->phys[i].phydev);
626 phy_disconnect(gsw->phys[i].phydev);
627 gsw->phys[i].phydev = NULL;
628 }
629 }
630}
631
632static int mt753x_mdio_register(struct gsw_mt753x *gsw)
633{
634 struct device_node *mii_np;
635 int i, ret;
636
637 mii_np = of_get_child_by_name(gsw->dev->of_node, "mdio-bus");
638 if (mii_np && !of_device_is_available(mii_np)) {
639 ret = -ENODEV;
640 goto err_put_node;
641 }
642
643 gsw->gphy_bus = devm_mdiobus_alloc(gsw->dev);
644 if (!gsw->gphy_bus) {
645 ret = -ENOMEM;
646 goto err_put_node;
647 }
648
649 gsw->gphy_bus->name = "mt753x_mdio";
650 gsw->gphy_bus->read = mt753x_mdio_read;
651 gsw->gphy_bus->write = mt753x_mdio_write;
652 gsw->gphy_bus->priv = gsw;
653 gsw->gphy_bus->parent = gsw->dev;
654 gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
developer2cdaeb12022-10-04 20:25:05 +0800655 // gsw->gphy_bus->irq = gsw->phy_irqs;
developerfd40db22021-04-29 10:08:25 +0800656
657 for (i = 0; i < PHY_MAX_ADDR; i++)
658 gsw->gphy_bus->irq[i] = PHY_POLL;
659
660 if (mii_np)
661 snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "%s@%s",
662 mii_np->name, gsw->dev->of_node->name);
663 else
664 snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "mdio@%s",
665 gsw->dev->of_node->name);
666
667 ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
668
669 if (ret) {
developerfd40db22021-04-29 10:08:25 +0800670 gsw->gphy_bus = NULL;
671 } else {
672 if (gsw->phy_status_poll)
673 mt753x_connect_internal_phys(gsw, mii_np);
674 }
675
676err_put_node:
677 if (mii_np)
678 of_node_put(mii_np);
679
680 return ret;
681}
developerfd40db22021-04-29 10:08:25 +0800682
683static irqreturn_t mt753x_irq_handler(int irq, void *dev)
684{
685 struct gsw_mt753x *gsw = dev;
686
687 disable_irq_nosync(gsw->irq);
688
689 schedule_work(&gsw->irq_worker);
690
691 return IRQ_HANDLED;
692}
693
694static int mt753x_probe(struct platform_device *pdev)
695{
696 struct gsw_mt753x *gsw;
697 struct mt753x_sw_id *sw;
698 struct device_node *np = pdev->dev.of_node;
699 struct device_node *mdio;
700 struct mii_bus *mdio_bus;
701 int ret = -EINVAL;
702 struct chip_rev rev;
703 struct mt753x_mapping *map;
704 int i;
705
706 mdio = of_parse_phandle(np, "mediatek,mdio", 0);
707 if (!mdio)
708 return -EINVAL;
709
710 mdio_bus = of_mdio_find_bus(mdio);
711 if (!mdio_bus)
712 return -EPROBE_DEFER;
713
714 gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_mt753x), GFP_KERNEL);
715 if (!gsw)
716 return -ENOMEM;
717
718 gsw->host_bus = mdio_bus;
719 gsw->dev = &pdev->dev;
720 mutex_init(&gsw->mii_lock);
721
722 /* Switch hard reset */
developer2cdaeb12022-10-04 20:25:05 +0800723 if (mt753x_hw_reset(gsw)) {
724 dev_info(&pdev->dev, "reset switch fail.\n");
developerfd40db22021-04-29 10:08:25 +0800725 goto fail;
developer2cdaeb12022-10-04 20:25:05 +0800726 }
developerfd40db22021-04-29 10:08:25 +0800727
728 /* Fetch the SMI address dirst */
729 if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
730 gsw->smi_addr = MT753X_DFL_SMI_ADDR;
731
732 /* Get LAN/WAN port mapping */
733 map = mt753x_find_mapping(np);
734 if (map) {
735 mt753x_apply_mapping(gsw, map);
736 gsw->global_vlan_enable = 1;
737 dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
738 }
739
740 /* Load MAC port configurations */
741 mt753x_load_port_cfg(gsw);
742
743 /* Check for valid switch and then initialize */
744 for (i = 0; i < ARRAY_SIZE(mt753x_sw_ids); i++) {
745 if (!mt753x_sw_ids[i]->detect(gsw, &rev)) {
746 sw = mt753x_sw_ids[i];
747
748 gsw->name = rev.name;
749 gsw->model = sw->model;
750
751 dev_info(gsw->dev, "Switch is MediaTek %s rev %d",
752 gsw->name, rev.rev);
753
754 /* Initialize the switch */
755 ret = sw->init(gsw);
756 if (ret)
757 goto fail;
758
759 break;
760 }
761 }
762
763 if (i >= ARRAY_SIZE(mt753x_sw_ids)) {
764 dev_err(gsw->dev, "No mt753x switch found\n");
765 goto fail;
766 }
767
768 gsw->irq = platform_get_irq(pdev, 0);
769 if (gsw->irq >= 0) {
770 ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler,
771 0, dev_name(gsw->dev), gsw);
772 if (ret) {
773 dev_err(gsw->dev, "Failed to request irq %d\n",
774 gsw->irq);
775 goto fail;
776 }
777
778 INIT_WORK(&gsw->irq_worker, mt753x_irq_worker);
779 }
780
781 platform_set_drvdata(pdev, gsw);
782
developer2cdaeb12022-10-04 20:25:05 +0800783 gsw->phy_status_poll =
784 of_property_read_bool(gsw->dev->of_node, "mediatek,phy-poll");
developerfd40db22021-04-29 10:08:25 +0800785
786 mt753x_add_gsw(gsw);
787#if 1 //XDXD
788 mt753x_mdio_register(gsw);
789#endif
790
developer5145ebb2022-07-14 15:16:24 +0800791 mt753x_nl_init();
792
developerfd40db22021-04-29 10:08:25 +0800793 mt753x_swconfig_init(gsw);
794
795 if (sw->post_init)
796 sw->post_init(gsw);
797
798 if (gsw->irq >= 0)
799 mt753x_irq_enable(gsw);
800
801 return 0;
802
803fail:
804 devm_kfree(&pdev->dev, gsw);
805
806 return ret;
807}
808
809static int mt753x_remove(struct platform_device *pdev)
810{
811 struct gsw_mt753x *gsw = platform_get_drvdata(pdev);
812
813 if (gsw->irq >= 0)
814 cancel_work_sync(&gsw->irq_worker);
815
816 if (gsw->reset_pin >= 0)
817 devm_gpio_free(&pdev->dev, gsw->reset_pin);
818
819#ifdef CONFIG_SWCONFIG
820 mt753x_swconfig_destroy(gsw);
821#endif
822
823#if 1 //XDXD
824 mt753x_disconnect_internal_phys(gsw);
825
826 mdiobus_unregister(gsw->gphy_bus);
827#endif
828
developer5145ebb2022-07-14 15:16:24 +0800829 mt753x_nl_exit();
830
developerfd40db22021-04-29 10:08:25 +0800831 mt753x_remove_gsw(gsw);
832
833 platform_set_drvdata(pdev, NULL);
834
835 return 0;
836}
837
838static const struct of_device_id mt753x_ids[] = {
839 { .compatible = "mediatek,mt753x" },
developer2cdaeb12022-10-04 20:25:05 +0800840 {},
developerfd40db22021-04-29 10:08:25 +0800841};
842
843MODULE_DEVICE_TABLE(of, mt753x_ids);
844
845static struct platform_driver mt753x_driver = {
846 .probe = mt753x_probe,
847 .remove = mt753x_remove,
848 .driver = {
849 .name = "mt753x",
850 .of_match_table = mt753x_ids,
851 },
852};
853
854static int __init mt753x_init(void)
855{
856 int ret;
857
858 INIT_LIST_HEAD(&mt753x_devs);
859 ret = platform_driver_register(&mt753x_driver);
860
developerfd40db22021-04-29 10:08:25 +0800861 return ret;
862}
863module_init(mt753x_init);
864
865static void __exit mt753x_exit(void)
866{
developerfd40db22021-04-29 10:08:25 +0800867 platform_driver_unregister(&mt753x_driver);
868}
869module_exit(mt753x_exit);
870
871MODULE_LICENSE("GPL");
872MODULE_AUTHOR("Weijie Gao <weijie.gao@mediatek.com>");
873MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");