icE1usb fw: Use green per-port LED to indicate alignment status

Whenever Rx is aligned, the green LED is permanently on.
Whenever Rx is not aligned, the green LED is blinking.

What's missing is to check for E1 clock ticks and turn the LED off
completely if there are no clock ticks.

Change-Id: I42d53544858dbbbae5206d9a62b08672966c9ebf
diff --git a/firmware/ice40-riscv/icE1usb/e1.c b/firmware/ice40-riscv/icE1usb/e1.c
index 0f1d89d..ad12fe2 100644
--- a/firmware/ice40-riscv/icE1usb/e1.c
+++ b/firmware/ice40-riscv/icE1usb/e1.c
@@ -412,10 +412,14 @@
 		return;
 
 	/* HACK: LED link status */
-	if (e1_regs->rx.csr & E1_RX_SR_ALIGNED)
+	if (e1_regs->rx.csr & E1_RX_SR_ALIGNED) {
+		e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_ON);
 		led_color(0, 48, 0);
-	else
+	} else {
+		e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_BLINK);
+		/* TODO: completely off if rx tick counter not incrementing */
 		led_color(48, 0, 0);
+	}
 
 	/* Recover any done TX BD */
 	while ( (bd = e1_regs->tx.bd) & E1_BD_VALID ) {
diff --git a/firmware/ice40-riscv/icE1usb/e1.h b/firmware/ice40-riscv/icE1usb/e1.h
index e68514f..c438cb9 100644
--- a/firmware/ice40-riscv/icE1usb/e1.h
+++ b/firmware/ice40-riscv/icE1usb/e1.h
@@ -13,3 +13,19 @@
 
 volatile uint8_t *e1_data_ptr(int mf, int frame, int ts);
 unsigned int e1_data_ofs(int mf, int frame, int ts);
+
+enum e1_platform_led {
+	E1P_LED_GREEN		= 0,
+	E1P_LED_YELLOW		= 1,
+};
+
+enum e1_platform_led_state {
+	E1P_LED_ST_OFF		= 0,
+	E1P_LED_ST_ON		= 1,
+	E1P_LED_ST_BLINK	= 2,
+	E1P_LED_ST_BLINK_FAST	= 3
+};
+
+/* external function provided by the platform; used by E1 driver to control LEDs */
+extern void e1_platform_led_set(uint8_t port, enum e1_platform_led led,
+				enum e1_platform_led_state state);
diff --git a/firmware/ice40-riscv/icE1usb/misc.c b/firmware/ice40-riscv/icE1usb/misc.c
index dca126a..3117be9 100644
--- a/firmware/ice40-riscv/icE1usb/misc.c
+++ b/firmware/ice40-riscv/icE1usb/misc.c
@@ -10,6 +10,7 @@
 
 #include "config.h"
 #include "misc.h"
+#include "e1.h"
 
 
 struct misc {
@@ -51,6 +52,24 @@
 	misc_regs->e1_led = (enable ? 0x100 : 0x000) | cfg;
 }
 
+void
+e1_platform_led_set(uint8_t port, enum e1_platform_led led,
+		    enum e1_platform_led_state state)
+{
+	uint32_t tmp;
+	unsigned int shift;
+
+	if (port >= 2)
+		return;
+
+	shift = 4*port + 2*led;
+
+	tmp = misc_regs->e1_led;
+	tmp &= ~(3 << shift);
+	tmp |= 0x100 | ((state & 3) << shift);
+	misc_regs->e1_led = tmp;
+}
+
 uint16_t
 e1_tick_read(void)
 {