root/drivers/gpio/gpio-mb86s7x.c

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

DEFINITIONS

This source file includes following definitions.
  1. mb86s70_gpio_request
  2. mb86s70_gpio_free
  3. mb86s70_gpio_direction_input
  4. mb86s70_gpio_direction_output
  5. mb86s70_gpio_get
  6. mb86s70_gpio_set
  7. mb86s70_gpio_to_irq
  8. mb86s70_gpio_probe
  9. mb86s70_gpio_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/drivers/gpio/gpio-mb86s7x.c
   4  *
   5  *  Copyright (C) 2015 Fujitsu Semiconductor Limited
   6  *  Copyright (C) 2015 Linaro Ltd.
   7  */
   8 
   9 #include <linux/acpi.h>
  10 #include <linux/io.h>
  11 #include <linux/init.h>
  12 #include <linux/clk.h>
  13 #include <linux/module.h>
  14 #include <linux/err.h>
  15 #include <linux/errno.h>
  16 #include <linux/ioport.h>
  17 #include <linux/of_device.h>
  18 #include <linux/gpio/driver.h>
  19 #include <linux/platform_device.h>
  20 #include <linux/spinlock.h>
  21 #include <linux/slab.h>
  22 
  23 #include "gpiolib.h"
  24 #include "gpiolib-acpi.h"
  25 
  26 /*
  27  * Only first 8bits of a register correspond to each pin,
  28  * so there are 4 registers for 32 pins.
  29  */
  30 #define PDR(x)  (0x0 + x / 8 * 4)
  31 #define DDR(x)  (0x10 + x / 8 * 4)
  32 #define PFR(x)  (0x20 + x / 8 * 4)
  33 
  34 #define OFFSET(x)       BIT((x) % 8)
  35 
  36 struct mb86s70_gpio_chip {
  37         struct gpio_chip gc;
  38         void __iomem *base;
  39         struct clk *clk;
  40         spinlock_t lock;
  41 };
  42 
  43 static int mb86s70_gpio_request(struct gpio_chip *gc, unsigned gpio)
  44 {
  45         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
  46         unsigned long flags;
  47         u32 val;
  48 
  49         spin_lock_irqsave(&gchip->lock, flags);
  50 
  51         val = readl(gchip->base + PFR(gpio));
  52         val &= ~OFFSET(gpio);
  53         writel(val, gchip->base + PFR(gpio));
  54 
  55         spin_unlock_irqrestore(&gchip->lock, flags);
  56 
  57         return 0;
  58 }
  59 
  60 static void mb86s70_gpio_free(struct gpio_chip *gc, unsigned gpio)
  61 {
  62         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
  63         unsigned long flags;
  64         u32 val;
  65 
  66         spin_lock_irqsave(&gchip->lock, flags);
  67 
  68         val = readl(gchip->base + PFR(gpio));
  69         val |= OFFSET(gpio);
  70         writel(val, gchip->base + PFR(gpio));
  71 
  72         spin_unlock_irqrestore(&gchip->lock, flags);
  73 }
  74 
  75 static int mb86s70_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
  76 {
  77         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
  78         unsigned long flags;
  79         unsigned char val;
  80 
  81         spin_lock_irqsave(&gchip->lock, flags);
  82 
  83         val = readl(gchip->base + DDR(gpio));
  84         val &= ~OFFSET(gpio);
  85         writel(val, gchip->base + DDR(gpio));
  86 
  87         spin_unlock_irqrestore(&gchip->lock, flags);
  88 
  89         return 0;
  90 }
  91 
  92 static int mb86s70_gpio_direction_output(struct gpio_chip *gc,
  93                                          unsigned gpio, int value)
  94 {
  95         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
  96         unsigned long flags;
  97         unsigned char val;
  98 
  99         spin_lock_irqsave(&gchip->lock, flags);
 100 
 101         val = readl(gchip->base + PDR(gpio));
 102         if (value)
 103                 val |= OFFSET(gpio);
 104         else
 105                 val &= ~OFFSET(gpio);
 106         writel(val, gchip->base + PDR(gpio));
 107 
 108         val = readl(gchip->base + DDR(gpio));
 109         val |= OFFSET(gpio);
 110         writel(val, gchip->base + DDR(gpio));
 111 
 112         spin_unlock_irqrestore(&gchip->lock, flags);
 113 
 114         return 0;
 115 }
 116 
 117 static int mb86s70_gpio_get(struct gpio_chip *gc, unsigned gpio)
 118 {
 119         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
 120 
 121         return !!(readl(gchip->base + PDR(gpio)) & OFFSET(gpio));
 122 }
 123 
 124 static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
 125 {
 126         struct mb86s70_gpio_chip *gchip = gpiochip_get_data(gc);
 127         unsigned long flags;
 128         unsigned char val;
 129 
 130         spin_lock_irqsave(&gchip->lock, flags);
 131 
 132         val = readl(gchip->base + PDR(gpio));
 133         if (value)
 134                 val |= OFFSET(gpio);
 135         else
 136                 val &= ~OFFSET(gpio);
 137         writel(val, gchip->base + PDR(gpio));
 138 
 139         spin_unlock_irqrestore(&gchip->lock, flags);
 140 }
 141 
 142 static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
 143 {
 144         int irq, index;
 145 
 146         for (index = 0;; index++) {
 147                 irq = platform_get_irq(to_platform_device(gc->parent), index);
 148                 if (irq <= 0)
 149                         break;
 150                 if (irq_get_irq_data(irq)->hwirq == offset)
 151                         return irq;
 152         }
 153         return -EINVAL;
 154 }
 155 
 156 static int mb86s70_gpio_probe(struct platform_device *pdev)
 157 {
 158         struct mb86s70_gpio_chip *gchip;
 159         int ret;
 160 
 161         gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL);
 162         if (gchip == NULL)
 163                 return -ENOMEM;
 164 
 165         platform_set_drvdata(pdev, gchip);
 166 
 167         gchip->base = devm_platform_ioremap_resource(pdev, 0);
 168         if (IS_ERR(gchip->base))
 169                 return PTR_ERR(gchip->base);
 170 
 171         if (!has_acpi_companion(&pdev->dev)) {
 172                 gchip->clk = devm_clk_get(&pdev->dev, NULL);
 173                 if (IS_ERR(gchip->clk))
 174                         return PTR_ERR(gchip->clk);
 175 
 176                 ret = clk_prepare_enable(gchip->clk);
 177                 if (ret)
 178                         return ret;
 179         }
 180 
 181         spin_lock_init(&gchip->lock);
 182 
 183         gchip->gc.direction_output = mb86s70_gpio_direction_output;
 184         gchip->gc.direction_input = mb86s70_gpio_direction_input;
 185         gchip->gc.request = mb86s70_gpio_request;
 186         gchip->gc.free = mb86s70_gpio_free;
 187         gchip->gc.get = mb86s70_gpio_get;
 188         gchip->gc.set = mb86s70_gpio_set;
 189         gchip->gc.label = dev_name(&pdev->dev);
 190         gchip->gc.ngpio = 32;
 191         gchip->gc.owner = THIS_MODULE;
 192         gchip->gc.parent = &pdev->dev;
 193         gchip->gc.base = -1;
 194 
 195         if (has_acpi_companion(&pdev->dev))
 196                 gchip->gc.to_irq = mb86s70_gpio_to_irq;
 197 
 198         ret = gpiochip_add_data(&gchip->gc, gchip);
 199         if (ret) {
 200                 dev_err(&pdev->dev, "couldn't register gpio driver\n");
 201                 clk_disable_unprepare(gchip->clk);
 202                 return ret;
 203         }
 204 
 205         if (has_acpi_companion(&pdev->dev))
 206                 acpi_gpiochip_request_interrupts(&gchip->gc);
 207 
 208         return 0;
 209 }
 210 
 211 static int mb86s70_gpio_remove(struct platform_device *pdev)
 212 {
 213         struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
 214 
 215         if (has_acpi_companion(&pdev->dev))
 216                 acpi_gpiochip_free_interrupts(&gchip->gc);
 217         gpiochip_remove(&gchip->gc);
 218         clk_disable_unprepare(gchip->clk);
 219 
 220         return 0;
 221 }
 222 
 223 static const struct of_device_id mb86s70_gpio_dt_ids[] = {
 224         { .compatible = "fujitsu,mb86s70-gpio" },
 225         { /* sentinel */ }
 226 };
 227 MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
 228 
 229 #ifdef CONFIG_ACPI
 230 static const struct acpi_device_id mb86s70_gpio_acpi_ids[] = {
 231         { "SCX0007" },
 232         { /* sentinel */ }
 233 };
 234 MODULE_DEVICE_TABLE(acpi, mb86s70_gpio_acpi_ids);
 235 #endif
 236 
 237 static struct platform_driver mb86s70_gpio_driver = {
 238         .driver = {
 239                 .name = "mb86s70-gpio",
 240                 .of_match_table = mb86s70_gpio_dt_ids,
 241                 .acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids),
 242         },
 243         .probe = mb86s70_gpio_probe,
 244         .remove = mb86s70_gpio_remove,
 245 };
 246 module_platform_driver(mb86s70_gpio_driver);
 247 
 248 MODULE_DESCRIPTION("MB86S7x GPIO Driver");
 249 MODULE_ALIAS("platform:mb86s70-gpio");
 250 MODULE_LICENSE("GPL");

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