|
@@ -48,6 +48,10 @@ struct sport_uart_port {
|
|
|
unsigned short txmask2;
|
|
|
unsigned char stopb;
|
|
|
/* unsigned char parib; */
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+ int cts_pin;
|
|
|
+ int rts_pin;
|
|
|
+#endif
|
|
|
};
|
|
|
|
|
|
static void sport_uart_tx_chars(struct sport_uart_port *up);
|
|
@@ -198,6 +202,59 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+static unsigned int sport_get_mctrl(struct uart_port *port)
|
|
|
+{
|
|
|
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
|
|
|
+ if (up->cts_pin < 0)
|
|
|
+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
|
|
+
|
|
|
+ /* CTS PIN is negative assertive. */
|
|
|
+ if (SPORT_UART_GET_CTS(up))
|
|
|
+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
|
|
+ else
|
|
|
+ return TIOCM_DSR | TIOCM_CAR;
|
|
|
+}
|
|
|
+
|
|
|
+static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|
|
+{
|
|
|
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
|
|
|
+ if (up->rts_pin < 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* RTS PIN is negative assertive. */
|
|
|
+ if (mctrl & TIOCM_RTS)
|
|
|
+ SPORT_UART_ENABLE_RTS(up);
|
|
|
+ else
|
|
|
+ SPORT_UART_DISABLE_RTS(up);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Handle any change of modem status signal.
|
|
|
+ */
|
|
|
+static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id)
|
|
|
+{
|
|
|
+ struct sport_uart_port *up = (struct sport_uart_port *)dev_id;
|
|
|
+ unsigned int status;
|
|
|
+
|
|
|
+ status = sport_get_mctrl(&up->port);
|
|
|
+ uart_handle_cts_change(&up->port, status & TIOCM_CTS);
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+#else
|
|
|
+static unsigned int sport_get_mctrl(struct uart_port *port)
|
|
|
+{
|
|
|
+ pr_debug("%s enter\n", __func__);
|
|
|
+ return TIOCM_CTS | TIOCM_CD | TIOCM_DSR;
|
|
|
+}
|
|
|
+
|
|
|
+static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|
|
+{
|
|
|
+ pr_debug("%s enter\n", __func__);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/* Reqeust IRQ, Setup clock */
|
|
|
static int sport_startup(struct uart_port *port)
|
|
|
{
|
|
@@ -226,6 +283,21 @@ static int sport_startup(struct uart_port *port)
|
|
|
goto fail2;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+ if (up->cts_pin >= 0) {
|
|
|
+ if (request_irq(gpio_to_irq(up->cts_pin),
|
|
|
+ sport_mctrl_cts_int,
|
|
|
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
|
|
|
+ IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) {
|
|
|
+ up->cts_pin = -1;
|
|
|
+ dev_info(port->dev, "Unable to attach BlackFin UART \
|
|
|
+ over SPORT CTS interrupt. So, disable it.\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (up->rts_pin >= 0)
|
|
|
+ gpio_direction_output(up->rts_pin, 0);
|
|
|
+#endif
|
|
|
+
|
|
|
return 0;
|
|
|
fail2:
|
|
|
free_irq(up->port.irq+1, up);
|
|
@@ -283,17 +355,6 @@ static unsigned int sport_tx_empty(struct uart_port *port)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static unsigned int sport_get_mctrl(struct uart_port *port)
|
|
|
-{
|
|
|
- pr_debug("%s enter\n", __func__);
|
|
|
- return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
|
|
|
-}
|
|
|
-
|
|
|
-static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|
|
-{
|
|
|
- pr_debug("%s enter\n", __func__);
|
|
|
-}
|
|
|
-
|
|
|
static void sport_stop_tx(struct uart_port *port)
|
|
|
{
|
|
|
struct sport_uart_port *up = (struct sport_uart_port *)port;
|
|
@@ -364,6 +425,10 @@ static void sport_shutdown(struct uart_port *port)
|
|
|
free_irq(up->port.irq, up);
|
|
|
free_irq(up->port.irq+1, up);
|
|
|
free_irq(up->err_irq, up);
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+ if (up->cts_pin >= 0)
|
|
|
+ free_irq(gpio_to_irq(up->cts_pin), up);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
static const char *sport_type(struct uart_port *port)
|
|
@@ -536,7 +601,11 @@ sport_uart_console_setup(struct console *co, char *options)
|
|
|
int baud = 57600;
|
|
|
int bits = 8;
|
|
|
int parity = 'n';
|
|
|
+# ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+ int flow = 'r';
|
|
|
+# else
|
|
|
int flow = 'n';
|
|
|
+# endif
|
|
|
|
|
|
/* Check whether an invalid uart number has been specified */
|
|
|
if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
|
|
@@ -729,6 +798,22 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
|
|
|
ret = -ENOENT;
|
|
|
goto out_error_unmap;
|
|
|
}
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
|
|
+ if (res == NULL)
|
|
|
+ sport->cts_pin = -1;
|
|
|
+ else
|
|
|
+ sport->cts_pin = res->start;
|
|
|
+
|
|
|
+ res = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
|
|
+ if (res == NULL)
|
|
|
+ sport->rts_pin = -1;
|
|
|
+ else
|
|
|
+ sport->rts_pin = res->start;
|
|
|
+
|
|
|
+ if (sport->rts_pin >= 0)
|
|
|
+ gpio_request(sport->rts_pin, DRV_NAME);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
|
|
@@ -767,6 +852,10 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
|
|
|
|
|
|
if (sport) {
|
|
|
uart_remove_one_port(&sport_uart_reg, &sport->port);
|
|
|
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
|
|
|
+ if (sport->rts_pin >= 0)
|
|
|
+ gpio_free(sport->rts_pin);
|
|
|
+#endif
|
|
|
iounmap(sport->port.membase);
|
|
|
peripheral_free_list(
|
|
|
(unsigned short *)pdev->dev.platform_data);
|