cuart icc clock freq and divider setting support
Change-Id: I9c99c68511d3972513348ee6be5e7bb3b3a5f99e
diff --git a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
index f9856f3..a8f8044 100644
--- a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
+++ b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
@@ -289,6 +289,8 @@
cuart->u.asf4.usa_pd = usa_pd;
cuart->u.asf4.slot_nr = slot_nr;
+ /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/
+ cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);
usart_async_register_callback(usa_pd, USART_ASYNC_RXC_CB, SIM_rx_cb[slot_nr]);
usart_async_register_callback(usa_pd, USART_ASYNC_TXC_CB, SIM_tx_cb[slot_nr]);
@@ -338,6 +340,8 @@
return io_read(&usa_pd->io, data, len);
}
+#include "ccid_device.h"
+#include "iso7816_3.h"
static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg)
{
struct ncn8025_settings settings;
@@ -349,7 +353,7 @@
sercom->USART.CTRLB.bit.RXEN = 1;
sercom->USART.CTRLB.bit.TXEN = 0;
} else {
- delay_us(100);
+ delay_us(cuart->u.asf4.extrawait_after_rx);
sercom->USART.CTRLB.bit.RXEN = 0;
sercom->USART.CTRLB.bit.TXEN = 1;
}
@@ -361,22 +365,47 @@
usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd);
break;
case CUART_CTL_POWER:
- ncn8025_get(cuart->u.asf4.slot_nr, &settings);
- settings.cmdvcc = arg ? true : false;
- settings.led = arg ? true : false;
- settings.vsel = SIM_VOLT_5V0;
+ /* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/
+ cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);
// set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)
if(arg)
slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);
+ ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+ settings.cmdvcc = arg ? true : false;
+ settings.led = arg ? true : false;
+ settings.vsel = SIM_VOLT_5V0;
ncn8025_set(cuart->u.asf4.slot_nr, &settings);
+
break;
case CUART_CTL_WTIME:
/* no driver-specific handling of this */
break;
case CUART_CTL_CLOCK:
- /* FIXME */
+ /* no clock stop support */
+ break;
+ case CUART_CTL_CLOCK_FREQ:
+ ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+
+ /* 2,5/5/10/20 supported by dividers */
+ enum ncn8025_sim_clkdiv clkdiv = SIM_CLKDIV_1;
+ if(arg < 20000000)
+ clkdiv = SIM_CLKDIV_2;
+ if(arg < 10000000)
+ clkdiv = SIM_CLKDIV_4;
+ if(arg < 5000000)
+ clkdiv = SIM_CLKDIV_8;
+ settings.clkdiv = clkdiv;
+ ncn8025_set(cuart->u.asf4.slot_nr, &settings);
+ break;
+ case CUART_CTL_FD:
+ ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+ uint8_t divider = ncn8025_div_val[settings.clkdiv];
+ uint32_t baudrate = (20e6/divider)/arg;
+ cuart->u.asf4.extrawait_after_rx = 1./baudrate * 1000 * 1000;
+ slot_set_baudrate(cuart->u.asf4.slot_nr, baudrate);
+ break;
default:
return -EINVAL;
}
diff --git a/sysmoOCTSIM/ncn8025.c b/sysmoOCTSIM/ncn8025.c
index 540b166..74d3b39 100644
--- a/sysmoOCTSIM/ncn8025.c
+++ b/sysmoOCTSIM/ncn8025.c
@@ -159,7 +159,7 @@
[SIM_VOLT_1V8] = "1.8",
};
-static const unsigned int div_val[] = {
+const unsigned int ncn8025_div_val[] = {
[SIM_CLKDIV_1] = 1,
[SIM_CLKDIV_2] = 2,
[SIM_CLKDIV_4] = 4,
@@ -168,7 +168,7 @@
void ncn8025_dump(const struct ncn8025_settings *set)
{
- printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], div_val[set->clkdiv]);
+ printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], ncn8025_div_val[set->clkdiv]);
if (set->rstin)
printf(", RST");
if (set->cmdvcc)
diff --git a/sysmoOCTSIM/ncn8025.h b/sysmoOCTSIM/ncn8025.h
index 2e774a7..01ddc97 100644
--- a/sysmoOCTSIM/ncn8025.h
+++ b/sysmoOCTSIM/ncn8025.h
@@ -14,6 +14,8 @@
SIM_CLKDIV_8 = 0,
};
+extern const unsigned int ncn8025_div_val[];
+
struct ncn8025_settings {
bool rstin; /* Reset signal (true: asserted low) */
bool cmdvcc; /* Command VCC pin. Activation sequence Enable (true: active low) */