1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Helpers for controlling modem lines via GPIO 4 * 5 * Copyright (C) 2014 Paratronic S.A. 6 */ 7 8 #include <linux/err.h> 9 #include <linux/device.h> 10 #include <linux/irq.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/termios.h> 13 #include <linux/serial_core.h> 14 #include <linux/module.h> 15 #include <linux/property.h> 16 17 #include "serial_mctrl_gpio.h" 18 19 struct mctrl_gpios { 20 struct uart_port *port; 21 struct gpio_desc *gpio[UART_GPIO_MAX]; 22 int irq[UART_GPIO_MAX]; 23 unsigned int mctrl_prev; 24 bool mctrl_on; 25 }; 26 27 static const struct { 28 const char *name; 29 unsigned int mctrl; 30 enum gpiod_flags flags; 31 } mctrl_gpios_desc[UART_GPIO_MAX] = { 32 { "cts", TIOCM_CTS, GPIOD_IN, }, 33 { "dsr", TIOCM_DSR, GPIOD_IN, }, 34 { "dcd", TIOCM_CD, GPIOD_IN, }, 35 { "rng", TIOCM_RNG, GPIOD_IN, }, 36 { "rts", TIOCM_RTS, GPIOD_OUT_LOW, }, 37 { "dtr", TIOCM_DTR, GPIOD_OUT_LOW, }, 38 }; 39 40 static bool mctrl_gpio_flags_is_dir_out(unsigned int idx) 41 { 42 return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT; 43 } 44 45 /** 46 * mctrl_gpio_set - set gpios according to mctrl state 47 * @gpios: gpios to set 48 * @mctrl: state to set 49 * 50 * Set the gpios according to the mctrl state. 51 */ 52 void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) 53 { 54 enum mctrl_gpio_idx i; 55 struct gpio_desc *desc_array[UART_GPIO_MAX]; 56 DECLARE_BITMAP(values, UART_GPIO_MAX); 57 unsigned int count = 0; 58 59 if (gpios == NULL) 60 return; 61 62 for (i = 0; i < UART_GPIO_MAX; i++) 63 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) { 64 desc_array[count] = gpios->gpio[i]; 65 __assign_bit(count, values, 66 mctrl & mctrl_gpios_desc[i].mctrl); 67 count++; 68 } 69 gpiod_set_array_value(count, desc_array, NULL, values); 70 } 71 EXPORT_SYMBOL_GPL(mctrl_gpio_set); 72 73 /** 74 * mctrl_gpio_to_gpiod - obtain gpio_desc of modem line index 75 * @gpios: gpios to look into 76 * @gidx: index of the modem line 77 * Returns: the gpio_desc structure associated to the modem line index 78 */ 79 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, 80 enum mctrl_gpio_idx gidx) 81 { 82 if (gpios == NULL) 83 return NULL; 84 85 return gpios->gpio[gidx]; 86 } 87 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod); 88 89 /** 90 * mctrl_gpio_get - update mctrl with the gpios values. 91 * @gpios: gpios to get the info from 92 * @mctrl: mctrl to set 93 * Returns: modified mctrl (the same value as in @mctrl) 94 * 95 * Update mctrl with the gpios values. 96 */ 97 unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) 98 { 99 enum mctrl_gpio_idx i; 100 101 if (gpios == NULL) 102 return *mctrl; 103 104 for (i = 0; i < UART_GPIO_MAX; i++) { 105 if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) { 106 if (gpiod_get_value(gpios->gpio[i])) 107 *mctrl |= mctrl_gpios_desc[i].mctrl; 108 else 109 *mctrl &= ~mctrl_gpios_desc[i].mctrl; 110 } 111 } 112 113 return *mctrl; 114 } 115 EXPORT_SYMBOL_GPL(mctrl_gpio_get); 116 117 unsigned int 118 mctrl_gpio_get_outputs(struct mctrl_gpios *gpios, unsigned int *mctrl) 119 { 120 enum mctrl_gpio_idx i; 121 122 if (gpios == NULL) 123 return *mctrl; 124 125 for (i = 0; i < UART_GPIO_MAX; i++) { 126 if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) { 127 if (gpiod_get_value(gpios->gpio[i])) 128 *mctrl |= mctrl_gpios_desc[i].mctrl; 129 else 130 *mctrl &= ~mctrl_gpios_desc[i].mctrl; 131 } 132 } 133 134 return *mctrl; 135 } 136 EXPORT_SYMBOL_GPL(mctrl_gpio_get_outputs); 137 138 struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx) 139 { 140 struct mctrl_gpios *gpios; 141 enum mctrl_gpio_idx i; 142 143 gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); 144 if (!gpios) 145 return ERR_PTR(-ENOMEM); 146 147 for (i = 0; i < UART_GPIO_MAX; i++) { 148 char *gpio_str; 149 bool present; 150 151 /* Check if GPIO property exists and continue if not */ 152 gpio_str = kasprintf(GFP_KERNEL, "%s-gpios", 153 mctrl_gpios_desc[i].name); 154 if (!gpio_str) 155 continue; 156 157 present = device_property_present(dev, gpio_str); 158 kfree(gpio_str); 159 if (!present) 160 continue; 161 162 gpios->gpio[i] = 163 devm_gpiod_get_index_optional(dev, 164 mctrl_gpios_desc[i].name, 165 idx, 166 mctrl_gpios_desc[i].flags); 167 168 if (IS_ERR(gpios->gpio[i])) 169 return ERR_CAST(gpios->gpio[i]); 170 } 171 172 return gpios; 173 } 174 EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto); 175 176 #define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS) 177 static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context) 178 { 179 struct mctrl_gpios *gpios = context; 180 struct uart_port *port = gpios->port; 181 u32 mctrl = gpios->mctrl_prev; 182 u32 mctrl_diff; 183 unsigned long flags; 184 185 mctrl_gpio_get(gpios, &mctrl); 186 187 uart_port_lock_irqsave(port, &flags); 188 189 mctrl_diff = mctrl ^ gpios->mctrl_prev; 190 gpios->mctrl_prev = mctrl; 191 192 if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) { 193 if ((mctrl_diff & mctrl) & TIOCM_RI) 194 port->icount.rng++; 195 196 if ((mctrl_diff & mctrl) & TIOCM_DSR) 197 port->icount.dsr++; 198 199 if (mctrl_diff & TIOCM_CD) 200 uart_handle_dcd_change(port, mctrl & TIOCM_CD); 201 202 if (mctrl_diff & TIOCM_CTS) 203 uart_handle_cts_change(port, mctrl & TIOCM_CTS); 204 205 wake_up_interruptible(&port->state->port.delta_msr_wait); 206 } 207 208 uart_port_unlock_irqrestore(port, flags); 209 210 return IRQ_HANDLED; 211 } 212 213 /** 214 * mctrl_gpio_init - initialize uart gpios 215 * @port: port to initialize gpios for 216 * @idx: index of the gpio in the @port's device 217 * 218 * This will get the {cts,rts,...}-gpios from device tree if they are present 219 * and request them, set direction etc, and return an allocated structure. 220 * `devm_*` functions are used, so there's no need to explicitly free. 221 * As this sets up the irq handling, make sure to not handle changes to the 222 * gpio input lines in your driver, too. 223 */ 224 struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) 225 { 226 struct mctrl_gpios *gpios; 227 enum mctrl_gpio_idx i; 228 229 gpios = mctrl_gpio_init_noauto(port->dev, idx); 230 if (IS_ERR(gpios)) 231 return gpios; 232 233 gpios->port = port; 234 235 for (i = 0; i < UART_GPIO_MAX; ++i) { 236 int ret; 237 238 if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i)) 239 continue; 240 241 ret = gpiod_to_irq(gpios->gpio[i]); 242 if (ret < 0) { 243 dev_err(port->dev, 244 "failed to find corresponding irq for %s (idx=%d, err=%d)\n", 245 mctrl_gpios_desc[i].name, idx, ret); 246 return ERR_PTR(ret); 247 } 248 gpios->irq[i] = ret; 249 250 /* irqs should only be enabled in .enable_ms */ 251 irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN); 252 253 ret = devm_request_irq(port->dev, gpios->irq[i], 254 mctrl_gpio_irq_handle, 255 IRQ_TYPE_EDGE_BOTH, dev_name(port->dev), 256 gpios); 257 if (ret) { 258 /* alternatively implement polling */ 259 dev_err(port->dev, 260 "failed to request irq for %s (idx=%d, err=%d)\n", 261 mctrl_gpios_desc[i].name, idx, ret); 262 return ERR_PTR(ret); 263 } 264 } 265 266 return gpios; 267 } 268 EXPORT_SYMBOL_GPL(mctrl_gpio_init); 269 270 /** 271 * mctrl_gpio_enable_ms - enable irqs and handling of changes to the ms lines 272 * @gpios: gpios to enable 273 */ 274 void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) 275 { 276 enum mctrl_gpio_idx i; 277 278 if (gpios == NULL) 279 return; 280 281 /* .enable_ms may be called multiple times */ 282 if (gpios->mctrl_on) 283 return; 284 285 gpios->mctrl_on = true; 286 287 /* get initial status of modem lines GPIOs */ 288 mctrl_gpio_get(gpios, &gpios->mctrl_prev); 289 290 for (i = 0; i < UART_GPIO_MAX; ++i) { 291 if (!gpios->irq[i]) 292 continue; 293 294 enable_irq(gpios->irq[i]); 295 } 296 } 297 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); 298 299 static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync) 300 { 301 enum mctrl_gpio_idx i; 302 303 if (gpios == NULL) 304 return; 305 306 if (!gpios->mctrl_on) 307 return; 308 309 gpios->mctrl_on = false; 310 311 for (i = 0; i < UART_GPIO_MAX; ++i) { 312 if (!gpios->irq[i]) 313 continue; 314 315 if (sync) 316 disable_irq(gpios->irq[i]); 317 else 318 disable_irq_nosync(gpios->irq[i]); 319 } 320 } 321 322 /** 323 * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms 324 * lines, and wait for any pending IRQ to be processed 325 * @gpios: gpios to disable 326 */ 327 void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) 328 { 329 mctrl_gpio_disable_ms(gpios, true); 330 } 331 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync); 332 333 /** 334 * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the 335 * ms lines, and return immediately 336 * @gpios: gpios to disable 337 */ 338 void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) 339 { 340 mctrl_gpio_disable_ms(gpios, false); 341 } 342 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync); 343 344 void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios) 345 { 346 enum mctrl_gpio_idx i; 347 348 if (!gpios) 349 return; 350 351 if (!gpios->mctrl_on) 352 return; 353 354 for (i = 0; i < UART_GPIO_MAX; ++i) { 355 if (!gpios->irq[i]) 356 continue; 357 358 enable_irq_wake(gpios->irq[i]); 359 } 360 } 361 EXPORT_SYMBOL_GPL(mctrl_gpio_enable_irq_wake); 362 363 void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios) 364 { 365 enum mctrl_gpio_idx i; 366 367 if (!gpios) 368 return; 369 370 if (!gpios->mctrl_on) 371 return; 372 373 for (i = 0; i < UART_GPIO_MAX; ++i) { 374 if (!gpios->irq[i]) 375 continue; 376 377 disable_irq_wake(gpios->irq[i]); 378 } 379 } 380 EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake); 381 382 MODULE_DESCRIPTION("Helpers for controlling modem lines via GPIO"); 383 MODULE_LICENSE("GPL"); 384