1 /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
4 * Hirschmann Hellcreek TSN switch.
6 * Copyright (C) 2019-2021 Linutronix GmbH
7 * Author Kurt Kanzenbach <kurt@linutronix.de>
13 #include <linux/bitmap.h>
14 #include <linux/bitops.h>
15 #include <linux/container_of.h>
16 #include <linux/device.h>
17 #include <linux/leds.h>
18 #include <linux/mutex.h>
19 #include <linux/platform_data/hirschmann-hellcreek.h>
20 #include <linux/ptp_clock_kernel.h>
21 #include <linux/timecounter.h>
22 #include <linux/types.h>
23 #include <linux/workqueue.h>
26 #include <net/pkt_sched.h>
31 * - 2: TSN front port 1
32 * - 3: TSN front port 2
38 #define HELLCREEK_VLAN_NO_MEMBER 0x0
39 #define HELLCREEK_VLAN_UNTAGGED_MEMBER 0x1
40 #define HELLCREEK_VLAN_TAGGED_MEMBER 0x3
41 #define HELLCREEK_NUM_EGRESS_QUEUES 8
42 #define HELLCREEK_DEFAULT_MAX_SDU 1536
44 /* Register definitions */
45 #define HR_MODID_C (0 * 2)
46 #define HR_REL_L_C (1 * 2)
47 #define HR_REL_H_C (2 * 2)
48 #define HR_BLD_L_C (3 * 2)
49 #define HR_BLD_H_C (4 * 2)
50 #define HR_CTRL_C (5 * 2)
51 #define HR_CTRL_C_READY BIT(14)
52 #define HR_CTRL_C_TRANSITION BIT(13)
53 #define HR_CTRL_C_ENABLE BIT(0)
55 #define HR_PSEL (0xa6 * 2)
56 #define HR_PSEL_PTWSEL_SHIFT 4
57 #define HR_PSEL_PTWSEL_MASK GENMASK(5, 4)
58 #define HR_PSEL_PRTCWSEL_SHIFT 0
59 #define HR_PSEL_PRTCWSEL_MASK GENMASK(2, 0)
61 #define HR_PTCFG (0xa7 * 2)
62 #define HR_PTCFG_MLIMIT_EN BIT(13)
63 #define HR_PTCFG_UMC_FLT BIT(10)
64 #define HR_PTCFG_UUC_FLT BIT(9)
65 #define HR_PTCFG_UNTRUST BIT(8)
66 #define HR_PTCFG_TAG_REQUIRED BIT(7)
67 #define HR_PTCFG_PPRIO_SHIFT 4
68 #define HR_PTCFG_PPRIO_MASK GENMASK(6, 4)
69 #define HR_PTCFG_INGRESSFLT BIT(3)
70 #define HR_PTCFG_BLOCKED BIT(2)
71 #define HR_PTCFG_LEARNING_EN BIT(1)
72 #define HR_PTCFG_ADMIN_EN BIT(0)
74 #define HR_PRTCCFG (0xa8 * 2)
75 #define HR_PRTCCFG_PCP_TC_MAP_SHIFT 0
76 #define HR_PRTCCFG_PCP_TC_MAP_MASK GENMASK(2, 0)
78 #define HR_PTPRTCCFG (0xa9 * 2)
79 #define HR_PTPRTCCFG_SET_QTRACK BIT(15)
80 #define HR_PTPRTCCFG_REJECT BIT(14)
81 #define HR_PTPRTCCFG_MAXSDU_SHIFT 0
82 #define HR_PTPRTCCFG_MAXSDU_MASK GENMASK(10, 0)
84 #define HR_CSEL (0x8d * 2)
85 #define HR_CSEL_SHIFT 0
86 #define HR_CSEL_MASK GENMASK(7, 0)
87 #define HR_CRDL (0x8e * 2)
88 #define HR_CRDH (0x8f * 2)
90 #define HR_SWTRC_CFG (0x90 * 2)
91 #define HR_SWTRC0 (0x91 * 2)
92 #define HR_SWTRC1 (0x92 * 2)
93 #define HR_PFREE (0x93 * 2)
94 #define HR_MFREE (0x94 * 2)
96 #define HR_FDBAGE (0x97 * 2)
97 #define HR_FDBMAX (0x98 * 2)
98 #define HR_FDBRDL (0x99 * 2)
99 #define HR_FDBRDM (0x9a * 2)
100 #define HR_FDBRDH (0x9b * 2)
102 #define HR_FDBMDRD (0x9c * 2)
103 #define HR_FDBMDRD_PORTMASK_SHIFT 0
104 #define HR_FDBMDRD_PORTMASK_MASK GENMASK(3, 0)
105 #define HR_FDBMDRD_AGE_SHIFT 4
106 #define HR_FDBMDRD_AGE_MASK GENMASK(7, 4)
107 #define HR_FDBMDRD_OBT BIT(8)
108 #define HR_FDBMDRD_PASS_BLOCKED BIT(9)
109 #define HR_FDBMDRD_STATIC BIT(11)
110 #define HR_FDBMDRD_REPRIO_TC_SHIFT 12
111 #define HR_FDBMDRD_REPRIO_TC_MASK GENMASK(14, 12)
112 #define HR_FDBMDRD_REPRIO_EN BIT(15)
114 #define HR_FDBWDL (0x9d * 2)
115 #define HR_FDBWDM (0x9e * 2)
116 #define HR_FDBWDH (0x9f * 2)
117 #define HR_FDBWRM0 (0xa0 * 2)
118 #define HR_FDBWRM0_PORTMASK_SHIFT 0
119 #define HR_FDBWRM0_PORTMASK_MASK GENMASK(3, 0)
120 #define HR_FDBWRM0_OBT BIT(8)
121 #define HR_FDBWRM0_PASS_BLOCKED BIT(9)
122 #define HR_FDBWRM0_REPRIO_TC_SHIFT 12
123 #define HR_FDBWRM0_REPRIO_TC_MASK GENMASK(14, 12)
124 #define HR_FDBWRM0_REPRIO_EN BIT(15)
125 #define HR_FDBWRM1 (0xa1 * 2)
127 #define HR_FDBWRCMD (0xa2 * 2)
128 #define HR_FDBWRCMD_FDBDEL BIT(9)
130 #define HR_SWCFG (0xa3 * 2)
131 #define HR_SWCFG_GM_STATEMD BIT(15)
132 #define HR_SWCFG_LAS_MODE_SHIFT 12
133 #define HR_SWCFG_LAS_MODE_MASK GENMASK(13, 12)
134 #define HR_SWCFG_LAS_OFF (0x00)
135 #define HR_SWCFG_LAS_ON (0x01)
136 #define HR_SWCFG_LAS_STATIC (0x10)
137 #define HR_SWCFG_CT_EN BIT(11)
138 #define HR_SWCFG_VLAN_UNAWARE BIT(10)
139 #define HR_SWCFG_ALWAYS_OBT BIT(9)
140 #define HR_SWCFG_FDBAGE_EN BIT(5)
141 #define HR_SWCFG_FDBLRN_EN BIT(4)
143 #define HR_SWSTAT (0xa4 * 2)
144 #define HR_SWSTAT_FAIL BIT(4)
145 #define HR_SWSTAT_BUSY BIT(0)
147 #define HR_SWCMD (0xa5 * 2)
148 #define HW_SWCMD_FLUSH BIT(0)
150 #define HR_VIDCFG (0xaa * 2)
151 #define HR_VIDCFG_VID_SHIFT 0
152 #define HR_VIDCFG_VID_MASK GENMASK(11, 0)
153 #define HR_VIDCFG_PVID BIT(12)
155 #define HR_VIDMBRCFG (0xab * 2)
156 #define HR_VIDMBRCFG_P0MBR_SHIFT 0
157 #define HR_VIDMBRCFG_P0MBR_MASK GENMASK(1, 0)
158 #define HR_VIDMBRCFG_P1MBR_SHIFT 2
159 #define HR_VIDMBRCFG_P1MBR_MASK GENMASK(3, 2)
160 #define HR_VIDMBRCFG_P2MBR_SHIFT 4
161 #define HR_VIDMBRCFG_P2MBR_MASK GENMASK(5, 4)
162 #define HR_VIDMBRCFG_P3MBR_SHIFT 6
163 #define HR_VIDMBRCFG_P3MBR_MASK GENMASK(7, 6)
165 #define HR_FEABITS0 (0xac * 2)
166 #define HR_FEABITS0_FDBBINS_SHIFT 4
167 #define HR_FEABITS0_FDBBINS_MASK GENMASK(7, 4)
168 #define HR_FEABITS0_PCNT_SHIFT 8
169 #define HR_FEABITS0_PCNT_MASK GENMASK(11, 8)
170 #define HR_FEABITS0_MCNT_SHIFT 12
171 #define HR_FEABITS0_MCNT_MASK GENMASK(15, 12)
173 #define TR_QTRACK (0xb1 * 2)
174 #define TR_TGDVER (0xb3 * 2)
175 #define TR_TGDVER_REV_MIN_MASK GENMASK(7, 0)
176 #define TR_TGDVER_REV_MIN_SHIFT 0
177 #define TR_TGDVER_REV_MAJ_MASK GENMASK(15, 8)
178 #define TR_TGDVER_REV_MAJ_SHIFT 8
179 #define TR_TGDSEL (0xb4 * 2)
180 #define TR_TGDSEL_TDGSEL_MASK GENMASK(1, 0)
181 #define TR_TGDSEL_TDGSEL_SHIFT 0
182 #define TR_TGDCTRL (0xb5 * 2)
183 #define TR_TGDCTRL_GATE_EN BIT(0)
184 #define TR_TGDCTRL_CYC_SNAP BIT(4)
185 #define TR_TGDCTRL_SNAP_EST BIT(5)
186 #define TR_TGDCTRL_ADMINGATESTATES_MASK GENMASK(15, 8)
187 #define TR_TGDCTRL_ADMINGATESTATES_SHIFT 8
188 #define TR_TGDSTAT0 (0xb6 * 2)
189 #define TR_TGDSTAT1 (0xb7 * 2)
190 #define TR_ESTWRL (0xb8 * 2)
191 #define TR_ESTWRH (0xb9 * 2)
192 #define TR_ESTCMD (0xba * 2)
193 #define TR_ESTCMD_ESTSEC_MASK GENMASK(2, 0)
194 #define TR_ESTCMD_ESTSEC_SHIFT 0
195 #define TR_ESTCMD_ESTARM BIT(4)
196 #define TR_ESTCMD_ESTSWCFG BIT(5)
197 #define TR_EETWRL (0xbb * 2)
198 #define TR_EETWRH (0xbc * 2)
199 #define TR_EETCMD (0xbd * 2)
200 #define TR_EETCMD_EETSEC_MASK GEMASK(2, 0)
201 #define TR_EETCMD_EETSEC_SHIFT 0
202 #define TR_EETCMD_EETARM BIT(4)
203 #define TR_CTWRL (0xbe * 2)
204 #define TR_CTWRH (0xbf * 2)
205 #define TR_LCNSL (0xc1 * 2)
206 #define TR_LCNSH (0xc2 * 2)
207 #define TR_LCS (0xc3 * 2)
208 #define TR_GCLDAT (0xc4 * 2)
209 #define TR_GCLDAT_GCLWRGATES_MASK GENMASK(7, 0)
210 #define TR_GCLDAT_GCLWRGATES_SHIFT 0
211 #define TR_GCLDAT_GCLWRLAST BIT(8)
212 #define TR_GCLDAT_GCLOVRI BIT(9)
213 #define TR_GCLTIL (0xc5 * 2)
214 #define TR_GCLTIH (0xc6 * 2)
215 #define TR_GCLCMD (0xc7 * 2)
216 #define TR_GCLCMD_GCLWRADR_MASK GENMASK(7, 0)
217 #define TR_GCLCMD_GCLWRADR_SHIFT 0
218 #define TR_GCLCMD_INIT_GATE_STATES_MASK GENMASK(15, 8)
219 #define TR_GCLCMD_INIT_GATE_STATES_SHIFT 8
221 struct hellcreek_counter
{
228 /* State flags for hellcreek_port_hwtstamp::state */
230 HELLCREEK_HWTSTAMP_ENABLED
,
231 HELLCREEK_HWTSTAMP_TX_IN_PROGRESS
,
234 /* A structure to hold hardware timestamping information per port */
235 struct hellcreek_port_hwtstamp
{
236 /* Timestamping state */
239 /* Resources for receive timestamping */
240 struct sk_buff_head rx_queue
; /* For synchronization messages */
242 /* Resources for transmit timestamping */
243 unsigned long tx_tstamp_start
;
244 struct sk_buff
*tx_skb
;
246 /* Current timestamp configuration */
247 struct hwtstamp_config tstamp_config
;
250 struct hellcreek_port
{
251 struct hellcreek
*hellcreek
;
252 unsigned long *vlan_dev_bitmap
;
254 u16 ptcfg
; /* ptcfg shadow */
257 /* Per-port timestamping resources */
258 struct hellcreek_port_hwtstamp port_hwtstamp
;
260 /* Per-port Qbv schedule information */
261 struct tc_taprio_qopt_offload
*current_schedule
;
262 struct delayed_work schedule_work
;
265 struct hellcreek_fdb_entry
{
267 unsigned char mac
[ETH_ALEN
];
278 const struct hellcreek_platform_data
*pdata
;
280 struct dsa_switch
*ds
;
281 struct ptp_clock
*ptp_clock
;
282 struct ptp_clock_info ptp_clock_info
;
283 struct hellcreek_port
*ports
;
284 struct delayed_work overflow_work
;
285 struct led_classdev led_is_gm
;
286 struct led_classdev led_sync_good
;
287 struct mutex reg_lock
; /* Switch IP register lock */
288 struct mutex vlan_lock
; /* VLAN bitmaps lock */
289 struct mutex ptp_lock
; /* PTP IP register lock */
290 struct devlink_region
*vlan_region
;
291 struct devlink_region
*fdb_region
;
293 void __iomem
*ptp_base
;
294 u16 swcfg
; /* swcfg shadow */
295 u8
*vidmbrcfg
; /* vidmbrcfg shadow */
296 u64 seconds
; /* PTP seconds */
297 u64 last_ts
; /* Used for overflow detection */
298 u16 status_out
; /* ptp.status_out shadow */
302 /* A Qbv schedule can only started up to 8 seconds in the future. If the delta
303 * between the base time and the current ptp time is larger than 8 seconds, then
304 * use periodic work to check for the schedule to be started. The delayed work
305 * cannot be armed directly to $base_time - 8 + X, because for large deltas the
306 * PTP frequency matters.
308 #define HELLCREEK_SCHEDULE_PERIOD (2 * HZ)
309 #define dw_to_hellcreek_port(dw) \
310 container_of(dw, struct hellcreek_port, schedule_work)
312 /* Devlink resources */
313 enum hellcreek_devlink_resource_id
{
314 HELLCREEK_DEVLINK_PARAM_ID_VLAN_TABLE
,
315 HELLCREEK_DEVLINK_PARAM_ID_FDB_TABLE
,
318 struct hellcreek_devlink_vlan_entry
{
323 #endif /* _HELLCREEK_H_ */