4848#include <linux/suspend.h>
4949#include <linux/mm.h>
5050
51+ #include <asm/div64.h>
5152#include <asm/io.h>
5253#include <asm/ioctls.h>
5354
@@ -161,6 +162,8 @@ struct atmel_uart_port {
161162 struct circ_buf rx_ring ;
162163
163164 struct mctrl_gpios * gpios ;
165+ u32 backup_mode ; /* MR saved during iso7816 operations */
166+ u32 backup_brgr ; /* BRGR saved during iso7816 operations */
164167 unsigned int tx_done_mask ;
165168 u32 fifo_size ;
166169 u32 rts_high ;
@@ -177,6 +180,10 @@ struct atmel_uart_port {
177180 unsigned int pending_status ;
178181 spinlock_t lock_suspended ;
179182
183+ /* ISO7816 */
184+ unsigned int fidi_min ;
185+ unsigned int fidi_max ;
186+
180187#ifdef CONFIG_PM
181188 struct {
182189 u32 cr ;
@@ -375,6 +382,127 @@ static int atmel_config_rs485(struct uart_port *port,
375382 return 0 ;
376383}
377384
385+ static unsigned int atmel_calc_cd (struct uart_port * port ,
386+ struct serial_iso7816 * iso7816conf )
387+ {
388+ struct atmel_uart_port * atmel_port = to_atmel_uart_port (port );
389+ unsigned int cd ;
390+ u64 mck_rate ;
391+
392+ mck_rate = (u64 )clk_get_rate (atmel_port -> clk );
393+ do_div (mck_rate , iso7816conf -> clk );
394+ cd = mck_rate ;
395+ return cd ;
396+ }
397+
398+ static unsigned int atmel_calc_fidi (struct uart_port * port ,
399+ struct serial_iso7816 * iso7816conf )
400+ {
401+ u64 fidi = 0 ;
402+
403+ if (iso7816conf -> sc_fi && iso7816conf -> sc_di ) {
404+ fidi = (u64 )iso7816conf -> sc_fi ;
405+ do_div (fidi , iso7816conf -> sc_di );
406+ }
407+ return (u32 )fidi ;
408+ }
409+
410+ /* Enable or disable the iso7816 support */
411+ /* Called with interrupts disabled */
412+ static int atmel_config_iso7816 (struct uart_port * port ,
413+ struct serial_iso7816 * iso7816conf )
414+ {
415+ struct atmel_uart_port * atmel_port = to_atmel_uart_port (port );
416+ unsigned int mode ;
417+ unsigned int cd , fidi ;
418+ int ret = 0 ;
419+
420+ /* Disable interrupts */
421+ atmel_uart_writel (port , ATMEL_US_IDR , atmel_port -> tx_done_mask );
422+
423+ mode = atmel_uart_readl (port , ATMEL_US_MR );
424+
425+ if (iso7816conf -> flags & SER_ISO7816_ENABLED ) {
426+ mode &= ~ATMEL_US_USMODE ;
427+
428+ if (iso7816conf -> tg > 255 ) {
429+ dev_err (port -> dev , "ISO7816: Timeguard exceeding 255\n" );
430+ memset (iso7816conf , 0 , sizeof (struct serial_iso7816 ));
431+ ret = - EINVAL ;
432+ goto err_out ;
433+ }
434+
435+ if ((iso7816conf -> flags & SER_ISO7816_T_PARAM )
436+ == SER_ISO7816_T (0 )) {
437+ mode |= ATMEL_US_USMODE_ISO7816_T0 | ATMEL_US_DSNACK ;
438+ } else if ((iso7816conf -> flags & SER_ISO7816_T_PARAM )
439+ == SER_ISO7816_T (1 )) {
440+ mode |= ATMEL_US_USMODE_ISO7816_T1 | ATMEL_US_INACK ;
441+ } else {
442+ dev_err (port -> dev , "ISO7816: Type not supported\n" );
443+ memset (iso7816conf , 0 , sizeof (struct serial_iso7816 ));
444+ ret = - EINVAL ;
445+ goto err_out ;
446+ }
447+
448+ mode &= ~(ATMEL_US_USCLKS | ATMEL_US_NBSTOP | ATMEL_US_PAR );
449+
450+ /* select mck clock, and output */
451+ mode |= ATMEL_US_USCLKS_MCK | ATMEL_US_CLKO ;
452+ /* set parity for normal/inverse mode + max iterations */
453+ mode |= ATMEL_US_PAR_EVEN | ATMEL_US_NBSTOP_1 | ATMEL_US_MAX_ITER (3 );
454+
455+ cd = atmel_calc_cd (port , iso7816conf );
456+ fidi = atmel_calc_fidi (port , iso7816conf );
457+ if (fidi == 0 ) {
458+ dev_warn (port -> dev , "ISO7816 fidi = 0, Generator generates no signal\n" );
459+ } else if (fidi < atmel_port -> fidi_min
460+ || fidi > atmel_port -> fidi_max ) {
461+ dev_err (port -> dev , "ISO7816 fidi = %u, value not supported\n" , fidi );
462+ memset (iso7816conf , 0 , sizeof (struct serial_iso7816 ));
463+ ret = - EINVAL ;
464+ goto err_out ;
465+ }
466+
467+ if (!(port -> iso7816 .flags & SER_ISO7816_ENABLED )) {
468+ /* port not yet in iso7816 mode: store configuration */
469+ atmel_port -> backup_mode = atmel_uart_readl (port , ATMEL_US_MR );
470+ atmel_port -> backup_brgr = atmel_uart_readl (port , ATMEL_US_BRGR );
471+ }
472+
473+ atmel_uart_writel (port , ATMEL_US_TTGR , iso7816conf -> tg );
474+ atmel_uart_writel (port , ATMEL_US_BRGR , cd );
475+ atmel_uart_writel (port , ATMEL_US_FIDI , fidi );
476+
477+ atmel_uart_writel (port , ATMEL_US_CR , ATMEL_US_TXDIS | ATMEL_US_RXEN );
478+ atmel_port -> tx_done_mask = ATMEL_US_TXEMPTY | ATMEL_US_NACK | ATMEL_US_ITERATION ;
479+ } else {
480+ dev_dbg (port -> dev , "Setting UART back to RS232\n" );
481+ /* back to last RS232 settings */
482+ mode = atmel_port -> backup_mode ;
483+ memset (iso7816conf , 0 , sizeof (struct serial_iso7816 ));
484+ atmel_uart_writel (port , ATMEL_US_TTGR , 0 );
485+ atmel_uart_writel (port , ATMEL_US_BRGR , atmel_port -> backup_brgr );
486+ atmel_uart_writel (port , ATMEL_US_FIDI , 0x174 );
487+
488+ if (atmel_use_pdc_tx (port ))
489+ atmel_port -> tx_done_mask = ATMEL_US_ENDTX |
490+ ATMEL_US_TXBUFE ;
491+ else
492+ atmel_port -> tx_done_mask = ATMEL_US_TXRDY ;
493+ }
494+
495+ port -> iso7816 = * iso7816conf ;
496+
497+ atmel_uart_writel (port , ATMEL_US_MR , mode );
498+
499+ err_out :
500+ /* Enable interrupts */
501+ atmel_uart_writel (port , ATMEL_US_IER , atmel_port -> tx_done_mask );
502+
503+ return ret ;
504+ }
505+
378506/*
379507 * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
380508 */
@@ -494,9 +622,12 @@ static void atmel_stop_tx(struct uart_port *port)
494622 /* Disable interrupts */
495623 atmel_uart_writel (port , ATMEL_US_IDR , atmel_port -> tx_done_mask );
496624
497- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
498- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX ))
499- atmel_start_rx (port );
625+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
626+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
627+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
628+ if (!atomic_read (& atmel_port -> tasklet_shutdown ))
629+ atmel_start_rx (port );
630+
500631}
501632
502633/*
@@ -513,8 +644,9 @@ static void atmel_start_tx(struct uart_port *port)
513644 return ;
514645
515646 if (atmel_use_pdc_tx (port ) || atmel_use_dma_tx (port ))
516- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
517- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX ))
647+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
648+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
649+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
518650 atmel_stop_rx (port );
519651
520652 if (atmel_use_pdc_tx (port ))
@@ -812,8 +944,9 @@ static void atmel_complete_tx_dma(void *arg)
812944 */
813945 if (!uart_circ_empty (xmit ))
814946 atmel_tasklet_schedule (atmel_port , & atmel_port -> tasklet_tx );
815- else if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
816- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) {
947+ else if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
948+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
949+ port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
817950 /* DMA done, stop TX, start RX for RS485 */
818951 atmel_start_rx (port );
819952 }
@@ -1295,6 +1428,9 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
12951428 wake_up_interruptible (& port -> state -> port .delta_msr_wait );
12961429 }
12971430 }
1431+
1432+ if (pending & (ATMEL_US_NACK | ATMEL_US_ITERATION ))
1433+ dev_dbg (port -> dev , "ISO7816 ERROR (0x%08x)\n" , pending );
12981434}
12991435
13001436/*
@@ -1387,8 +1523,9 @@ static void atmel_tx_pdc(struct uart_port *port)
13871523 atmel_uart_writel (port , ATMEL_US_IER ,
13881524 atmel_port -> tx_done_mask );
13891525 } else {
1390- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
1391- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) {
1526+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
1527+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
1528+ port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
13921529 /* DMA done, stop TX, start RX for RS485 */
13931530 atmel_start_rx (port );
13941531 }
@@ -1763,6 +1900,22 @@ static void atmel_get_ip_name(struct uart_port *port)
17631900 atmel_port -> has_frac_baudrate = true;
17641901 atmel_port -> has_hw_timer = true;
17651902 atmel_port -> rtor = ATMEL_US_RTOR ;
1903+ version = atmel_uart_readl (port , ATMEL_US_VERSION );
1904+ switch (version ) {
1905+ case 0x814 : /* sama5d2 */
1906+ /* fall through */
1907+ case 0x701 : /* sama5d4 */
1908+ atmel_port -> fidi_min = 3 ;
1909+ atmel_port -> fidi_max = 65535 ;
1910+ break ;
1911+ case 0x502 : /* sam9x5, sama5d3 */
1912+ atmel_port -> fidi_min = 3 ;
1913+ atmel_port -> fidi_max = 2047 ;
1914+ break ;
1915+ default :
1916+ atmel_port -> fidi_min = 1 ;
1917+ atmel_port -> fidi_max = 2047 ;
1918+ }
17661919 } else if (name == dbgu_uart ) {
17671920 dev_dbg (port -> dev , "Dbgu or uart without hw timer\n" );
17681921 } else {
@@ -2143,6 +2296,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
21432296 atmel_uart_writel (port , ATMEL_US_TTGR ,
21442297 port -> rs485 .delay_rts_after_send );
21452298 mode |= ATMEL_US_USMODE_RS485 ;
2299+ } else if (port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
2300+ atmel_uart_writel (port , ATMEL_US_TTGR , port -> iso7816 .tg );
2301+ /* select mck clock, and output */
2302+ mode |= ATMEL_US_USCLKS_MCK | ATMEL_US_CLKO ;
2303+ /* set max iterations */
2304+ mode |= ATMEL_US_MAX_ITER (3 );
2305+ if ((port -> iso7816 .flags & SER_ISO7816_T_PARAM )
2306+ == SER_ISO7816_T (0 ))
2307+ mode |= ATMEL_US_USMODE_ISO7816_T0 ;
2308+ else
2309+ mode |= ATMEL_US_USMODE_ISO7816_T1 ;
21462310 } else if (termios -> c_cflag & CRTSCTS ) {
21472311 /* RS232 with hardware handshake (RTS/CTS) */
21482312 if (atmel_use_fifo (port ) &&
@@ -2219,7 +2383,8 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
22192383 }
22202384 quot = cd | fp << ATMEL_US_FP_OFFSET ;
22212385
2222- atmel_uart_writel (port , ATMEL_US_BRGR , quot );
2386+ if (!(port -> iso7816 .flags & SER_ISO7816_ENABLED ))
2387+ atmel_uart_writel (port , ATMEL_US_BRGR , quot );
22232388 atmel_uart_writel (port , ATMEL_US_CR , ATMEL_US_RSTSTA | ATMEL_US_RSTRX );
22242389 atmel_uart_writel (port , ATMEL_US_CR ,
22252390 mdrop | ATMEL_US_TXEN | ATMEL_US_RXEN );
@@ -2401,7 +2566,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
24012566 port -> mapbase = mpdev -> resource [0 ].start ;
24022567 port -> irq = mpdev -> resource [1 ].start ;
24032568 port -> rs485_config = atmel_config_rs485 ;
2404- port -> membase = NULL ;
2569+ port -> iso7816_config = atmel_config_iso7816 ;
2570+ port -> membase = NULL ;
24052571
24062572 memset (& atmel_port -> rx_ring , 0 , sizeof (atmel_port -> rx_ring ));
24072573
@@ -2424,8 +2590,12 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
24242590 /* only enable clock when USART is in use */
24252591 }
24262592
2427- /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
2428- if (port -> rs485 .flags & SER_RS485_ENABLED )
2593+ /*
2594+ * Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or
2595+ * ENDTX|TXBUFE
2596+ */
2597+ if (port -> rs485 .flags & SER_RS485_ENABLED ||
2598+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
24292599 atmel_port -> tx_done_mask = ATMEL_US_TXEMPTY ;
24302600 else if (atmel_use_pdc_tx (port )) {
24312601 port -> fifosize = PDC_BUFFER_SIZE ;
0 commit comments