linux/drivers/gpio/gpio-cadence.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Copyright 2017-2018 Cadence
   5 *
   6 * Authors:
   7 *  Jan Kotas <jank@cadence.com>
   8 *  Boris Brezillon <boris.brezillon@free-electrons.com>
   9 */
  10
  11#include <linux/gpio/driver.h>
  12#include <linux/clk.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/spinlock.h>
  18
  19#define CDNS_GPIO_BYPASS_MODE           0x00
  20#define CDNS_GPIO_DIRECTION_MODE        0x04
  21#define CDNS_GPIO_OUTPUT_EN             0x08
  22#define CDNS_GPIO_OUTPUT_VALUE          0x0c
  23#define CDNS_GPIO_INPUT_VALUE           0x10
  24#define CDNS_GPIO_IRQ_MASK              0x14
  25#define CDNS_GPIO_IRQ_EN                0x18
  26#define CDNS_GPIO_IRQ_DIS               0x1c
  27#define CDNS_GPIO_IRQ_STATUS            0x20
  28#define CDNS_GPIO_IRQ_TYPE              0x24
  29#define CDNS_GPIO_IRQ_VALUE             0x28
  30#define CDNS_GPIO_IRQ_ANY_EDGE          0x2c
  31
  32struct cdns_gpio_chip {
  33        struct gpio_chip gc;
  34        struct clk *pclk;
  35        void __iomem *regs;
  36        u32 bypass_orig;
  37};
  38
  39static int cdns_gpio_request(struct gpio_chip *chip, unsigned int offset)
  40{
  41        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
  42        unsigned long flags;
  43
  44        spin_lock_irqsave(&chip->bgpio_lock, flags);
  45
  46        iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) & ~BIT(offset),
  47                  cgpio->regs + CDNS_GPIO_BYPASS_MODE);
  48
  49        spin_unlock_irqrestore(&chip->bgpio_lock, flags);
  50        return 0;
  51}
  52
  53static void cdns_gpio_free(struct gpio_chip *chip, unsigned int offset)
  54{
  55        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
  56        unsigned long flags;
  57
  58        spin_lock_irqsave(&chip->bgpio_lock, flags);
  59
  60        iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) |
  61                  (BIT(offset) & cgpio->bypass_orig),
  62                  cgpio->regs + CDNS_GPIO_BYPASS_MODE);
  63
  64        spin_unlock_irqrestore(&chip->bgpio_lock, flags);
  65}
  66
  67static void cdns_gpio_irq_mask(struct irq_data *d)
  68{
  69        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
  70        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
  71
  72        iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_DIS);
  73}
  74
  75static void cdns_gpio_irq_unmask(struct irq_data *d)
  76{
  77        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
  78        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
  79
  80        iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_EN);
  81}
  82
  83static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
  84{
  85        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
  86        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
  87        unsigned long flags;
  88        u32 int_value;
  89        u32 int_type;
  90        u32 mask = BIT(d->hwirq);
  91        int ret = 0;
  92
  93        spin_lock_irqsave(&chip->bgpio_lock, flags);
  94
  95        int_value = ioread32(cgpio->regs + CDNS_GPIO_IRQ_VALUE) & ~mask;
  96        int_type = ioread32(cgpio->regs + CDNS_GPIO_IRQ_TYPE) & ~mask;
  97
  98        /*
  99         * The GPIO controller doesn't have an ACK register.
 100         * All interrupt statuses are cleared on a status register read.
 101         * Don't support edge interrupts for now.
 102         */
 103
 104        if (type == IRQ_TYPE_LEVEL_HIGH) {
 105                int_type |= mask;
 106                int_value |= mask;
 107        } else if (type == IRQ_TYPE_LEVEL_LOW) {
 108                int_type |= mask;
 109        } else {
 110                ret = -EINVAL;
 111                goto err_irq_type;
 112        }
 113
 114        iowrite32(int_value, cgpio->regs + CDNS_GPIO_IRQ_VALUE);
 115        iowrite32(int_type, cgpio->regs + CDNS_GPIO_IRQ_TYPE);
 116
 117err_irq_type:
 118        spin_unlock_irqrestore(&chip->bgpio_lock, flags);
 119        return ret;
 120}
 121
 122static void cdns_gpio_irq_handler(struct irq_desc *desc)
 123{
 124        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 125        struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
 126        struct irq_chip *irqchip = irq_desc_get_chip(desc);
 127        unsigned long status;
 128        int hwirq;
 129
 130        chained_irq_enter(irqchip, desc);
 131
 132        status = ioread32(cgpio->regs + CDNS_GPIO_IRQ_STATUS) &
 133                ~ioread32(cgpio->regs + CDNS_GPIO_IRQ_MASK);
 134
 135        for_each_set_bit(hwirq, &status, chip->ngpio)
 136                generic_handle_domain_irq(chip->irq.domain, hwirq);
 137
 138        chained_irq_exit(irqchip, desc);
 139}
 140
 141static struct irq_chip cdns_gpio_irqchip = {
 142        .name           = "cdns-gpio",
 143        .irq_mask       = cdns_gpio_irq_mask,
 144        .irq_unmask     = cdns_gpio_irq_unmask,
 145        .irq_set_type   = cdns_gpio_irq_set_type
 146};
 147
 148static int cdns_gpio_probe(struct platform_device *pdev)
 149{
 150        struct cdns_gpio_chip *cgpio;
 151        int ret, irq;
 152        u32 dir_prev;
 153        u32 num_gpios = 32;
 154
 155        cgpio = devm_kzalloc(&pdev->dev, sizeof(*cgpio), GFP_KERNEL);
 156        if (!cgpio)
 157                return -ENOMEM;
 158
 159        cgpio->regs = devm_platform_ioremap_resource(pdev, 0);
 160        if (IS_ERR(cgpio->regs))
 161                return PTR_ERR(cgpio->regs);
 162
 163        of_property_read_u32(pdev->dev.of_node, "ngpios", &num_gpios);
 164
 165        if (num_gpios > 32) {
 166                dev_err(&pdev->dev, "ngpios must be less or equal 32\n");
 167                return -EINVAL;
 168        }
 169
 170        /*
 171         * Set all pins as inputs by default, otherwise:
 172         * gpiochip_lock_as_irq:
 173         * tried to flag a GPIO set as output for IRQ
 174         * Generic GPIO driver stores the direction value internally,
 175         * so it needs to be changed before bgpio_init() is called.
 176         */
 177        dir_prev = ioread32(cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
 178        iowrite32(GENMASK(num_gpios - 1, 0),
 179                  cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
 180
 181        ret = bgpio_init(&cgpio->gc, &pdev->dev, 4,
 182                         cgpio->regs + CDNS_GPIO_INPUT_VALUE,
 183                         cgpio->regs + CDNS_GPIO_OUTPUT_VALUE,
 184                         NULL,
 185                         NULL,
 186                         cgpio->regs + CDNS_GPIO_DIRECTION_MODE,
 187                         BGPIOF_READ_OUTPUT_REG_SET);
 188        if (ret) {
 189                dev_err(&pdev->dev, "Failed to register generic gpio, %d\n",
 190                        ret);
 191                goto err_revert_dir;
 192        }
 193
 194        cgpio->gc.label = dev_name(&pdev->dev);
 195        cgpio->gc.ngpio = num_gpios;
 196        cgpio->gc.parent = &pdev->dev;
 197        cgpio->gc.base = -1;
 198        cgpio->gc.owner = THIS_MODULE;
 199        cgpio->gc.request = cdns_gpio_request;
 200        cgpio->gc.free = cdns_gpio_free;
 201
 202        cgpio->pclk = devm_clk_get(&pdev->dev, NULL);
 203        if (IS_ERR(cgpio->pclk)) {
 204                ret = PTR_ERR(cgpio->pclk);
 205                dev_err(&pdev->dev,
 206                        "Failed to retrieve peripheral clock, %d\n", ret);
 207                goto err_revert_dir;
 208        }
 209
 210        ret = clk_prepare_enable(cgpio->pclk);
 211        if (ret) {
 212                dev_err(&pdev->dev,
 213                        "Failed to enable the peripheral clock, %d\n", ret);
 214                goto err_revert_dir;
 215        }
 216
 217        /*
 218         * Optional irq_chip support
 219         */
 220        irq = platform_get_irq(pdev, 0);
 221        if (irq >= 0) {
 222                struct gpio_irq_chip *girq;
 223
 224                girq = &cgpio->gc.irq;
 225                girq->chip = &cdns_gpio_irqchip;
 226                girq->parent_handler = cdns_gpio_irq_handler;
 227                girq->num_parents = 1;
 228                girq->parents = devm_kcalloc(&pdev->dev, 1,
 229                                             sizeof(*girq->parents),
 230                                             GFP_KERNEL);
 231                if (!girq->parents) {
 232                        ret = -ENOMEM;
 233                        goto err_disable_clk;
 234                }
 235                girq->parents[0] = irq;
 236                girq->default_type = IRQ_TYPE_NONE;
 237                girq->handler = handle_level_irq;
 238        }
 239
 240        ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio);
 241        if (ret < 0) {
 242                dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
 243                goto err_disable_clk;
 244        }
 245
 246        cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE);
 247
 248        /*
 249         * Enable gpio outputs, ignored for input direction
 250         */
 251        iowrite32(GENMASK(num_gpios - 1, 0),
 252                  cgpio->regs + CDNS_GPIO_OUTPUT_EN);
 253        iowrite32(0, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
 254
 255        platform_set_drvdata(pdev, cgpio);
 256        return 0;
 257
 258err_disable_clk:
 259        clk_disable_unprepare(cgpio->pclk);
 260
 261err_revert_dir:
 262        iowrite32(dir_prev, cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
 263
 264        return ret;
 265}
 266
 267static int cdns_gpio_remove(struct platform_device *pdev)
 268{
 269        struct cdns_gpio_chip *cgpio = platform_get_drvdata(pdev);
 270
 271        iowrite32(cgpio->bypass_orig, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
 272        clk_disable_unprepare(cgpio->pclk);
 273
 274        return 0;
 275}
 276
 277static const struct of_device_id cdns_of_ids[] = {
 278        { .compatible = "cdns,gpio-r1p02" },
 279        { /* sentinel */ },
 280};
 281MODULE_DEVICE_TABLE(of, cdns_of_ids);
 282
 283static struct platform_driver cdns_gpio_driver = {
 284        .driver = {
 285                .name = "cdns-gpio",
 286                .of_match_table = cdns_of_ids,
 287        },
 288        .probe = cdns_gpio_probe,
 289        .remove = cdns_gpio_remove,
 290};
 291module_platform_driver(cdns_gpio_driver);
 292
 293MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
 294MODULE_DESCRIPTION("Cadence GPIO driver");
 295MODULE_LICENSE("GPL v2");
 296MODULE_ALIAS("platform:cdns-gpio");
 297