]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/ethernet/mscc/ocelot_board.c
Merge branch 'sched/urgent' into sched/core, to pick up fixes
[linux.git] / drivers / net / ethernet / mscc / ocelot_board.c
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * Microsemi Ocelot Switch driver
4  *
5  * Copyright (c) 2017 Microsemi Corporation
6  */
7 #include <linux/interrupt.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/of_mdio.h>
11 #include <linux/of_platform.h>
12 #include <linux/skbuff.h>
13
14 #include "ocelot.h"
15
16 static int ocelot_parse_ifh(u32 *ifh, struct frame_info *info)
17 {
18         int i;
19         u8 llen, wlen;
20
21         /* The IFH is in network order, switch to CPU order */
22         for (i = 0; i < IFH_LEN; i++)
23                 ifh[i] = ntohl((__force __be32)ifh[i]);
24
25         wlen = (ifh[1] >> 7) & 0xff;
26         llen = (ifh[1] >> 15) & 0x3f;
27         info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
28
29         info->port = (ifh[2] & GENMASK(14, 11)) >> 11;
30
31         info->cpuq = (ifh[3] & GENMASK(27, 20)) >> 20;
32         info->tag_type = (ifh[3] & BIT(16)) >> 16;
33         info->vid = ifh[3] & GENMASK(11, 0);
34
35         return 0;
36 }
37
38 static int ocelot_rx_frame_word(struct ocelot *ocelot, u8 grp, bool ifh,
39                                 u32 *rval)
40 {
41         u32 val;
42         u32 bytes_valid;
43
44         val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
45         if (val == XTR_NOT_READY) {
46                 if (ifh)
47                         return -EIO;
48
49                 do {
50                         val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
51                 } while (val == XTR_NOT_READY);
52         }
53
54         switch (val) {
55         case XTR_ABORT:
56                 return -EIO;
57         case XTR_EOF_0:
58         case XTR_EOF_1:
59         case XTR_EOF_2:
60         case XTR_EOF_3:
61         case XTR_PRUNED:
62                 bytes_valid = XTR_VALID_BYTES(val);
63                 val = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
64                 if (val == XTR_ESCAPE)
65                         *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
66                 else
67                         *rval = val;
68
69                 return bytes_valid;
70         case XTR_ESCAPE:
71                 *rval = ocelot_read_rix(ocelot, QS_XTR_RD, grp);
72
73                 return 4;
74         default:
75                 *rval = val;
76
77                 return 4;
78         }
79 }
80
81 static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
82 {
83         struct ocelot *ocelot = arg;
84         int i = 0, grp = 0;
85         int err = 0;
86
87         if (!(ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)))
88                 return IRQ_NONE;
89
90         do {
91                 struct sk_buff *skb;
92                 struct net_device *dev;
93                 u32 *buf;
94                 int sz, len, buf_len;
95                 u32 ifh[4];
96                 u32 val;
97                 struct frame_info info;
98
99                 for (i = 0; i < IFH_LEN; i++) {
100                         err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
101                         if (err != 4)
102                                 break;
103                 }
104
105                 if (err != 4)
106                         break;
107
108                 ocelot_parse_ifh(ifh, &info);
109
110                 dev = ocelot->ports[info.port]->dev;
111
112                 skb = netdev_alloc_skb(dev, info.len);
113
114                 if (unlikely(!skb)) {
115                         netdev_err(dev, "Unable to allocate sk_buff\n");
116                         err = -ENOMEM;
117                         break;
118                 }
119                 buf_len = info.len - ETH_FCS_LEN;
120                 buf = (u32 *)skb_put(skb, buf_len);
121
122                 len = 0;
123                 do {
124                         sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
125                         *buf++ = val;
126                         len += sz;
127                 } while (len < buf_len);
128
129                 /* Read the FCS and discard it */
130                 sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
131                 /* Update the statistics if part of the FCS was read before */
132                 len -= ETH_FCS_LEN - sz;
133
134                 if (sz < 0) {
135                         err = sz;
136                         break;
137                 }
138
139                 /* Everything we see on an interface that is in the HW bridge
140                  * has already been forwarded.
141                  */
142                 if (ocelot->bridge_mask & BIT(info.port))
143                         skb->offload_fwd_mark = 1;
144
145                 skb->protocol = eth_type_trans(skb, dev);
146                 netif_rx(skb);
147                 dev->stats.rx_bytes += len;
148                 dev->stats.rx_packets++;
149         } while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp));
150
151         if (err)
152                 while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp))
153                         ocelot_read_rix(ocelot, QS_XTR_RD, grp);
154
155         return IRQ_HANDLED;
156 }
157
158 static const struct of_device_id mscc_ocelot_match[] = {
159         { .compatible = "mscc,vsc7514-switch" },
160         { }
161 };
162 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
163
164 static int mscc_ocelot_probe(struct platform_device *pdev)
165 {
166         int err, irq;
167         unsigned int i;
168         struct device_node *np = pdev->dev.of_node;
169         struct device_node *ports, *portnp;
170         struct ocelot *ocelot;
171         u32 val;
172
173         struct {
174                 enum ocelot_target id;
175                 char *name;
176         } res[] = {
177                 { SYS, "sys" },
178                 { REW, "rew" },
179                 { QSYS, "qsys" },
180                 { ANA, "ana" },
181                 { QS, "qs" },
182                 { HSIO, "hsio" },
183         };
184
185         if (!np && !pdev->dev.platform_data)
186                 return -ENODEV;
187
188         ocelot = devm_kzalloc(&pdev->dev, sizeof(*ocelot), GFP_KERNEL);
189         if (!ocelot)
190                 return -ENOMEM;
191
192         platform_set_drvdata(pdev, ocelot);
193         ocelot->dev = &pdev->dev;
194
195         for (i = 0; i < ARRAY_SIZE(res); i++) {
196                 struct regmap *target;
197
198                 target = ocelot_io_platform_init(ocelot, pdev, res[i].name);
199                 if (IS_ERR(target))
200                         return PTR_ERR(target);
201
202                 ocelot->targets[res[i].id] = target;
203         }
204
205         err = ocelot_chip_init(ocelot);
206         if (err)
207                 return err;
208
209         irq = platform_get_irq_byname(pdev, "xtr");
210         if (irq < 0)
211                 return -ENODEV;
212
213         err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
214                                         ocelot_xtr_irq_handler, IRQF_ONESHOT,
215                                         "frame extraction", ocelot);
216         if (err)
217                 return err;
218
219         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
220         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
221
222         do {
223                 msleep(1);
224                 regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
225                                   &val);
226         } while (val);
227
228         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
229         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
230
231         ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */
232
233         ports = of_get_child_by_name(np, "ethernet-ports");
234         if (!ports) {
235                 dev_err(&pdev->dev, "no ethernet-ports child node found\n");
236                 return -ENODEV;
237         }
238
239         ocelot->num_phys_ports = of_get_child_count(ports);
240
241         ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
242                                      sizeof(struct ocelot_port *), GFP_KERNEL);
243
244         INIT_LIST_HEAD(&ocelot->multicast);
245         ocelot_init(ocelot);
246
247         ocelot_rmw(ocelot, HSIO_HW_CFG_DEV1G_4_MODE |
248                      HSIO_HW_CFG_DEV1G_6_MODE |
249                      HSIO_HW_CFG_DEV1G_9_MODE,
250                      HSIO_HW_CFG_DEV1G_4_MODE |
251                      HSIO_HW_CFG_DEV1G_6_MODE |
252                      HSIO_HW_CFG_DEV1G_9_MODE,
253                      HSIO_HW_CFG);
254
255         for_each_available_child_of_node(ports, portnp) {
256                 struct device_node *phy_node;
257                 struct phy_device *phy;
258                 struct resource *res;
259                 void __iomem *regs;
260                 char res_name[8];
261                 u32 port;
262
263                 if (of_property_read_u32(portnp, "reg", &port))
264                         continue;
265
266                 snprintf(res_name, sizeof(res_name), "port%d", port);
267
268                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
269                                                    res_name);
270                 regs = devm_ioremap_resource(&pdev->dev, res);
271                 if (IS_ERR(regs))
272                         continue;
273
274                 phy_node = of_parse_phandle(portnp, "phy-handle", 0);
275                 if (!phy_node)
276                         continue;
277
278                 phy = of_phy_find_device(phy_node);
279                 if (!phy)
280                         continue;
281
282                 err = ocelot_probe_port(ocelot, port, regs, phy);
283                 if (err) {
284                         dev_err(&pdev->dev, "failed to probe ports\n");
285                         goto err_probe_ports;
286                 }
287         }
288
289         register_netdevice_notifier(&ocelot_netdevice_nb);
290
291         dev_info(&pdev->dev, "Ocelot switch probed\n");
292
293         return 0;
294
295 err_probe_ports:
296         return err;
297 }
298
299 static int mscc_ocelot_remove(struct platform_device *pdev)
300 {
301         struct ocelot *ocelot = platform_get_drvdata(pdev);
302
303         ocelot_deinit(ocelot);
304         unregister_netdevice_notifier(&ocelot_netdevice_nb);
305
306         return 0;
307 }
308
309 static struct platform_driver mscc_ocelot_driver = {
310         .probe = mscc_ocelot_probe,
311         .remove = mscc_ocelot_remove,
312         .driver = {
313                 .name = "ocelot-switch",
314                 .of_match_table = mscc_ocelot_match,
315         },
316 };
317
318 module_platform_driver(mscc_ocelot_driver);
319
320 MODULE_DESCRIPTION("Microsemi Ocelot switch driver");
321 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
322 MODULE_LICENSE("Dual MIT/GPL");