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_irq(irq_find_mapping(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 resource *io[2], *irq[2];
 273        struct gpio_chip *gpio_chip;
 274        struct irq_chip *irq_chip;
 275        const char *name = dev_name(&pdev->dev);
 276        unsigned int ngpios;
 277        int ret;
 278
 279        p = devm_kzalloc(&pdev->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        io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 288        io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 289        irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 290        irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
 291
 292        if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
 293                dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
 294                return -EINVAL;
 295        }
 296
 297        p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start,
 298                                        resource_size(io[0]));
 299        if (!p->base0)
 300                return -ENOMEM;
 301
 302        p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start,
 303                                   resource_size(io[1]));
 304        if (!p->base1)
 305                return -ENOMEM;
 306
 307        if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
 308                dev_err(&pdev->dev, "Missing ngpios OF property\n");
 309                return -EINVAL;
 310        }
 311
 312        gpio_chip = &p->gpio_chip;
 313        gpio_chip->of_node = pdev->dev.of_node;
 314        gpio_chip->direction_input = em_gio_direction_input;
 315        gpio_chip->get = em_gio_get;
 316        gpio_chip->direction_output = em_gio_direction_output;
 317        gpio_chip->set = em_gio_set;
 318        gpio_chip->to_irq = em_gio_to_irq;
 319        gpio_chip->request = em_gio_request;
 320        gpio_chip->free = em_gio_free;
 321        gpio_chip->label = name;
 322        gpio_chip->parent = &pdev->dev;
 323        gpio_chip->owner = THIS_MODULE;
 324        gpio_chip->base = -1;
 325        gpio_chip->ngpio = ngpios;
 326
 327        irq_chip = &p->irq_chip;
 328        irq_chip->name = name;
 329        irq_chip->irq_mask = em_gio_irq_disable;
 330        irq_chip->irq_unmask = em_gio_irq_enable;
 331        irq_chip->irq_set_type = em_gio_irq_set_type;
 332        irq_chip->irq_request_resources = em_gio_irq_reqres;
 333        irq_chip->irq_release_resources = em_gio_irq_relres;
 334        irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
 335
 336        p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0,
 337                                              &em_gio_irq_domain_ops, p);
 338        if (!p->irq_domain) {
 339                dev_err(&pdev->dev, "cannot initialize irq domain\n");
 340                return -ENXIO;
 341        }
 342
 343        ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove,
 344                                       p->irq_domain);
 345        if (ret)
 346                return ret;
 347
 348        if (devm_request_irq(&pdev->dev, irq[0]->start,
 349                             em_gio_irq_handler, 0, name, p)) {
 350                dev_err(&pdev->dev, "failed to request low IRQ\n");
 351                return -ENOENT;
 352        }
 353
 354        if (devm_request_irq(&pdev->dev, irq[1]->start,
 355                             em_gio_irq_handler, 0, name, p)) {
 356                dev_err(&pdev->dev, "failed to request high IRQ\n");
 357                return -ENOENT;
 358        }
 359
 360        ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p);
 361        if (ret) {
 362                dev_err(&pdev->dev, "failed to add GPIO controller\n");
 363                return ret;
 364        }
 365
 366        return 0;
 367}
 368
 369static const struct of_device_id em_gio_dt_ids[] = {
 370        { .compatible = "renesas,em-gio", },
 371        {},
 372};
 373MODULE_DEVICE_TABLE(of, em_gio_dt_ids);
 374
 375static struct platform_driver em_gio_device_driver = {
 376        .probe          = em_gio_probe,
 377        .driver         = {
 378                .name   = "em_gio",
 379                .of_match_table = em_gio_dt_ids,
 380        }
 381};
 382
 383static int __init em_gio_init(void)
 384{
 385        return platform_driver_register(&em_gio_device_driver);
 386}
 387postcore_initcall(em_gio_init);
 388
 389static void __exit em_gio_exit(void)
 390{
 391        platform_driver_unregister(&em_gio_device_driver);
 392}
 393module_exit(em_gio_exit);
 394
 395MODULE_AUTHOR("Magnus Damm");
 396MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
 397MODULE_LICENSE("GPL v2");
 398