diff options
author | Harald Welte <laforge@gnumonks.org> | 2018-05-17 00:25:14 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2018-05-17 00:25:14 +0200 |
commit | 1626391425ac1b18337c2cd36063db2e89bfb3c8 (patch) | |
tree | 27c77af6c30744cd954dda7f23ac5d6ca5677077 | |
parent | c853db4ca17d1ed3633e776ffe64d51cb902c235 (diff) |
Add SPI support for the IDT82v2081 LIU chip
-rw-r--r-- | sam/applications/sam_e1/e1_ssc_tc.c | 19 | ||||
-rw-r--r-- | sam/applications/sam_e1/idt82v2081.c | 122 | ||||
-rw-r--r-- | sam/applications/sam_e1/idt82v2081.h | 34 | ||||
-rw-r--r-- | sam/applications/sam_e1/idt82v2081_asf.c | 82 | ||||
-rw-r--r-- | sam/applications/sam_e1/idt82v2081_asf.h | 7 | ||||
-rw-r--r-- | sam/applications/sam_e1/idt82v2081_regs.h | 81 | ||||
-rw-r--r-- | sam/applications/sam_e1/main.c | 8 | ||||
-rw-r--r-- | sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/asf.h | 2 | ||||
-rw-r--r-- | sam/applications/sam_e1/sam4sd32c_sam4s_xplained_pro/gcc/config.mk | 2 |
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 \ |