root/drivers/gpio/gpio-em.c

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

DEFINITIONS

This source file includes following definitions.
  1. em_gio_read
  2. em_gio_write
  3. em_gio_irq_disable
  4. em_gio_irq_enable
  5. em_gio_irq_reqres
  6. em_gio_irq_relres
  7. em_gio_irq_set_type
  8. em_gio_irq_handler
  9. gpio_to_priv
  10. em_gio_direction_input
  11. em_gio_get
  12. __em_gio_set
  13. em_gio_set
  14. em_gio_direction_output
  15. em_gio_to_irq
  16. em_gio_request
  17. em_gio_free
  18. em_gio_irq_domain_map
  19. em_gio_irq_domain_remove
  20. em_gio_probe
  21. em_gio_init
  22. em_gio_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Emma Mobile GPIO Support - GIO
   4  *
   5  *  Copyright (C) 2012 Magnus Damm
   6  */
   7 
   8 #include <linux/init.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/spinlock.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/ioport.h>
  13 #include <linux/io.h>
  14 #include <linux/irq.h>
  15 #include <linux/irqdomain.h>
  16 #include <linux/bitops.h>
  17 #include <linux/err.h>
  18 #include <linux/gpio/driver.h>
  19 #include <linux/slab.h>
  20 #include <linux/module.h>
  21 #include <linux/pinctrl/consumer.h>
  22 
  23 struct em_gio_priv {
  24         void __iomem *base0;
  25         void __iomem *base1;
  26         spinlock_t sense_lock;
  27         struct platform_device *pdev;
  28         struct gpio_chip gpio_chip;
  29         struct irq_chip irq_chip;
  30         struct irq_domain *irq_domain;
  31 };
  32 
  33 #define GIO_E1 0x00
  34 #define GIO_E0 0x04
  35 #define GIO_EM 0x04
  36 #define GIO_OL 0x08
  37 #define GIO_OH 0x0c
  38 #define GIO_I 0x10
  39 #define GIO_IIA 0x14
  40 #define GIO_IEN 0x18
  41 #define GIO_IDS 0x1c
  42 #define GIO_IIM 0x1c
  43 #define GIO_RAW 0x20
  44 #define GIO_MST 0x24
  45 #define GIO_IIR 0x28
  46 
  47 #define GIO_IDT0 0x40
  48 #define GIO_IDT1 0x44
  49 #define GIO_IDT2 0x48
  50 #define GIO_IDT3 0x4c
  51 #define GIO_RAWBL 0x50
  52 #define GIO_RAWBH 0x54
  53 #define GIO_IRBL 0x58
  54 #define GIO_IRBH 0x5c
  55 
  56 #define GIO_IDT(n) (GIO_IDT0 + ((n) * 4))
  57 
  58 static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs)
  59 {
  60         if (offs < GIO_IDT0)
  61                 return ioread32(p->base0 + offs);
  62         else
  63                 return ioread32(p->base1 + (offs - GIO_IDT0));
  64 }
  65 
  66 static inline void em_gio_write(struct em_gio_priv *p, int offs,
  67                                 unsigned long value)
  68 {
  69         if (offs < GIO_IDT0)
  70                 iowrite32(value, p->base0 + offs);
  71         else
  72                 iowrite32(value, p->base1 + (offs - GIO_IDT0));
  73 }
  74 
  75 static void em_gio_irq_disable(struct irq_data *d)
  76 {
  77         struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  78 
  79         em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
  80 }
  81 
  82 static void em_gio_irq_enable(struct irq_data *d)
  83 {
  84         struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  85 
  86         em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
  87 }
  88 
  89 static int em_gio_irq_reqres(struct irq_data *d)
  90 {
  91         struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
  92         int ret;
  93 
  94         ret = gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
  95         if (ret) {
  96                 dev_err(p->gpio_chip.parent,
  97                         "unable to lock HW IRQ %lu for IRQ\n",
  98                         irqd_to_hwirq(d));
  99                 return ret;
 100         }
 101         return 0;
 102 }
 103 
 104 static void em_gio_irq_relres(struct irq_data *d)
 105 {
 106         struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 107 
 108         gpiochip_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
 109 }
 110 
 111 
 112 #define GIO_ASYNC(x) (x + 8)
 113 
 114 static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
 115         [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00),
 116         [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01),
 117         [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02),
 118         [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03),
 119         [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04),
 120 };
 121 
 122 static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
 123 {
 124         unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
 125         struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 126         unsigned int reg, offset, shift;
 127         unsigned long flags;
 128         unsigned long tmp;
 129 
 130         if (!value)
 131                 return -EINVAL;
 132 
 133         offset = irqd_to_hwirq(d);
 134 
 135         pr_debug("gio: sense irq = %d, mode = %d\n", offset, value);
 136 
 137         /* 8 x 4 bit fields in 4 IDT registers */
 138         reg = GIO_IDT(offset >> 3);
 139         shift = (offset & 0x07) << 4;
 140 
 141         spin_lock_irqsave(&p->sense_lock, flags);
 142 
 143         /* disable the interrupt in IIA */
 144         tmp = em_gio_read(p, GIO_IIA);
 145         tmp &= ~BIT(offset);
 146         em_gio_write(p, GIO_IIA, tmp);
 147 
 148         /* change the sense setting in IDT */
 149         tmp = em_gio_read(p, reg);
 150         tmp &= ~(0xf << shift);
 151         tmp |= value << shift;
 152         em_gio_write(p, reg, tmp);
 153 
 154         /* clear pending interrupts */
 155         em_gio_write(p, GIO_IIR, BIT(offset));
 156 
 157         /* enable the interrupt in IIA */
 158         tmp = em_gio_read(p, GIO_IIA);
 159         tmp |= BIT(offset);
 160         em_gio_write(p, GIO_IIA, tmp);
 161 
 162         spin_unlock_irqrestore(&p->sense_lock, flags);
 163 
 164         return 0;
 165 }
 166 
 167 static irqreturn_t em_gio_irq_handler(int irq, void *dev_id)
 168 {
 169         struct em_gio_priv *p = dev_id;
 170         unsigned long pending;
 171         unsigned int offset, irqs_handled = 0;
 172 
 173         while ((pending = em_gio_read(p, GIO_MST))) {
 174                 offset = __ffs(pending);
 175                 em_gio_write(p, GIO_IIR, BIT(offset));
 176                 generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
 177                 irqs_handled++;
 178         }
 179 
 180         return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
 181 }
 182 
 183 static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip)
 184 {
 185         return gpiochip_get_data(chip);
 186 }
 187 
 188 static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset)
 189 {
 190         em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset));
 191         return 0;
 192 }
 193 
 194 static int em_gio_get(struct gpio_chip *chip, unsigned offset)
 195 {
 196         return !!(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset));
 197 }
 198 
 199 static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
 200                          unsigned shift, int value)
 201 {
 202         /* upper 16 bits contains mask and lower 16 actual value */
 203         em_gio_write(gpio_to_priv(chip), reg,
 204                      (BIT(shift + 16)) | (value << shift));
 205 }
 206 
 207 static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
 208 {
 209         /* output is split into two registers */
 210         if (offset < 16)
 211                 __em_gio_set(chip, GIO_OL, offset, value);
 212         else
 213                 __em_gio_set(chip, GIO_OH, offset - 16, value);
 214 }
 215 
 216 static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
 217                                    int value)
 218 {
 219         /* write GPIO value to output before selecting output mode of pin */
 220         em_gio_set(chip, offset, value);
 221         em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset));
 222         return 0;
 223 }
 224 
 225 static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
 226 {
 227         return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 228 }
 229 
 230 static int em_gio_request(struct gpio_chip *chip, unsigned offset)
 231 {
 232         return pinctrl_gpio_request(chip->base + offset);
 233 }
 234 
 235 static void em_gio_free(struct gpio_chip *chip, unsigned offset)
 236 {
 237         pinctrl_gpio_free(chip->base + offset);
 238 
 239         /* Set the GPIO as an input to ensure that the next GPIO request won't
 240         * drive the GPIO pin as an output.
 241         */
 242         em_gio_direction_input(chip, offset);
 243 }
 244 
 245 static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq,
 246                                  irq_hw_number_t hwirq)
 247 {
 248         struct em_gio_priv *p = h->host_data;
 249 
 250         pr_debug("gio: map hw irq = %d, irq = %d\n", (int)hwirq, irq);
 251 
 252         irq_set_chip_data(irq, h->host_data);
 253         irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
 254         return 0;
 255 }
 256 
 257 static const struct irq_domain_ops em_gio_irq_domain_ops = {
 258         .map    = em_gio_irq_domain_map,
 259         .xlate  = irq_domain_xlate_twocell,
 260 };
 261 
 262 static void em_gio_irq_domain_remove(void *data)
 263 {
 264         struct irq_domain *domain = data;
 265 
 266         irq_domain_remove(domain);
 267 }
 268 
 269 static int em_gio_probe(struct platform_device *pdev)
 270 {
 271         struct em_gio_priv *p;
 272         struct resource *io[2], *irq[2];
 273         struct gpio_chip *gpio_chip;
 274         struct irq_chip *irq_chip;
 275         struct device *dev = &pdev->dev;
 276         const char *name = dev_name(dev);
 277         unsigned int ngpios;
 278         int ret;
 279 
 280         p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
 281         if (!p)
 282                 return -ENOMEM;
 283 
 284         p->pdev = pdev;
 285         platform_set_drvdata(pdev, p);
 286         spin_lock_init(&p->sense_lock);
 287 
 288         io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 289         io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 290         irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 291         irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
 292 
 293         if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
 294                 dev_err(dev, "missing IRQ or IOMEM\n");
 295                 return -EINVAL;
 296         }
 297 
 298         p->base0 = devm_ioremap_nocache(dev, io[0]->start,
 299                                         resource_size(io[0]));
 300         if (!p->base0)
 301                 return -ENOMEM;
 302 
 303         p->base1 = devm_ioremap_nocache(dev, io[1]->start,
 304                                    resource_size(io[1]));
 305         if (!p->base1)
 306                 return -ENOMEM;
 307 
 308         if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
 309                 dev_err(dev, "Missing ngpios OF property\n");
 310                 return -EINVAL;
 311         }
 312 
 313         gpio_chip = &p->gpio_chip;
 314         gpio_chip->of_node = dev->of_node;
 315         gpio_chip->direction_input = em_gio_direction_input;
 316         gpio_chip->get = em_gio_get;
 317         gpio_chip->direction_output = em_gio_direction_output;
 318         gpio_chip->set = em_gio_set;
 319         gpio_chip->to_irq = em_gio_to_irq;
 320         gpio_chip->request = em_gio_request;
 321         gpio_chip->free = em_gio_free;
 322         gpio_chip->label = name;
 323         gpio_chip->parent = dev;
 324         gpio_chip->owner = THIS_MODULE;
 325         gpio_chip->base = -1;
 326         gpio_chip->ngpio = ngpios;
 327 
 328         irq_chip = &p->irq_chip;
 329         irq_chip->name = name;
 330         irq_chip->irq_mask = em_gio_irq_disable;
 331         irq_chip->irq_unmask = em_gio_irq_enable;
 332         irq_chip->irq_set_type = em_gio_irq_set_type;
 333         irq_chip->irq_request_resources = em_gio_irq_reqres;
 334         irq_chip->irq_release_resources = em_gio_irq_relres;
 335         irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
 336 
 337         p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0,
 338                                               &em_gio_irq_domain_ops, p);
 339         if (!p->irq_domain) {
 340                 dev_err(dev, "cannot initialize irq domain\n");
 341                 return -ENXIO;
 342         }
 343 
 344         ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove,
 345                                        p->irq_domain);
 346         if (ret)
 347                 return ret;
 348 
 349         if (devm_request_irq(dev, irq[0]->start,
 350                              em_gio_irq_handler, 0, name, p)) {
 351                 dev_err(dev, "failed to request low IRQ\n");
 352                 return -ENOENT;
 353         }
 354 
 355         if (devm_request_irq(dev, irq[1]->start,
 356                              em_gio_irq_handler, 0, name, p)) {
 357                 dev_err(dev, "failed to request high IRQ\n");
 358                 return -ENOENT;
 359         }
 360 
 361         ret = devm_gpiochip_add_data(dev, gpio_chip, p);
 362         if (ret) {
 363                 dev_err(dev, "failed to add GPIO controller\n");
 364                 return ret;
 365         }
 366 
 367         return 0;
 368 }
 369 
 370 static const struct of_device_id em_gio_dt_ids[] = {
 371         { .compatible = "renesas,em-gio", },
 372         {},
 373 };
 374 MODULE_DEVICE_TABLE(of, em_gio_dt_ids);
 375 
 376 static struct platform_driver em_gio_device_driver = {
 377         .probe          = em_gio_probe,
 378         .driver         = {
 379                 .name   = "em_gio",
 380                 .of_match_table = em_gio_dt_ids,
 381         }
 382 };
 383 
 384 static int __init em_gio_init(void)
 385 {
 386         return platform_driver_register(&em_gio_device_driver);
 387 }
 388 postcore_initcall(em_gio_init);
 389 
 390 static void __exit em_gio_exit(void)
 391 {
 392         platform_driver_unregister(&em_gio_device_driver);
 393 }
 394 module_exit(em_gio_exit);
 395 
 396 MODULE_AUTHOR("Magnus Damm");
 397 MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver");
 398 MODULE_LICENSE("GPL v2");

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