.. | .. |
---|
20 | 20 | #include <linux/platform_device.h> |
---|
21 | 21 | #include <linux/of.h> |
---|
22 | 22 | #include <linux/of_device.h> |
---|
23 | | -#include <linux/of_gpio.h> |
---|
24 | 23 | #include <linux/dma-mapping.h> |
---|
25 | 24 | #include <linux/dmaengine.h> |
---|
26 | 25 | #include <linux/atmel_pdc.h> |
---|
27 | 26 | #include <linux/uaccess.h> |
---|
28 | 27 | #include <linux/platform_data/atmel.h> |
---|
29 | 28 | #include <linux/timer.h> |
---|
30 | | -#include <linux/gpio.h> |
---|
31 | | -#include <linux/gpio/consumer.h> |
---|
32 | 29 | #include <linux/err.h> |
---|
33 | 30 | #include <linux/irq.h> |
---|
34 | 31 | #include <linux/suspend.h> |
---|
35 | 32 | #include <linux/mm.h> |
---|
36 | 33 | |
---|
| 34 | +#include <asm/div64.h> |
---|
37 | 35 | #include <asm/io.h> |
---|
38 | 36 | #include <asm/ioctls.h> |
---|
39 | 37 | |
---|
.. | .. |
---|
49 | 47 | */ |
---|
50 | 48 | #define ATMEL_RTS_HIGH_OFFSET 16 |
---|
51 | 49 | #define ATMEL_RTS_LOW_OFFSET 20 |
---|
52 | | - |
---|
53 | | -#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
---|
54 | | -#define SUPPORT_SYSRQ |
---|
55 | | -#endif |
---|
56 | 50 | |
---|
57 | 51 | #include <linux/serial_core.h> |
---|
58 | 52 | |
---|
.. | .. |
---|
147 | 141 | struct circ_buf rx_ring; |
---|
148 | 142 | |
---|
149 | 143 | struct mctrl_gpios *gpios; |
---|
| 144 | + u32 backup_mode; /* MR saved during iso7816 operations */ |
---|
| 145 | + u32 backup_brgr; /* BRGR saved during iso7816 operations */ |
---|
150 | 146 | unsigned int tx_done_mask; |
---|
151 | 147 | u32 fifo_size; |
---|
152 | 148 | u32 rts_high; |
---|
.. | .. |
---|
164 | 160 | spinlock_t lock_suspended; |
---|
165 | 161 | |
---|
166 | 162 | bool hd_start_rx; /* can start RX during half-duplex operation */ |
---|
| 163 | + |
---|
| 164 | + /* ISO7816 */ |
---|
| 165 | + unsigned int fidi_min; |
---|
| 166 | + unsigned int fidi_max; |
---|
167 | 167 | |
---|
168 | 168 | #ifdef CONFIG_PM |
---|
169 | 169 | struct { |
---|
.. | .. |
---|
189 | 189 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
---|
190 | 190 | static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART); |
---|
191 | 191 | |
---|
192 | | -#ifdef SUPPORT_SYSRQ |
---|
193 | | -static struct console atmel_console; |
---|
194 | | -#endif |
---|
195 | | - |
---|
196 | 192 | #if defined(CONFIG_OF) |
---|
197 | 193 | static const struct of_device_id atmel_serial_dt_ids[] = { |
---|
198 | | - { .compatible = "atmel,at91rm9200-usart" }, |
---|
199 | | - { .compatible = "atmel,at91sam9260-usart" }, |
---|
| 194 | + { .compatible = "atmel,at91rm9200-usart-serial" }, |
---|
200 | 195 | { /* sentinel */ } |
---|
201 | 196 | }; |
---|
202 | 197 | #endif |
---|
.. | .. |
---|
229 | 224 | |
---|
230 | 225 | static inline int atmel_uart_is_half_duplex(struct uart_port *port) |
---|
231 | 226 | { |
---|
232 | | - return (port->rs485.flags & SER_RS485_ENABLED) && |
---|
233 | | - !(port->rs485.flags & SER_RS485_RX_DURING_TX); |
---|
| 227 | + return ((port->rs485.flags & SER_RS485_ENABLED) && |
---|
| 228 | + !(port->rs485.flags & SER_RS485_RX_DURING_TX)) || |
---|
| 229 | + (port->iso7816.flags & SER_ISO7816_ENABLED); |
---|
234 | 230 | } |
---|
235 | 231 | |
---|
236 | 232 | #ifdef CONFIG_SERIAL_ATMEL_PDC |
---|
.. | .. |
---|
287 | 283 | tasklet_schedule(t); |
---|
288 | 284 | } |
---|
289 | 285 | |
---|
290 | | -static unsigned int atmel_get_lines_status(struct uart_port *port) |
---|
291 | | -{ |
---|
292 | | - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
293 | | - unsigned int status, ret = 0; |
---|
294 | | - |
---|
295 | | - status = atmel_uart_readl(port, ATMEL_US_CSR); |
---|
296 | | - |
---|
297 | | - mctrl_gpio_get(atmel_port->gpios, &ret); |
---|
298 | | - |
---|
299 | | - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, |
---|
300 | | - UART_GPIO_CTS))) { |
---|
301 | | - if (ret & TIOCM_CTS) |
---|
302 | | - status &= ~ATMEL_US_CTS; |
---|
303 | | - else |
---|
304 | | - status |= ATMEL_US_CTS; |
---|
305 | | - } |
---|
306 | | - |
---|
307 | | - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, |
---|
308 | | - UART_GPIO_DSR))) { |
---|
309 | | - if (ret & TIOCM_DSR) |
---|
310 | | - status &= ~ATMEL_US_DSR; |
---|
311 | | - else |
---|
312 | | - status |= ATMEL_US_DSR; |
---|
313 | | - } |
---|
314 | | - |
---|
315 | | - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, |
---|
316 | | - UART_GPIO_RI))) { |
---|
317 | | - if (ret & TIOCM_RI) |
---|
318 | | - status &= ~ATMEL_US_RI; |
---|
319 | | - else |
---|
320 | | - status |= ATMEL_US_RI; |
---|
321 | | - } |
---|
322 | | - |
---|
323 | | - if (!IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(atmel_port->gpios, |
---|
324 | | - UART_GPIO_DCD))) { |
---|
325 | | - if (ret & TIOCM_CD) |
---|
326 | | - status &= ~ATMEL_US_DCD; |
---|
327 | | - else |
---|
328 | | - status |= ATMEL_US_DCD; |
---|
329 | | - } |
---|
330 | | - |
---|
331 | | - return status; |
---|
332 | | -} |
---|
333 | | - |
---|
334 | 286 | /* Enable or disable the rs485 support */ |
---|
335 | 287 | static int atmel_config_rs485(struct uart_port *port, |
---|
336 | 288 | struct serial_rs485 *rs485conf) |
---|
.. | .. |
---|
343 | 295 | |
---|
344 | 296 | mode = atmel_uart_readl(port, ATMEL_US_MR); |
---|
345 | 297 | |
---|
346 | | - /* Resetting serial mode to RS232 (0x0) */ |
---|
347 | | - mode &= ~ATMEL_US_USMODE; |
---|
348 | | - |
---|
349 | | - port->rs485 = *rs485conf; |
---|
350 | | - |
---|
351 | 298 | if (rs485conf->flags & SER_RS485_ENABLED) { |
---|
352 | 299 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
---|
353 | | - atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
---|
| 300 | + if (rs485conf->flags & SER_RS485_RX_DURING_TX) |
---|
| 301 | + atmel_port->tx_done_mask = ATMEL_US_TXRDY; |
---|
| 302 | + else |
---|
| 303 | + atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
---|
| 304 | + |
---|
354 | 305 | atmel_uart_writel(port, ATMEL_US_TTGR, |
---|
355 | 306 | rs485conf->delay_rts_after_send); |
---|
| 307 | + mode &= ~ATMEL_US_USMODE; |
---|
356 | 308 | mode |= ATMEL_US_USMODE_RS485; |
---|
357 | 309 | } else { |
---|
358 | 310 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
---|
.. | .. |
---|
368 | 320 | atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask); |
---|
369 | 321 | |
---|
370 | 322 | return 0; |
---|
| 323 | +} |
---|
| 324 | + |
---|
| 325 | +static unsigned int atmel_calc_cd(struct uart_port *port, |
---|
| 326 | + struct serial_iso7816 *iso7816conf) |
---|
| 327 | +{ |
---|
| 328 | + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 329 | + unsigned int cd; |
---|
| 330 | + u64 mck_rate; |
---|
| 331 | + |
---|
| 332 | + mck_rate = (u64)clk_get_rate(atmel_port->clk); |
---|
| 333 | + do_div(mck_rate, iso7816conf->clk); |
---|
| 334 | + cd = mck_rate; |
---|
| 335 | + return cd; |
---|
| 336 | +} |
---|
| 337 | + |
---|
| 338 | +static unsigned int atmel_calc_fidi(struct uart_port *port, |
---|
| 339 | + struct serial_iso7816 *iso7816conf) |
---|
| 340 | +{ |
---|
| 341 | + u64 fidi = 0; |
---|
| 342 | + |
---|
| 343 | + if (iso7816conf->sc_fi && iso7816conf->sc_di) { |
---|
| 344 | + fidi = (u64)iso7816conf->sc_fi; |
---|
| 345 | + do_div(fidi, iso7816conf->sc_di); |
---|
| 346 | + } |
---|
| 347 | + return (u32)fidi; |
---|
| 348 | +} |
---|
| 349 | + |
---|
| 350 | +/* Enable or disable the iso7816 support */ |
---|
| 351 | +/* Called with interrupts disabled */ |
---|
| 352 | +static int atmel_config_iso7816(struct uart_port *port, |
---|
| 353 | + struct serial_iso7816 *iso7816conf) |
---|
| 354 | +{ |
---|
| 355 | + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 356 | + unsigned int mode; |
---|
| 357 | + unsigned int cd, fidi; |
---|
| 358 | + int ret = 0; |
---|
| 359 | + |
---|
| 360 | + /* Disable interrupts */ |
---|
| 361 | + atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask); |
---|
| 362 | + |
---|
| 363 | + mode = atmel_uart_readl(port, ATMEL_US_MR); |
---|
| 364 | + |
---|
| 365 | + if (iso7816conf->flags & SER_ISO7816_ENABLED) { |
---|
| 366 | + mode &= ~ATMEL_US_USMODE; |
---|
| 367 | + |
---|
| 368 | + if (iso7816conf->tg > 255) { |
---|
| 369 | + dev_err(port->dev, "ISO7816: Timeguard exceeding 255\n"); |
---|
| 370 | + memset(iso7816conf, 0, sizeof(struct serial_iso7816)); |
---|
| 371 | + ret = -EINVAL; |
---|
| 372 | + goto err_out; |
---|
| 373 | + } |
---|
| 374 | + |
---|
| 375 | + if ((iso7816conf->flags & SER_ISO7816_T_PARAM) |
---|
| 376 | + == SER_ISO7816_T(0)) { |
---|
| 377 | + mode |= ATMEL_US_USMODE_ISO7816_T0 | ATMEL_US_DSNACK; |
---|
| 378 | + } else if ((iso7816conf->flags & SER_ISO7816_T_PARAM) |
---|
| 379 | + == SER_ISO7816_T(1)) { |
---|
| 380 | + mode |= ATMEL_US_USMODE_ISO7816_T1 | ATMEL_US_INACK; |
---|
| 381 | + } else { |
---|
| 382 | + dev_err(port->dev, "ISO7816: Type not supported\n"); |
---|
| 383 | + memset(iso7816conf, 0, sizeof(struct serial_iso7816)); |
---|
| 384 | + ret = -EINVAL; |
---|
| 385 | + goto err_out; |
---|
| 386 | + } |
---|
| 387 | + |
---|
| 388 | + mode &= ~(ATMEL_US_USCLKS | ATMEL_US_NBSTOP | ATMEL_US_PAR); |
---|
| 389 | + |
---|
| 390 | + /* select mck clock, and output */ |
---|
| 391 | + mode |= ATMEL_US_USCLKS_MCK | ATMEL_US_CLKO; |
---|
| 392 | + /* set parity for normal/inverse mode + max iterations */ |
---|
| 393 | + mode |= ATMEL_US_PAR_EVEN | ATMEL_US_NBSTOP_1 | ATMEL_US_MAX_ITER(3); |
---|
| 394 | + |
---|
| 395 | + cd = atmel_calc_cd(port, iso7816conf); |
---|
| 396 | + fidi = atmel_calc_fidi(port, iso7816conf); |
---|
| 397 | + if (fidi == 0) { |
---|
| 398 | + dev_warn(port->dev, "ISO7816 fidi = 0, Generator generates no signal\n"); |
---|
| 399 | + } else if (fidi < atmel_port->fidi_min |
---|
| 400 | + || fidi > atmel_port->fidi_max) { |
---|
| 401 | + dev_err(port->dev, "ISO7816 fidi = %u, value not supported\n", fidi); |
---|
| 402 | + memset(iso7816conf, 0, sizeof(struct serial_iso7816)); |
---|
| 403 | + ret = -EINVAL; |
---|
| 404 | + goto err_out; |
---|
| 405 | + } |
---|
| 406 | + |
---|
| 407 | + if (!(port->iso7816.flags & SER_ISO7816_ENABLED)) { |
---|
| 408 | + /* port not yet in iso7816 mode: store configuration */ |
---|
| 409 | + atmel_port->backup_mode = atmel_uart_readl(port, ATMEL_US_MR); |
---|
| 410 | + atmel_port->backup_brgr = atmel_uart_readl(port, ATMEL_US_BRGR); |
---|
| 411 | + } |
---|
| 412 | + |
---|
| 413 | + atmel_uart_writel(port, ATMEL_US_TTGR, iso7816conf->tg); |
---|
| 414 | + atmel_uart_writel(port, ATMEL_US_BRGR, cd); |
---|
| 415 | + atmel_uart_writel(port, ATMEL_US_FIDI, fidi); |
---|
| 416 | + |
---|
| 417 | + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXEN); |
---|
| 418 | + atmel_port->tx_done_mask = ATMEL_US_TXEMPTY | ATMEL_US_NACK | ATMEL_US_ITERATION; |
---|
| 419 | + } else { |
---|
| 420 | + dev_dbg(port->dev, "Setting UART back to RS232\n"); |
---|
| 421 | + /* back to last RS232 settings */ |
---|
| 422 | + mode = atmel_port->backup_mode; |
---|
| 423 | + memset(iso7816conf, 0, sizeof(struct serial_iso7816)); |
---|
| 424 | + atmel_uart_writel(port, ATMEL_US_TTGR, 0); |
---|
| 425 | + atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->backup_brgr); |
---|
| 426 | + atmel_uart_writel(port, ATMEL_US_FIDI, 0x174); |
---|
| 427 | + |
---|
| 428 | + if (atmel_use_pdc_tx(port)) |
---|
| 429 | + atmel_port->tx_done_mask = ATMEL_US_ENDTX | |
---|
| 430 | + ATMEL_US_TXBUFE; |
---|
| 431 | + else |
---|
| 432 | + atmel_port->tx_done_mask = ATMEL_US_TXRDY; |
---|
| 433 | + } |
---|
| 434 | + |
---|
| 435 | + port->iso7816 = *iso7816conf; |
---|
| 436 | + |
---|
| 437 | + atmel_uart_writel(port, ATMEL_US_MR, mode); |
---|
| 438 | + |
---|
| 439 | +err_out: |
---|
| 440 | + /* Enable interrupts */ |
---|
| 441 | + atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask); |
---|
| 442 | + |
---|
| 443 | + return ret; |
---|
371 | 444 | } |
---|
372 | 445 | |
---|
373 | 446 | /* |
---|
.. | .. |
---|
748 | 821 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
749 | 822 | |
---|
750 | 823 | if (port->x_char && |
---|
751 | | - (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) { |
---|
| 824 | + (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) { |
---|
752 | 825 | atmel_uart_write_char(port, port->x_char); |
---|
753 | 826 | port->icount.tx++; |
---|
754 | 827 | port->x_char = 0; |
---|
.. | .. |
---|
756 | 829 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) |
---|
757 | 830 | return; |
---|
758 | 831 | |
---|
759 | | - while (atmel_uart_readl(port, ATMEL_US_CSR) & |
---|
760 | | - atmel_port->tx_done_mask) { |
---|
| 832 | + while (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY) { |
---|
761 | 833 | atmel_uart_write_char(port, xmit->buf[xmit->tail]); |
---|
762 | 834 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
---|
763 | 835 | port->icount.tx++; |
---|
.. | .. |
---|
768 | 840 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
---|
769 | 841 | uart_write_wakeup(port); |
---|
770 | 842 | |
---|
771 | | - if (!uart_circ_empty(xmit)) |
---|
| 843 | + if (!uart_circ_empty(xmit)) { |
---|
| 844 | + /* we still have characters to transmit, so we should continue |
---|
| 845 | + * transmitting them when TX is ready, regardless of |
---|
| 846 | + * mode or duplexity |
---|
| 847 | + */ |
---|
| 848 | + atmel_port->tx_done_mask |= ATMEL_US_TXRDY; |
---|
| 849 | + |
---|
772 | 850 | /* Enable interrupts */ |
---|
773 | 851 | atmel_uart_writel(port, ATMEL_US_IER, |
---|
774 | 852 | atmel_port->tx_done_mask); |
---|
| 853 | + } else { |
---|
| 854 | + if (atmel_uart_is_half_duplex(port)) |
---|
| 855 | + atmel_port->tx_done_mask &= ~ATMEL_US_TXRDY; |
---|
| 856 | + } |
---|
775 | 857 | } |
---|
776 | 858 | |
---|
777 | 859 | static void atmel_complete_tx_dma(void *arg) |
---|
.. | .. |
---|
791 | 873 | |
---|
792 | 874 | port->icount.tx += atmel_port->tx_len; |
---|
793 | 875 | |
---|
794 | | - spin_lock_irq(&atmel_port->lock_tx); |
---|
| 876 | + spin_lock(&atmel_port->lock_tx); |
---|
795 | 877 | async_tx_ack(atmel_port->desc_tx); |
---|
796 | 878 | atmel_port->cookie_tx = -EINVAL; |
---|
797 | 879 | atmel_port->desc_tx = NULL; |
---|
798 | | - spin_unlock_irq(&atmel_port->lock_tx); |
---|
| 880 | + spin_unlock(&atmel_port->lock_tx); |
---|
799 | 881 | |
---|
800 | 882 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
---|
801 | 883 | uart_write_wakeup(port); |
---|
.. | .. |
---|
934 | 1016 | static int atmel_prepare_tx_dma(struct uart_port *port) |
---|
935 | 1017 | { |
---|
936 | 1018 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 1019 | + struct device *mfd_dev = port->dev->parent; |
---|
937 | 1020 | dma_cap_mask_t mask; |
---|
938 | 1021 | struct dma_slave_config config; |
---|
939 | 1022 | int ret, nent; |
---|
.. | .. |
---|
941 | 1024 | dma_cap_zero(mask); |
---|
942 | 1025 | dma_cap_set(DMA_SLAVE, mask); |
---|
943 | 1026 | |
---|
944 | | - atmel_port->chan_tx = dma_request_slave_channel(port->dev, "tx"); |
---|
| 1027 | + atmel_port->chan_tx = dma_request_slave_channel(mfd_dev, "tx"); |
---|
945 | 1028 | if (atmel_port->chan_tx == NULL) |
---|
946 | 1029 | goto chan_err; |
---|
947 | 1030 | dev_info(port->dev, "using %s for tx DMA transfers\n", |
---|
.. | .. |
---|
990 | 1073 | |
---|
991 | 1074 | chan_err: |
---|
992 | 1075 | dev_err(port->dev, "TX channel not available, switch to pio\n"); |
---|
993 | | - atmel_port->use_dma_tx = 0; |
---|
| 1076 | + atmel_port->use_dma_tx = false; |
---|
994 | 1077 | if (atmel_port->chan_tx) |
---|
995 | 1078 | atmel_release_tx_dma(port); |
---|
996 | 1079 | return -EINVAL; |
---|
.. | .. |
---|
1112 | 1195 | static int atmel_prepare_rx_dma(struct uart_port *port) |
---|
1113 | 1196 | { |
---|
1114 | 1197 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 1198 | + struct device *mfd_dev = port->dev->parent; |
---|
1115 | 1199 | struct dma_async_tx_descriptor *desc; |
---|
1116 | 1200 | dma_cap_mask_t mask; |
---|
1117 | 1201 | struct dma_slave_config config; |
---|
.. | .. |
---|
1123 | 1207 | dma_cap_zero(mask); |
---|
1124 | 1208 | dma_cap_set(DMA_CYCLIC, mask); |
---|
1125 | 1209 | |
---|
1126 | | - atmel_port->chan_rx = dma_request_slave_channel(port->dev, "rx"); |
---|
| 1210 | + atmel_port->chan_rx = dma_request_slave_channel(mfd_dev, "rx"); |
---|
1127 | 1211 | if (atmel_port->chan_rx == NULL) |
---|
1128 | 1212 | goto chan_err; |
---|
1129 | 1213 | dev_info(port->dev, "using %s for rx DMA transfers\n", |
---|
.. | .. |
---|
1195 | 1279 | |
---|
1196 | 1280 | chan_err: |
---|
1197 | 1281 | dev_err(port->dev, "RX channel not available, switch to pio\n"); |
---|
1198 | | - atmel_port->use_dma_rx = 0; |
---|
| 1282 | + atmel_port->use_dma_rx = false; |
---|
1199 | 1283 | if (atmel_port->chan_rx) |
---|
1200 | 1284 | atmel_release_rx_dma(port); |
---|
1201 | 1285 | return -EINVAL; |
---|
.. | .. |
---|
1321 | 1405 | wake_up_interruptible(&port->state->port.delta_msr_wait); |
---|
1322 | 1406 | } |
---|
1323 | 1407 | } |
---|
| 1408 | + |
---|
| 1409 | + if (pending & (ATMEL_US_NACK | ATMEL_US_ITERATION)) |
---|
| 1410 | + dev_dbg(port->dev, "ISO7816 ERROR (0x%08x)\n", pending); |
---|
1324 | 1411 | } |
---|
1325 | 1412 | |
---|
1326 | 1413 | /* |
---|
.. | .. |
---|
1335 | 1422 | spin_lock(&atmel_port->lock_suspended); |
---|
1336 | 1423 | |
---|
1337 | 1424 | do { |
---|
1338 | | - status = atmel_get_lines_status(port); |
---|
| 1425 | + status = atmel_uart_readl(port, ATMEL_US_CSR); |
---|
1339 | 1426 | mask = atmel_uart_readl(port, ATMEL_US_IMR); |
---|
1340 | 1427 | pending = status & mask; |
---|
1341 | 1428 | if (!pending) |
---|
.. | .. |
---|
1619 | 1706 | DMA_FROM_DEVICE); |
---|
1620 | 1707 | kfree(atmel_port->pdc_rx[0].buf); |
---|
1621 | 1708 | } |
---|
1622 | | - atmel_port->use_pdc_rx = 0; |
---|
| 1709 | + atmel_port->use_pdc_rx = false; |
---|
1623 | 1710 | return -ENOMEM; |
---|
1624 | 1711 | } |
---|
1625 | 1712 | pdc->dma_addr = dma_map_single(port->dev, |
---|
.. | .. |
---|
1645 | 1732 | /* |
---|
1646 | 1733 | * tasklet handling tty stuff outside the interrupt handler. |
---|
1647 | 1734 | */ |
---|
1648 | | -static void atmel_tasklet_rx_func(unsigned long data) |
---|
| 1735 | +static void atmel_tasklet_rx_func(struct tasklet_struct *t) |
---|
1649 | 1736 | { |
---|
1650 | | - struct uart_port *port = (struct uart_port *)data; |
---|
1651 | | - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 1737 | + struct atmel_uart_port *atmel_port = from_tasklet(atmel_port, t, |
---|
| 1738 | + tasklet_rx); |
---|
| 1739 | + struct uart_port *port = &atmel_port->uart; |
---|
1652 | 1740 | |
---|
1653 | 1741 | /* The interrupt handler does not take the lock */ |
---|
1654 | 1742 | spin_lock(&port->lock); |
---|
.. | .. |
---|
1656 | 1744 | spin_unlock(&port->lock); |
---|
1657 | 1745 | } |
---|
1658 | 1746 | |
---|
1659 | | -static void atmel_tasklet_tx_func(unsigned long data) |
---|
| 1747 | +static void atmel_tasklet_tx_func(struct tasklet_struct *t) |
---|
1660 | 1748 | { |
---|
1661 | | - struct uart_port *port = (struct uart_port *)data; |
---|
1662 | | - struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
| 1749 | + struct atmel_uart_port *atmel_port = from_tasklet(atmel_port, t, |
---|
| 1750 | + tasklet_tx); |
---|
| 1751 | + struct uart_port *port = &atmel_port->uart; |
---|
1663 | 1752 | |
---|
1664 | 1753 | /* The interrupt handler does not take the lock */ |
---|
1665 | 1754 | spin_lock(&port->lock); |
---|
.. | .. |
---|
1765 | 1854 | atmel_port->has_frac_baudrate = true; |
---|
1766 | 1855 | atmel_port->has_hw_timer = true; |
---|
1767 | 1856 | atmel_port->rtor = ATMEL_US_RTOR; |
---|
| 1857 | + version = atmel_uart_readl(port, ATMEL_US_VERSION); |
---|
| 1858 | + switch (version) { |
---|
| 1859 | + case 0x814: /* sama5d2 */ |
---|
| 1860 | + fallthrough; |
---|
| 1861 | + case 0x701: /* sama5d4 */ |
---|
| 1862 | + atmel_port->fidi_min = 3; |
---|
| 1863 | + atmel_port->fidi_max = 65535; |
---|
| 1864 | + break; |
---|
| 1865 | + case 0x502: /* sam9x5, sama5d3 */ |
---|
| 1866 | + atmel_port->fidi_min = 3; |
---|
| 1867 | + atmel_port->fidi_max = 2047; |
---|
| 1868 | + break; |
---|
| 1869 | + default: |
---|
| 1870 | + atmel_port->fidi_min = 1; |
---|
| 1871 | + atmel_port->fidi_max = 2047; |
---|
| 1872 | + } |
---|
1768 | 1873 | } else if (name == dbgu_uart) { |
---|
1769 | 1874 | dev_dbg(port->dev, "Dbgu or uart without hw timer\n"); |
---|
1770 | 1875 | } else { |
---|
.. | .. |
---|
1818 | 1923 | } |
---|
1819 | 1924 | |
---|
1820 | 1925 | atomic_set(&atmel_port->tasklet_shutdown, 0); |
---|
1821 | | - tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func, |
---|
1822 | | - (unsigned long)port); |
---|
1823 | | - tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func, |
---|
1824 | | - (unsigned long)port); |
---|
| 1926 | + tasklet_setup(&atmel_port->tasklet_rx, atmel_tasklet_rx_func); |
---|
| 1927 | + tasklet_setup(&atmel_port->tasklet_tx, atmel_tasklet_tx_func); |
---|
1825 | 1928 | |
---|
1826 | 1929 | /* |
---|
1827 | 1930 | * Initialize DMA (if necessary) |
---|
.. | .. |
---|
1868 | 1971 | } |
---|
1869 | 1972 | |
---|
1870 | 1973 | /* Save current CSR for comparison in atmel_tasklet_func() */ |
---|
1871 | | - atmel_port->irq_status_prev = atmel_get_lines_status(port); |
---|
| 1974 | + atmel_port->irq_status_prev = atmel_uart_readl(port, ATMEL_US_CSR); |
---|
1872 | 1975 | |
---|
1873 | 1976 | /* |
---|
1874 | 1977 | * Finally, enable the serial port |
---|
.. | .. |
---|
2138 | 2241 | atmel_uart_writel(port, ATMEL_US_TTGR, |
---|
2139 | 2242 | port->rs485.delay_rts_after_send); |
---|
2140 | 2243 | mode |= ATMEL_US_USMODE_RS485; |
---|
| 2244 | + } else if (port->iso7816.flags & SER_ISO7816_ENABLED) { |
---|
| 2245 | + atmel_uart_writel(port, ATMEL_US_TTGR, port->iso7816.tg); |
---|
| 2246 | + /* select mck clock, and output */ |
---|
| 2247 | + mode |= ATMEL_US_USCLKS_MCK | ATMEL_US_CLKO; |
---|
| 2248 | + /* set max iterations */ |
---|
| 2249 | + mode |= ATMEL_US_MAX_ITER(3); |
---|
| 2250 | + if ((port->iso7816.flags & SER_ISO7816_T_PARAM) |
---|
| 2251 | + == SER_ISO7816_T(0)) |
---|
| 2252 | + mode |= ATMEL_US_USMODE_ISO7816_T0; |
---|
| 2253 | + else |
---|
| 2254 | + mode |= ATMEL_US_USMODE_ISO7816_T1; |
---|
2141 | 2255 | } else if (termios->c_cflag & CRTSCTS) { |
---|
2142 | 2256 | /* RS232 with hardware handshake (RTS/CTS) */ |
---|
2143 | 2257 | if (atmel_use_fifo(port) && |
---|
.. | .. |
---|
2193 | 2307 | } |
---|
2194 | 2308 | quot = cd | fp << ATMEL_US_FP_OFFSET; |
---|
2195 | 2309 | |
---|
2196 | | - atmel_uart_writel(port, ATMEL_US_BRGR, quot); |
---|
| 2310 | + if (!(port->iso7816.flags & SER_ISO7816_ENABLED)) |
---|
| 2311 | + atmel_uart_writel(port, ATMEL_US_BRGR, quot); |
---|
2197 | 2312 | |
---|
2198 | 2313 | /* set the mode, clock divisor, parity, stop bits and data size */ |
---|
2199 | 2314 | atmel_uart_writel(port, ATMEL_US_MR, mode); |
---|
.. | .. |
---|
2262 | 2377 | */ |
---|
2263 | 2378 | static void atmel_release_port(struct uart_port *port) |
---|
2264 | 2379 | { |
---|
2265 | | - struct platform_device *pdev = to_platform_device(port->dev); |
---|
2266 | | - int size = pdev->resource[0].end - pdev->resource[0].start + 1; |
---|
| 2380 | + struct platform_device *mpdev = to_platform_device(port->dev->parent); |
---|
| 2381 | + int size = resource_size(mpdev->resource); |
---|
2267 | 2382 | |
---|
2268 | 2383 | release_mem_region(port->mapbase, size); |
---|
2269 | 2384 | |
---|
.. | .. |
---|
2278 | 2393 | */ |
---|
2279 | 2394 | static int atmel_request_port(struct uart_port *port) |
---|
2280 | 2395 | { |
---|
2281 | | - struct platform_device *pdev = to_platform_device(port->dev); |
---|
2282 | | - int size = pdev->resource[0].end - pdev->resource[0].start + 1; |
---|
| 2396 | + struct platform_device *mpdev = to_platform_device(port->dev->parent); |
---|
| 2397 | + int size = resource_size(mpdev->resource); |
---|
2283 | 2398 | |
---|
2284 | 2399 | if (!request_mem_region(port->mapbase, size, "atmel_serial")) |
---|
2285 | 2400 | return -EBUSY; |
---|
.. | .. |
---|
2381 | 2496 | { |
---|
2382 | 2497 | int ret; |
---|
2383 | 2498 | struct uart_port *port = &atmel_port->uart; |
---|
| 2499 | + struct platform_device *mpdev = to_platform_device(pdev->dev.parent); |
---|
2384 | 2500 | |
---|
2385 | 2501 | atmel_init_property(atmel_port, pdev); |
---|
2386 | 2502 | atmel_set_ops(port); |
---|
2387 | | - |
---|
2388 | | - uart_get_rs485_mode(&pdev->dev, &port->rs485); |
---|
2389 | 2503 | |
---|
2390 | 2504 | port->iotype = UPIO_MEM; |
---|
2391 | 2505 | port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; |
---|
2392 | 2506 | port->ops = &atmel_pops; |
---|
2393 | 2507 | port->fifosize = 1; |
---|
2394 | 2508 | port->dev = &pdev->dev; |
---|
2395 | | - port->mapbase = pdev->resource[0].start; |
---|
2396 | | - port->irq = pdev->resource[1].start; |
---|
| 2509 | + port->mapbase = mpdev->resource[0].start; |
---|
| 2510 | + port->irq = mpdev->resource[1].start; |
---|
2397 | 2511 | port->rs485_config = atmel_config_rs485; |
---|
2398 | | - port->membase = NULL; |
---|
| 2512 | + port->iso7816_config = atmel_config_iso7816; |
---|
| 2513 | + port->membase = NULL; |
---|
2399 | 2514 | |
---|
2400 | 2515 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); |
---|
2401 | 2516 | |
---|
| 2517 | + ret = uart_get_rs485_mode(port); |
---|
| 2518 | + if (ret) |
---|
| 2519 | + return ret; |
---|
| 2520 | + |
---|
2402 | 2521 | /* for console, the clock could already be configured */ |
---|
2403 | 2522 | if (!atmel_port->clk) { |
---|
2404 | | - atmel_port->clk = clk_get(&pdev->dev, "usart"); |
---|
| 2523 | + atmel_port->clk = clk_get(&mpdev->dev, "usart"); |
---|
2405 | 2524 | if (IS_ERR(atmel_port->clk)) { |
---|
2406 | 2525 | ret = PTR_ERR(atmel_port->clk); |
---|
2407 | 2526 | atmel_port->clk = NULL; |
---|
.. | .. |
---|
2418 | 2537 | /* only enable clock when USART is in use */ |
---|
2419 | 2538 | } |
---|
2420 | 2539 | |
---|
2421 | | - /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ |
---|
2422 | | - if (port->rs485.flags & SER_RS485_ENABLED) |
---|
| 2540 | + /* |
---|
| 2541 | + * Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or |
---|
| 2542 | + * ENDTX|TXBUFE |
---|
| 2543 | + */ |
---|
| 2544 | + if (atmel_uart_is_half_duplex(port)) |
---|
2423 | 2545 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
---|
2424 | 2546 | else if (atmel_use_pdc_tx(port)) { |
---|
2425 | 2547 | port->fifosize = PDC_BUFFER_SIZE; |
---|
.. | .. |
---|
2511 | 2633 | else if (mr == ATMEL_US_PAR_ODD) |
---|
2512 | 2634 | *parity = 'o'; |
---|
2513 | 2635 | |
---|
2514 | | - /* |
---|
2515 | | - * The serial core only rounds down when matching this to a |
---|
2516 | | - * supported baud rate. Make sure we don't end up slightly |
---|
2517 | | - * lower than one of those, as it would make us fall through |
---|
2518 | | - * to a much lower baud rate than we really want. |
---|
2519 | | - */ |
---|
2520 | | - *baud = port->uartclk / (16 * (quot - 1)); |
---|
| 2636 | + *baud = port->uartclk / (16 * quot); |
---|
2521 | 2637 | } |
---|
2522 | 2638 | |
---|
2523 | 2639 | static int __init atmel_console_setup(struct console *co, char *options) |
---|
.. | .. |
---|
2566 | 2682 | |
---|
2567 | 2683 | #define ATMEL_CONSOLE_DEVICE (&atmel_console) |
---|
2568 | 2684 | |
---|
2569 | | -static inline bool atmel_is_console_port(struct uart_port *port) |
---|
2570 | | -{ |
---|
2571 | | - return port->cons && port->cons->index == port->line; |
---|
2572 | | -} |
---|
2573 | | - |
---|
2574 | 2685 | #else |
---|
2575 | 2686 | #define ATMEL_CONSOLE_DEVICE NULL |
---|
2576 | | - |
---|
2577 | | -static inline bool atmel_is_console_port(struct uart_port *port) |
---|
2578 | | -{ |
---|
2579 | | - return false; |
---|
2580 | | -} |
---|
2581 | 2687 | #endif |
---|
2582 | 2688 | |
---|
2583 | 2689 | static struct uart_driver atmel_uart = { |
---|
.. | .. |
---|
2606 | 2712 | struct uart_port *port = platform_get_drvdata(pdev); |
---|
2607 | 2713 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
2608 | 2714 | |
---|
2609 | | - if (atmel_is_console_port(port) && console_suspend_enabled) { |
---|
| 2715 | + if (uart_console(port) && console_suspend_enabled) { |
---|
2610 | 2716 | /* Drain the TX shifter */ |
---|
2611 | 2717 | while (!(atmel_uart_readl(port, ATMEL_US_CSR) & |
---|
2612 | 2718 | ATMEL_US_TXEMPTY)) |
---|
2613 | 2719 | cpu_relax(); |
---|
2614 | 2720 | } |
---|
2615 | 2721 | |
---|
2616 | | - if (atmel_is_console_port(port) && !console_suspend_enabled) { |
---|
| 2722 | + if (uart_console(port) && !console_suspend_enabled) { |
---|
2617 | 2723 | /* Cache register values as we won't get a full shutdown/startup |
---|
2618 | 2724 | * cycle |
---|
2619 | 2725 | */ |
---|
.. | .. |
---|
2649 | 2755 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
---|
2650 | 2756 | unsigned long flags; |
---|
2651 | 2757 | |
---|
2652 | | - if (atmel_is_console_port(port) && !console_suspend_enabled) { |
---|
| 2758 | + if (uart_console(port) && !console_suspend_enabled) { |
---|
2653 | 2759 | atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr); |
---|
2654 | 2760 | atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr); |
---|
2655 | 2761 | atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr); |
---|
.. | .. |
---|
2734 | 2840 | static int atmel_serial_probe(struct platform_device *pdev) |
---|
2735 | 2841 | { |
---|
2736 | 2842 | struct atmel_uart_port *atmel_port; |
---|
2737 | | - struct device_node *np = pdev->dev.of_node; |
---|
| 2843 | + struct device_node *np = pdev->dev.parent->of_node; |
---|
2738 | 2844 | void *data; |
---|
2739 | | - int ret = -ENODEV; |
---|
| 2845 | + int ret; |
---|
2740 | 2846 | bool rs485_enabled; |
---|
2741 | 2847 | |
---|
2742 | 2848 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); |
---|
| 2849 | + |
---|
| 2850 | + /* |
---|
| 2851 | + * In device tree there is no node with "atmel,at91rm9200-usart-serial" |
---|
| 2852 | + * as compatible string. This driver is probed by at91-usart mfd driver |
---|
| 2853 | + * which is just a wrapper over the atmel_serial driver and |
---|
| 2854 | + * spi-at91-usart driver. All attributes needed by this driver are |
---|
| 2855 | + * found in of_node of parent. |
---|
| 2856 | + */ |
---|
| 2857 | + pdev->dev.of_node = np; |
---|
2743 | 2858 | |
---|
2744 | 2859 | ret = of_alias_get_id(np, "serial"); |
---|
2745 | 2860 | if (ret < 0) |
---|
.. | .. |
---|
2761 | 2876 | atmel_port = &atmel_ports[ret]; |
---|
2762 | 2877 | atmel_port->backup_imr = 0; |
---|
2763 | 2878 | atmel_port->uart.line = ret; |
---|
| 2879 | + atmel_port->uart.has_sysrq = IS_ENABLED(CONFIG_SERIAL_ATMEL_CONSOLE); |
---|
2764 | 2880 | atmel_serial_probe_fifos(atmel_port, pdev); |
---|
2765 | 2881 | |
---|
2766 | 2882 | atomic_set(&atmel_port->tasklet_shutdown, 0); |
---|
.. | .. |
---|
2793 | 2909 | goto err_add_port; |
---|
2794 | 2910 | |
---|
2795 | 2911 | #ifdef CONFIG_SERIAL_ATMEL_CONSOLE |
---|
2796 | | - if (atmel_is_console_port(&atmel_port->uart) |
---|
| 2912 | + if (uart_console(&atmel_port->uart) |
---|
2797 | 2913 | && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { |
---|
2798 | 2914 | /* |
---|
2799 | 2915 | * The serial core enabled the clock for us, so undo |
---|
.. | .. |
---|
2836 | 2952 | kfree(atmel_port->rx_ring.buf); |
---|
2837 | 2953 | atmel_port->rx_ring.buf = NULL; |
---|
2838 | 2954 | err_alloc_ring: |
---|
2839 | | - if (!atmel_is_console_port(&atmel_port->uart)) { |
---|
| 2955 | + if (!uart_console(&atmel_port->uart)) { |
---|
2840 | 2956 | clk_put(atmel_port->clk); |
---|
2841 | 2957 | atmel_port->clk = NULL; |
---|
2842 | 2958 | } |
---|
.. | .. |
---|
2876 | 2992 | |
---|
2877 | 2993 | clk_put(atmel_port->clk); |
---|
2878 | 2994 | atmel_port->clk = NULL; |
---|
| 2995 | + pdev->dev.of_node = NULL; |
---|
2879 | 2996 | |
---|
2880 | 2997 | return ret; |
---|
2881 | 2998 | } |
---|
.. | .. |
---|
2886 | 3003 | .suspend = atmel_serial_suspend, |
---|
2887 | 3004 | .resume = atmel_serial_resume, |
---|
2888 | 3005 | .driver = { |
---|
2889 | | - .name = "atmel_usart", |
---|
| 3006 | + .name = "atmel_usart_serial", |
---|
2890 | 3007 | .of_match_table = of_match_ptr(atmel_serial_dt_ids), |
---|
2891 | 3008 | }, |
---|
2892 | 3009 | }; |
---|