aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/of_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/of_serial.c')
-rw-r--r--drivers/tty/serial/of_serial.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index df443b908ca3..e7cae1c2d7d2 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -21,8 +21,10 @@
21#include <linux/of_serial.h> 21#include <linux/of_serial.h>
22#include <linux/of_platform.h> 22#include <linux/of_platform.h>
23#include <linux/nwpserial.h> 23#include <linux/nwpserial.h>
24#include <linux/clk.h>
24 25
25struct of_serial_info { 26struct of_serial_info {
27 struct clk *clk;
26 int type; 28 int type;
27 int line; 29 int line;
28}; 30};
@@ -50,8 +52,9 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
50/* 52/*
51 * Fill a struct uart_port for a given device node 53 * Fill a struct uart_port for a given device node
52 */ 54 */
53static int __devinit of_platform_serial_setup(struct platform_device *ofdev, 55static int of_platform_serial_setup(struct platform_device *ofdev,
54 int type, struct uart_port *port) 56 int type, struct uart_port *port,
57 struct of_serial_info *info)
55{ 58{
56 struct resource resource; 59 struct resource resource;
57 struct device_node *np = ofdev->dev.of_node; 60 struct device_node *np = ofdev->dev.of_node;
@@ -60,8 +63,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
60 63
61 memset(port, 0, sizeof *port); 64 memset(port, 0, sizeof *port);
62 if (of_property_read_u32(np, "clock-frequency", &clk)) { 65 if (of_property_read_u32(np, "clock-frequency", &clk)) {
63 dev_warn(&ofdev->dev, "no clock-frequency property set\n"); 66
64 return -ENODEV; 67 /* Get clk rate through clk driver if present */
68 info->clk = clk_get(&ofdev->dev, NULL);
69 if (IS_ERR(info->clk)) {
70 dev_warn(&ofdev->dev,
71 "clk or clock-frequency not defined\n");
72 return PTR_ERR(info->clk);
73 }
74
75 clk_prepare_enable(info->clk);
76 clk = clk_get_rate(info->clk);
65 } 77 }
66 /* If current-speed was set, then try not to change it. */ 78 /* If current-speed was set, then try not to change it. */
67 if (of_property_read_u32(np, "current-speed", &spd) == 0) 79 if (of_property_read_u32(np, "current-speed", &spd) == 0)
@@ -70,7 +82,7 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
70 ret = of_address_to_resource(np, 0, &resource); 82 ret = of_address_to_resource(np, 0, &resource);
71 if (ret) { 83 if (ret) {
72 dev_warn(&ofdev->dev, "invalid address\n"); 84 dev_warn(&ofdev->dev, "invalid address\n");
73 return ret; 85 goto out;
74 } 86 }
75 87
76 spin_lock_init(&port->lock); 88 spin_lock_init(&port->lock);
@@ -97,7 +109,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
97 default: 109 default:
98 dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", 110 dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
99 prop); 111 prop);
100 return -EINVAL; 112 ret = -EINVAL;
113 goto out;
101 } 114 }
102 } 115 }
103 116
@@ -115,13 +128,17 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
115 port->handle_break = tegra_serial_handle_break; 128 port->handle_break = tegra_serial_handle_break;
116 129
117 return 0; 130 return 0;
131out:
132 if (info->clk)
133 clk_disable_unprepare(info->clk);
134 return ret;
118} 135}
119 136
120/* 137/*
121 * Try to register a serial port 138 * Try to register a serial port
122 */ 139 */
123static struct of_device_id of_platform_serial_table[]; 140static struct of_device_id of_platform_serial_table[];
124static int __devinit of_platform_serial_probe(struct platform_device *ofdev) 141static int of_platform_serial_probe(struct platform_device *ofdev)
125{ 142{
126 const struct of_device_id *match; 143 const struct of_device_id *match;
127 struct of_serial_info *info; 144 struct of_serial_info *info;
@@ -141,7 +158,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
141 return -ENOMEM; 158 return -ENOMEM;
142 159
143 port_type = (unsigned long)match->data; 160 port_type = (unsigned long)match->data;
144 ret = of_platform_serial_setup(ofdev, port_type, &port); 161 ret = of_platform_serial_setup(ofdev, port_type, &port, info);
145 if (ret) 162 if (ret)
146 goto out; 163 goto out;
147 164
@@ -204,6 +221,9 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
204 /* need to add code for these */ 221 /* need to add code for these */
205 break; 222 break;
206 } 223 }
224
225 if (info->clk)
226 clk_disable_unprepare(info->clk);
207 kfree(info); 227 kfree(info);
208 return 0; 228 return 0;
209} 229}
@@ -211,7 +231,7 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
211/* 231/*
212 * A few common types, add more as needed. 232 * A few common types, add more as needed.
213 */ 233 */
214static struct of_device_id __devinitdata of_platform_serial_table[] = { 234static struct of_device_id of_platform_serial_table[] = {
215 { .compatible = "ns8250", .data = (void *)PORT_8250, }, 235 { .compatible = "ns8250", .data = (void *)PORT_8250, },
216 { .compatible = "ns16450", .data = (void *)PORT_16450, }, 236 { .compatible = "ns16450", .data = (void *)PORT_16450, },
217 { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, 237 { .compatible = "ns16550a", .data = (void *)PORT_16550A, },