Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: sprd: Add support for sc9632

Due to the platform's new project uart ip upgrade,
the new project's timeout interrupt needs to use bit17
while other projects' timeout interrupt needs to use
bit13, using private data to adapt and be compatible
with all projects.

Signed-off-by: Wenhua Lin <Wenhua.Lin@unisoc.com>
Link: https://lore.kernel.org/r/20241113110516.2166328-2-Wenhua.Lin@unisoc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Wenhua Lin and committed by
Greg Kroah-Hartman
8f9eeb5c b3a882e8

+36 -5
+36 -5
drivers/tty/serial/sprd_serial.c
··· 53 53 #define SPRD_IEN_TX_EMPTY BIT(1) 54 54 #define SPRD_IEN_BREAK_DETECT BIT(7) 55 55 #define SPRD_IEN_TIMEOUT BIT(13) 56 + #define SPRD_IEN_DATA_TIMEOUT BIT(17) 56 57 57 58 /* interrupt clear register */ 58 59 #define SPRD_ICLR 0x0014 59 60 #define SPRD_ICLR_TIMEOUT BIT(13) 61 + #define SPRD_ICLR_DATA_TIMEOUT BIT(17) 60 62 61 63 /* line control register */ 62 64 #define SPRD_LCR 0x0018 ··· 104 102 #define SPRD_IMSR_TX_FIFO_EMPTY BIT(1) 105 103 #define SPRD_IMSR_BREAK_DETECT BIT(7) 106 104 #define SPRD_IMSR_TIMEOUT BIT(13) 105 + #define SPRD_IMSR_DATA_TIMEOUT BIT(17) 107 106 #define SPRD_DEFAULT_SOURCE_CLK 26000000 108 107 109 108 #define SPRD_RX_DMA_STEP 1 ··· 121 118 bool enable; 122 119 }; 123 120 121 + struct sprd_uart_data { 122 + unsigned int timeout_ien; 123 + unsigned int timeout_iclr; 124 + unsigned int timeout_imsr; 125 + }; 126 + 124 127 struct sprd_uart_port { 125 128 struct uart_port port; 126 129 char name[16]; ··· 135 126 struct sprd_uart_dma rx_dma; 136 127 dma_addr_t pos; 137 128 unsigned char *rx_buf_tail; 129 + const struct sprd_uart_data *pdata; 138 130 }; 139 131 140 132 static struct sprd_uart_port *sprd_port[UART_NR_MAX]; ··· 143 133 144 134 static int sprd_start_dma_rx(struct uart_port *port); 145 135 static int sprd_tx_dma_config(struct uart_port *port); 136 + 137 + static const struct sprd_uart_data sc9836_data = { 138 + .timeout_ien = SPRD_IEN_TIMEOUT, 139 + .timeout_iclr = SPRD_ICLR_TIMEOUT, 140 + .timeout_imsr = SPRD_IMSR_TIMEOUT, 141 + }; 142 + 143 + static const struct sprd_uart_data sc9632_data = { 144 + .timeout_ien = SPRD_IEN_DATA_TIMEOUT, 145 + .timeout_iclr = SPRD_ICLR_DATA_TIMEOUT, 146 + .timeout_imsr = SPRD_IMSR_DATA_TIMEOUT, 147 + }; 146 148 147 149 static inline unsigned int serial_in(struct uart_port *port, 148 150 unsigned int offset) ··· 659 637 { 660 638 struct uart_port *port = dev_id; 661 639 unsigned int ims; 640 + struct sprd_uart_port *sp = 641 + container_of(port, struct sprd_uart_port, port); 662 642 663 643 uart_port_lock(port); 664 644 ··· 671 647 return IRQ_NONE; 672 648 } 673 649 674 - if (ims & SPRD_IMSR_TIMEOUT) 675 - serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT); 650 + if (ims & sp->pdata->timeout_imsr) 651 + serial_out(port, SPRD_ICLR, sp->pdata->timeout_iclr); 676 652 677 653 if (ims & SPRD_IMSR_BREAK_DETECT) 678 654 serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT); 679 655 680 656 if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT | 681 - SPRD_IMSR_TIMEOUT)) 657 + sp->pdata->timeout_imsr)) 682 658 sprd_rx(port); 683 659 684 660 if (ims & SPRD_IMSR_TX_FIFO_EMPTY) ··· 753 729 /* enable interrupt */ 754 730 uart_port_lock_irqsave(port, &flags); 755 731 ien = serial_in(port, SPRD_IEN); 756 - ien |= SPRD_IEN_BREAK_DETECT | SPRD_IEN_TIMEOUT; 732 + ien |= SPRD_IEN_BREAK_DETECT | sp->pdata->timeout_ien; 757 733 if (!sp->rx_dma.enable) 758 734 ien |= SPRD_IEN_RX_FULL; 759 735 serial_out(port, SPRD_IEN, ien); ··· 1208 1184 1209 1185 up->mapbase = res->start; 1210 1186 1187 + sport->pdata = of_device_get_match_data(&pdev->dev); 1188 + if (!sport->pdata) { 1189 + dev_err(&pdev->dev, "get match data failed!\n"); 1190 + return -EINVAL; 1191 + } 1192 + 1211 1193 irq = platform_get_irq(pdev, 0); 1212 1194 if (irq < 0) 1213 1195 return irq; ··· 1278 1248 static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume); 1279 1249 1280 1250 static const struct of_device_id serial_ids[] = { 1281 - {.compatible = "sprd,sc9836-uart",}, 1251 + {.compatible = "sprd,sc9836-uart", .data = &sc9836_data}, 1252 + {.compatible = "sprd,sc9632-uart", .data = &sc9632_data}, 1282 1253 {} 1283 1254 }; 1284 1255 MODULE_DEVICE_TABLE(of, serial_ids);