summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Knispel <gknispel@proformatique.com>2012-02-14 19:57:59 +0100
committerGuillaume Knispel <gknispel@proformatique.com>2012-02-14 19:57:59 +0100
commit601c956ad9c8d0c8489bd976c2100cb00718634b (patch)
tree165bf77c003508c0e53b758d25331a9e8db3ff4c
parent31a6429bd5b4cc283b8d9336fb3e579b70705ac8 (diff)
switch to leb cs1 based gpio for ntte and terms
-rw-r--r--xhfc/base.c123
-rw-r--r--xhfc/xhfc.h2
-rw-r--r--xhfc/xhfc_leb.h14
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 <linux/acpi.h>
@@ -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) ({ \