icE1usb fw: Expose error conditions from E1 driver
This will allow the USB interface code to report the errors to the
host PC.
Related: OS#4674
Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed
diff --git a/firmware/ice40-riscv/icE1usb/usb_e1.c b/firmware/ice40-riscv/icE1usb/usb_e1.c
index 0698de5..bbbb24e 100644
--- a/firmware/ice40-riscv/icE1usb/usb_e1.c
+++ b/firmware/ice40-riscv/icE1usb/usb_e1.c
@@ -25,6 +25,7 @@
int in_bdi; /* buffer descriptor index for IN EP */
struct ice1usb_tx_config tx_cfg;
struct ice1usb_rx_config rx_cfg;
+ struct e1_error_count last_err;
} g_usb_e1;
/* default configuration at power-up */
@@ -87,6 +88,29 @@
if (!g_usb_e1.running)
return;
+ /* EP3 IRQ */
+ if ((usb_ep_regs[3].in.bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {
+ const struct e1_error_count *cur_err = e1_get_error_count();
+ if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) {
+ struct ice1usb_irq errmsg = {
+ .type = ICE1USB_IRQ_T_ERRCNT,
+ .u = {
+ .errors = {
+ .crc = cur_err->crc,
+ .align = cur_err->align,
+ .ovfl = cur_err->ovfl,
+ .unfl = cur_err->unfl,
+ .flags = cur_err->flags,
+ }
+ }
+ };
+ printf("E");
+ usb_data_write(usb_ep_regs[3].in.bd[0].ptr, &errmsg, sizeof(errmsg));
+ usb_ep_regs[3].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));
+ g_usb_e1.last_err = *cur_err;
+ }
+ }
+
/* EP2 IN */
bdi = g_usb_e1.in_bdi;
@@ -213,6 +237,7 @@
usb_ep_boot(intf, 0x01, true);
usb_ep_boot(intf, 0x81, true);
usb_ep_boot(intf, 0x82, true);
+ usb_ep_boot(intf, 0x83, true);
return USB_FND_SUCCESS;
}
@@ -274,6 +299,11 @@
/* EP1 IN: Queue buffer */
_usb_fill_feedback_ep();
+ /* EP3 IN: Interrupt */
+ usb_ep_regs[3].in.status = USB_EP_TYPE_INT;
+ usb_ep_regs[3].in.bd[0].ptr = 68;
+ usb_ep_regs[3].in.bd[0].csr = 0;
+
return USB_FND_SUCCESS;
}