linux/drivers/gpio/gpio-ingenic.c
<<
>>
Prefs
   1/*
   2 * Ingenic JZ47xx GPIO driver
   3 *
   4 * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
   5 *
   6 * License terms: GNU General Public License (GPL) version 2
   7 */
   8
   9#include <linux/gpio/driver.h>
  10#include <linux/interrupt.h>
  11#include <linux/io.h>
  12#include <linux/module.h>
  13#include <linux/of_address.h>
  14#include <linux/of_device.h>
  15#include <linux/of_irq.h>
  16#include <linux/pinctrl/consumer.h>
  17#include <linux/regmap.h>
  18
  19#define GPIO_PIN        0x00
  20#define GPIO_MSK        0x20
  21
  22#define JZ4740_GPIO_DATA        0x10
  23#define JZ4740_GPIO_SELECT      0x50
  24#define JZ4740_GPIO_DIR         0x60
  25#define JZ4740_GPIO_TRIG        0x70
  26#define JZ4740_GPIO_FLAG        0x80
  27
  28#define JZ4770_GPIO_INT         0x10
  29#define JZ4770_GPIO_PAT1        0x30
  30#define JZ4770_GPIO_PAT0        0x40
  31#define JZ4770_GPIO_FLAG        0x50
  32
  33#define REG_SET(x) ((x) + 0x4)
  34#define REG_CLEAR(x) ((x) + 0x8)
  35
  36enum jz_version {
  37        ID_JZ4740,
  38        ID_JZ4770,
  39        ID_JZ4780,
  40};
  41
  42struct ingenic_gpio_chip {
  43        struct regmap *map;
  44        struct gpio_chip gc;
  45        struct irq_chip irq_chip;
  46        unsigned int irq, reg_base;
  47        enum jz_version version;
  48};
  49
  50static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
  51{
  52        unsigned int val;
  53
  54        regmap_read(jzgc->map, jzgc->reg_base + reg, &val);
  55
  56        return (u32) val;
  57}
  58
  59static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc,
  60                u8 reg, u8 offset, bool set)
  61{
  62        if (set)
  63                reg = REG_SET(reg);
  64        else
  65                reg = REG_CLEAR(reg);
  66
  67        regmap_write(jzgc->map, jzgc->reg_base + reg, BIT(offset));
  68}
  69
  70static inline bool gpio_get_value(struct ingenic_gpio_chip *jzgc, u8 offset)
  71{
  72        unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN);
  73
  74        return !!(val & BIT(offset));
  75}
  76
  77static void gpio_set_value(struct ingenic_gpio_chip *jzgc, u8 offset, int value)
  78{
  79        if (jzgc->version >= ID_JZ4770)
  80                gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
  81        else
  82                gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
  83}
  84
  85static void irq_set_type(struct ingenic_gpio_chip *jzgc,
  86                u8 offset, unsigned int type)
  87{
  88        u8 reg1, reg2;
  89
  90        if (jzgc->version >= ID_JZ4770) {
  91                reg1 = JZ4770_GPIO_PAT1;
  92                reg2 = JZ4770_GPIO_PAT0;
  93        } else {
  94                reg1 = JZ4740_GPIO_TRIG;
  95                reg2 = JZ4740_GPIO_DIR;
  96        }
  97
  98        switch (type) {
  99        case IRQ_TYPE_EDGE_RISING:
 100                gpio_ingenic_set_bit(jzgc, reg2, offset, true);
 101                gpio_ingenic_set_bit(jzgc, reg1, offset, true);
 102                break;
 103        case IRQ_TYPE_EDGE_FALLING:
 104                gpio_ingenic_set_bit(jzgc, reg2, offset, false);
 105                gpio_ingenic_set_bit(jzgc, reg1, offset, true);
 106                break;
 107        case IRQ_TYPE_LEVEL_HIGH:
 108                gpio_ingenic_set_bit(jzgc, reg2, offset, true);
 109                gpio_ingenic_set_bit(jzgc, reg1, offset, false);
 110                break;
 111        case IRQ_TYPE_LEVEL_LOW:
 112        default:
 113                gpio_ingenic_set_bit(jzgc, reg2, offset, false);
 114                gpio_ingenic_set_bit(jzgc, reg1, offset, false);
 115                break;
 116        }
 117}
 118
 119static void ingenic_gpio_irq_mask(struct irq_data *irqd)
 120{
 121        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 122        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 123
 124        gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true);
 125}
 126
 127static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
 128{
 129        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 130        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 131
 132        gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false);
 133}
 134
 135static void ingenic_gpio_irq_enable(struct irq_data *irqd)
 136{
 137        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 138        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 139        int irq = irqd->hwirq;
 140
 141        if (jzgc->version >= ID_JZ4770)
 142                gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
 143        else
 144                gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
 145
 146        ingenic_gpio_irq_unmask(irqd);
 147}
 148
 149static void ingenic_gpio_irq_disable(struct irq_data *irqd)
 150{
 151        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 152        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 153        int irq = irqd->hwirq;
 154
 155        ingenic_gpio_irq_mask(irqd);
 156
 157        if (jzgc->version >= ID_JZ4770)
 158                gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
 159        else
 160                gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
 161}
 162
 163static void ingenic_gpio_irq_ack(struct irq_data *irqd)
 164{
 165        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 166        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 167        int irq = irqd->hwirq;
 168        bool high;
 169
 170        if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
 171                /*
 172                 * Switch to an interrupt for the opposite edge to the one that
 173                 * triggered the interrupt being ACKed.
 174                 */
 175                high = gpio_get_value(jzgc, irq);
 176                if (high)
 177                        irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
 178                else
 179                        irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
 180        }
 181
 182        if (jzgc->version >= ID_JZ4770)
 183                gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
 184        else
 185                gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
 186}
 187
 188static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 189{
 190        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 191        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 192
 193        switch (type) {
 194        case IRQ_TYPE_EDGE_BOTH:
 195        case IRQ_TYPE_EDGE_RISING:
 196        case IRQ_TYPE_EDGE_FALLING:
 197                irq_set_handler_locked(irqd, handle_edge_irq);
 198                break;
 199        case IRQ_TYPE_LEVEL_HIGH:
 200        case IRQ_TYPE_LEVEL_LOW:
 201                irq_set_handler_locked(irqd, handle_level_irq);
 202                break;
 203        default:
 204                irq_set_handler_locked(irqd, handle_bad_irq);
 205        }
 206
 207        if (type == IRQ_TYPE_EDGE_BOTH) {
 208                /*
 209                 * The hardware does not support interrupts on both edges. The
 210                 * best we can do is to set up a single-edge interrupt and then
 211                 * switch to the opposing edge when ACKing the interrupt.
 212                 */
 213                bool high = gpio_get_value(jzgc, irqd->hwirq);
 214
 215                type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
 216        }
 217
 218        irq_set_type(jzgc, irqd->hwirq, type);
 219        return 0;
 220}
 221
 222static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
 223{
 224        struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
 225        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 226
 227        return irq_set_irq_wake(jzgc->irq, on);
 228}
 229
 230static void ingenic_gpio_irq_handler(struct irq_desc *desc)
 231{
 232        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 233        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 234        struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
 235        unsigned long flag, i;
 236
 237        chained_irq_enter(irq_chip, desc);
 238
 239        if (jzgc->version >= ID_JZ4770)
 240                flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG);
 241        else
 242                flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
 243
 244        for_each_set_bit(i, &flag, 32)
 245                generic_handle_irq(irq_linear_revmap(gc->irqdomain, i));
 246        chained_irq_exit(irq_chip, desc);
 247}
 248
 249static void ingenic_gpio_set(struct gpio_chip *gc,
 250                unsigned int offset, int value)
 251{
 252        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 253
 254        gpio_set_value(jzgc, offset, value);
 255}
 256
 257static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
 258{
 259        struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 260
 261        return (int) gpio_get_value(jzgc, offset);
 262}
 263
 264static int ingenic_gpio_direction_input(struct gpio_chip *gc,
 265                unsigned int offset)
 266{
 267        return pinctrl_gpio_direction_input(gc->base + offset);
 268}
 269
 270static int ingenic_gpio_direction_output(struct gpio_chip *gc,
 271                unsigned int offset, int value)
 272{
 273        ingenic_gpio_set(gc, offset, value);
 274        return pinctrl_gpio_direction_output(gc->base + offset);
 275}
 276
 277static const struct of_device_id ingenic_gpio_of_match[] = {
 278        { .compatible = "ingenic,jz4740-gpio", .data = (void *)ID_JZ4740 },
 279        { .compatible = "ingenic,jz4770-gpio", .data = (void *)ID_JZ4770 },
 280        { .compatible = "ingenic,jz4780-gpio", .data = (void *)ID_JZ4780 },
 281        {},
 282};
 283MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match);
 284
 285static int ingenic_gpio_probe(struct platform_device *pdev)
 286{
 287        struct device *dev = &pdev->dev;
 288        const struct of_device_id *of_id = of_match_device(
 289                        ingenic_gpio_of_match, dev);
 290        struct ingenic_gpio_chip *jzgc;
 291        u32 bank;
 292        int err;
 293
 294        jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
 295        if (!jzgc)
 296                return -ENOMEM;
 297
 298        jzgc->map = dev_get_drvdata(dev->parent);
 299        if (!jzgc->map) {
 300                dev_err(dev, "Cannot get parent regmap\n");
 301                return -ENXIO;
 302        }
 303
 304        err = of_property_read_u32(dev->of_node, "reg", &bank);
 305        if (err) {
 306                dev_err(dev, "Cannot read \"reg\" property: %i\n", err);
 307                return err;
 308        }
 309
 310        jzgc->reg_base = bank * 0x100;
 311
 312        jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank);
 313        if (!jzgc->gc.label)
 314                return -ENOMEM;
 315
 316        /* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY
 317         * ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN
 318         * <linux/gpio/consumer.h> INSTEAD.
 319         */
 320        jzgc->gc.base = bank * 32;
 321
 322        jzgc->gc.ngpio = 32;
 323        jzgc->gc.parent = dev;
 324        jzgc->gc.of_node = dev->of_node;
 325        jzgc->gc.owner = THIS_MODULE;
 326        jzgc->version = (enum jz_version)of_id->data;
 327
 328        jzgc->gc.set = ingenic_gpio_set;
 329        jzgc->gc.get = ingenic_gpio_get;
 330        jzgc->gc.direction_input = ingenic_gpio_direction_input;
 331        jzgc->gc.direction_output = ingenic_gpio_direction_output;
 332
 333        if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 334                jzgc->gc.request = gpiochip_generic_request;
 335                jzgc->gc.free = gpiochip_generic_free;
 336        }
 337
 338        err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
 339        if (err)
 340                return err;
 341
 342        jzgc->irq = irq_of_parse_and_map(dev->of_node, 0);
 343        if (!jzgc->irq)
 344                return -EINVAL;
 345
 346        jzgc->irq_chip.name = jzgc->gc.label;
 347        jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
 348        jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
 349        jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
 350        jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
 351        jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
 352        jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
 353        jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
 354        jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
 355
 356        err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
 357                        handle_level_irq, IRQ_TYPE_NONE);
 358        if (err)
 359                return err;
 360
 361        gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
 362                        jzgc->irq, ingenic_gpio_irq_handler);
 363        return 0;
 364}
 365
 366static int ingenic_gpio_remove(struct platform_device *pdev)
 367{
 368        return 0;
 369}
 370
 371static struct platform_driver ingenic_gpio_driver = {
 372        .driver = {
 373                .name = "gpio-ingenic",
 374                .of_match_table = of_match_ptr(ingenic_gpio_of_match),
 375        },
 376        .probe = ingenic_gpio_probe,
 377        .remove = ingenic_gpio_remove,
 378};
 379
 380static int __init ingenic_gpio_drv_register(void)
 381{
 382        return platform_driver_register(&ingenic_gpio_driver);
 383}
 384subsys_initcall(ingenic_gpio_drv_register);
 385
 386static void __exit ingenic_gpio_drv_unregister(void)
 387{
 388        platform_driver_unregister(&ingenic_gpio_driver);
 389}
 390module_exit(ingenic_gpio_drv_unregister);
 391
 392MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 393MODULE_DESCRIPTION("Ingenic JZ47xx GPIO driver");
 394MODULE_LICENSE("GPL");
 395