|
@@ -233,6 +233,7 @@
|
|
|
/* Misc definitions */
|
|
|
#define MAX310X_FIFO_SIZE (128)
|
|
|
#define MAX310x_REV_MASK (0xf8)
|
|
|
+#define MAX310X_WRITE_BIT 0x80
|
|
|
|
|
|
/* MAX3107 specific */
|
|
|
#define MAX3107_REV_ID (0xa0)
|
|
@@ -593,57 +594,118 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
|
|
|
return (int)bestfreq;
|
|
|
}
|
|
|
|
|
|
-static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|
|
+static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
|
|
|
{
|
|
|
- unsigned int sts, ch, flag;
|
|
|
+ u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT };
|
|
|
+ struct spi_transfer xfer[] = {
|
|
|
+ {
|
|
|
+ .tx_buf = &header,
|
|
|
+ .len = sizeof(header),
|
|
|
+ }, {
|
|
|
+ .tx_buf = txbuf,
|
|
|
+ .len = len,
|
|
|
+ }
|
|
|
+ };
|
|
|
+ spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
|
|
+}
|
|
|
|
|
|
- if (unlikely(rxlen >= port->fifosize)) {
|
|
|
- dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
|
|
|
- port->icount.buf_overrun++;
|
|
|
- /* Ensure sanity of RX level */
|
|
|
- rxlen = port->fifosize;
|
|
|
- }
|
|
|
+static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
|
|
|
+{
|
|
|
+ u8 header[] = { port->iobase + MAX310X_RHR_REG };
|
|
|
+ struct spi_transfer xfer[] = {
|
|
|
+ {
|
|
|
+ .tx_buf = &header,
|
|
|
+ .len = sizeof(header),
|
|
|
+ }, {
|
|
|
+ .rx_buf = rxbuf,
|
|
|
+ .len = len,
|
|
|
+ }
|
|
|
+ };
|
|
|
+ spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
|
|
+}
|
|
|
|
|
|
- while (rxlen--) {
|
|
|
- ch = max310x_port_read(port, MAX310X_RHR_REG);
|
|
|
- sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
|
|
+static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|
|
+{
|
|
|
+ unsigned int sts, ch, flag, i;
|
|
|
+ u8 buf[MAX310X_FIFO_SIZE];
|
|
|
+
|
|
|
+ if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) {
|
|
|
+ /* We are just reading, happily ignoring any error conditions.
|
|
|
+ * Break condition, parity checking, framing errors -- they
|
|
|
+ * are all ignored. That means that we can do a batch-read.
|
|
|
+ *
|
|
|
+ * There is a small opportunity for race if the RX FIFO
|
|
|
+ * overruns while we're reading the buffer; the datasheets says
|
|
|
+ * that the LSR register applies to the "current" character.
|
|
|
+ * That's also the reason why we cannot do batched reads when
|
|
|
+ * asked to check the individual statuses.
|
|
|
+ * */
|
|
|
|
|
|
- sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
|
|
|
- MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
|
|
|
+ sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
|
|
+ max310x_batch_read(port, buf, rxlen);
|
|
|
|
|
|
- port->icount.rx++;
|
|
|
+ port->icount.rx += rxlen;
|
|
|
flag = TTY_NORMAL;
|
|
|
+ sts &= port->read_status_mask;
|
|
|
|
|
|
- if (unlikely(sts)) {
|
|
|
- if (sts & MAX310X_LSR_RXBRK_BIT) {
|
|
|
- port->icount.brk++;
|
|
|
- if (uart_handle_break(port))
|
|
|
- continue;
|
|
|
- } else if (sts & MAX310X_LSR_RXPAR_BIT)
|
|
|
- port->icount.parity++;
|
|
|
- else if (sts & MAX310X_LSR_FRERR_BIT)
|
|
|
- port->icount.frame++;
|
|
|
- else if (sts & MAX310X_LSR_RXOVR_BIT)
|
|
|
- port->icount.overrun++;
|
|
|
-
|
|
|
- sts &= port->read_status_mask;
|
|
|
- if (sts & MAX310X_LSR_RXBRK_BIT)
|
|
|
- flag = TTY_BREAK;
|
|
|
- else if (sts & MAX310X_LSR_RXPAR_BIT)
|
|
|
- flag = TTY_PARITY;
|
|
|
- else if (sts & MAX310X_LSR_FRERR_BIT)
|
|
|
- flag = TTY_FRAME;
|
|
|
- else if (sts & MAX310X_LSR_RXOVR_BIT)
|
|
|
- flag = TTY_OVERRUN;
|
|
|
+ if (sts & MAX310X_LSR_RXOVR_BIT) {
|
|
|
+ dev_warn_ratelimited(port->dev, "Hardware RX FIFO overrun\n");
|
|
|
+ port->icount.overrun++;
|
|
|
}
|
|
|
|
|
|
- if (uart_handle_sysrq_char(port, ch))
|
|
|
- continue;
|
|
|
+ for (i = 0; i < rxlen; ++i) {
|
|
|
+ uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag);
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if (unlikely(rxlen >= port->fifosize)) {
|
|
|
+ dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
|
|
|
+ port->icount.buf_overrun++;
|
|
|
+ /* Ensure sanity of RX level */
|
|
|
+ rxlen = port->fifosize;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (rxlen--) {
|
|
|
+ ch = max310x_port_read(port, MAX310X_RHR_REG);
|
|
|
+ sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
|
|
+
|
|
|
+ sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT |
|
|
|
+ MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT;
|
|
|
+
|
|
|
+ port->icount.rx++;
|
|
|
+ flag = TTY_NORMAL;
|
|
|
+
|
|
|
+ if (unlikely(sts)) {
|
|
|
+ if (sts & MAX310X_LSR_RXBRK_BIT) {
|
|
|
+ port->icount.brk++;
|
|
|
+ if (uart_handle_break(port))
|
|
|
+ continue;
|
|
|
+ } else if (sts & MAX310X_LSR_RXPAR_BIT)
|
|
|
+ port->icount.parity++;
|
|
|
+ else if (sts & MAX310X_LSR_FRERR_BIT)
|
|
|
+ port->icount.frame++;
|
|
|
+ else if (sts & MAX310X_LSR_RXOVR_BIT)
|
|
|
+ port->icount.overrun++;
|
|
|
+
|
|
|
+ sts &= port->read_status_mask;
|
|
|
+ if (sts & MAX310X_LSR_RXBRK_BIT)
|
|
|
+ flag = TTY_BREAK;
|
|
|
+ else if (sts & MAX310X_LSR_RXPAR_BIT)
|
|
|
+ flag = TTY_PARITY;
|
|
|
+ else if (sts & MAX310X_LSR_FRERR_BIT)
|
|
|
+ flag = TTY_FRAME;
|
|
|
+ else if (sts & MAX310X_LSR_RXOVR_BIT)
|
|
|
+ flag = TTY_OVERRUN;
|
|
|
+ }
|
|
|
|
|
|
- if (sts & port->ignore_status_mask)
|
|
|
- continue;
|
|
|
+ if (uart_handle_sysrq_char(port, ch))
|
|
|
+ continue;
|
|
|
|
|
|
- uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag);
|
|
|
+ if (sts & port->ignore_status_mask)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
tty_flip_buffer_push(&port->state->port);
|
|
@@ -652,7 +714,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|
|
static void max310x_handle_tx(struct uart_port *port)
|
|
|
{
|
|
|
struct circ_buf *xmit = &port->state->xmit;
|
|
|
- unsigned int txlen, to_send;
|
|
|
+ unsigned int txlen, to_send, until_end;
|
|
|
|
|
|
if (unlikely(port->x_char)) {
|
|
|
max310x_port_write(port, MAX310X_THR_REG, port->x_char);
|
|
@@ -666,28 +728,43 @@ static void max310x_handle_tx(struct uart_port *port)
|
|
|
|
|
|
/* Get length of data pending in circular buffer */
|
|
|
to_send = uart_circ_chars_pending(xmit);
|
|
|
+ until_end = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
|
|
if (likely(to_send)) {
|
|
|
/* Limit to size of TX FIFO */
|
|
|
txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
|
|
|
txlen = port->fifosize - txlen;
|
|
|
to_send = (to_send > txlen) ? txlen : to_send;
|
|
|
|
|
|
+ if (until_end < to_send) {
|
|
|
+ /* It's a circ buffer -- wrap around.
|
|
|
+ * We could do that in one SPI transaction, but meh. */
|
|
|
+ max310x_batch_write(port, xmit->buf + xmit->tail, until_end);
|
|
|
+ max310x_batch_write(port, xmit->buf, to_send - until_end);
|
|
|
+ } else {
|
|
|
+ max310x_batch_write(port, xmit->buf + xmit->tail, to_send);
|
|
|
+ }
|
|
|
+
|
|
|
/* Add data to send */
|
|
|
port->icount.tx += to_send;
|
|
|
- while (to_send--) {
|
|
|
- max310x_port_write(port, MAX310X_THR_REG,
|
|
|
- xmit->buf[xmit->tail]);
|
|
|
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
|
|
- }
|
|
|
+ xmit->tail = (xmit->tail + to_send) & (UART_XMIT_SIZE - 1);
|
|
|
}
|
|
|
|
|
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
|
|
uart_write_wakeup(port);
|
|
|
}
|
|
|
|
|
|
-static void max310x_port_irq(struct max310x_port *s, int portno)
|
|
|
+static void max310x_start_tx(struct uart_port *port)
|
|
|
+{
|
|
|
+ struct max310x_one *one = container_of(port, struct max310x_one, port);
|
|
|
+
|
|
|
+ if (!work_pending(&one->tx_work))
|
|
|
+ schedule_work(&one->tx_work);
|
|
|
+}
|
|
|
+
|
|
|
+static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
|
|
|
{
|
|
|
struct uart_port *port = &s->p[portno].port;
|
|
|
+ irqreturn_t res = IRQ_NONE;
|
|
|
|
|
|
do {
|
|
|
unsigned int ists, lsr, rxlen;
|
|
@@ -698,6 +775,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
|
|
if (!ists && !rxlen)
|
|
|
break;
|
|
|
|
|
|
+ res = IRQ_HANDLED;
|
|
|
+
|
|
|
if (ists & MAX310X_IRQ_CTS_BIT) {
|
|
|
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
|
|
uart_handle_cts_change(port,
|
|
@@ -705,17 +784,16 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
|
|
}
|
|
|
if (rxlen)
|
|
|
max310x_handle_rx(port, rxlen);
|
|
|
- if (ists & MAX310X_IRQ_TXEMPTY_BIT) {
|
|
|
- mutex_lock(&s->mutex);
|
|
|
- max310x_handle_tx(port);
|
|
|
- mutex_unlock(&s->mutex);
|
|
|
- }
|
|
|
+ if (ists & MAX310X_IRQ_TXEMPTY_BIT)
|
|
|
+ max310x_start_tx(port);
|
|
|
} while (1);
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
static irqreturn_t max310x_ist(int irq, void *dev_id)
|
|
|
{
|
|
|
struct max310x_port *s = (struct max310x_port *)dev_id;
|
|
|
+ bool handled = false;
|
|
|
|
|
|
if (s->devtype->nr > 1) {
|
|
|
do {
|
|
@@ -726,12 +804,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
|
|
|
val = ((1 << s->devtype->nr) - 1) & ~val;
|
|
|
if (!val)
|
|
|
break;
|
|
|
- max310x_port_irq(s, fls(val) - 1);
|
|
|
+ if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED)
|
|
|
+ handled = true;
|
|
|
} while (1);
|
|
|
- } else
|
|
|
- max310x_port_irq(s, 0);
|
|
|
+ } else {
|
|
|
+ if (max310x_port_irq(s, 0) == IRQ_HANDLED)
|
|
|
+ handled = true;
|
|
|
+ }
|
|
|
|
|
|
- return IRQ_HANDLED;
|
|
|
+ return IRQ_RETVAL(handled);
|
|
|
}
|
|
|
|
|
|
static void max310x_wq_proc(struct work_struct *ws)
|
|
@@ -744,14 +825,6 @@ static void max310x_wq_proc(struct work_struct *ws)
|
|
|
mutex_unlock(&s->mutex);
|
|
|
}
|
|
|
|
|
|
-static void max310x_start_tx(struct uart_port *port)
|
|
|
-{
|
|
|
- struct max310x_one *one = container_of(port, struct max310x_one, port);
|
|
|
-
|
|
|
- if (!work_pending(&one->tx_work))
|
|
|
- schedule_work(&one->tx_work);
|
|
|
-}
|
|
|
-
|
|
|
static unsigned int max310x_tx_empty(struct uart_port *port)
|
|
|
{
|
|
|
unsigned int lvl, sts;
|
|
@@ -1086,10 +1159,31 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
|
|
+ unsigned long config)
|
|
|
+{
|
|
|
+ struct max310x_port *s = gpiochip_get_data(chip);
|
|
|
+ struct uart_port *port = &s->p[offset / 4].port;
|
|
|
+
|
|
|
+ switch (pinconf_to_config_param(config)) {
|
|
|
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
|
|
+ max310x_port_update(port, MAX310X_GPIOCFG_REG,
|
|
|
+ 1 << ((offset % 4) + 4),
|
|
|
+ 1 << ((offset % 4) + 4));
|
|
|
+ return 0;
|
|
|
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
|
|
|
+ max310x_port_update(port, MAX310X_GPIOCFG_REG,
|
|
|
+ 1 << ((offset % 4) + 4), 0);
|
|
|
+ return 0;
|
|
|
+ default:
|
|
|
+ return -ENOTSUPP;
|
|
|
+ }
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
- struct regmap *regmap, int irq, unsigned long flags)
|
|
|
+ struct regmap *regmap, int irq)
|
|
|
{
|
|
|
int i, ret, fmin, fmax, freq, uartclk;
|
|
|
struct clk *clk_osc, *clk_xtal;
|
|
@@ -1169,23 +1263,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
uartclk = max310x_set_ref_clk(s, freq, xtal);
|
|
|
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
|
|
|
|
|
-#ifdef CONFIG_GPIOLIB
|
|
|
- /* Setup GPIO cotroller */
|
|
|
- s->gpio.owner = THIS_MODULE;
|
|
|
- s->gpio.parent = dev;
|
|
|
- s->gpio.label = dev_name(dev);
|
|
|
- s->gpio.direction_input = max310x_gpio_direction_input;
|
|
|
- s->gpio.get = max310x_gpio_get;
|
|
|
- s->gpio.direction_output= max310x_gpio_direction_output;
|
|
|
- s->gpio.set = max310x_gpio_set;
|
|
|
- s->gpio.base = -1;
|
|
|
- s->gpio.ngpio = devtype->nr * 4;
|
|
|
- s->gpio.can_sleep = 1;
|
|
|
- ret = devm_gpiochip_add_data(dev, &s->gpio, s);
|
|
|
- if (ret)
|
|
|
- goto out_clk;
|
|
|
-#endif
|
|
|
-
|
|
|
mutex_init(&s->mutex);
|
|
|
|
|
|
for (i = 0; i < devtype->nr; i++) {
|
|
@@ -1237,9 +1314,27 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
devtype->power(&s->p[i].port, 0);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_GPIOLIB
|
|
|
+ /* Setup GPIO cotroller */
|
|
|
+ s->gpio.owner = THIS_MODULE;
|
|
|
+ s->gpio.parent = dev;
|
|
|
+ s->gpio.label = dev_name(dev);
|
|
|
+ s->gpio.direction_input = max310x_gpio_direction_input;
|
|
|
+ s->gpio.get = max310x_gpio_get;
|
|
|
+ s->gpio.direction_output= max310x_gpio_direction_output;
|
|
|
+ s->gpio.set = max310x_gpio_set;
|
|
|
+ s->gpio.set_config = max310x_gpio_set_config;
|
|
|
+ s->gpio.base = -1;
|
|
|
+ s->gpio.ngpio = devtype->nr * 4;
|
|
|
+ s->gpio.can_sleep = 1;
|
|
|
+ ret = devm_gpiochip_add_data(dev, &s->gpio, s);
|
|
|
+ if (ret)
|
|
|
+ goto out_uart;
|
|
|
+#endif
|
|
|
+
|
|
|
/* Setup interrupt */
|
|
|
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
|
|
|
- IRQF_ONESHOT | flags, dev_name(dev), s);
|
|
|
+ IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s);
|
|
|
if (!ret)
|
|
|
return 0;
|
|
|
|
|
@@ -1293,7 +1388,7 @@ MODULE_DEVICE_TABLE(of, max310x_dt_ids);
|
|
|
static struct regmap_config regcfg = {
|
|
|
.reg_bits = 8,
|
|
|
.val_bits = 8,
|
|
|
- .write_flag_mask = 0x80,
|
|
|
+ .write_flag_mask = MAX310X_WRITE_BIT,
|
|
|
.cache_type = REGCACHE_RBTREE,
|
|
|
.writeable_reg = max310x_reg_writeable,
|
|
|
.volatile_reg = max310x_reg_volatile,
|
|
@@ -1304,7 +1399,6 @@ static struct regmap_config regcfg = {
|
|
|
static int max310x_spi_probe(struct spi_device *spi)
|
|
|
{
|
|
|
struct max310x_devtype *devtype;
|
|
|
- unsigned long flags = 0;
|
|
|
struct regmap *regmap;
|
|
|
int ret;
|
|
|
|
|
@@ -1327,11 +1421,10 @@ static int max310x_spi_probe(struct spi_device *spi)
|
|
|
devtype = (struct max310x_devtype *)id_entry->driver_data;
|
|
|
}
|
|
|
|
|
|
- flags = IRQF_TRIGGER_FALLING;
|
|
|
regcfg.max_register = devtype->nr * 0x20 - 1;
|
|
|
regmap = devm_regmap_init_spi(spi, ®cfg);
|
|
|
|
|
|
- return max310x_probe(&spi->dev, devtype, regmap, spi->irq, flags);
|
|
|
+ return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
|
|
|
}
|
|
|
|
|
|
static int max310x_spi_remove(struct spi_device *spi)
|