From da02f556e0a666d12e60be9dd8614f0c6805f4a2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 14 Jan 2012 18:18:31 +0100 Subject: add initial driver skeleton for idt82v2081 chip --- driver/idt82v2081.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ driver/idt82v2081.h | 33 ++++++++++++++++ driver/idt82v2081_regs.h | 81 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 driver/idt82v2081.c create mode 100644 driver/idt82v2081.h create mode 100644 driver/idt82v2081_regs.h diff --git a/driver/idt82v2081.c b/driver/idt82v2081.c new file mode 100644 index 0000000..daf8c18 --- /dev/null +++ b/driver/idt82v2081.c @@ -0,0 +1,99 @@ +#include + +#include "idt82v2081.h" +#include "idt82v2081_regs.h" + +int idt82_termination(struct idt82 *idt, enum idt82_term term) +{ + idt82_reg_set_bit_mask(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_REG_TCF1, puls, IDT_TCF1_PULS_MASK); + idt82_reg_set_bit_mask(IDT_REG_TCF2, scal, IDT_TCF1_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: + idt82_reg_set_bit_mask(idt, IDT_REG_GCF, IDT_GCF_T1E1_T1, + IDT_GCF_T1E1_MASK); + break; + } + idt->mode = mode; +} + +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_JA, 0); + idt82_reg_write(idt, IDT_REG_TCF0, 0); + idt82_reg_write(idt, IDT_REG_TCF5, 0); + idt82_reg_write(idt, IDT_REG_RCF1, 0); /* short haul */ + + idt82_mode(idt, IDT_MODE_E1); + idt82_term(idt, IDT_TERM_INT_120); + + return 0; +} + diff --git a/driver/idt82v2081.h b/driver/idt82v2081.h new file mode 100644 index 0000000..1d78093 --- /dev/null +++ b/driver/idt82v2081.h @@ -0,0 +1,33 @@ +#ifndef _IDT82_H +#define _IDT82_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; +}; + +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, uin8_t val); +int idt82_reg_read(struct idt82 *idt, uint8_t reg); + +#endif diff --git a/driver/idt82v2081_regs.h b/driver/idt82v2081_regs.h new file mode 100644 index 0000000..a9bee8e --- /dev/null +++ b/driver/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 */ -- cgit v1.2.3