1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
2 | /* Distributed Switch Architecture VSC9953 driver |
3 | * Copyright (C) 2020, Maxim Kochetkov <fido_max@inbox.ru> |
4 | */ |
5 | #include <linux/platform_device.h> |
6 | #include <linux/types.h> |
7 | #include <soc/mscc/ocelot_vcap.h> |
8 | #include <soc/mscc/ocelot_sys.h> |
9 | #include <soc/mscc/ocelot.h> |
10 | #include <linux/mdio/mdio-mscc-miim.h> |
11 | #include <linux/mod_devicetable.h> |
12 | #include <linux/of_mdio.h> |
13 | #include <linux/pcs-lynx.h> |
14 | #include <linux/dsa/ocelot.h> |
15 | #include <linux/iopoll.h> |
16 | #include "felix.h" |
17 | |
18 | #define VSC9953_NUM_PORTS 10 |
19 | |
20 | #define VSC9953_VCAP_POLICER_BASE 11 |
21 | #define VSC9953_VCAP_POLICER_MAX 31 |
22 | #define VSC9953_VCAP_POLICER_BASE2 120 |
23 | #define VSC9953_VCAP_POLICER_MAX2 161 |
24 | |
25 | #define VSC9953_PORT_MODE_SERDES (OCELOT_PORT_MODE_1000BASEX | \ |
26 | OCELOT_PORT_MODE_SGMII | \ |
27 | OCELOT_PORT_MODE_QSGMII) |
28 | |
29 | static const u32 vsc9953_port_modes[VSC9953_NUM_PORTS] = { |
30 | VSC9953_PORT_MODE_SERDES, |
31 | VSC9953_PORT_MODE_SERDES, |
32 | VSC9953_PORT_MODE_SERDES, |
33 | VSC9953_PORT_MODE_SERDES, |
34 | VSC9953_PORT_MODE_SERDES, |
35 | VSC9953_PORT_MODE_SERDES, |
36 | VSC9953_PORT_MODE_SERDES, |
37 | VSC9953_PORT_MODE_SERDES, |
38 | OCELOT_PORT_MODE_INTERNAL, |
39 | OCELOT_PORT_MODE_INTERNAL, |
40 | }; |
41 | |
42 | static const u32 vsc9953_ana_regmap[] = { |
43 | REG(ANA_ADVLEARN, 0x00b500), |
44 | REG(ANA_VLANMASK, 0x00b504), |
45 | REG_RESERVED(ANA_PORT_B_DOMAIN), |
46 | REG(ANA_ANAGEFIL, 0x00b50c), |
47 | REG(ANA_ANEVENTS, 0x00b510), |
48 | REG(ANA_STORMLIMIT_BURST, 0x00b514), |
49 | REG(ANA_STORMLIMIT_CFG, 0x00b518), |
50 | REG(ANA_ISOLATED_PORTS, 0x00b528), |
51 | REG(ANA_COMMUNITY_PORTS, 0x00b52c), |
52 | REG(ANA_AUTOAGE, 0x00b530), |
53 | REG(ANA_MACTOPTIONS, 0x00b534), |
54 | REG(ANA_LEARNDISC, 0x00b538), |
55 | REG(ANA_AGENCTRL, 0x00b53c), |
56 | REG(ANA_MIRRORPORTS, 0x00b540), |
57 | REG(ANA_EMIRRORPORTS, 0x00b544), |
58 | REG(ANA_FLOODING, 0x00b548), |
59 | REG(ANA_FLOODING_IPMC, 0x00b54c), |
60 | REG(ANA_SFLOW_CFG, 0x00b550), |
61 | REG(ANA_PORT_MODE, 0x00b57c), |
62 | REG_RESERVED(ANA_CUT_THRU_CFG), |
63 | REG(ANA_PGID_PGID, 0x00b600), |
64 | REG(ANA_TABLES_ANMOVED, 0x00b4ac), |
65 | REG(ANA_TABLES_MACHDATA, 0x00b4b0), |
66 | REG(ANA_TABLES_MACLDATA, 0x00b4b4), |
67 | REG_RESERVED(ANA_TABLES_STREAMDATA), |
68 | REG(ANA_TABLES_MACACCESS, 0x00b4b8), |
69 | REG(ANA_TABLES_MACTINDX, 0x00b4bc), |
70 | REG(ANA_TABLES_VLANACCESS, 0x00b4c0), |
71 | REG(ANA_TABLES_VLANTIDX, 0x00b4c4), |
72 | REG_RESERVED(ANA_TABLES_ISDXACCESS), |
73 | REG_RESERVED(ANA_TABLES_ISDXTIDX), |
74 | REG(ANA_TABLES_ENTRYLIM, 0x00b480), |
75 | REG_RESERVED(ANA_TABLES_PTP_ID_HIGH), |
76 | REG_RESERVED(ANA_TABLES_PTP_ID_LOW), |
77 | REG_RESERVED(ANA_TABLES_STREAMACCESS), |
78 | REG_RESERVED(ANA_TABLES_STREAMTIDX), |
79 | REG_RESERVED(ANA_TABLES_SEQ_HISTORY), |
80 | REG_RESERVED(ANA_TABLES_SEQ_MASK), |
81 | REG_RESERVED(ANA_TABLES_SFID_MASK), |
82 | REG_RESERVED(ANA_TABLES_SFIDACCESS), |
83 | REG_RESERVED(ANA_TABLES_SFIDTIDX), |
84 | REG_RESERVED(ANA_MSTI_STATE), |
85 | REG_RESERVED(ANA_OAM_UPM_LM_CNT), |
86 | REG_RESERVED(ANA_SG_ACCESS_CTRL), |
87 | REG_RESERVED(ANA_SG_CONFIG_REG_1), |
88 | REG_RESERVED(ANA_SG_CONFIG_REG_2), |
89 | REG_RESERVED(ANA_SG_CONFIG_REG_3), |
90 | REG_RESERVED(ANA_SG_CONFIG_REG_4), |
91 | REG_RESERVED(ANA_SG_CONFIG_REG_5), |
92 | REG_RESERVED(ANA_SG_GCL_GS_CONFIG), |
93 | REG_RESERVED(ANA_SG_GCL_TI_CONFIG), |
94 | REG_RESERVED(ANA_SG_STATUS_REG_1), |
95 | REG_RESERVED(ANA_SG_STATUS_REG_2), |
96 | REG_RESERVED(ANA_SG_STATUS_REG_3), |
97 | REG(ANA_PORT_VLAN_CFG, 0x000000), |
98 | REG(ANA_PORT_DROP_CFG, 0x000004), |
99 | REG(ANA_PORT_QOS_CFG, 0x000008), |
100 | REG(ANA_PORT_VCAP_CFG, 0x00000c), |
101 | REG(ANA_PORT_VCAP_S1_KEY_CFG, 0x000010), |
102 | REG(ANA_PORT_VCAP_S2_CFG, 0x00001c), |
103 | REG(ANA_PORT_PCP_DEI_MAP, 0x000020), |
104 | REG(ANA_PORT_CPU_FWD_CFG, 0x000060), |
105 | REG(ANA_PORT_CPU_FWD_BPDU_CFG, 0x000064), |
106 | REG(ANA_PORT_CPU_FWD_GARP_CFG, 0x000068), |
107 | REG(ANA_PORT_CPU_FWD_CCM_CFG, 0x00006c), |
108 | REG(ANA_PORT_PORT_CFG, 0x000070), |
109 | REG(ANA_PORT_POL_CFG, 0x000074), |
110 | REG_RESERVED(ANA_PORT_PTP_CFG), |
111 | REG_RESERVED(ANA_PORT_PTP_DLY1_CFG), |
112 | REG_RESERVED(ANA_PORT_PTP_DLY2_CFG), |
113 | REG_RESERVED(ANA_PORT_SFID_CFG), |
114 | REG(ANA_PFC_PFC_CFG, 0x00c000), |
115 | REG_RESERVED(ANA_PFC_PFC_TIMER), |
116 | REG_RESERVED(ANA_IPT_OAM_MEP_CFG), |
117 | REG_RESERVED(ANA_IPT_IPT), |
118 | REG_RESERVED(ANA_PPT_PPT), |
119 | REG_RESERVED(ANA_FID_MAP_FID_MAP), |
120 | REG(ANA_AGGR_CFG, 0x00c600), |
121 | REG(ANA_CPUQ_CFG, 0x00c604), |
122 | REG_RESERVED(ANA_CPUQ_CFG2), |
123 | REG(ANA_CPUQ_8021_CFG, 0x00c60c), |
124 | REG(ANA_DSCP_CFG, 0x00c64c), |
125 | REG(ANA_DSCP_REWR_CFG, 0x00c74c), |
126 | REG(ANA_VCAP_RNG_TYPE_CFG, 0x00c78c), |
127 | REG(ANA_VCAP_RNG_VAL_CFG, 0x00c7ac), |
128 | REG_RESERVED(ANA_VRAP_CFG), |
129 | REG_RESERVED(ANA_VRAP_HDR_DATA), |
130 | REG_RESERVED(ANA_VRAP_HDR_MASK), |
131 | REG(ANA_DISCARD_CFG, 0x00c7d8), |
132 | REG(ANA_FID_CFG, 0x00c7dc), |
133 | REG(ANA_POL_PIR_CFG, 0x00a000), |
134 | REG(ANA_POL_CIR_CFG, 0x00a004), |
135 | REG(ANA_POL_MODE_CFG, 0x00a008), |
136 | REG(ANA_POL_PIR_STATE, 0x00a00c), |
137 | REG(ANA_POL_CIR_STATE, 0x00a010), |
138 | REG_RESERVED(ANA_POL_STATE), |
139 | REG(ANA_POL_FLOWC, 0x00c280), |
140 | REG(ANA_POL_HYST, 0x00c2ec), |
141 | REG_RESERVED(ANA_POL_MISC_CFG), |
142 | }; |
143 | |
144 | static const u32 vsc9953_qs_regmap[] = { |
145 | REG(QS_XTR_GRP_CFG, 0x000000), |
146 | REG(QS_XTR_RD, 0x000008), |
147 | REG(QS_XTR_FRM_PRUNING, 0x000010), |
148 | REG(QS_XTR_FLUSH, 0x000018), |
149 | REG(QS_XTR_DATA_PRESENT, 0x00001c), |
150 | REG(QS_XTR_CFG, 0x000020), |
151 | REG(QS_INJ_GRP_CFG, 0x000024), |
152 | REG(QS_INJ_WR, 0x00002c), |
153 | REG(QS_INJ_CTRL, 0x000034), |
154 | REG(QS_INJ_STATUS, 0x00003c), |
155 | REG(QS_INJ_ERR, 0x000040), |
156 | REG_RESERVED(QS_INH_DBG), |
157 | }; |
158 | |
159 | static const u32 vsc9953_vcap_regmap[] = { |
160 | /* VCAP_CORE_CFG */ |
161 | REG(VCAP_CORE_UPDATE_CTRL, 0x000000), |
162 | REG(VCAP_CORE_MV_CFG, 0x000004), |
163 | /* VCAP_CORE_CACHE */ |
164 | REG(VCAP_CACHE_ENTRY_DAT, 0x000008), |
165 | REG(VCAP_CACHE_MASK_DAT, 0x000108), |
166 | REG(VCAP_CACHE_ACTION_DAT, 0x000208), |
167 | REG(VCAP_CACHE_CNT_DAT, 0x000308), |
168 | REG(VCAP_CACHE_TG_DAT, 0x000388), |
169 | /* VCAP_CONST */ |
170 | REG(VCAP_CONST_VCAP_VER, 0x000398), |
171 | REG(VCAP_CONST_ENTRY_WIDTH, 0x00039c), |
172 | REG(VCAP_CONST_ENTRY_CNT, 0x0003a0), |
173 | REG(VCAP_CONST_ENTRY_SWCNT, 0x0003a4), |
174 | REG(VCAP_CONST_ENTRY_TG_WIDTH, 0x0003a8), |
175 | REG(VCAP_CONST_ACTION_DEF_CNT, 0x0003ac), |
176 | REG(VCAP_CONST_ACTION_WIDTH, 0x0003b0), |
177 | REG(VCAP_CONST_CNT_WIDTH, 0x0003b4), |
178 | REG_RESERVED(VCAP_CONST_CORE_CNT), |
179 | REG_RESERVED(VCAP_CONST_IF_CNT), |
180 | }; |
181 | |
182 | static const u32 vsc9953_qsys_regmap[] = { |
183 | REG(QSYS_PORT_MODE, 0x003600), |
184 | REG(QSYS_SWITCH_PORT_MODE, 0x003630), |
185 | REG(QSYS_STAT_CNT_CFG, 0x00365c), |
186 | REG(QSYS_EEE_CFG, 0x003660), |
187 | REG(QSYS_EEE_THRES, 0x003688), |
188 | REG(QSYS_IGR_NO_SHARING, 0x00368c), |
189 | REG(QSYS_EGR_NO_SHARING, 0x003690), |
190 | REG(QSYS_SW_STATUS, 0x003694), |
191 | REG(QSYS_EXT_CPU_CFG, 0x0036c0), |
192 | REG_RESERVED(QSYS_PAD_CFG), |
193 | REG(QSYS_CPU_GROUP_MAP, 0x0036c8), |
194 | REG_RESERVED(QSYS_QMAP), |
195 | REG_RESERVED(QSYS_ISDX_SGRP), |
196 | REG_RESERVED(QSYS_TIMED_FRAME_ENTRY), |
197 | REG_RESERVED(QSYS_TFRM_MISC), |
198 | REG_RESERVED(QSYS_TFRM_PORT_DLY), |
199 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_1), |
200 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_2), |
201 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_3), |
202 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_4), |
203 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_5), |
204 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_6), |
205 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_7), |
206 | REG_RESERVED(QSYS_TFRM_TIMER_CFG_8), |
207 | REG(QSYS_RED_PROFILE, 0x003724), |
208 | REG(QSYS_RES_QOS_MODE, 0x003764), |
209 | REG(QSYS_RES_CFG, 0x004000), |
210 | REG(QSYS_RES_STAT, 0x004004), |
211 | REG(QSYS_EGR_DROP_MODE, 0x003768), |
212 | REG(QSYS_EQ_CTRL, 0x00376c), |
213 | REG_RESERVED(QSYS_EVENTS_CORE), |
214 | REG_RESERVED(QSYS_QMAXSDU_CFG_0), |
215 | REG_RESERVED(QSYS_QMAXSDU_CFG_1), |
216 | REG_RESERVED(QSYS_QMAXSDU_CFG_2), |
217 | REG_RESERVED(QSYS_QMAXSDU_CFG_3), |
218 | REG_RESERVED(QSYS_QMAXSDU_CFG_4), |
219 | REG_RESERVED(QSYS_QMAXSDU_CFG_5), |
220 | REG_RESERVED(QSYS_QMAXSDU_CFG_6), |
221 | REG_RESERVED(QSYS_QMAXSDU_CFG_7), |
222 | REG_RESERVED(QSYS_PREEMPTION_CFG), |
223 | REG(QSYS_CIR_CFG, 0x000000), |
224 | REG_RESERVED(QSYS_EIR_CFG), |
225 | REG(QSYS_SE_CFG, 0x000008), |
226 | REG(QSYS_SE_DWRR_CFG, 0x00000c), |
227 | REG_RESERVED(QSYS_SE_CONNECT), |
228 | REG_RESERVED(QSYS_SE_DLB_SENSE), |
229 | REG(QSYS_CIR_STATE, 0x000044), |
230 | REG_RESERVED(QSYS_EIR_STATE), |
231 | REG_RESERVED(QSYS_SE_STATE), |
232 | REG(QSYS_HSCH_MISC_CFG, 0x003774), |
233 | REG_RESERVED(QSYS_TAG_CONFIG), |
234 | REG_RESERVED(QSYS_TAS_PARAM_CFG_CTRL), |
235 | REG_RESERVED(QSYS_PORT_MAX_SDU), |
236 | REG_RESERVED(QSYS_PARAM_CFG_REG_1), |
237 | REG_RESERVED(QSYS_PARAM_CFG_REG_2), |
238 | REG_RESERVED(QSYS_PARAM_CFG_REG_3), |
239 | REG_RESERVED(QSYS_PARAM_CFG_REG_4), |
240 | REG_RESERVED(QSYS_PARAM_CFG_REG_5), |
241 | REG_RESERVED(QSYS_GCL_CFG_REG_1), |
242 | REG_RESERVED(QSYS_GCL_CFG_REG_2), |
243 | REG_RESERVED(QSYS_PARAM_STATUS_REG_1), |
244 | REG_RESERVED(QSYS_PARAM_STATUS_REG_2), |
245 | REG_RESERVED(QSYS_PARAM_STATUS_REG_3), |
246 | REG_RESERVED(QSYS_PARAM_STATUS_REG_4), |
247 | REG_RESERVED(QSYS_PARAM_STATUS_REG_5), |
248 | REG_RESERVED(QSYS_PARAM_STATUS_REG_6), |
249 | REG_RESERVED(QSYS_PARAM_STATUS_REG_7), |
250 | REG_RESERVED(QSYS_PARAM_STATUS_REG_8), |
251 | REG_RESERVED(QSYS_PARAM_STATUS_REG_9), |
252 | REG_RESERVED(QSYS_GCL_STATUS_REG_1), |
253 | REG_RESERVED(QSYS_GCL_STATUS_REG_2), |
254 | }; |
255 | |
256 | static const u32 vsc9953_rew_regmap[] = { |
257 | REG(REW_PORT_VLAN_CFG, 0x000000), |
258 | REG(REW_TAG_CFG, 0x000004), |
259 | REG(REW_PORT_CFG, 0x000008), |
260 | REG(REW_DSCP_CFG, 0x00000c), |
261 | REG(REW_PCP_DEI_QOS_MAP_CFG, 0x000010), |
262 | REG_RESERVED(REW_PTP_CFG), |
263 | REG_RESERVED(REW_PTP_DLY1_CFG), |
264 | REG_RESERVED(REW_RED_TAG_CFG), |
265 | REG(REW_DSCP_REMAP_DP1_CFG, 0x000610), |
266 | REG(REW_DSCP_REMAP_CFG, 0x000710), |
267 | REG_RESERVED(REW_STAT_CFG), |
268 | REG_RESERVED(REW_REW_STICKY), |
269 | REG_RESERVED(REW_PPT), |
270 | }; |
271 | |
272 | static const u32 vsc9953_sys_regmap[] = { |
273 | REG(SYS_COUNT_RX_OCTETS, 0x000000), |
274 | REG(SYS_COUNT_RX_UNICAST, 0x000004), |
275 | REG(SYS_COUNT_RX_MULTICAST, 0x000008), |
276 | REG(SYS_COUNT_RX_BROADCAST, 0x00000c), |
277 | REG(SYS_COUNT_RX_SHORTS, 0x000010), |
278 | REG(SYS_COUNT_RX_FRAGMENTS, 0x000014), |
279 | REG(SYS_COUNT_RX_JABBERS, 0x000018), |
280 | REG(SYS_COUNT_RX_CRC_ALIGN_ERRS, 0x00001c), |
281 | REG(SYS_COUNT_RX_SYM_ERRS, 0x000020), |
282 | REG(SYS_COUNT_RX_64, 0x000024), |
283 | REG(SYS_COUNT_RX_65_127, 0x000028), |
284 | REG(SYS_COUNT_RX_128_255, 0x00002c), |
285 | REG(SYS_COUNT_RX_256_511, 0x000030), |
286 | REG(SYS_COUNT_RX_512_1023, 0x000034), |
287 | REG(SYS_COUNT_RX_1024_1526, 0x000038), |
288 | REG(SYS_COUNT_RX_1527_MAX, 0x00003c), |
289 | REG(SYS_COUNT_RX_PAUSE, 0x000040), |
290 | REG(SYS_COUNT_RX_CONTROL, 0x000044), |
291 | REG(SYS_COUNT_RX_LONGS, 0x000048), |
292 | REG(SYS_COUNT_RX_CLASSIFIED_DROPS, 0x00004c), |
293 | REG(SYS_COUNT_RX_RED_PRIO_0, 0x000050), |
294 | REG(SYS_COUNT_RX_RED_PRIO_1, 0x000054), |
295 | REG(SYS_COUNT_RX_RED_PRIO_2, 0x000058), |
296 | REG(SYS_COUNT_RX_RED_PRIO_3, 0x00005c), |
297 | REG(SYS_COUNT_RX_RED_PRIO_4, 0x000060), |
298 | REG(SYS_COUNT_RX_RED_PRIO_5, 0x000064), |
299 | REG(SYS_COUNT_RX_RED_PRIO_6, 0x000068), |
300 | REG(SYS_COUNT_RX_RED_PRIO_7, 0x00006c), |
301 | REG(SYS_COUNT_RX_YELLOW_PRIO_0, 0x000070), |
302 | REG(SYS_COUNT_RX_YELLOW_PRIO_1, 0x000074), |
303 | REG(SYS_COUNT_RX_YELLOW_PRIO_2, 0x000078), |
304 | REG(SYS_COUNT_RX_YELLOW_PRIO_3, 0x00007c), |
305 | REG(SYS_COUNT_RX_YELLOW_PRIO_4, 0x000080), |
306 | REG(SYS_COUNT_RX_YELLOW_PRIO_5, 0x000084), |
307 | REG(SYS_COUNT_RX_YELLOW_PRIO_6, 0x000088), |
308 | REG(SYS_COUNT_RX_YELLOW_PRIO_7, 0x00008c), |
309 | REG(SYS_COUNT_RX_GREEN_PRIO_0, 0x000090), |
310 | REG(SYS_COUNT_RX_GREEN_PRIO_1, 0x000094), |
311 | REG(SYS_COUNT_RX_GREEN_PRIO_2, 0x000098), |
312 | REG(SYS_COUNT_RX_GREEN_PRIO_3, 0x00009c), |
313 | REG(SYS_COUNT_RX_GREEN_PRIO_4, 0x0000a0), |
314 | REG(SYS_COUNT_RX_GREEN_PRIO_5, 0x0000a4), |
315 | REG(SYS_COUNT_RX_GREEN_PRIO_6, 0x0000a8), |
316 | REG(SYS_COUNT_RX_GREEN_PRIO_7, 0x0000ac), |
317 | REG(SYS_COUNT_TX_OCTETS, 0x000100), |
318 | REG(SYS_COUNT_TX_UNICAST, 0x000104), |
319 | REG(SYS_COUNT_TX_MULTICAST, 0x000108), |
320 | REG(SYS_COUNT_TX_BROADCAST, 0x00010c), |
321 | REG(SYS_COUNT_TX_COLLISION, 0x000110), |
322 | REG(SYS_COUNT_TX_DROPS, 0x000114), |
323 | REG(SYS_COUNT_TX_PAUSE, 0x000118), |
324 | REG(SYS_COUNT_TX_64, 0x00011c), |
325 | REG(SYS_COUNT_TX_65_127, 0x000120), |
326 | REG(SYS_COUNT_TX_128_255, 0x000124), |
327 | REG(SYS_COUNT_TX_256_511, 0x000128), |
328 | REG(SYS_COUNT_TX_512_1023, 0x00012c), |
329 | REG(SYS_COUNT_TX_1024_1526, 0x000130), |
330 | REG(SYS_COUNT_TX_1527_MAX, 0x000134), |
331 | REG(SYS_COUNT_TX_YELLOW_PRIO_0, 0x000138), |
332 | REG(SYS_COUNT_TX_YELLOW_PRIO_1, 0x00013c), |
333 | REG(SYS_COUNT_TX_YELLOW_PRIO_2, 0x000140), |
334 | REG(SYS_COUNT_TX_YELLOW_PRIO_3, 0x000144), |
335 | REG(SYS_COUNT_TX_YELLOW_PRIO_4, 0x000148), |
336 | REG(SYS_COUNT_TX_YELLOW_PRIO_5, 0x00014c), |
337 | REG(SYS_COUNT_TX_YELLOW_PRIO_6, 0x000150), |
338 | REG(SYS_COUNT_TX_YELLOW_PRIO_7, 0x000154), |
339 | REG(SYS_COUNT_TX_GREEN_PRIO_0, 0x000158), |
340 | REG(SYS_COUNT_TX_GREEN_PRIO_1, 0x00015c), |
341 | REG(SYS_COUNT_TX_GREEN_PRIO_2, 0x000160), |
342 | REG(SYS_COUNT_TX_GREEN_PRIO_3, 0x000164), |
343 | REG(SYS_COUNT_TX_GREEN_PRIO_4, 0x000168), |
344 | REG(SYS_COUNT_TX_GREEN_PRIO_5, 0x00016c), |
345 | REG(SYS_COUNT_TX_GREEN_PRIO_6, 0x000170), |
346 | REG(SYS_COUNT_TX_GREEN_PRIO_7, 0x000174), |
347 | REG(SYS_COUNT_TX_AGED, 0x000178), |
348 | REG(SYS_COUNT_DROP_LOCAL, 0x000200), |
349 | REG(SYS_COUNT_DROP_TAIL, 0x000204), |
350 | REG(SYS_COUNT_DROP_YELLOW_PRIO_0, 0x000208), |
351 | REG(SYS_COUNT_DROP_YELLOW_PRIO_1, 0x00020c), |
352 | REG(SYS_COUNT_DROP_YELLOW_PRIO_2, 0x000210), |
353 | REG(SYS_COUNT_DROP_YELLOW_PRIO_3, 0x000214), |
354 | REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218), |
355 | REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c), |
356 | REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220), |
357 | REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000224), |
358 | REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000228), |
359 | REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00022c), |
360 | REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000230), |
361 | REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000234), |
362 | REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000238), |
363 | REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00023c), |
364 | REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000240), |
365 | REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000244), |
366 | REG(SYS_RESET_CFG, 0x000318), |
367 | REG_RESERVED(SYS_SR_ETYPE_CFG), |
368 | REG(SYS_VLAN_ETYPE_CFG, 0x000320), |
369 | REG(SYS_PORT_MODE, 0x000324), |
370 | REG(SYS_FRONT_PORT_MODE, 0x000354), |
371 | REG(SYS_FRM_AGING, 0x00037c), |
372 | REG(SYS_STAT_CFG, 0x000380), |
373 | REG_RESERVED(SYS_SW_STATUS), |
374 | REG_RESERVED(SYS_MISC_CFG), |
375 | REG_RESERVED(SYS_REW_MAC_HIGH_CFG), |
376 | REG_RESERVED(SYS_REW_MAC_LOW_CFG), |
377 | REG_RESERVED(SYS_TIMESTAMP_OFFSET), |
378 | REG(SYS_PAUSE_CFG, 0x00044c), |
379 | REG(SYS_PAUSE_TOT_CFG, 0x000478), |
380 | REG(SYS_ATOP, 0x00047c), |
381 | REG(SYS_ATOP_TOT_CFG, 0x0004a8), |
382 | REG(SYS_MAC_FC_CFG, 0x0004ac), |
383 | REG(SYS_MMGT, 0x0004d4), |
384 | REG_RESERVED(SYS_MMGT_FAST), |
385 | REG_RESERVED(SYS_EVENTS_DIF), |
386 | REG_RESERVED(SYS_EVENTS_CORE), |
387 | REG_RESERVED(SYS_PTP_STATUS), |
388 | REG_RESERVED(SYS_PTP_TXSTAMP), |
389 | REG_RESERVED(SYS_PTP_NXT), |
390 | REG_RESERVED(SYS_PTP_CFG), |
391 | REG_RESERVED(SYS_RAM_INIT), |
392 | REG_RESERVED(SYS_CM_ADDR), |
393 | REG_RESERVED(SYS_CM_DATA_WR), |
394 | REG_RESERVED(SYS_CM_DATA_RD), |
395 | REG_RESERVED(SYS_CM_OP), |
396 | REG_RESERVED(SYS_CM_DATA), |
397 | }; |
398 | |
399 | static const u32 vsc9953_gcb_regmap[] = { |
400 | REG(GCB_SOFT_RST, 0x000008), |
401 | REG(GCB_MIIM_MII_STATUS, 0x0000ac), |
402 | REG(GCB_MIIM_MII_CMD, 0x0000b4), |
403 | REG(GCB_MIIM_MII_DATA, 0x0000b8), |
404 | }; |
405 | |
406 | static const u32 vsc9953_dev_gmii_regmap[] = { |
407 | REG(DEV_CLOCK_CFG, 0x0), |
408 | REG(DEV_PORT_MISC, 0x4), |
409 | REG_RESERVED(DEV_EVENTS), |
410 | REG(DEV_EEE_CFG, 0xc), |
411 | REG_RESERVED(DEV_RX_PATH_DELAY), |
412 | REG_RESERVED(DEV_TX_PATH_DELAY), |
413 | REG_RESERVED(DEV_PTP_PREDICT_CFG), |
414 | REG(DEV_MAC_ENA_CFG, 0x10), |
415 | REG(DEV_MAC_MODE_CFG, 0x14), |
416 | REG(DEV_MAC_MAXLEN_CFG, 0x18), |
417 | REG(DEV_MAC_TAGS_CFG, 0x1c), |
418 | REG(DEV_MAC_ADV_CHK_CFG, 0x20), |
419 | REG(DEV_MAC_IFG_CFG, 0x24), |
420 | REG(DEV_MAC_HDX_CFG, 0x28), |
421 | REG_RESERVED(DEV_MAC_DBG_CFG), |
422 | REG(DEV_MAC_FC_MAC_LOW_CFG, 0x30), |
423 | REG(DEV_MAC_FC_MAC_HIGH_CFG, 0x34), |
424 | REG(DEV_MAC_STICKY, 0x38), |
425 | REG_RESERVED(PCS1G_CFG), |
426 | REG_RESERVED(PCS1G_MODE_CFG), |
427 | REG_RESERVED(PCS1G_SD_CFG), |
428 | REG_RESERVED(PCS1G_ANEG_CFG), |
429 | REG_RESERVED(PCS1G_ANEG_NP_CFG), |
430 | REG_RESERVED(PCS1G_LB_CFG), |
431 | REG_RESERVED(PCS1G_DBG_CFG), |
432 | REG_RESERVED(PCS1G_CDET_CFG), |
433 | REG_RESERVED(PCS1G_ANEG_STATUS), |
434 | REG_RESERVED(PCS1G_ANEG_NP_STATUS), |
435 | REG_RESERVED(PCS1G_LINK_STATUS), |
436 | REG_RESERVED(PCS1G_LINK_DOWN_CNT), |
437 | REG_RESERVED(PCS1G_STICKY), |
438 | REG_RESERVED(PCS1G_DEBUG_STATUS), |
439 | REG_RESERVED(PCS1G_LPI_CFG), |
440 | REG_RESERVED(PCS1G_LPI_WAKE_ERROR_CNT), |
441 | REG_RESERVED(PCS1G_LPI_STATUS), |
442 | REG_RESERVED(PCS1G_TSTPAT_MODE_CFG), |
443 | REG_RESERVED(PCS1G_TSTPAT_STATUS), |
444 | REG_RESERVED(DEV_PCS_FX100_CFG), |
445 | REG_RESERVED(DEV_PCS_FX100_STATUS), |
446 | }; |
447 | |
448 | static const u32 *vsc9953_regmap[TARGET_MAX] = { |
449 | [ANA] = vsc9953_ana_regmap, |
450 | [QS] = vsc9953_qs_regmap, |
451 | [QSYS] = vsc9953_qsys_regmap, |
452 | [REW] = vsc9953_rew_regmap, |
453 | [SYS] = vsc9953_sys_regmap, |
454 | [S0] = vsc9953_vcap_regmap, |
455 | [S1] = vsc9953_vcap_regmap, |
456 | [S2] = vsc9953_vcap_regmap, |
457 | [GCB] = vsc9953_gcb_regmap, |
458 | [DEV_GMII] = vsc9953_dev_gmii_regmap, |
459 | }; |
460 | |
461 | /* Addresses are relative to the device's base address */ |
462 | static const struct resource vsc9953_resources[] = { |
463 | DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys" ), |
464 | DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew" ), |
465 | DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0" ), |
466 | DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1" ), |
467 | DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2" ), |
468 | DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb" ), |
469 | DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs" ), |
470 | DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp" ), |
471 | DEFINE_RES_MEM_NAMED(0x0100000, 0x0010000, "port0" ), |
472 | DEFINE_RES_MEM_NAMED(0x0110000, 0x0010000, "port1" ), |
473 | DEFINE_RES_MEM_NAMED(0x0120000, 0x0010000, "port2" ), |
474 | DEFINE_RES_MEM_NAMED(0x0130000, 0x0010000, "port3" ), |
475 | DEFINE_RES_MEM_NAMED(0x0140000, 0x0010000, "port4" ), |
476 | DEFINE_RES_MEM_NAMED(0x0150000, 0x0010000, "port5" ), |
477 | DEFINE_RES_MEM_NAMED(0x0160000, 0x0010000, "port6" ), |
478 | DEFINE_RES_MEM_NAMED(0x0170000, 0x0010000, "port7" ), |
479 | DEFINE_RES_MEM_NAMED(0x0180000, 0x0010000, "port8" ), |
480 | DEFINE_RES_MEM_NAMED(0x0190000, 0x0010000, "port9" ), |
481 | DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys" ), |
482 | DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana" ), |
483 | }; |
484 | |
485 | static const char * const vsc9953_resource_names[TARGET_MAX] = { |
486 | [SYS] = "sys" , |
487 | [REW] = "rew" , |
488 | [S0] = "s0" , |
489 | [S1] = "s1" , |
490 | [S2] = "s2" , |
491 | [GCB] = "devcpu_gcb" , |
492 | [QS] = "qs" , |
493 | [PTP] = "ptp" , |
494 | [QSYS] = "qsys" , |
495 | [ANA] = "ana" , |
496 | }; |
497 | |
498 | static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = { |
499 | [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 10, 10), |
500 | [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 9), |
501 | [ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24), |
502 | [ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22), |
503 | [ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21), |
504 | [ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20), |
505 | [ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19), |
506 | [ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18), |
507 | [ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17), |
508 | [ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16), |
509 | [ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15), |
510 | [ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13), |
511 | [ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12), |
512 | [ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11), |
513 | [ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10), |
514 | [ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9), |
515 | [ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8), |
516 | [ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7), |
517 | [ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6), |
518 | [ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5), |
519 | [ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4), |
520 | [ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3), |
521 | [ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2), |
522 | [ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1), |
523 | [ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0), |
524 | [ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 16, 16), |
525 | [ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 11, 12), |
526 | [ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 10), |
527 | [SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 7, 7), |
528 | [SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 6, 6), |
529 | [SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 5, 5), |
530 | [GCB_SOFT_RST_SWC_RST] = REG_FIELD(GCB_SOFT_RST, 0, 0), |
531 | [GCB_MIIM_MII_STATUS_PENDING] = REG_FIELD(GCB_MIIM_MII_STATUS, 2, 2), |
532 | [GCB_MIIM_MII_STATUS_BUSY] = REG_FIELD(GCB_MIIM_MII_STATUS, 3, 3), |
533 | /* Replicated per number of ports (11), register size 4 per port */ |
534 | [QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 13, 13, 11, 4), |
535 | [QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 11, 4), |
536 | [QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 11, 4), |
537 | [QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 11, 4), |
538 | [QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 11, 4), |
539 | [SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 4, 5, 11, 4), |
540 | [SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 2, 3, 11, 4), |
541 | [SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 11, 4), |
542 | [SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 11, 20, 11, 4), |
543 | [SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 10, 11, 4), |
544 | [SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 11, 4), |
545 | }; |
546 | |
547 | static const struct vcap_field vsc9953_vcap_es0_keys[] = { |
548 | [VCAP_ES0_EGR_PORT] = { 0, 4}, |
549 | [VCAP_ES0_IGR_PORT] = { .offset: 4, .length: 4}, |
550 | [VCAP_ES0_RSV] = { .offset: 8, .length: 2}, |
551 | [VCAP_ES0_L2_MC] = { .offset: 10, .length: 1}, |
552 | [VCAP_ES0_L2_BC] = { .offset: 11, .length: 1}, |
553 | [VCAP_ES0_VID] = { .offset: 12, .length: 12}, |
554 | [VCAP_ES0_DP] = { .offset: 24, .length: 1}, |
555 | [VCAP_ES0_PCP] = { .offset: 25, .length: 3}, |
556 | }; |
557 | |
558 | static const struct vcap_field vsc9953_vcap_es0_actions[] = { |
559 | [VCAP_ES0_ACT_PUSH_OUTER_TAG] = { .offset: 0, .length: 2}, |
560 | [VCAP_ES0_ACT_PUSH_INNER_TAG] = { .offset: 2, .length: 1}, |
561 | [VCAP_ES0_ACT_TAG_A_TPID_SEL] = { .offset: 3, .length: 2}, |
562 | [VCAP_ES0_ACT_TAG_A_VID_SEL] = { .offset: 5, .length: 1}, |
563 | [VCAP_ES0_ACT_TAG_A_PCP_SEL] = { .offset: 6, .length: 2}, |
564 | [VCAP_ES0_ACT_TAG_A_DEI_SEL] = { .offset: 8, .length: 2}, |
565 | [VCAP_ES0_ACT_TAG_B_TPID_SEL] = { .offset: 10, .length: 2}, |
566 | [VCAP_ES0_ACT_TAG_B_VID_SEL] = { .offset: 12, .length: 1}, |
567 | [VCAP_ES0_ACT_TAG_B_PCP_SEL] = { .offset: 13, .length: 2}, |
568 | [VCAP_ES0_ACT_TAG_B_DEI_SEL] = { .offset: 15, .length: 2}, |
569 | [VCAP_ES0_ACT_VID_A_VAL] = { .offset: 17, .length: 12}, |
570 | [VCAP_ES0_ACT_PCP_A_VAL] = { .offset: 29, .length: 3}, |
571 | [VCAP_ES0_ACT_DEI_A_VAL] = { .offset: 32, .length: 1}, |
572 | [VCAP_ES0_ACT_VID_B_VAL] = { .offset: 33, .length: 12}, |
573 | [VCAP_ES0_ACT_PCP_B_VAL] = { .offset: 45, .length: 3}, |
574 | [VCAP_ES0_ACT_DEI_B_VAL] = { .offset: 48, .length: 1}, |
575 | [VCAP_ES0_ACT_RSV] = { .offset: 49, .length: 24}, |
576 | [VCAP_ES0_ACT_HIT_STICKY] = { .offset: 73, .length: 1}, |
577 | }; |
578 | |
579 | static const struct vcap_field vsc9953_vcap_is1_keys[] = { |
580 | [VCAP_IS1_HK_TYPE] = { .offset: 0, .length: 1}, |
581 | [VCAP_IS1_HK_LOOKUP] = { .offset: 1, .length: 2}, |
582 | [VCAP_IS1_HK_IGR_PORT_MASK] = { .offset: 3, .length: 11}, |
583 | [VCAP_IS1_HK_RSV] = { .offset: 14, .length: 10}, |
584 | /* VCAP_IS1_HK_OAM_Y1731 not supported */ |
585 | [VCAP_IS1_HK_L2_MC] = { .offset: 24, .length: 1}, |
586 | [VCAP_IS1_HK_L2_BC] = { .offset: 25, .length: 1}, |
587 | [VCAP_IS1_HK_IP_MC] = { .offset: 26, .length: 1}, |
588 | [VCAP_IS1_HK_VLAN_TAGGED] = { .offset: 27, .length: 1}, |
589 | [VCAP_IS1_HK_VLAN_DBL_TAGGED] = { .offset: 28, .length: 1}, |
590 | [VCAP_IS1_HK_TPID] = { .offset: 29, .length: 1}, |
591 | [VCAP_IS1_HK_VID] = { .offset: 30, .length: 12}, |
592 | [VCAP_IS1_HK_DEI] = { .offset: 42, .length: 1}, |
593 | [VCAP_IS1_HK_PCP] = { .offset: 43, .length: 3}, |
594 | /* Specific Fields for IS1 Half Key S1_NORMAL */ |
595 | [VCAP_IS1_HK_L2_SMAC] = { .offset: 46, .length: 48}, |
596 | [VCAP_IS1_HK_ETYPE_LEN] = { .offset: 94, .length: 1}, |
597 | [VCAP_IS1_HK_ETYPE] = { .offset: 95, .length: 16}, |
598 | [VCAP_IS1_HK_IP_SNAP] = {.offset: 111, .length: 1}, |
599 | [VCAP_IS1_HK_IP4] = {.offset: 112, .length: 1}, |
600 | /* Layer-3 Information */ |
601 | [VCAP_IS1_HK_L3_FRAGMENT] = {.offset: 113, .length: 1}, |
602 | [VCAP_IS1_HK_L3_FRAG_OFS_GT0] = {.offset: 114, .length: 1}, |
603 | [VCAP_IS1_HK_L3_OPTIONS] = {.offset: 115, .length: 1}, |
604 | [VCAP_IS1_HK_L3_DSCP] = {.offset: 116, .length: 6}, |
605 | [VCAP_IS1_HK_L3_IP4_SIP] = {.offset: 122, .length: 32}, |
606 | /* Layer-4 Information */ |
607 | [VCAP_IS1_HK_TCP_UDP] = {.offset: 154, .length: 1}, |
608 | [VCAP_IS1_HK_TCP] = {.offset: 155, .length: 1}, |
609 | [VCAP_IS1_HK_L4_SPORT] = {.offset: 156, .length: 16}, |
610 | [VCAP_IS1_HK_L4_RNG] = {.offset: 172, .length: 8}, |
611 | /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */ |
612 | [VCAP_IS1_HK_IP4_INNER_TPID] = { .offset: 46, .length: 1}, |
613 | [VCAP_IS1_HK_IP4_INNER_VID] = { .offset: 47, .length: 12}, |
614 | [VCAP_IS1_HK_IP4_INNER_DEI] = { .offset: 59, .length: 1}, |
615 | [VCAP_IS1_HK_IP4_INNER_PCP] = { .offset: 60, .length: 3}, |
616 | [VCAP_IS1_HK_IP4_IP4] = { .offset: 63, .length: 1}, |
617 | [VCAP_IS1_HK_IP4_L3_FRAGMENT] = { .offset: 64, .length: 1}, |
618 | [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0] = { .offset: 65, .length: 1}, |
619 | [VCAP_IS1_HK_IP4_L3_OPTIONS] = { .offset: 66, .length: 1}, |
620 | [VCAP_IS1_HK_IP4_L3_DSCP] = { .offset: 67, .length: 6}, |
621 | [VCAP_IS1_HK_IP4_L3_IP4_DIP] = { .offset: 73, .length: 32}, |
622 | [VCAP_IS1_HK_IP4_L3_IP4_SIP] = {.offset: 105, .length: 32}, |
623 | [VCAP_IS1_HK_IP4_L3_PROTO] = {.offset: 137, .length: 8}, |
624 | [VCAP_IS1_HK_IP4_TCP_UDP] = {.offset: 145, .length: 1}, |
625 | [VCAP_IS1_HK_IP4_TCP] = {.offset: 146, .length: 1}, |
626 | [VCAP_IS1_HK_IP4_L4_RNG] = {.offset: 147, .length: 8}, |
627 | [VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE] = {.offset: 155, .length: 32}, |
628 | }; |
629 | |
630 | static const struct vcap_field vsc9953_vcap_is1_actions[] = { |
631 | [VCAP_IS1_ACT_DSCP_ENA] = { .offset: 0, .length: 1}, |
632 | [VCAP_IS1_ACT_DSCP_VAL] = { .offset: 1, .length: 6}, |
633 | [VCAP_IS1_ACT_QOS_ENA] = { .offset: 7, .length: 1}, |
634 | [VCAP_IS1_ACT_QOS_VAL] = { .offset: 8, .length: 3}, |
635 | [VCAP_IS1_ACT_DP_ENA] = { .offset: 11, .length: 1}, |
636 | [VCAP_IS1_ACT_DP_VAL] = { .offset: 12, .length: 1}, |
637 | [VCAP_IS1_ACT_PAG_OVERRIDE_MASK] = { .offset: 13, .length: 8}, |
638 | [VCAP_IS1_ACT_PAG_VAL] = { .offset: 21, .length: 8}, |
639 | [VCAP_IS1_ACT_RSV] = { .offset: 29, .length: 11}, |
640 | [VCAP_IS1_ACT_VID_REPLACE_ENA] = { .offset: 40, .length: 1}, |
641 | [VCAP_IS1_ACT_VID_ADD_VAL] = { .offset: 41, .length: 12}, |
642 | [VCAP_IS1_ACT_FID_SEL] = { .offset: 53, .length: 2}, |
643 | [VCAP_IS1_ACT_FID_VAL] = { .offset: 55, .length: 13}, |
644 | [VCAP_IS1_ACT_PCP_DEI_ENA] = { .offset: 68, .length: 1}, |
645 | [VCAP_IS1_ACT_PCP_VAL] = { .offset: 69, .length: 3}, |
646 | [VCAP_IS1_ACT_DEI_VAL] = { .offset: 72, .length: 1}, |
647 | [VCAP_IS1_ACT_VLAN_POP_CNT_ENA] = { .offset: 73, .length: 1}, |
648 | [VCAP_IS1_ACT_VLAN_POP_CNT] = { .offset: 74, .length: 2}, |
649 | [VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA] = { .offset: 76, .length: 4}, |
650 | [VCAP_IS1_ACT_HIT_STICKY] = { .offset: 80, .length: 1}, |
651 | }; |
652 | |
653 | static struct vcap_field vsc9953_vcap_is2_keys[] = { |
654 | /* Common: 41 bits */ |
655 | [VCAP_IS2_TYPE] = { .offset: 0, .length: 4}, |
656 | [VCAP_IS2_HK_FIRST] = { .offset: 4, .length: 1}, |
657 | [VCAP_IS2_HK_PAG] = { .offset: 5, .length: 8}, |
658 | [VCAP_IS2_HK_IGR_PORT_MASK] = { .offset: 13, .length: 11}, |
659 | [VCAP_IS2_HK_RSV2] = { .offset: 24, .length: 1}, |
660 | [VCAP_IS2_HK_HOST_MATCH] = { .offset: 25, .length: 1}, |
661 | [VCAP_IS2_HK_L2_MC] = { .offset: 26, .length: 1}, |
662 | [VCAP_IS2_HK_L2_BC] = { .offset: 27, .length: 1}, |
663 | [VCAP_IS2_HK_VLAN_TAGGED] = { .offset: 28, .length: 1}, |
664 | [VCAP_IS2_HK_VID] = { .offset: 29, .length: 12}, |
665 | [VCAP_IS2_HK_DEI] = { .offset: 41, .length: 1}, |
666 | [VCAP_IS2_HK_PCP] = { .offset: 42, .length: 3}, |
667 | /* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ |
668 | [VCAP_IS2_HK_L2_DMAC] = { .offset: 45, .length: 48}, |
669 | [VCAP_IS2_HK_L2_SMAC] = { .offset: 93, .length: 48}, |
670 | /* MAC_ETYPE (TYPE=000) */ |
671 | [VCAP_IS2_HK_MAC_ETYPE_ETYPE] = {.offset: 141, .length: 16}, |
672 | [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0] = {.offset: 157, .length: 16}, |
673 | [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1] = {.offset: 173, .length: 8}, |
674 | [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2] = {.offset: 181, .length: 3}, |
675 | /* MAC_LLC (TYPE=001) */ |
676 | [VCAP_IS2_HK_MAC_LLC_L2_LLC] = {.offset: 141, .length: 40}, |
677 | /* MAC_SNAP (TYPE=010) */ |
678 | [VCAP_IS2_HK_MAC_SNAP_L2_SNAP] = {.offset: 141, .length: 40}, |
679 | /* MAC_ARP (TYPE=011) */ |
680 | [VCAP_IS2_HK_MAC_ARP_SMAC] = { .offset: 45, .length: 48}, |
681 | [VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { .offset: 93, .length: 1}, |
682 | [VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { .offset: 94, .length: 1}, |
683 | [VCAP_IS2_HK_MAC_ARP_LEN_OK] = { .offset: 95, .length: 1}, |
684 | [VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { .offset: 96, .length: 1}, |
685 | [VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { .offset: 97, .length: 1}, |
686 | [VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { .offset: 98, .length: 1}, |
687 | [VCAP_IS2_HK_MAC_ARP_OPCODE] = { .offset: 99, .length: 2}, |
688 | [VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP] = {.offset: 101, .length: 32}, |
689 | [VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP] = {.offset: 133, .length: 32}, |
690 | [VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = {.offset: 165, .length: 1}, |
691 | /* IP4_TCP_UDP / IP4_OTHER common */ |
692 | [VCAP_IS2_HK_IP4] = { .offset: 45, .length: 1}, |
693 | [VCAP_IS2_HK_L3_FRAGMENT] = { .offset: 46, .length: 1}, |
694 | [VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { .offset: 47, .length: 1}, |
695 | [VCAP_IS2_HK_L3_OPTIONS] = { .offset: 48, .length: 1}, |
696 | [VCAP_IS2_HK_IP4_L3_TTL_GT0] = { .offset: 49, .length: 1}, |
697 | [VCAP_IS2_HK_L3_TOS] = { .offset: 50, .length: 8}, |
698 | [VCAP_IS2_HK_L3_IP4_DIP] = { .offset: 58, .length: 32}, |
699 | [VCAP_IS2_HK_L3_IP4_SIP] = { .offset: 90, .length: 32}, |
700 | [VCAP_IS2_HK_DIP_EQ_SIP] = {.offset: 122, .length: 1}, |
701 | /* IP4_TCP_UDP (TYPE=100) */ |
702 | [VCAP_IS2_HK_TCP] = {.offset: 123, .length: 1}, |
703 | [VCAP_IS2_HK_L4_DPORT] = {.offset: 124, .length: 16}, |
704 | [VCAP_IS2_HK_L4_SPORT] = {.offset: 140, .length: 16}, |
705 | [VCAP_IS2_HK_L4_RNG] = {.offset: 156, .length: 8}, |
706 | [VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = {.offset: 164, .length: 1}, |
707 | [VCAP_IS2_HK_L4_SEQUENCE_EQ0] = {.offset: 165, .length: 1}, |
708 | [VCAP_IS2_HK_L4_FIN] = {.offset: 166, .length: 1}, |
709 | [VCAP_IS2_HK_L4_SYN] = {.offset: 167, .length: 1}, |
710 | [VCAP_IS2_HK_L4_RST] = {.offset: 168, .length: 1}, |
711 | [VCAP_IS2_HK_L4_PSH] = {.offset: 169, .length: 1}, |
712 | [VCAP_IS2_HK_L4_ACK] = {.offset: 170, .length: 1}, |
713 | [VCAP_IS2_HK_L4_URG] = {.offset: 171, .length: 1}, |
714 | /* IP4_OTHER (TYPE=101) */ |
715 | [VCAP_IS2_HK_IP4_L3_PROTO] = {.offset: 123, .length: 8}, |
716 | [VCAP_IS2_HK_L3_PAYLOAD] = {.offset: 131, .length: 56}, |
717 | /* IP6_STD (TYPE=110) */ |
718 | [VCAP_IS2_HK_IP6_L3_TTL_GT0] = { .offset: 45, .length: 1}, |
719 | [VCAP_IS2_HK_L3_IP6_SIP] = { .offset: 46, .length: 128}, |
720 | [VCAP_IS2_HK_IP6_L3_PROTO] = {.offset: 174, .length: 8}, |
721 | }; |
722 | |
723 | static struct vcap_field vsc9953_vcap_is2_actions[] = { |
724 | [VCAP_IS2_ACT_HIT_ME_ONCE] = { .offset: 0, .length: 1}, |
725 | [VCAP_IS2_ACT_CPU_COPY_ENA] = { .offset: 1, .length: 1}, |
726 | [VCAP_IS2_ACT_CPU_QU_NUM] = { .offset: 2, .length: 3}, |
727 | [VCAP_IS2_ACT_MASK_MODE] = { .offset: 5, .length: 2}, |
728 | [VCAP_IS2_ACT_MIRROR_ENA] = { .offset: 7, .length: 1}, |
729 | [VCAP_IS2_ACT_LRN_DIS] = { .offset: 8, .length: 1}, |
730 | [VCAP_IS2_ACT_POLICE_ENA] = { .offset: 9, .length: 1}, |
731 | [VCAP_IS2_ACT_POLICE_IDX] = { .offset: 10, .length: 8}, |
732 | [VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { .offset: 21, .length: 1}, |
733 | [VCAP_IS2_ACT_PORT_MASK] = { .offset: 22, .length: 10}, |
734 | [VCAP_IS2_ACT_ACL_ID] = { .offset: 44, .length: 6}, |
735 | [VCAP_IS2_ACT_HIT_CNT] = { .offset: 50, .length: 32}, |
736 | }; |
737 | |
738 | static struct vcap_props vsc9953_vcap_props[] = { |
739 | [VCAP_ES0] = { |
740 | .action_type_width = 0, |
741 | .action_table = { |
742 | [ES0_ACTION_TYPE_NORMAL] = { |
743 | .width = 73, /* HIT_STICKY not included */ |
744 | .count = 1, |
745 | }, |
746 | }, |
747 | .target = S0, |
748 | .keys = vsc9953_vcap_es0_keys, |
749 | .actions = vsc9953_vcap_es0_actions, |
750 | }, |
751 | [VCAP_IS1] = { |
752 | .action_type_width = 0, |
753 | .action_table = { |
754 | [IS1_ACTION_TYPE_NORMAL] = { |
755 | .width = 80, /* HIT_STICKY not included */ |
756 | .count = 4, |
757 | }, |
758 | }, |
759 | .target = S1, |
760 | .keys = vsc9953_vcap_is1_keys, |
761 | .actions = vsc9953_vcap_is1_actions, |
762 | }, |
763 | [VCAP_IS2] = { |
764 | .action_type_width = 1, |
765 | .action_table = { |
766 | [IS2_ACTION_TYPE_NORMAL] = { |
767 | .width = 50, /* HIT_CNT not included */ |
768 | .count = 2 |
769 | }, |
770 | [IS2_ACTION_TYPE_SMAC_SIP] = { |
771 | .width = 6, |
772 | .count = 4 |
773 | }, |
774 | }, |
775 | .target = S2, |
776 | .keys = vsc9953_vcap_is2_keys, |
777 | .actions = vsc9953_vcap_is2_actions, |
778 | }, |
779 | }; |
780 | |
781 | #define VSC9953_INIT_TIMEOUT 50000 |
782 | #define VSC9953_GCB_RST_SLEEP 100 |
783 | #define VSC9953_SYS_RAMINIT_SLEEP 80 |
784 | |
785 | static int vsc9953_gcb_soft_rst_status(struct ocelot *ocelot) |
786 | { |
787 | int val; |
788 | |
789 | ocelot_field_read(ocelot, GCB_SOFT_RST_SWC_RST, &val); |
790 | |
791 | return val; |
792 | } |
793 | |
794 | static int vsc9953_sys_ram_init_status(struct ocelot *ocelot) |
795 | { |
796 | int val; |
797 | |
798 | ocelot_field_read(ocelot, SYS_RESET_CFG_MEM_INIT, &val); |
799 | |
800 | return val; |
801 | } |
802 | |
803 | |
804 | /* CORE_ENA is in SYS:SYSTEM:RESET_CFG |
805 | * MEM_INIT is in SYS:SYSTEM:RESET_CFG |
806 | * MEM_ENA is in SYS:SYSTEM:RESET_CFG |
807 | */ |
808 | static int vsc9953_reset(struct ocelot *ocelot) |
809 | { |
810 | int val, err; |
811 | |
812 | /* soft-reset the switch core */ |
813 | ocelot_field_write(ocelot, GCB_SOFT_RST_SWC_RST, 1); |
814 | |
815 | err = readx_poll_timeout(vsc9953_gcb_soft_rst_status, ocelot, val, !val, |
816 | VSC9953_GCB_RST_SLEEP, VSC9953_INIT_TIMEOUT); |
817 | if (err) { |
818 | dev_err(ocelot->dev, "timeout: switch core reset\n" ); |
819 | return err; |
820 | } |
821 | |
822 | /* initialize switch mem ~40us */ |
823 | ocelot_field_write(ocelot, SYS_RESET_CFG_MEM_ENA, 1); |
824 | ocelot_field_write(ocelot, SYS_RESET_CFG_MEM_INIT, 1); |
825 | |
826 | err = readx_poll_timeout(vsc9953_sys_ram_init_status, ocelot, val, !val, |
827 | VSC9953_SYS_RAMINIT_SLEEP, |
828 | VSC9953_INIT_TIMEOUT); |
829 | if (err) { |
830 | dev_err(ocelot->dev, "timeout: switch sram init\n" ); |
831 | return err; |
832 | } |
833 | |
834 | /* enable switch core */ |
835 | ocelot_field_write(ocelot, SYS_RESET_CFG_CORE_ENA, 1); |
836 | |
837 | return 0; |
838 | } |
839 | |
840 | /* Watermark encode |
841 | * Bit 9: Unit; 0:1, 1:16 |
842 | * Bit 8-0: Value to be multiplied with unit |
843 | */ |
844 | static u16 vsc9953_wm_enc(u16 value) |
845 | { |
846 | WARN_ON(value >= 16 * BIT(9)); |
847 | |
848 | if (value >= BIT(9)) |
849 | return BIT(9) | (value / 16); |
850 | |
851 | return value; |
852 | } |
853 | |
854 | static u16 vsc9953_wm_dec(u16 wm) |
855 | { |
856 | WARN_ON(wm & ~GENMASK(9, 0)); |
857 | |
858 | if (wm & BIT(9)) |
859 | return (wm & GENMASK(8, 0)) * 16; |
860 | |
861 | return wm; |
862 | } |
863 | |
864 | static void vsc9953_wm_stat(u32 val, u32 *inuse, u32 *maxuse) |
865 | { |
866 | *inuse = (val & GENMASK(25, 13)) >> 13; |
867 | *maxuse = val & GENMASK(12, 0); |
868 | } |
869 | |
870 | static const struct ocelot_ops vsc9953_ops = { |
871 | .reset = vsc9953_reset, |
872 | .wm_enc = vsc9953_wm_enc, |
873 | .wm_dec = vsc9953_wm_dec, |
874 | .wm_stat = vsc9953_wm_stat, |
875 | .port_to_netdev = felix_port_to_netdev, |
876 | .netdev_to_port = felix_netdev_to_port, |
877 | }; |
878 | |
879 | static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) |
880 | { |
881 | struct felix *felix = ocelot_to_felix(ocelot); |
882 | struct device *dev = ocelot->dev; |
883 | struct mii_bus *bus; |
884 | int port; |
885 | int rc; |
886 | |
887 | felix->pcs = devm_kcalloc(dev, n: felix->info->num_ports, |
888 | size: sizeof(struct phylink_pcs *), |
889 | GFP_KERNEL); |
890 | if (!felix->pcs) { |
891 | dev_err(dev, "failed to allocate array for PCS PHYs\n" ); |
892 | return -ENOMEM; |
893 | } |
894 | |
895 | rc = mscc_miim_setup(device: dev, bus: &bus, name: "VSC9953 internal MDIO bus" , |
896 | mii_regmap: ocelot->targets[GCB], |
897 | status_offset: ocelot->map[GCB][GCB_MIIM_MII_STATUS & REG_MASK], |
898 | ignore_read_errors: true); |
899 | if (rc) { |
900 | dev_err(dev, "failed to setup MDIO bus\n" ); |
901 | return rc; |
902 | } |
903 | |
904 | /* Needed in order to initialize the bus mutex lock */ |
905 | rc = devm_of_mdiobus_register(dev, mdio: bus, NULL); |
906 | if (rc < 0) { |
907 | dev_err(dev, "failed to register MDIO bus\n" ); |
908 | return rc; |
909 | } |
910 | |
911 | felix->imdio = bus; |
912 | |
913 | for (port = 0; port < felix->info->num_ports; port++) { |
914 | struct ocelot_port *ocelot_port = ocelot->ports[port]; |
915 | struct phylink_pcs *phylink_pcs; |
916 | int addr = port + 4; |
917 | |
918 | if (dsa_is_unused_port(ds: felix->ds, p: port)) |
919 | continue; |
920 | |
921 | if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) |
922 | continue; |
923 | |
924 | phylink_pcs = lynx_pcs_create_mdiodev(bus: felix->imdio, addr); |
925 | if (IS_ERR(ptr: phylink_pcs)) |
926 | continue; |
927 | |
928 | felix->pcs[port] = phylink_pcs; |
929 | |
930 | dev_info(dev, "Found PCS at internal MDIO address %d\n" , addr); |
931 | } |
932 | |
933 | return 0; |
934 | } |
935 | |
936 | static void vsc9953_mdio_bus_free(struct ocelot *ocelot) |
937 | { |
938 | struct felix *felix = ocelot_to_felix(ocelot); |
939 | int port; |
940 | |
941 | for (port = 0; port < ocelot->num_phys_ports; port++) { |
942 | struct phylink_pcs *phylink_pcs = felix->pcs[port]; |
943 | |
944 | if (phylink_pcs) |
945 | lynx_pcs_destroy(pcs: phylink_pcs); |
946 | } |
947 | |
948 | /* mdiobus_unregister and mdiobus_free handled by devres */ |
949 | } |
950 | |
951 | static const struct felix_info seville_info_vsc9953 = { |
952 | .resources = vsc9953_resources, |
953 | .num_resources = ARRAY_SIZE(vsc9953_resources), |
954 | .resource_names = vsc9953_resource_names, |
955 | .regfields = vsc9953_regfields, |
956 | .map = vsc9953_regmap, |
957 | .ops = &vsc9953_ops, |
958 | .vcap = vsc9953_vcap_props, |
959 | .vcap_pol_base = VSC9953_VCAP_POLICER_BASE, |
960 | .vcap_pol_max = VSC9953_VCAP_POLICER_MAX, |
961 | .vcap_pol_base2 = VSC9953_VCAP_POLICER_BASE2, |
962 | .vcap_pol_max2 = VSC9953_VCAP_POLICER_MAX2, |
963 | .quirks = FELIX_MAC_QUIRKS, |
964 | .num_mact_rows = 2048, |
965 | .num_ports = VSC9953_NUM_PORTS, |
966 | .num_tx_queues = OCELOT_NUM_TC, |
967 | .mdio_bus_alloc = vsc9953_mdio_bus_alloc, |
968 | .mdio_bus_free = vsc9953_mdio_bus_free, |
969 | .port_modes = vsc9953_port_modes, |
970 | }; |
971 | |
972 | static int seville_probe(struct platform_device *pdev) |
973 | { |
974 | struct dsa_switch *ds; |
975 | struct ocelot *ocelot; |
976 | struct resource *res; |
977 | struct felix *felix; |
978 | int err; |
979 | |
980 | felix = kzalloc(size: sizeof(struct felix), GFP_KERNEL); |
981 | if (!felix) { |
982 | err = -ENOMEM; |
983 | dev_err(&pdev->dev, "Failed to allocate driver memory\n" ); |
984 | goto err_alloc_felix; |
985 | } |
986 | |
987 | platform_set_drvdata(pdev, data: felix); |
988 | |
989 | ocelot = &felix->ocelot; |
990 | ocelot->dev = &pdev->dev; |
991 | ocelot->num_flooding_pgids = 1; |
992 | felix->info = &seville_info_vsc9953; |
993 | |
994 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
995 | if (!res) { |
996 | err = -EINVAL; |
997 | dev_err(&pdev->dev, "Invalid resource\n" ); |
998 | goto err_alloc_felix; |
999 | } |
1000 | felix->switch_base = res->start; |
1001 | |
1002 | ds = kzalloc(size: sizeof(struct dsa_switch), GFP_KERNEL); |
1003 | if (!ds) { |
1004 | err = -ENOMEM; |
1005 | dev_err(&pdev->dev, "Failed to allocate DSA switch\n" ); |
1006 | goto err_alloc_ds; |
1007 | } |
1008 | |
1009 | ds->dev = &pdev->dev; |
1010 | ds->num_ports = felix->info->num_ports; |
1011 | ds->ops = &felix_switch_ops; |
1012 | ds->priv = ocelot; |
1013 | felix->ds = ds; |
1014 | felix->tag_proto = DSA_TAG_PROTO_SEVILLE; |
1015 | |
1016 | err = dsa_register_switch(ds); |
1017 | if (err) { |
1018 | dev_err(&pdev->dev, "Failed to register DSA switch: %d\n" , err); |
1019 | goto err_register_ds; |
1020 | } |
1021 | |
1022 | return 0; |
1023 | |
1024 | err_register_ds: |
1025 | kfree(objp: ds); |
1026 | err_alloc_ds: |
1027 | err_alloc_felix: |
1028 | kfree(objp: felix); |
1029 | return err; |
1030 | } |
1031 | |
1032 | static void seville_remove(struct platform_device *pdev) |
1033 | { |
1034 | struct felix *felix = platform_get_drvdata(pdev); |
1035 | |
1036 | if (!felix) |
1037 | return; |
1038 | |
1039 | dsa_unregister_switch(ds: felix->ds); |
1040 | |
1041 | kfree(objp: felix->ds); |
1042 | kfree(objp: felix); |
1043 | } |
1044 | |
1045 | static void seville_shutdown(struct platform_device *pdev) |
1046 | { |
1047 | struct felix *felix = platform_get_drvdata(pdev); |
1048 | |
1049 | if (!felix) |
1050 | return; |
1051 | |
1052 | dsa_switch_shutdown(ds: felix->ds); |
1053 | |
1054 | platform_set_drvdata(pdev, NULL); |
1055 | } |
1056 | |
1057 | static const struct of_device_id seville_of_match[] = { |
1058 | { .compatible = "mscc,vsc9953-switch" }, |
1059 | { }, |
1060 | }; |
1061 | MODULE_DEVICE_TABLE(of, seville_of_match); |
1062 | |
1063 | static struct platform_driver seville_vsc9953_driver = { |
1064 | .probe = seville_probe, |
1065 | .remove_new = seville_remove, |
1066 | .shutdown = seville_shutdown, |
1067 | .driver = { |
1068 | .name = "mscc_seville" , |
1069 | .of_match_table = seville_of_match, |
1070 | }, |
1071 | }; |
1072 | module_platform_driver(seville_vsc9953_driver); |
1073 | |
1074 | MODULE_DESCRIPTION("Seville Switch driver" ); |
1075 | MODULE_LICENSE("GPL v2" ); |
1076 | |