linux/drivers/gpio/gpio-em.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Emma Mobile GPIO Support - GIO
   4 *
   5 *  Copyright (C) 2012 Magnus Damm
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/platform_device.h>
  10#include <linux/spinlock.h>
  11#include <linux/interrupt.h>
  12#include <linux/ioport.h>
  13#include <linux/io.h>
  14#include <linux/irq.h>
  15#include <linux/irqdomain.h>
  16#include <linux/bitops.h>
  17#include <linux/err.h>
  18#include <linux/gpio/driver.h>
  19#include <linux/slab.h>
  20#include <linux/module.h>
  21#include <linux/pinctrl/consumer.h>
  22
  23struct em_gio_priv {
  24        void __iomem *base0;
  25        void __iomem *base1;
  26        spinlock_t sense_lock;
  27        struct platform_device *pdev;
  28        struct gpio_chip gpio_chip;
  29        struct irq_chip irq_chip;
  30        struct irq_domain *irq_domain;
  31};
  32
  33#define GIO_E1 0x00
  34#define GIO_E0 0x04
  35#define GIO_EM 0x04
  36#define GIO_OL 0x08
  37#define GIO_OH 0x0c
  38#define GIO_I 0x10
  39#define GIO_IIA 0x14
  40#define GIO_IEN 0x18
  41#define GIO_IDS 0x1c
  42#define GIO_IIM 0x1c
  43#define GIO_RAW 0x20
  44#define GIO_MST 0x24
  45#define GIO_IIR 0x28
  46
  47#define GIO_IDT0 0x40
  48#define GIO_IDT1 0x44
  49#define GIO_IDT2 0x48
  50#define GIO_IDT3 0x4c
  51#define GIO_RAWBL 0x50
  52#define GIO_RAWBH 0x54
  53#define GIO_IRBL 0x58
  54#define GIO_IRBH 0x5c
  55
  56#define GIO_IDT(n) (GIO_IDT0 + ((n) * 4))
  57
  58static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs)
  59{
  60        if (offs < GIO_IDT0)
  61                return ioread32(p->base0 + offs);
  62        else
  63                return ioread32(p->base1 + (offs - GIO_IDT0));
  64}
  65
  66static inline void em_gio_write(struct em_gio_priv *p, int offs,
  67                                unsigned long value)
  68{
  69        if (offs < GIO_IDT0)
  70                iowrite32(value, p->base0 + offs);
  71        else
  72                iowrite32(value, p->base1 + (offs - GIO_IDT0));
  73}
  74
  75static void em_gio_irq_disable(struct irq_data *d)
  76{
  77        struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  78
  79        em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
  80}
  81
  82static void em_gio_irq_enable(struct irq_data *d)
  83{
  84        struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  85
  86        em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
  87}
  88
  89static int em_gio_irq_reqres(struct irq_data *d)
  90{
  91        struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  92        int ret;
  93
  94        ret = gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
  95        if (ret) {
  96                dev_err(p->gpio_chip.parent,
  97                        "unable to lock HW IRQ %lu for IRQ\n",
  98                        irqd_to_hwirq(d));
  99                return ret;
 100        }
 101        return 0;
 102}
 103
 104static void em_gio_irq_relres(struct irq_data *d)
 105{
 106        struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 107
 108        gpiochip_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
 109}
 110
 111
 112#define GIO_ASYNC(x) (x + 8)
 113
 114static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
 115        [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00),
 116        [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01),
 117        [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02),
 118        [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03),
 119        [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04),
 120};
 121
 122static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
 123{
 124        unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
 125        struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 126        unsigned int reg, offset, shift;
 127        unsigned long flags;
 128        unsigned long tmp;
 129
 130        if (!value)
 131                return -EINVAL;
 132
 133        offset = irqd_to_hwirq(d);
 134
 135        pr_debug("gio: sense irq = %d, mode = %d\n", offset, value);
 136
 137        /* 8 x 4 bit fields in 4 IDT registers */
 138        reg = GIO_IDT(offset >> 3);
 139        shift = (offset & 0x07) << 4;
 140
 141        spin_lock_irqsave(&p->sense_lock, flags);
 142
 143        /* disable the interrupt in IIA */
 144        tmp = em_gio_read(p, GIO_IIA);
 145        tmp &= ~BIT(offset);
 146        em_gio_write(p, GIO_IIA, tmp);
 147
 148        /* change the sense setting in IDT */
 149        tmp = em_gio_read(p, reg);
 150        tmp &= ~(0xf << shift);
 151        tmp |= value << shift;
 152        em_gio_write(p, reg, tmp);
 153
 154        /* clear pending interrupts */
 155        em_gio_write(p, GIO_IIR, BIT(offset));
 156
 157        /* enable the interrupt in IIA */
 158        tmp = em_gio_read(p, GIO_IIA);
 159        tmp |= BIT(offset);
 160        em_gio_write(p, GIO_IIA, tmp);
 161
 162        spin_unlock_irqrestore(&p->sense_lock, flags);
 163
 164        return 0;
 165}
 166
 167static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
 168{
 169        struct em_gio_priv *p = dev_id;
 170        unsigned long pending;
 171        unsigned int offset, irqs_handled = 0;
 172
 173        while ((pending = em_gio_read(p, GIO_MST))) {
 174                offset = __ffs(pending);
 175                em_gio_write(p, GIO_IIR, BIT(offset));
 176                generic_handle_domain_irq(p->irq_domain, offset);
 177                irqs_handled++;
 178        }
 179
 180        return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
 181}
 182
 183static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip)
 184{
 185        return gpiochip_get_data(chip);
 186}
 187
 188static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset)
 189{
 190        em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset));
 191        return 0;
 192}
 193
 194static int em_gio_get(struct gpio_chip *chip, unsigned offset)
 195{
 196        return !!(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset));
 197}
 198
 199static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
 200                         unsigned shift, int value)
 201{
 202        /* upper 16 bits contains mask and lower 16 actual value */
 203        em_gio_write(gpio_to_priv(chip), reg,
 204                     (BIT(shift + 16)) | (value << shift));
 205}
 206
 207static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
 208{
 209        /* output is split into two registers */
 210        if (offset < 16)
 211                __em_gio_set(chip, GIO_OL, offset, value);
 212        else
 213                __em_gio_set(chip, GIO_OH, offset - 16, value);
 214}
 215
 216static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
 217                                   int value)
 218{
 219        /* write GPIO value to output before selecting output mode of pin */
 220        em_gio_set(chip, offset, value);
 221        em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset));
 222        return 0;
 223}
 224
 225static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
 226{
 227        return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 228}
 229
 230static int em_gio_request(struct gpio_chip *chip, unsigned offset)
 231{
 232        return pinctrl_gpio_request(chip->base + offset);
 233}
 234
 235static void em_gio_free(struct gpio_chip *chip, unsigned offset)
 236{
 237        pinctrl_gpio_free(chip->base + offset);
 238
 239        /* Set the GPIO as an input to ensure that the next GPIO request won't
 240        * drive the GPIO pin as an output.
 241        */
 242        em_gio_direction_input(chip, offset);
 243}
 244
 245static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq,
 246                                 irq_hw_number_t hwirq)
 247{
 248        struct em_gio_priv *p = h->host_data;
 249
 250        pr_debug("gio: map hw irq = %d, irq = %d\n", (int)hwirq, irq);
 251
 252        irq_set_chip_data(irq, h->host_data);
 253        irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
 254        return 0;
 255}
 256
 257static const struct irq_domain_ops em_gio_irq_domain_ops = {
 258        .map    = em_gio_irq_domain_map,
 259        .xlate  = irq_domain_xlate_twocell,
 260};
 261
 262static void em_gio_irq_domain_remove(void *data)
 263{
 264        struct irq_domain *domain = data;
 265
 266        irq_domain_remove(domain);
 267}
 268
 269static int em_gio_probe(struct platform_device *pdev)
 270{
 271        struct em_gio_priv *p;
 272        struct gpio_chip *gpio_chip;
 273        struct irq_chip *irq_chip;
 274        struct device *dev = &pdev->dev;
 275        const char *name = dev_name(dev);
 276        unsigned int ngpios;
 277        int irq[2], ret;
 278
 279        p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
 280        if (!p)
 281                return -ENOMEM;
 282
 283        p->pdev = pdev;
 284        platform_set_drvdata(pdev, p);
 285        spin_lock_init(&p->sense_lock);
 286
 287        irq[0] = platform_get_irq(pdev, 0);
 288        if (irq[0] < 0)
 289                return irq[0];
 290
 291        irq[1] = platform_get_irq(pdev, 1);
 292        if (irq[1] < 0)
 293                return irq[1];
 294
 295        p->base0 = devm_platform_ioremap_resource(pdev, 0);
 296        if (IS_ERR(p->base0))
 297                return PTR_ERR(p->base0);
 298
 299        p->base1 = devm_platform_ioremap_resource(pdev, 1);
 300        if (IS_ERR(p->base1))
 301                return PTR_ERR(p->base1);
 302
 303        if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
 304                dev_err(dev, "Missing ngpios OF property\n");
 305                return -EINVAL;
 306        }
 307
 308        gpio_chip = &p->gpio_chip;
 309        gpio_chip->of_node = dev->of_node;
 310        gpio_chip->direction_input = em_gio_direction_input;
 311        gpio_chip->get = em_gio_get;
 312        gpio_chip->direction_output = em_gio_direction_output;
 313        gpio_chip->set = em_gio_set;
 314        gpio_chip->to_irq = em_gio_to_irq;
 315        gpio_chip->request = em_gio_request;
 316        gpio_chip->free = em_gio_free;
 317        gpio_chip->label = name;
 318        gpio_chip->parent = dev;
 319        gpio_chip->owner = THIS_MODULE;
 320        gpio_chip->base = -1;
 321        gpio_chip->ngpio = ngpios;
 322
 323        irq_chip = &p->irq_chip;
 324        irq_chip->name = "gpio-em";
 325        irq_chip->irq_mask = em_gio_irq_disable;
 326        irq_chip->irq_unmask = em_gio_irq_enable;
 327        irq_chip->irq_set_type = em_gio_irq_set_type;
 328        irq_chip->irq_request_resources = em_gio_irq_reqres;
 329        irq_chip->irq_release_resources = em_gio_irq_relres;
 330        irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
 331
 332        p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0,
 333                                              &em_gio_irq_domain_ops, p);
 334        if (!p->irq_domain) {
 335                dev_err(dev, "cannot initialize irq domain\n");
 336                return -ENXIO;
 337        }
 338
 339        ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove,
 340                                       p->irq_domain);
 341        if (ret)
 342                return ret;
 343
 344        if (devm_request_irq(dev, irq[0], em_gio_irq_handler, 0, name, p)) {
 345                dev_err(dev, "failed to request low IRQ\n");
 346                return -ENOENT;
 347        }
 348
 349        if (devm_request_irq(dev, irq[1], em_gio_irq_handler, 0, name, p)) {
 350                dev_err(dev, "failed to request high IRQ\n");
 351                return -ENOENT;
 352        }
 353
 354        ret = devm_gpiochip_add_data(dev, gpio_chip, p);
 355        if (ret) {
 356                dev_err(dev, "failed to add GPIO controller\n");
 357                return ret;
 358        }
 359
 360        return 0;
 361}
 362
 363static const struct of_device_id em_gio_dt_ids[] = {
 364        { .compatible = "renesas,em-gio", },
 365        {},
 366};
 367MODULE_DEVICE_TABLE(of, em_gio_dt_ids);
 368
 369static struct platform_driver em_gio_device_driver = {
 370        .probe          = em_gio_probe,
 371        .driver         = {
 372                .name   = "em_gio",
 373                .of_match_table = em_gio_dt_ids,
 374        }
 375};
 376
 377static int __init em_gio_init(void)
 378{
 379        return platform_driver_register(&em_gio_device_driver);
 380}
 381postcore_initcall(em_gio_init);
 382
 383static void __exit em_gio_exit(void)
 384{
 385        platform_driver_unregister(&em_gio_device_driver);
 386}
 387module_exit(em_gio_exit);
 388
 389MODULE_AUTHOR("Magnus Damm");
 390MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
 391MODULE_LICENSE("GPL v2");
 392