linux/drivers/gpio/gpio-msic.c
<<
>>
Prefs
   1/*
   2 * Intel Medfield MSIC GPIO driver>
   3 * Copyright (c) 2011, Intel Corporation.
   4 *
   5 * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
   6 * Based on intel_pmic_gpio.c
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms and conditions of the GNU General Public License,
  10 * version 2, as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along with
  18 * this program; if not, write to the Free Software Foundation, Inc.,
  19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  20 *
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/kernel.h>
  25#include <linux/slab.h>
  26#include <linux/interrupt.h>
  27#include <linux/init.h>
  28#include <linux/gpio.h>
  29#include <linux/platform_device.h>
  30#include <linux/mfd/intel_msic.h>
  31
  32/* the offset for the mapping of global gpio pin to irq */
  33#define MSIC_GPIO_IRQ_OFFSET    0x100
  34
  35#define MSIC_GPIO_DIR_IN        0
  36#define MSIC_GPIO_DIR_OUT       BIT(5)
  37#define MSIC_GPIO_TRIG_FALL     BIT(1)
  38#define MSIC_GPIO_TRIG_RISE     BIT(2)
  39
  40/* masks for msic gpio output GPIOxxxxCTLO registers */
  41#define MSIC_GPIO_DIR_MASK      BIT(5)
  42#define MSIC_GPIO_DRV_MASK      BIT(4)
  43#define MSIC_GPIO_REN_MASK      BIT(3)
  44#define MSIC_GPIO_RVAL_MASK     (BIT(2) | BIT(1))
  45#define MSIC_GPIO_DOUT_MASK     BIT(0)
  46
  47/* masks for msic gpio input GPIOxxxxCTLI registers */
  48#define MSIC_GPIO_GLBYP_MASK    BIT(5)
  49#define MSIC_GPIO_DBNC_MASK     (BIT(4) | BIT(3))
  50#define MSIC_GPIO_INTCNT_MASK   (BIT(2) | BIT(1))
  51#define MSIC_GPIO_DIN_MASK      BIT(0)
  52
  53#define MSIC_NUM_GPIO           24
  54
  55struct msic_gpio {
  56        struct platform_device  *pdev;
  57        struct mutex            buslock;
  58        struct gpio_chip        chip;
  59        int                     irq;
  60        unsigned                irq_base;
  61        unsigned long           trig_change_mask;
  62        unsigned                trig_type;
  63};
  64
  65/*
  66 * MSIC has 24 gpios, 16 low voltage (1.2-1.8v) and 8 high voltage (3v).
  67 * Both the high and low voltage gpios are divided in two banks.
  68 * GPIOs are numbered with GPIO0LV0 as gpio_base in the following order:
  69 * GPIO0LV0..GPIO0LV7: low voltage, bank 0, gpio_base
  70 * GPIO1LV0..GPIO1LV7: low voltage, bank 1,  gpio_base + 8
  71 * GPIO0HV0..GPIO0HV3: high voltage, bank 0, gpio_base + 16
  72 * GPIO1HV0..GPIO1HV3: high voltage, bank 1, gpio_base + 20
  73 */
  74
  75static int msic_gpio_to_ireg(unsigned offset)
  76{
  77        if (offset >= MSIC_NUM_GPIO)
  78                return -EINVAL;
  79
  80        if (offset < 8)
  81                return INTEL_MSIC_GPIO0LV0CTLI - offset;
  82        if (offset < 16)
  83                return INTEL_MSIC_GPIO1LV0CTLI - offset + 8;
  84        if (offset < 20)
  85                return INTEL_MSIC_GPIO0HV0CTLI - offset + 16;
  86
  87        return INTEL_MSIC_GPIO1HV0CTLI - offset + 20;
  88}
  89
  90static int msic_gpio_to_oreg(unsigned offset)
  91{
  92        if (offset >= MSIC_NUM_GPIO)
  93                return -EINVAL;
  94
  95        if (offset < 8)
  96                return INTEL_MSIC_GPIO0LV0CTLO - offset;
  97        if (offset < 16)
  98                return INTEL_MSIC_GPIO1LV0CTLO - offset + 8;
  99        if (offset < 20)
 100                return INTEL_MSIC_GPIO0HV0CTLO - offset + 16;
 101
 102        return INTEL_MSIC_GPIO1HV0CTLO - offset + 20;
 103}
 104
 105static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 106{
 107        int reg;
 108
 109        reg = msic_gpio_to_oreg(offset);
 110        if (reg < 0)
 111                return reg;
 112
 113        return intel_msic_reg_update(reg, MSIC_GPIO_DIR_IN, MSIC_GPIO_DIR_MASK);
 114}
 115
 116static int msic_gpio_direction_output(struct gpio_chip *chip,
 117                        unsigned offset, int value)
 118{
 119        int reg;
 120        unsigned mask;
 121
 122        value = (!!value) | MSIC_GPIO_DIR_OUT;
 123        mask = MSIC_GPIO_DIR_MASK | MSIC_GPIO_DOUT_MASK;
 124
 125        reg = msic_gpio_to_oreg(offset);
 126        if (reg < 0)
 127                return reg;
 128
 129        return intel_msic_reg_update(reg, value, mask);
 130}
 131
 132static int msic_gpio_get(struct gpio_chip *chip, unsigned offset)
 133{
 134        u8 r;
 135        int ret;
 136        int reg;
 137
 138        reg = msic_gpio_to_ireg(offset);
 139        if (reg < 0)
 140                return reg;
 141
 142        ret = intel_msic_reg_read(reg, &r);
 143        if (ret < 0)
 144                return ret;
 145
 146        return r & MSIC_GPIO_DIN_MASK;
 147}
 148
 149static void msic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 150{
 151        int reg;
 152
 153        reg = msic_gpio_to_oreg(offset);
 154        if (reg < 0)
 155                return;
 156
 157        intel_msic_reg_update(reg, !!value , MSIC_GPIO_DOUT_MASK);
 158}
 159
 160/*
 161 * This is called from genirq with mg->buslock locked and
 162 * irq_desc->lock held. We can not access the scu bus here, so we
 163 * store the change and update in the bus_sync_unlock() function below
 164 */
 165static int msic_irq_type(struct irq_data *data, unsigned type)
 166{
 167        struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
 168        u32 gpio = data->irq - mg->irq_base;
 169
 170        if (gpio >= mg->chip.ngpio)
 171                return -EINVAL;
 172
 173        /* mark for which gpio the trigger changed, protected by buslock */
 174        mg->trig_change_mask |= (1 << gpio);
 175        mg->trig_type = type;
 176
 177        return 0;
 178}
 179
 180static int msic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 181{
 182        struct msic_gpio *mg = container_of(chip, struct msic_gpio, chip);
 183        return mg->irq_base + offset;
 184}
 185
 186static void msic_bus_lock(struct irq_data *data)
 187{
 188        struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
 189        mutex_lock(&mg->buslock);
 190}
 191
 192static void msic_bus_sync_unlock(struct irq_data *data)
 193{
 194        struct msic_gpio *mg = irq_data_get_irq_chip_data(data);
 195        int offset;
 196        int reg;
 197        u8 trig = 0;
 198
 199        /* We can only get one change at a time as the buslock covers the
 200           entire transaction. The irq_desc->lock is dropped before we are
 201           called but that is fine */
 202        if (mg->trig_change_mask) {
 203                offset = __ffs(mg->trig_change_mask);
 204
 205                reg = msic_gpio_to_ireg(offset);
 206                if (reg < 0)
 207                        goto out;
 208
 209                if (mg->trig_type & IRQ_TYPE_EDGE_RISING)
 210                        trig |= MSIC_GPIO_TRIG_RISE;
 211                if (mg->trig_type & IRQ_TYPE_EDGE_FALLING)
 212                        trig |= MSIC_GPIO_TRIG_FALL;
 213
 214                intel_msic_reg_update(reg, trig, MSIC_GPIO_INTCNT_MASK);
 215                mg->trig_change_mask = 0;
 216        }
 217out:
 218        mutex_unlock(&mg->buslock);
 219}
 220
 221/* Firmware does all the masking and unmasking for us, no masking here. */
 222static void msic_irq_unmask(struct irq_data *data) { }
 223
 224static void msic_irq_mask(struct irq_data *data) { }
 225
 226static struct irq_chip msic_irqchip = {
 227        .name                   = "MSIC-GPIO",
 228        .irq_mask               = msic_irq_mask,
 229        .irq_unmask             = msic_irq_unmask,
 230        .irq_set_type           = msic_irq_type,
 231        .irq_bus_lock           = msic_bus_lock,
 232        .irq_bus_sync_unlock    = msic_bus_sync_unlock,
 233};
 234
 235static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 236{
 237        struct irq_data *data = irq_desc_get_irq_data(desc);
 238        struct msic_gpio *mg = irq_data_get_irq_handler_data(data);
 239        struct irq_chip *chip = irq_data_get_irq_chip(data);
 240        struct intel_msic *msic = pdev_to_intel_msic(mg->pdev);
 241        int i;
 242        int bitnr;
 243        u8 pin;
 244        unsigned long pending = 0;
 245
 246        for (i = 0; i < (mg->chip.ngpio / BITS_PER_BYTE); i++) {
 247                intel_msic_irq_read(msic, INTEL_MSIC_GPIO0LVIRQ + i, &pin);
 248                pending = pin;
 249
 250                if (pending) {
 251                        for_each_set_bit(bitnr, &pending, BITS_PER_BYTE)
 252                                generic_handle_irq(mg->irq_base +
 253                                                   (i * BITS_PER_BYTE) + bitnr);
 254                }
 255        }
 256        chip->irq_eoi(data);
 257}
 258
 259static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
 260{
 261        struct device *dev = &pdev->dev;
 262        struct intel_msic_gpio_pdata *pdata = dev->platform_data;
 263        struct msic_gpio *mg;
 264        int irq = platform_get_irq(pdev, 0);
 265        int retval;
 266        int i;
 267
 268        if (irq < 0) {
 269                dev_err(dev, "no IRQ line\n");
 270                return -EINVAL;
 271        }
 272
 273        if (!pdata || !pdata->gpio_base) {
 274                dev_err(dev, "incorrect or missing platform data\n");
 275                return -EINVAL;
 276        }
 277
 278        mg = kzalloc(sizeof(*mg), GFP_KERNEL);
 279        if (!mg)
 280                return -ENOMEM;
 281
 282        dev_set_drvdata(dev, mg);
 283
 284        mg->pdev = pdev;
 285        mg->irq = irq;
 286        mg->irq_base = pdata->gpio_base + MSIC_GPIO_IRQ_OFFSET;
 287        mg->chip.label = "msic_gpio";
 288        mg->chip.direction_input = msic_gpio_direction_input;
 289        mg->chip.direction_output = msic_gpio_direction_output;
 290        mg->chip.get = msic_gpio_get;
 291        mg->chip.set = msic_gpio_set;
 292        mg->chip.to_irq = msic_gpio_to_irq;
 293        mg->chip.base = pdata->gpio_base;
 294        mg->chip.ngpio = MSIC_NUM_GPIO;
 295        mg->chip.can_sleep = 1;
 296        mg->chip.dev = dev;
 297
 298        mutex_init(&mg->buslock);
 299
 300        retval = gpiochip_add(&mg->chip);
 301        if (retval) {
 302                dev_err(dev, "Adding MSIC gpio chip failed\n");
 303                goto err;
 304        }
 305
 306        for (i = 0; i < mg->chip.ngpio; i++) {
 307                irq_set_chip_data(i + mg->irq_base, mg);
 308                irq_set_chip_and_handler_name(i + mg->irq_base,
 309                                              &msic_irqchip,
 310                                              handle_simple_irq,
 311                                              "demux");
 312        }
 313        irq_set_chained_handler(mg->irq, msic_gpio_irq_handler);
 314        irq_set_handler_data(mg->irq, mg);
 315
 316        return 0;
 317err:
 318        kfree(mg);
 319        return retval;
 320}
 321
 322static struct platform_driver platform_msic_gpio_driver = {
 323        .driver = {
 324                .name           = "msic_gpio",
 325                .owner          = THIS_MODULE,
 326        },
 327        .probe          = platform_msic_gpio_probe,
 328};
 329
 330static int __init platform_msic_gpio_init(void)
 331{
 332        return platform_driver_register(&platform_msic_gpio_driver);
 333}
 334
 335subsys_initcall(platform_msic_gpio_init);
 336
 337MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
 338MODULE_DESCRIPTION("Intel Medfield MSIC GPIO driver");
 339MODULE_LICENSE("GPL v2");
 340
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.