linux/drivers/gpio/gpio-tqmx86.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * TQ-Systems TQMx86 PLD GPIO driver
   4 *
   5 * Based on vendor driver by:
   6 *   Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
   7 */
   8
   9#include <linux/bitops.h>
  10#include <linux/errno.h>
  11#include <linux/gpio/driver.h>
  12#include <linux/init.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/slab.h>
  19
  20#define TQMX86_NGPIO    8
  21#define TQMX86_NGPO     4       /* 0-3 - output */
  22#define TQMX86_NGPI     4       /* 4-7 - input */
  23#define TQMX86_DIR_INPUT_MASK   0xf0    /* 0-3 - output, 4-7 - input */
  24
  25#define TQMX86_GPIODD   0       /* GPIO Data Direction Register */
  26#define TQMX86_GPIOD    1       /* GPIO Data Register */
  27#define TQMX86_GPIIC    3       /* GPI Interrupt Configuration Register */
  28#define TQMX86_GPIIS    4       /* GPI Interrupt Status Register */
  29
  30#define TQMX86_GPII_FALLING     BIT(0)
  31#define TQMX86_GPII_RISING      BIT(1)
  32#define TQMX86_GPII_MASK        (BIT(0) | BIT(1))
  33#define TQMX86_GPII_BITS        2
  34
  35struct tqmx86_gpio_data {
  36        struct gpio_chip        chip;
  37        struct irq_chip         irq_chip;
  38        void __iomem            *io_base;
  39        int                     irq;
  40        raw_spinlock_t          spinlock;
  41        u8                      irq_type[TQMX86_NGPI];
  42};
  43
  44static u8 tqmx86_gpio_read(struct tqmx86_gpio_data *gd, unsigned int reg)
  45{
  46        return ioread8(gd->io_base + reg);
  47}
  48
  49static void tqmx86_gpio_write(struct tqmx86_gpio_data *gd, u8 val,
  50                              unsigned int reg)
  51{
  52        iowrite8(val, gd->io_base + reg);
  53}
  54
  55static int tqmx86_gpio_get(struct gpio_chip *chip, unsigned int offset)
  56{
  57        struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
  58
  59        return !!(tqmx86_gpio_read(gpio, TQMX86_GPIOD) & BIT(offset));
  60}
  61
  62static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
  63                            int value)
  64{
  65        struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
  66        unsigned long flags;
  67        u8 val;
  68
  69        raw_spin_lock_irqsave(&gpio->spinlock, flags);
  70        val = tqmx86_gpio_read(gpio, TQMX86_GPIOD);
  71        if (value)
  72                val |= BIT(offset);
  73        else
  74                val &= ~BIT(offset);
  75        tqmx86_gpio_write(gpio, val, TQMX86_GPIOD);
  76        raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
  77}
  78
  79static int tqmx86_gpio_direction_input(struct gpio_chip *chip,
  80                                       unsigned int offset)
  81{
  82        /* Direction cannot be changed. Validate is an input. */
  83        if (BIT(offset) & TQMX86_DIR_INPUT_MASK)
  84                return 0;
  85        else
  86                return -EINVAL;
  87}
  88
  89static int tqmx86_gpio_direction_output(struct gpio_chip *chip,
  90                                        unsigned int offset,
  91                                        int value)
  92{
  93        /* Direction cannot be changed, validate is an output */
  94        if (BIT(offset) & TQMX86_DIR_INPUT_MASK)
  95                return -EINVAL;
  96
  97        tqmx86_gpio_set(chip, offset, value);
  98        return 0;
  99}
 100
 101static int tqmx86_gpio_get_direction(struct gpio_chip *chip,
 102                                     unsigned int offset)
 103{
 104        if (TQMX86_DIR_INPUT_MASK & BIT(offset))
 105                return GPIO_LINE_DIRECTION_IN;
 106
 107        return GPIO_LINE_DIRECTION_OUT;
 108}
 109
 110static void tqmx86_gpio_irq_mask(struct irq_data *data)
 111{
 112        unsigned int offset = (data->hwirq - TQMX86_NGPO);
 113        struct tqmx86_gpio_data *gpio = gpiochip_get_data(
 114                irq_data_get_irq_chip_data(data));
 115        unsigned long flags;
 116        u8 gpiic, mask;
 117
 118        mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
 119
 120        raw_spin_lock_irqsave(&gpio->spinlock, flags);
 121        gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
 122        gpiic &= ~mask;
 123        tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
 124        raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
 125}
 126
 127static void tqmx86_gpio_irq_unmask(struct irq_data *data)
 128{
 129        unsigned int offset = (data->hwirq - TQMX86_NGPO);
 130        struct tqmx86_gpio_data *gpio = gpiochip_get_data(
 131                irq_data_get_irq_chip_data(data));
 132        unsigned long flags;
 133        u8 gpiic, mask;
 134
 135        mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
 136
 137        raw_spin_lock_irqsave(&gpio->spinlock, flags);
 138        gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
 139        gpiic &= ~mask;
 140        gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS);
 141        tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
 142        raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
 143}
 144
 145static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 146{
 147        struct tqmx86_gpio_data *gpio = gpiochip_get_data(
 148                irq_data_get_irq_chip_data(data));
 149        unsigned int offset = (data->hwirq - TQMX86_NGPO);
 150        unsigned int edge_type = type & IRQF_TRIGGER_MASK;
 151        unsigned long flags;
 152        u8 new_type, gpiic;
 153
 154        switch (edge_type) {
 155        case IRQ_TYPE_EDGE_RISING:
 156                new_type = TQMX86_GPII_RISING;
 157                break;
 158        case IRQ_TYPE_EDGE_FALLING:
 159                new_type = TQMX86_GPII_FALLING;
 160                break;
 161        case IRQ_TYPE_EDGE_BOTH:
 162                new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING;
 163                break;
 164        default:
 165                return -EINVAL; /* not supported */
 166        }
 167
 168        gpio->irq_type[offset] = new_type;
 169
 170        raw_spin_lock_irqsave(&gpio->spinlock, flags);
 171        gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
 172        gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS));
 173        gpiic |= new_type << (offset * TQMX86_GPII_BITS);
 174        tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
 175        raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
 176
 177        return 0;
 178}
 179
 180static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
 181{
 182        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 183        struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
 184        struct irq_chip *irq_chip = irq_desc_get_chip(desc);
 185        unsigned long irq_bits;
 186        int i = 0, child_irq;
 187        u8 irq_status;
 188
 189        chained_irq_enter(irq_chip, desc);
 190
 191        irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
 192        tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
 193
 194        irq_bits = irq_status;
 195        for_each_set_bit(i, &irq_bits, TQMX86_NGPI) {
 196                child_irq = irq_find_mapping(gpio->chip.irq.domain,
 197                                             i + TQMX86_NGPO);
 198                generic_handle_irq(child_irq);
 199        }
 200
 201        chained_irq_exit(irq_chip, desc);
 202}
 203
 204/* Minimal runtime PM is needed by the IRQ subsystem */
 205static int __maybe_unused tqmx86_gpio_runtime_suspend(struct device *dev)
 206{
 207        return 0;
 208}
 209
 210static int __maybe_unused tqmx86_gpio_runtime_resume(struct device *dev)
 211{
 212        return 0;
 213}
 214
 215static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = {
 216        SET_RUNTIME_PM_OPS(tqmx86_gpio_runtime_suspend,
 217                           tqmx86_gpio_runtime_resume, NULL)
 218};
 219
 220static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
 221                                       unsigned long *valid_mask,
 222                                       unsigned int ngpios)
 223{
 224        /* Only GPIOs 4-7 are valid for interrupts. Clear the others */
 225        clear_bit(0, valid_mask);
 226        clear_bit(1, valid_mask);
 227        clear_bit(2, valid_mask);
 228        clear_bit(3, valid_mask);
 229}
 230
 231static int tqmx86_gpio_probe(struct platform_device *pdev)
 232{
 233        struct device *dev = &pdev->dev;
 234        struct tqmx86_gpio_data *gpio;
 235        struct gpio_chip *chip;
 236        struct gpio_irq_chip *girq;
 237        void __iomem *io_base;
 238        struct resource *res;
 239        int ret, irq;
 240
 241        irq = platform_get_irq(pdev, 0);
 242        if (irq < 0)
 243                return irq;
 244
 245        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 246        if (!res) {
 247                dev_err(&pdev->dev, "Cannot get I/O\n");
 248                return -ENODEV;
 249        }
 250
 251        io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res));
 252        if (!io_base)
 253                return -ENOMEM;
 254
 255        gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
 256        if (!gpio)
 257                return -ENOMEM;
 258
 259        raw_spin_lock_init(&gpio->spinlock);
 260        gpio->io_base = io_base;
 261
 262        tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
 263
 264        platform_set_drvdata(pdev, gpio);
 265
 266        chip = &gpio->chip;
 267        chip->label = "gpio-tqmx86";
 268        chip->owner = THIS_MODULE;
 269        chip->can_sleep = false;
 270        chip->base = -1;
 271        chip->direction_input = tqmx86_gpio_direction_input;
 272        chip->direction_output = tqmx86_gpio_direction_output;
 273        chip->get_direction = tqmx86_gpio_get_direction;
 274        chip->get = tqmx86_gpio_get;
 275        chip->set = tqmx86_gpio_set;
 276        chip->ngpio = TQMX86_NGPIO;
 277        chip->parent = pdev->dev.parent;
 278
 279        pm_runtime_enable(&pdev->dev);
 280
 281        if (irq) {
 282                struct irq_chip *irq_chip = &gpio->irq_chip;
 283                u8 irq_status;
 284
 285                irq_chip->name = chip->label;
 286                irq_chip->parent_device = &pdev->dev;
 287                irq_chip->irq_mask = tqmx86_gpio_irq_mask;
 288                irq_chip->irq_unmask = tqmx86_gpio_irq_unmask;
 289                irq_chip->irq_set_type = tqmx86_gpio_irq_set_type;
 290
 291                /* Mask all interrupts */
 292                tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC);
 293
 294                /* Clear all pending interrupts */
 295                irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
 296                tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
 297
 298                girq = &chip->irq;
 299                girq->chip = irq_chip;
 300                girq->parent_handler = tqmx86_gpio_irq_handler;
 301                girq->num_parents = 1;
 302                girq->parents = devm_kcalloc(&pdev->dev, 1,
 303                                             sizeof(*girq->parents),
 304                                             GFP_KERNEL);
 305                if (!girq->parents) {
 306                        ret = -ENOMEM;
 307                        goto out_pm_dis;
 308                }
 309                girq->parents[0] = irq;
 310                girq->default_type = IRQ_TYPE_NONE;
 311                girq->handler = handle_simple_irq;
 312                girq->init_valid_mask = tqmx86_init_irq_valid_mask;
 313        }
 314
 315        ret = devm_gpiochip_add_data(dev, chip, gpio);
 316        if (ret) {
 317                dev_err(dev, "Could not register GPIO chip\n");
 318                goto out_pm_dis;
 319        }
 320
 321        dev_info(dev, "GPIO functionality initialized with %d pins\n",
 322                 chip->ngpio);
 323
 324        return 0;
 325
 326out_pm_dis:
 327        pm_runtime_disable(&pdev->dev);
 328
 329        return ret;
 330}
 331
 332static struct platform_driver tqmx86_gpio_driver = {
 333        .driver = {
 334                .name = "tqmx86-gpio",
 335                .pm = &tqmx86_gpio_dev_pm_ops,
 336        },
 337        .probe          = tqmx86_gpio_probe,
 338};
 339
 340module_platform_driver(tqmx86_gpio_driver);
 341
 342MODULE_DESCRIPTION("TQMx86 PLD GPIO Driver");
 343MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
 344MODULE_LICENSE("GPL");
 345MODULE_ALIAS("platform:tqmx86-gpio");
 346