1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Nuvoton NCT6694 GPIO controller driver based on USB interface. 4 * 5 * Copyright (C) 2025 Nuvoton Technology Corp. 6 */ 7 8 #include <linux/bits.h> 9 #include <linux/gpio/driver.h> 10 #include <linux/idr.h> 11 #include <linux/interrupt.h> 12 #include <linux/mfd/nct6694.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 16 /* 17 * USB command module type for NCT6694 GPIO controller. 18 * This defines the module type used for communication with the NCT6694 19 * GPIO controller over the USB interface. 20 */ 21 #define NCT6694_GPIO_MOD 0xFF 22 23 #define NCT6694_GPIO_VER 0x90 24 #define NCT6694_GPIO_VALID 0x110 25 #define NCT6694_GPI_DATA 0x120 26 #define NCT6694_GPO_DIR 0x170 27 #define NCT6694_GPO_TYPE 0x180 28 #define NCT6694_GPO_DATA 0x190 29 30 #define NCT6694_GPI_STS 0x130 31 #define NCT6694_GPI_CLR 0x140 32 #define NCT6694_GPI_FALLING 0x150 33 #define NCT6694_GPI_RISING 0x160 34 35 #define NCT6694_NR_GPIO 8 36 37 struct nct6694_gpio_data { 38 struct nct6694 *nct6694; 39 struct gpio_chip gpio; 40 struct mutex lock; 41 /* Protect irq operation */ 42 struct mutex irq_lock; 43 44 unsigned char reg_val; 45 unsigned char irq_trig_falling; 46 unsigned char irq_trig_rising; 47 48 /* Current gpio group */ 49 unsigned char group; 50 int irq; 51 }; 52 53 static int nct6694_get_direction(struct gpio_chip *gpio, unsigned int offset) 54 { 55 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 56 const struct nct6694_cmd_header cmd_hd = { 57 .mod = NCT6694_GPIO_MOD, 58 .offset = cpu_to_le16(NCT6694_GPO_DIR + data->group), 59 .len = cpu_to_le16(sizeof(data->reg_val)) 60 }; 61 int ret; 62 63 guard(mutex)(&data->lock); 64 65 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 66 if (ret < 0) 67 return ret; 68 69 return !(BIT(offset) & data->reg_val); 70 } 71 72 static int nct6694_direction_input(struct gpio_chip *gpio, unsigned int offset) 73 { 74 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 75 const struct nct6694_cmd_header cmd_hd = { 76 .mod = NCT6694_GPIO_MOD, 77 .offset = cpu_to_le16(NCT6694_GPO_DIR + data->group), 78 .len = cpu_to_le16(sizeof(data->reg_val)) 79 }; 80 int ret; 81 82 guard(mutex)(&data->lock); 83 84 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 85 if (ret < 0) 86 return ret; 87 88 data->reg_val &= ~BIT(offset); 89 90 return nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 91 } 92 93 static int nct6694_direction_output(struct gpio_chip *gpio, 94 unsigned int offset, int val) 95 { 96 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 97 struct nct6694_cmd_header cmd_hd = { 98 .mod = NCT6694_GPIO_MOD, 99 .offset = cpu_to_le16(NCT6694_GPO_DIR + data->group), 100 .len = cpu_to_le16(sizeof(data->reg_val)) 101 }; 102 int ret; 103 104 guard(mutex)(&data->lock); 105 106 /* Set direction to output */ 107 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 108 if (ret < 0) 109 return ret; 110 111 data->reg_val |= BIT(offset); 112 ret = nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 113 if (ret < 0) 114 return ret; 115 116 /* Then set output level */ 117 cmd_hd.offset = cpu_to_le16(NCT6694_GPO_DATA + data->group); 118 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 119 if (ret < 0) 120 return ret; 121 122 if (val) 123 data->reg_val |= BIT(offset); 124 else 125 data->reg_val &= ~BIT(offset); 126 127 return nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 128 } 129 130 static int nct6694_get_value(struct gpio_chip *gpio, unsigned int offset) 131 { 132 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 133 struct nct6694_cmd_header cmd_hd = { 134 .mod = NCT6694_GPIO_MOD, 135 .offset = cpu_to_le16(NCT6694_GPO_DIR + data->group), 136 .len = cpu_to_le16(sizeof(data->reg_val)) 137 }; 138 int ret; 139 140 guard(mutex)(&data->lock); 141 142 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 143 if (ret < 0) 144 return ret; 145 146 if (BIT(offset) & data->reg_val) { 147 cmd_hd.offset = cpu_to_le16(NCT6694_GPO_DATA + data->group); 148 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 149 if (ret < 0) 150 return ret; 151 152 return !!(BIT(offset) & data->reg_val); 153 } 154 155 cmd_hd.offset = cpu_to_le16(NCT6694_GPI_DATA + data->group); 156 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 157 if (ret < 0) 158 return ret; 159 160 return !!(BIT(offset) & data->reg_val); 161 } 162 163 static int nct6694_set_value(struct gpio_chip *gpio, unsigned int offset, 164 int val) 165 { 166 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 167 const struct nct6694_cmd_header cmd_hd = { 168 .mod = NCT6694_GPIO_MOD, 169 .offset = cpu_to_le16(NCT6694_GPO_DATA + data->group), 170 .len = cpu_to_le16(sizeof(data->reg_val)) 171 }; 172 int ret; 173 174 guard(mutex)(&data->lock); 175 176 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 177 if (ret < 0) 178 return ret; 179 180 if (val) 181 data->reg_val |= BIT(offset); 182 else 183 data->reg_val &= ~BIT(offset); 184 185 return nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 186 } 187 188 static int nct6694_set_config(struct gpio_chip *gpio, unsigned int offset, 189 unsigned long config) 190 { 191 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 192 const struct nct6694_cmd_header cmd_hd = { 193 .mod = NCT6694_GPIO_MOD, 194 .offset = cpu_to_le16(NCT6694_GPO_TYPE + data->group), 195 .len = cpu_to_le16(sizeof(data->reg_val)) 196 }; 197 int ret; 198 199 guard(mutex)(&data->lock); 200 201 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 202 if (ret < 0) 203 return ret; 204 205 switch (pinconf_to_config_param(config)) { 206 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 207 data->reg_val |= BIT(offset); 208 break; 209 case PIN_CONFIG_DRIVE_PUSH_PULL: 210 data->reg_val &= ~BIT(offset); 211 break; 212 default: 213 return -ENOTSUPP; 214 } 215 216 return nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 217 } 218 219 static int nct6694_init_valid_mask(struct gpio_chip *gpio, 220 unsigned long *valid_mask, 221 unsigned int ngpios) 222 { 223 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 224 const struct nct6694_cmd_header cmd_hd = { 225 .mod = NCT6694_GPIO_MOD, 226 .offset = cpu_to_le16(NCT6694_GPIO_VALID + data->group), 227 .len = cpu_to_le16(sizeof(data->reg_val)) 228 }; 229 int ret; 230 231 guard(mutex)(&data->lock); 232 233 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 234 if (ret < 0) 235 return ret; 236 237 *valid_mask = data->reg_val; 238 239 return ret; 240 } 241 242 static irqreturn_t nct6694_irq_handler(int irq, void *priv) 243 { 244 struct nct6694_gpio_data *data = priv; 245 struct nct6694_cmd_header cmd_hd = { 246 .mod = NCT6694_GPIO_MOD, 247 .offset = cpu_to_le16(NCT6694_GPI_STS + data->group), 248 .len = cpu_to_le16(sizeof(data->reg_val)) 249 }; 250 unsigned char status; 251 int ret; 252 253 guard(mutex)(&data->lock); 254 255 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->reg_val); 256 if (ret) 257 return IRQ_NONE; 258 259 status = data->reg_val; 260 261 while (status) { 262 int bit = __ffs(status); 263 264 data->reg_val = BIT(bit); 265 handle_nested_irq(irq_find_mapping(data->gpio.irq.domain, bit)); 266 status &= ~BIT(bit); 267 cmd_hd.offset = cpu_to_le16(NCT6694_GPI_CLR + data->group); 268 nct6694_write_msg(data->nct6694, &cmd_hd, &data->reg_val); 269 } 270 271 return IRQ_HANDLED; 272 } 273 274 static int nct6694_get_irq_trig(struct nct6694_gpio_data *data) 275 { 276 struct nct6694_cmd_header cmd_hd = { 277 .mod = NCT6694_GPIO_MOD, 278 .offset = cpu_to_le16(NCT6694_GPI_FALLING + data->group), 279 .len = cpu_to_le16(sizeof(data->reg_val)) 280 }; 281 int ret; 282 283 guard(mutex)(&data->lock); 284 285 ret = nct6694_read_msg(data->nct6694, &cmd_hd, &data->irq_trig_falling); 286 if (ret) 287 return ret; 288 289 cmd_hd.offset = cpu_to_le16(NCT6694_GPI_RISING + data->group); 290 return nct6694_read_msg(data->nct6694, &cmd_hd, &data->irq_trig_rising); 291 } 292 293 static void nct6694_irq_mask(struct irq_data *d) 294 { 295 struct gpio_chip *gpio = irq_data_get_irq_chip_data(d); 296 irq_hw_number_t hwirq = irqd_to_hwirq(d); 297 298 gpiochip_disable_irq(gpio, hwirq); 299 } 300 301 static void nct6694_irq_unmask(struct irq_data *d) 302 { 303 struct gpio_chip *gpio = irq_data_get_irq_chip_data(d); 304 irq_hw_number_t hwirq = irqd_to_hwirq(d); 305 306 gpiochip_enable_irq(gpio, hwirq); 307 } 308 309 static int nct6694_irq_set_type(struct irq_data *d, unsigned int type) 310 { 311 struct gpio_chip *gpio = irq_data_get_irq_chip_data(d); 312 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 313 irq_hw_number_t hwirq = irqd_to_hwirq(d); 314 315 guard(mutex)(&data->lock); 316 317 switch (type) { 318 case IRQ_TYPE_EDGE_RISING: 319 data->irq_trig_rising |= BIT(hwirq); 320 break; 321 322 case IRQ_TYPE_EDGE_FALLING: 323 data->irq_trig_falling |= BIT(hwirq); 324 break; 325 326 case IRQ_TYPE_EDGE_BOTH: 327 data->irq_trig_rising |= BIT(hwirq); 328 data->irq_trig_falling |= BIT(hwirq); 329 break; 330 331 default: 332 return -ENOTSUPP; 333 } 334 335 return 0; 336 } 337 338 static void nct6694_irq_bus_lock(struct irq_data *d) 339 { 340 struct gpio_chip *gpio = irq_data_get_irq_chip_data(d); 341 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 342 343 mutex_lock(&data->irq_lock); 344 } 345 346 static void nct6694_irq_bus_sync_unlock(struct irq_data *d) 347 { 348 struct gpio_chip *gpio = irq_data_get_irq_chip_data(d); 349 struct nct6694_gpio_data *data = gpiochip_get_data(gpio); 350 struct nct6694_cmd_header cmd_hd = { 351 .mod = NCT6694_GPIO_MOD, 352 .offset = cpu_to_le16(NCT6694_GPI_FALLING + data->group), 353 .len = cpu_to_le16(sizeof(data->reg_val)) 354 }; 355 356 scoped_guard(mutex, &data->lock) { 357 nct6694_write_msg(data->nct6694, &cmd_hd, &data->irq_trig_falling); 358 359 cmd_hd.offset = cpu_to_le16(NCT6694_GPI_RISING + data->group); 360 nct6694_write_msg(data->nct6694, &cmd_hd, &data->irq_trig_rising); 361 } 362 363 mutex_unlock(&data->irq_lock); 364 } 365 366 static const struct irq_chip nct6694_irq_chip = { 367 .name = "gpio-nct6694", 368 .irq_mask = nct6694_irq_mask, 369 .irq_unmask = nct6694_irq_unmask, 370 .irq_set_type = nct6694_irq_set_type, 371 .irq_bus_lock = nct6694_irq_bus_lock, 372 .irq_bus_sync_unlock = nct6694_irq_bus_sync_unlock, 373 .flags = IRQCHIP_IMMUTABLE, 374 GPIOCHIP_IRQ_RESOURCE_HELPERS, 375 }; 376 377 static void nct6694_irq_dispose_mapping(void *d) 378 { 379 struct nct6694_gpio_data *data = d; 380 381 irq_dispose_mapping(data->irq); 382 } 383 384 static void nct6694_gpio_ida_free(void *d) 385 { 386 struct nct6694_gpio_data *data = d; 387 struct nct6694 *nct6694 = data->nct6694; 388 389 ida_free(&nct6694->gpio_ida, data->group); 390 } 391 392 static int nct6694_gpio_probe(struct platform_device *pdev) 393 { 394 struct device *dev = &pdev->dev; 395 struct nct6694 *nct6694 = dev_get_drvdata(dev->parent); 396 struct nct6694_gpio_data *data; 397 struct gpio_irq_chip *girq; 398 int ret, i; 399 char **names; 400 401 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 402 if (!data) 403 return -ENOMEM; 404 405 data->nct6694 = nct6694; 406 407 ret = ida_alloc(&nct6694->gpio_ida, GFP_KERNEL); 408 if (ret < 0) 409 return ret; 410 data->group = ret; 411 412 ret = devm_add_action_or_reset(dev, nct6694_gpio_ida_free, data); 413 if (ret) 414 return ret; 415 416 names = devm_kcalloc(dev, NCT6694_NR_GPIO, sizeof(char *), 417 GFP_KERNEL); 418 if (!names) 419 return -ENOMEM; 420 421 for (i = 0; i < NCT6694_NR_GPIO; i++) { 422 names[i] = devm_kasprintf(dev, GFP_KERNEL, "GPIO%X%d", 423 data->group, i); 424 if (!names[i]) 425 return -ENOMEM; 426 } 427 428 data->irq = irq_create_mapping(nct6694->domain, 429 NCT6694_IRQ_GPIO0 + data->group); 430 if (!data->irq) 431 return -EINVAL; 432 433 ret = devm_add_action_or_reset(dev, nct6694_irq_dispose_mapping, data); 434 if (ret) 435 return ret; 436 437 data->gpio.names = (const char * const*)names; 438 data->gpio.label = pdev->name; 439 data->gpio.direction_input = nct6694_direction_input; 440 data->gpio.get = nct6694_get_value; 441 data->gpio.direction_output = nct6694_direction_output; 442 data->gpio.set = nct6694_set_value; 443 data->gpio.get_direction = nct6694_get_direction; 444 data->gpio.set_config = nct6694_set_config; 445 data->gpio.init_valid_mask = nct6694_init_valid_mask; 446 data->gpio.base = -1; 447 data->gpio.can_sleep = false; 448 data->gpio.owner = THIS_MODULE; 449 data->gpio.ngpio = NCT6694_NR_GPIO; 450 451 platform_set_drvdata(pdev, data); 452 453 ret = devm_mutex_init(dev, &data->lock); 454 if (ret) 455 return ret; 456 457 ret = devm_mutex_init(dev, &data->irq_lock); 458 if (ret) 459 return ret; 460 461 ret = nct6694_get_irq_trig(data); 462 if (ret) { 463 dev_err_probe(dev, ret, "Failed to get irq trigger type\n"); 464 return ret; 465 } 466 467 girq = &data->gpio.irq; 468 gpio_irq_chip_set_chip(girq, &nct6694_irq_chip); 469 girq->parent_handler = NULL; 470 girq->num_parents = 0; 471 girq->parents = NULL; 472 girq->default_type = IRQ_TYPE_NONE; 473 girq->handler = handle_level_irq; 474 girq->threaded = true; 475 476 ret = devm_request_threaded_irq(dev, data->irq, NULL, nct6694_irq_handler, 477 IRQF_ONESHOT | IRQF_SHARED, 478 "gpio-nct6694", data); 479 if (ret) { 480 dev_err_probe(dev, ret, "Failed to request irq\n"); 481 return ret; 482 } 483 484 return devm_gpiochip_add_data(dev, &data->gpio, data); 485 } 486 487 static struct platform_driver nct6694_gpio_driver = { 488 .driver = { 489 .name = "nct6694-gpio", 490 }, 491 .probe = nct6694_gpio_probe, 492 }; 493 494 module_platform_driver(nct6694_gpio_driver); 495 496 MODULE_DESCRIPTION("USB-GPIO controller driver for NCT6694"); 497 MODULE_AUTHOR("Ming Yu <tmyu0@nuvoton.com>"); 498 MODULE_LICENSE("GPL"); 499 MODULE_ALIAS("platform:nct6694-gpio"); 500