1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2025 KEBA Industrial Automation GmbH 4 * 5 * Driver for KEBA UART FPGA IP core 6 */ 7 8 #include <linux/auxiliary_bus.h> 9 #include <linux/bits.h> 10 #include <linux/container_of.h> 11 #include <linux/dev_printk.h> 12 #include <linux/device/devres.h> 13 #include <linux/err.h> 14 #include <linux/io.h> 15 #include <linux/misc/keba.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/module.h> 18 #include <linux/serial_core.h> 19 #include <linux/spinlock.h> 20 #include <linux/types.h> 21 22 #include "8250.h" 23 24 #define KUART "kuart" 25 26 /* flags */ 27 #define KUART_RS485 BIT(0) 28 #define KUART_USE_CAPABILITY BIT(1) 29 30 /* registers */ 31 #define KUART_VERSION 0x0000 32 #define KUART_REVISION 0x0001 33 #define KUART_CAPABILITY 0x0002 34 #define KUART_CONTROL 0x0004 35 #define KUART_BASE 0x000C 36 #define KUART_REGSHIFT 2 37 #define KUART_CLK 1843200 38 39 /* mode flags */ 40 enum kuart_mode { 41 KUART_MODE_NONE = 0, 42 KUART_MODE_RS485, 43 KUART_MODE_RS422, 44 KUART_MODE_RS232 45 }; 46 47 /* capability flags */ 48 #define KUART_CAPABILITY_NONE BIT(KUART_MODE_NONE) 49 #define KUART_CAPABILITY_RS485 BIT(KUART_MODE_RS485) 50 #define KUART_CAPABILITY_RS422 BIT(KUART_MODE_RS422) 51 #define KUART_CAPABILITY_RS232 BIT(KUART_MODE_RS232) 52 #define KUART_CAPABILITY_MASK GENMASK(3, 0) 53 54 /* registers for Indexed Control Register access in enhanced mode */ 55 #define KUART_EMODE_ICR_OFFSET UART_SCR 56 #define KUART_EMODE_ICR_VALUE UART_LSR 57 58 /* Additional Control Register DTR line configuration */ 59 #define UART_ACR_DTRLC_MASK 0x18 60 #define UART_ACR_DTRLC_COMPAT 0x00 61 #define UART_ACR_DTRLC_ENABLE_LOW 0x10 62 63 struct kuart { 64 struct keba_uart_auxdev *auxdev; 65 void __iomem *base; 66 unsigned int line; 67 68 unsigned int flags; 69 u8 capability; 70 enum kuart_mode mode; 71 }; 72 73 static void kuart_set_phy_mode(struct kuart *kuart, enum kuart_mode mode) 74 { 75 iowrite8(mode, kuart->base + KUART_CONTROL); 76 } 77 78 static void kuart_enhanced_mode(struct uart_8250_port *up, bool enable) 79 { 80 u8 lcr, efr; 81 82 /* backup LCR register */ 83 lcr = serial_in(up, UART_LCR); 84 85 /* enable 650 compatible register set (EFR, ...) */ 86 serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 87 88 /* enable/disable enhanced mode with indexed control registers */ 89 efr = serial_in(up, UART_EFR); 90 if (enable) 91 efr |= UART_EFR_ECB; 92 else 93 efr &= ~UART_EFR_ECB; 94 serial_out(up, UART_EFR, efr); 95 96 /* disable 650 compatible register set, restore LCR */ 97 serial_out(up, UART_LCR, lcr); 98 } 99 100 static void kuart_dtr_line_config(struct uart_8250_port *up, u8 dtrlc) 101 { 102 u8 acr; 103 104 /* set index register to 0 to access ACR register */ 105 serial_out(up, KUART_EMODE_ICR_OFFSET, UART_ACR); 106 107 /* set value register to 0x10 writing DTR mode (1,0) */ 108 acr = serial_in(up, KUART_EMODE_ICR_VALUE); 109 acr &= ~UART_ACR_DTRLC_MASK; 110 acr |= dtrlc; 111 serial_out(up, KUART_EMODE_ICR_VALUE, acr); 112 } 113 114 static int kuart_rs485_config(struct uart_port *port, struct ktermios *termios, 115 struct serial_rs485 *rs485) 116 { 117 struct uart_8250_port *up = up_to_u8250p(port); 118 struct kuart *kuart = port->private_data; 119 enum kuart_mode mode; 120 u8 dtrlc; 121 122 if (rs485->flags & SER_RS485_ENABLED) { 123 if (rs485->flags & SER_RS485_MODE_RS422) 124 mode = KUART_MODE_RS422; 125 else 126 mode = KUART_MODE_RS485; 127 } else { 128 mode = KUART_MODE_RS232; 129 } 130 131 if (mode == kuart->mode) 132 return 0; 133 134 if (kuart->flags & KUART_USE_CAPABILITY) { 135 /* deactivate physical interface, break before make */ 136 kuart_set_phy_mode(kuart, KUART_MODE_NONE); 137 } 138 139 if (mode == KUART_MODE_RS485) { 140 /* 141 * Set DTR line configuration of 95x UART to DTR mode (1,0). 142 * In this mode the DTR pin drives the active-low enable pin of 143 * an external RS485 buffer. The DTR pin will be forced low 144 * whenever the transmitter is not empty, otherwise DTR pin is 145 * high. 146 */ 147 dtrlc = UART_ACR_DTRLC_ENABLE_LOW; 148 } else { 149 /* 150 * Set DTR line configuration of 95x UART to DTR mode (0,0). 151 * In this mode the DTR pin is compatible with 16C450, 16C550, 152 * 16C650 and 16c670 (i.e. normal). 153 */ 154 dtrlc = UART_ACR_DTRLC_COMPAT; 155 } 156 157 kuart_enhanced_mode(up, true); 158 kuart_dtr_line_config(up, dtrlc); 159 kuart_enhanced_mode(up, false); 160 161 if (kuart->flags & KUART_USE_CAPABILITY) { 162 /* activate selected physical interface */ 163 kuart_set_phy_mode(kuart, mode); 164 } 165 166 kuart->mode = mode; 167 168 return 0; 169 } 170 171 static int kuart_probe(struct auxiliary_device *auxdev, 172 const struct auxiliary_device_id *id) 173 { 174 struct device *dev = &auxdev->dev; 175 struct uart_8250_port uart = {}; 176 struct resource res; 177 struct kuart *kuart; 178 int retval; 179 180 kuart = devm_kzalloc(dev, sizeof(*kuart), GFP_KERNEL); 181 if (!kuart) 182 return -ENOMEM; 183 kuart->auxdev = container_of(auxdev, struct keba_uart_auxdev, auxdev); 184 kuart->flags = id->driver_data; 185 auxiliary_set_drvdata(auxdev, kuart); 186 187 /* 188 * map only memory in front of UART registers, UART registers will be 189 * mapped by serial port 190 */ 191 res = kuart->auxdev->io; 192 res.end = res.start + KUART_BASE - 1; 193 kuart->base = devm_ioremap_resource(dev, &res); 194 if (IS_ERR(kuart->base)) 195 return PTR_ERR(kuart->base); 196 197 if (kuart->flags & KUART_USE_CAPABILITY) { 198 /* 199 * supported modes are read from capability register, at least 200 * one mode other than none must be supported 201 */ 202 kuart->capability = ioread8(kuart->base + KUART_CAPABILITY) & 203 KUART_CAPABILITY_MASK; 204 if ((kuart->capability & ~KUART_CAPABILITY_NONE) == 0) 205 return -EIO; 206 } 207 208 spin_lock_init(&uart.port.lock); 209 uart.port.dev = dev; 210 uart.port.mapbase = kuart->auxdev->io.start + KUART_BASE; 211 uart.port.irq = kuart->auxdev->irq; 212 uart.port.uartclk = KUART_CLK; 213 uart.port.private_data = kuart; 214 215 /* 8 bit registers are 32 bit aligned => shift register offset */ 216 uart.port.iotype = UPIO_MEM32; 217 uart.port.regshift = KUART_REGSHIFT; 218 219 /* 220 * UART mixes 16550, 16750 and 16C950 (for RS485) standard => auto 221 * configuration works best 222 */ 223 uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_IOREMAP; 224 225 /* 226 * UART supports RS485, RS422 and RS232 with switching of physical 227 * interface 228 */ 229 uart.port.rs485_config = kuart_rs485_config; 230 if (kuart->flags & KUART_RS485) { 231 uart.port.rs485_supported.flags = SER_RS485_ENABLED | 232 SER_RS485_RTS_ON_SEND; 233 uart.port.rs485.flags = SER_RS485_ENABLED | 234 SER_RS485_RTS_ON_SEND; 235 } 236 if (kuart->flags & KUART_USE_CAPABILITY) { 237 /* default mode priority is RS485 > RS422 > RS232 */ 238 if (kuart->capability & KUART_CAPABILITY_RS422) { 239 uart.port.rs485_supported.flags |= SER_RS485_ENABLED | 240 SER_RS485_RTS_ON_SEND | 241 SER_RS485_MODE_RS422; 242 uart.port.rs485.flags = SER_RS485_ENABLED | 243 SER_RS485_RTS_ON_SEND | 244 SER_RS485_MODE_RS422; 245 } 246 if (kuart->capability & KUART_CAPABILITY_RS485) { 247 uart.port.rs485_supported.flags |= SER_RS485_ENABLED | 248 SER_RS485_RTS_ON_SEND; 249 uart.port.rs485.flags = SER_RS485_ENABLED | 250 SER_RS485_RTS_ON_SEND; 251 } 252 } 253 254 retval = serial8250_register_8250_port(&uart); 255 if (retval < 0) 256 return dev_err_probe(&auxdev->dev, retval, 257 "UART registration failed!\n"); 258 kuart->line = retval; 259 260 return 0; 261 } 262 263 static void kuart_remove(struct auxiliary_device *auxdev) 264 { 265 struct kuart *kuart = auxiliary_get_drvdata(auxdev); 266 267 if (kuart->flags & KUART_USE_CAPABILITY) 268 kuart_set_phy_mode(kuart, KUART_MODE_NONE); 269 270 serial8250_unregister_port(kuart->line); 271 } 272 273 static const struct auxiliary_device_id kuart_devtype_aux[] = { 274 { .name = "keba.rs485-uart", .driver_data = KUART_RS485 }, 275 { .name = "keba.rs232-uart", .driver_data = 0 }, 276 { .name = "keba.uart", .driver_data = KUART_USE_CAPABILITY }, 277 {} 278 }; 279 MODULE_DEVICE_TABLE(auxiliary, kuart_devtype_aux); 280 281 static struct auxiliary_driver kuart_driver_aux = { 282 .name = KUART, 283 .id_table = kuart_devtype_aux, 284 .probe = kuart_probe, 285 .remove = kuart_remove, 286 }; 287 module_auxiliary_driver(kuart_driver_aux); 288 289 MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>"); 290 MODULE_DESCRIPTION("KEBA 8250 serial port driver"); 291 MODULE_LICENSE("GPL"); 292