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 ;
@@ -176,6 +179,10 @@ struct atmel_uart_port {
176179 unsigned int pending_status ;
177180 spinlock_t lock_suspended ;
178181
182+ /* ISO7816 */
183+ unsigned int fidi_min ;
184+ unsigned int fidi_max ;
185+
179186#ifdef CONFIG_PM
180187 struct {
181188 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 */
@@ -489,8 +617,9 @@ static void atmel_stop_tx(struct uart_port *port)
489617 /* Disable interrupts */
490618 atmel_uart_writel (port , ATMEL_US_IDR , atmel_port -> tx_done_mask );
491619
492- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
493- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX ))
620+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
621+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
622+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
494623 atmel_start_rx (port );
495624}
496625
@@ -508,8 +637,9 @@ static void atmel_start_tx(struct uart_port *port)
508637 return ;
509638
510639 if (atmel_use_pdc_tx (port ) || atmel_use_dma_tx (port ))
511- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
512- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX ))
640+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
641+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
642+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
513643 atmel_stop_rx (port );
514644
515645 if (atmel_use_pdc_tx (port ))
@@ -806,8 +936,9 @@ static void atmel_complete_tx_dma(void *arg)
806936 */
807937 if (!uart_circ_empty (xmit ))
808938 atmel_tasklet_schedule (atmel_port , & atmel_port -> tasklet_tx );
809- else if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
810- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) {
939+ else if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
940+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
941+ port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
811942 /* DMA done, stop TX, start RX for RS485 */
812943 atmel_start_rx (port );
813944 }
@@ -1287,6 +1418,9 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
12871418 wake_up_interruptible (& port -> state -> port .delta_msr_wait );
12881419 }
12891420 }
1421+
1422+ if (pending & (ATMEL_US_NACK | ATMEL_US_ITERATION ))
1423+ dev_dbg (port -> dev , "ISO7816 ERROR (0x%08x)\n" , pending );
12901424}
12911425
12921426/*
@@ -1379,8 +1513,9 @@ static void atmel_tx_pdc(struct uart_port *port)
13791513 atmel_uart_writel (port , ATMEL_US_IER ,
13801514 atmel_port -> tx_done_mask );
13811515 } else {
1382- if ((port -> rs485 .flags & SER_RS485_ENABLED ) &&
1383- !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) {
1516+ if (((port -> rs485 .flags & SER_RS485_ENABLED ) &&
1517+ !(port -> rs485 .flags & SER_RS485_RX_DURING_TX )) ||
1518+ port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
13841519 /* DMA done, stop TX, start RX for RS485 */
13851520 atmel_start_rx (port );
13861521 }
@@ -1755,6 +1890,22 @@ static void atmel_get_ip_name(struct uart_port *port)
17551890 atmel_port -> has_frac_baudrate = true;
17561891 atmel_port -> has_hw_timer = true;
17571892 atmel_port -> rtor = ATMEL_US_RTOR ;
1893+ version = atmel_uart_readl (port , ATMEL_US_VERSION );
1894+ switch (version ) {
1895+ case 0x814 : /* sama5d2 */
1896+ /* fall through */
1897+ case 0x701 : /* sama5d4 */
1898+ atmel_port -> fidi_min = 3 ;
1899+ atmel_port -> fidi_max = 65535 ;
1900+ break ;
1901+ case 0x502 : /* sam9x5, sama5d3 */
1902+ atmel_port -> fidi_min = 3 ;
1903+ atmel_port -> fidi_max = 2047 ;
1904+ break ;
1905+ default :
1906+ atmel_port -> fidi_min = 1 ;
1907+ atmel_port -> fidi_max = 2047 ;
1908+ }
17581909 } else if (name == dbgu_uart ) {
17591910 dev_dbg (port -> dev , "Dbgu or uart without hw timer\n" );
17601911 } else {
@@ -2128,6 +2279,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
21282279 atmel_uart_writel (port , ATMEL_US_TTGR ,
21292280 port -> rs485 .delay_rts_after_send );
21302281 mode |= ATMEL_US_USMODE_RS485 ;
2282+ } else if (port -> iso7816 .flags & SER_ISO7816_ENABLED ) {
2283+ atmel_uart_writel (port , ATMEL_US_TTGR , port -> iso7816 .tg );
2284+ /* select mck clock, and output */
2285+ mode |= ATMEL_US_USCLKS_MCK | ATMEL_US_CLKO ;
2286+ /* set max iterations */
2287+ mode |= ATMEL_US_MAX_ITER (3 );
2288+ if ((port -> iso7816 .flags & SER_ISO7816_T_PARAM )
2289+ == SER_ISO7816_T (0 ))
2290+ mode |= ATMEL_US_USMODE_ISO7816_T0 ;
2291+ else
2292+ mode |= ATMEL_US_USMODE_ISO7816_T1 ;
21312293 } else if (termios -> c_cflag & CRTSCTS ) {
21322294 /* RS232 with hardware handshake (RTS/CTS) */
21332295 if (atmel_use_fifo (port ) &&
@@ -2204,7 +2366,8 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
22042366 }
22052367 quot = cd | fp << ATMEL_US_FP_OFFSET ;
22062368
2207- atmel_uart_writel (port , ATMEL_US_BRGR , quot );
2369+ if (!(port -> iso7816 .flags & SER_ISO7816_ENABLED ))
2370+ atmel_uart_writel (port , ATMEL_US_BRGR , quot );
22082371 atmel_uart_writel (port , ATMEL_US_CR , ATMEL_US_RSTSTA | ATMEL_US_RSTRX );
22092372 atmel_uart_writel (port , ATMEL_US_CR , ATMEL_US_TXEN | ATMEL_US_RXEN );
22102373
@@ -2383,6 +2546,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
23832546 port -> mapbase = pdev -> resource [0 ].start ;
23842547 port -> irq = pdev -> resource [1 ].start ;
23852548 port -> rs485_config = atmel_config_rs485 ;
2549+ port -> iso7816_config = atmel_config_iso7816 ;
23862550 port -> membase = NULL ;
23872551
23882552 memset (& atmel_port -> rx_ring , 0 , sizeof (atmel_port -> rx_ring ));
@@ -2406,8 +2570,12 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
24062570 /* only enable clock when USART is in use */
24072571 }
24082572
2409- /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
2410- if (port -> rs485 .flags & SER_RS485_ENABLED )
2573+ /*
2574+ * Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or
2575+ * ENDTX|TXBUFE
2576+ */
2577+ if (port -> rs485 .flags & SER_RS485_ENABLED ||
2578+ port -> iso7816 .flags & SER_ISO7816_ENABLED )
24112579 atmel_port -> tx_done_mask = ATMEL_US_TXEMPTY ;
24122580 else if (atmel_use_pdc_tx (port )) {
24132581 port -> fifosize = PDC_BUFFER_SIZE ;
0 commit comments