aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-05-17 00:25:14 +0200
committerHarald Welte <laforge@gnumonks.org>2018-05-17 00:25:14 +0200
commit1626391425ac1b18337c2cd36063db2e89bfb3c8 (patch)
tree27c77af6c30744cd954dda7f23ac5d6ca5677077
parentc853db4ca17d1ed3633e776ffe64d51cb902c235 (diff)
Add SPI support for the IDT82v2081 LIU chip
-rw-r--r--sam/applications/sam_e1/e1_ssc_tc.c19
-rw-r--r--sam/applications/sam_e1/idt82v2081.c122
-rw-r--r--sam/applications/sam_e1/idt82v2081.h34
-rw-r--r--sam/applications/sam_e1/idt82v2081_asf.c82
-rw-r--r--sam/applications/sam_e1/idt82v2081_asf.h7
-rw-r--r--sam/applications/sam_e1/idt82v2081_regs.h81
-rw-r--r--sam/applications/sam_e1/main.c8
-rw-r--r--sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h2
-rw-r--r--sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk2
9 files changed, 345 insertions, 12 deletions
diff --git a/sam/applications/sam_e1/e1_ssc_tc.c b/sam/applications/sam_e1/e1_ssc_tc.c
index 672a84e4..4b0370a2 100644
--- a/sam/applications/sam_e1/e1_ssc_tc.c
+++ b/sam/applications/sam_e1/e1_ssc_tc.c
@@ -127,6 +127,13 @@ void e1_init_gpio()
pio_configure_pin(PIO_PA20_IDX, PIO_PERIPH_A); /* RF */
pio_configure_pin(PIO_PC26_IDX, PIO_PERIPH_B); /* TIOA4 */
//pio_configure_pin(PIO_PC27_IDX, PIO_PERIPH_B); /* TIOB4 */
+
+ /* SPI to LIU */
+ pio_configure_pin(PIO_PC27_IDX, PIO_INPUT); /* !LIU_INT */
+ pio_configure_pin(PIO_PA9_IDX, PIO_PERIPH_B); /* NPCS1 / !LIU_CS */
+ pio_configure_pin(PIO_PA12_IDX, PIO_PERIPH_A); /* LIU_MISO */
+ pio_configure_pin(PIO_PA14_IDX, PIO_PERIPH_A); /* LIU_SCLK */
+ pio_configure_pin(PIO_PA13_IDX, PIO_PERIPH_A); /* LIU_MOSI */
}
void e1_ssc_init()
@@ -220,15 +227,3 @@ void e1_ssc_init()
ssc_enable_tx(SSC);
#endif
}
-
-#if 0
-static struct idt82 g_idt;
-
-static void idt_init()
-{
- idt82_at91_init(&g_idt, SPI, ID_SPI, );
- idt82_init(&g_idt);
- idt82_mode(&g_idt, IDT_MODE_E1);
- idt82_termination(&g_idt, IDT_TERM_INT_120);
-}
-#endif
diff --git a/sam/applications/sam_e1/idt82v2081.c b/sam/applications/sam_e1/idt82v2081.c
new file mode 100644
index 00000000..59cae9ee
--- /dev/null
+++ b/sam/applications/sam_e1/idt82v2081.c
@@ -0,0 +1,122 @@
+#include <stdint.h>
+
+#include "idt82v2081.h"
+#include "idt82v2081_regs.h"
+
+/*! \brief Set or clear some (masked) bits inside a register
+ * \param[in] e4k reference to the tuner
+ * \param[in] reg number of the register
+ * \param[in] mask bit-mask of the value
+ * \param[in] val data value to be written to register
+ * \returns 0 on success, negative in case of error
+ */
+static int idt82_reg_set_bit_mask(struct idt82 *idt, uint8_t reg,
+ uint8_t mask, uint8_t val)
+{
+ uint8_t tmp = idt82_reg_read(idt, reg);
+
+ if ((tmp & mask) == val)
+ return 0;
+
+ return idt82_reg_write(idt, reg, (tmp & ~mask) | (val & mask));
+}
+
+int idt82_termination(struct idt82 *idt, enum idt82_term term)
+{
+ uint8_t puls, scal;
+
+ idt82_reg_set_bit_mask(idt, IDT_REG_TERM, term | (term << IDT_TERM_T_SHIFT),
+ IDT_TERM_T_MASK | IDT_TERM_R_MASK);
+
+ switch (idt->mode) {
+ case IDT_MODE_E1:
+ if (term == IDT_TERM_INT_75)
+ puls = 0;
+ else
+ puls = 1;
+ scal = 0x21;
+ break;
+ case IDT_MODE_T1:
+ /* FIXME: different length! */
+ puls = 2;
+ scal = 0x36;
+ break;
+ case IDT_MODE_J1:
+ puls = 7;
+ scal = 0x36;
+ break;
+ }
+
+ idt82_reg_set_bit_mask(idt, IDT_REG_TCF1, puls, IDT_TCF1_PULS_MASK);
+ idt82_reg_set_bit_mask(idt, IDT_REG_TCF2, scal, IDT_TCF2_SCAL_MASK);
+
+ idt->term = term;
+
+ return 0;
+}
+
+int idt82_mode(struct idt82 *idt, enum idt82_mode mode)
+{
+ switch (mode) {
+ case IDT_MODE_E1:
+ idt82_reg_set_bit_mask(idt, IDT_REG_GCF, IDT_GCF_T1E1_E1,
+ IDT_GCF_T1E1_MASK);
+ break;
+ case IDT_MODE_T1:
+ case IDT_MODE_J1:
+ idt82_reg_set_bit_mask(idt, IDT_REG_GCF, IDT_GCF_T1E1_T1,
+ IDT_GCF_T1E1_MASK);
+ break;
+ }
+ idt->mode = mode;
+
+ return 0;
+}
+
+int idt82_get_errcount(struct idt82 *idt)
+{
+ uint16_t ret;
+ int rc;
+
+ rc = idt82_reg_read(idt, IDT_REG_CNT0);
+ if (rc < 0)
+ return ret;
+
+ ret = rc;
+
+ rc = idt82_reg_read(idt, IDT_REG_CNT1);
+ if (rc < 0)
+ return ret;
+
+ ret |= (rc << 8);
+
+ return ret;
+
+}
+
+/* return in dB, range is return value ... (value + 2) */
+int idt82_get_line_att(struct idt82 *idt)
+{
+ int rc;
+
+ rc = idt82_reg_read(idt, IDT_REG_STAT1);
+ if (rc < 0)
+ return rc;
+
+ return (rc & IDT_STAT1_ATT_MASK)*2;
+}
+
+int idt82_init(struct idt82 *idt)
+{
+ idt82_reg_write(idt, IDT_REG_GCF, 0);
+ idt82_reg_write(idt, IDT_REG_JACF, 0);
+ idt82_reg_write(idt, IDT_REG_TCF0, 0);
+ idt82_reg_write(idt, IDT_REG_TCF1, 0);
+ idt82_reg_write(idt, IDT_REG_RCF1, 0); /* short haul */
+
+ idt82_mode(idt, IDT_MODE_E1);
+ idt82_termination(idt, IDT_TERM_INT_120);
+
+ return 0;
+}
+
diff --git a/sam/applications/sam_e1/idt82v2081.h b/sam/applications/sam_e1/idt82v2081.h
new file mode 100644
index 00000000..191ae632
--- /dev/null
+++ b/sam/applications/sam_e1/idt82v2081.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <stdint.h>
+
+enum idt82_term {
+ IDT_TERM_INT_75 = 0,
+ IDT_TERM_INT_120,
+ IDT_TERM_INT_100,
+ IDT_TERM_INT_110,
+ IDT_TERM_EXT,
+};
+
+enum idt82_mode {
+ IDT_MODE_E1 = 0,
+ IDT_MODE_T1,
+ IDT_MODE_J1,
+};
+
+struct idt82 {
+ enum idt82_mode mode;
+ enum idt82_term term;
+ void *priv;
+ uint8_t cs;
+};
+
+int idt82_termination(struct idt82 *idt, enum idt82_term term);
+int idt82_mode(struct idt82 *idt, enum idt82_mode mode);
+int idt82_get_errcount(struct idt82 *idt);
+int idt82_get_line_att(struct idt82 *idt);
+int idt82_init(struct idt82 *idt);
+
+/* callbacks into transport */
+int idt82_reg_write(struct idt82 *idt, uint8_t reg, uint8_t val);
+int idt82_reg_read(struct idt82 *idt, uint8_t reg);
diff --git a/sam/applications/sam_e1/idt82v2081_asf.c b/sam/applications/sam_e1/idt82v2081_asf.c
new file mode 100644
index 00000000..753dfa6e
--- /dev/null
+++ b/sam/applications/sam_e1/idt82v2081_asf.c
@@ -0,0 +1,82 @@
+#include <stdint.h>
+#include <asf.h>
+
+#include "idt82v2081.h"
+#include "idt82v2081_asf.h"
+
+/* Adaption layer between idt82 driver and Atmel ASF SPI driver */
+
+/*! reverse the bit order in a byte
+ * \param[in] x 8bit input value
+ * \returns 8bit value where bits order has been reversed
+ *
+ * See Chapter 7 "Hackers Delight"
+ */
+static uint32_t osmo_revbytebits_8(uint8_t x)
+{
+ x = (x & 0x55) << 1 | (x & 0xAA) >> 1;
+ x = (x & 0x33) << 2 | (x & 0xCC) >> 2;
+ x = (x & 0x0F) << 4 | (x & 0xF0) >> 4;
+
+ return x;
+}
+
+#define B_READ (1 << 5)
+
+static struct spi_device g_spidev = {
+ .id = 1,
+};
+
+/* backend function for core idt82 driver */
+int idt82_reg_read(struct idt82 *idt, uint8_t reg)
+{
+ uint8_t req[2] = { (reg & 0x1F) | B_READ, 0 };
+ uint8_t res[2];
+
+ req[0] = osmo_revbytebits_8(req[0]);
+ req[1] = osmo_revbytebits_8(req[1]);
+
+ spi_select_device(idt->priv, &g_spidev);
+#if 0
+ spi_write_packet(idt->priv, (reg & 0x1F) | B_READ, 16);
+ while (!SPI_IsFinished(idt->priv));
+ spi_read_packet(idt->priv, &res, 16);
+#else
+ spi_transceive_packet(idt->priv, req, res, sizeof(res));
+#endif
+ spi_deselect_device(idt->priv, &g_spidev);
+ res[1] = osmo_revbytebits_8(res[1]);
+
+ return res[1];
+}
+/* backend function for core idt82 driver */
+int idt82_reg_write(struct idt82 *idt, uint8_t reg, uint8_t val)
+{
+ uint8_t req[2] = { (reg & 0x1F), val };
+ req[0] = osmo_revbytebits_8(req[0]);
+ req[1] = osmo_revbytebits_8(req[1]);
+
+ spi_select_device(idt->priv, &g_spidev);
+ spi_write_packet(idt->priv, req, sizeof(req));
+ spi_deselect_device(idt->priv, &g_spidev);
+
+ return 0;
+}
+
+/* initialize the SPI interface to the IDT82 */
+int idt82_asf_init(struct idt82 *idt, Spi *spi, uint8_t cs)
+{
+ g_spidev.id = cs;
+ idt->priv = spi;
+
+ printf("%s: spi=%p, cs=%u\n\r", __func__, spi, cs);
+
+ pmc_enable_periph_clk(ID_SPI);
+
+ spi_master_init(idt->priv);
+ spi_master_setup_device(idt->priv, &g_spidev, SPI_MODE_0, 100000, cs);
+ //spi_configure_cs_behavior(idt->priv, g_spidev.id, SPI_CS_RISE_NO_TX);
+ spi_enable(idt->priv);
+
+ return 0;
+}
diff --git a/sam/applications/sam_e1/idt82v2081_asf.h b/sam/applications/sam_e1/idt82v2081_asf.h
new file mode 100644
index 00000000..90c3ec26
--- /dev/null
+++ b/sam/applications/sam_e1/idt82v2081_asf.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdint.h>
+
+#include "idt82v2081.h"
+
+int idt82_asf_init(struct idt82 *idt, Spi *spi, uint8_t cs);
diff --git a/sam/applications/sam_e1/idt82v2081_regs.h b/sam/applications/sam_e1/idt82v2081_regs.h
new file mode 100644
index 00000000..a9bee8e8
--- /dev/null
+++ b/sam/applications/sam_e1/idt82v2081_regs.h
@@ -0,0 +1,81 @@
+#ifndef _IDT82_REGS_H
+#define _IDT82_REGS_H
+
+/* Section 4.1 of Data Sheet */
+enum idt82v2081_reg {
+ IDT_REG_ID, /* control */
+ IDT_REG_RST,
+ IDT_REG_GCF,
+ IDT_REG_TERM,
+ IDT_REG_JACF,
+ IDT_REG_TCF0, /* Tx path control */
+ IDT_REG_TCF1,
+ IDT_REG_TCF2,
+ IDT_REG_TCF3,
+ IDT_REG_TCF4,
+ IDT_REG_RCF0, /* Rx path control */
+ IDT_REG_RCF1,
+ IDT_REG_RCF2,
+ IDT_REG_MAINT0, /* Net Diag Ctrl */
+ IDT_REG_MAINT1,
+ IDT_REG_MAINT2,
+ IDT_REG_MAINT3,
+ IDT_REG_MAINT4,
+ IDT_REG_MAINT5,
+ IDT_REG_MAINT6,
+ IDT_REG_INTM0, /* Interrupt Control */
+ IDT_REG_INTM1,
+ IDT_REG_INTES,
+ IDT_REG_STAT0, /* Line Status */
+ IDT_REG_STAT1,
+ IDT_REG_INTS0, /* Interrupt Status */
+ IDT_REG_INTS1,
+ IDT_REG_CNT0, /* Counter */
+ IDT_REG_CNT1,
+};
+
+#define IDT_GCF_T1E1_E1 (0 << 2)
+#define IDT_GCF_T1E1_T1 (1 << 2)
+#define IDT_GCF_T1E1_MASK (1 << 2)
+
+#define IDT_TERM_T_SHIFT 3
+#define IDT_TERM_T_MASK (7 << IDT_TERM_T_SHIFT)
+#define IDT_TERM_R_SHIFT 0
+#define IDT_TERM_R_MASK (7 << IDT_TERM_R_SHIFT)
+
+#define IDT_TCF1_PULS_MASK 0xF
+
+#define IDT_TCF2_SCAL_MASK 0x3F
+
+#define IDT_RCF2_MG_MASK 3
+#define IDT_RCF2_UPDW_SHIFT 2
+#define IDT_RCF2_UPDW_MASK (3 << IDT_TERM_INT_75)
+#define IDT_RCF2_SLICE_SHIFT 4
+#define IDT_RCF2_SLICE_MASK (3 << IDT_RCF2_SLICE_SHIFT)
+
+#define IDT_INTM0_EQ (1 << 7) /* equalizer out of range */
+#define IDT_INTM0_IBLBA (1 << 6) /* in-band LB act detect */
+#define IDT_INTM0_IBLBD (1 << 5) /* in-band LB deact detect */
+#define IDT_INTM0_PRBS (1 << 4) /* prbs sync signal detect */
+#define IDT_INTM0_TCLK (1 << 3) /* tclk loss */
+#define IDT_INTM0_DF (1 << 2) /* driver failure */
+#define IDT_INTM0_AIS (1 << 1) /* Alarm Indication Signal */
+#define IDT_INTM0_LOS (1 << 0) /* Loss Of Signal */
+
+#define IDT_INTM1_DAC_OV (1 << 7) /* DAC arithmetic overflow */
+#define IDT_INTM1_JA_OV (1 << 6) /* JA overflow */
+#define IDT_INTM1_JA_UD (1 << 5) /* JA underflow */
+#define IDT_INTM1_ERR (1 << 4) /* PRBS/QRBS logic error detect */
+#define IDT_INTM1_EXZ (1 << 3) /* Receive excess zeros */
+#define IDT_INTM1_CV (1 << 2) /* Receive error */
+#define IDT_INTM1_TIMER (1 << 1) /* One second timer expiration */
+#define IDT_INTM1_CNT (1 << 0) /* Counter overflow */
+
+/* STAT0 == INTES == INTS0 == INTM0 */
+
+/* INTS1 == INTM1 */
+
+#define IDT_STAT1_RLP (1 << 5)
+#define IDT_STAT1_ATT_MASK 0x1F
+
+#endif /* _IDT82_REGS_H */
diff --git a/sam/applications/sam_e1/main.c b/sam/applications/sam_e1/main.c
index a9c56eb9..b5ef607b 100644
--- a/sam/applications/sam_e1/main.c
+++ b/sam/applications/sam_e1/main.c
@@ -90,6 +90,7 @@
#include "conf_usb.h"
#include "low_power_board.h"
#include "e1_ssc_tc.h"
+#include "idt82v2081_asf.h"
#if !defined(PMC_PCK_PRES_CLK_1)
#define PMC_PCK_PRES_CLK_1 PMC_PCK_PRES(0)
@@ -147,6 +148,8 @@ uint32_t g_ul_current_mck;
/** Button pressed flag */
volatile uint32_t g_ul_button_pressed = 0;
+static struct idt82 g_idt;
+
/**
* \brief Set default clock (MCK = 24MHz).
*/
@@ -450,10 +453,15 @@ int main(void)
if (!udc_include_vbus_monitoring())
main_vbus_action(true);
+ /* General SSC for E1 init */
e1_init_gpio();
e1_tc_align_init();
e1_ssc_init();
+ /* LIU specific bits */
+ idt82_asf_init(&g_idt, SPI, 1);
+ idt82_init(&g_idt);
+
/* Test core consumption */
test_core();
diff --git a/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h b/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h
index 5135834b..c52e4c69 100644
--- a/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h
+++ b/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h
@@ -118,5 +118,7 @@
#include <tc.h>
#include <pdc.h>
#include <udc.h>
+#include <spi.h>
+#include <spi_master.h>
#endif // ASF_H
diff --git a/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk b/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk
index 8a92ec7e..fa51abca 100644
--- a/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk
+++ b/sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk
@@ -65,6 +65,8 @@ CSRCS = \
common/utils/stdio/write.c \
sam/applications/sam_e1/main.c \
sam/applications/sam_e1/e1_ssc_tc.c \
+ sam/applications/sam_e1/idt82v2081.c \
+ sam/applications/sam_e1/idt82v2081_asf.c \
sam/applications/sam_e1/hardfault.c \
sam/boards/sam4s_xplained_pro/init.c \
sam/drivers/adc/adc.c \