summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sirfsoc_uart.h
blob: 2b41b06362df9fd6cdcd667408e2934a5af27fd6 (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
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/*
 * Drivers for CSR SiRFprimaII onboard UARTs.
 *
 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
 *
 * Licensed under GPLv2 or later.
 */
#include <linux/bitops.h>
struct sirfsoc_uart_param {
	const char *uart_name;
	const char *port_name;
	u32 uart_nr;
	u32 register_uart_nr;
};

struct sirfsoc_register {
	/* hardware uart specific */
	u32 sirfsoc_line_ctrl;
	u32 sirfsoc_divisor;
	/* uart - usp common */
	u32 sirfsoc_tx_rx_en;
	u32 sirfsoc_int_en_reg;
	u32 sirfsoc_int_st_reg;
	u32 sirfsoc_tx_dma_io_ctrl;
	u32 sirfsoc_tx_dma_io_len;
	u32 sirfsoc_tx_fifo_ctrl;
	u32 sirfsoc_tx_fifo_level_chk;
	u32 sirfsoc_tx_fifo_op;
	u32 sirfsoc_tx_fifo_status;
	u32 sirfsoc_tx_fifo_data;
	u32 sirfsoc_rx_dma_io_ctrl;
	u32 sirfsoc_rx_dma_io_len;
	u32 sirfsoc_rx_fifo_ctrl;
	u32 sirfsoc_rx_fifo_level_chk;
	u32 sirfsoc_rx_fifo_op;
	u32 sirfsoc_rx_fifo_status;
	u32 sirfsoc_rx_fifo_data;
	u32 sirfsoc_afc_ctrl;
	u32 sirfsoc_swh_dma_io;
	/* hardware usp specific */
	u32 sirfsoc_mode1;
	u32 sirfsoc_mode2;
	u32 sirfsoc_tx_frame_ctrl;
	u32 sirfsoc_rx_frame_ctrl;
	u32 sirfsoc_async_param_reg;
};

typedef u32 (*fifo_full_mask)(int line);
typedef u32 (*fifo_empty_mask)(int line);

struct sirfsoc_fifo_status {
	fifo_full_mask ff_full;
	fifo_empty_mask ff_empty;
};

struct sirfsoc_int_en {
	u32 sirfsoc_rx_done_en;
	u32 sirfsoc_tx_done_en;
	u32 sirfsoc_rx_oflow_en;
	u32 sirfsoc_tx_allout_en;
	u32 sirfsoc_rx_io_dma_en;
	u32 sirfsoc_tx_io_dma_en;
	u32 sirfsoc_rxfifo_full_en;
	u32 sirfsoc_txfifo_empty_en;
	u32 sirfsoc_rxfifo_thd_en;
	u32 sirfsoc_txfifo_thd_en;
	u32 sirfsoc_frm_err_en;
	u32 sirfsoc_rxd_brk_en;
	u32 sirfsoc_rx_timeout_en;
	u32 sirfsoc_parity_err_en;
	u32 sirfsoc_cts_en;
	u32 sirfsoc_rts_en;
};

struct sirfsoc_int_status {
	u32 sirfsoc_rx_done;
	u32 sirfsoc_tx_done;
	u32 sirfsoc_rx_oflow;
	u32 sirfsoc_tx_allout;
	u32 sirfsoc_rx_io_dma;
	u32 sirfsoc_tx_io_dma;
	u32 sirfsoc_rxfifo_full;
	u32 sirfsoc_txfifo_empty;
	u32 sirfsoc_rxfifo_thd;
	u32 sirfsoc_txfifo_thd;
	u32 sirfsoc_frm_err;
	u32 sirfsoc_rxd_brk;
	u32 sirfsoc_rx_timeout;
	u32 sirfsoc_parity_err;
	u32 sirfsoc_cts;
	u32 sirfsoc_rts;
};

enum sirfsoc_uart_type {
	SIRF_REAL_UART,
	SIRF_USP_UART,
};

struct sirfsoc_uart_register {
	struct sirfsoc_register uart_reg;
	struct sirfsoc_int_en uart_int_en;
	struct sirfsoc_int_status uart_int_st;
	struct sirfsoc_fifo_status fifo_status;
	struct sirfsoc_uart_param uart_param;
	enum sirfsoc_uart_type uart_type;
};

u32 usp_ff_full(int line)
{
	return 0x80;
}
u32 usp_ff_empty(int line)
{
	return 0x100;
}
u32 uart_ff_full(int line)
{
	return (line == 1) ? (0x20) : (0x80);
}
u32 uart_ff_empty(int line)
{
	return (line == 1) ? (0x40) : (0x100);
}
struct sirfsoc_uart_register sirfsoc_usp = {
	.uart_reg = {
		.sirfsoc_mode1		= 0x0000,
		.sirfsoc_mode2		= 0x0004,
		.sirfsoc_tx_frame_ctrl	= 0x0008,
		.sirfsoc_rx_frame_ctrl	= 0x000c,
		.sirfsoc_tx_rx_en	= 0x0010,
		.sirfsoc_int_en_reg	= 0x0014,
		.sirfsoc_int_st_reg	= 0x0018,
		.sirfsoc_async_param_reg = 0x0024,
		.sirfsoc_tx_dma_io_ctrl	= 0x0100,
		.sirfsoc_tx_dma_io_len	= 0x0104,
		.sirfsoc_tx_fifo_ctrl	= 0x0108,
		.sirfsoc_tx_fifo_level_chk = 0x010c,
		.sirfsoc_tx_fifo_op	= 0x0110,
		.sirfsoc_tx_fifo_status	= 0x0114,
		.sirfsoc_tx_fifo_data	= 0x0118,
		.sirfsoc_rx_dma_io_ctrl	= 0x0120,
		.sirfsoc_rx_dma_io_len	= 0x0124,
		.sirfsoc_rx_fifo_ctrl	= 0x0128,
		.sirfsoc_rx_fifo_level_chk = 0x012c,
		.sirfsoc_rx_fifo_op	= 0x0130,
		.sirfsoc_rx_fifo_status	= 0x0134,
		.sirfsoc_rx_fifo_data	= 0x0138,
	},
	.uart_int_en = {
		.sirfsoc_rx_done_en	= BIT(0),
		.sirfsoc_tx_done_en	= BIT(1),
		.sirfsoc_rx_oflow_en	= BIT(2),
		.sirfsoc_tx_allout_en	= BIT(3),
		.sirfsoc_rx_io_dma_en	= BIT(4),
		.sirfsoc_tx_io_dma_en	= BIT(5),
		.sirfsoc_rxfifo_full_en	= BIT(6),
		.sirfsoc_txfifo_empty_en = BIT(7),
		.sirfsoc_rxfifo_thd_en	= BIT(8),
		.sirfsoc_txfifo_thd_en	= BIT(9),
		.sirfsoc_frm_err_en	= BIT(10),
		.sirfsoc_rx_timeout_en	= BIT(11),
		.sirfsoc_rxd_brk_en	= BIT(15),
	},
	.uart_int_st = {
		.sirfsoc_rx_done	= BIT(0),
		.sirfsoc_tx_done	= BIT(1),
		.sirfsoc_rx_oflow	= BIT(2),
		.sirfsoc_tx_allout	= BIT(3),
		.sirfsoc_rx_io_dma	= BIT(4),
		.sirfsoc_tx_io_dma	= BIT(5),
		.sirfsoc_rxfifo_full	= BIT(6),
		.sirfsoc_txfifo_empty	= BIT(7),
		.sirfsoc_rxfifo_thd	= BIT(8),
		.sirfsoc_txfifo_thd	= BIT(9),
		.sirfsoc_frm_err	= BIT(10),
		.sirfsoc_rx_timeout	= BIT(11),
		.sirfsoc_rxd_brk	= BIT(15),
	},
	.fifo_status = {
		.ff_full		= usp_ff_full,
		.ff_empty		= usp_ff_empty,
	},
	.uart_param = {
		.uart_name = "ttySiRF",
		.port_name = "sirfsoc-uart",
		.uart_nr = 2,
		.register_uart_nr = 3,
	},
};

struct sirfsoc_uart_register sirfsoc_uart = {
	.uart_reg = {
		.sirfsoc_line_ctrl	= 0x0040,
		.sirfsoc_tx_rx_en	= 0x004c,
		.sirfsoc_divisor	= 0x0050,
		.sirfsoc_int_en_reg	= 0x0054,
		.sirfsoc_int_st_reg	= 0x0058,
		.sirfsoc_tx_dma_io_ctrl	= 0x0100,
		.sirfsoc_tx_dma_io_len	= 0x0104,
		.sirfsoc_tx_fifo_ctrl	= 0x0108,
		.sirfsoc_tx_fifo_level_chk = 0x010c,
		.sirfsoc_tx_fifo_op	= 0x0110,
		.sirfsoc_tx_fifo_status	= 0x0114,
		.sirfsoc_tx_fifo_data	= 0x0118,
		.sirfsoc_rx_dma_io_ctrl	= 0x0120,
		.sirfsoc_rx_dma_io_len	= 0x0124,
		.sirfsoc_rx_fifo_ctrl	= 0x0128,
		.sirfsoc_rx_fifo_level_chk = 0x012c,
		.sirfsoc_rx_fifo_op	= 0x0130,
		.sirfsoc_rx_fifo_status	= 0x0134,
		.sirfsoc_rx_fifo_data	= 0x0138,
		.sirfsoc_afc_ctrl	= 0x0140,
		.sirfsoc_swh_dma_io	= 0x0148,
	},
	.uart_int_en = {
		.sirfsoc_rx_done_en	= BIT(0),
		.sirfsoc_tx_done_en	= BIT(1),
		.sirfsoc_rx_oflow_en	= BIT(2),
		.sirfsoc_tx_allout_en	= BIT(3),
		.sirfsoc_rx_io_dma_en	= BIT(4),
		.sirfsoc_tx_io_dma_en	= BIT(5),
		.sirfsoc_rxfifo_full_en	= BIT(6),
		.sirfsoc_txfifo_empty_en = BIT(7),
		.sirfsoc_rxfifo_thd_en	= BIT(8),
		.sirfsoc_txfifo_thd_en	= BIT(9),
		.sirfsoc_frm_err_en	= BIT(10),
		.sirfsoc_rxd_brk_en	= BIT(11),
		.sirfsoc_rx_timeout_en	= BIT(12),
		.sirfsoc_parity_err_en	= BIT(13),
		.sirfsoc_cts_en		= BIT(14),
		.sirfsoc_rts_en		= BIT(15),
	},
	.uart_int_st = {
		.sirfsoc_rx_done	= BIT(0),
		.sirfsoc_tx_done	= BIT(1),
		.sirfsoc_rx_oflow	= BIT(2),
		.sirfsoc_tx_allout	= BIT(3),
		.sirfsoc_rx_io_dma	= BIT(4),
		.sirfsoc_tx_io_dma	= BIT(5),
		.sirfsoc_rxfifo_full	= BIT(6),
		.sirfsoc_txfifo_empty	= BIT(7),
		.sirfsoc_rxfifo_thd	= BIT(8),
		.sirfsoc_txfifo_thd	= BIT(9),
		.sirfsoc_frm_err	= BIT(10),
		.sirfsoc_rxd_brk	= BIT(11),
		.sirfsoc_rx_timeout	= BIT(12),
		.sirfsoc_parity_err	= BIT(13),
		.sirfsoc_cts		= BIT(14),
		.sirfsoc_rts		= BIT(15),
	},
	.fifo_status = {
		.ff_full		= uart_ff_full,
		.ff_empty		= uart_ff_empty,
	},
	.uart_param = {
		.uart_name = "ttySiRF",
		.port_name = "sirfsoc_uart",
		.uart_nr = 3,
		.register_uart_nr = 0,
	},
};
/* uart io ctrl */
#define SIRFUART_DATA_BIT_LEN_MASK		0x3
#define SIRFUART_DATA_BIT_LEN_5			BIT(0)
#define SIRFUART_DATA_BIT_LEN_6			1
#define SIRFUART_DATA_BIT_LEN_7			2
#define SIRFUART_DATA_BIT_LEN_8			3
#define SIRFUART_STOP_BIT_LEN_1			0
#define SIRFUART_STOP_BIT_LEN_2			BIT(2)
#define SIRFUART_PARITY_EN			BIT(3)
#define SIRFUART_EVEN_BIT			BIT(4)
#define SIRFUART_STICK_BIT_MASK			(7 << 3)
#define SIRFUART_STICK_BIT_NONE			(0 << 3)
#define SIRFUART_STICK_BIT_EVEN			BIT(3)
#define SIRFUART_STICK_BIT_ODD			(3 << 3)
#define SIRFUART_STICK_BIT_MARK			(5 << 3)
#define SIRFUART_STICK_BIT_SPACE		(7 << 3)
#define SIRFUART_SET_BREAK			BIT(6)
#define SIRFUART_LOOP_BACK			BIT(7)
#define SIRFUART_PARITY_MASK			(7 << 3)
#define SIRFUART_DUMMY_READ			BIT(16)
#define SIRFUART_AFC_CTRL_RX_THD		0x70
#define SIRFUART_AFC_RX_EN			BIT(8)
#define SIRFUART_AFC_TX_EN			BIT(9)
#define SIRFUART_AFC_CTS_CTRL			BIT(10)
#define SIRFUART_AFC_RTS_CTRL			BIT(11)
#define	SIRFUART_AFC_CTS_STATUS			BIT(12)
#define	SIRFUART_AFC_RTS_STATUS			BIT(13)
/* UART FIFO Register */
#define SIRFUART_FIFO_STOP			0x0
#define SIRFUART_FIFO_RESET			BIT(0)
#define SIRFUART_FIFO_START			BIT(1)

#define SIRFUART_RX_EN				BIT(0)
#define SIRFUART_TX_EN				BIT(1)

#define SIRFUART_IO_MODE			BIT(0)
#define SIRFUART_DMA_MODE			0x0

/* Macro Specific*/
#define SIRFUART_INT_EN_CLR                    0x0060
/* Baud Rate Calculation */
#define SIRF_MIN_SAMPLE_DIV			0xf
#define SIRF_MAX_SAMPLE_DIV			0x3f
#define SIRF_IOCLK_DIV_MAX			0xffff
#define SIRF_SAMPLE_DIV_SHIFT			16
#define SIRF_IOCLK_DIV_MASK			0xffff
#define SIRF_SAMPLE_DIV_MASK			0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR		18

/* USP SPEC */
#define SIRFSOC_USP_ENDIAN_CTRL_LSBF		BIT(4)
#define SIRFSOC_USP_EN				BIT(5)

/* USP-UART Common */
#define SIRFSOC_UART_RX_TIMEOUT(br, to)	(((br) * (((to) + 999) / 1000)) / 1000)
#define SIRFUART_RECV_TIMEOUT_VALUE(x)	\
				(((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF))
#define SIRFUART_RECV_TIMEOUT(port, x)	\
		(((port)->line > 2) ? (x & 0xFFFF) : ((x) & 0xFFFF) << 16)

#define SIRFUART_FIFO_THD(port)		((port->line) == 1 ? 16 : 64)
#define SIRFUART_ERR_INT_STAT(port, unit_st)			\
				(uint_st->sirfsoc_rx_oflow |		\
				uint_st->sirfsoc_frm_err |		\
				uint_st->sirfsoc_rxd_brk |		\
		((port->line > 2) ? 0 : uint_st->sirfsoc_parity_err))
#define SIRFUART_RX_IO_INT_EN(port, uint_en)				\
				(uint_en->sirfsoc_rx_timeout_en |\
				 uint_en->sirfsoc_rxfifo_thd_en |\
				 uint_en->sirfsoc_rxfifo_full_en |\
				 uint_en->sirfsoc_frm_err_en |\
				 uint_en->sirfsoc_rx_oflow_en |\
				 uint_en->sirfsoc_rxd_brk_en |\
		((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
#define SIRFUART_RX_IO_INT_ST(uint_st)				\
				(uint_st->sirfsoc_rx_timeout |\
				 uint_st->sirfsoc_rxfifo_thd |\
				 uint_st->sirfsoc_rxfifo_full)
#define SIRFUART_CTS_INT_ST(uint_st)	(uint_st->sirfsoc_cts)
/* Generic Definitions */
#define SIRFSOC_UART_NAME			"ttySiRF"
#define SIRFSOC_UART_MAJOR			0
#define SIRFSOC_UART_MINOR			0
#define SIRFUART_PORT_NAME			"sirfsoc-uart"
#define SIRFUART_MAP_SIZE			0x200
#define SIRFSOC_UART_NR				5
#define SIRFSOC_PORT_TYPE			0xa5

/* Baud Rate Calculation */
#define SIRF_MIN_SAMPLE_DIV			0xf
#define SIRF_MAX_SAMPLE_DIV			0x3f
#define SIRF_IOCLK_DIV_MAX			0xffff
#define SIRF_SAMPLE_DIV_SHIFT			16
#define SIRF_IOCLK_DIV_MASK			0xffff
#define SIRF_SAMPLE_DIV_MASK			0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR		18

/* For Fast Baud Rate Calculation */
struct sirfsoc_baudrate_to_regv {
	unsigned int baud_rate;
	unsigned int reg_val;
};

struct sirfsoc_uart_port {
	unsigned char			hw_flow_ctrl;
	unsigned char			ms_enabled;

	struct uart_port		port;
	struct clk			*clk;
	/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
	bool				is_marco;
	struct sirfsoc_uart_register	*uart_reg;
};

/* Hardware Flow Control */
#define SIRFUART_AFC_CTRL_RX_THD	0x70

/* Register Access Control */
#define portaddr(port, reg)		((port)->membase + (reg))
#define rd_regb(port, reg)		(__raw_readb(portaddr(port, reg)))
#define rd_regl(port, reg)		(__raw_readl(portaddr(port, reg)))
#define wr_regb(port, reg, val)		__raw_writeb(val, portaddr(port, reg))
#define wr_regl(port, reg, val)		__raw_writel(val, portaddr(port, reg))

/* UART Port Mask */
#define SIRFUART_FIFOLEVEL_MASK(port)	((port->line == 1) ? (0x1f) : (0x7f))
#define SIRFUART_FIFOFULL_MASK(port)	((port->line == 1) ? (0x20) : (0x80))
#define SIRFUART_FIFOEMPTY_MASK(port)	((port->line == 1) ? (0x40) : (0x100))

/* I/O Mode */
#define SIRFSOC_UART_IO_RX_MAX_CNT		256
#define SIRFSOC_UART_IO_TX_REASONABLE_CNT	6