]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/net/dsa/ocelot/felix.c
net: dsa: ocelot: add driver for Felix switch family
[mirror_ubuntu-jammy-kernel.git] / drivers / net / dsa / ocelot / felix.c
CommitLineData
56051948
VO
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2019 NXP Semiconductors
3 */
4#include <uapi/linux/if_bridge.h>
5#include <soc/mscc/ocelot.h>
6#include <linux/module.h>
7#include <linux/pci.h>
8#include <linux/of.h>
9#include <net/dsa.h>
10#include "felix.h"
11
12static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
13 int port)
14{
15 return DSA_TAG_PROTO_OCELOT;
16}
17
18static int felix_set_ageing_time(struct dsa_switch *ds,
19 unsigned int ageing_time)
20{
21 struct ocelot *ocelot = ds->priv;
22
23 ocelot_set_ageing_time(ocelot, ageing_time);
24
25 return 0;
26}
27
28static void felix_adjust_link(struct dsa_switch *ds, int port,
29 struct phy_device *phydev)
30{
31 struct ocelot *ocelot = ds->priv;
32
33 ocelot_adjust_link(ocelot, port, phydev);
34}
35
36static int felix_fdb_dump(struct dsa_switch *ds, int port,
37 dsa_fdb_dump_cb_t *cb, void *data)
38{
39 struct ocelot *ocelot = ds->priv;
40
41 return ocelot_fdb_dump(ocelot, port, cb, data);
42}
43
44static int felix_fdb_add(struct dsa_switch *ds, int port,
45 const unsigned char *addr, u16 vid)
46{
47 struct ocelot *ocelot = ds->priv;
48 bool vlan_aware;
49
50 vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port));
51
52 return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware);
53}
54
55static int felix_fdb_del(struct dsa_switch *ds, int port,
56 const unsigned char *addr, u16 vid)
57{
58 struct ocelot *ocelot = ds->priv;
59
60 return ocelot_fdb_del(ocelot, port, addr, vid);
61}
62
63static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port,
64 u8 state)
65{
66 struct ocelot *ocelot = ds->priv;
67
68 return ocelot_bridge_stp_state_set(ocelot, port, state);
69}
70
71static int felix_bridge_join(struct dsa_switch *ds, int port,
72 struct net_device *br)
73{
74 struct ocelot *ocelot = ds->priv;
75
76 return ocelot_port_bridge_join(ocelot, port, br);
77}
78
79static void felix_bridge_leave(struct dsa_switch *ds, int port,
80 struct net_device *br)
81{
82 struct ocelot *ocelot = ds->priv;
83
84 ocelot_port_bridge_leave(ocelot, port, br);
85}
86
87/* This callback needs to be present */
88static int felix_vlan_prepare(struct dsa_switch *ds, int port,
89 const struct switchdev_obj_port_vlan *vlan)
90{
91 return 0;
92}
93
94static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
95{
96 struct ocelot *ocelot = ds->priv;
97
98 ocelot_port_vlan_filtering(ocelot, port, enabled);
99
100 return 0;
101}
102
103static void felix_vlan_add(struct dsa_switch *ds, int port,
104 const struct switchdev_obj_port_vlan *vlan)
105{
106 struct ocelot *ocelot = ds->priv;
107 u16 vid;
108 int err;
109
110 for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
111 err = ocelot_vlan_add(ocelot, port, vid,
112 vlan->flags & BRIDGE_VLAN_INFO_PVID,
113 vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
114 if (err) {
115 dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n",
116 vid, port, err);
117 return;
118 }
119 }
120}
121
122static int felix_vlan_del(struct dsa_switch *ds, int port,
123 const struct switchdev_obj_port_vlan *vlan)
124{
125 struct ocelot *ocelot = ds->priv;
126 u16 vid;
127 int err;
128
129 for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
130 err = ocelot_vlan_del(ocelot, port, vid);
131 if (err) {
132 dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n",
133 vid, port, err);
134 return err;
135 }
136 }
137 return 0;
138}
139
140static int felix_port_enable(struct dsa_switch *ds, int port,
141 struct phy_device *phy)
142{
143 struct ocelot *ocelot = ds->priv;
144
145 ocelot_port_enable(ocelot, port, phy);
146
147 return 0;
148}
149
150static void felix_port_disable(struct dsa_switch *ds, int port)
151{
152 struct ocelot *ocelot = ds->priv;
153
154 return ocelot_port_disable(ocelot, port);
155}
156
157static void felix_get_strings(struct dsa_switch *ds, int port,
158 u32 stringset, u8 *data)
159{
160 struct ocelot *ocelot = ds->priv;
161
162 return ocelot_get_strings(ocelot, port, stringset, data);
163}
164
165static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
166{
167 struct ocelot *ocelot = ds->priv;
168
169 ocelot_get_ethtool_stats(ocelot, port, data);
170}
171
172static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset)
173{
174 struct ocelot *ocelot = ds->priv;
175
176 return ocelot_get_sset_count(ocelot, port, sset);
177}
178
179static int felix_get_ts_info(struct dsa_switch *ds, int port,
180 struct ethtool_ts_info *info)
181{
182 struct ocelot *ocelot = ds->priv;
183
184 return ocelot_get_ts_info(ocelot, port, info);
185}
186
187static int felix_init_structs(struct felix *felix, int num_phys_ports)
188{
189 struct ocelot *ocelot = &felix->ocelot;
190 resource_size_t base;
191 int port, i, err;
192
193 ocelot->num_phys_ports = num_phys_ports;
194 ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports,
195 sizeof(struct ocelot_port *), GFP_KERNEL);
196 if (!ocelot->ports)
197 return -ENOMEM;
198
199 ocelot->map = felix->info->map;
200 ocelot->stats_layout = felix->info->stats_layout;
201 ocelot->num_stats = felix->info->num_stats;
202 ocelot->shared_queue_sz = felix->info->shared_queue_sz;
203 ocelot->ops = felix->info->ops;
204
205 base = pci_resource_start(felix->pdev, felix->info->pci_bar);
206
207 for (i = 0; i < TARGET_MAX; i++) {
208 struct regmap *target;
209 struct resource *res;
210
211 if (!felix->info->target_io_res[i].name)
212 continue;
213
214 res = &felix->info->target_io_res[i];
215 res->flags = IORESOURCE_MEM;
216 res->start += base;
217 res->end += base;
218
219 target = ocelot_regmap_init(ocelot, res);
220 if (IS_ERR(target)) {
221 dev_err(ocelot->dev,
222 "Failed to map device memory space\n");
223 return PTR_ERR(target);
224 }
225
226 ocelot->targets[i] = target;
227 }
228
229 err = ocelot_regfields_init(ocelot, felix->info->regfields);
230 if (err) {
231 dev_err(ocelot->dev, "failed to init reg fields map\n");
232 return err;
233 }
234
235 for (port = 0; port < num_phys_ports; port++) {
236 struct ocelot_port *ocelot_port;
237 void __iomem *port_regs;
238 struct resource *res;
239
240 ocelot_port = devm_kzalloc(ocelot->dev,
241 sizeof(struct ocelot_port),
242 GFP_KERNEL);
243 if (!ocelot_port) {
244 dev_err(ocelot->dev,
245 "failed to allocate port memory\n");
246 return -ENOMEM;
247 }
248
249 res = &felix->info->port_io_res[port];
250 res->flags = IORESOURCE_MEM;
251 res->start += base;
252 res->end += base;
253
254 port_regs = devm_ioremap_resource(ocelot->dev, res);
255 if (IS_ERR(port_regs)) {
256 dev_err(ocelot->dev,
257 "failed to map registers for port %d\n", port);
258 return PTR_ERR(port_regs);
259 }
260
261 ocelot_port->ocelot = ocelot;
262 ocelot_port->regs = port_regs;
263 ocelot->ports[port] = ocelot_port;
264 }
265
266 return 0;
267}
268
269/* Hardware initialization done here so that we can allocate structures with
270 * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
271 * us to allocate structures twice (leak memory) and map PCI memory twice
272 * (which will not work).
273 */
274static int felix_setup(struct dsa_switch *ds)
275{
276 struct ocelot *ocelot = ds->priv;
277 struct felix *felix = ocelot_to_felix(ocelot);
278 int port, err;
279
280 err = felix_init_structs(felix, ds->num_ports);
281 if (err)
282 return err;
283
284 ocelot_init(ocelot);
285
286 for (port = 0; port < ds->num_ports; port++) {
287 ocelot_init_port(ocelot, port);
288
289 if (port == dsa_upstream_port(ds, port))
290 ocelot_set_cpu_port(ocelot, port,
291 OCELOT_TAG_PREFIX_NONE,
292 OCELOT_TAG_PREFIX_LONG);
293 }
294
295 return 0;
296}
297
298static void felix_teardown(struct dsa_switch *ds)
299{
300 struct ocelot *ocelot = ds->priv;
301
302 /* stop workqueue thread */
303 ocelot_deinit(ocelot);
304}
305
306static const struct dsa_switch_ops felix_switch_ops = {
307 .get_tag_protocol = felix_get_tag_protocol,
308 .setup = felix_setup,
309 .teardown = felix_teardown,
310 .set_ageing_time = felix_set_ageing_time,
311 .get_strings = felix_get_strings,
312 .get_ethtool_stats = felix_get_ethtool_stats,
313 .get_sset_count = felix_get_sset_count,
314 .get_ts_info = felix_get_ts_info,
315 .adjust_link = felix_adjust_link,
316 .port_enable = felix_port_enable,
317 .port_disable = felix_port_disable,
318 .port_fdb_dump = felix_fdb_dump,
319 .port_fdb_add = felix_fdb_add,
320 .port_fdb_del = felix_fdb_del,
321 .port_bridge_join = felix_bridge_join,
322 .port_bridge_leave = felix_bridge_leave,
323 .port_stp_state_set = felix_bridge_stp_state_set,
324 .port_vlan_prepare = felix_vlan_prepare,
325 .port_vlan_filtering = felix_vlan_filtering,
326 .port_vlan_add = felix_vlan_add,
327 .port_vlan_del = felix_vlan_del,
328};
329
330static struct felix_info *felix_instance_tbl[] = {
331 [FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959,
332};
333
334static int felix_pci_probe(struct pci_dev *pdev,
335 const struct pci_device_id *id)
336{
337 enum felix_instance instance = id->driver_data;
338 struct dsa_switch *ds;
339 struct ocelot *ocelot;
340 struct felix *felix;
341 int err;
342
343 err = pci_enable_device(pdev);
344 if (err) {
345 dev_err(&pdev->dev, "device enable failed\n");
346 goto err_pci_enable;
347 }
348
349 /* set up for high or low dma */
350 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
351 if (err) {
352 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
353 if (err) {
354 dev_err(&pdev->dev,
355 "DMA configuration failed: 0x%x\n", err);
356 goto err_dma;
357 }
358 }
359
360 felix = kzalloc(sizeof(struct felix), GFP_KERNEL);
361 if (!felix) {
362 err = -ENOMEM;
363 dev_err(&pdev->dev, "Failed to allocate driver memory\n");
364 goto err_alloc_felix;
365 }
366
367 pci_set_drvdata(pdev, felix);
368 ocelot = &felix->ocelot;
369 ocelot->dev = &pdev->dev;
370 felix->pdev = pdev;
371 felix->info = felix_instance_tbl[instance];
372
373 pci_set_master(pdev);
374
375 ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
376 if (!ds) {
377 err = -ENOMEM;
378 dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
379 goto err_alloc_ds;
380 }
381
382 ds->dev = &pdev->dev;
383 ds->num_ports = felix->info->num_ports;
384 ds->ops = &felix_switch_ops;
385 ds->priv = ocelot;
386 felix->ds = ds;
387
388 err = dsa_register_switch(ds);
389 if (err) {
390 dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
391 goto err_register_ds;
392 }
393
394 return 0;
395
396err_register_ds:
397 kfree(ds);
398err_alloc_ds:
399err_alloc_felix:
400 kfree(felix);
401err_dma:
402 pci_disable_device(pdev);
403err_pci_enable:
404 return err;
405}
406
407static void felix_pci_remove(struct pci_dev *pdev)
408{
409 struct felix *felix;
410
411 felix = pci_get_drvdata(pdev);
412
413 dsa_unregister_switch(felix->ds);
414
415 kfree(felix->ds);
416 kfree(felix);
417
418 pci_disable_device(pdev);
419}
420
421static struct pci_device_id felix_ids[] = {
422 {
423 /* NXP LS1028A */
424 PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),
425 .driver_data = FELIX_INSTANCE_VSC9959,
426 },
427 { 0, }
428};
429MODULE_DEVICE_TABLE(pci, felix_ids);
430
431static struct pci_driver felix_pci_driver = {
432 .name = KBUILD_MODNAME,
433 .id_table = felix_ids,
434 .probe = felix_pci_probe,
435 .remove = felix_pci_remove,
436};
437
438module_pci_driver(felix_pci_driver);
439
440MODULE_DESCRIPTION("Felix Switch driver");
441MODULE_LICENSE("GPL v2");