linux/drivers/gpio/gpio-pl061.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008, 2009 Provigent Ltd.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
   9 *
  10 * Data sheet: ARM DDI 0190B, September 2000
  11 */
  12#include <linux/spinlock.h>
  13#include <linux/errno.h>
  14#include <linux/module.h>
  15#include <linux/io.h>
  16#include <linux/ioport.h>
  17#include <linux/interrupt.h>
  18#include <linux/irq.h>
  19#include <linux/irqchip/chained_irq.h>
  20#include <linux/bitops.h>
  21#include <linux/gpio.h>
  22#include <linux/device.h>
  23#include <linux/amba/bus.h>
  24#include <linux/amba/pl061.h>
  25#include <linux/slab.h>
  26#include <linux/pinctrl/consumer.h>
  27#include <linux/pm.h>
  28
  29#define GPIODIR 0x400
  30#define GPIOIS  0x404
  31#define GPIOIBE 0x408
  32#define GPIOIEV 0x40C
  33#define GPIOIE  0x410
  34#define GPIORIS 0x414
  35#define GPIOMIS 0x418
  36#define GPIOIC  0x41C
  37
  38#define PL061_GPIO_NR   8
  39
  40#ifdef CONFIG_PM
  41struct pl061_context_save_regs {
  42        u8 gpio_data;
  43        u8 gpio_dir;
  44        u8 gpio_is;
  45        u8 gpio_ibe;
  46        u8 gpio_iev;
  47        u8 gpio_ie;
  48};
  49#endif
  50
  51struct pl061_gpio {
  52        spinlock_t              lock;
  53
  54        void __iomem            *base;
  55        struct gpio_chip        gc;
  56
  57#ifdef CONFIG_PM
  58        struct pl061_context_save_regs csave_regs;
  59#endif
  60};
  61
  62static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
  63{
  64        struct pl061_gpio *chip = gpiochip_get_data(gc);
  65        unsigned long flags;
  66        unsigned char gpiodir;
  67
  68        if (offset >= gc->ngpio)
  69                return -EINVAL;
  70
  71        spin_lock_irqsave(&chip->lock, flags);
  72        gpiodir = readb(chip->base + GPIODIR);
  73        gpiodir &= ~(BIT(offset));
  74        writeb(gpiodir, chip->base + GPIODIR);
  75        spin_unlock_irqrestore(&chip->lock, flags);
  76
  77        return 0;
  78}
  79
  80static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
  81                int value)
  82{
  83        struct pl061_gpio *chip = gpiochip_get_data(gc);
  84        unsigned long flags;
  85        unsigned char gpiodir;
  86
  87        if (offset >= gc->ngpio)
  88                return -EINVAL;
  89
  90        spin_lock_irqsave(&chip->lock, flags);
  91        writeb(!!value << offset, chip->base + (BIT(offset + 2)));
  92        gpiodir = readb(chip->base + GPIODIR);
  93        gpiodir |= BIT(offset);
  94        writeb(gpiodir, chip->base + GPIODIR);
  95
  96        /*
  97         * gpio value is set again, because pl061 doesn't allow to set value of
  98         * a gpio pin before configuring it in OUT mode.
  99         */
 100        writeb(!!value << offset, chip->base + (BIT(offset + 2)));
 101        spin_unlock_irqrestore(&chip->lock, flags);
 102
 103        return 0;
 104}
 105
 106static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
 107{
 108        struct pl061_gpio *chip = gpiochip_get_data(gc);
 109
 110        return !!readb(chip->base + (BIT(offset + 2)));
 111}
 112
 113static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
 114{
 115        struct pl061_gpio *chip = gpiochip_get_data(gc);
 116
 117        writeb(!!value << offset, chip->base + (BIT(offset + 2)));
 118}
 119
 120static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 121{
 122        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 123        struct pl061_gpio *chip = gpiochip_get_data(gc);
 124        int offset = irqd_to_hwirq(d);
 125        unsigned long flags;
 126        u8 gpiois, gpioibe, gpioiev;
 127        u8 bit = BIT(offset);
 128
 129        if (offset < 0 || offset >= PL061_GPIO_NR)
 130                return -EINVAL;
 131
 132        if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
 133            (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
 134        {
 135                dev_err(gc->parent,
 136                        "trying to configure line %d for both level and edge "
 137                        "detection, choose one!\n",
 138                        offset);
 139                return -EINVAL;
 140        }
 141
 142
 143        spin_lock_irqsave(&chip->lock, flags);
 144
 145        gpioiev = readb(chip->base + GPIOIEV);
 146        gpiois = readb(chip->base + GPIOIS);
 147        gpioibe = readb(chip->base + GPIOIBE);
 148
 149        if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
 150                bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
 151
 152                /* Disable edge detection */
 153                gpioibe &= ~bit;
 154                /* Enable level detection */
 155                gpiois |= bit;
 156                /* Select polarity */
 157                if (polarity)
 158                        gpioiev |= bit;
 159                else
 160                        gpioiev &= ~bit;
 161                irq_set_handler_locked(d, handle_level_irq);
 162                dev_dbg(gc->parent, "line %d: IRQ on %s level\n",
 163                        offset,
 164                        polarity ? "HIGH" : "LOW");
 165        } else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
 166                /* Disable level detection */
 167                gpiois &= ~bit;
 168                /* Select both edges, setting this makes GPIOEV be ignored */
 169                gpioibe |= bit;
 170                irq_set_handler_locked(d, handle_edge_irq);
 171                dev_dbg(gc->parent, "line %d: IRQ on both edges\n", offset);
 172        } else if ((trigger & IRQ_TYPE_EDGE_RISING) ||
 173                   (trigger & IRQ_TYPE_EDGE_FALLING)) {
 174                bool rising = trigger & IRQ_TYPE_EDGE_RISING;
 175
 176                /* Disable level detection */
 177                gpiois &= ~bit;
 178                /* Clear detection on both edges */
 179                gpioibe &= ~bit;
 180                /* Select edge */
 181                if (rising)
 182                        gpioiev |= bit;
 183                else
 184                        gpioiev &= ~bit;
 185                irq_set_handler_locked(d, handle_edge_irq);
 186                dev_dbg(gc->parent, "line %d: IRQ on %s edge\n",
 187                        offset,
 188                        rising ? "RISING" : "FALLING");
 189        } else {
 190                /* No trigger: disable everything */
 191                gpiois &= ~bit;
 192                gpioibe &= ~bit;
 193                gpioiev &= ~bit;
 194                irq_set_handler_locked(d, handle_bad_irq);
 195                dev_warn(gc->parent, "no trigger selected for line %d\n",
 196                         offset);
 197        }
 198
 199        writeb(gpiois, chip->base + GPIOIS);
 200        writeb(gpioibe, chip->base + GPIOIBE);
 201        writeb(gpioiev, chip->base + GPIOIEV);
 202
 203        spin_unlock_irqrestore(&chip->lock, flags);
 204
 205        return 0;
 206}
 207
 208static void pl061_irq_handler(struct irq_desc *desc)
 209{
 210        unsigned long pending;
 211        int offset;
 212        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 213        struct pl061_gpio *chip = gpiochip_get_data(gc);
 214        struct irq_chip *irqchip = irq_desc_get_chip(desc);
 215
 216        chained_irq_enter(irqchip, desc);
 217
 218        pending = readb(chip->base + GPIOMIS);
 219        if (pending) {
 220                for_each_set_bit(offset, &pending, PL061_GPIO_NR)
 221                        generic_handle_irq(irq_find_mapping(gc->irqdomain,
 222                                                            offset));
 223        }
 224
 225        chained_irq_exit(irqchip, desc);
 226}
 227
 228static void pl061_irq_mask(struct irq_data *d)
 229{
 230        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 231        struct pl061_gpio *chip = gpiochip_get_data(gc);
 232        u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 233        u8 gpioie;
 234
 235        spin_lock(&chip->lock);
 236        gpioie = readb(chip->base + GPIOIE) & ~mask;
 237        writeb(gpioie, chip->base + GPIOIE);
 238        spin_unlock(&chip->lock);
 239}
 240
 241static void pl061_irq_unmask(struct irq_data *d)
 242{
 243        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 244        struct pl061_gpio *chip = gpiochip_get_data(gc);
 245        u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 246        u8 gpioie;
 247
 248        spin_lock(&chip->lock);
 249        gpioie = readb(chip->base + GPIOIE) | mask;
 250        writeb(gpioie, chip->base + GPIOIE);
 251        spin_unlock(&chip->lock);
 252}
 253
 254/**
 255 * pl061_irq_ack() - ACK an edge IRQ
 256 * @d: IRQ data for this IRQ
 257 *
 258 * This gets called from the edge IRQ handler to ACK the edge IRQ
 259 * in the GPIOIC (interrupt-clear) register. For level IRQs this is
 260 * not needed: these go away when the level signal goes away.
 261 */
 262static void pl061_irq_ack(struct irq_data *d)
 263{
 264        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 265        struct pl061_gpio *chip = gpiochip_get_data(gc);
 266        u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 267
 268        spin_lock(&chip->lock);
 269        writeb(mask, chip->base + GPIOIC);
 270        spin_unlock(&chip->lock);
 271}
 272
 273static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
 274{
 275        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 276
 277        return irq_set_irq_wake(gc->irq_parent, state);
 278}
 279
 280static struct irq_chip pl061_irqchip = {
 281        .name           = "pl061",
 282        .irq_ack        = pl061_irq_ack,
 283        .irq_mask       = pl061_irq_mask,
 284        .irq_unmask     = pl061_irq_unmask,
 285        .irq_set_type   = pl061_irq_type,
 286        .irq_set_wake   = pl061_irq_set_wake,
 287};
 288
 289static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 290{
 291        struct device *dev = &adev->dev;
 292        struct pl061_platform_data *pdata = dev_get_platdata(dev);
 293        struct pl061_gpio *chip;
 294        int ret, irq, i, irq_base;
 295
 296        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 297        if (chip == NULL)
 298                return -ENOMEM;
 299
 300        if (pdata) {
 301                chip->gc.base = pdata->gpio_base;
 302                irq_base = pdata->irq_base;
 303                if (irq_base <= 0) {
 304                        dev_err(&adev->dev, "invalid IRQ base in pdata\n");
 305                        return -ENODEV;
 306                }
 307        } else {
 308                chip->gc.base = -1;
 309                irq_base = 0;
 310        }
 311
 312        chip->base = devm_ioremap_resource(dev, &adev->res);
 313        if (IS_ERR(chip->base))
 314                return PTR_ERR(chip->base);
 315
 316        spin_lock_init(&chip->lock);
 317        if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 318                chip->gc.request = gpiochip_generic_request;
 319                chip->gc.free = gpiochip_generic_free;
 320        }
 321
 322        chip->gc.direction_input = pl061_direction_input;
 323        chip->gc.direction_output = pl061_direction_output;
 324        chip->gc.get = pl061_get_value;
 325        chip->gc.set = pl061_set_value;
 326        chip->gc.ngpio = PL061_GPIO_NR;
 327        chip->gc.label = dev_name(dev);
 328        chip->gc.parent = dev;
 329        chip->gc.owner = THIS_MODULE;
 330
 331        ret = gpiochip_add_data(&chip->gc, chip);
 332        if (ret)
 333                return ret;
 334
 335        /*
 336         * irq_chip support
 337         */
 338        writeb(0, chip->base + GPIOIE); /* disable irqs */
 339        irq = adev->irq[0];
 340        if (irq < 0) {
 341                dev_err(&adev->dev, "invalid IRQ\n");
 342                return -ENODEV;
 343        }
 344
 345        ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip,
 346                                   irq_base, handle_bad_irq,
 347                                   IRQ_TYPE_NONE);
 348        if (ret) {
 349                dev_info(&adev->dev, "could not add irqchip\n");
 350                return ret;
 351        }
 352        gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip,
 353                                     irq, pl061_irq_handler);
 354
 355        for (i = 0; i < PL061_GPIO_NR; i++) {
 356                if (pdata) {
 357                        if (pdata->directions & (BIT(i)))
 358                                pl061_direction_output(&chip->gc, i,
 359                                                pdata->values & (BIT(i)));
 360                        else
 361                                pl061_direction_input(&chip->gc, i);
 362                }
 363        }
 364
 365        amba_set_drvdata(adev, chip);
 366        dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n",
 367                 &adev->res.start);
 368
 369        return 0;
 370}
 371
 372#ifdef CONFIG_PM
 373static int pl061_suspend(struct device *dev)
 374{
 375        struct pl061_gpio *chip = dev_get_drvdata(dev);
 376        int offset;
 377
 378        chip->csave_regs.gpio_data = 0;
 379        chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR);
 380        chip->csave_regs.gpio_is = readb(chip->base + GPIOIS);
 381        chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE);
 382        chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV);
 383        chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
 384
 385        for (offset = 0; offset < PL061_GPIO_NR; offset++) {
 386                if (chip->csave_regs.gpio_dir & (BIT(offset)))
 387                        chip->csave_regs.gpio_data |=
 388                                pl061_get_value(&chip->gc, offset) << offset;
 389        }
 390
 391        return 0;
 392}
 393
 394static int pl061_resume(struct device *dev)
 395{
 396        struct pl061_gpio *chip = dev_get_drvdata(dev);
 397        int offset;
 398
 399        for (offset = 0; offset < PL061_GPIO_NR; offset++) {
 400                if (chip->csave_regs.gpio_dir & (BIT(offset)))
 401                        pl061_direction_output(&chip->gc, offset,
 402                                        chip->csave_regs.gpio_data &
 403                                        (BIT(offset)));
 404                else
 405                        pl061_direction_input(&chip->gc, offset);
 406        }
 407
 408        writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS);
 409        writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE);
 410        writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV);
 411        writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE);
 412
 413        return 0;
 414}
 415
 416static const struct dev_pm_ops pl061_dev_pm_ops = {
 417        .suspend = pl061_suspend,
 418        .resume = pl061_resume,
 419        .freeze = pl061_suspend,
 420        .restore = pl061_resume,
 421};
 422#endif
 423
 424static struct amba_id pl061_ids[] = {
 425        {
 426                .id     = 0x00041061,
 427                .mask   = 0x000fffff,
 428        },
 429        { 0, 0 },
 430};
 431
 432MODULE_DEVICE_TABLE(amba, pl061_ids);
 433
 434static struct amba_driver pl061_gpio_driver = {
 435        .drv = {
 436                .name   = "pl061_gpio",
 437#ifdef CONFIG_PM
 438                .pm     = &pl061_dev_pm_ops,
 439#endif
 440        },
 441        .id_table       = pl061_ids,
 442        .probe          = pl061_probe,
 443};
 444
 445static int __init pl061_gpio_init(void)
 446{
 447        return amba_driver_register(&pl061_gpio_driver);
 448}
 449module_init(pl061_gpio_init);
 450
 451MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
 452MODULE_DESCRIPTION("PL061 GPIO driver");
 453MODULE_LICENSE("GPL");
 454