blob: 920240d76c3d049f9b18144f3be2a4194b99f37c [file] [log] [blame]
developer69bcd592024-03-25 14:26:39 +08001// SPDX-License-Identifian8855_gsw_ider: GPL-2.0
2/*
3 * Copyright (c) 2023 Airoha Inc.
4 * Author: Min Yao <min.yao@airoha.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 "an8855.h"
23#include "an8855_swconfig.h"
24#include "an8855_regs.h"
25#include "an8855_nl.h"
26
27/* AN8855 driver version */
28#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.1-L5.4"
29
30static u32 an8855_gsw_id;
31struct list_head an8855_devs;
32static DEFINE_MUTEX(an8855_devs_lock);
33
34static struct an8855_sw_id *an8855_sw_ids[] = {
35 &an8855_id,
36};
37
38u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg)
39{
40 u32 high, low;
41
42 mutex_lock(&gsw->host_bus->mdio_lock);
43
44 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4);
45 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
46
47 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x15,
48 ((reg >> 16) & 0xFFFF));
49 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x16,
50 (reg & 0xFFFF));
51
52 low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x18);
53 high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x17);
54
55 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
56 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
57
58 mutex_unlock(&gsw->host_bus->mdio_lock);
59
60 return (high << 16) | (low & 0xffff);
61}
62
63void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val)
64{
65 mutex_lock(&gsw->host_bus->mdio_lock);
66
67 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4);
68 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
69
70 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x11,
71 ((reg >> 16) & 0xFFFF));
72 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x12,
73 (reg & 0xFFFF));
74
75 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x13,
76 ((val >> 16) & 0xFFFF));
77 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x14,
78 (val & 0xFFFF));
79
80 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
81 gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
82
83 mutex_unlock(&gsw->host_bus->mdio_lock);
84}
85
86int an8855_mii_read(struct gsw_an8855 *gsw, int phy, int reg)
87{
88 int val;
89
90 if (phy < AN8855_NUM_PHYS)
91 phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK;
92
93 mutex_lock(&gsw->host_bus->mdio_lock);
94 val = gsw->host_bus->read(gsw->host_bus, phy, reg);
95 mutex_unlock(&gsw->host_bus->mdio_lock);
96
97 return val;
98}
99
100void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val)
101{
102 if (phy < AN8855_NUM_PHYS)
103 phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK;
104
105 mutex_lock(&gsw->host_bus->mdio_lock);
106 gsw->host_bus->write(gsw->host_bus, phy, reg, val);
107 mutex_unlock(&gsw->host_bus->mdio_lock);
108}
109
110int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg)
111{
112 int val;
113 u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
114
115 if (addr < AN8855_NUM_PHYS)
116 addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
117
118 mutex_lock(&gsw->host_bus->mdio_lock);
119 val = gsw->host_bus->read(gsw->host_bus, addr, regnum);
120 mutex_unlock(&gsw->host_bus->mdio_lock);
121
122 return val;
123}
124
125void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg,
126 u16 val)
127{
128 u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
129
130 if (addr < AN8855_NUM_PHYS)
131 addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
132
133 mutex_lock(&gsw->host_bus->mdio_lock);
134 gsw->host_bus->write(gsw->host_bus, addr, regnum, val);
135 mutex_unlock(&gsw->host_bus->mdio_lock);
136}
137
138static inline int an8855_get_duplex(const struct device_node *np)
139{
140 return of_property_read_bool(np, "full-duplex");
141}
142
143static void an8855_load_port_cfg(struct gsw_an8855 *gsw)
144{
145 struct device_node *port_np;
146 struct device_node *fixed_link_node;
147 struct an8855_port_cfg *port_cfg;
148 u32 port;
149
150 for_each_child_of_node(gsw->dev->of_node, port_np) {
151 if (!of_device_is_compatible(port_np, "airoha,an8855-port"))
152 continue;
153
154 if (!of_device_is_available(port_np))
155 continue;
156
157 if (of_property_read_u32(port_np, "reg", &port))
158 continue;
159
160 switch (port) {
161 case 5:
162 port_cfg = &gsw->port5_cfg;
163 break;
164 default:
165 continue;
166 }
167
168 if (port_cfg->enabled) {
169 dev_info(gsw->dev, "duplicated node for port%d\n",
170 port_cfg->phy_mode);
171 continue;
172 }
173
174 port_cfg->np = port_np;
175
176 port_cfg->phy_mode = of_get_phy_mode(port_np);
177 if (port_cfg->phy_mode < 0) {
178 dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
179 continue;
180 }
181
182 fixed_link_node = of_get_child_by_name(port_np, "fixed-link");
183 if (fixed_link_node) {
184 u32 speed;
185
186 port_cfg->force_link = 1;
187 port_cfg->duplex = an8855_get_duplex(fixed_link_node);
188
189 if (of_property_read_u32(fixed_link_node, "speed",
190 &speed)) {
191 speed = 0;
192 continue;
193 }
194
195 of_node_put(fixed_link_node);
196
197 switch (speed) {
198 case 10:
199 port_cfg->speed = MAC_SPD_10;
200 break;
201 case 100:
202 port_cfg->speed = MAC_SPD_100;
203 break;
204 case 1000:
205 port_cfg->speed = MAC_SPD_1000;
206 break;
207 case 2500:
208 port_cfg->speed = MAC_SPD_2500;
209 break;
210
211 default:
212 dev_info(gsw->dev, "incorrect speed %d\n",
213 speed);
214 continue;
215 }
216 }
217
218 port_cfg->stag_on =
219 of_property_read_bool(port_cfg->np, "airoha,stag-on");
220 port_cfg->enabled = 1;
221 }
222}
223
224static void an8855_add_gsw(struct gsw_an8855 *gsw)
225{
226 mutex_lock(&an8855_devs_lock);
227 gsw->id = an8855_gsw_id++;
228 INIT_LIST_HEAD(&gsw->list);
229 list_add_tail(&gsw->list, &an8855_devs);
230 mutex_unlock(&an8855_devs_lock);
231}
232
233static void an8855_remove_gsw(struct gsw_an8855 *gsw)
234{
235 mutex_lock(&an8855_devs_lock);
236 list_del(&gsw->list);
237 mutex_unlock(&an8855_devs_lock);
238}
239
240struct gsw_an8855 *an8855_get_gsw(u32 id)
241{
242 struct gsw_an8855 *dev;
243
244 mutex_lock(&an8855_devs_lock);
245
246 list_for_each_entry(dev, &an8855_devs, list) {
247 if (dev->id == id)
248 return dev;
249 }
250
251 mutex_unlock(&an8855_devs_lock);
252
253 return NULL;
254}
255
256struct gsw_an8855 *an8855_get_first_gsw(void)
257{
258 struct gsw_an8855 *dev;
259
260 mutex_lock(&an8855_devs_lock);
261
262 list_for_each_entry(dev, &an8855_devs, list)
263 return dev;
264
265 mutex_unlock(&an8855_devs_lock);
266
267 return NULL;
268}
269
270void an8855_put_gsw(void)
271{
272 mutex_unlock(&an8855_devs_lock);
273}
274
275void an8855_lock_gsw(void)
276{
277 mutex_lock(&an8855_devs_lock);
278}
279
280static int an8855_hw_reset(struct gsw_an8855 *gsw)
281{
282 struct device_node *np = gsw->dev->of_node;
283 int ret;
284
285 gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
286 if (gsw->reset_pin < 0) {
287 dev_info(gsw->dev, "No reset pin of switch\n");
288 return 0;
289 }
290
291 ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "an8855-reset");
292 if (ret) {
293 dev_info(gsw->dev, "Failed to request gpio %d\n",
294 gsw->reset_pin);
295 return ret;
296 }
297
298 gpio_direction_output(gsw->reset_pin, 0);
299 usleep_range(100000, 150000);
300 gpio_set_value(gsw->reset_pin, 1);
301 usleep_range(100000, 150000);
302
303 return 0;
304}
305
306static irqreturn_t an8855_irq_handler(int irq, void *dev)
307{
308 struct gsw_an8855 *gsw = dev;
309
310 disable_irq_nosync(gsw->irq);
311
312 schedule_work(&gsw->irq_worker);
313
314 return IRQ_HANDLED;
315}
316
317static int an8855_probe(struct platform_device *pdev)
318{
319 struct gsw_an8855 *gsw;
320 struct an8855_sw_id *sw;
321 struct device_node *np = pdev->dev.of_node;
322 struct device_node *mdio;
323 struct mii_bus *mdio_bus;
324 int ret = -EINVAL;
325 struct chip_rev rev;
326 struct an8855_mapping *map;
327 int i;
328
329 mdio = of_parse_phandle(np, "airoha,mdio", 0);
330 if (!mdio)
331 return -EINVAL;
332
333 mdio_bus = of_mdio_find_bus(mdio);
334 if (!mdio_bus)
335 return -EPROBE_DEFER;
336
337 gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_an8855), GFP_KERNEL);
338 if (!gsw)
339 return -ENOMEM;
340
341 gsw->host_bus = mdio_bus;
342 gsw->dev = &pdev->dev;
343
344 dev_info(gsw->dev, "AN8855 Driver Version=%s\n",
345 ARHT_AN8855_SWCFG_DRIVER_VER);
346
347 /* Switch hard reset */
348 if (an8855_hw_reset(gsw)) {
349 dev_info(&pdev->dev, "reset switch fail.\n");
350 goto fail;
351 }
352
353 /* Fetch the SMI address first */
354 gsw->smi_addr = AN8855_DFL_SMI_ADDR;
355 if (of_property_read_u32(np, "airoha,smi-addr", &gsw->new_smi_addr))
356 gsw->new_smi_addr = AN8855_DFL_SMI_ADDR;
357
358 /* Get LAN/WAN port mapping */
359 map = an8855_find_mapping(np);
360 if (map) {
361 an8855_apply_mapping(gsw, map);
362 gsw->global_vlan_enable = 1;
363 dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
364 }
365
366 /* Load MAC port configurations */
367 an8855_load_port_cfg(gsw);
368
369 /* Check for valid switch and then initialize */
370 an8855_gsw_id = 0;
371 for (i = 0; i < ARRAY_SIZE(an8855_sw_ids); i++) {
372 if (!an8855_sw_ids[i]->detect(gsw, &rev)) {
373 sw = an8855_sw_ids[i];
374
375 gsw->name = rev.name;
376 gsw->model = sw->model;
377
378 dev_info(gsw->dev, "Switch is Airoha %s rev %d",
379 gsw->name, rev.rev);
380
381 /* Initialize the switch */
382 ret = sw->init(gsw);
383 if (ret)
384 goto fail;
385
386 break;
387 }
388 }
389
390 if (i >= ARRAY_SIZE(an8855_sw_ids)) {
391 dev_err(gsw->dev, "No an8855 switch found\n");
392 goto fail;
393 }
394
395 gsw->irq = platform_get_irq(pdev, 0);
396 if (gsw->irq >= 0) {
397 ret = devm_request_irq(gsw->dev, gsw->irq, an8855_irq_handler,
398 0, dev_name(gsw->dev), gsw);
399 if (ret) {
400 dev_err(gsw->dev, "Failed to request irq %d\n",
401 gsw->irq);
402 goto fail;
403 }
404
405 INIT_WORK(&gsw->irq_worker, an8855_irq_worker);
406 }
407
408 platform_set_drvdata(pdev, gsw);
409
410 an8855_add_gsw(gsw);
411
412 an8855_gsw_nl_init();
413
414 an8855_swconfig_init(gsw);
415
416 if (sw->post_init)
417 sw->post_init(gsw);
418
419 if (gsw->irq >= 0)
420 an8855_irq_enable(gsw);
421
422 return 0;
423
424fail:
425 devm_kfree(&pdev->dev, gsw);
426
427 return ret;
428}
429
430static int an8855_remove(struct platform_device *pdev)
431{
432 struct gsw_an8855 *gsw = platform_get_drvdata(pdev);
433
434 if (gsw->irq >= 0)
435 cancel_work_sync(&gsw->irq_worker);
436
437 if (gsw->reset_pin >= 0)
438 devm_gpio_free(&pdev->dev, gsw->reset_pin);
439
440#ifdef CONFIG_SWCONFIG
441 an8855_swconfig_destroy(gsw);
442#endif
443
444 an8855_gsw_nl_exit();
445
446 an8855_remove_gsw(gsw);
447
448 platform_set_drvdata(pdev, NULL);
449
450 return 0;
451}
452
453static const struct of_device_id an8855_ids[] = {
454 {.compatible = "airoha,an8855"},
455 {},
456};
457
458MODULE_DEVICE_TABLE(of, an8855_ids);
459
460static struct platform_driver an8855_driver = {
461 .probe = an8855_probe,
462 .remove = an8855_remove,
463 .driver = {
464 .name = "an8855",
465 .of_match_table = an8855_ids,
466 },
467};
468
469static int __init an8855_init(void)
470{
471 int ret;
472
473 INIT_LIST_HEAD(&an8855_devs);
474 ret = platform_driver_register(&an8855_driver);
475
476 return ret;
477}
478
479module_init(an8855_init);
480
481static void __exit an8855_exit(void)
482{
483 platform_driver_unregister(&an8855_driver);
484}
485
486module_exit(an8855_exit);
487
488MODULE_LICENSE("GPL");
489MODULE_AUTHOR("Min Yao <min.yao@airoha.com>");
490MODULE_VERSION(ARHT_AN8855_SWCFG_DRIVER_VER);
491MODULE_DESCRIPTION("Driver for Airoha AN8855 Gigabit Switch");