diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-12-02 06:09:48 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-12-02 06:09:48 -0500 |
commit | 50f0959ad4f9ac1c5ee208bb820de299a1b3730b (patch) | |
tree | 3e4965ee4764f98ba3cd840e3733604825475998 /drivers/tty/serial/sh-sci.c | |
parent | 73c3d53f38e0a8e6c67b0d12d77a8e77c082cd03 (diff) |
serial: sh-sci: Handle GPIO function requests.
This adds initial support for requesting the various GPIO functions
necessary for certain ports. This just plugs in dumb request/free logic,
but serves as a building block for migrating off of the ->init_pins mess
to a wholly gpiolib backed solution (primarily parts with external
RTS/CTS pins, but will also allow us to clean up RXD pin testing).
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 761a800cb483..9e62349b3d9f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/dma-mapping.h> | 50 | #include <linux/dma-mapping.h> |
51 | #include <linux/scatterlist.h> | 51 | #include <linux/scatterlist.h> |
52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
53 | #include <linux/gpio.h> | ||
53 | 54 | ||
54 | #ifdef CONFIG_SUPERH | 55 | #ifdef CONFIG_SUPERH |
55 | #include <asm/sh_bios.h> | 56 | #include <asm/sh_bios.h> |
@@ -73,6 +74,7 @@ struct sci_port { | |||
73 | struct clk *fclk; | 74 | struct clk *fclk; |
74 | 75 | ||
75 | char *irqstr[SCIx_NR_IRQS]; | 76 | char *irqstr[SCIx_NR_IRQS]; |
77 | char *gpiostr[SCIx_NR_FNS]; | ||
76 | 78 | ||
77 | struct dma_chan *chan_tx; | 79 | struct dma_chan *chan_tx; |
78 | struct dma_chan *chan_rx; | 80 | struct dma_chan *chan_rx; |
@@ -1105,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port) | |||
1105 | } | 1107 | } |
1106 | } | 1108 | } |
1107 | 1109 | ||
1110 | static const char *sci_gpio_names[SCIx_NR_FNS] = { | ||
1111 | "sck", "rxd", "txd", "cts", "rts", | ||
1112 | }; | ||
1113 | |||
1114 | static const char *sci_gpio_str(unsigned int index) | ||
1115 | { | ||
1116 | return sci_gpio_names[index]; | ||
1117 | } | ||
1118 | |||
1119 | static void __devinit sci_init_gpios(struct sci_port *port) | ||
1120 | { | ||
1121 | struct uart_port *up = &port->port; | ||
1122 | int i; | ||
1123 | |||
1124 | if (!port->cfg) | ||
1125 | return; | ||
1126 | |||
1127 | for (i = 0; i < SCIx_NR_FNS; i++) { | ||
1128 | const char *desc; | ||
1129 | int ret; | ||
1130 | |||
1131 | if (!port->cfg->gpios[i]) | ||
1132 | continue; | ||
1133 | |||
1134 | desc = sci_gpio_str(i); | ||
1135 | |||
1136 | port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s", | ||
1137 | dev_name(up->dev), desc); | ||
1138 | |||
1139 | /* | ||
1140 | * If we've failed the allocation, we can still continue | ||
1141 | * on with a NULL string. | ||
1142 | */ | ||
1143 | if (!port->gpiostr[i]) | ||
1144 | dev_notice(up->dev, "%s string allocation failure\n", | ||
1145 | desc); | ||
1146 | |||
1147 | ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]); | ||
1148 | if (unlikely(ret != 0)) { | ||
1149 | dev_notice(up->dev, "failed %s gpio request\n", desc); | ||
1150 | |||
1151 | /* | ||
1152 | * If we can't get the GPIO for whatever reason, | ||
1153 | * no point in keeping the verbose string around. | ||
1154 | */ | ||
1155 | kfree(port->gpiostr[i]); | ||
1156 | } | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | static void sci_free_gpios(struct sci_port *port) | ||
1161 | { | ||
1162 | int i; | ||
1163 | |||
1164 | for (i = 0; i < SCIx_NR_FNS; i++) | ||
1165 | if (port->cfg->gpios[i]) { | ||
1166 | gpio_free(port->cfg->gpios[i]); | ||
1167 | kfree(port->gpiostr[i]); | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1108 | static unsigned int sci_tx_empty(struct uart_port *port) | 1171 | static unsigned int sci_tx_empty(struct uart_port *port) |
1109 | { | 1172 | { |
1110 | unsigned short status = sci_in(port, SCxSR); | 1173 | unsigned short status = sci_in(port, SCxSR); |
@@ -1962,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1962 | struct uart_port *port = &sci_port->port; | 2025 | struct uart_port *port = &sci_port->port; |
1963 | int ret; | 2026 | int ret; |
1964 | 2027 | ||
2028 | sci_port->cfg = p; | ||
2029 | |||
1965 | port->ops = &sci_uart_ops; | 2030 | port->ops = &sci_uart_ops; |
1966 | port->iotype = UPIO_MEM; | 2031 | port->iotype = UPIO_MEM; |
1967 | port->line = index; | 2032 | port->line = index; |
@@ -2007,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
2007 | 2072 | ||
2008 | port->dev = &dev->dev; | 2073 | port->dev = &dev->dev; |
2009 | 2074 | ||
2075 | sci_init_gpios(sci_port); | ||
2076 | |||
2010 | pm_runtime_irq_safe(&dev->dev); | 2077 | pm_runtime_irq_safe(&dev->dev); |
2011 | pm_runtime_enable(&dev->dev); | 2078 | pm_runtime_enable(&dev->dev); |
2012 | } | 2079 | } |
@@ -2041,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
2041 | p->error_mask |= (1 << p->overrun_bit); | 2108 | p->error_mask |= (1 << p->overrun_bit); |
2042 | } | 2109 | } |
2043 | 2110 | ||
2044 | sci_port->cfg = p; | ||
2045 | |||
2046 | port->mapbase = p->mapbase; | 2111 | port->mapbase = p->mapbase; |
2047 | port->type = p->type; | 2112 | port->type = p->type; |
2048 | port->flags = p->flags; | 2113 | port->flags = p->flags; |
@@ -2249,6 +2314,8 @@ static int sci_remove(struct platform_device *dev) | |||
2249 | cpufreq_unregister_notifier(&port->freq_transition, | 2314 | cpufreq_unregister_notifier(&port->freq_transition, |
2250 | CPUFREQ_TRANSITION_NOTIFIER); | 2315 | CPUFREQ_TRANSITION_NOTIFIER); |
2251 | 2316 | ||
2317 | sci_free_gpios(port); | ||
2318 | |||
2252 | uart_remove_one_port(&sci_uart_driver, &port->port); | 2319 | uart_remove_one_port(&sci_uart_driver, &port->port); |
2253 | 2320 | ||
2254 | clk_put(port->iclk); | 2321 | clk_put(port->iclk); |