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

serial: 8250_fintek: Add F81866 Support

Fintek F81866 is a LPC to 6 UARTs SuperIO. It has fully functional UARTs
likes F81216H. It's also need check the IRQ mode with system assigned,
but the configuration is not the same with F81216 series.

F81866 IRQ Mode setting:
0xf0
Bit1: IRQ_MODE0
Bit0: Share mode (always on)
0xf6
Bit3: IRQ_MODE1

Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
Edge/High: IRQ_MODE0:1, IRQ_MODE1:0

The following list is brief descriptions of F81866:

F81866 (1010)
9Bit/High baud rate(not implements with mainline)
RS485, 128Bytes FIFO (implemented)

Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ji-Ze Hong (Peter Hong) and committed by
Greg Kroah-Hartman
da60d6af 1e26c472

+68 -6
+68 -6
drivers/tty/serial/8250/8250_fintek.c
··· 21 21 #define EXIT_KEY 0xAA 22 22 #define CHIP_ID1 0x20 23 23 #define CHIP_ID2 0x21 24 + #define CHIP_ID_F81866 0x1010 24 25 #define CHIP_ID_F81216AD 0x1602 25 26 #define CHIP_ID_F81216H 0x0501 26 27 #define CHIP_ID_F81216 0x0802 ··· 50 49 #define FIFO_MODE_128 (BIT(1) | BIT(0)) 51 50 #define RXFTHR_MODE_MASK (BIT(5) | BIT(4)) 52 51 #define RXFTHR_MODE_4X BIT(5) 52 + 53 + #define F81216_LDN_LOW 0x0 54 + #define F81216_LDN_HIGH 0x4 55 + 56 + /* 57 + * F81866 registers 58 + * 59 + * The IRQ setting mode of F81866 is not the same with F81216 series. 60 + * Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 61 + * Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 62 + */ 63 + #define F81866_IRQ_MODE 0xf0 64 + #define F81866_IRQ_SHARE BIT(0) 65 + #define F81866_IRQ_MODE0 BIT(1) 66 + 67 + #define F81866_FIFO_CTRL FIFO_CTRL 68 + #define F81866_IRQ_MODE1 BIT(3) 69 + 70 + #define F81866_LDN_LOW 0x10 71 + #define F81866_LDN_HIGH 0x16 53 72 54 73 struct fintek_8250 { 55 74 u16 pid; ··· 130 109 chip |= sio_read_reg(pdata, CHIP_ID2) << 8; 131 110 132 111 switch (chip) { 112 + case CHIP_ID_F81866: 133 113 case CHIP_ID_F81216AD: 134 114 case CHIP_ID_F81216H: 135 115 case CHIP_ID_F81216: ··· 141 119 142 120 pdata->pid = chip; 143 121 return 0; 122 + } 123 + 124 + static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, 125 + int *max) 126 + { 127 + switch (pdata->pid) { 128 + case CHIP_ID_F81866: 129 + *min = F81866_LDN_LOW; 130 + *max = F81866_LDN_HIGH; 131 + return 0; 132 + 133 + case CHIP_ID_F81216AD: 134 + case CHIP_ID_F81216H: 135 + case CHIP_ID_F81216: 136 + *min = F81216_LDN_LOW; 137 + *max = F81216_LDN_HIGH; 138 + return 0; 139 + } 140 + 141 + return -ENODEV; 144 142 } 145 143 146 144 static int fintek_8250_rs485_config(struct uart_port *port, ··· 214 172 static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) 215 173 { 216 174 sio_write_reg(pdata, LDN, pdata->index); 217 - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, IRQ_SHARE); 218 - sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, 219 - is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); 175 + 176 + switch (pdata->pid) { 177 + case CHIP_ID_F81866: 178 + sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, 179 + 0); 180 + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, 181 + F81866_IRQ_SHARE); 182 + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_MODE0, 183 + is_level ? 0 : F81866_IRQ_MODE0); 184 + break; 185 + 186 + case CHIP_ID_F81216AD: 187 + case CHIP_ID_F81216H: 188 + case CHIP_ID_F81216: 189 + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, 190 + IRQ_SHARE); 191 + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, 192 + is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); 193 + break; 194 + } 220 195 } 221 196 222 197 static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) 223 198 { 224 199 switch (pdata->pid) { 225 200 case CHIP_ID_F81216H: /* 128Bytes FIFO */ 201 + case CHIP_ID_F81866: 226 202 sio_write_mask_reg(pdata, FIFO_CTRL, 227 203 FIFO_MODE_MASK | RXFTHR_MODE_MASK, 228 204 FIFO_MODE_128 | RXFTHR_MODE_4X); ··· 258 198 static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; 259 199 struct irq_data *irq_data; 260 200 bool level_mode = false; 261 - int i, j, k; 201 + int i, j, k, min, max; 262 202 263 203 for (i = 0; i < ARRAY_SIZE(addr); i++) { 264 204 for (j = 0; j < ARRAY_SIZE(keys); j++) { ··· 267 207 268 208 if (fintek_8250_enter_key(addr[i], keys[j])) 269 209 continue; 270 - if (fintek_8250_check_id(pdata)) { 210 + if (fintek_8250_check_id(pdata) || 211 + fintek_8250_get_ldn_range(pdata, &min, &max)) { 271 212 fintek_8250_exit_key(addr[i]); 272 213 continue; 273 214 } 274 215 275 - for (k = 0; k < 4; k++) { 216 + for (k = min; k < max; k++) { 276 217 u16 aux; 277 218 278 219 sio_write_reg(pdata, LDN, k); ··· 310 249 switch (pdata->pid) { 311 250 case CHIP_ID_F81216AD: 312 251 case CHIP_ID_F81216H: 252 + case CHIP_ID_F81866: 313 253 uart->port.rs485_config = fintek_8250_rs485_config; 314 254 break; 315 255