Skip to content

Commit

Permalink
serial: bfin_sport_uart: add support for CTS/RTS via GPIOs
Browse files Browse the repository at this point in the history
Some people need flow control on their ports, so now boards can support
that via any GPIOs.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Sonic Zhang authored and Greg Kroah-Hartman committed May 21, 2010
1 parent b59588a commit 1f7d1c8
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 11 deletions.
24 changes: 24 additions & 0 deletions drivers/serial/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1443,24 +1443,48 @@ config SERIAL_BFIN_SPORT0_UART
help
Enable UART over SPORT0

config SERIAL_BFIN_SPORT0_UART_CTSRTS
bool "Enable UART over SPORT0 hardware flow control"
depends on SERIAL_BFIN_SPORT0_UART
help
Enable hardware flow control in the driver.

config SERIAL_BFIN_SPORT1_UART
bool "Enable UART over SPORT1"
depends on SERIAL_BFIN_SPORT
help
Enable UART over SPORT1

config SERIAL_BFIN_SPORT1_UART_CTSRTS
bool "Enable UART over SPORT1 hardware flow control"
depends on SERIAL_BFIN_SPORT1_UART
help
Enable hardware flow control in the driver.

config SERIAL_BFIN_SPORT2_UART
bool "Enable UART over SPORT2"
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
help
Enable UART over SPORT2

config SERIAL_BFIN_SPORT2_UART_CTSRTS
bool "Enable UART over SPORT2 hardware flow control"
depends on SERIAL_BFIN_SPORT2_UART
help
Enable hardware flow control in the driver.

config SERIAL_BFIN_SPORT3_UART
bool "Enable UART over SPORT3"
depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
help
Enable UART over SPORT3

config SERIAL_BFIN_SPORT3_UART_CTSRTS
bool "Enable UART over SPORT3 hardware flow control"
depends on SERIAL_BFIN_SPORT3_UART
help
Enable hardware flow control in the driver.

config SERIAL_TIMBERDALE
tristate "Support for timberdale UART"
select SERIAL_CORE
Expand Down
111 changes: 100 additions & 11 deletions drivers/serial/bfin_sport_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand 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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand 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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions drivers/serial/bfin_sport_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,15 @@

#define SPORT_TX_FIFO_SIZE 8

#define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin)
#define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
#define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)

#if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \
|| defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS)
# define CONFIG_SERIAL_BFIN_SPORT_CTSRTS
#endif

#endif /* _BFIN_SPORT_UART_H */

0 comments on commit 1f7d1c8

Please sign in to comment.