.. | .. |
---|
19 | 19 | #include <linux/of_irq.h> |
---|
20 | 20 | #include <linux/of_platform.h> |
---|
21 | 21 | #include <linux/platform_device.h> |
---|
| 22 | +#include <linux/workqueue.h> |
---|
| 23 | +#include <linux/notifier.h> |
---|
22 | 24 | #include <linux/slab.h> |
---|
23 | 25 | #include <linux/acpi.h> |
---|
24 | 26 | #include <linux/clk.h> |
---|
.. | .. |
---|
27 | 29 | |
---|
28 | 30 | #include <asm/byteorder.h> |
---|
29 | 31 | |
---|
30 | | -#include "8250.h" |
---|
| 32 | +#ifdef MODULE |
---|
| 33 | +#include "8250_dwlib.c" |
---|
| 34 | +#else |
---|
| 35 | +#include "8250_dwlib.h" |
---|
| 36 | +#endif |
---|
31 | 37 | |
---|
32 | 38 | /* Offsets for the DesignWare specific registers */ |
---|
33 | 39 | #define DW_UART_USR 0x1f /* UART Status Register */ |
---|
34 | | -#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ |
---|
35 | 40 | #define DW_UART_RFL 0x21 /* UART Receive Fifo Level Register */ |
---|
36 | | -#define DW_UART_CPR 0xf4 /* Component Parameter Register */ |
---|
37 | | -#define DW_UART_UCV 0xf8 /* UART Component Version */ |
---|
38 | | - |
---|
39 | | -/* Component Parameter Register bits */ |
---|
40 | | -#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) |
---|
41 | | -#define DW_UART_CPR_AFCE_MODE (1 << 4) |
---|
42 | | -#define DW_UART_CPR_THRE_MODE (1 << 5) |
---|
43 | | -#define DW_UART_CPR_SIR_MODE (1 << 6) |
---|
44 | | -#define DW_UART_CPR_SIR_LP_MODE (1 << 7) |
---|
45 | | -#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) |
---|
46 | | -#define DW_UART_CPR_FIFO_ACCESS (1 << 9) |
---|
47 | | -#define DW_UART_CPR_FIFO_STAT (1 << 10) |
---|
48 | | -#define DW_UART_CPR_SHADOW (1 << 11) |
---|
49 | | -#define DW_UART_CPR_ENCODED_PARMS (1 << 12) |
---|
50 | | -#define DW_UART_CPR_DMA_EXTRA (1 << 13) |
---|
51 | | -#define DW_UART_CPR_FIFO_MODE (0xff << 16) |
---|
52 | | -/* Helper for fifo size calculation */ |
---|
53 | | -#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) |
---|
54 | 41 | |
---|
55 | 42 | /* DesignWare specific register fields */ |
---|
56 | 43 | #define DW_UART_MCR_SIRE BIT(6) |
---|
57 | 44 | |
---|
58 | 45 | struct dw8250_data { |
---|
| 46 | + struct dw8250_port_data data; |
---|
| 47 | + |
---|
59 | 48 | u8 usr_reg; |
---|
60 | | - u8 dlf_size; |
---|
61 | | - int line; |
---|
62 | 49 | int msr_mask_on; |
---|
63 | 50 | int msr_mask_off; |
---|
64 | 51 | struct clk *clk; |
---|
65 | 52 | struct clk *pclk; |
---|
| 53 | + struct notifier_block clk_notifier; |
---|
| 54 | + struct work_struct clk_work; |
---|
66 | 55 | struct reset_control *rst; |
---|
67 | | - struct uart_8250_dma dma; |
---|
| 56 | + |
---|
68 | 57 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
69 | 58 | int irq; |
---|
70 | 59 | int irq_wake; |
---|
.. | .. |
---|
74 | 63 | unsigned int uart_16550_compatible:1; |
---|
75 | 64 | }; |
---|
76 | 65 | |
---|
77 | | -static inline u32 dw8250_readl_ext(struct uart_port *p, int offset) |
---|
| 66 | +static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) |
---|
78 | 67 | { |
---|
79 | | - if (p->iotype == UPIO_MEM32BE) |
---|
80 | | - return ioread32be(p->membase + offset); |
---|
81 | | - return readl(p->membase + offset); |
---|
| 68 | + return container_of(data, struct dw8250_data, data); |
---|
82 | 69 | } |
---|
83 | 70 | |
---|
84 | | -static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg) |
---|
| 71 | +static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) |
---|
85 | 72 | { |
---|
86 | | - if (p->iotype == UPIO_MEM32BE) |
---|
87 | | - iowrite32be(reg, p->membase + offset); |
---|
88 | | - else |
---|
89 | | - writel(reg, p->membase + offset); |
---|
| 73 | + return container_of(nb, struct dw8250_data, clk_notifier); |
---|
| 74 | +} |
---|
| 75 | + |
---|
| 76 | +static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work) |
---|
| 77 | +{ |
---|
| 78 | + return container_of(work, struct dw8250_data, clk_work); |
---|
90 | 79 | } |
---|
91 | 80 | |
---|
92 | 81 | static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) |
---|
93 | 82 | { |
---|
94 | | - struct dw8250_data *d = p->private_data; |
---|
| 83 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
95 | 84 | |
---|
96 | 85 | /* Override any modem control signals if needed */ |
---|
97 | 86 | if (offset == UART_MSR) { |
---|
.. | .. |
---|
145 | 134 | /* Returns once the transmitter is empty or we run out of retries */ |
---|
146 | 135 | static void dw8250_tx_wait_empty(struct uart_port *p) |
---|
147 | 136 | { |
---|
| 137 | + struct uart_8250_port *up = up_to_u8250p(p); |
---|
148 | 138 | unsigned int tries = 20000; |
---|
149 | 139 | unsigned int delay_threshold = tries - 1000; |
---|
150 | 140 | unsigned int lsr; |
---|
151 | 141 | |
---|
152 | 142 | while (tries--) { |
---|
153 | 143 | lsr = readb (p->membase + (UART_LSR << p->regshift)); |
---|
| 144 | + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; |
---|
| 145 | + |
---|
154 | 146 | if (lsr & UART_LSR_TEMT) |
---|
155 | 147 | break; |
---|
156 | 148 | |
---|
.. | .. |
---|
165 | 157 | |
---|
166 | 158 | static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) |
---|
167 | 159 | { |
---|
168 | | - struct dw8250_data *d = p->private_data; |
---|
| 160 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
169 | 161 | |
---|
170 | 162 | /* Allow the TX to drain before we reconfigure */ |
---|
171 | 163 | if (offset == UART_LCR) |
---|
.. | .. |
---|
180 | 172 | |
---|
181 | 173 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) |
---|
182 | 174 | { |
---|
183 | | - struct dw8250_data *d = p->private_data; |
---|
| 175 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
184 | 176 | |
---|
185 | 177 | writeb(value, p->membase + (offset << p->regshift)); |
---|
186 | 178 | |
---|
.. | .. |
---|
207 | 199 | |
---|
208 | 200 | static void dw8250_serial_outq(struct uart_port *p, int offset, int value) |
---|
209 | 201 | { |
---|
210 | | - struct dw8250_data *d = p->private_data; |
---|
| 202 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
211 | 203 | |
---|
212 | 204 | value &= 0xff; |
---|
213 | 205 | __raw_writeq(value, p->membase + (offset << p->regshift)); |
---|
.. | .. |
---|
221 | 213 | |
---|
222 | 214 | static void dw8250_serial_out32(struct uart_port *p, int offset, int value) |
---|
223 | 215 | { |
---|
224 | | - struct dw8250_data *d = p->private_data; |
---|
| 216 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
225 | 217 | |
---|
226 | 218 | writel(value, p->membase + (offset << p->regshift)); |
---|
227 | 219 | |
---|
.. | .. |
---|
238 | 230 | |
---|
239 | 231 | static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) |
---|
240 | 232 | { |
---|
241 | | - struct dw8250_data *d = p->private_data; |
---|
| 233 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
242 | 234 | |
---|
243 | 235 | iowrite32be(value, p->membase + (offset << p->regshift)); |
---|
244 | 236 | |
---|
.. | .. |
---|
256 | 248 | |
---|
257 | 249 | static int dw8250_handle_irq(struct uart_port *p) |
---|
258 | 250 | { |
---|
259 | | - struct dw8250_data *d = p->private_data; |
---|
| 251 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
260 | 252 | unsigned int iir = p->serial_in(p, UART_IIR); |
---|
261 | 253 | unsigned int status, usr, rfl; |
---|
262 | 254 | unsigned long flags; |
---|
.. | .. |
---|
292 | 284 | return 0; |
---|
293 | 285 | } |
---|
294 | 286 | |
---|
| 287 | +static void dw8250_clk_work_cb(struct work_struct *work) |
---|
| 288 | +{ |
---|
| 289 | + struct dw8250_data *d = work_to_dw8250_data(work); |
---|
| 290 | + struct uart_8250_port *up; |
---|
| 291 | + unsigned long rate; |
---|
| 292 | + |
---|
| 293 | + rate = clk_get_rate(d->clk); |
---|
| 294 | + if (rate <= 0) |
---|
| 295 | + return; |
---|
| 296 | + |
---|
| 297 | + up = serial8250_get_port(d->data.line); |
---|
| 298 | + |
---|
| 299 | + serial8250_update_uartclk(&up->port, rate); |
---|
| 300 | +} |
---|
| 301 | + |
---|
| 302 | +static int dw8250_clk_notifier_cb(struct notifier_block *nb, |
---|
| 303 | + unsigned long event, void *data) |
---|
| 304 | +{ |
---|
| 305 | + struct dw8250_data *d = clk_to_dw8250_data(nb); |
---|
| 306 | + |
---|
| 307 | + /* |
---|
| 308 | + * We have no choice but to defer the uartclk update due to two |
---|
| 309 | + * deadlocks. First one is caused by a recursive mutex lock which |
---|
| 310 | + * happens when clk_set_rate() is called from dw8250_set_termios(). |
---|
| 311 | + * Second deadlock is more tricky and is caused by an inverted order of |
---|
| 312 | + * the clk and tty-port mutexes lock. It happens if clock rate change |
---|
| 313 | + * is requested asynchronously while set_termios() is executed between |
---|
| 314 | + * tty-port mutex lock and clk_set_rate() function invocation and |
---|
| 315 | + * vise-versa. Anyway if we didn't have the reference clock alteration |
---|
| 316 | + * in the dw8250_set_termios() method we wouldn't have needed this |
---|
| 317 | + * deferred event handling complication. |
---|
| 318 | + */ |
---|
| 319 | + if (event == POST_RATE_CHANGE) { |
---|
| 320 | + queue_work(system_unbound_wq, &d->clk_work); |
---|
| 321 | + return NOTIFY_OK; |
---|
| 322 | + } |
---|
| 323 | + |
---|
| 324 | + return NOTIFY_DONE; |
---|
| 325 | +} |
---|
| 326 | + |
---|
295 | 327 | static void |
---|
296 | 328 | dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) |
---|
297 | 329 | { |
---|
.. | .. |
---|
307 | 339 | static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, |
---|
308 | 340 | struct ktermios *old) |
---|
309 | 341 | { |
---|
310 | | - unsigned int baud = tty_termios_baud_rate(termios); |
---|
311 | | - struct dw8250_data *d = p->private_data; |
---|
| 342 | +#ifndef CONFIG_ARCH_ROCKCHIP |
---|
| 343 | + unsigned long newrate = tty_termios_baud_rate(termios) * 16; |
---|
| 344 | +#endif |
---|
| 345 | + struct dw8250_data *d = to_dw8250_data(p->private_data); |
---|
312 | 346 | long rate; |
---|
313 | 347 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
| 348 | + unsigned int baud = tty_termios_baud_rate(termios); |
---|
314 | 349 | unsigned int rate_temp, diff; |
---|
315 | 350 | #endif |
---|
316 | 351 | int ret; |
---|
317 | 352 | |
---|
318 | | - if (IS_ERR(d->clk)) |
---|
319 | | - goto out; |
---|
320 | | - |
---|
321 | 353 | clk_disable_unprepare(d->clk); |
---|
322 | 354 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
323 | | - if (baud <= 115200) |
---|
324 | | - rate = 24000000; |
---|
325 | | - else if (baud == 230400) |
---|
326 | | - rate = baud * 16 * 2; |
---|
327 | | - else if (baud == 1152000) |
---|
328 | | - rate = baud * 16 * 2; |
---|
329 | | - else |
---|
330 | | - rate = baud * 16; |
---|
| 355 | + if (d->clk) { |
---|
| 356 | + if (baud <= 115200) |
---|
| 357 | + rate = 24000000; |
---|
| 358 | + else if (baud == 230400) |
---|
| 359 | + rate = baud * 16 * 2; |
---|
| 360 | + else if (baud == 1152000) |
---|
| 361 | + rate = baud * 16 * 2; |
---|
| 362 | + else |
---|
| 363 | + rate = baud * 16; |
---|
331 | 364 | |
---|
332 | | - ret = clk_set_rate(d->clk, rate); |
---|
333 | | - rate_temp = clk_get_rate(d->clk); |
---|
334 | | - diff = rate * 20 / 1000; |
---|
335 | | - /* |
---|
336 | | - * If rate_temp is not equal to rate, is means fractional frequency |
---|
337 | | - * division is failed. Then use Integer frequency division, and |
---|
338 | | - * the buad rate error must be under -+2% |
---|
339 | | - */ |
---|
340 | | - if ((rate_temp < rate) && ((rate - rate_temp) > diff)) { |
---|
341 | | - ret = clk_set_rate(d->clk, rate + diff); |
---|
| 365 | + ret = clk_set_rate(d->clk, rate); |
---|
342 | 366 | rate_temp = clk_get_rate(d->clk); |
---|
343 | | - if ((rate_temp < rate) && ((rate - rate_temp) > diff)) |
---|
344 | | - dev_info(p->dev, "set rate:%ld, but get rate:%d\n", |
---|
345 | | - rate, rate_temp); |
---|
346 | | - else if ((rate < rate_temp) && ((rate_temp - rate) > diff)) |
---|
347 | | - dev_info(p->dev, "set rate:%ld, but get rate:%d\n", |
---|
348 | | - rate, rate_temp); |
---|
| 367 | + diff = rate * 20 / 1000; |
---|
| 368 | + /* |
---|
| 369 | + * If rate_temp is not equal to rate, is means fractional frequency |
---|
| 370 | + * division is failed. Then use Integer frequency division, and |
---|
| 371 | + * the baud rate error must be under -+2% |
---|
| 372 | + */ |
---|
| 373 | + if ((rate_temp < rate) && ((rate - rate_temp) > diff)) { |
---|
| 374 | + ret = clk_set_rate(d->clk, rate + diff); |
---|
| 375 | + rate_temp = clk_get_rate(d->clk); |
---|
| 376 | + if ((rate_temp < rate) && ((rate - rate_temp) > diff)) |
---|
| 377 | + dev_info(p->dev, "set rate:%ld, but get rate:%d\n", |
---|
| 378 | + rate, rate_temp); |
---|
| 379 | + else if ((rate < rate_temp) && ((rate_temp - rate) > diff)) |
---|
| 380 | + dev_info(p->dev, "set rate:%ld, but get rate:%d\n", |
---|
| 381 | + rate, rate_temp); |
---|
| 382 | + } |
---|
| 383 | + if (!ret) |
---|
| 384 | + p->uartclk = rate; |
---|
349 | 385 | } |
---|
350 | 386 | #else |
---|
351 | | - rate = clk_round_rate(d->clk, baud * 16); |
---|
352 | | - if (rate < 0) |
---|
353 | | - ret = rate; |
---|
354 | | - else if (rate == 0) |
---|
355 | | - ret = -ENOENT; |
---|
356 | | - else |
---|
357 | | - ret = clk_set_rate(d->clk, rate); |
---|
| 387 | + rate = clk_round_rate(d->clk, newrate); |
---|
| 388 | + if (rate > 0) { |
---|
| 389 | + /* |
---|
| 390 | + * Premilinary set the uartclk to the new clock rate so the |
---|
| 391 | + * clock update event handler caused by the clk_set_rate() |
---|
| 392 | + * calling wouldn't actually update the UART divisor since |
---|
| 393 | + * we about to do this anyway. |
---|
| 394 | + */ |
---|
| 395 | + swap(p->uartclk, rate); |
---|
| 396 | + ret = clk_set_rate(d->clk, newrate); |
---|
| 397 | + if (ret) |
---|
| 398 | + swap(p->uartclk, rate); |
---|
| 399 | + } |
---|
358 | 400 | #endif |
---|
359 | 401 | clk_prepare_enable(d->clk); |
---|
360 | 402 | |
---|
361 | | - if (!ret) |
---|
362 | | - p->uartclk = rate; |
---|
363 | | - |
---|
364 | | -out: |
---|
365 | 403 | p->status &= ~UPSTAT_AUTOCTS; |
---|
366 | 404 | if (termios->c_cflag & CRTSCTS) |
---|
367 | 405 | p->status |= UPSTAT_AUTOCTS; |
---|
.. | .. |
---|
403 | 441 | return param == chan->device->dev; |
---|
404 | 442 | } |
---|
405 | 443 | |
---|
406 | | -/* |
---|
407 | | - * divisor = div(I) + div(F) |
---|
408 | | - * "I" means integer, "F" means fractional |
---|
409 | | - * quot = div(I) = clk / (16 * baud) |
---|
410 | | - * frac = div(F) * 2^dlf_size |
---|
411 | | - * |
---|
412 | | - * let rem = clk % (16 * baud) |
---|
413 | | - * we have: div(F) * (16 * baud) = rem |
---|
414 | | - * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) |
---|
415 | | - */ |
---|
416 | | -static unsigned int dw8250_get_divisor(struct uart_port *p, |
---|
417 | | - unsigned int baud, |
---|
418 | | - unsigned int *frac) |
---|
419 | | -{ |
---|
420 | | - unsigned int quot, rem, base_baud = baud * 16; |
---|
421 | | - struct dw8250_data *d = p->private_data; |
---|
422 | | - |
---|
423 | | - quot = p->uartclk / base_baud; |
---|
424 | | - rem = p->uartclk % base_baud; |
---|
425 | | - *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); |
---|
426 | | - |
---|
427 | | - return quot; |
---|
428 | | -} |
---|
429 | | - |
---|
430 | | -static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, |
---|
431 | | - unsigned int quot, unsigned int quot_frac) |
---|
432 | | -{ |
---|
433 | | - dw8250_writel_ext(p, DW_UART_DLF, quot_frac); |
---|
434 | | - serial8250_do_set_divisor(p, baud, quot, quot_frac); |
---|
435 | | -} |
---|
436 | | - |
---|
437 | 444 | static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) |
---|
438 | 445 | { |
---|
439 | 446 | if (p->dev->of_node) { |
---|
.. | .. |
---|
444 | 451 | id = of_alias_get_id(np, "serial"); |
---|
445 | 452 | if (id >= 0) |
---|
446 | 453 | p->line = id; |
---|
| 454 | + |
---|
| 455 | + if (IS_ENABLED(CONFIG_ROCKCHIP_MINI_KERNEL)) |
---|
| 456 | + return; |
---|
| 457 | + |
---|
447 | 458 | #ifdef CONFIG_64BIT |
---|
448 | 459 | if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) { |
---|
449 | 460 | p->serial_in = dw8250_serial_inq; |
---|
.. | .. |
---|
469 | 480 | data->uart_16550_compatible = true; |
---|
470 | 481 | } |
---|
471 | 482 | |
---|
| 483 | + if (IS_ENABLED(CONFIG_ROCKCHIP_MINI_KERNEL)) |
---|
| 484 | + return; |
---|
| 485 | + |
---|
472 | 486 | /* Platforms with iDMA 64-bit */ |
---|
473 | 487 | if (platform_get_resource_byname(to_platform_device(p->dev), |
---|
474 | 488 | IORESOURCE_MEM, "lpss_priv")) { |
---|
475 | | - data->dma.rx_param = p->dev->parent; |
---|
476 | | - data->dma.tx_param = p->dev->parent; |
---|
477 | | - data->dma.fn = dw8250_idma_filter; |
---|
| 489 | + data->data.dma.rx_param = p->dev->parent; |
---|
| 490 | + data->data.dma.tx_param = p->dev->parent; |
---|
| 491 | + data->data.dma.fn = dw8250_idma_filter; |
---|
478 | 492 | } |
---|
479 | | -} |
---|
480 | | - |
---|
481 | | -static void dw8250_setup_port(struct uart_port *p) |
---|
482 | | -{ |
---|
483 | | - struct uart_8250_port *up = up_to_u8250p(p); |
---|
484 | | - u32 reg; |
---|
485 | | - |
---|
486 | | - /* |
---|
487 | | - * If the Component Version Register returns zero, we know that |
---|
488 | | - * ADDITIONAL_FEATURES are not enabled. No need to go any further. |
---|
489 | | - */ |
---|
490 | | - reg = dw8250_readl_ext(p, DW_UART_UCV); |
---|
491 | | - if (!reg) |
---|
492 | | - return; |
---|
493 | | - |
---|
494 | | - dev_dbg(p->dev, "Designware UART version %c.%c%c\n", |
---|
495 | | - (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); |
---|
496 | | - |
---|
497 | | - dw8250_writel_ext(p, DW_UART_DLF, ~0U); |
---|
498 | | - reg = dw8250_readl_ext(p, DW_UART_DLF); |
---|
499 | | - dw8250_writel_ext(p, DW_UART_DLF, 0); |
---|
500 | | - |
---|
501 | | - if (reg) { |
---|
502 | | - struct dw8250_data *d = p->private_data; |
---|
503 | | - |
---|
504 | | - d->dlf_size = fls(reg); |
---|
505 | | - p->get_divisor = dw8250_get_divisor; |
---|
506 | | - p->set_divisor = dw8250_set_divisor; |
---|
507 | | - } |
---|
508 | | - |
---|
509 | | - reg = dw8250_readl_ext(p, DW_UART_CPR); |
---|
510 | | - |
---|
511 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
512 | | - /* |
---|
513 | | - * The UART CPR may be 0 of some rockchip soc, |
---|
514 | | - * but it supports fifo and AFC, fifo entry is 32 default. |
---|
515 | | - */ |
---|
516 | | - if (reg == 0) |
---|
517 | | - reg = 0x00023ff2; |
---|
518 | | -#endif |
---|
519 | | - if (!reg) |
---|
520 | | - return; |
---|
521 | | - |
---|
522 | | - /* Select the type based on fifo */ |
---|
523 | | - if (reg & DW_UART_CPR_FIFO_MODE) { |
---|
524 | | - p->type = PORT_16550A; |
---|
525 | | - p->flags |= UPF_FIXED_TYPE; |
---|
526 | | - p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); |
---|
527 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
528 | | - up->tx_loadsz = p->fifosize * 3 / 4; |
---|
529 | | -#endif |
---|
530 | | - up->capabilities = UART_CAP_FIFO; |
---|
531 | | - } |
---|
532 | | - |
---|
533 | | - if (reg & DW_UART_CPR_AFCE_MODE) |
---|
534 | | - up->capabilities |= UART_CAP_AFE; |
---|
535 | | - |
---|
536 | | - if (reg & DW_UART_CPR_SIR_MODE) |
---|
537 | | - up->capabilities |= UART_CAP_IRDA; |
---|
538 | 493 | } |
---|
539 | 494 | |
---|
540 | 495 | static int dw8250_probe(struct platform_device *pdev) |
---|
541 | 496 | { |
---|
542 | | - struct uart_8250_port uart = {}; |
---|
| 497 | + struct uart_8250_port uart = {}, *up = &uart; |
---|
543 | 498 | struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
544 | | - int irq = platform_get_irq(pdev, 0); |
---|
545 | | - struct uart_port *p = &uart.port; |
---|
| 499 | + struct uart_port *p = &up->port; |
---|
546 | 500 | struct device *dev = &pdev->dev; |
---|
547 | 501 | struct dw8250_data *data; |
---|
| 502 | + int irq; |
---|
548 | 503 | int err; |
---|
549 | 504 | u32 val; |
---|
550 | 505 | |
---|
.. | .. |
---|
553 | 508 | return -EINVAL; |
---|
554 | 509 | } |
---|
555 | 510 | |
---|
556 | | - if (irq < 0) { |
---|
557 | | - if (irq != -EPROBE_DEFER) |
---|
558 | | - dev_err(dev, "cannot get irq\n"); |
---|
| 511 | + irq = platform_get_irq(pdev, 0); |
---|
| 512 | + if (irq < 0) |
---|
559 | 513 | return irq; |
---|
560 | | - } |
---|
561 | 514 | |
---|
562 | 515 | spin_lock_init(&p->lock); |
---|
563 | 516 | p->mapbase = regs->start; |
---|
.. | .. |
---|
581 | 534 | if (!data) |
---|
582 | 535 | return -ENOMEM; |
---|
583 | 536 | |
---|
584 | | - data->dma.fn = dw8250_fallback_dma_filter; |
---|
| 537 | + data->data.dma.fn = dw8250_fallback_dma_filter; |
---|
585 | 538 | data->usr_reg = DW_UART_USR; |
---|
| 539 | + p->private_data = &data->data; |
---|
586 | 540 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
587 | 541 | data->irq = irq; |
---|
588 | 542 | #endif |
---|
589 | | - p->private_data = data; |
---|
590 | 543 | |
---|
591 | 544 | data->uart_16550_compatible = device_property_read_bool(dev, |
---|
592 | 545 | "snps,uart-16550-compatible"); |
---|
.. | .. |
---|
637 | 590 | device_property_read_u32(dev, "clock-frequency", &p->uartclk); |
---|
638 | 591 | |
---|
639 | 592 | /* If there is separate baudclk, get the rate from it. */ |
---|
640 | | - data->clk = devm_clk_get(dev, "baudclk"); |
---|
641 | | - if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER) |
---|
642 | | - data->clk = devm_clk_get(dev, NULL); |
---|
643 | | - if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) |
---|
644 | | - return -EPROBE_DEFER; |
---|
645 | | - if (!IS_ERR_OR_NULL(data->clk)) { |
---|
646 | | - err = clk_prepare_enable(data->clk); |
---|
647 | | - if (err) |
---|
648 | | - dev_warn(dev, "could not enable optional baudclk: %d\n", |
---|
649 | | - err); |
---|
650 | | - else |
---|
651 | | - p->uartclk = clk_get_rate(data->clk); |
---|
652 | | - } |
---|
| 593 | + data->clk = devm_clk_get_optional(dev, "baudclk"); |
---|
| 594 | + if (data->clk == NULL) |
---|
| 595 | + data->clk = devm_clk_get_optional(dev, NULL); |
---|
| 596 | + if (IS_ERR(data->clk)) |
---|
| 597 | + return PTR_ERR(data->clk); |
---|
| 598 | + |
---|
| 599 | + INIT_WORK(&data->clk_work, dw8250_clk_work_cb); |
---|
| 600 | + data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; |
---|
| 601 | + |
---|
| 602 | + err = clk_prepare_enable(data->clk); |
---|
| 603 | + if (err) |
---|
| 604 | + dev_warn(dev, "could not enable optional baudclk: %d\n", err); |
---|
| 605 | + |
---|
| 606 | + if (data->clk) |
---|
| 607 | + p->uartclk = clk_get_rate(data->clk); |
---|
653 | 608 | |
---|
654 | 609 | /* If no clock rate is defined, fail. */ |
---|
655 | 610 | if (!p->uartclk) { |
---|
.. | .. |
---|
658 | 613 | goto err_clk; |
---|
659 | 614 | } |
---|
660 | 615 | |
---|
661 | | - data->pclk = devm_clk_get(dev, "apb_pclk"); |
---|
662 | | - if (IS_ERR(data->pclk) && PTR_ERR(data->pclk) == -EPROBE_DEFER) { |
---|
663 | | - err = -EPROBE_DEFER; |
---|
| 616 | + data->pclk = devm_clk_get_optional(dev, "apb_pclk"); |
---|
| 617 | + if (IS_ERR(data->pclk)) { |
---|
| 618 | + err = PTR_ERR(data->pclk); |
---|
664 | 619 | goto err_clk; |
---|
665 | 620 | } |
---|
666 | | - if (!IS_ERR(data->pclk)) { |
---|
667 | | - err = clk_prepare_enable(data->pclk); |
---|
668 | | - if (err) { |
---|
669 | | - dev_err(dev, "could not enable apb_pclk\n"); |
---|
670 | | - goto err_clk; |
---|
671 | | - } |
---|
| 621 | + |
---|
| 622 | + err = clk_prepare_enable(data->pclk); |
---|
| 623 | + if (err) { |
---|
| 624 | + dev_err(dev, "could not enable apb_pclk\n"); |
---|
| 625 | + goto err_clk; |
---|
672 | 626 | } |
---|
673 | 627 | |
---|
674 | 628 | data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); |
---|
.. | .. |
---|
689 | 643 | |
---|
690 | 644 | /* If we have a valid fifosize, try hooking up DMA */ |
---|
691 | 645 | if (p->fifosize) { |
---|
692 | | - data->dma.rxconf.src_maxburst = p->fifosize / 4; |
---|
693 | | - data->dma.txconf.dst_maxburst = p->fifosize / 4; |
---|
694 | | - uart.dma = &data->dma; |
---|
| 646 | + data->data.dma.rxconf.src_maxburst = p->fifosize / 4; |
---|
| 647 | + data->data.dma.txconf.dst_maxburst = p->fifosize / 4; |
---|
| 648 | + up->dma = &data->data.dma; |
---|
695 | 649 | } |
---|
696 | 650 | |
---|
697 | | - data->line = serial8250_register_8250_port(&uart); |
---|
698 | | - if (data->line < 0) { |
---|
699 | | - err = data->line; |
---|
| 651 | + data->data.line = serial8250_register_8250_port(up); |
---|
| 652 | + if (data->data.line < 0) { |
---|
| 653 | + err = data->data.line; |
---|
700 | 654 | goto err_reset; |
---|
701 | 655 | } |
---|
702 | 656 | |
---|
| 657 | + /* |
---|
| 658 | + * Some platforms may provide a reference clock shared between several |
---|
| 659 | + * devices. In this case any clock state change must be known to the |
---|
| 660 | + * UART port at least post factum. |
---|
| 661 | + */ |
---|
| 662 | + if (data->clk) { |
---|
| 663 | + err = clk_notifier_register(data->clk, &data->clk_notifier); |
---|
| 664 | + if (err) |
---|
| 665 | + dev_warn(p->dev, "Failed to set the clock notifier\n"); |
---|
| 666 | + else |
---|
| 667 | + queue_work(system_unbound_wq, &data->clk_work); |
---|
| 668 | + } |
---|
703 | 669 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
704 | 670 | if (data->enable_wakeup) |
---|
705 | 671 | device_init_wakeup(&pdev->dev, true); |
---|
706 | 672 | #endif |
---|
707 | | - |
---|
708 | 673 | platform_set_drvdata(pdev, data); |
---|
709 | 674 | |
---|
710 | 675 | pm_runtime_set_active(dev); |
---|
.. | .. |
---|
716 | 681 | reset_control_assert(data->rst); |
---|
717 | 682 | |
---|
718 | 683 | err_pclk: |
---|
719 | | - if (!IS_ERR(data->pclk)) |
---|
720 | | - clk_disable_unprepare(data->pclk); |
---|
| 684 | + clk_disable_unprepare(data->pclk); |
---|
721 | 685 | |
---|
722 | 686 | err_clk: |
---|
723 | | - if (!IS_ERR(data->clk)) |
---|
724 | | - clk_disable_unprepare(data->clk); |
---|
| 687 | + clk_disable_unprepare(data->clk); |
---|
725 | 688 | |
---|
726 | 689 | return err; |
---|
727 | 690 | } |
---|
.. | .. |
---|
729 | 692 | static int dw8250_remove(struct platform_device *pdev) |
---|
730 | 693 | { |
---|
731 | 694 | struct dw8250_data *data = platform_get_drvdata(pdev); |
---|
| 695 | + struct device *dev = &pdev->dev; |
---|
732 | 696 | |
---|
733 | | - pm_runtime_get_sync(&pdev->dev); |
---|
| 697 | + pm_runtime_get_sync(dev); |
---|
734 | 698 | |
---|
735 | | - serial8250_unregister_port(data->line); |
---|
| 699 | + if (data->clk) { |
---|
| 700 | + clk_notifier_unregister(data->clk, &data->clk_notifier); |
---|
| 701 | + |
---|
| 702 | + flush_work(&data->clk_work); |
---|
| 703 | + } |
---|
| 704 | + |
---|
| 705 | + serial8250_unregister_port(data->data.line); |
---|
736 | 706 | |
---|
737 | 707 | reset_control_assert(data->rst); |
---|
738 | 708 | |
---|
739 | | - if (!IS_ERR(data->pclk)) |
---|
740 | | - clk_disable_unprepare(data->pclk); |
---|
| 709 | + clk_disable_unprepare(data->pclk); |
---|
741 | 710 | |
---|
742 | | - if (!IS_ERR(data->clk)) |
---|
743 | | - clk_disable_unprepare(data->clk); |
---|
| 711 | + clk_disable_unprepare(data->clk); |
---|
744 | 712 | |
---|
| 713 | + pm_runtime_disable(dev); |
---|
| 714 | + pm_runtime_put_noidle(dev); |
---|
745 | 715 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
746 | 716 | if (data->enable_wakeup) |
---|
747 | 717 | device_init_wakeup(&pdev->dev, false); |
---|
748 | 718 | #endif |
---|
749 | | - |
---|
750 | | - pm_runtime_disable(&pdev->dev); |
---|
751 | | - pm_runtime_put_noidle(&pdev->dev); |
---|
752 | 719 | |
---|
753 | 720 | return 0; |
---|
754 | 721 | } |
---|
.. | .. |
---|
765 | 732 | return 0; |
---|
766 | 733 | } |
---|
767 | 734 | #endif |
---|
768 | | - serial8250_suspend_port(data->line); |
---|
| 735 | + serial8250_suspend_port(data->data.line); |
---|
769 | 736 | |
---|
770 | 737 | return 0; |
---|
771 | 738 | } |
---|
.. | .. |
---|
783 | 750 | return 0; |
---|
784 | 751 | } |
---|
785 | 752 | #endif |
---|
786 | | - serial8250_resume_port(data->line); |
---|
| 753 | + serial8250_resume_port(data->data.line); |
---|
787 | 754 | |
---|
788 | 755 | return 0; |
---|
789 | 756 | } |
---|
.. | .. |
---|
794 | 761 | { |
---|
795 | 762 | struct dw8250_data *data = dev_get_drvdata(dev); |
---|
796 | 763 | |
---|
797 | | - if (!IS_ERR(data->clk)) |
---|
798 | | - clk_disable_unprepare(data->clk); |
---|
| 764 | + clk_disable_unprepare(data->clk); |
---|
799 | 765 | |
---|
800 | | - if (!IS_ERR(data->pclk)) |
---|
801 | | - clk_disable_unprepare(data->pclk); |
---|
| 766 | + clk_disable_unprepare(data->pclk); |
---|
802 | 767 | |
---|
803 | 768 | return 0; |
---|
804 | 769 | } |
---|
.. | .. |
---|
807 | 772 | { |
---|
808 | 773 | struct dw8250_data *data = dev_get_drvdata(dev); |
---|
809 | 774 | |
---|
810 | | - if (!IS_ERR(data->pclk)) |
---|
811 | | - clk_prepare_enable(data->pclk); |
---|
| 775 | + clk_prepare_enable(data->pclk); |
---|
812 | 776 | |
---|
813 | | - if (!IS_ERR(data->clk)) |
---|
814 | | - clk_prepare_enable(data->clk); |
---|
| 777 | + clk_prepare_enable(data->clk); |
---|
815 | 778 | |
---|
816 | 779 | return 0; |
---|
817 | 780 | } |
---|
.. | .. |
---|
824 | 787 | |
---|
825 | 788 | static const struct of_device_id dw8250_of_match[] = { |
---|
826 | 789 | { .compatible = "snps,dw-apb-uart" }, |
---|
| 790 | +#ifndef CONFIG_ROCKCHIP_MINI_KERNEL |
---|
827 | 791 | { .compatible = "cavium,octeon-3860-uart" }, |
---|
828 | 792 | { .compatible = "marvell,armada-38x-uart" }, |
---|
829 | 793 | { .compatible = "renesas,rzn1-uart" }, |
---|
| 794 | +#endif |
---|
830 | 795 | { /* Sentinel */ } |
---|
831 | 796 | }; |
---|
832 | 797 | MODULE_DEVICE_TABLE(of, dw8250_of_match); |
---|
.. | .. |
---|
841 | 806 | { "APMC0D08", 0}, |
---|
842 | 807 | { "AMD0020", 0 }, |
---|
843 | 808 | { "AMDI0020", 0 }, |
---|
| 809 | + { "AMDI0022", 0 }, |
---|
844 | 810 | { "BRCM2032", 0 }, |
---|
845 | 811 | { "HISI0031", 0 }, |
---|
846 | 812 | { }, |
---|