.. | .. |
---|
5 | 5 | #include <linux/console.h> |
---|
6 | 6 | #include <linux/io.h> |
---|
7 | 7 | #include <linux/iopoll.h> |
---|
| 8 | +#include <linux/irq.h> |
---|
8 | 9 | #include <linux/module.h> |
---|
9 | 10 | #include <linux/of.h> |
---|
10 | 11 | #include <linux/of_device.h> |
---|
| 12 | +#include <linux/pm_opp.h> |
---|
11 | 13 | #include <linux/platform_device.h> |
---|
| 14 | +#include <linux/pm_runtime.h> |
---|
| 15 | +#include <linux/pm_wakeirq.h> |
---|
12 | 16 | #include <linux/qcom-geni-se.h> |
---|
13 | 17 | #include <linux/serial.h> |
---|
14 | 18 | #include <linux/serial_core.h> |
---|
.. | .. |
---|
18 | 22 | |
---|
19 | 23 | /* UART specific GENI registers */ |
---|
20 | 24 | #define SE_UART_LOOPBACK_CFG 0x22c |
---|
| 25 | +#define SE_UART_IO_MACRO_CTRL 0x240 |
---|
21 | 26 | #define SE_UART_TX_TRANS_CFG 0x25c |
---|
22 | 27 | #define SE_UART_TX_WORD_LEN 0x268 |
---|
23 | 28 | #define SE_UART_TX_STOP_BIT_LEN 0x26c |
---|
.. | .. |
---|
86 | 91 | #define DEF_TX_WM 2 |
---|
87 | 92 | #define DEF_FIFO_WIDTH_BITS 32 |
---|
88 | 93 | #define UART_RX_WM 2 |
---|
89 | | -#define MAX_LOOPBACK_CFG 3 |
---|
90 | 94 | |
---|
91 | | -#ifdef CONFIG_CONSOLE_POLL |
---|
92 | | -#define RX_BYTES_PW 1 |
---|
93 | | -#else |
---|
94 | | -#define RX_BYTES_PW 4 |
---|
95 | | -#endif |
---|
| 95 | +/* SE_UART_LOOPBACK_CFG */ |
---|
| 96 | +#define RX_TX_SORTED BIT(0) |
---|
| 97 | +#define CTS_RTS_SORTED BIT(1) |
---|
| 98 | +#define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED) |
---|
| 99 | + |
---|
| 100 | +/* UART pin swap value */ |
---|
| 101 | +#define DEFAULT_IO_MACRO_IO0_IO1_MASK GENMASK(3, 0) |
---|
| 102 | +#define IO_MACRO_IO0_SEL 0x3 |
---|
| 103 | +#define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4) |
---|
| 104 | +#define IO_MACRO_IO2_IO3_SWAP 0x4640 |
---|
| 105 | + |
---|
| 106 | +/* We always configure 4 bytes per FIFO word */ |
---|
| 107 | +#define BYTES_PER_FIFO_WORD 4 |
---|
| 108 | + |
---|
| 109 | +struct qcom_geni_private_data { |
---|
| 110 | + /* NOTE: earlycon port will have NULL here */ |
---|
| 111 | + struct uart_driver *drv; |
---|
| 112 | + |
---|
| 113 | + u32 poll_cached_bytes; |
---|
| 114 | + unsigned int poll_cached_bytes_cnt; |
---|
| 115 | + |
---|
| 116 | + u32 write_cached_bytes; |
---|
| 117 | + unsigned int write_cached_bytes_cnt; |
---|
| 118 | +}; |
---|
96 | 119 | |
---|
97 | 120 | struct qcom_geni_serial_port { |
---|
98 | 121 | struct uart_port uport; |
---|
99 | 122 | struct geni_se se; |
---|
100 | | - char name[20]; |
---|
| 123 | + const char *name; |
---|
101 | 124 | u32 tx_fifo_depth; |
---|
102 | 125 | u32 tx_fifo_width; |
---|
103 | 126 | u32 rx_fifo_depth; |
---|
104 | 127 | bool setup; |
---|
| 128 | + unsigned long clk_rate; |
---|
105 | 129 | int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop); |
---|
106 | 130 | unsigned int baud; |
---|
107 | | - unsigned int tx_bytes_pw; |
---|
108 | | - unsigned int rx_bytes_pw; |
---|
109 | | - u32 *rx_fifo; |
---|
| 131 | + void *rx_fifo; |
---|
110 | 132 | u32 loopback; |
---|
111 | 133 | bool brk; |
---|
112 | 134 | |
---|
113 | 135 | unsigned int tx_remaining; |
---|
| 136 | + int wakeup_irq; |
---|
| 137 | + bool rx_tx_swap; |
---|
| 138 | + bool cts_rts_swap; |
---|
| 139 | + |
---|
| 140 | + struct qcom_geni_private_data private_data; |
---|
114 | 141 | }; |
---|
115 | 142 | |
---|
116 | 143 | static const struct uart_ops qcom_geni_console_pops; |
---|
.. | .. |
---|
124 | 151 | static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop); |
---|
125 | 152 | |
---|
126 | 153 | static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, |
---|
127 | | - 32000000, 48000000, 64000000, 80000000, |
---|
128 | | - 96000000, 100000000, 102400000, |
---|
129 | | - 112000000, 120000000, 128000000}; |
---|
| 154 | + 32000000, 48000000, 51200000, 64000000, |
---|
| 155 | + 80000000, 96000000, 100000000, |
---|
| 156 | + 102400000, 112000000, 120000000, |
---|
| 157 | + 128000000}; |
---|
130 | 158 | |
---|
131 | 159 | #define to_dev_port(ptr, member) \ |
---|
132 | 160 | container_of(ptr, struct qcom_geni_serial_port, member) |
---|
.. | .. |
---|
158 | 186 | }, |
---|
159 | 187 | }; |
---|
160 | 188 | |
---|
161 | | -static ssize_t loopback_show(struct device *dev, |
---|
162 | | - struct device_attribute *attr, char *buf) |
---|
163 | | -{ |
---|
164 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
165 | | - struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); |
---|
166 | | - |
---|
167 | | - return snprintf(buf, sizeof(u32), "%d\n", port->loopback); |
---|
168 | | -} |
---|
169 | | - |
---|
170 | | -static ssize_t loopback_store(struct device *dev, |
---|
171 | | - struct device_attribute *attr, const char *buf, |
---|
172 | | - size_t size) |
---|
173 | | -{ |
---|
174 | | - struct platform_device *pdev = to_platform_device(dev); |
---|
175 | | - struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); |
---|
176 | | - u32 loopback; |
---|
177 | | - |
---|
178 | | - if (kstrtoint(buf, 0, &loopback) || loopback > MAX_LOOPBACK_CFG) { |
---|
179 | | - dev_err(dev, "Invalid input\n"); |
---|
180 | | - return -EINVAL; |
---|
181 | | - } |
---|
182 | | - port->loopback = loopback; |
---|
183 | | - return size; |
---|
184 | | -} |
---|
185 | | -static DEVICE_ATTR_RW(loopback); |
---|
186 | | - |
---|
187 | 189 | static struct qcom_geni_serial_port qcom_geni_console_port = { |
---|
188 | 190 | .uport = { |
---|
189 | 191 | .iotype = UPIO_MEM, |
---|
.. | .. |
---|
197 | 199 | { |
---|
198 | 200 | struct platform_device *pdev = to_platform_device(uport->dev); |
---|
199 | 201 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
200 | | - struct resource *res; |
---|
201 | 202 | |
---|
202 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
203 | | - uport->membase = devm_ioremap_resource(&pdev->dev, res); |
---|
| 203 | + uport->membase = devm_platform_ioremap_resource(pdev, 0); |
---|
204 | 204 | if (IS_ERR(uport->membase)) |
---|
205 | 205 | return PTR_ERR(uport->membase); |
---|
206 | 206 | port->se.base = uport->membase; |
---|
.. | .. |
---|
235 | 235 | unsigned int mctrl) |
---|
236 | 236 | { |
---|
237 | 237 | u32 uart_manual_rfr = 0; |
---|
| 238 | + struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
238 | 239 | |
---|
239 | 240 | if (uart_console(uport)) |
---|
240 | 241 | return; |
---|
241 | 242 | |
---|
242 | | - if (!(mctrl & TIOCM_RTS)) |
---|
| 243 | + if (mctrl & TIOCM_LOOP) |
---|
| 244 | + port->loopback = RX_TX_CTS_RTS_SORTED; |
---|
| 245 | + |
---|
| 246 | + if (!(mctrl & TIOCM_RTS) && !uport->suspended) |
---|
243 | 247 | uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY; |
---|
244 | 248 | writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); |
---|
245 | 249 | } |
---|
.. | .. |
---|
269 | 273 | unsigned int baud; |
---|
270 | 274 | unsigned int fifo_bits; |
---|
271 | 275 | unsigned long timeout_us = 20000; |
---|
| 276 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
272 | 277 | |
---|
273 | | - if (uport->private_data) { |
---|
| 278 | + if (private_data->drv) { |
---|
274 | 279 | port = to_dev_port(uport, uport); |
---|
275 | 280 | baud = port->baud; |
---|
276 | 281 | if (!baud) |
---|
.. | .. |
---|
336 | 341 | } |
---|
337 | 342 | |
---|
338 | 343 | #ifdef CONFIG_CONSOLE_POLL |
---|
| 344 | + |
---|
339 | 345 | static int qcom_geni_serial_get_char(struct uart_port *uport) |
---|
340 | 346 | { |
---|
341 | | - u32 rx_fifo; |
---|
| 347 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
342 | 348 | u32 status; |
---|
| 349 | + u32 word_cnt; |
---|
| 350 | + int ret; |
---|
343 | 351 | |
---|
344 | | - status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); |
---|
345 | | - writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); |
---|
| 352 | + if (!private_data->poll_cached_bytes_cnt) { |
---|
| 353 | + status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); |
---|
| 354 | + writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); |
---|
346 | 355 | |
---|
347 | | - status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); |
---|
348 | | - writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); |
---|
| 356 | + status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); |
---|
| 357 | + writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); |
---|
349 | 358 | |
---|
350 | | - status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); |
---|
351 | | - if (!(status & RX_FIFO_WC_MSK)) |
---|
352 | | - return NO_POLL_CHAR; |
---|
| 359 | + status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); |
---|
| 360 | + word_cnt = status & RX_FIFO_WC_MSK; |
---|
| 361 | + if (!word_cnt) |
---|
| 362 | + return NO_POLL_CHAR; |
---|
353 | 363 | |
---|
354 | | - rx_fifo = readl(uport->membase + SE_GENI_RX_FIFOn); |
---|
355 | | - return rx_fifo & 0xff; |
---|
| 364 | + if (word_cnt == 1 && (status & RX_LAST)) |
---|
| 365 | + /* |
---|
| 366 | + * NOTE: If RX_LAST_BYTE_VALID is 0 it needs to be |
---|
| 367 | + * treated as if it was BYTES_PER_FIFO_WORD. |
---|
| 368 | + */ |
---|
| 369 | + private_data->poll_cached_bytes_cnt = |
---|
| 370 | + (status & RX_LAST_BYTE_VALID_MSK) >> |
---|
| 371 | + RX_LAST_BYTE_VALID_SHFT; |
---|
| 372 | + |
---|
| 373 | + if (private_data->poll_cached_bytes_cnt == 0) |
---|
| 374 | + private_data->poll_cached_bytes_cnt = BYTES_PER_FIFO_WORD; |
---|
| 375 | + |
---|
| 376 | + private_data->poll_cached_bytes = |
---|
| 377 | + readl(uport->membase + SE_GENI_RX_FIFOn); |
---|
| 378 | + } |
---|
| 379 | + |
---|
| 380 | + private_data->poll_cached_bytes_cnt--; |
---|
| 381 | + ret = private_data->poll_cached_bytes & 0xff; |
---|
| 382 | + private_data->poll_cached_bytes >>= 8; |
---|
| 383 | + |
---|
| 384 | + return ret; |
---|
356 | 385 | } |
---|
357 | 386 | |
---|
358 | 387 | static void qcom_geni_serial_poll_put_char(struct uart_port *uport, |
---|
.. | .. |
---|
371 | 400 | #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE |
---|
372 | 401 | static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch) |
---|
373 | 402 | { |
---|
374 | | - writel(ch, uport->membase + SE_GENI_TX_FIFOn); |
---|
| 403 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
| 404 | + |
---|
| 405 | + private_data->write_cached_bytes = |
---|
| 406 | + (private_data->write_cached_bytes >> 8) | (ch << 24); |
---|
| 407 | + private_data->write_cached_bytes_cnt++; |
---|
| 408 | + |
---|
| 409 | + if (private_data->write_cached_bytes_cnt == BYTES_PER_FIFO_WORD) { |
---|
| 410 | + writel(private_data->write_cached_bytes, |
---|
| 411 | + uport->membase + SE_GENI_TX_FIFOn); |
---|
| 412 | + private_data->write_cached_bytes_cnt = 0; |
---|
| 413 | + } |
---|
375 | 414 | } |
---|
376 | 415 | |
---|
377 | 416 | static void |
---|
378 | 417 | __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, |
---|
379 | 418 | unsigned int count) |
---|
380 | 419 | { |
---|
| 420 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
| 421 | + |
---|
381 | 422 | int i; |
---|
382 | 423 | u32 bytes_to_send = count; |
---|
383 | 424 | |
---|
.. | .. |
---|
412 | 453 | SE_GENI_M_IRQ_CLEAR); |
---|
413 | 454 | i += chars_to_write; |
---|
414 | 455 | } |
---|
| 456 | + |
---|
| 457 | + if (private_data->write_cached_bytes_cnt) { |
---|
| 458 | + private_data->write_cached_bytes >>= BITS_PER_BYTE * |
---|
| 459 | + (BYTES_PER_FIFO_WORD - private_data->write_cached_bytes_cnt); |
---|
| 460 | + writel(private_data->write_cached_bytes, |
---|
| 461 | + uport->membase + SE_GENI_TX_FIFOn); |
---|
| 462 | + private_data->write_cached_bytes_cnt = 0; |
---|
| 463 | + } |
---|
| 464 | + |
---|
415 | 465 | qcom_geni_serial_poll_tx_done(uport); |
---|
416 | 466 | } |
---|
417 | 467 | |
---|
.. | .. |
---|
484 | 534 | tport = &uport->state->port; |
---|
485 | 535 | for (i = 0; i < bytes; ) { |
---|
486 | 536 | int c; |
---|
487 | | - int chunk = min_t(int, bytes - i, port->rx_bytes_pw); |
---|
| 537 | + int chunk = min_t(int, bytes - i, BYTES_PER_FIFO_WORD); |
---|
488 | 538 | |
---|
489 | 539 | ioread32_rep(uport->membase + SE_GENI_RX_FIFOn, buf, 1); |
---|
490 | 540 | i += chunk; |
---|
.. | .. |
---|
501 | 551 | continue; |
---|
502 | 552 | } |
---|
503 | 553 | |
---|
504 | | - sysrq = uart_handle_sysrq_char(uport, buf[c]); |
---|
| 554 | + sysrq = uart_prepare_sysrq_char(uport, buf[c]); |
---|
| 555 | + |
---|
505 | 556 | if (!sysrq) |
---|
506 | 557 | tty_insert_flip_char(tport, buf[c], TTY_NORMAL); |
---|
507 | 558 | } |
---|
.. | .. |
---|
520 | 571 | |
---|
521 | 572 | static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop) |
---|
522 | 573 | { |
---|
523 | | - unsigned char *buf; |
---|
524 | 574 | struct tty_port *tport; |
---|
525 | 575 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
526 | 576 | u32 num_bytes_pw = port->tx_fifo_width / BITS_PER_BYTE; |
---|
.. | .. |
---|
532 | 582 | if (drop) |
---|
533 | 583 | return 0; |
---|
534 | 584 | |
---|
535 | | - buf = (unsigned char *)port->rx_fifo; |
---|
536 | | - ret = tty_insert_flip_string(tport, buf, bytes); |
---|
| 585 | + ret = tty_insert_flip_string(tport, port->rx_fifo, bytes); |
---|
537 | 586 | if (ret != bytes) { |
---|
538 | 587 | dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n", |
---|
539 | 588 | __func__, ret, bytes); |
---|
.. | .. |
---|
665 | 714 | |
---|
666 | 715 | if (!word_cnt) |
---|
667 | 716 | return; |
---|
668 | | - total_bytes = port->rx_bytes_pw * (word_cnt - 1); |
---|
| 717 | + total_bytes = BYTES_PER_FIFO_WORD * (word_cnt - 1); |
---|
669 | 718 | if (last_word_partial && last_word_byte_cnt) |
---|
670 | 719 | total_bytes += last_word_byte_cnt; |
---|
671 | 720 | else |
---|
672 | | - total_bytes += port->rx_bytes_pw; |
---|
| 721 | + total_bytes += BYTES_PER_FIFO_WORD; |
---|
673 | 722 | port->handle_rx(uport, total_bytes, drop); |
---|
674 | 723 | } |
---|
675 | 724 | |
---|
.. | .. |
---|
702 | 751 | } |
---|
703 | 752 | |
---|
704 | 753 | avail = port->tx_fifo_depth - (status & TX_FIFO_WC); |
---|
705 | | - avail *= port->tx_bytes_pw; |
---|
| 754 | + avail *= BYTES_PER_FIFO_WORD; |
---|
706 | 755 | |
---|
707 | 756 | tail = xmit->tail; |
---|
708 | 757 | chunk = min(avail, pending); |
---|
.. | .. |
---|
725 | 774 | u8 buf[sizeof(u32)]; |
---|
726 | 775 | int c; |
---|
727 | 776 | |
---|
728 | | - memset(buf, 0, ARRAY_SIZE(buf)); |
---|
729 | | - tx_bytes = min_t(size_t, remaining, port->tx_bytes_pw); |
---|
| 777 | + memset(buf, 0, sizeof(buf)); |
---|
| 778 | + tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD); |
---|
730 | 779 | |
---|
731 | 780 | for (c = 0; c < tx_bytes ; c++) { |
---|
732 | 781 | buf[c] = xmit->buf[tail++]; |
---|
.. | .. |
---|
765 | 814 | |
---|
766 | 815 | static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) |
---|
767 | 816 | { |
---|
768 | | - unsigned int m_irq_status; |
---|
769 | | - unsigned int s_irq_status; |
---|
770 | | - unsigned int geni_status; |
---|
| 817 | + u32 m_irq_en; |
---|
| 818 | + u32 m_irq_status; |
---|
| 819 | + u32 s_irq_status; |
---|
| 820 | + u32 geni_status; |
---|
771 | 821 | struct uart_port *uport = dev; |
---|
772 | 822 | unsigned long flags; |
---|
773 | | - unsigned int m_irq_en; |
---|
774 | 823 | bool drop_rx = false; |
---|
775 | 824 | struct tty_port *tport = &uport->state->port; |
---|
776 | 825 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
.. | .. |
---|
813 | 862 | qcom_geni_serial_handle_rx(uport, drop_rx); |
---|
814 | 863 | |
---|
815 | 864 | out_unlock: |
---|
816 | | - spin_unlock_irqrestore(&uport->lock, flags); |
---|
| 865 | + uart_unlock_and_check_sysrq(uport, flags); |
---|
| 866 | + |
---|
817 | 867 | return IRQ_HANDLED; |
---|
818 | 868 | } |
---|
819 | 869 | |
---|
820 | | -static void get_tx_fifo_size(struct qcom_geni_serial_port *port) |
---|
| 870 | +static int setup_fifos(struct qcom_geni_serial_port *port) |
---|
821 | 871 | { |
---|
822 | 872 | struct uart_port *uport; |
---|
| 873 | + u32 old_rx_fifo_depth = port->rx_fifo_depth; |
---|
823 | 874 | |
---|
824 | 875 | uport = &port->uport; |
---|
825 | 876 | port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se); |
---|
.. | .. |
---|
827 | 878 | port->rx_fifo_depth = geni_se_get_rx_fifo_depth(&port->se); |
---|
828 | 879 | uport->fifosize = |
---|
829 | 880 | (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE; |
---|
| 881 | + |
---|
| 882 | + if (port->rx_fifo && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) { |
---|
| 883 | + port->rx_fifo = devm_krealloc(uport->dev, port->rx_fifo, |
---|
| 884 | + port->rx_fifo_depth * sizeof(u32), |
---|
| 885 | + GFP_KERNEL); |
---|
| 886 | + if (!port->rx_fifo) |
---|
| 887 | + return -ENOMEM; |
---|
| 888 | + } |
---|
| 889 | + |
---|
| 890 | + return 0; |
---|
830 | 891 | } |
---|
831 | 892 | |
---|
832 | 893 | |
---|
833 | 894 | static void qcom_geni_serial_shutdown(struct uart_port *uport) |
---|
834 | 895 | { |
---|
835 | | - unsigned long flags; |
---|
836 | | - |
---|
837 | | - /* Stop the console before stopping the current tx */ |
---|
838 | | - if (uart_console(uport)) |
---|
839 | | - console_stop(uport->cons); |
---|
840 | | - |
---|
841 | | - free_irq(uport->irq, uport); |
---|
842 | | - spin_lock_irqsave(&uport->lock, flags); |
---|
843 | | - qcom_geni_serial_stop_tx(uport); |
---|
844 | | - qcom_geni_serial_stop_rx(uport); |
---|
845 | | - spin_unlock_irqrestore(&uport->lock, flags); |
---|
| 896 | + disable_irq(uport->irq); |
---|
846 | 897 | } |
---|
847 | 898 | |
---|
848 | 899 | static int qcom_geni_serial_port_setup(struct uart_port *uport) |
---|
849 | 900 | { |
---|
850 | 901 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
851 | | - unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; |
---|
| 902 | + u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; |
---|
852 | 903 | u32 proto; |
---|
853 | | - |
---|
854 | | - if (uart_console(uport)) |
---|
855 | | - port->tx_bytes_pw = 1; |
---|
856 | | - else |
---|
857 | | - port->tx_bytes_pw = 4; |
---|
858 | | - port->rx_bytes_pw = RX_BYTES_PW; |
---|
| 904 | + u32 pin_swap; |
---|
| 905 | + int ret; |
---|
859 | 906 | |
---|
860 | 907 | proto = geni_se_read_proto(&port->se); |
---|
861 | 908 | if (proto != GENI_SE_UART) { |
---|
.. | .. |
---|
865 | 912 | |
---|
866 | 913 | qcom_geni_serial_stop_rx(uport); |
---|
867 | 914 | |
---|
868 | | - get_tx_fifo_size(port); |
---|
| 915 | + ret = setup_fifos(port); |
---|
| 916 | + if (ret) |
---|
| 917 | + return ret; |
---|
869 | 918 | |
---|
870 | 919 | writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); |
---|
| 920 | + |
---|
| 921 | + pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL); |
---|
| 922 | + if (port->rx_tx_swap) { |
---|
| 923 | + pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK; |
---|
| 924 | + pin_swap |= IO_MACRO_IO2_IO3_SWAP; |
---|
| 925 | + } |
---|
| 926 | + if (port->cts_rts_swap) { |
---|
| 927 | + pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK; |
---|
| 928 | + pin_swap |= IO_MACRO_IO0_SEL; |
---|
| 929 | + } |
---|
| 930 | + /* Configure this register if RX-TX, CTS-RTS pins are swapped */ |
---|
| 931 | + if (port->rx_tx_swap || port->cts_rts_swap) |
---|
| 932 | + writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL); |
---|
| 933 | + |
---|
871 | 934 | /* |
---|
872 | 935 | * Make an unconditional cancel on the main sequencer to reset |
---|
873 | 936 | * it else we could end up in data loss scenarios. |
---|
874 | 937 | */ |
---|
875 | 938 | if (uart_console(uport)) |
---|
876 | 939 | qcom_geni_serial_poll_tx_done(uport); |
---|
877 | | - geni_se_config_packing(&port->se, BITS_PER_BYTE, port->tx_bytes_pw, |
---|
878 | | - false, true, false); |
---|
879 | | - geni_se_config_packing(&port->se, BITS_PER_BYTE, port->rx_bytes_pw, |
---|
880 | | - false, false, true); |
---|
| 940 | + geni_se_config_packing(&port->se, BITS_PER_BYTE, BYTES_PER_FIFO_WORD, |
---|
| 941 | + false, true, true); |
---|
881 | 942 | geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2); |
---|
882 | 943 | geni_se_select_mode(&port->se, GENI_SE_FIFO); |
---|
883 | | - if (!uart_console(uport)) { |
---|
884 | | - port->rx_fifo = devm_kcalloc(uport->dev, |
---|
885 | | - port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); |
---|
886 | | - if (!port->rx_fifo) |
---|
887 | | - return -ENOMEM; |
---|
888 | | - } |
---|
889 | 944 | port->setup = true; |
---|
890 | 945 | |
---|
891 | 946 | return 0; |
---|
.. | .. |
---|
896 | 951 | int ret; |
---|
897 | 952 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
898 | 953 | |
---|
899 | | - scnprintf(port->name, sizeof(port->name), |
---|
900 | | - "qcom_serial_%s%d", |
---|
901 | | - (uart_console(uport) ? "console" : "uart"), uport->line); |
---|
902 | | - |
---|
903 | 954 | if (!port->setup) { |
---|
904 | 955 | ret = qcom_geni_serial_port_setup(uport); |
---|
905 | 956 | if (ret) |
---|
906 | 957 | return ret; |
---|
907 | 958 | } |
---|
| 959 | + enable_irq(uport->irq); |
---|
908 | 960 | |
---|
909 | | - ret = request_irq(uport->irq, qcom_geni_serial_isr, IRQF_TRIGGER_HIGH, |
---|
910 | | - port->name, uport); |
---|
911 | | - if (ret) |
---|
912 | | - dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret); |
---|
913 | | - return ret; |
---|
| 961 | + return 0; |
---|
914 | 962 | } |
---|
915 | 963 | |
---|
916 | 964 | static unsigned long get_clk_cfg(unsigned long clk_freq) |
---|
.. | .. |
---|
924 | 972 | return 0; |
---|
925 | 973 | } |
---|
926 | 974 | |
---|
927 | | -static unsigned long get_clk_div_rate(unsigned int baud, unsigned int *clk_div) |
---|
| 975 | +static unsigned long get_clk_div_rate(unsigned int baud, |
---|
| 976 | + unsigned int sampling_rate, unsigned int *clk_div) |
---|
928 | 977 | { |
---|
929 | 978 | unsigned long ser_clk; |
---|
930 | 979 | unsigned long desired_clk; |
---|
931 | 980 | |
---|
932 | | - desired_clk = baud * UART_OVERSAMPLING; |
---|
| 981 | + desired_clk = baud * sampling_rate; |
---|
933 | 982 | ser_clk = get_clk_cfg(desired_clk); |
---|
934 | 983 | if (!ser_clk) { |
---|
935 | 984 | pr_err("%s: Can't find matching DFS entry for baud %d\n", |
---|
.. | .. |
---|
945 | 994 | struct ktermios *termios, struct ktermios *old) |
---|
946 | 995 | { |
---|
947 | 996 | unsigned int baud; |
---|
948 | | - unsigned int bits_per_char; |
---|
949 | | - unsigned int tx_trans_cfg; |
---|
950 | | - unsigned int tx_parity_cfg; |
---|
951 | | - unsigned int rx_trans_cfg; |
---|
952 | | - unsigned int rx_parity_cfg; |
---|
953 | | - unsigned int stop_bit_len; |
---|
| 997 | + u32 bits_per_char; |
---|
| 998 | + u32 tx_trans_cfg; |
---|
| 999 | + u32 tx_parity_cfg; |
---|
| 1000 | + u32 rx_trans_cfg; |
---|
| 1001 | + u32 rx_parity_cfg; |
---|
| 1002 | + u32 stop_bit_len; |
---|
954 | 1003 | unsigned int clk_div; |
---|
955 | | - unsigned long ser_clk_cfg; |
---|
| 1004 | + u32 ser_clk_cfg; |
---|
956 | 1005 | struct qcom_geni_serial_port *port = to_dev_port(uport, uport); |
---|
957 | 1006 | unsigned long clk_rate; |
---|
| 1007 | + u32 ver, sampling_rate; |
---|
| 1008 | + unsigned int avg_bw_core; |
---|
958 | 1009 | |
---|
959 | 1010 | qcom_geni_serial_stop_rx(uport); |
---|
960 | 1011 | /* baud rate */ |
---|
961 | 1012 | baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); |
---|
962 | 1013 | port->baud = baud; |
---|
963 | | - clk_rate = get_clk_div_rate(baud, &clk_div); |
---|
| 1014 | + |
---|
| 1015 | + sampling_rate = UART_OVERSAMPLING; |
---|
| 1016 | + /* Sampling rate is halved for IP versions >= 2.5 */ |
---|
| 1017 | + ver = geni_se_get_qup_hw_version(&port->se); |
---|
| 1018 | + if (ver >= QUP_SE_VERSION_2_5) |
---|
| 1019 | + sampling_rate /= 2; |
---|
| 1020 | + |
---|
| 1021 | + clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div); |
---|
964 | 1022 | if (!clk_rate) |
---|
965 | 1023 | goto out_restart_rx; |
---|
966 | 1024 | |
---|
967 | 1025 | uport->uartclk = clk_rate; |
---|
968 | | - clk_set_rate(port->se.clk, clk_rate); |
---|
| 1026 | + port->clk_rate = clk_rate; |
---|
| 1027 | + dev_pm_opp_set_rate(uport->dev, clk_rate); |
---|
969 | 1028 | ser_clk_cfg = SER_CLK_EN; |
---|
970 | 1029 | ser_clk_cfg |= clk_div << CLK_DIV_SHFT; |
---|
| 1030 | + |
---|
| 1031 | + /* |
---|
| 1032 | + * Bump up BW vote on CPU and CORE path as driver supports FIFO mode |
---|
| 1033 | + * only. |
---|
| 1034 | + */ |
---|
| 1035 | + avg_bw_core = (baud > 115200) ? Bps_to_icc(CORE_2X_50_MHZ) |
---|
| 1036 | + : GENI_DEFAULT_BW; |
---|
| 1037 | + port->se.icc_paths[GENI_TO_CORE].avg_bw = avg_bw_core; |
---|
| 1038 | + port->se.icc_paths[CPU_TO_GENI].avg_bw = Bps_to_icc(baud); |
---|
| 1039 | + geni_icc_set_bw(&port->se); |
---|
971 | 1040 | |
---|
972 | 1041 | /* parity */ |
---|
973 | 1042 | tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG); |
---|
.. | .. |
---|
1054 | 1123 | { |
---|
1055 | 1124 | struct uart_port *uport; |
---|
1056 | 1125 | struct qcom_geni_serial_port *port; |
---|
1057 | | - int baud = 9600; |
---|
| 1126 | + int baud = 115200; |
---|
1058 | 1127 | int bits = 8; |
---|
1059 | 1128 | int parity = 'n'; |
---|
1060 | 1129 | int flow = 'n'; |
---|
.. | .. |
---|
1094 | 1163 | __qcom_geni_serial_console_write(&dev->port, s, n); |
---|
1095 | 1164 | } |
---|
1096 | 1165 | |
---|
| 1166 | +#ifdef CONFIG_CONSOLE_POLL |
---|
| 1167 | +static int qcom_geni_serial_earlycon_read(struct console *con, |
---|
| 1168 | + char *s, unsigned int n) |
---|
| 1169 | +{ |
---|
| 1170 | + struct earlycon_device *dev = con->data; |
---|
| 1171 | + struct uart_port *uport = &dev->port; |
---|
| 1172 | + int num_read = 0; |
---|
| 1173 | + int ch; |
---|
| 1174 | + |
---|
| 1175 | + while (num_read < n) { |
---|
| 1176 | + ch = qcom_geni_serial_get_char(uport); |
---|
| 1177 | + if (ch == NO_POLL_CHAR) |
---|
| 1178 | + break; |
---|
| 1179 | + s[num_read++] = ch; |
---|
| 1180 | + } |
---|
| 1181 | + |
---|
| 1182 | + return num_read; |
---|
| 1183 | +} |
---|
| 1184 | + |
---|
| 1185 | +static void __init qcom_geni_serial_enable_early_read(struct geni_se *se, |
---|
| 1186 | + struct console *con) |
---|
| 1187 | +{ |
---|
| 1188 | + geni_se_setup_s_cmd(se, UART_START_READ, 0); |
---|
| 1189 | + con->read = qcom_geni_serial_earlycon_read; |
---|
| 1190 | +} |
---|
| 1191 | +#else |
---|
| 1192 | +static inline void qcom_geni_serial_enable_early_read(struct geni_se *se, |
---|
| 1193 | + struct console *con) { } |
---|
| 1194 | +#endif |
---|
| 1195 | + |
---|
| 1196 | +static struct qcom_geni_private_data earlycon_private_data; |
---|
| 1197 | + |
---|
1097 | 1198 | static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev, |
---|
1098 | 1199 | const char *opt) |
---|
1099 | 1200 | { |
---|
.. | .. |
---|
1108 | 1209 | |
---|
1109 | 1210 | if (!uport->membase) |
---|
1110 | 1211 | return -EINVAL; |
---|
| 1212 | + |
---|
| 1213 | + uport->private_data = &earlycon_private_data; |
---|
1111 | 1214 | |
---|
1112 | 1215 | memset(&se, 0, sizeof(se)); |
---|
1113 | 1216 | se.base = uport->membase; |
---|
.. | .. |
---|
1126 | 1229 | */ |
---|
1127 | 1230 | qcom_geni_serial_poll_tx_done(uport); |
---|
1128 | 1231 | qcom_geni_serial_abort_rx(uport); |
---|
1129 | | - geni_se_config_packing(&se, BITS_PER_BYTE, 1, false, true, false); |
---|
| 1232 | + geni_se_config_packing(&se, BITS_PER_BYTE, BYTES_PER_FIFO_WORD, |
---|
| 1233 | + false, true, true); |
---|
1130 | 1234 | geni_se_init(&se, DEF_FIFO_DEPTH_WORDS / 2, DEF_FIFO_DEPTH_WORDS - 2); |
---|
1131 | 1235 | geni_se_select_mode(&se, GENI_SE_FIFO); |
---|
1132 | 1236 | |
---|
.. | .. |
---|
1140 | 1244 | |
---|
1141 | 1245 | dev->con->write = qcom_geni_serial_earlycon_write; |
---|
1142 | 1246 | dev->con->setup = NULL; |
---|
| 1247 | + qcom_geni_serial_enable_early_read(&se, dev->con); |
---|
| 1248 | + |
---|
1143 | 1249 | return 0; |
---|
1144 | 1250 | } |
---|
1145 | 1251 | OF_EARLYCON_DECLARE(qcom_geni, "qcom,geni-debug-uart", |
---|
.. | .. |
---|
1199 | 1305 | if (old_state == UART_PM_STATE_UNDEFINED) |
---|
1200 | 1306 | old_state = UART_PM_STATE_OFF; |
---|
1201 | 1307 | |
---|
1202 | | - if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) |
---|
| 1308 | + if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) { |
---|
| 1309 | + geni_icc_enable(&port->se); |
---|
| 1310 | + if (port->clk_rate) |
---|
| 1311 | + dev_pm_opp_set_rate(uport->dev, port->clk_rate); |
---|
1203 | 1312 | geni_se_resources_on(&port->se); |
---|
1204 | | - else if (new_state == UART_PM_STATE_OFF && |
---|
1205 | | - old_state == UART_PM_STATE_ON) |
---|
| 1313 | + } else if (new_state == UART_PM_STATE_OFF && |
---|
| 1314 | + old_state == UART_PM_STATE_ON) { |
---|
1206 | 1315 | geni_se_resources_off(&port->se); |
---|
| 1316 | + dev_pm_opp_set_rate(uport->dev, 0); |
---|
| 1317 | + geni_icc_disable(&port->se); |
---|
| 1318 | + } |
---|
1207 | 1319 | } |
---|
1208 | 1320 | |
---|
1209 | 1321 | static const struct uart_ops qcom_geni_console_pops = { |
---|
.. | .. |
---|
1256 | 1368 | if (of_device_is_compatible(pdev->dev.of_node, "qcom,geni-debug-uart")) |
---|
1257 | 1369 | console = true; |
---|
1258 | 1370 | |
---|
1259 | | - if (pdev->dev.of_node) { |
---|
1260 | | - if (console) { |
---|
1261 | | - drv = &qcom_geni_console_driver; |
---|
1262 | | - line = of_alias_get_id(pdev->dev.of_node, "serial"); |
---|
1263 | | - } else { |
---|
1264 | | - drv = &qcom_geni_uart_driver; |
---|
1265 | | - line = of_alias_get_id(pdev->dev.of_node, "hsuart"); |
---|
1266 | | - } |
---|
| 1371 | + if (console) { |
---|
| 1372 | + drv = &qcom_geni_console_driver; |
---|
| 1373 | + line = of_alias_get_id(pdev->dev.of_node, "serial"); |
---|
| 1374 | + } else { |
---|
| 1375 | + drv = &qcom_geni_uart_driver; |
---|
| 1376 | + line = of_alias_get_id(pdev->dev.of_node, "hsuart"); |
---|
1267 | 1377 | } |
---|
1268 | 1378 | |
---|
1269 | 1379 | port = get_port_from_line(line, console); |
---|
.. | .. |
---|
1296 | 1406 | port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS; |
---|
1297 | 1407 | port->tx_fifo_width = DEF_FIFO_WIDTH_BITS; |
---|
1298 | 1408 | |
---|
1299 | | - irq = platform_get_irq(pdev, 0); |
---|
1300 | | - if (irq < 0) { |
---|
1301 | | - dev_err(&pdev->dev, "Failed to get IRQ %d\n", irq); |
---|
1302 | | - return irq; |
---|
| 1409 | + if (!console) { |
---|
| 1410 | + port->rx_fifo = devm_kcalloc(uport->dev, |
---|
| 1411 | + port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); |
---|
| 1412 | + if (!port->rx_fifo) |
---|
| 1413 | + return -ENOMEM; |
---|
1303 | 1414 | } |
---|
1304 | | - uport->irq = irq; |
---|
1305 | 1415 | |
---|
1306 | | - uport->private_data = drv; |
---|
| 1416 | + ret = geni_icc_get(&port->se, NULL); |
---|
| 1417 | + if (ret) |
---|
| 1418 | + return ret; |
---|
| 1419 | + port->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW; |
---|
| 1420 | + port->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW; |
---|
| 1421 | + |
---|
| 1422 | + /* Set BW for register access */ |
---|
| 1423 | + ret = geni_icc_set_bw(&port->se); |
---|
| 1424 | + if (ret) |
---|
| 1425 | + return ret; |
---|
| 1426 | + |
---|
| 1427 | + port->name = devm_kasprintf(uport->dev, GFP_KERNEL, |
---|
| 1428 | + "qcom_geni_serial_%s%d", |
---|
| 1429 | + uart_console(uport) ? "console" : "uart", uport->line); |
---|
| 1430 | + if (!port->name) |
---|
| 1431 | + return -ENOMEM; |
---|
| 1432 | + |
---|
| 1433 | + irq = platform_get_irq(pdev, 0); |
---|
| 1434 | + if (irq < 0) |
---|
| 1435 | + return irq; |
---|
| 1436 | + uport->irq = irq; |
---|
| 1437 | + uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE); |
---|
| 1438 | + |
---|
| 1439 | + if (!console) |
---|
| 1440 | + port->wakeup_irq = platform_get_irq_optional(pdev, 1); |
---|
| 1441 | + |
---|
| 1442 | + if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap")) |
---|
| 1443 | + port->rx_tx_swap = true; |
---|
| 1444 | + |
---|
| 1445 | + if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) |
---|
| 1446 | + port->cts_rts_swap = true; |
---|
| 1447 | + |
---|
| 1448 | + port->se.opp_table = dev_pm_opp_set_clkname(&pdev->dev, "se"); |
---|
| 1449 | + if (IS_ERR(port->se.opp_table)) |
---|
| 1450 | + return PTR_ERR(port->se.opp_table); |
---|
| 1451 | + /* OPP table is optional */ |
---|
| 1452 | + ret = dev_pm_opp_of_add_table(&pdev->dev); |
---|
| 1453 | + if (ret && ret != -ENODEV) { |
---|
| 1454 | + dev_err(&pdev->dev, "invalid OPP table in device tree\n"); |
---|
| 1455 | + goto put_clkname; |
---|
| 1456 | + } |
---|
| 1457 | + |
---|
| 1458 | + port->private_data.drv = drv; |
---|
| 1459 | + uport->private_data = &port->private_data; |
---|
1307 | 1460 | platform_set_drvdata(pdev, port); |
---|
1308 | 1461 | port->handle_rx = console ? handle_rx_console : handle_rx_uart; |
---|
1309 | | - if (!console) |
---|
1310 | | - device_create_file(uport->dev, &dev_attr_loopback); |
---|
1311 | | - return uart_add_one_port(drv, uport); |
---|
| 1462 | + |
---|
| 1463 | + ret = uart_add_one_port(drv, uport); |
---|
| 1464 | + if (ret) |
---|
| 1465 | + goto err; |
---|
| 1466 | + |
---|
| 1467 | + irq_set_status_flags(uport->irq, IRQ_NOAUTOEN); |
---|
| 1468 | + ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr, |
---|
| 1469 | + IRQF_TRIGGER_HIGH, port->name, uport); |
---|
| 1470 | + if (ret) { |
---|
| 1471 | + dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret); |
---|
| 1472 | + uart_remove_one_port(drv, uport); |
---|
| 1473 | + goto err; |
---|
| 1474 | + } |
---|
| 1475 | + |
---|
| 1476 | + if (port->wakeup_irq > 0) { |
---|
| 1477 | + device_init_wakeup(&pdev->dev, true); |
---|
| 1478 | + ret = dev_pm_set_dedicated_wake_irq(&pdev->dev, |
---|
| 1479 | + port->wakeup_irq); |
---|
| 1480 | + if (ret) { |
---|
| 1481 | + device_init_wakeup(&pdev->dev, false); |
---|
| 1482 | + uart_remove_one_port(drv, uport); |
---|
| 1483 | + goto err; |
---|
| 1484 | + } |
---|
| 1485 | + } |
---|
| 1486 | + |
---|
| 1487 | + return 0; |
---|
| 1488 | +err: |
---|
| 1489 | + dev_pm_opp_of_remove_table(&pdev->dev); |
---|
| 1490 | +put_clkname: |
---|
| 1491 | + dev_pm_opp_put_clkname(port->se.opp_table); |
---|
| 1492 | + return ret; |
---|
1312 | 1493 | } |
---|
1313 | 1494 | |
---|
1314 | 1495 | static int qcom_geni_serial_remove(struct platform_device *pdev) |
---|
1315 | 1496 | { |
---|
1316 | 1497 | struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); |
---|
1317 | | - struct uart_driver *drv = port->uport.private_data; |
---|
| 1498 | + struct uart_driver *drv = port->private_data.drv; |
---|
1318 | 1499 | |
---|
| 1500 | + dev_pm_opp_of_remove_table(&pdev->dev); |
---|
| 1501 | + dev_pm_opp_put_clkname(port->se.opp_table); |
---|
| 1502 | + dev_pm_clear_wake_irq(&pdev->dev); |
---|
| 1503 | + device_init_wakeup(&pdev->dev, false); |
---|
1319 | 1504 | uart_remove_one_port(drv, &port->uport); |
---|
| 1505 | + |
---|
1320 | 1506 | return 0; |
---|
1321 | 1507 | } |
---|
1322 | 1508 | |
---|
1323 | | -static int __maybe_unused qcom_geni_serial_sys_suspend_noirq(struct device *dev) |
---|
| 1509 | +static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev) |
---|
1324 | 1510 | { |
---|
1325 | 1511 | struct qcom_geni_serial_port *port = dev_get_drvdata(dev); |
---|
1326 | 1512 | struct uart_port *uport = &port->uport; |
---|
| 1513 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
1327 | 1514 | |
---|
| 1515 | + /* |
---|
| 1516 | + * This is done so we can hit the lowest possible state in suspend |
---|
| 1517 | + * even with no_console_suspend |
---|
| 1518 | + */ |
---|
1328 | 1519 | if (uart_console(uport)) { |
---|
1329 | | - uart_suspend_port(uport->private_data, uport); |
---|
1330 | | - } else { |
---|
1331 | | - struct uart_state *state = uport->state; |
---|
1332 | | - /* |
---|
1333 | | - * If the port is open, deny system suspend. |
---|
1334 | | - */ |
---|
1335 | | - if (state->pm_state == UART_PM_STATE_ON) |
---|
1336 | | - return -EBUSY; |
---|
| 1520 | + geni_icc_set_tag(&port->se, 0x3); |
---|
| 1521 | + geni_icc_set_bw(&port->se); |
---|
1337 | 1522 | } |
---|
1338 | | - |
---|
1339 | | - return 0; |
---|
| 1523 | + return uart_suspend_port(private_data->drv, uport); |
---|
1340 | 1524 | } |
---|
1341 | 1525 | |
---|
1342 | | -static int __maybe_unused qcom_geni_serial_sys_resume_noirq(struct device *dev) |
---|
| 1526 | +static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev) |
---|
1343 | 1527 | { |
---|
| 1528 | + int ret; |
---|
1344 | 1529 | struct qcom_geni_serial_port *port = dev_get_drvdata(dev); |
---|
1345 | 1530 | struct uart_port *uport = &port->uport; |
---|
| 1531 | + struct qcom_geni_private_data *private_data = uport->private_data; |
---|
1346 | 1532 | |
---|
1347 | | - if (uart_console(uport) && |
---|
1348 | | - console_suspend_enabled && uport->suspended) { |
---|
1349 | | - uart_resume_port(uport->private_data, uport); |
---|
1350 | | - /* |
---|
1351 | | - * uart_suspend_port() invokes port shutdown which in turn |
---|
1352 | | - * frees the irq. uart_resume_port invokes port startup which |
---|
1353 | | - * performs request_irq. The request_irq auto-enables the IRQ. |
---|
1354 | | - * In addition, resume_noirq implicitly enables the IRQ and |
---|
1355 | | - * leads to an unbalanced IRQ enable warning. Disable the IRQ |
---|
1356 | | - * before returning so that the warning is suppressed. |
---|
1357 | | - */ |
---|
1358 | | - disable_irq(uport->irq); |
---|
| 1533 | + ret = uart_resume_port(private_data->drv, uport); |
---|
| 1534 | + if (uart_console(uport)) { |
---|
| 1535 | + geni_icc_set_tag(&port->se, 0x7); |
---|
| 1536 | + geni_icc_set_bw(&port->se); |
---|
1359 | 1537 | } |
---|
1360 | | - return 0; |
---|
| 1538 | + return ret; |
---|
1361 | 1539 | } |
---|
1362 | 1540 | |
---|
1363 | 1541 | static const struct dev_pm_ops qcom_geni_serial_pm_ops = { |
---|
1364 | | - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_sys_suspend_noirq, |
---|
1365 | | - qcom_geni_serial_sys_resume_noirq) |
---|
| 1542 | + SET_SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_sys_suspend, |
---|
| 1543 | + qcom_geni_serial_sys_resume) |
---|
1366 | 1544 | }; |
---|
1367 | 1545 | |
---|
1368 | 1546 | static const struct of_device_id qcom_geni_serial_match_table[] = { |
---|