summaryrefslogtreecommitdiff
path: root/firmware/src/simtrace/iso7816_uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/src/simtrace/iso7816_uart.c')
-rw-r--r--firmware/src/simtrace/iso7816_uart.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/firmware/src/simtrace/iso7816_uart.c b/firmware/src/simtrace/iso7816_uart.c
index 9022830..6ed797c 100644
--- a/firmware/src/simtrace/iso7816_uart.c
+++ b/firmware/src/simtrace/iso7816_uart.c
@@ -11,6 +11,7 @@
#include <os/usb_handler.h>
#include <os/dbgu.h>
+#include <os/pio_irq.h>
#include "../simtrace.h"
#include "../openpcd.h"
@@ -111,14 +112,18 @@ static void set_atr_state(struct iso7816_3_handle *ih, enum atr_state new_atrs)
static void set_state(struct iso7816_3_handle *ih, enum iso7816_3_state new_state)
{
- if (new_state == ISO7816_S_WAIT_ATR) {
+ if (new_state == ISO7816_S_RESET) {
+ usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX;
+ } else if (new_state == ISO7816_S_WAIT_ATR) {
int rc;
/* Initial Fi / Di ratio */
ih->fi = 1;
ih->di = 1;
rc = compute_fidi_ratio(ih->fi, ih->di);
DEBUGPCRF("computed Fi(%u) Di(%u) ratio: %d", ih->fi, ih->di, rc);
+ usart->US_CR |= AT91C_US_RXDIS | AT91C_US_RSTRX;
usart->US_FIDI = rc & 0x3ff;
+ usart->US_CR |= AT91C_US_RXEN;
set_atr_state(ih, ATR_S_WAIT_TS);
} else if (new_state == ISO7816_S_WAIT_READER) {
/* CLA INS P1 P2 LEN */
@@ -157,11 +162,11 @@ static enum atr_state next_intb_state(struct iso7816_3_handle *ih, u_int8_t ch)
DEBUGPCR("found Fi=%u Di=%u", ih->fi, ih->di);
}
goto from_ta;
+ default:
+ DEBUGPCR("something wrong, old_state != TA");
+ return ATR_S_WAIT_TCK;
}
- DEBUGPCR("something wrong, old_state != TA");
- return ATR_S_WAIT_TCK;
-
from_td:
if (ih->atr_last_td & 0x10)
return ATR_S_WAIT_TA;
@@ -278,7 +283,7 @@ void process_byte(struct iso7816_3_handle *ih, u_int8_t byte)
new_state = process_byte_reader(ih, byte);
break;
case ISO7816_S_WAIT_CARD:
- //new_state = process_byte_card(ih, byte);
+ new_state = process_byte_card(ih, byte);
break;
}
@@ -286,7 +291,7 @@ void process_byte(struct iso7816_3_handle *ih, u_int8_t byte)
set_state(ih, new_state);
}
-static int __ramfunc usart_irq(void)
+static __ramfunc void usart_irq(void)
{
u_int32_t csr = usart->US_CSR;
u_int8_t octet;
@@ -309,6 +314,18 @@ static int __ramfunc usart_irq(void)
}
}
+/* handler for the RST input pin state change */
+static void reset_pin_irq(u_int32_t pio)
+{
+ if (!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, pio)) {
+ DEBUGPCR("nRST");
+ set_state(&isoh, ISO7816_S_RESET);
+ } else {
+ DEBUGPCR("RST");
+ set_state(&isoh, ISO7816_S_WAIT_ATR);
+ }
+}
+
void iso_uart_dump(void)
{
u_int32_t csr = usart->US_CSR;
@@ -318,7 +335,7 @@ void iso_uart_dump(void)
void iso_uart_rst(unsigned int state)
{
- DEBUGPCR("USART nRST set state=%u", state);
+ DEBUGPCR("USART set nRST set state=%u", state);
switch (state) {
case 0:
AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
@@ -341,10 +358,9 @@ void iso_uart_rx_mode(void)
usart->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME |
AT91C_US_PARE | AT91C_US_NACK | AT91C_US_ITERATION;
- /* Enable the receiver */
- usart->US_CR = AT91C_US_RXEN;
- set_state(&isoh, ISO7816_S_WAIT_ATR);
+ /* call interrupt handler once to set initial state RESET / ATR */
+ reset_pin_irq(SIMTRACE_PIO_nRST);
}
void iso_uart_clk_master(unsigned int master)
@@ -367,23 +383,23 @@ void iso_uart_init(void)
{
DEBUGPCR("USART Initializing");
+ /* make sure we get clock from the power management controller */
AT91F_US0_CfgPMC();
/* configure all 3 signals as input */
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, SIMTRACE_PIO_IO, SIMTRACE_PIO_CLK);
-
AT91F_PIO_CfgInput(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US0,
OPENPCD_IRQ_PRIO_USART,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &usart_irq);
-
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_US0);
usart->US_CR = AT91C_US_RXDIS | AT91C_US_TXDIS | (AT91C_US_RSTRX | AT91C_US_RSTTX);
/* FIXME: wait for some time */
usart->US_CR = AT91C_US_RXDIS | AT91C_US_TXDIS;
+ /* ISO7816 T=0 mode with external clock input */
usart->US_MR = AT91C_US_USMODE_ISO7816_0 | AT91C_US_CLKS_EXT |
AT91C_US_CHRL_8_BITS | AT91C_US_NBSTOP_1_BIT |
AT91C_US_CKLO;
@@ -396,4 +412,8 @@ void iso_uart_init(void)
usart->US_RTOR = 0;
/* Disable Transmitter Timeguard */
usart->US_TTGR = 0;
+
+ pio_irq_register(SIMTRACE_PIO_nRST, &reset_pin_irq);
+ AT91F_PIO_CfgInputFilter(AT91C_BASE_PIOA, SIMTRACE_PIO_nRST);
+ pio_irq_enable(SIMTRACE_PIO_nRST);
}
personal git repositories of Harald Welte. Your mileage may vary