Commit 8caf1f5a3efaf0f76f470c338e7727a558ac01bc

Authored by Fugang Duan
1 parent 4334e58772

MLK-16086 tty: serial: lpuart: add port.lock to protect registers accessing in suspend

Add port.lock to protect register accessing in suspend/resume function.
Disable RIE and ILIE before DMA chan is ternminated in suspend function.

Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
(cherry picked from commit: 51f874a9205cbcbbdb55642f5502bf18aaf245bd)

Showing 1 changed file with 23 additions and 11 deletions Side-by-side Diff

drivers/tty/serial/fsl_lpuart.c
... ... @@ -254,6 +254,7 @@
254 254  
255 255 bool lpuart_dma_tx_use;
256 256 bool lpuart_dma_rx_use;
  257 + bool dma_rx_chan_active;
257 258 struct dma_chan *dma_tx_chan;
258 259 struct dma_chan *dma_rx_chan;
259 260 struct dma_async_tx_descriptor *dma_tx_desc;
... ... @@ -776,7 +777,7 @@
776 777 if (!sport->lpuart_dma_rx_use ||
777 778 (sts & (UARTSTAT_PE | UARTSTAT_NF | UARTSTAT_FE)))
778 779 lpuart32_rxint(irq, dev_id);
779   - else
  780 + else if (sport->lpuart_dma_rx_use && sport->dma_rx_chan_active)
780 781 lpuart_prepare_rx(sport);
781 782 }
782 783  
... ... @@ -809,7 +810,7 @@
809 810 sport->port.icount.rx += copied;
810 811 }
811 812  
812   -static void lpuart_dma_stop(struct lpuart_port *sport)
  813 +static void lpuart_dma_stop(struct lpuart_port *sport, bool enable_pio)
813 814 {
814 815 unsigned int temp;
815 816 unsigned int crdma;
... ... @@ -819,9 +820,11 @@
819 820 crdma = lpuart32_read(sport->port.membase + UARTBAUD);
820 821 lpuart32_write(crdma & ~(UARTBAUD_RDMAE),
821 822 sport->port.membase + UARTBAUD);
822   - temp = lpuart32_read(sport->port.membase + UARTCTRL);
823   - temp |= (UARTCTRL_RIE | UARTCTRL_ILIE);
824   - lpuart32_write(temp, sport->port.membase + UARTCTRL);
  823 + if (enable_pio) {
  824 + temp = lpuart32_read(sport->port.membase + UARTCTRL);
  825 + temp |= (UARTCTRL_RIE | UARTCTRL_ILIE);
  826 + lpuart32_write(temp, sport->port.membase + UARTCTRL);
  827 + }
825 828 } else {
826 829 temp = readb(sport->port.membase + UARTCR5);
827 830 writeb(temp & ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
... ... @@ -847,7 +850,7 @@
847 850 tty_flip_buffer_push(port);
848 851  
849 852 if (count < sport->rxfifo_watermark)
850   - lpuart_dma_stop(sport);
  853 + lpuart_dma_stop(sport, true);
851 854 else
852 855 lpuart_dma_rx(sport);
853 856  
... ... @@ -874,7 +877,7 @@
874 877 sport->dma_rx_in_progress = false;
875 878 lpuart_copy_rx_to_tty(sport, port, count);
876 879 tty_flip_buffer_push(port);
877   - lpuart_dma_stop(sport);
  880 + lpuart_dma_stop(sport, true);
878 881  
879 882 spin_unlock_irqrestore(&sport->port.lock, flags);
880 883 }
... ... @@ -906,6 +909,7 @@
906 909 struct lpuart_port *sport = container_of(port,
907 910 struct lpuart_port, port);
908 911  
  912 + sport->dma_rx_chan_active = false;
909 913 dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
910 914 sport->rxdma_len, DMA_FROM_DEVICE);
911 915  
... ... @@ -1188,6 +1192,7 @@
1188 1192 sport->dma_rx_buf_virt = dma_buf;
1189 1193 sport->dma_rx_buf_bus = dma_bus;
1190 1194 sport->dma_rx_in_progress = false;
  1195 + sport->dma_rx_chan_active = true;
1191 1196  
1192 1197 return 0;
1193 1198 }
... ... @@ -2302,6 +2307,7 @@
2302 2307 struct lpuart_port *sport = dev_get_drvdata(dev);
2303 2308 struct tty_port *port = &sport->port.state->port;
2304 2309 unsigned long temp;
  2310 + unsigned long flags;
2305 2311 int ret;
2306 2312  
2307 2313 ret = clk_prepare_enable(sport->ipg_clk);
2308 2314  
... ... @@ -2311,12 +2317,10 @@
2311 2317 uart_suspend_port(&lpuart_reg, &sport->port);
2312 2318  
2313 2319 if (sport->lpuart32) {
2314   - /* disable Rx/Tx and interrupts */
2315 2320 temp = lpuart32_read(sport->port.membase + UARTCTRL);
2316 2321 temp &= ~(UARTCTRL_TE | UARTCTRL_TIE | UARTCTRL_TCIE);
2317 2322 lpuart32_write(temp, sport->port.membase + UARTCTRL);
2318 2323 } else {
2319   - /* disable Rx/Tx and interrupts */
2320 2324 temp = readb(sport->port.membase + UARTCR2);
2321 2325 temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE);
2322 2326 writeb(temp, sport->port.membase + UARTCR2);
... ... @@ -2324,8 +2328,10 @@
2324 2328  
2325 2329 if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
2326 2330 tty_port_initialized(port)) {
2327   - /* it needs uart interrupt as wakeup source in low power mode */
2328   - lpuart_dma_stop(sport);
  2331 + spin_lock_irqsave(&sport->port.lock, flags);
  2332 + lpuart_dma_stop(sport, false);
  2333 + spin_unlock_irqrestore(&sport->port.lock, flags);
  2334 +
2329 2335 dmaengine_terminate_all(sport->dma_rx_chan);
2330 2336 del_timer_sync(&sport->lpuart_timer);
2331 2337 lpuart_dma_rx_free(&sport->port);
2332 2338  
... ... @@ -2353,7 +2359,9 @@
2353 2359 {
2354 2360 struct tty_port *port = &sport->port.state->port;
2355 2361 unsigned long temp;
  2362 + unsigned long flags;
2356 2363  
  2364 + spin_lock_irqsave(&sport->port.lock, flags);
2357 2365 lpuart32_setup_watermark(sport);
2358 2366  
2359 2367 temp = lpuart32_read(sport->port.membase + UARTCTRL);
... ... @@ -2367,6 +2375,7 @@
2367 2375 temp &= ~(UARTCTRL_TIE | UARTCTRL_TE);
2368 2376  
2369 2377 lpuart32_write(temp, sport->port.membase + UARTCTRL);
  2378 + spin_unlock_irqrestore(&sport->port.lock, flags);
2370 2379  
2371 2380 if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
2372 2381 tty_port_initialized(port)) {
2373 2382  
... ... @@ -2405,7 +2414,9 @@
2405 2414 {
2406 2415 struct tty_port *port = &sport->port.state->port;
2407 2416 unsigned char temp;
  2417 + unsigned long flags;
2408 2418  
  2419 + spin_lock_irqsave(&sport->port.lock, flags);
2409 2420 lpuart_setup_watermark(sport);
2410 2421 temp = readb(sport->port.membase + UARTCR2);
2411 2422 temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
... ... @@ -2417,6 +2428,7 @@
2417 2428 temp &= ~(UARTCR2_TIE | UARTCR2_TE);
2418 2429  
2419 2430 writeb(temp, sport->port.membase + UARTCR2);
  2431 + spin_unlock_irqrestore(&sport->port.lock, flags);
2420 2432  
2421 2433 if (sport->lpuart_dma_rx_use && sport->port.irq_wake &&
2422 2434 tty_port_initialized(port)) {