tty: n_gsm: avoid call of sleeping functions from atomic context
[platform/kernel/linux-rpi.git] / drivers / net / ethernet / mscc / ocelot_vsc7514.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/dsa/ocelot.h>
8 #include <linux/interrupt.h>
9 #include <linux/module.h>
10 #include <linux/of_net.h>
11 #include <linux/netdevice.h>
12 #include <linux/phylink.h>
13 #include <linux/of_mdio.h>
14 #include <linux/of_platform.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/skbuff.h>
17 #include <net/switchdev.h>
18
19 #include <soc/mscc/ocelot_vcap.h>
20 #include <soc/mscc/ocelot_hsio.h>
21 #include <soc/mscc/vsc7514_regs.h>
22 #include "ocelot_fdma.h"
23 #include "ocelot.h"
24
25 #define VSC7514_VCAP_POLICER_BASE                       128
26 #define VSC7514_VCAP_POLICER_MAX                        191
27
28 static const u32 *ocelot_regmap[TARGET_MAX] = {
29         [ANA] = vsc7514_ana_regmap,
30         [QS] = vsc7514_qs_regmap,
31         [QSYS] = vsc7514_qsys_regmap,
32         [REW] = vsc7514_rew_regmap,
33         [SYS] = vsc7514_sys_regmap,
34         [S0] = vsc7514_vcap_regmap,
35         [S1] = vsc7514_vcap_regmap,
36         [S2] = vsc7514_vcap_regmap,
37         [PTP] = vsc7514_ptp_regmap,
38         [DEV_GMII] = vsc7514_dev_gmii_regmap,
39 };
40
41 static const struct reg_field ocelot_regfields[REGFIELD_MAX] = {
42         [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11),
43         [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10),
44         [ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27),
45         [ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26),
46         [ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25),
47         [ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24),
48         [ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23),
49         [ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22),
50         [ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21),
51         [ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20),
52         [ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19),
53         [ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
54         [ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17),
55         [ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16),
56         [ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15),
57         [ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14),
58         [ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13),
59         [ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12),
60         [ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
61         [ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
62         [ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9),
63         [ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8),
64         [ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7),
65         [ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
66         [ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
67         [ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4),
68         [ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3),
69         [ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2),
70         [ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1),
71         [ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0),
72         [ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18),
73         [ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11),
74         [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9),
75         [QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20),
76         [QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19),
77         [QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7),
78         [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3),
79         [QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0),
80         [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2),
81         [SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1),
82         [SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0),
83         /* Replicated per number of ports (12), register size 4 per port */
84         [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4),
85         [QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4),
86         [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4),
87         [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4),
88         [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4),
89         [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4),
90         [SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4),
91         [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4),
92         [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4),
93         [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4),
94         [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4),
95         [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4),
96         [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4),
97 };
98
99 static const struct ocelot_stat_layout ocelot_stats_layout[] = {
100         { .name = "rx_octets", .offset = 0x00, },
101         { .name = "rx_unicast", .offset = 0x01, },
102         { .name = "rx_multicast", .offset = 0x02, },
103         { .name = "rx_broadcast", .offset = 0x03, },
104         { .name = "rx_shorts", .offset = 0x04, },
105         { .name = "rx_fragments", .offset = 0x05, },
106         { .name = "rx_jabbers", .offset = 0x06, },
107         { .name = "rx_crc_align_errs", .offset = 0x07, },
108         { .name = "rx_sym_errs", .offset = 0x08, },
109         { .name = "rx_frames_below_65_octets", .offset = 0x09, },
110         { .name = "rx_frames_65_to_127_octets", .offset = 0x0A, },
111         { .name = "rx_frames_128_to_255_octets", .offset = 0x0B, },
112         { .name = "rx_frames_256_to_511_octets", .offset = 0x0C, },
113         { .name = "rx_frames_512_to_1023_octets", .offset = 0x0D, },
114         { .name = "rx_frames_1024_to_1526_octets", .offset = 0x0E, },
115         { .name = "rx_frames_over_1526_octets", .offset = 0x0F, },
116         { .name = "rx_pause", .offset = 0x10, },
117         { .name = "rx_control", .offset = 0x11, },
118         { .name = "rx_longs", .offset = 0x12, },
119         { .name = "rx_classified_drops", .offset = 0x13, },
120         { .name = "rx_red_prio_0", .offset = 0x14, },
121         { .name = "rx_red_prio_1", .offset = 0x15, },
122         { .name = "rx_red_prio_2", .offset = 0x16, },
123         { .name = "rx_red_prio_3", .offset = 0x17, },
124         { .name = "rx_red_prio_4", .offset = 0x18, },
125         { .name = "rx_red_prio_5", .offset = 0x19, },
126         { .name = "rx_red_prio_6", .offset = 0x1A, },
127         { .name = "rx_red_prio_7", .offset = 0x1B, },
128         { .name = "rx_yellow_prio_0", .offset = 0x1C, },
129         { .name = "rx_yellow_prio_1", .offset = 0x1D, },
130         { .name = "rx_yellow_prio_2", .offset = 0x1E, },
131         { .name = "rx_yellow_prio_3", .offset = 0x1F, },
132         { .name = "rx_yellow_prio_4", .offset = 0x20, },
133         { .name = "rx_yellow_prio_5", .offset = 0x21, },
134         { .name = "rx_yellow_prio_6", .offset = 0x22, },
135         { .name = "rx_yellow_prio_7", .offset = 0x23, },
136         { .name = "rx_green_prio_0", .offset = 0x24, },
137         { .name = "rx_green_prio_1", .offset = 0x25, },
138         { .name = "rx_green_prio_2", .offset = 0x26, },
139         { .name = "rx_green_prio_3", .offset = 0x27, },
140         { .name = "rx_green_prio_4", .offset = 0x28, },
141         { .name = "rx_green_prio_5", .offset = 0x29, },
142         { .name = "rx_green_prio_6", .offset = 0x2A, },
143         { .name = "rx_green_prio_7", .offset = 0x2B, },
144         { .name = "tx_octets", .offset = 0x40, },
145         { .name = "tx_unicast", .offset = 0x41, },
146         { .name = "tx_multicast", .offset = 0x42, },
147         { .name = "tx_broadcast", .offset = 0x43, },
148         { .name = "tx_collision", .offset = 0x44, },
149         { .name = "tx_drops", .offset = 0x45, },
150         { .name = "tx_pause", .offset = 0x46, },
151         { .name = "tx_frames_below_65_octets", .offset = 0x47, },
152         { .name = "tx_frames_65_to_127_octets", .offset = 0x48, },
153         { .name = "tx_frames_128_255_octets", .offset = 0x49, },
154         { .name = "tx_frames_256_511_octets", .offset = 0x4A, },
155         { .name = "tx_frames_512_1023_octets", .offset = 0x4B, },
156         { .name = "tx_frames_1024_1526_octets", .offset = 0x4C, },
157         { .name = "tx_frames_over_1526_octets", .offset = 0x4D, },
158         { .name = "tx_yellow_prio_0", .offset = 0x4E, },
159         { .name = "tx_yellow_prio_1", .offset = 0x4F, },
160         { .name = "tx_yellow_prio_2", .offset = 0x50, },
161         { .name = "tx_yellow_prio_3", .offset = 0x51, },
162         { .name = "tx_yellow_prio_4", .offset = 0x52, },
163         { .name = "tx_yellow_prio_5", .offset = 0x53, },
164         { .name = "tx_yellow_prio_6", .offset = 0x54, },
165         { .name = "tx_yellow_prio_7", .offset = 0x55, },
166         { .name = "tx_green_prio_0", .offset = 0x56, },
167         { .name = "tx_green_prio_1", .offset = 0x57, },
168         { .name = "tx_green_prio_2", .offset = 0x58, },
169         { .name = "tx_green_prio_3", .offset = 0x59, },
170         { .name = "tx_green_prio_4", .offset = 0x5A, },
171         { .name = "tx_green_prio_5", .offset = 0x5B, },
172         { .name = "tx_green_prio_6", .offset = 0x5C, },
173         { .name = "tx_green_prio_7", .offset = 0x5D, },
174         { .name = "tx_aged", .offset = 0x5E, },
175         { .name = "drop_local", .offset = 0x80, },
176         { .name = "drop_tail", .offset = 0x81, },
177         { .name = "drop_yellow_prio_0", .offset = 0x82, },
178         { .name = "drop_yellow_prio_1", .offset = 0x83, },
179         { .name = "drop_yellow_prio_2", .offset = 0x84, },
180         { .name = "drop_yellow_prio_3", .offset = 0x85, },
181         { .name = "drop_yellow_prio_4", .offset = 0x86, },
182         { .name = "drop_yellow_prio_5", .offset = 0x87, },
183         { .name = "drop_yellow_prio_6", .offset = 0x88, },
184         { .name = "drop_yellow_prio_7", .offset = 0x89, },
185         { .name = "drop_green_prio_0", .offset = 0x8A, },
186         { .name = "drop_green_prio_1", .offset = 0x8B, },
187         { .name = "drop_green_prio_2", .offset = 0x8C, },
188         { .name = "drop_green_prio_3", .offset = 0x8D, },
189         { .name = "drop_green_prio_4", .offset = 0x8E, },
190         { .name = "drop_green_prio_5", .offset = 0x8F, },
191         { .name = "drop_green_prio_6", .offset = 0x90, },
192         { .name = "drop_green_prio_7", .offset = 0x91, },
193         OCELOT_STAT_END
194 };
195
196 static void ocelot_pll5_init(struct ocelot *ocelot)
197 {
198         /* Configure PLL5. This will need a proper CCF driver
199          * The values are coming from the VTSS API for Ocelot
200          */
201         regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
202                      HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
203                      HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
204         regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
205                      HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
206                      HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
207                      HSIO_PLL5G_CFG0_ENA_BIAS |
208                      HSIO_PLL5G_CFG0_ENA_VCO_BUF |
209                      HSIO_PLL5G_CFG0_ENA_CP1 |
210                      HSIO_PLL5G_CFG0_SELCPI(2) |
211                      HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) |
212                      HSIO_PLL5G_CFG0_SELBGV820(4) |
213                      HSIO_PLL5G_CFG0_DIV4 |
214                      HSIO_PLL5G_CFG0_ENA_CLKTREE |
215                      HSIO_PLL5G_CFG0_ENA_LANE);
216         regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
217                      HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
218                      HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
219                      HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
220                      HSIO_PLL5G_CFG2_ENA_AMPCTRL |
221                      HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
222                      HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
223 }
224
225 static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
226 {
227         int ret;
228
229         ocelot->map = ocelot_regmap;
230         ocelot->stats_layout = ocelot_stats_layout;
231         ocelot->num_mact_rows = 1024;
232         ocelot->ops = ops;
233
234         ret = ocelot_regfields_init(ocelot, ocelot_regfields);
235         if (ret)
236                 return ret;
237
238         ocelot_pll5_init(ocelot);
239
240         eth_random_addr(ocelot->base_mac);
241         ocelot->base_mac[5] &= 0xf0;
242
243         return 0;
244 }
245
246 static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
247 {
248         struct ocelot *ocelot = arg;
249         int grp = 0, err;
250
251         while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) {
252                 struct sk_buff *skb;
253
254                 err = ocelot_xtr_poll_frame(ocelot, grp, &skb);
255                 if (err)
256                         goto out;
257
258                 skb->dev->stats.rx_bytes += skb->len;
259                 skb->dev->stats.rx_packets++;
260
261                 if (!skb_defer_rx_timestamp(skb))
262                         netif_rx(skb);
263         }
264
265 out:
266         if (err < 0)
267                 ocelot_drain_cpu_queue(ocelot, 0);
268
269         return IRQ_HANDLED;
270 }
271
272 static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
273 {
274         struct ocelot *ocelot = arg;
275
276         ocelot_get_txtstamp(ocelot);
277
278         return IRQ_HANDLED;
279 }
280
281 static const struct of_device_id mscc_ocelot_match[] = {
282         { .compatible = "mscc,vsc7514-switch" },
283         { }
284 };
285 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
286
287 static int ocelot_reset(struct ocelot *ocelot)
288 {
289         int retries = 100;
290         u32 val;
291
292         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
293         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
294
295         do {
296                 msleep(1);
297                 regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
298                                   &val);
299         } while (val && --retries);
300
301         if (!retries)
302                 return -ETIMEDOUT;
303
304         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
305         regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
306
307         return 0;
308 }
309
310 /* Watermark encode
311  * Bit 8:   Unit; 0:1, 1:16
312  * Bit 7-0: Value to be multiplied with unit
313  */
314 static u16 ocelot_wm_enc(u16 value)
315 {
316         WARN_ON(value >= 16 * BIT(8));
317
318         if (value >= BIT(8))
319                 return BIT(8) | (value / 16);
320
321         return value;
322 }
323
324 static u16 ocelot_wm_dec(u16 wm)
325 {
326         if (wm & BIT(8))
327                 return (wm & GENMASK(7, 0)) * 16;
328
329         return wm;
330 }
331
332 static void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
333 {
334         *inuse = (val & GENMASK(23, 12)) >> 12;
335         *maxuse = val & GENMASK(11, 0);
336 }
337
338 static const struct ocelot_ops ocelot_ops = {
339         .reset                  = ocelot_reset,
340         .wm_enc                 = ocelot_wm_enc,
341         .wm_dec                 = ocelot_wm_dec,
342         .wm_stat                = ocelot_wm_stat,
343         .port_to_netdev         = ocelot_port_to_netdev,
344         .netdev_to_port         = ocelot_netdev_to_port,
345 };
346
347 static struct vcap_props vsc7514_vcap_props[] = {
348         [VCAP_ES0] = {
349                 .action_type_width = 0,
350                 .action_table = {
351                         [ES0_ACTION_TYPE_NORMAL] = {
352                                 .width = 73, /* HIT_STICKY not included */
353                                 .count = 1,
354                         },
355                 },
356                 .target = S0,
357                 .keys = vsc7514_vcap_es0_keys,
358                 .actions = vsc7514_vcap_es0_actions,
359         },
360         [VCAP_IS1] = {
361                 .action_type_width = 0,
362                 .action_table = {
363                         [IS1_ACTION_TYPE_NORMAL] = {
364                                 .width = 78, /* HIT_STICKY not included */
365                                 .count = 4,
366                         },
367                 },
368                 .target = S1,
369                 .keys = vsc7514_vcap_is1_keys,
370                 .actions = vsc7514_vcap_is1_actions,
371         },
372         [VCAP_IS2] = {
373                 .action_type_width = 1,
374                 .action_table = {
375                         [IS2_ACTION_TYPE_NORMAL] = {
376                                 .width = 49,
377                                 .count = 2
378                         },
379                         [IS2_ACTION_TYPE_SMAC_SIP] = {
380                                 .width = 6,
381                                 .count = 4
382                         },
383                 },
384                 .target = S2,
385                 .keys = vsc7514_vcap_is2_keys,
386                 .actions = vsc7514_vcap_is2_actions,
387         },
388 };
389
390 static struct ptp_clock_info ocelot_ptp_clock_info = {
391         .owner          = THIS_MODULE,
392         .name           = "ocelot ptp",
393         .max_adj        = 0x7fffffff,
394         .n_alarm        = 0,
395         .n_ext_ts       = 0,
396         .n_per_out      = OCELOT_PTP_PINS_NUM,
397         .n_pins         = OCELOT_PTP_PINS_NUM,
398         .pps            = 0,
399         .gettime64      = ocelot_ptp_gettime64,
400         .settime64      = ocelot_ptp_settime64,
401         .adjtime        = ocelot_ptp_adjtime,
402         .adjfine        = ocelot_ptp_adjfine,
403         .verify         = ocelot_ptp_verify,
404         .enable         = ocelot_ptp_enable,
405 };
406
407 static void mscc_ocelot_teardown_devlink_ports(struct ocelot *ocelot)
408 {
409         int port;
410
411         for (port = 0; port < ocelot->num_phys_ports; port++)
412                 ocelot_port_devlink_teardown(ocelot, port);
413 }
414
415 static void mscc_ocelot_release_ports(struct ocelot *ocelot)
416 {
417         int port;
418
419         for (port = 0; port < ocelot->num_phys_ports; port++) {
420                 struct ocelot_port *ocelot_port;
421
422                 ocelot_port = ocelot->ports[port];
423                 if (!ocelot_port)
424                         continue;
425
426                 ocelot_deinit_port(ocelot, port);
427                 ocelot_release_port(ocelot_port);
428         }
429 }
430
431 static int mscc_ocelot_init_ports(struct platform_device *pdev,
432                                   struct device_node *ports)
433 {
434         struct ocelot *ocelot = platform_get_drvdata(pdev);
435         u32 devlink_ports_registered = 0;
436         struct device_node *portnp;
437         int port, err;
438         u32 reg;
439
440         ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
441                                      sizeof(struct ocelot_port *), GFP_KERNEL);
442         if (!ocelot->ports)
443                 return -ENOMEM;
444
445         ocelot->devlink_ports = devm_kcalloc(ocelot->dev,
446                                              ocelot->num_phys_ports,
447                                              sizeof(*ocelot->devlink_ports),
448                                              GFP_KERNEL);
449         if (!ocelot->devlink_ports)
450                 return -ENOMEM;
451
452         for_each_available_child_of_node(ports, portnp) {
453                 struct ocelot_port_private *priv;
454                 struct ocelot_port *ocelot_port;
455                 struct devlink_port *dlp;
456                 struct regmap *target;
457                 struct resource *res;
458                 char res_name[8];
459
460                 if (of_property_read_u32(portnp, "reg", &reg))
461                         continue;
462
463                 port = reg;
464                 if (port < 0 || port >= ocelot->num_phys_ports) {
465                         dev_err(ocelot->dev,
466                                 "invalid port number: %d >= %d\n", port,
467                                 ocelot->num_phys_ports);
468                         continue;
469                 }
470
471                 snprintf(res_name, sizeof(res_name), "port%d", port);
472
473                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
474                                                    res_name);
475                 target = ocelot_regmap_init(ocelot, res);
476                 if (IS_ERR(target)) {
477                         err = PTR_ERR(target);
478                         of_node_put(portnp);
479                         goto out_teardown;
480                 }
481
482                 err = ocelot_port_devlink_init(ocelot, port,
483                                                DEVLINK_PORT_FLAVOUR_PHYSICAL);
484                 if (err) {
485                         of_node_put(portnp);
486                         goto out_teardown;
487                 }
488
489                 err = ocelot_probe_port(ocelot, port, target, portnp);
490                 if (err) {
491                         ocelot_port_devlink_teardown(ocelot, port);
492                         continue;
493                 }
494
495                 devlink_ports_registered |= BIT(port);
496
497                 ocelot_port = ocelot->ports[port];
498                 priv = container_of(ocelot_port, struct ocelot_port_private,
499                                     port);
500                 dlp = &ocelot->devlink_ports[port];
501                 devlink_port_type_eth_set(dlp, priv->dev);
502         }
503
504         /* Initialize unused devlink ports at the end */
505         for (port = 0; port < ocelot->num_phys_ports; port++) {
506                 if (devlink_ports_registered & BIT(port))
507                         continue;
508
509                 err = ocelot_port_devlink_init(ocelot, port,
510                                                DEVLINK_PORT_FLAVOUR_UNUSED);
511                 if (err)
512                         goto out_teardown;
513
514                 devlink_ports_registered |= BIT(port);
515         }
516
517         return 0;
518
519 out_teardown:
520         /* Unregister the network interfaces */
521         mscc_ocelot_release_ports(ocelot);
522         /* Tear down devlink ports for the registered network interfaces */
523         for (port = 0; port < ocelot->num_phys_ports; port++) {
524                 if (devlink_ports_registered & BIT(port))
525                         ocelot_port_devlink_teardown(ocelot, port);
526         }
527         return err;
528 }
529
530 static int mscc_ocelot_probe(struct platform_device *pdev)
531 {
532         struct device_node *np = pdev->dev.of_node;
533         int err, irq_xtr, irq_ptp_rdy;
534         struct device_node *ports;
535         struct devlink *devlink;
536         struct ocelot *ocelot;
537         struct regmap *hsio;
538         unsigned int i;
539
540         struct {
541                 enum ocelot_target id;
542                 char *name;
543                 u8 optional:1;
544         } io_target[] = {
545                 { SYS, "sys" },
546                 { REW, "rew" },
547                 { QSYS, "qsys" },
548                 { ANA, "ana" },
549                 { QS, "qs" },
550                 { S0, "s0" },
551                 { S1, "s1" },
552                 { S2, "s2" },
553                 { PTP, "ptp", 1 },
554                 { FDMA, "fdma", 1 },
555         };
556
557         if (!np && !pdev->dev.platform_data)
558                 return -ENODEV;
559
560         devlink =
561                 devlink_alloc(&ocelot_devlink_ops, sizeof(*ocelot), &pdev->dev);
562         if (!devlink)
563                 return -ENOMEM;
564
565         ocelot = devlink_priv(devlink);
566         ocelot->devlink = priv_to_devlink(ocelot);
567         platform_set_drvdata(pdev, ocelot);
568         ocelot->dev = &pdev->dev;
569
570         for (i = 0; i < ARRAY_SIZE(io_target); i++) {
571                 struct regmap *target;
572                 struct resource *res;
573
574                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
575                                                    io_target[i].name);
576
577                 target = ocelot_regmap_init(ocelot, res);
578                 if (IS_ERR(target)) {
579                         if (io_target[i].optional) {
580                                 ocelot->targets[io_target[i].id] = NULL;
581                                 continue;
582                         }
583                         err = PTR_ERR(target);
584                         goto out_free_devlink;
585                 }
586
587                 ocelot->targets[io_target[i].id] = target;
588         }
589
590         if (ocelot->targets[FDMA])
591                 ocelot_fdma_init(pdev, ocelot);
592
593         hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
594         if (IS_ERR(hsio)) {
595                 dev_err(&pdev->dev, "missing hsio syscon\n");
596                 err = PTR_ERR(hsio);
597                 goto out_free_devlink;
598         }
599
600         ocelot->targets[HSIO] = hsio;
601
602         err = ocelot_chip_init(ocelot, &ocelot_ops);
603         if (err)
604                 goto out_free_devlink;
605
606         irq_xtr = platform_get_irq_byname(pdev, "xtr");
607         if (irq_xtr < 0) {
608                 err = irq_xtr;
609                 goto out_free_devlink;
610         }
611
612         err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
613                                         ocelot_xtr_irq_handler, IRQF_ONESHOT,
614                                         "frame extraction", ocelot);
615         if (err)
616                 goto out_free_devlink;
617
618         irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
619         if (irq_ptp_rdy > 0 && ocelot->targets[PTP]) {
620                 err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
621                                                 ocelot_ptp_rdy_irq_handler,
622                                                 IRQF_ONESHOT, "ptp ready",
623                                                 ocelot);
624                 if (err)
625                         goto out_free_devlink;
626
627                 /* Both the PTP interrupt and the PTP bank are available */
628                 ocelot->ptp = 1;
629         }
630
631         ports = of_get_child_by_name(np, "ethernet-ports");
632         if (!ports) {
633                 dev_err(ocelot->dev, "no ethernet-ports child node found\n");
634                 err = -ENODEV;
635                 goto out_free_devlink;
636         }
637
638         ocelot->num_phys_ports = of_get_child_count(ports);
639         ocelot->num_flooding_pgids = 1;
640
641         ocelot->vcap = vsc7514_vcap_props;
642
643         ocelot->vcap_pol.base = VSC7514_VCAP_POLICER_BASE;
644         ocelot->vcap_pol.max = VSC7514_VCAP_POLICER_MAX;
645
646         ocelot->npi = -1;
647
648         err = ocelot_init(ocelot);
649         if (err)
650                 goto out_put_ports;
651
652         err = mscc_ocelot_init_ports(pdev, ports);
653         if (err)
654                 goto out_ocelot_devlink_unregister;
655
656         if (ocelot->fdma)
657                 ocelot_fdma_start(ocelot);
658
659         err = ocelot_devlink_sb_register(ocelot);
660         if (err)
661                 goto out_ocelot_release_ports;
662
663         if (ocelot->ptp) {
664                 err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
665                 if (err) {
666                         dev_err(ocelot->dev,
667                                 "Timestamp initialization failed\n");
668                         ocelot->ptp = 0;
669                 }
670         }
671
672         register_netdevice_notifier(&ocelot_netdevice_nb);
673         register_switchdev_notifier(&ocelot_switchdev_nb);
674         register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
675
676         of_node_put(ports);
677         devlink_register(devlink);
678
679         dev_info(&pdev->dev, "Ocelot switch probed\n");
680
681         return 0;
682
683 out_ocelot_release_ports:
684         mscc_ocelot_release_ports(ocelot);
685         mscc_ocelot_teardown_devlink_ports(ocelot);
686 out_ocelot_devlink_unregister:
687         ocelot_deinit(ocelot);
688 out_put_ports:
689         of_node_put(ports);
690 out_free_devlink:
691         devlink_free(devlink);
692         return err;
693 }
694
695 static int mscc_ocelot_remove(struct platform_device *pdev)
696 {
697         struct ocelot *ocelot = platform_get_drvdata(pdev);
698
699         if (ocelot->fdma)
700                 ocelot_fdma_deinit(ocelot);
701         devlink_unregister(ocelot->devlink);
702         ocelot_deinit_timestamp(ocelot);
703         ocelot_devlink_sb_unregister(ocelot);
704         mscc_ocelot_release_ports(ocelot);
705         mscc_ocelot_teardown_devlink_ports(ocelot);
706         ocelot_deinit(ocelot);
707         unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
708         unregister_switchdev_notifier(&ocelot_switchdev_nb);
709         unregister_netdevice_notifier(&ocelot_netdevice_nb);
710         devlink_free(ocelot->devlink);
711
712         return 0;
713 }
714
715 static struct platform_driver mscc_ocelot_driver = {
716         .probe = mscc_ocelot_probe,
717         .remove = mscc_ocelot_remove,
718         .driver = {
719                 .name = "ocelot-switch",
720                 .of_match_table = mscc_ocelot_match,
721         },
722 };
723
724 module_platform_driver(mscc_ocelot_driver);
725
726 MODULE_DESCRIPTION("Microsemi Ocelot switch driver");
727 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
728 MODULE_LICENSE("Dual MIT/GPL");