Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Drivers for CSR SiRFprimaII onboard UARTs. |
| 3 | * |
| 4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. |
| 5 | * |
| 6 | * Licensed under GPLv2 or later. |
| 7 | */ |
| 8 | #include <linux/bitops.h> |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 9 | #include <linux/log2.h> |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 10 | #include <linux/hrtimer.h> |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 11 | struct sirfsoc_uart_param { |
| 12 | const char *uart_name; |
| 13 | const char *port_name; |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 14 | }; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 15 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 16 | struct sirfsoc_register { |
| 17 | /* hardware uart specific */ |
| 18 | u32 sirfsoc_line_ctrl; |
| 19 | u32 sirfsoc_divisor; |
| 20 | /* uart - usp common */ |
| 21 | u32 sirfsoc_tx_rx_en; |
| 22 | u32 sirfsoc_int_en_reg; |
| 23 | u32 sirfsoc_int_st_reg; |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 24 | u32 sirfsoc_int_en_clr_reg; |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 25 | u32 sirfsoc_tx_dma_io_ctrl; |
| 26 | u32 sirfsoc_tx_dma_io_len; |
| 27 | u32 sirfsoc_tx_fifo_ctrl; |
| 28 | u32 sirfsoc_tx_fifo_level_chk; |
| 29 | u32 sirfsoc_tx_fifo_op; |
| 30 | u32 sirfsoc_tx_fifo_status; |
| 31 | u32 sirfsoc_tx_fifo_data; |
| 32 | u32 sirfsoc_rx_dma_io_ctrl; |
| 33 | u32 sirfsoc_rx_dma_io_len; |
| 34 | u32 sirfsoc_rx_fifo_ctrl; |
| 35 | u32 sirfsoc_rx_fifo_level_chk; |
| 36 | u32 sirfsoc_rx_fifo_op; |
| 37 | u32 sirfsoc_rx_fifo_status; |
| 38 | u32 sirfsoc_rx_fifo_data; |
| 39 | u32 sirfsoc_afc_ctrl; |
| 40 | u32 sirfsoc_swh_dma_io; |
| 41 | /* hardware usp specific */ |
| 42 | u32 sirfsoc_mode1; |
| 43 | u32 sirfsoc_mode2; |
| 44 | u32 sirfsoc_tx_frame_ctrl; |
| 45 | u32 sirfsoc_rx_frame_ctrl; |
| 46 | u32 sirfsoc_async_param_reg; |
| 47 | }; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 48 | |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 49 | typedef u32 (*fifo_full_mask)(struct uart_port *port); |
| 50 | typedef u32 (*fifo_empty_mask)(struct uart_port *port); |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 51 | |
| 52 | struct sirfsoc_fifo_status { |
| 53 | fifo_full_mask ff_full; |
| 54 | fifo_empty_mask ff_empty; |
| 55 | }; |
| 56 | |
| 57 | struct sirfsoc_int_en { |
| 58 | u32 sirfsoc_rx_done_en; |
| 59 | u32 sirfsoc_tx_done_en; |
| 60 | u32 sirfsoc_rx_oflow_en; |
| 61 | u32 sirfsoc_tx_allout_en; |
| 62 | u32 sirfsoc_rx_io_dma_en; |
| 63 | u32 sirfsoc_tx_io_dma_en; |
| 64 | u32 sirfsoc_rxfifo_full_en; |
| 65 | u32 sirfsoc_txfifo_empty_en; |
| 66 | u32 sirfsoc_rxfifo_thd_en; |
| 67 | u32 sirfsoc_txfifo_thd_en; |
| 68 | u32 sirfsoc_frm_err_en; |
| 69 | u32 sirfsoc_rxd_brk_en; |
| 70 | u32 sirfsoc_rx_timeout_en; |
| 71 | u32 sirfsoc_parity_err_en; |
| 72 | u32 sirfsoc_cts_en; |
| 73 | u32 sirfsoc_rts_en; |
| 74 | }; |
| 75 | |
| 76 | struct sirfsoc_int_status { |
| 77 | u32 sirfsoc_rx_done; |
| 78 | u32 sirfsoc_tx_done; |
| 79 | u32 sirfsoc_rx_oflow; |
| 80 | u32 sirfsoc_tx_allout; |
| 81 | u32 sirfsoc_rx_io_dma; |
| 82 | u32 sirfsoc_tx_io_dma; |
| 83 | u32 sirfsoc_rxfifo_full; |
| 84 | u32 sirfsoc_txfifo_empty; |
| 85 | u32 sirfsoc_rxfifo_thd; |
| 86 | u32 sirfsoc_txfifo_thd; |
| 87 | u32 sirfsoc_frm_err; |
| 88 | u32 sirfsoc_rxd_brk; |
| 89 | u32 sirfsoc_rx_timeout; |
| 90 | u32 sirfsoc_parity_err; |
| 91 | u32 sirfsoc_cts; |
| 92 | u32 sirfsoc_rts; |
| 93 | }; |
| 94 | |
| 95 | enum sirfsoc_uart_type { |
| 96 | SIRF_REAL_UART, |
| 97 | SIRF_USP_UART, |
| 98 | }; |
| 99 | |
| 100 | struct sirfsoc_uart_register { |
| 101 | struct sirfsoc_register uart_reg; |
| 102 | struct sirfsoc_int_en uart_int_en; |
| 103 | struct sirfsoc_int_status uart_int_st; |
| 104 | struct sirfsoc_fifo_status fifo_status; |
| 105 | struct sirfsoc_uart_param uart_param; |
| 106 | enum sirfsoc_uart_type uart_type; |
| 107 | }; |
| 108 | |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 109 | u32 uart_usp_ff_full_mask(struct uart_port *port) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 110 | { |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 111 | u32 full_bit; |
| 112 | |
| 113 | full_bit = ilog2(port->fifosize); |
| 114 | return (1 << full_bit); |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 115 | } |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 116 | |
| 117 | u32 uart_usp_ff_empty_mask(struct uart_port *port) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 118 | { |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 119 | u32 empty_bit; |
| 120 | |
Qipan Li | 86459b0 | 2015-05-26 09:35:59 +0000 | [diff] [blame] | 121 | empty_bit = ilog2(port->fifosize) + 1; |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 122 | return (1 << empty_bit); |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 123 | } |
| 124 | struct sirfsoc_uart_register sirfsoc_usp = { |
| 125 | .uart_reg = { |
| 126 | .sirfsoc_mode1 = 0x0000, |
| 127 | .sirfsoc_mode2 = 0x0004, |
| 128 | .sirfsoc_tx_frame_ctrl = 0x0008, |
| 129 | .sirfsoc_rx_frame_ctrl = 0x000c, |
| 130 | .sirfsoc_tx_rx_en = 0x0010, |
| 131 | .sirfsoc_int_en_reg = 0x0014, |
| 132 | .sirfsoc_int_st_reg = 0x0018, |
| 133 | .sirfsoc_async_param_reg = 0x0024, |
| 134 | .sirfsoc_tx_dma_io_ctrl = 0x0100, |
| 135 | .sirfsoc_tx_dma_io_len = 0x0104, |
| 136 | .sirfsoc_tx_fifo_ctrl = 0x0108, |
| 137 | .sirfsoc_tx_fifo_level_chk = 0x010c, |
| 138 | .sirfsoc_tx_fifo_op = 0x0110, |
| 139 | .sirfsoc_tx_fifo_status = 0x0114, |
| 140 | .sirfsoc_tx_fifo_data = 0x0118, |
| 141 | .sirfsoc_rx_dma_io_ctrl = 0x0120, |
| 142 | .sirfsoc_rx_dma_io_len = 0x0124, |
| 143 | .sirfsoc_rx_fifo_ctrl = 0x0128, |
| 144 | .sirfsoc_rx_fifo_level_chk = 0x012c, |
| 145 | .sirfsoc_rx_fifo_op = 0x0130, |
| 146 | .sirfsoc_rx_fifo_status = 0x0134, |
| 147 | .sirfsoc_rx_fifo_data = 0x0138, |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 148 | .sirfsoc_int_en_clr_reg = 0x140, |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 149 | }, |
| 150 | .uart_int_en = { |
| 151 | .sirfsoc_rx_done_en = BIT(0), |
| 152 | .sirfsoc_tx_done_en = BIT(1), |
| 153 | .sirfsoc_rx_oflow_en = BIT(2), |
| 154 | .sirfsoc_tx_allout_en = BIT(3), |
| 155 | .sirfsoc_rx_io_dma_en = BIT(4), |
| 156 | .sirfsoc_tx_io_dma_en = BIT(5), |
| 157 | .sirfsoc_rxfifo_full_en = BIT(6), |
| 158 | .sirfsoc_txfifo_empty_en = BIT(7), |
| 159 | .sirfsoc_rxfifo_thd_en = BIT(8), |
| 160 | .sirfsoc_txfifo_thd_en = BIT(9), |
| 161 | .sirfsoc_frm_err_en = BIT(10), |
| 162 | .sirfsoc_rx_timeout_en = BIT(11), |
| 163 | .sirfsoc_rxd_brk_en = BIT(15), |
| 164 | }, |
| 165 | .uart_int_st = { |
| 166 | .sirfsoc_rx_done = BIT(0), |
| 167 | .sirfsoc_tx_done = BIT(1), |
| 168 | .sirfsoc_rx_oflow = BIT(2), |
| 169 | .sirfsoc_tx_allout = BIT(3), |
| 170 | .sirfsoc_rx_io_dma = BIT(4), |
| 171 | .sirfsoc_tx_io_dma = BIT(5), |
| 172 | .sirfsoc_rxfifo_full = BIT(6), |
| 173 | .sirfsoc_txfifo_empty = BIT(7), |
| 174 | .sirfsoc_rxfifo_thd = BIT(8), |
| 175 | .sirfsoc_txfifo_thd = BIT(9), |
| 176 | .sirfsoc_frm_err = BIT(10), |
| 177 | .sirfsoc_rx_timeout = BIT(11), |
| 178 | .sirfsoc_rxd_brk = BIT(15), |
| 179 | }, |
| 180 | .fifo_status = { |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 181 | .ff_full = uart_usp_ff_full_mask, |
| 182 | .ff_empty = uart_usp_ff_empty_mask, |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 183 | }, |
| 184 | .uart_param = { |
| 185 | .uart_name = "ttySiRF", |
| 186 | .port_name = "sirfsoc-uart", |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 187 | }, |
| 188 | }; |
| 189 | |
| 190 | struct sirfsoc_uart_register sirfsoc_uart = { |
| 191 | .uart_reg = { |
| 192 | .sirfsoc_line_ctrl = 0x0040, |
| 193 | .sirfsoc_tx_rx_en = 0x004c, |
| 194 | .sirfsoc_divisor = 0x0050, |
| 195 | .sirfsoc_int_en_reg = 0x0054, |
| 196 | .sirfsoc_int_st_reg = 0x0058, |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 197 | .sirfsoc_int_en_clr_reg = 0x0060, |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 198 | .sirfsoc_tx_dma_io_ctrl = 0x0100, |
| 199 | .sirfsoc_tx_dma_io_len = 0x0104, |
| 200 | .sirfsoc_tx_fifo_ctrl = 0x0108, |
| 201 | .sirfsoc_tx_fifo_level_chk = 0x010c, |
| 202 | .sirfsoc_tx_fifo_op = 0x0110, |
| 203 | .sirfsoc_tx_fifo_status = 0x0114, |
| 204 | .sirfsoc_tx_fifo_data = 0x0118, |
| 205 | .sirfsoc_rx_dma_io_ctrl = 0x0120, |
| 206 | .sirfsoc_rx_dma_io_len = 0x0124, |
| 207 | .sirfsoc_rx_fifo_ctrl = 0x0128, |
| 208 | .sirfsoc_rx_fifo_level_chk = 0x012c, |
| 209 | .sirfsoc_rx_fifo_op = 0x0130, |
| 210 | .sirfsoc_rx_fifo_status = 0x0134, |
| 211 | .sirfsoc_rx_fifo_data = 0x0138, |
| 212 | .sirfsoc_afc_ctrl = 0x0140, |
| 213 | .sirfsoc_swh_dma_io = 0x0148, |
| 214 | }, |
| 215 | .uart_int_en = { |
| 216 | .sirfsoc_rx_done_en = BIT(0), |
| 217 | .sirfsoc_tx_done_en = BIT(1), |
| 218 | .sirfsoc_rx_oflow_en = BIT(2), |
| 219 | .sirfsoc_tx_allout_en = BIT(3), |
| 220 | .sirfsoc_rx_io_dma_en = BIT(4), |
| 221 | .sirfsoc_tx_io_dma_en = BIT(5), |
| 222 | .sirfsoc_rxfifo_full_en = BIT(6), |
| 223 | .sirfsoc_txfifo_empty_en = BIT(7), |
| 224 | .sirfsoc_rxfifo_thd_en = BIT(8), |
| 225 | .sirfsoc_txfifo_thd_en = BIT(9), |
| 226 | .sirfsoc_frm_err_en = BIT(10), |
| 227 | .sirfsoc_rxd_brk_en = BIT(11), |
| 228 | .sirfsoc_rx_timeout_en = BIT(12), |
| 229 | .sirfsoc_parity_err_en = BIT(13), |
| 230 | .sirfsoc_cts_en = BIT(14), |
| 231 | .sirfsoc_rts_en = BIT(15), |
| 232 | }, |
| 233 | .uart_int_st = { |
| 234 | .sirfsoc_rx_done = BIT(0), |
| 235 | .sirfsoc_tx_done = BIT(1), |
| 236 | .sirfsoc_rx_oflow = BIT(2), |
| 237 | .sirfsoc_tx_allout = BIT(3), |
| 238 | .sirfsoc_rx_io_dma = BIT(4), |
| 239 | .sirfsoc_tx_io_dma = BIT(5), |
| 240 | .sirfsoc_rxfifo_full = BIT(6), |
| 241 | .sirfsoc_txfifo_empty = BIT(7), |
| 242 | .sirfsoc_rxfifo_thd = BIT(8), |
| 243 | .sirfsoc_txfifo_thd = BIT(9), |
| 244 | .sirfsoc_frm_err = BIT(10), |
| 245 | .sirfsoc_rxd_brk = BIT(11), |
| 246 | .sirfsoc_rx_timeout = BIT(12), |
| 247 | .sirfsoc_parity_err = BIT(13), |
| 248 | .sirfsoc_cts = BIT(14), |
| 249 | .sirfsoc_rts = BIT(15), |
| 250 | }, |
| 251 | .fifo_status = { |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 252 | .ff_full = uart_usp_ff_full_mask, |
| 253 | .ff_empty = uart_usp_ff_empty_mask, |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 254 | }, |
| 255 | .uart_param = { |
| 256 | .uart_name = "ttySiRF", |
| 257 | .port_name = "sirfsoc_uart", |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 258 | }, |
| 259 | }; |
| 260 | /* uart io ctrl */ |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 261 | #define SIRFUART_DATA_BIT_LEN_MASK 0x3 |
| 262 | #define SIRFUART_DATA_BIT_LEN_5 BIT(0) |
| 263 | #define SIRFUART_DATA_BIT_LEN_6 1 |
| 264 | #define SIRFUART_DATA_BIT_LEN_7 2 |
| 265 | #define SIRFUART_DATA_BIT_LEN_8 3 |
| 266 | #define SIRFUART_STOP_BIT_LEN_1 0 |
| 267 | #define SIRFUART_STOP_BIT_LEN_2 BIT(2) |
| 268 | #define SIRFUART_PARITY_EN BIT(3) |
| 269 | #define SIRFUART_EVEN_BIT BIT(4) |
| 270 | #define SIRFUART_STICK_BIT_MASK (7 << 3) |
| 271 | #define SIRFUART_STICK_BIT_NONE (0 << 3) |
| 272 | #define SIRFUART_STICK_BIT_EVEN BIT(3) |
| 273 | #define SIRFUART_STICK_BIT_ODD (3 << 3) |
| 274 | #define SIRFUART_STICK_BIT_MARK (5 << 3) |
| 275 | #define SIRFUART_STICK_BIT_SPACE (7 << 3) |
| 276 | #define SIRFUART_SET_BREAK BIT(6) |
| 277 | #define SIRFUART_LOOP_BACK BIT(7) |
| 278 | #define SIRFUART_PARITY_MASK (7 << 3) |
| 279 | #define SIRFUART_DUMMY_READ BIT(16) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 280 | #define SIRFUART_AFC_CTRL_RX_THD 0x70 |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 281 | #define SIRFUART_AFC_RX_EN BIT(8) |
| 282 | #define SIRFUART_AFC_TX_EN BIT(9) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 283 | #define SIRFUART_AFC_CTS_CTRL BIT(10) |
| 284 | #define SIRFUART_AFC_RTS_CTRL BIT(11) |
| 285 | #define SIRFUART_AFC_CTS_STATUS BIT(12) |
| 286 | #define SIRFUART_AFC_RTS_STATUS BIT(13) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 287 | /* UART FIFO Register */ |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 288 | #define SIRFUART_FIFO_STOP 0x0 |
| 289 | #define SIRFUART_FIFO_RESET BIT(0) |
| 290 | #define SIRFUART_FIFO_START BIT(1) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 291 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 292 | #define SIRFUART_RX_EN BIT(0) |
| 293 | #define SIRFUART_TX_EN BIT(1) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 294 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 295 | #define SIRFUART_IO_MODE BIT(0) |
| 296 | #define SIRFUART_DMA_MODE 0x0 |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 297 | #define SIRFUART_RX_DMA_FLUSH 0x4 |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 298 | |
Qipan Li | 1d26c9f | 2015-07-14 00:52:22 +0000 | [diff] [blame] | 299 | #define SIRFUART_CLEAR_RX_ADDR_EN 0x2 |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 300 | /* Baud Rate Calculation */ |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 301 | #define SIRF_USP_MIN_SAMPLE_DIV 0x1 |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 302 | #define SIRF_MIN_SAMPLE_DIV 0xf |
| 303 | #define SIRF_MAX_SAMPLE_DIV 0x3f |
| 304 | #define SIRF_IOCLK_DIV_MAX 0xffff |
| 305 | #define SIRF_SAMPLE_DIV_SHIFT 16 |
| 306 | #define SIRF_IOCLK_DIV_MASK 0xffff |
| 307 | #define SIRF_SAMPLE_DIV_MASK 0x3f0000 |
| 308 | #define SIRF_BAUD_RATE_SUPPORT_NR 18 |
| 309 | |
| 310 | /* USP SPEC */ |
| 311 | #define SIRFSOC_USP_ENDIAN_CTRL_LSBF BIT(4) |
| 312 | #define SIRFSOC_USP_EN BIT(5) |
Qipan Li | 459f15c | 2013-08-25 20:18:40 +0800 | [diff] [blame] | 313 | #define SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET 0 |
| 314 | #define SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET 8 |
| 315 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK 0x3ff |
| 316 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET 21 |
| 317 | #define SIRFSOC_USP_TX_DATA_LEN_OFFSET 0 |
| 318 | #define SIRFSOC_USP_TX_SYNC_LEN_OFFSET 8 |
| 319 | #define SIRFSOC_USP_TX_FRAME_LEN_OFFSET 16 |
| 320 | #define SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET 24 |
| 321 | #define SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET 30 |
| 322 | #define SIRFSOC_USP_RX_DATA_LEN_OFFSET 0 |
| 323 | #define SIRFSOC_USP_RX_FRAME_LEN_OFFSET 8 |
| 324 | #define SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET 16 |
| 325 | #define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET 24 |
| 326 | #define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f |
| 327 | #define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16 |
Qipan Li | 7f60f2f | 2015-05-14 06:45:25 +0000 | [diff] [blame] | 328 | #define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2) |
Qipan Li | 1d26c9f | 2015-07-14 00:52:22 +0000 | [diff] [blame] | 329 | #define SIRFSOC_USP_FRADDR_CLR_EN BIT(1) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 330 | /* USP-UART Common */ |
| 331 | #define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000) |
| 332 | #define SIRFUART_RECV_TIMEOUT_VALUE(x) \ |
| 333 | (((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF)) |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 334 | #define SIRFUART_USP_RECV_TIMEOUT(x) (x & 0xFFFF) |
| 335 | #define SIRFUART_UART_RECV_TIMEOUT(x) ((x & 0xFFFF) << 16) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 336 | |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 337 | #define SIRFUART_FIFO_THD(port) (port->fifosize >> 1) |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 338 | #define SIRFUART_ERR_INT_STAT(unit_st, uart_type) \ |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 339 | (uint_st->sirfsoc_rx_oflow | \ |
| 340 | uint_st->sirfsoc_frm_err | \ |
| 341 | uint_st->sirfsoc_rxd_brk | \ |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 342 | ((uart_type != SIRF_REAL_UART) ? \ |
| 343 | 0 : uint_st->sirfsoc_parity_err)) |
| 344 | #define SIRFUART_RX_IO_INT_EN(uint_en, uart_type) \ |
| 345 | (uint_en->sirfsoc_rx_done_en |\ |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 346 | uint_en->sirfsoc_rxfifo_thd_en |\ |
| 347 | uint_en->sirfsoc_rxfifo_full_en |\ |
| 348 | uint_en->sirfsoc_frm_err_en |\ |
| 349 | uint_en->sirfsoc_rx_oflow_en |\ |
| 350 | uint_en->sirfsoc_rxd_brk_en |\ |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 351 | ((uart_type != SIRF_REAL_UART) ? \ |
| 352 | 0 : uint_en->sirfsoc_parity_err_en)) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 353 | #define SIRFUART_RX_IO_INT_ST(uint_st) \ |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 354 | (uint_st->sirfsoc_rxfifo_thd |\ |
| 355 | uint_st->sirfsoc_rxfifo_full|\ |
| 356 | uint_st->sirfsoc_rx_done |\ |
| 357 | uint_st->sirfsoc_rx_timeout) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 358 | #define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts) |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 359 | #define SIRFUART_RX_DMA_INT_EN(uint_en, uart_type) \ |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 360 | (uint_en->sirfsoc_frm_err_en |\ |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 361 | uint_en->sirfsoc_rx_oflow_en |\ |
| 362 | uint_en->sirfsoc_rxd_brk_en |\ |
Qipan Li | c1b7ac6 | 2015-05-14 06:45:21 +0000 | [diff] [blame] | 363 | ((uart_type != SIRF_REAL_UART) ? \ |
| 364 | 0 : uint_en->sirfsoc_parity_err_en)) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 365 | /* Generic Definitions */ |
| 366 | #define SIRFSOC_UART_NAME "ttySiRF" |
| 367 | #define SIRFSOC_UART_MAJOR 0 |
| 368 | #define SIRFSOC_UART_MINOR 0 |
| 369 | #define SIRFUART_PORT_NAME "sirfsoc-uart" |
| 370 | #define SIRFUART_MAP_SIZE 0x200 |
Qipan Li | a6ffe89 | 2015-04-29 06:45:08 +0000 | [diff] [blame] | 371 | #define SIRFSOC_UART_NR 11 |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 372 | #define SIRFSOC_PORT_TYPE 0xa5 |
| 373 | |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 374 | /* Uart Common Use Macro*/ |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 375 | #define SIRFSOC_RX_DMA_BUF_SIZE (1024 * 32) |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 376 | #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 377 | /* Uart Fifo Level Chk */ |
| 378 | #define SIRFUART_TX_FIFO_SC_OFFSET 0 |
| 379 | #define SIRFUART_TX_FIFO_LC_OFFSET 10 |
| 380 | #define SIRFUART_TX_FIFO_HC_OFFSET 20 |
| 381 | #define SIRFUART_TX_FIFO_CHK_SC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 382 | (value & 0x1f)) << SIRFUART_TX_FIFO_SC_OFFSET) |
| 383 | #define SIRFUART_TX_FIFO_CHK_LC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 384 | (value & 0x1f)) << SIRFUART_TX_FIFO_LC_OFFSET) |
| 385 | #define SIRFUART_TX_FIFO_CHK_HC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 386 | (value & 0x1f)) << SIRFUART_TX_FIFO_HC_OFFSET) |
| 387 | |
| 388 | #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC |
| 389 | #define SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC |
| 390 | #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 391 | #define SIRFUART_RX_FIFO_MASK 0x7f |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 392 | /* Indicate how many buffers used */ |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 393 | |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 394 | /* For Fast Baud Rate Calculation */ |
| 395 | struct sirfsoc_baudrate_to_regv { |
| 396 | unsigned int baud_rate; |
| 397 | unsigned int reg_val; |
| 398 | }; |
| 399 | |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 400 | enum sirfsoc_tx_state { |
| 401 | TX_DMA_IDLE, |
| 402 | TX_DMA_RUNNING, |
| 403 | TX_DMA_PAUSE, |
| 404 | }; |
| 405 | |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 406 | struct sirfsoc_rx_buffer { |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 407 | struct circ_buf xmit; |
| 408 | dma_cookie_t cookie; |
| 409 | struct dma_async_tx_descriptor *desc; |
| 410 | dma_addr_t dma_addr; |
| 411 | }; |
| 412 | |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 413 | struct sirfsoc_uart_port { |
Qipan Li | 2eb5618 | 2013-08-15 06:52:15 +0800 | [diff] [blame] | 414 | bool hw_flow_ctrl; |
| 415 | bool ms_enabled; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 416 | |
| 417 | struct uart_port port; |
Barry Song | ac4ce71 | 2013-01-16 14:49:27 +0800 | [diff] [blame] | 418 | struct clk *clk; |
Barry Song | 057badd | 2015-01-03 17:02:57 +0800 | [diff] [blame] | 419 | /* for SiRFatlas7, there are SET/CLR for UART_INT_EN */ |
| 420 | bool is_atlas7; |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 421 | struct sirfsoc_uart_register *uart_reg; |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 422 | struct dma_chan *rx_dma_chan; |
| 423 | struct dma_chan *tx_dma_chan; |
| 424 | dma_addr_t tx_dma_addr; |
| 425 | struct dma_async_tx_descriptor *tx_dma_desc; |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 426 | unsigned long transfer_size; |
| 427 | enum sirfsoc_tx_state tx_dma_state; |
Qipan Li | 2eb5618 | 2013-08-15 06:52:15 +0800 | [diff] [blame] | 428 | unsigned int cts_gpio; |
| 429 | unsigned int rts_gpio; |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 430 | |
Qipan Li | 0f17e3b | 2015-05-26 09:36:00 +0000 | [diff] [blame] | 431 | struct sirfsoc_rx_buffer rx_dma_items; |
| 432 | struct hrtimer hrt; |
| 433 | bool is_hrt_enabled; |
| 434 | unsigned long rx_period_time; |
Qipan Li | 1d26c9f | 2015-07-14 00:52:22 +0000 | [diff] [blame] | 435 | unsigned long rx_last_pos; |
| 436 | unsigned long pio_fetch_cnt; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 437 | }; |
| 438 | |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 439 | /* Register Access Control */ |
| 440 | #define portaddr(port, reg) ((port)->membase + (reg)) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 441 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 442 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) |
| 443 | |
| 444 | /* UART Port Mask */ |
Qipan Li | cb4595a | 2015-04-29 06:45:09 +0000 | [diff] [blame] | 445 | #define SIRFUART_FIFOLEVEL_MASK(port) ((port->fifosize - 1) & 0xFFF) |
| 446 | #define SIRFUART_FIFOFULL_MASK(port) (port->fifosize & 0xFFF) |
| 447 | #define SIRFUART_FIFOEMPTY_MASK(port) ((port->fifosize & 0xFFF) << 1) |