@@ -236,7 +236,8 @@
/* IOControl register bits (Only 75x/76x) */
#define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */
-#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */
+#define SC16IS7XX_IOCONTROL_MODEM_A_BIT (1 << 1) /* Enable GPIO[7:4] as modem A pins */
+#define SC16IS7XX_IOCONTROL_MODEM_B_BIT (1 << 2) /* Enable GPIO[3:0] as modem B pins */
#define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */
/* EFCR register bits */
@@ -301,12 +302,12 @@
/* Misc definitions */
#define SC16IS7XX_FIFO_SIZE (64)
#define SC16IS7XX_REG_SHIFT 2
+#define SC16IS7XX_GPIOS_PER_BANK 4
struct sc16is7xx_devtype {
char name[10];
int nr_gpio;
int nr_uart;
- int has_mctrl;
};
#define SC16IS7XX_RECONF_MD (1 << 0)
@@ -336,6 +337,7 @@ struct sc16is7xx_port {
struct clk *clk;
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio;
+ int gpio_configured;
#endif
unsigned char buf[SC16IS7XX_FIFO_SIZE];
struct kthread_worker kworker;
@@ -447,35 +449,30 @@ static const struct sc16is7xx_devtype sc16is74x_devtype = {
.name = "SC16IS74X",
.nr_gpio = 0,
.nr_uart = 1,
- .has_mctrl = 0,
};
static const struct sc16is7xx_devtype sc16is750_devtype = {
.name = "SC16IS750",
- .nr_gpio = 4,
+ .nr_gpio = 8,
.nr_uart = 1,
- .has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is752_devtype = {
.name = "SC16IS752",
- .nr_gpio = 0,
+ .nr_gpio = 8,
.nr_uart = 2,
- .has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is760_devtype = {
.name = "SC16IS760",
- .nr_gpio = 4,
+ .nr_gpio = 8,
.nr_uart = 1,
- .has_mctrl = 1,
};
static const struct sc16is7xx_devtype sc16is762_devtype = {
.name = "SC16IS762",
- .nr_gpio = 0,
+ .nr_gpio = 8,
.nr_uart = 2,
- .has_mctrl = 1,
};
static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
@@ -1396,6 +1393,10 @@ static int sc16is7xx_probe(struct device *dev,
return -ENOMEM;
}
+#ifdef CONFIG_GPIOLIB
+ s->gpio_configured = devtype->nr_gpio;
+#endif /* CONFIG_GPIOLIB */
+
/* Always ask for fixed clock rate from a property. */
device_property_read_u32(dev, "clock-frequency", &uartclk);
@@ -1473,12 +1474,6 @@ static int sc16is7xx_probe(struct device *dev,
SC16IS7XX_EFCR_RXDISABLE_BIT |
SC16IS7XX_EFCR_TXDISABLE_BIT);
- /* Use GPIO lines as modem status registers */
- if (devtype->has_mctrl)
- sc16is7xx_port_write(&s->p[i].port,
- SC16IS7XX_IOCONTROL_REG,
- SC16IS7XX_IOCONTROL_MODEM_BIT);
-
/* Initialize kthread work structs */
kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
@@ -1514,10 +1509,38 @@ static int sc16is7xx_probe(struct device *dev,
prop, p, u)
if (u < devtype->nr_uart)
s->p[u].irda_mode = true;
+
+ val = 0;
+
+ of_property_for_each_u32(dev->of_node, "nxp,modem-control-line-ports",
+ prop, p, u)
+ if (u < devtype->nr_uart) {
+ /* Use GPIO lines as modem control lines */
+ if (u == 0)
+ val |= SC16IS7XX_IOCONTROL_MODEM_A_BIT;
+ else if (u == 1)
+ val |= SC16IS7XX_IOCONTROL_MODEM_B_BIT;
+
+#ifdef CONFIG_GPIOLIB
+ if (s->gpio_configured >=
+ SC16IS7XX_GPIOS_PER_BANK)
+ s->gpio_configured -=
+ SC16IS7XX_GPIOS_PER_BANK;
+#endif /* CONFIG_GPIOLIB */
+ }
+
+ if (val)
+ regmap_update_bits(
+ s->regmap,
+ SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
+ SC16IS7XX_IOCONTROL_MODEM_A_BIT |
+ SC16IS7XX_IOCONTROL_MODEM_B_BIT, val);
}
#ifdef CONFIG_GPIOLIB
- if (devtype->nr_gpio) {
+ dev_dbg(dev, "GPIOs to configure: %d\n", s->gpio_configured);
+
+ if (s->gpio_configured) {
/* Setup GPIO controller */
s->gpio.owner = THIS_MODULE;
s->gpio.parent = dev;
@@ -1527,7 +1550,7 @@ static int sc16is7xx_probe(struct device *dev,
s->gpio.direction_output = sc16is7xx_gpio_direction_output;
s->gpio.set = sc16is7xx_gpio_set;
s->gpio.base = -1;
- s->gpio.ngpio = devtype->nr_gpio;
+ s->gpio.ngpio = s->gpio_configured;
s->gpio.can_sleep = 1;
ret = gpiochip_add_data(&s->gpio, s);
if (ret)
@@ -1555,7 +1578,7 @@ static int sc16is7xx_probe(struct device *dev,
return 0;
#ifdef CONFIG_GPIOLIB
- if (devtype->nr_gpio)
+ if (s->gpio_configured)
gpiochip_remove(&s->gpio);
out_thread:
@@ -1581,7 +1604,7 @@ static void sc16is7xx_remove(struct device *dev)
int i;
#ifdef CONFIG_GPIOLIB
- if (s->devtype->nr_gpio)
+ if (s->gpio_configured)
gpiochip_remove(&s->gpio);
#endif