diff options
Diffstat (limited to 'drivers/tty/serial/8250/8250_dw.c')
-rw-r--r-- | drivers/tty/serial/8250/8250_dw.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index db0e66f6dd0e..3dedd2470db1 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/acpi.h> | 28 | #include <linux/acpi.h> |
29 | #include <linux/clk.h> | ||
29 | 30 | ||
30 | #include "8250.h" | 31 | #include "8250.h" |
31 | 32 | ||
@@ -55,8 +56,9 @@ | |||
55 | 56 | ||
56 | 57 | ||
57 | struct dw8250_data { | 58 | struct dw8250_data { |
58 | int last_lcr; | 59 | int last_lcr; |
59 | int line; | 60 | int line; |
61 | struct clk *clk; | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) | 64 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) |
@@ -136,8 +138,13 @@ static int dw8250_probe_of(struct uart_port *p) | |||
136 | if (!of_property_read_u32(np, "reg-shift", &val)) | 138 | if (!of_property_read_u32(np, "reg-shift", &val)) |
137 | p->regshift = val; | 139 | p->regshift = val; |
138 | 140 | ||
141 | /* clock got configured through clk api, all done */ | ||
142 | if (p->uartclk) | ||
143 | return 0; | ||
144 | |||
145 | /* try to find out clock frequency from DT as fallback */ | ||
139 | if (of_property_read_u32(np, "clock-frequency", &val)) { | 146 | if (of_property_read_u32(np, "clock-frequency", &val)) { |
140 | dev_err(p->dev, "no clock-frequency property set\n"); | 147 | dev_err(p->dev, "clk or clock-frequency not defined\n"); |
141 | return -EINVAL; | 148 | return -EINVAL; |
142 | } | 149 | } |
143 | p->uartclk = val; | 150 | p->uartclk = val; |
@@ -294,9 +301,20 @@ static int dw8250_probe(struct platform_device *pdev) | |||
294 | if (!uart.port.membase) | 301 | if (!uart.port.membase) |
295 | return -ENOMEM; | 302 | return -ENOMEM; |
296 | 303 | ||
304 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
305 | if (!data) | ||
306 | return -ENOMEM; | ||
307 | |||
308 | data->clk = devm_clk_get(&pdev->dev, NULL); | ||
309 | if (!IS_ERR(data->clk)) { | ||
310 | clk_prepare_enable(data->clk); | ||
311 | uart.port.uartclk = clk_get_rate(data->clk); | ||
312 | } | ||
313 | |||
297 | uart.port.iotype = UPIO_MEM; | 314 | uart.port.iotype = UPIO_MEM; |
298 | uart.port.serial_in = dw8250_serial_in; | 315 | uart.port.serial_in = dw8250_serial_in; |
299 | uart.port.serial_out = dw8250_serial_out; | 316 | uart.port.serial_out = dw8250_serial_out; |
317 | uart.port.private_data = data; | ||
300 | 318 | ||
301 | dw8250_setup_port(&uart); | 319 | dw8250_setup_port(&uart); |
302 | 320 | ||
@@ -312,12 +330,6 @@ static int dw8250_probe(struct platform_device *pdev) | |||
312 | return -ENODEV; | 330 | return -ENODEV; |
313 | } | 331 | } |
314 | 332 | ||
315 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
316 | if (!data) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | uart.port.private_data = data; | ||
320 | |||
321 | data->line = serial8250_register_8250_port(&uart); | 333 | data->line = serial8250_register_8250_port(&uart); |
322 | if (data->line < 0) | 334 | if (data->line < 0) |
323 | return data->line; | 335 | return data->line; |
@@ -333,6 +345,9 @@ static int dw8250_remove(struct platform_device *pdev) | |||
333 | 345 | ||
334 | serial8250_unregister_port(data->line); | 346 | serial8250_unregister_port(data->line); |
335 | 347 | ||
348 | if (!IS_ERR(data->clk)) | ||
349 | clk_disable_unprepare(data->clk); | ||
350 | |||
336 | return 0; | 351 | return 0; |
337 | } | 352 | } |
338 | 353 | ||