Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) ST-Ericsson SA 2010
0004  *
0005  * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
0006  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
0007  */
0008 
0009 #include <linux/init.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/slab.h>
0012 #include <linux/gpio/driver.h>
0013 #include <linux/of.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/mfd/tc3589x.h>
0016 #include <linux/bitops.h>
0017 
0018 /*
0019  * These registers are modified under the irq bus lock and cached to avoid
0020  * unnecessary writes in bus_sync_unlock.
0021  */
0022 enum { REG_IBE, REG_IEV, REG_IS, REG_IE, REG_DIRECT };
0023 
0024 #define CACHE_NR_REGS   5
0025 #define CACHE_NR_BANKS  3
0026 
0027 struct tc3589x_gpio {
0028     struct gpio_chip chip;
0029     struct tc3589x *tc3589x;
0030     struct device *dev;
0031     struct mutex irq_lock;
0032     /* Caches of interrupt control registers for bus_lock */
0033     u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
0034     u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
0035 };
0036 
0037 static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned int offset)
0038 {
0039     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0040     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0041     u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
0042     u8 mask = BIT(offset % 8);
0043     int ret;
0044 
0045     ret = tc3589x_reg_read(tc3589x, reg);
0046     if (ret < 0)
0047         return ret;
0048 
0049     return !!(ret & mask);
0050 }
0051 
0052 static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned int offset, int val)
0053 {
0054     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0055     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0056     u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
0057     unsigned int pos = offset % 8;
0058     u8 data[] = {val ? BIT(pos) : 0, BIT(pos)};
0059 
0060     tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
0061 }
0062 
0063 static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
0064                      unsigned int offset, int val)
0065 {
0066     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0067     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0068     u8 reg = TC3589x_GPIODIR0 + offset / 8;
0069     unsigned int pos = offset % 8;
0070 
0071     tc3589x_gpio_set(chip, offset, val);
0072 
0073     return tc3589x_set_bits(tc3589x, reg, BIT(pos), BIT(pos));
0074 }
0075 
0076 static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
0077                     unsigned int offset)
0078 {
0079     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0080     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0081     u8 reg = TC3589x_GPIODIR0 + offset / 8;
0082     unsigned int pos = offset % 8;
0083 
0084     return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0);
0085 }
0086 
0087 static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
0088                       unsigned int offset)
0089 {
0090     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0091     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0092     u8 reg = TC3589x_GPIODIR0 + offset / 8;
0093     unsigned int pos = offset % 8;
0094     int ret;
0095 
0096     ret = tc3589x_reg_read(tc3589x, reg);
0097     if (ret < 0)
0098         return ret;
0099 
0100     if (ret & BIT(pos))
0101         return GPIO_LINE_DIRECTION_OUT;
0102 
0103     return GPIO_LINE_DIRECTION_IN;
0104 }
0105 
0106 static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
0107                    unsigned long config)
0108 {
0109     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
0110     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0111     /*
0112      * These registers are alterated at each second address
0113      * ODM bit 0 = drive to GND or Hi-Z (open drain)
0114      * ODM bit 1 = drive to VDD or Hi-Z (open source)
0115      */
0116     u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2;
0117     u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2;
0118     unsigned int pos = offset % 8;
0119     int ret;
0120 
0121     switch (pinconf_to_config_param(config)) {
0122     case PIN_CONFIG_DRIVE_OPEN_DRAIN:
0123         /* Set open drain mode */
0124         ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0);
0125         if (ret)
0126             return ret;
0127         /* Enable open drain/source mode */
0128         return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
0129     case PIN_CONFIG_DRIVE_OPEN_SOURCE:
0130         /* Set open source mode */
0131         ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos));
0132         if (ret)
0133             return ret;
0134         /* Enable open drain/source mode */
0135         return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
0136     case PIN_CONFIG_DRIVE_PUSH_PULL:
0137         /* Disable open drain/source mode */
0138         return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0);
0139     default:
0140         break;
0141     }
0142     return -ENOTSUPP;
0143 }
0144 
0145 static const struct gpio_chip template_chip = {
0146     .label          = "tc3589x",
0147     .owner          = THIS_MODULE,
0148     .get            = tc3589x_gpio_get,
0149     .set            = tc3589x_gpio_set,
0150     .direction_output   = tc3589x_gpio_direction_output,
0151     .direction_input    = tc3589x_gpio_direction_input,
0152     .get_direction      = tc3589x_gpio_get_direction,
0153     .set_config     = tc3589x_gpio_set_config,
0154     .can_sleep      = true,
0155 };
0156 
0157 static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
0158 {
0159     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0160     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
0161     int offset = d->hwirq;
0162     int regoffset = offset / 8;
0163     int mask = BIT(offset % 8);
0164 
0165     if (type == IRQ_TYPE_EDGE_BOTH) {
0166         tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
0167         return 0;
0168     }
0169 
0170     tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask;
0171 
0172     if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
0173         tc3589x_gpio->regs[REG_IS][regoffset] |= mask;
0174     else
0175         tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask;
0176 
0177     if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
0178         tc3589x_gpio->regs[REG_IEV][regoffset] |= mask;
0179     else
0180         tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask;
0181 
0182     return 0;
0183 }
0184 
0185 static void tc3589x_gpio_irq_lock(struct irq_data *d)
0186 {
0187     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0188     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
0189 
0190     mutex_lock(&tc3589x_gpio->irq_lock);
0191 }
0192 
0193 static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
0194 {
0195     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0196     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
0197     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0198     static const u8 regmap[] = {
0199         [REG_IBE]   = TC3589x_GPIOIBE0,
0200         [REG_IEV]   = TC3589x_GPIOIEV0,
0201         [REG_IS]    = TC3589x_GPIOIS0,
0202         [REG_IE]    = TC3589x_GPIOIE0,
0203         [REG_DIRECT]    = TC3589x_DIRECT0,
0204     };
0205     int i, j;
0206 
0207     for (i = 0; i < CACHE_NR_REGS; i++) {
0208         for (j = 0; j < CACHE_NR_BANKS; j++) {
0209             u8 old = tc3589x_gpio->oldregs[i][j];
0210             u8 new = tc3589x_gpio->regs[i][j];
0211 
0212             if (new == old)
0213                 continue;
0214 
0215             tc3589x_gpio->oldregs[i][j] = new;
0216             tc3589x_reg_write(tc3589x, regmap[i] + j, new);
0217         }
0218     }
0219 
0220     mutex_unlock(&tc3589x_gpio->irq_lock);
0221 }
0222 
0223 static void tc3589x_gpio_irq_mask(struct irq_data *d)
0224 {
0225     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0226     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
0227     int offset = d->hwirq;
0228     int regoffset = offset / 8;
0229     int mask = BIT(offset % 8);
0230 
0231     tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
0232     tc3589x_gpio->regs[REG_DIRECT][regoffset] |= mask;
0233 }
0234 
0235 static void tc3589x_gpio_irq_unmask(struct irq_data *d)
0236 {
0237     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0238     struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
0239     int offset = d->hwirq;
0240     int regoffset = offset / 8;
0241     int mask = BIT(offset % 8);
0242 
0243     tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
0244     tc3589x_gpio->regs[REG_DIRECT][regoffset] &= ~mask;
0245 }
0246 
0247 static struct irq_chip tc3589x_gpio_irq_chip = {
0248     .name           = "tc3589x-gpio",
0249     .irq_bus_lock       = tc3589x_gpio_irq_lock,
0250     .irq_bus_sync_unlock    = tc3589x_gpio_irq_sync_unlock,
0251     .irq_mask       = tc3589x_gpio_irq_mask,
0252     .irq_unmask     = tc3589x_gpio_irq_unmask,
0253     .irq_set_type       = tc3589x_gpio_irq_set_type,
0254 };
0255 
0256 static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
0257 {
0258     struct tc3589x_gpio *tc3589x_gpio = dev;
0259     struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
0260     u8 status[CACHE_NR_BANKS];
0261     int ret;
0262     int i;
0263 
0264     ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0,
0265                  ARRAY_SIZE(status), status);
0266     if (ret < 0)
0267         return IRQ_NONE;
0268 
0269     for (i = 0; i < ARRAY_SIZE(status); i++) {
0270         unsigned int stat = status[i];
0271         if (!stat)
0272             continue;
0273 
0274         while (stat) {
0275             int bit = __ffs(stat);
0276             int line = i * 8 + bit;
0277             int irq = irq_find_mapping(tc3589x_gpio->chip.irq.domain,
0278                            line);
0279 
0280             handle_nested_irq(irq);
0281             stat &= ~(1 << bit);
0282         }
0283 
0284         tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]);
0285     }
0286 
0287     return IRQ_HANDLED;
0288 }
0289 
0290 static int tc3589x_gpio_probe(struct platform_device *pdev)
0291 {
0292     struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
0293     struct device_node *np = pdev->dev.of_node;
0294     struct tc3589x_gpio *tc3589x_gpio;
0295     struct gpio_irq_chip *girq;
0296     int ret;
0297     int irq;
0298 
0299     if (!np) {
0300         dev_err(&pdev->dev, "No Device Tree node found\n");
0301         return -EINVAL;
0302     }
0303 
0304     irq = platform_get_irq(pdev, 0);
0305     if (irq < 0)
0306         return irq;
0307 
0308     tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio),
0309                     GFP_KERNEL);
0310     if (!tc3589x_gpio)
0311         return -ENOMEM;
0312 
0313     mutex_init(&tc3589x_gpio->irq_lock);
0314 
0315     tc3589x_gpio->dev = &pdev->dev;
0316     tc3589x_gpio->tc3589x = tc3589x;
0317 
0318     tc3589x_gpio->chip = template_chip;
0319     tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
0320     tc3589x_gpio->chip.parent = &pdev->dev;
0321     tc3589x_gpio->chip.base = -1;
0322 
0323     girq = &tc3589x_gpio->chip.irq;
0324     girq->chip = &tc3589x_gpio_irq_chip;
0325     /* This will let us handle the parent IRQ in the driver */
0326     girq->parent_handler = NULL;
0327     girq->num_parents = 0;
0328     girq->parents = NULL;
0329     girq->default_type = IRQ_TYPE_NONE;
0330     girq->handler = handle_simple_irq;
0331     girq->threaded = true;
0332 
0333     /* Bring the GPIO module out of reset */
0334     ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
0335                    TC3589x_RSTCTRL_GPIRST, 0);
0336     if (ret < 0)
0337         return ret;
0338 
0339      /* For tc35894, have to disable Direct KBD interrupts,
0340       * else IRQST will always be 0x20, IRQN low level, can't
0341       * clear the irq status.
0342       * TODO: need more test on other tc3589x chip.
0343       *
0344       */
0345     ret = tc3589x_reg_write(tc3589x, TC3589x_DKBDMSK,
0346             TC3589x_DKBDMSK_ELINT | TC3589x_DKBDMSK_EINT);
0347     if (ret < 0)
0348         return ret;
0349 
0350     ret = devm_request_threaded_irq(&pdev->dev,
0351                     irq, NULL, tc3589x_gpio_irq,
0352                     IRQF_ONESHOT, "tc3589x-gpio",
0353                     tc3589x_gpio);
0354     if (ret) {
0355         dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
0356         return ret;
0357     }
0358 
0359     return devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, tc3589x_gpio);
0360 }
0361 
0362 static struct platform_driver tc3589x_gpio_driver = {
0363     .driver.name    = "tc3589x-gpio",
0364     .probe      = tc3589x_gpio_probe,
0365 };
0366 
0367 static int __init tc3589x_gpio_init(void)
0368 {
0369     return platform_driver_register(&tc3589x_gpio_driver);
0370 }
0371 subsys_initcall(tc3589x_gpio_init);