Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
[deliverable/linux.git] / drivers / tty / serial / 8250 / 8250_dw.c
CommitLineData
7d4008eb
JI
1/*
2 * Synopsys DesignWare 8250 driver.
3 *
4 * Copyright 2011 Picochip, Jamie Iles.
6a7320c4 5 * Copyright 2013 Intel Corporation
7d4008eb
JI
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
13 * LCR is written whilst busy. If it is, then a busy detect interrupt is
14 * raised, the LCR needs to be rewritten and the uart status register read.
15 */
16#include <linux/device.h>
17#include <linux/init.h>
18#include <linux/io.h>
19#include <linux/module.h>
20#include <linux/serial_8250.h>
21#include <linux/serial_core.h>
22#include <linux/serial_reg.h>
23#include <linux/of.h>
24#include <linux/of_irq.h>
25#include <linux/of_platform.h>
26#include <linux/platform_device.h>
27#include <linux/slab.h>
6a7320c4 28#include <linux/acpi.h>
e302cd93 29#include <linux/clk.h>
ffc3ae6d 30#include <linux/pm_runtime.h>
7d4008eb 31
d5f1af7e
DD
32#include <asm/byteorder.h>
33
7277b2a1
HK
34#include "8250.h"
35
30046df2
HK
36/* Offsets for the DesignWare specific registers */
37#define DW_UART_USR 0x1f /* UART Status Register */
38#define DW_UART_CPR 0xf4 /* Component Parameter Register */
39#define DW_UART_UCV 0xf8 /* UART Component Version */
40
41/* Component Parameter Register bits */
42#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
43#define DW_UART_CPR_AFCE_MODE (1 << 4)
44#define DW_UART_CPR_THRE_MODE (1 << 5)
45#define DW_UART_CPR_SIR_MODE (1 << 6)
46#define DW_UART_CPR_SIR_LP_MODE (1 << 7)
47#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8)
48#define DW_UART_CPR_FIFO_ACCESS (1 << 9)
49#define DW_UART_CPR_FIFO_STAT (1 << 10)
50#define DW_UART_CPR_SHADOW (1 << 11)
51#define DW_UART_CPR_ENCODED_PARMS (1 << 12)
52#define DW_UART_CPR_DMA_EXTRA (1 << 13)
53#define DW_UART_CPR_FIFO_MODE (0xff << 16)
54/* Helper for fifo size calculation */
55#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16)
56
57
7d4008eb 58struct dw8250_data {
e302cd93
EL
59 int last_lcr;
60 int line;
61 struct clk *clk;
d5f1af7e 62 u8 usr_reg;
7d4008eb
JI
63};
64
65static void dw8250_serial_out(struct uart_port *p, int offset, int value)
66{
67 struct dw8250_data *d = p->private_data;
68
69 if (offset == UART_LCR)
70 d->last_lcr = value;
71
72 offset <<= p->regshift;
73 writeb(value, p->membase + offset);
74}
75
76static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
77{
78 offset <<= p->regshift;
79
80 return readb(p->membase + offset);
81}
82
d5f1af7e
DD
83/* Read Back (rb) version to ensure register access ording. */
84static void dw8250_serial_out_rb(struct uart_port *p, int offset, int value)
85{
86 dw8250_serial_out(p, offset, value);
87 dw8250_serial_in(p, UART_LCR);
88}
89
7d4008eb
JI
90static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
91{
92 struct dw8250_data *d = p->private_data;
93
94 if (offset == UART_LCR)
95 d->last_lcr = value;
96
97 offset <<= p->regshift;
98 writel(value, p->membase + offset);
99}
100
101static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
102{
103 offset <<= p->regshift;
104
105 return readl(p->membase + offset);
106}
107
7d4008eb
JI
108static int dw8250_handle_irq(struct uart_port *p)
109{
110 struct dw8250_data *d = p->private_data;
111 unsigned int iir = p->serial_in(p, UART_IIR);
112
113 if (serial8250_handle_irq(p, iir)) {
114 return 1;
115 } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
116 /* Clear the USR and write the LCR again. */
d5f1af7e 117 (void)p->serial_in(p, d->usr_reg);
68e56cb3 118 p->serial_out(p, UART_LCR, d->last_lcr);
7d4008eb
JI
119
120 return 1;
121 }
122
123 return 0;
124}
125
ffc3ae6d
HK
126static void
127dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
128{
129 if (!state)
130 pm_runtime_get_sync(port->dev);
131
132 serial8250_do_pm(port, state, old);
133
134 if (state)
135 pm_runtime_put_sync_suspend(port->dev);
136}
137
d5f1af7e
DD
138static void dw8250_setup_port(struct uart_8250_port *up)
139{
140 struct uart_port *p = &up->port;
141 u32 reg = readl(p->membase + DW_UART_UCV);
142
143 /*
144 * If the Component Version Register returns zero, we know that
145 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
146 */
147 if (!reg)
148 return;
149
150 dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
151 (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
152
153 reg = readl(p->membase + DW_UART_CPR);
154 if (!reg)
155 return;
156
157 /* Select the type based on fifo */
158 if (reg & DW_UART_CPR_FIFO_MODE) {
159 p->type = PORT_16550A;
160 p->flags |= UPF_FIXED_TYPE;
161 p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
162 up->tx_loadsz = p->fifosize;
163 up->capabilities = UART_CAP_FIFO;
164 }
165
166 if (reg & DW_UART_CPR_AFCE_MODE)
167 up->capabilities |= UART_CAP_AFE;
168}
169
170static int dw8250_probe_of(struct uart_port *p,
171 struct dw8250_data *data)
a7260c8c
HK
172{
173 struct device_node *np = p->dev->of_node;
174 u32 val;
d5f1af7e
DD
175 bool has_ucv = true;
176
177 if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
178#ifdef __BIG_ENDIAN
179 /*
180 * Low order bits of these 64-bit registers, when
181 * accessed as a byte, are 7 bytes further down in the
182 * address space in big endian mode.
183 */
184 p->membase += 7;
185#endif
186 p->serial_out = dw8250_serial_out_rb;
187 p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
188 p->type = PORT_OCTEON;
189 data->usr_reg = 0x27;
190 has_ucv = false;
191 } else if (!of_property_read_u32(np, "reg-io-width", &val)) {
a7260c8c
HK
192 switch (val) {
193 case 1:
194 break;
195 case 4:
196 p->iotype = UPIO_MEM32;
197 p->serial_in = dw8250_serial_in32;
198 p->serial_out = dw8250_serial_out32;
199 break;
200 default:
201 dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
202 return -EINVAL;
203 }
204 }
d5f1af7e
DD
205 if (has_ucv)
206 dw8250_setup_port(container_of(p, struct uart_8250_port, port));
a7260c8c
HK
207
208 if (!of_property_read_u32(np, "reg-shift", &val))
209 p->regshift = val;
210
e302cd93
EL
211 /* clock got configured through clk api, all done */
212 if (p->uartclk)
213 return 0;
214
215 /* try to find out clock frequency from DT as fallback */
a7260c8c 216 if (of_property_read_u32(np, "clock-frequency", &val)) {
e302cd93 217 dev_err(p->dev, "clk or clock-frequency not defined\n");
a7260c8c
HK
218 return -EINVAL;
219 }
220 p->uartclk = val;
221
222 return 0;
223}
224
053fac36 225#ifdef CONFIG_ACPI
94b2b47c 226static int dw8250_probe_acpi(struct uart_8250_port *up)
6a7320c4
HK
227{
228 const struct acpi_device_id *id;
94b2b47c 229 struct uart_port *p = &up->port;
6a7320c4 230
d5f1af7e
DD
231 dw8250_setup_port(up);
232
6a7320c4
HK
233 id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
234 if (!id)
235 return -ENODEV;
236
237 p->iotype = UPIO_MEM32;
238 p->serial_in = dw8250_serial_in32;
239 p->serial_out = dw8250_serial_out32;
240 p->regshift = 2;
aea02e87
HK
241
242 if (!p->uartclk)
243 p->uartclk = (unsigned int)id->driver_data;
6a7320c4 244
94b2b47c
HK
245 up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
246 if (!up->dma)
247 return -ENOMEM;
248
249 up->dma->rxconf.src_maxburst = p->fifosize / 4;
250 up->dma->txconf.dst_maxburst = p->fifosize / 4;
7277b2a1 251
6a7320c4
HK
252 return 0;
253}
053fac36 254#else
3ec857ff 255static inline int dw8250_probe_acpi(struct uart_8250_port *up)
053fac36
HK
256{
257 return -ENODEV;
258}
259#endif /* CONFIG_ACPI */
6a7320c4 260
9671f099 261static int dw8250_probe(struct platform_device *pdev)
7d4008eb 262{
2655a2c7 263 struct uart_8250_port uart = {};
7d4008eb
JI
264 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
265 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
7d4008eb 266 struct dw8250_data *data;
a7260c8c 267 int err;
7d4008eb
JI
268
269 if (!regs || !irq) {
270 dev_err(&pdev->dev, "no registers/irq defined\n");
271 return -EINVAL;
272 }
273
2655a2c7
AC
274 spin_lock_init(&uart.port.lock);
275 uart.port.mapbase = regs->start;
276 uart.port.irq = irq->start;
277 uart.port.handle_irq = dw8250_handle_irq;
ffc3ae6d 278 uart.port.pm = dw8250_do_pm;
2655a2c7 279 uart.port.type = PORT_8250;
f93366ff 280 uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
2655a2c7 281 uart.port.dev = &pdev->dev;
7d4008eb 282
b88d0826
HK
283 uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
284 resource_size(regs));
f93366ff
HK
285 if (!uart.port.membase)
286 return -ENOMEM;
287
e302cd93
EL
288 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
289 if (!data)
290 return -ENOMEM;
291
d5f1af7e 292 data->usr_reg = DW_UART_USR;
e302cd93
EL
293 data->clk = devm_clk_get(&pdev->dev, NULL);
294 if (!IS_ERR(data->clk)) {
295 clk_prepare_enable(data->clk);
296 uart.port.uartclk = clk_get_rate(data->clk);
297 }
298
2655a2c7
AC
299 uart.port.iotype = UPIO_MEM;
300 uart.port.serial_in = dw8250_serial_in;
301 uart.port.serial_out = dw8250_serial_out;
e302cd93 302 uart.port.private_data = data;
a7260c8c
HK
303
304 if (pdev->dev.of_node) {
d5f1af7e 305 err = dw8250_probe_of(&uart.port, data);
a7260c8c
HK
306 if (err)
307 return err;
6a7320c4 308 } else if (ACPI_HANDLE(&pdev->dev)) {
94b2b47c 309 err = dw8250_probe_acpi(&uart);
6a7320c4
HK
310 if (err)
311 return err;
a7260c8c
HK
312 } else {
313 return -ENODEV;
7d4008eb
JI
314 }
315
2655a2c7 316 data->line = serial8250_register_8250_port(&uart);
7d4008eb
JI
317 if (data->line < 0)
318 return data->line;
319
320 platform_set_drvdata(pdev, data);
321
ffc3ae6d
HK
322 pm_runtime_set_active(&pdev->dev);
323 pm_runtime_enable(&pdev->dev);
324
7d4008eb
JI
325 return 0;
326}
327
ae8d8a14 328static int dw8250_remove(struct platform_device *pdev)
7d4008eb
JI
329{
330 struct dw8250_data *data = platform_get_drvdata(pdev);
331
ffc3ae6d
HK
332 pm_runtime_get_sync(&pdev->dev);
333
7d4008eb
JI
334 serial8250_unregister_port(data->line);
335
e302cd93
EL
336 if (!IS_ERR(data->clk))
337 clk_disable_unprepare(data->clk);
338
ffc3ae6d
HK
339 pm_runtime_disable(&pdev->dev);
340 pm_runtime_put_noidle(&pdev->dev);
341
7d4008eb
JI
342 return 0;
343}
344
b61c5ed5 345#ifdef CONFIG_PM
ffc3ae6d 346static int dw8250_suspend(struct device *dev)
b61c5ed5 347{
ffc3ae6d 348 struct dw8250_data *data = dev_get_drvdata(dev);
b61c5ed5
JH
349
350 serial8250_suspend_port(data->line);
351
352 return 0;
353}
354
ffc3ae6d 355static int dw8250_resume(struct device *dev)
b61c5ed5 356{
ffc3ae6d 357 struct dw8250_data *data = dev_get_drvdata(dev);
b61c5ed5
JH
358
359 serial8250_resume_port(data->line);
360
361 return 0;
362}
b61c5ed5
JH
363#endif /* CONFIG_PM */
364
ffc3ae6d
HK
365#ifdef CONFIG_PM_RUNTIME
366static int dw8250_runtime_suspend(struct device *dev)
367{
368 struct dw8250_data *data = dev_get_drvdata(dev);
369
dbd2df85
EG
370 if (!IS_ERR(data->clk))
371 clk_disable_unprepare(data->clk);
ffc3ae6d
HK
372
373 return 0;
374}
375
376static int dw8250_runtime_resume(struct device *dev)
377{
378 struct dw8250_data *data = dev_get_drvdata(dev);
379
dbd2df85
EG
380 if (!IS_ERR(data->clk))
381 clk_prepare_enable(data->clk);
ffc3ae6d
HK
382
383 return 0;
384}
385#endif
386
387static const struct dev_pm_ops dw8250_pm_ops = {
388 SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
389 SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
390};
391
a7260c8c 392static const struct of_device_id dw8250_of_match[] = {
7d4008eb 393 { .compatible = "snps,dw-apb-uart" },
d5f1af7e 394 { .compatible = "cavium,octeon-3860-uart" },
7d4008eb
JI
395 { /* Sentinel */ }
396};
a7260c8c 397MODULE_DEVICE_TABLE(of, dw8250_of_match);
7d4008eb 398
6a7320c4 399static const struct acpi_device_id dw8250_acpi_match[] = {
aea02e87
HK
400 { "INT33C4", 0 },
401 { "INT33C5", 0 },
9d83e180 402 { "80860F0A", 0 },
6a7320c4
HK
403 { },
404};
405MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
406
7d4008eb
JI
407static struct platform_driver dw8250_platform_driver = {
408 .driver = {
409 .name = "dw-apb-uart",
410 .owner = THIS_MODULE,
ffc3ae6d 411 .pm = &dw8250_pm_ops,
a7260c8c 412 .of_match_table = dw8250_of_match,
6a7320c4 413 .acpi_match_table = ACPI_PTR(dw8250_acpi_match),
7d4008eb
JI
414 },
415 .probe = dw8250_probe,
2d47b716 416 .remove = dw8250_remove,
7d4008eb
JI
417};
418
c8381c15 419module_platform_driver(dw8250_platform_driver);
7d4008eb
JI
420
421MODULE_AUTHOR("Jamie Iles");
422MODULE_LICENSE("GPL");
423MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
This page took 0.157854 seconds and 5 git commands to generate.