From 601c956ad9c8d0c8489bd976c2100cb00718634b Mon Sep 17 00:00:00 2001 From: Guillaume Knispel Date: Tue, 14 Feb 2012 19:57:59 +0100 Subject: switch to leb cs1 based gpio for ntte and terms --- xhfc/base.c | 123 ++++++++++++++++++++++---------------------------------- xhfc/xhfc.h | 2 + xhfc/xhfc_leb.h | 14 ++++++- 3 files changed, 63 insertions(+), 76 deletions(-) diff --git a/xhfc/base.c b/xhfc/base.c index 0d12d1f..6d3df56 100644 --- a/xhfc/base.c +++ b/xhfc/base.c @@ -25,6 +25,11 @@ * * TODO: resource management strategy has been designed under influence, * clean it + * + * TODO: hardware modif to ensure terminations are not activated + * while the xhfc is in reset. + * + * TODO: we might want to remove the ntte module param? */ #include @@ -53,48 +58,12 @@ MODULE_LICENSE("GPL"); #define GPIO_FROM_PLATFORM_DESC (-2) #define GPIO_NONE (-1) -#define XIOH_PROTO_MB_V4_RESET_GPIO 27 // XXX unused static int reset_gpio = GPIO_FROM_PLATFORM_DESC; -static int port1_ntte_gpio = GPIO_NONE; -static int port2_ntte_gpio = GPIO_NONE; -static int port3_ntte_gpio = GPIO_NONE; -static int port4_ntte_gpio = GPIO_NONE; - -static int port1_term_gpio = GPIO_NONE; -static int port2_term_gpio = GPIO_NONE; -static int port3_term_gpio = GPIO_NONE; -static int port4_term_gpio = GPIO_NONE; - module_param(reset_gpio, int, S_IRUGO); -module_param(port1_ntte_gpio, int, S_IRUGO); -module_param(port2_ntte_gpio, int, S_IRUGO); -module_param(port3_ntte_gpio, int, S_IRUGO); -module_param(port4_ntte_gpio, int, S_IRUGO); -module_param(port1_term_gpio, int, S_IRUGO); -module_param(port2_term_gpio, int, S_IRUGO); -module_param(port3_term_gpio, int, S_IRUGO); -module_param(port4_term_gpio, int, S_IRUGO); MODULE_PARM_DESC(reset_gpio, "Reset the XHFC using this GPIO" "(override ACPI platform description)"); - -MODULE_PARM_DESC(port1_ntte_gpio, "GPIO used for setting port 1 as NT/TE " - "(default: -1 = none)"); -MODULE_PARM_DESC(port2_ntte_gpio, "GPIO used for setting port 2 as NT/TE " - "(default: -1 = none)"); -MODULE_PARM_DESC(port3_ntte_gpio, "GPIO used for setting port 3 as NT/TE " - "(default: -1 = none)"); -MODULE_PARM_DESC(port4_ntte_gpio, "GPIO used for setting port 4 as NT/TE " - "(default: -1 = none)"); -MODULE_PARM_DESC(port1_term_gpio, "GPIO used for line termination on port 1 " - "(default: -1 = none)"); -MODULE_PARM_DESC(port2_term_gpio, "GPIO used for line termination on port 2 " - "(default: -1 = none)"); -MODULE_PARM_DESC(port3_term_gpio, "GPIO used for line termination on port 3 " - "(default: -1 = none)"); -MODULE_PARM_DESC(port4_term_gpio, "GPIO used for line termination on port 4 " - "(default: -1 = none)"); #endif static struct xhfc_pi *g_pi; @@ -102,7 +71,7 @@ static struct xhfc_pi *g_pi; uint debug = 0; uint dbg_spanfilter = 0xFFFFFFFF; static int exit_after_reset = 0; -static uint ntte = 0x3; +static uint ntte = 0x3; // XXX we might want to remove that module_param(debug, uint, S_IRUGO | S_IWUSR); module_param(dbg_spanfilter, uint, S_IRUGO | S_IWUSR); @@ -796,47 +765,49 @@ static void xhfc_hard_reset(void) #endif } -static void configure_ntte(int port, int nt) +static inline int lebcs1_bit_nt(int port) { - static int *ntte_gpio[] = { - &port1_ntte_gpio, - &port2_ntte_gpio, - &port3_ntte_gpio, - &port4_ntte_gpio, - }; + return (3 - port) * 2 + 1; +} - if (*ntte_gpio[port] == GPIO_NONE) { - printk(KERN_WARNING DRIVER_NAME ": Can't configure " - "port %d as %s (no GPIO configured)\n", - port + 1, nt ? "NT" : "TE"); - return; - } +/* on the leb, cs1 */ +static inline int lebcs1_bit_term(int port) +{ + return (3 - port) * 2; +} - gpio_set_direction(*ntte_gpio[port], GPIO_OUTPUT); - gpio_set_to_gpio(*ntte_gpio[port]); - gpio_set_level(*ntte_gpio[port], nt); +static inline u8 byte_replace_bit(u8 byte, int nr, bool value) +{ + return (byte & ~(1 << nr)) | (value << nr); } -static void configure_term(int port, int lineterm) +static void configure_ntte(struct xhfc_span *xhfc_span, int nt) { - static int *term_gpio[] = { - &port1_term_gpio, - &port2_term_gpio, - &port3_term_gpio, - &port4_term_gpio, - }; + struct xhfc *xhfc = xhfc_span->xhfc; + u8 newb; + newb = byte_replace_bit(xhfc->pi->soft_conf_byte, + lebcs1_bit_nt(xhfc_span->port), + !!nt); + xhfc->pi->soft_conf_byte = newb; + write_xhfc_soft_conf(xhfc, newb); +} - if (*term_gpio[port] == GPIO_NONE) { - printk(KERN_WARNING DRIVER_NAME ": Can't configure " - "line termination on port %d " - "(no GPIO configured)\n", - port + 1); - return; - } +static void configure_term(struct xhfc_span *xhfc_span, int lineterm) +{ + struct xhfc *xhfc = xhfc_span->xhfc; + u8 newb; + newb = byte_replace_bit(xhfc->pi->soft_conf_byte, + lebcs1_bit_term(xhfc_span->port), + !!lineterm); + xhfc->pi->soft_conf_byte = newb; + write_xhfc_soft_conf(xhfc, xhfc->pi->soft_conf_byte); +} - gpio_set_direction(*term_gpio[port], GPIO_OUTPUT); - gpio_set_to_gpio(*term_gpio[port]); - gpio_set_level(*term_gpio[port], lineterm); +static void __devinit +xhfc_preset_all_te_noterm(struct xhfc *xhfc) +{ + xhfc->pi->soft_conf_byte = 0; // te: 0 / noterm: 0 + write_xhfc_soft_conf(xhfc, 0); } static void xhfc_init_and_configure(struct xhfc* x) @@ -883,8 +854,8 @@ static int xhfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) term ? "ENABLED" : "DISABLED"); xhfc_config_st(xhfc, xhfc_span->port, xhfc_span->nt); - configure_ntte(xhfc_span->port, xhfc_span->nt); - configure_term(xhfc_span->port, term); + configure_ntte(xhfc_span, xhfc_span->nt); + configure_term(xhfc_span, term); if (lc->sync < 0) { printk(KERN_INFO DRIVER_NAME @@ -1126,6 +1097,8 @@ static int __devinit xhfc_init_one(struct pci_dev *pdev, * see [Intel 320066] 42.4.1.1 Chip Select Address Allocation */ pi->cs_n1 = pi->cs_n0 + 16 * 1024 * 1024; + /* WARNING: don't use cs_n0 / cs_n1 before leb_init() */ + pci_set_drvdata(pdev, pi); @@ -1133,6 +1106,10 @@ static int __devinit xhfc_init_one(struct pci_dev *pdev, * Hard init * *************/ + leb_init(pi); // XXX maybe we should disable the CS on exit? + + xhfc_preset_all_te_noterm(&pi->xhfc); + xhfc_hard_reset(); if (exit_after_reset) { @@ -1140,8 +1117,6 @@ static int __devinit xhfc_init_one(struct pci_dev *pdev, goto exit_after_reset; } - leb_init(pi); - #ifdef AUDIO /************* diff --git a/xhfc/xhfc.h b/xhfc/xhfc.h index 1aaa74d..4128fe1 100644 --- a/xhfc/xhfc.h +++ b/xhfc/xhfc.h @@ -152,6 +152,7 @@ struct xhfc_pi { struct tlp_leb_regs __iomem *regs; /* own ioremap */ u8 __iomem *cs_n0; /* own ioremap */ u8 __iomem *cs_n1; /* don't own ioremap */ + u8 soft_conf_byte; int irq; struct xhfc xhfc; /* mem for one XHFC */ @@ -161,6 +162,7 @@ struct xhfc_pi { /* maybe should be in struct xhfc but mainly used to retrieve the irq, * so for now it ends up here */ struct pnp_dev *pnp_dev; + #ifdef AUDIO struct xivo_tdm_port *tdm_port; #endif diff --git a/xhfc/xhfc_leb.h b/xhfc/xhfc_leb.h index acce53e..0f95a13 100644 --- a/xhfc/xhfc_leb.h +++ b/xhfc/xhfc_leb.h @@ -38,20 +38,30 @@ void leb_init(struct xhfc_pi *leb); -static inline u8 read_xhfc(struct xhfc * xhfc, u8 reg_addr) +static inline u8 read_xhfc(struct xhfc *xhfc, u8 reg_addr) { u8 __iomem *cs_n0 = xhfc->pi->cs_n0; return readb(&cs_n0[reg_addr]); } -static inline void write_xhfc(struct xhfc * xhfc, u8 reg_addr, u8 value) +static inline void write_xhfc(struct xhfc *xhfc, u8 reg_addr, u8 value) { u8 __iomem *cs_n0 = xhfc->pi->cs_n0; writeb(value, &cs_n0[reg_addr]); } +static inline void write_xhfc_soft_conf(struct xhfc *xhfc, u8 soft_conf) +{ + u8 __iomem *cs_n1 = xhfc->pi->cs_n1; + + writeb(soft_conf, &cs_n1[0]); + + /* ensure the write has been completed: */ + (void)readb(&cs_n1[0]); +} + #if 0 #ifdef DEBUG #define read_xhfc(x, reg) ({ \ -- cgit v1.2.3