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