root/drivers/gpio/gpio-cadence.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdns_gpio_request
  2. cdns_gpio_free
  3. cdns_gpio_irq_mask
  4. cdns_gpio_irq_unmask
  5. cdns_gpio_irq_set_type
  6. cdns_gpio_irq_handler
  7. cdns_gpio_probe
  8. cdns_gpio_remove

   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 
  32 struct cdns_gpio_chip {
  33         struct gpio_chip gc;
  34         struct clk *pclk;
  35         void __iomem *regs;
  36         u32 bypass_orig;
  37 };
  38 
  39 static 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 
  53 static 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 
  67 static 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 
  75 static 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 
  83 static 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 
 117 err_irq_type:
 118         spin_unlock_irqrestore(&chip->bgpio_lock, flags);
 119         return ret;
 120 }
 121 
 122 static 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_irq(irq_find_mapping(chip->irq.domain, hwirq));
 137 
 138         chained_irq_exit(irqchip, desc);
 139 }
 140 
 141 static 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 
 148 static 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 
 258 err_disable_clk:
 259         clk_disable_unprepare(cgpio->pclk);
 260 
 261 err_revert_dir:
 262         iowrite32(dir_prev, cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
 263 
 264         return ret;
 265 }
 266 
 267 static 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 
 277 static const struct of_device_id cdns_of_ids[] = {
 278         { .compatible = "cdns,gpio-r1p02" },
 279         { /* sentinel */ },
 280 };
 281 
 282 static struct platform_driver cdns_gpio_driver = {
 283         .driver = {
 284                 .name = "cdns-gpio",
 285                 .of_match_table = cdns_of_ids,
 286         },
 287         .probe = cdns_gpio_probe,
 288         .remove = cdns_gpio_remove,
 289 };
 290 module_platform_driver(cdns_gpio_driver);
 291 
 292 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
 293 MODULE_DESCRIPTION("Cadence GPIO driver");
 294 MODULE_LICENSE("GPL v2");
 295 MODULE_ALIAS("platform:cdns-gpio");

/* [<][>][^][v][top][bottom][index][help] */