Commit 8caf1f5a3efaf0f76f470c338e7727a558ac01bc
1 parent
4334e58772
Exists in
smarc-n7.1.2_2.0.0-ga
and in
2 other branches
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)) { |