aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/can/esd/esdacc.h
blob: a70488b25d3905948f5031807b25ecf16385736c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2015 - 2016 Thomas Körper, esd electronic system design gmbh
 * Copyright (C) 2017 - 2023 Stefan Mätje, esd electronics gmbh
 */

#include <linux/bits.h>
#include <linux/can/dev.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/units.h>

#define ACC_TS_FREQ_80MHZ (80 * HZ_PER_MHZ)
#define ACC_I2C_ADDON_DETECT_DELAY_MS 10

/* esdACC Overview Module */
#define ACC_OV_OF_PROBE	0x0000
#define ACC_OV_OF_VERSION 0x0004
#define ACC_OV_OF_INFO 0x0008
#define ACC_OV_OF_CANCORE_FREQ 0x000c
#define ACC_OV_OF_TS_FREQ_LO 0x0010
#define ACC_OV_OF_TS_FREQ_HI 0x0014
#define ACC_OV_OF_IRQ_STATUS_CORES 0x0018
#define ACC_OV_OF_TS_CURR_LO 0x001c
#define ACC_OV_OF_TS_CURR_HI 0x0020
#define ACC_OV_OF_IRQ_STATUS 0x0028
#define ACC_OV_OF_MODE 0x002c
#define ACC_OV_OF_BM_IRQ_COUNTER 0x0070
#define ACC_OV_OF_BM_IRQ_MASK 0x0074
#define ACC_OV_OF_MSI_DATA 0x0080
#define ACC_OV_OF_MSI_ADDRESSOFFSET 0x0084

/* Feature flags are contained in the upper 16 bit of the version
 * register at ACC_OV_OF_VERSION but only used with these masks after
 * extraction into an extra variable => (xx - 16).
 */
#define ACC_OV_REG_FEAT_MASK_CANFD BIT(27 - 16)
#define ACC_OV_REG_FEAT_MASK_NEW_PSC BIT(28 - 16)

#define ACC_OV_REG_MODE_MASK_ENDIAN_LITTLE BIT(0)
#define ACC_OV_REG_MODE_MASK_BM_ENABLE BIT(1)
#define ACC_OV_REG_MODE_MASK_MODE_LED BIT(2)
#define ACC_OV_REG_MODE_MASK_TIMER_ENABLE BIT(4)
#define ACC_OV_REG_MODE_MASK_TIMER_ONE_SHOT BIT(5)
#define ACC_OV_REG_MODE_MASK_TIMER_ABSOLUTE BIT(6)
#define ACC_OV_REG_MODE_MASK_TIMER GENMASK(6, 4)
#define ACC_OV_REG_MODE_MASK_TS_SRC GENMASK(8, 7)
#define ACC_OV_REG_MODE_MASK_I2C_ENABLE BIT(11)
#define ACC_OV_REG_MODE_MASK_MSI_ENABLE BIT(14)
#define ACC_OV_REG_MODE_MASK_NEW_PSC_ENABLE BIT(15)
#define ACC_OV_REG_MODE_MASK_FPGA_RESET BIT(31)

/* esdACC CAN Core Module */
#define ACC_CORE_OF_CTRL_MODE 0x0000
#define ACC_CORE_OF_STATUS_IRQ 0x0008
#define ACC_CORE_OF_BRP	0x000c
#define ACC_CORE_OF_BTR	0x0010
#define ACC_CORE_OF_FBTR 0x0014
#define ACC_CORE_OF_STATUS 0x0030
#define ACC_CORE_OF_TXFIFO_CONFIG 0x0048
#define ACC_CORE_OF_TXFIFO_STATUS 0x004c
#define ACC_CORE_OF_TX_STATUS_IRQ 0x0050
#define ACC_CORE_OF_TX_ABORT_MASK 0x0054
#define ACC_CORE_OF_BM_IRQ_COUNTER 0x0070
#define ACC_CORE_OF_TXFIFO_ID 0x00c0
#define ACC_CORE_OF_TXFIFO_DLC 0x00c4
#define ACC_CORE_OF_TXFIFO_DATA_0 0x00c8
#define ACC_CORE_OF_TXFIFO_DATA_1 0x00cc

#define ACC_REG_CONTROL_MASK_MODE_RESETMODE BIT(0)
#define ACC_REG_CONTROL_MASK_MODE_LOM BIT(1)
#define ACC_REG_CONTROL_MASK_MODE_STM BIT(2)
#define ACC_REG_CONTROL_MASK_MODE_TRANSEN BIT(5)
#define ACC_REG_CONTROL_MASK_MODE_TS BIT(6)
#define ACC_REG_CONTROL_MASK_MODE_SCHEDULE BIT(7)

#define ACC_REG_CONTROL_MASK_IE_RXTX BIT(8)
#define ACC_REG_CONTROL_MASK_IE_TXERROR BIT(9)
#define ACC_REG_CONTROL_MASK_IE_ERRWARN BIT(10)
#define ACC_REG_CONTROL_MASK_IE_OVERRUN BIT(11)
#define ACC_REG_CONTROL_MASK_IE_TSI BIT(12)
#define ACC_REG_CONTROL_MASK_IE_ERRPASS BIT(13)
#define ACC_REG_CONTROL_MASK_IE_ALI BIT(14)
#define ACC_REG_CONTROL_MASK_IE_BUSERR BIT(15)

/* BRP and BTR register layout for CAN-Classic version */
#define ACC_REG_BRP_CL_MASK_BRP GENMASK(8, 0)
#define ACC_REG_BTR_CL_MASK_TSEG1 GENMASK(3, 0)
#define ACC_REG_BTR_CL_MASK_TSEG2 GENMASK(18, 16)
#define ACC_REG_BTR_CL_MASK_SJW GENMASK(25, 24)

/* BRP and BTR register layout for CAN-FD version */
#define ACC_REG_BRP_FD_MASK_BRP GENMASK(7, 0)
#define ACC_REG_BTR_FD_MASK_TSEG1 GENMASK(7, 0)
#define ACC_REG_BTR_FD_MASK_TSEG2 GENMASK(22, 16)
#define ACC_REG_BTR_FD_MASK_SJW GENMASK(30, 24)

/* 256 BM_MSGs of 32 byte size */
#define ACC_CORE_DMAMSG_SIZE 32U
#define ACC_CORE_DMABUF_SIZE (256U * ACC_CORE_DMAMSG_SIZE)

enum acc_bmmsg_id {
	BM_MSG_ID_RXTXDONE = 0x01,
	BM_MSG_ID_TXABORT = 0x02,
	BM_MSG_ID_OVERRUN = 0x03,
	BM_MSG_ID_BUSERR = 0x04,
	BM_MSG_ID_ERRPASSIVE = 0x05,
	BM_MSG_ID_ERRWARN = 0x06,
	BM_MSG_ID_TIMESLICE = 0x07,
	BM_MSG_ID_HWTIMER = 0x08,
	BM_MSG_ID_HOTPLUG = 0x09,
};

/* The struct acc_bmmsg_* structure declarations that follow here provide
 * access to the ring buffer of bus master messages maintained by the FPGA
 * bus master engine. All bus master messages have the same size of
 * ACC_CORE_DMAMSG_SIZE and a minimum alignment of ACC_CORE_DMAMSG_SIZE in
 * memory.
 *
 * All structure members are natural aligned. Therefore we should not need
 * a __packed attribute. All struct acc_bmmsg_* declarations have at least
 * reserved* members to fill the structure to the full ACC_CORE_DMAMSG_SIZE.
 *
 * A failure of this property due padding will be detected at compile time
 * by static_assert(sizeof(union acc_bmmsg) == ACC_CORE_DMAMSG_SIZE).
 */

struct acc_bmmsg_rxtxdone {
	u8 msg_id;
	u8 txfifo_level;
	u8 reserved1[2];
	u8 txtsfifo_level;
	u8 reserved2[3];
	u32 id;
	struct {
		u8 len;
		u8 txdfifo_idx;
		u8 zeroes8;
		u8 reserved;
	} acc_dlc;
	u8 data[CAN_MAX_DLEN];
	/* Time stamps in struct acc_ov::timestamp_frequency ticks. */
	u64 ts;
};

struct acc_bmmsg_txabort {
	u8 msg_id;
	u8 txfifo_level;
	u16 abort_mask;
	u8 txtsfifo_level;
	u8 reserved2[1];
	u16 abort_mask_txts;
	u64 ts;
	u32 reserved3[4];
};

struct acc_bmmsg_overrun {
	u8 msg_id;
	u8 txfifo_level;
	u8 lost_cnt;
	u8 reserved1;
	u8 txtsfifo_level;
	u8 reserved2[3];
	u64 ts;
	u32 reserved3[4];
};

struct acc_bmmsg_buserr {
	u8 msg_id;
	u8 txfifo_level;
	u8 ecc;
	u8 reserved1;
	u8 txtsfifo_level;
	u8 reserved2[3];
	u64 ts;
	u32 reg_status;
	u32 reg_btr;
	u32 reserved3[2];
};

struct acc_bmmsg_errstatechange {
	u8 msg_id;
	u8 txfifo_level;
	u8 reserved1[2];
	u8 txtsfifo_level;
	u8 reserved2[3];
	u64 ts;
	u32 reg_status;
	u32 reserved3[3];
};

struct acc_bmmsg_timeslice {
	u8 msg_id;
	u8 txfifo_level;
	u8 reserved1[2];
	u8 txtsfifo_level;
	u8 reserved2[3];
	u64 ts;
	u32 reserved3[4];
};

struct acc_bmmsg_hwtimer {
	u8 msg_id;
	u8 reserved1[3];
	u32 reserved2[1];
	u64 timer;
	u32 reserved3[4];
};

struct acc_bmmsg_hotplug {
	u8 msg_id;
	u8 reserved1[3];
	u32 reserved2[7];
};

union acc_bmmsg {
	u8 msg_id;
	struct acc_bmmsg_rxtxdone rxtxdone;
	struct acc_bmmsg_txabort txabort;
	struct acc_bmmsg_overrun overrun;
	struct acc_bmmsg_buserr buserr;
	struct acc_bmmsg_errstatechange errstatechange;
	struct acc_bmmsg_timeslice timeslice;
	struct acc_bmmsg_hwtimer hwtimer;
};

/* Check size of union acc_bmmsg to be of expected size. */
static_assert(sizeof(union acc_bmmsg) == ACC_CORE_DMAMSG_SIZE);

struct acc_bmfifo {
	const union acc_bmmsg *messages;
	/* irq_cnt points to an u32 value where the esdACC FPGA deposits
	 * the bm_fifo head index in coherent DMA memory. Only bits 7..0
	 * are valid. Use READ_ONCE() to access this memory location.
	 */
	const u32 *irq_cnt;
	u32 local_irq_cnt;
	u32 msg_fifo_tail;
};

struct acc_core {
	void __iomem *addr;
	struct net_device *netdev;
	struct acc_bmfifo bmfifo;
	u8 tx_fifo_size;
	u8 tx_fifo_head;
	u8 tx_fifo_tail;
};

struct acc_ov {
	void __iomem *addr;
	struct acc_bmfifo bmfifo;
	u32 timestamp_frequency;
	u32 core_frequency;
	u16 version;
	u16 features;
	u8 total_cores;
	u8 active_cores;
};

struct acc_net_priv {
	struct can_priv can; /* must be the first member! */
	struct acc_core *core;
	struct acc_ov *ov;
};

static inline u32 acc_read32(struct acc_core *core, unsigned short offs)
{
	return ioread32be(core->addr + offs);
}

static inline void acc_write32(struct acc_core *core,
			       unsigned short offs, u32 v)
{
	iowrite32be(v, core->addr + offs);
}

static inline void acc_write32_noswap(struct acc_core *core,
				      unsigned short offs, u32 v)
{
	iowrite32(v, core->addr + offs);
}

static inline void acc_set_bits(struct acc_core *core,
				unsigned short offs, u32 mask)
{
	u32 v = acc_read32(core, offs);

	v |= mask;
	acc_write32(core, offs, v);
}

static inline void acc_clear_bits(struct acc_core *core,
				  unsigned short offs, u32 mask)
{
	u32 v = acc_read32(core, offs);

	v &= ~mask;
	acc_write32(core, offs, v);
}

static inline int acc_resetmode_entered(struct acc_core *core)
{
	u32 ctrl = acc_read32(core, ACC_CORE_OF_CTRL_MODE);

	return (ctrl & ACC_REG_CONTROL_MASK_MODE_RESETMODE) != 0;
}

static inline u32 acc_ov_read32(struct acc_ov *ov, unsigned short offs)
{
	return ioread32be(ov->addr + offs);
}

static inline void acc_ov_write32(struct acc_ov *ov,
				  unsigned short offs, u32 v)
{
	iowrite32be(v, ov->addr + offs);
}

static inline void acc_ov_set_bits(struct acc_ov *ov,
				   unsigned short offs, u32 b)
{
	u32 v = acc_ov_read32(ov, offs);

	v |= b;
	acc_ov_write32(ov, offs, v);
}

static inline void acc_ov_clear_bits(struct acc_ov *ov,
				     unsigned short offs, u32 b)
{
	u32 v = acc_ov_read32(ov, offs);

	v &= ~b;
	acc_ov_write32(ov, offs, v);
}

static inline void acc_reset_fpga(struct acc_ov *ov)
{
	acc_ov_write32(ov, ACC_OV_OF_MODE, ACC_OV_REG_MODE_MASK_FPGA_RESET);

	/* (Re-)start and wait for completion of addon detection on the I^2C bus */
	acc_ov_set_bits(ov, ACC_OV_OF_MODE, ACC_OV_REG_MODE_MASK_I2C_ENABLE);
	mdelay(ACC_I2C_ADDON_DETECT_DELAY_MS);
}

void acc_init_ov(struct acc_ov *ov, struct device *dev);
void acc_init_bm_ptr(struct acc_ov *ov, struct acc_core *cores,
		     const void *mem);
int acc_open(struct net_device *netdev);
int acc_close(struct net_device *netdev);
netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev);
int acc_get_berr_counter(const struct net_device *netdev,
			 struct can_berr_counter *bec);
int acc_set_mode(struct net_device *netdev, enum can_mode mode);
int acc_set_bittiming(struct net_device *netdev);
irqreturn_t acc_card_interrupt(struct acc_ov *ov, struct acc_core *cores);