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 | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 9 | struct sirfsoc_uart_param { |
| 10 | const char *uart_name; |
| 11 | const char *port_name; |
| 12 | u32 uart_nr; |
| 13 | u32 register_uart_nr; |
| 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; |
| 24 | u32 sirfsoc_tx_dma_io_ctrl; |
| 25 | u32 sirfsoc_tx_dma_io_len; |
| 26 | u32 sirfsoc_tx_fifo_ctrl; |
| 27 | u32 sirfsoc_tx_fifo_level_chk; |
| 28 | u32 sirfsoc_tx_fifo_op; |
| 29 | u32 sirfsoc_tx_fifo_status; |
| 30 | u32 sirfsoc_tx_fifo_data; |
| 31 | u32 sirfsoc_rx_dma_io_ctrl; |
| 32 | u32 sirfsoc_rx_dma_io_len; |
| 33 | u32 sirfsoc_rx_fifo_ctrl; |
| 34 | u32 sirfsoc_rx_fifo_level_chk; |
| 35 | u32 sirfsoc_rx_fifo_op; |
| 36 | u32 sirfsoc_rx_fifo_status; |
| 37 | u32 sirfsoc_rx_fifo_data; |
| 38 | u32 sirfsoc_afc_ctrl; |
| 39 | u32 sirfsoc_swh_dma_io; |
| 40 | /* hardware usp specific */ |
| 41 | u32 sirfsoc_mode1; |
| 42 | u32 sirfsoc_mode2; |
| 43 | u32 sirfsoc_tx_frame_ctrl; |
| 44 | u32 sirfsoc_rx_frame_ctrl; |
| 45 | u32 sirfsoc_async_param_reg; |
| 46 | }; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 47 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 48 | typedef u32 (*fifo_full_mask)(int line); |
| 49 | typedef u32 (*fifo_empty_mask)(int line); |
| 50 | |
| 51 | struct sirfsoc_fifo_status { |
| 52 | fifo_full_mask ff_full; |
| 53 | fifo_empty_mask ff_empty; |
| 54 | }; |
| 55 | |
| 56 | struct sirfsoc_int_en { |
| 57 | u32 sirfsoc_rx_done_en; |
| 58 | u32 sirfsoc_tx_done_en; |
| 59 | u32 sirfsoc_rx_oflow_en; |
| 60 | u32 sirfsoc_tx_allout_en; |
| 61 | u32 sirfsoc_rx_io_dma_en; |
| 62 | u32 sirfsoc_tx_io_dma_en; |
| 63 | u32 sirfsoc_rxfifo_full_en; |
| 64 | u32 sirfsoc_txfifo_empty_en; |
| 65 | u32 sirfsoc_rxfifo_thd_en; |
| 66 | u32 sirfsoc_txfifo_thd_en; |
| 67 | u32 sirfsoc_frm_err_en; |
| 68 | u32 sirfsoc_rxd_brk_en; |
| 69 | u32 sirfsoc_rx_timeout_en; |
| 70 | u32 sirfsoc_parity_err_en; |
| 71 | u32 sirfsoc_cts_en; |
| 72 | u32 sirfsoc_rts_en; |
| 73 | }; |
| 74 | |
| 75 | struct sirfsoc_int_status { |
| 76 | u32 sirfsoc_rx_done; |
| 77 | u32 sirfsoc_tx_done; |
| 78 | u32 sirfsoc_rx_oflow; |
| 79 | u32 sirfsoc_tx_allout; |
| 80 | u32 sirfsoc_rx_io_dma; |
| 81 | u32 sirfsoc_tx_io_dma; |
| 82 | u32 sirfsoc_rxfifo_full; |
| 83 | u32 sirfsoc_txfifo_empty; |
| 84 | u32 sirfsoc_rxfifo_thd; |
| 85 | u32 sirfsoc_txfifo_thd; |
| 86 | u32 sirfsoc_frm_err; |
| 87 | u32 sirfsoc_rxd_brk; |
| 88 | u32 sirfsoc_rx_timeout; |
| 89 | u32 sirfsoc_parity_err; |
| 90 | u32 sirfsoc_cts; |
| 91 | u32 sirfsoc_rts; |
| 92 | }; |
| 93 | |
| 94 | enum sirfsoc_uart_type { |
| 95 | SIRF_REAL_UART, |
| 96 | SIRF_USP_UART, |
| 97 | }; |
| 98 | |
| 99 | struct sirfsoc_uart_register { |
| 100 | struct sirfsoc_register uart_reg; |
| 101 | struct sirfsoc_int_en uart_int_en; |
| 102 | struct sirfsoc_int_status uart_int_st; |
| 103 | struct sirfsoc_fifo_status fifo_status; |
| 104 | struct sirfsoc_uart_param uart_param; |
| 105 | enum sirfsoc_uart_type uart_type; |
| 106 | }; |
| 107 | |
| 108 | u32 usp_ff_full(int line) |
| 109 | { |
| 110 | return 0x80; |
| 111 | } |
| 112 | u32 usp_ff_empty(int line) |
| 113 | { |
| 114 | return 0x100; |
| 115 | } |
| 116 | u32 uart_ff_full(int line) |
| 117 | { |
| 118 | return (line == 1) ? (0x20) : (0x80); |
| 119 | } |
| 120 | u32 uart_ff_empty(int line) |
| 121 | { |
| 122 | return (line == 1) ? (0x40) : (0x100); |
| 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, |
| 148 | }, |
| 149 | .uart_int_en = { |
| 150 | .sirfsoc_rx_done_en = BIT(0), |
| 151 | .sirfsoc_tx_done_en = BIT(1), |
| 152 | .sirfsoc_rx_oflow_en = BIT(2), |
| 153 | .sirfsoc_tx_allout_en = BIT(3), |
| 154 | .sirfsoc_rx_io_dma_en = BIT(4), |
| 155 | .sirfsoc_tx_io_dma_en = BIT(5), |
| 156 | .sirfsoc_rxfifo_full_en = BIT(6), |
| 157 | .sirfsoc_txfifo_empty_en = BIT(7), |
| 158 | .sirfsoc_rxfifo_thd_en = BIT(8), |
| 159 | .sirfsoc_txfifo_thd_en = BIT(9), |
| 160 | .sirfsoc_frm_err_en = BIT(10), |
| 161 | .sirfsoc_rx_timeout_en = BIT(11), |
| 162 | .sirfsoc_rxd_brk_en = BIT(15), |
| 163 | }, |
| 164 | .uart_int_st = { |
| 165 | .sirfsoc_rx_done = BIT(0), |
| 166 | .sirfsoc_tx_done = BIT(1), |
| 167 | .sirfsoc_rx_oflow = BIT(2), |
| 168 | .sirfsoc_tx_allout = BIT(3), |
| 169 | .sirfsoc_rx_io_dma = BIT(4), |
| 170 | .sirfsoc_tx_io_dma = BIT(5), |
| 171 | .sirfsoc_rxfifo_full = BIT(6), |
| 172 | .sirfsoc_txfifo_empty = BIT(7), |
| 173 | .sirfsoc_rxfifo_thd = BIT(8), |
| 174 | .sirfsoc_txfifo_thd = BIT(9), |
| 175 | .sirfsoc_frm_err = BIT(10), |
| 176 | .sirfsoc_rx_timeout = BIT(11), |
| 177 | .sirfsoc_rxd_brk = BIT(15), |
| 178 | }, |
| 179 | .fifo_status = { |
| 180 | .ff_full = usp_ff_full, |
| 181 | .ff_empty = usp_ff_empty, |
| 182 | }, |
| 183 | .uart_param = { |
| 184 | .uart_name = "ttySiRF", |
| 185 | .port_name = "sirfsoc-uart", |
| 186 | .uart_nr = 2, |
| 187 | .register_uart_nr = 3, |
| 188 | }, |
| 189 | }; |
| 190 | |
| 191 | struct sirfsoc_uart_register sirfsoc_uart = { |
| 192 | .uart_reg = { |
| 193 | .sirfsoc_line_ctrl = 0x0040, |
| 194 | .sirfsoc_tx_rx_en = 0x004c, |
| 195 | .sirfsoc_divisor = 0x0050, |
| 196 | .sirfsoc_int_en_reg = 0x0054, |
| 197 | .sirfsoc_int_st_reg = 0x0058, |
| 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 = { |
| 252 | .ff_full = uart_ff_full, |
| 253 | .ff_empty = uart_ff_empty, |
| 254 | }, |
| 255 | .uart_param = { |
| 256 | .uart_name = "ttySiRF", |
| 257 | .port_name = "sirfsoc_uart", |
| 258 | .uart_nr = 3, |
| 259 | .register_uart_nr = 0, |
| 260 | }, |
| 261 | }; |
| 262 | /* uart io ctrl */ |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 263 | #define SIRFUART_DATA_BIT_LEN_MASK 0x3 |
| 264 | #define SIRFUART_DATA_BIT_LEN_5 BIT(0) |
| 265 | #define SIRFUART_DATA_BIT_LEN_6 1 |
| 266 | #define SIRFUART_DATA_BIT_LEN_7 2 |
| 267 | #define SIRFUART_DATA_BIT_LEN_8 3 |
| 268 | #define SIRFUART_STOP_BIT_LEN_1 0 |
| 269 | #define SIRFUART_STOP_BIT_LEN_2 BIT(2) |
| 270 | #define SIRFUART_PARITY_EN BIT(3) |
| 271 | #define SIRFUART_EVEN_BIT BIT(4) |
| 272 | #define SIRFUART_STICK_BIT_MASK (7 << 3) |
| 273 | #define SIRFUART_STICK_BIT_NONE (0 << 3) |
| 274 | #define SIRFUART_STICK_BIT_EVEN BIT(3) |
| 275 | #define SIRFUART_STICK_BIT_ODD (3 << 3) |
| 276 | #define SIRFUART_STICK_BIT_MARK (5 << 3) |
| 277 | #define SIRFUART_STICK_BIT_SPACE (7 << 3) |
| 278 | #define SIRFUART_SET_BREAK BIT(6) |
| 279 | #define SIRFUART_LOOP_BACK BIT(7) |
| 280 | #define SIRFUART_PARITY_MASK (7 << 3) |
| 281 | #define SIRFUART_DUMMY_READ BIT(16) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 282 | #define SIRFUART_AFC_CTRL_RX_THD 0x70 |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 283 | #define SIRFUART_AFC_RX_EN BIT(8) |
| 284 | #define SIRFUART_AFC_TX_EN BIT(9) |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 285 | #define SIRFUART_AFC_CTS_CTRL BIT(10) |
| 286 | #define SIRFUART_AFC_RTS_CTRL BIT(11) |
| 287 | #define SIRFUART_AFC_CTS_STATUS BIT(12) |
| 288 | #define SIRFUART_AFC_RTS_STATUS BIT(13) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 289 | /* UART FIFO Register */ |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 290 | #define SIRFUART_FIFO_STOP 0x0 |
| 291 | #define SIRFUART_FIFO_RESET BIT(0) |
| 292 | #define SIRFUART_FIFO_START BIT(1) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 293 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 294 | #define SIRFUART_RX_EN BIT(0) |
| 295 | #define SIRFUART_TX_EN BIT(1) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 296 | |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 297 | #define SIRFUART_IO_MODE BIT(0) |
| 298 | #define SIRFUART_DMA_MODE 0x0 |
| 299 | |
| 300 | /* Macro Specific*/ |
| 301 | #define SIRFUART_INT_EN_CLR 0x0060 |
| 302 | /* Baud Rate Calculation */ |
| 303 | #define SIRF_MIN_SAMPLE_DIV 0xf |
| 304 | #define SIRF_MAX_SAMPLE_DIV 0x3f |
| 305 | #define SIRF_IOCLK_DIV_MAX 0xffff |
| 306 | #define SIRF_SAMPLE_DIV_SHIFT 16 |
| 307 | #define SIRF_IOCLK_DIV_MASK 0xffff |
| 308 | #define SIRF_SAMPLE_DIV_MASK 0x3f0000 |
| 309 | #define SIRF_BAUD_RATE_SUPPORT_NR 18 |
| 310 | |
| 311 | /* USP SPEC */ |
| 312 | #define SIRFSOC_USP_ENDIAN_CTRL_LSBF BIT(4) |
| 313 | #define SIRFSOC_USP_EN BIT(5) |
Qipan Li | 459f15c | 2013-08-25 20:18:40 +0800 | [diff] [blame] | 314 | #define SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET 0 |
| 315 | #define SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET 8 |
| 316 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK 0x3ff |
| 317 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET 21 |
| 318 | #define SIRFSOC_USP_TX_DATA_LEN_OFFSET 0 |
| 319 | #define SIRFSOC_USP_TX_SYNC_LEN_OFFSET 8 |
| 320 | #define SIRFSOC_USP_TX_FRAME_LEN_OFFSET 16 |
| 321 | #define SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET 24 |
| 322 | #define SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET 30 |
| 323 | #define SIRFSOC_USP_RX_DATA_LEN_OFFSET 0 |
| 324 | #define SIRFSOC_USP_RX_FRAME_LEN_OFFSET 8 |
| 325 | #define SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET 16 |
| 326 | #define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET 24 |
| 327 | #define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f |
| 328 | #define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16 |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 329 | |
| 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)) |
| 334 | #define SIRFUART_RECV_TIMEOUT(port, x) \ |
| 335 | (((port)->line > 2) ? (x & 0xFFFF) : ((x) & 0xFFFF) << 16) |
| 336 | |
| 337 | #define SIRFUART_FIFO_THD(port) ((port->line) == 1 ? 16 : 64) |
| 338 | #define SIRFUART_ERR_INT_STAT(port, unit_st) \ |
| 339 | (uint_st->sirfsoc_rx_oflow | \ |
| 340 | uint_st->sirfsoc_frm_err | \ |
| 341 | uint_st->sirfsoc_rxd_brk | \ |
| 342 | ((port->line > 2) ? 0 : uint_st->sirfsoc_parity_err)) |
| 343 | #define SIRFUART_RX_IO_INT_EN(port, uint_en) \ |
| 344 | (uint_en->sirfsoc_rx_timeout_en |\ |
| 345 | uint_en->sirfsoc_rxfifo_thd_en |\ |
| 346 | uint_en->sirfsoc_rxfifo_full_en |\ |
| 347 | uint_en->sirfsoc_frm_err_en |\ |
| 348 | uint_en->sirfsoc_rx_oflow_en |\ |
| 349 | uint_en->sirfsoc_rxd_brk_en |\ |
| 350 | ((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en)) |
| 351 | #define SIRFUART_RX_IO_INT_ST(uint_st) \ |
| 352 | (uint_st->sirfsoc_rx_timeout |\ |
| 353 | uint_st->sirfsoc_rxfifo_thd |\ |
| 354 | uint_st->sirfsoc_rxfifo_full) |
| 355 | #define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts) |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 356 | #define SIRFUART_RX_DMA_INT_EN(port, uint_en) \ |
| 357 | (uint_en->sirfsoc_rx_timeout_en |\ |
| 358 | uint_en->sirfsoc_frm_err_en |\ |
| 359 | uint_en->sirfsoc_rx_oflow_en |\ |
| 360 | uint_en->sirfsoc_rxd_brk_en |\ |
| 361 | ((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en)) |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 362 | /* Generic Definitions */ |
| 363 | #define SIRFSOC_UART_NAME "ttySiRF" |
| 364 | #define SIRFSOC_UART_MAJOR 0 |
| 365 | #define SIRFSOC_UART_MINOR 0 |
| 366 | #define SIRFUART_PORT_NAME "sirfsoc-uart" |
| 367 | #define SIRFUART_MAP_SIZE 0x200 |
Qipan Li | b60dfba | 2013-08-25 20:18:41 +0800 | [diff] [blame] | 368 | #define SIRFSOC_UART_NR 6 |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 369 | #define SIRFSOC_PORT_TYPE 0xa5 |
| 370 | |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 371 | /* Uart Common Use Macro*/ |
| 372 | #define SIRFSOC_RX_DMA_BUF_SIZE 256 |
| 373 | #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) |
| 374 | #define LOOP_DMA_BUFA_FILL 1 |
| 375 | #define LOOP_DMA_BUFB_FILL 2 |
| 376 | #define TX_TRAN_PIO 1 |
| 377 | #define TX_TRAN_DMA 2 |
| 378 | /* Uart Fifo Level Chk */ |
| 379 | #define SIRFUART_TX_FIFO_SC_OFFSET 0 |
| 380 | #define SIRFUART_TX_FIFO_LC_OFFSET 10 |
| 381 | #define SIRFUART_TX_FIFO_HC_OFFSET 20 |
| 382 | #define SIRFUART_TX_FIFO_CHK_SC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 383 | (value & 0x1f)) << SIRFUART_TX_FIFO_SC_OFFSET) |
| 384 | #define SIRFUART_TX_FIFO_CHK_LC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 385 | (value & 0x1f)) << SIRFUART_TX_FIFO_LC_OFFSET) |
| 386 | #define SIRFUART_TX_FIFO_CHK_HC(line, value) ((((line) == 1) ? (value & 0x3) :\ |
| 387 | (value & 0x1f)) << SIRFUART_TX_FIFO_HC_OFFSET) |
| 388 | |
| 389 | #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC |
| 390 | #define SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC |
| 391 | #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC |
| 392 | /* Indicate how many buffers used */ |
| 393 | #define SIRFSOC_RX_LOOP_BUF_CNT 2 |
| 394 | |
| 395 | /* Indicate if DMA channel valid */ |
| 396 | #define IS_DMA_CHAN_VALID(x) ((x) != -1) |
| 397 | #define UNVALID_DMA_CHAN -1 |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 398 | /* For Fast Baud Rate Calculation */ |
| 399 | struct sirfsoc_baudrate_to_regv { |
| 400 | unsigned int baud_rate; |
| 401 | unsigned int reg_val; |
| 402 | }; |
| 403 | |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 404 | enum sirfsoc_tx_state { |
| 405 | TX_DMA_IDLE, |
| 406 | TX_DMA_RUNNING, |
| 407 | TX_DMA_PAUSE, |
| 408 | }; |
| 409 | |
| 410 | struct sirfsoc_loop_buffer { |
| 411 | struct circ_buf xmit; |
| 412 | dma_cookie_t cookie; |
| 413 | struct dma_async_tx_descriptor *desc; |
| 414 | dma_addr_t dma_addr; |
| 415 | }; |
| 416 | |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 417 | struct sirfsoc_uart_port { |
Qipan Li | 2eb5618 | 2013-08-15 06:52:15 +0800 | [diff] [blame] | 418 | bool hw_flow_ctrl; |
| 419 | bool ms_enabled; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 420 | |
| 421 | struct uart_port port; |
Barry Song | ac4ce71 | 2013-01-16 14:49:27 +0800 | [diff] [blame] | 422 | struct clk *clk; |
Barry Song | 909102d | 2013-08-07 13:35:38 +0800 | [diff] [blame] | 423 | /* for SiRFmarco, there are SET/CLR for UART_INT_EN */ |
| 424 | bool is_marco; |
Qipan Li | 5df8311 | 2013-08-12 18:15:35 +0800 | [diff] [blame] | 425 | struct sirfsoc_uart_register *uart_reg; |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 426 | int rx_dma_no; |
| 427 | int tx_dma_no; |
| 428 | struct dma_chan *rx_dma_chan; |
| 429 | struct dma_chan *tx_dma_chan; |
| 430 | dma_addr_t tx_dma_addr; |
| 431 | struct dma_async_tx_descriptor *tx_dma_desc; |
| 432 | spinlock_t rx_lock; |
| 433 | spinlock_t tx_lock; |
| 434 | struct tasklet_struct rx_dma_complete_tasklet; |
| 435 | struct tasklet_struct rx_tmo_process_tasklet; |
| 436 | unsigned int rx_io_count; |
| 437 | unsigned long transfer_size; |
| 438 | enum sirfsoc_tx_state tx_dma_state; |
Qipan Li | 2eb5618 | 2013-08-15 06:52:15 +0800 | [diff] [blame] | 439 | unsigned int cts_gpio; |
| 440 | unsigned int rts_gpio; |
Qipan Li | 8316d04 | 2013-08-19 11:47:53 +0800 | [diff] [blame] | 441 | |
| 442 | struct sirfsoc_loop_buffer rx_dma_items[SIRFSOC_RX_LOOP_BUF_CNT]; |
| 443 | int rx_completed; |
| 444 | int rx_issued; |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 445 | }; |
| 446 | |
Rong Wang | 161e773 | 2011-11-17 23:17:04 +0800 | [diff] [blame] | 447 | /* Register Access Control */ |
| 448 | #define portaddr(port, reg) ((port)->membase + (reg)) |
| 449 | #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) |
| 450 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) |
| 451 | #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) |
| 452 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) |
| 453 | |
| 454 | /* UART Port Mask */ |
| 455 | #define SIRFUART_FIFOLEVEL_MASK(port) ((port->line == 1) ? (0x1f) : (0x7f)) |
| 456 | #define SIRFUART_FIFOFULL_MASK(port) ((port->line == 1) ? (0x20) : (0x80)) |
| 457 | #define SIRFUART_FIFOEMPTY_MASK(port) ((port->line == 1) ? (0x40) : (0x100)) |
| 458 | |
| 459 | /* I/O Mode */ |
| 460 | #define SIRFSOC_UART_IO_RX_MAX_CNT 256 |
| 461 | #define SIRFSOC_UART_IO_TX_REASONABLE_CNT 6 |