aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMurali Karicheri <m-karicheri2@ti.com>2012-10-22 11:58:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-25 14:32:29 -0400
commit0bbeb3c3e84bc963d1c66661e082d207023b0e5c (patch)
tree7cde25a865c1acd1bc030da4816ea78603484ec8
parentcadf74869013dc309bde50ed446f56d33a6a9806 (diff)
of serial port driver - add clk_get_rate() support
Currently this driver expects the clock-frequency attribute. This patch allows getting clock-frequency through clk driver API clk_get_rate() if clock-frequency attribute is not defined. So in the device bindings for serial device, one can add clocks phandle to refer to the clk device to get the rate. Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/of_serial.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index df443b908ca3..533ccfe77094 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};
@@ -51,7 +53,8 @@ EXPORT_SYMBOL_GPL(tegra_serial_handle_break);
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 __devinit 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 (info->clk == NULL) {
70 dev_warn(&ofdev->dev,
71 "clk or clock-frequency not defined\n");
72 return -ENODEV;
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,6 +128,10 @@ 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/*
@@ -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}