root/drivers/gpio/gpio-htc-egpio.c

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

DEFINITIONS

This source file includes following definitions.
  1. egpio_writew
  2. egpio_readw
  3. ack_irqs
  4. egpio_ack
  5. egpio_mask
  6. egpio_unmask
  7. egpio_handler
  8. egpio_pos
  9. egpio_bit
  10. egpio_get
  11. egpio_direction_input
  12. egpio_set
  13. egpio_direction_output
  14. egpio_get_direction
  15. egpio_write_cache
  16. egpio_probe
  17. egpio_suspend
  18. egpio_resume
  19. egpio_init

   1 /*
   2  * Support for the GPIO/IRQ expander chips present on several HTC phones.
   3  * These are implemented in CPLD chips present on the board.
   4  *
   5  * Copyright (c) 2007 Kevin O'Connor <kevin@koconnor.net>
   6  * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
   7  *
   8  * This file may be distributed under the terms of the GNU GPL license.
   9  */
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/errno.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/irq.h>
  15 #include <linux/io.h>
  16 #include <linux/spinlock.h>
  17 #include <linux/platform_data/gpio-htc-egpio.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/slab.h>
  20 #include <linux/init.h>
  21 #include <linux/gpio/driver.h>
  22 
  23 struct egpio_chip {
  24         int              reg_start;
  25         int              cached_values;
  26         unsigned long    is_out;
  27         struct device    *dev;
  28         struct gpio_chip chip;
  29 };
  30 
  31 struct egpio_info {
  32         spinlock_t        lock;
  33 
  34         /* iomem info */
  35         void __iomem      *base_addr;
  36         int               bus_shift;    /* byte shift */
  37         int               reg_shift;    /* bit shift */
  38         int               reg_mask;
  39 
  40         /* irq info */
  41         int               ack_register;
  42         int               ack_write;
  43         u16               irqs_enabled;
  44         uint              irq_start;
  45         int               nirqs;
  46         uint              chained_irq;
  47 
  48         /* egpio info */
  49         struct egpio_chip *chip;
  50         int               nchips;
  51 };
  52 
  53 static inline void egpio_writew(u16 value, struct egpio_info *ei, int reg)
  54 {
  55         writew(value, ei->base_addr + (reg << ei->bus_shift));
  56 }
  57 
  58 static inline u16 egpio_readw(struct egpio_info *ei, int reg)
  59 {
  60         return readw(ei->base_addr + (reg << ei->bus_shift));
  61 }
  62 
  63 /*
  64  * IRQs
  65  */
  66 
  67 static inline void ack_irqs(struct egpio_info *ei)
  68 {
  69         egpio_writew(ei->ack_write, ei, ei->ack_register);
  70         pr_debug("EGPIO ack - write %x to base+%x\n",
  71                         ei->ack_write, ei->ack_register << ei->bus_shift);
  72 }
  73 
  74 static void egpio_ack(struct irq_data *data)
  75 {
  76 }
  77 
  78 /* There does not appear to be a way to proactively mask interrupts
  79  * on the egpio chip itself.  So, we simply ignore interrupts that
  80  * aren't desired. */
  81 static void egpio_mask(struct irq_data *data)
  82 {
  83         struct egpio_info *ei = irq_data_get_irq_chip_data(data);
  84         ei->irqs_enabled &= ~(1 << (data->irq - ei->irq_start));
  85         pr_debug("EGPIO mask %d %04x\n", data->irq, ei->irqs_enabled);
  86 }
  87 
  88 static void egpio_unmask(struct irq_data *data)
  89 {
  90         struct egpio_info *ei = irq_data_get_irq_chip_data(data);
  91         ei->irqs_enabled |= 1 << (data->irq - ei->irq_start);
  92         pr_debug("EGPIO unmask %d %04x\n", data->irq, ei->irqs_enabled);
  93 }
  94 
  95 static struct irq_chip egpio_muxed_chip = {
  96         .name           = "htc-egpio",
  97         .irq_ack        = egpio_ack,
  98         .irq_mask       = egpio_mask,
  99         .irq_unmask     = egpio_unmask,
 100 };
 101 
 102 static void egpio_handler(struct irq_desc *desc)
 103 {
 104         struct egpio_info *ei = irq_desc_get_handler_data(desc);
 105         int irqpin;
 106 
 107         /* Read current pins. */
 108         unsigned long readval = egpio_readw(ei, ei->ack_register);
 109         pr_debug("IRQ reg: %x\n", (unsigned int)readval);
 110         /* Ack/unmask interrupts. */
 111         ack_irqs(ei);
 112         /* Process all set pins. */
 113         readval &= ei->irqs_enabled;
 114         for_each_set_bit(irqpin, &readval, ei->nirqs) {
 115                 /* Run irq handler */
 116                 pr_debug("got IRQ %d\n", irqpin);
 117                 generic_handle_irq(ei->irq_start + irqpin);
 118         }
 119 }
 120 
 121 static inline int egpio_pos(struct egpio_info *ei, int bit)
 122 {
 123         return bit >> ei->reg_shift;
 124 }
 125 
 126 static inline int egpio_bit(struct egpio_info *ei, int bit)
 127 {
 128         return 1 << (bit & ((1 << ei->reg_shift)-1));
 129 }
 130 
 131 /*
 132  * Input pins
 133  */
 134 
 135 static int egpio_get(struct gpio_chip *chip, unsigned offset)
 136 {
 137         struct egpio_chip *egpio;
 138         struct egpio_info *ei;
 139         unsigned           bit;
 140         int                reg;
 141         int                value;
 142 
 143         pr_debug("egpio_get_value(%d)\n", chip->base + offset);
 144 
 145         egpio = gpiochip_get_data(chip);
 146         ei    = dev_get_drvdata(egpio->dev);
 147         bit   = egpio_bit(ei, offset);
 148         reg   = egpio->reg_start + egpio_pos(ei, offset);
 149 
 150         if (test_bit(offset, &egpio->is_out)) {
 151                 return !!(egpio->cached_values & (1 << offset));
 152         } else {
 153                 value = egpio_readw(ei, reg);
 154                 pr_debug("readw(%p + %x) = %x\n",
 155                          ei->base_addr, reg << ei->bus_shift, value);
 156                 return !!(value & bit);
 157         }
 158 }
 159 
 160 static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
 161 {
 162         struct egpio_chip *egpio;
 163 
 164         egpio = gpiochip_get_data(chip);
 165         return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
 166 }
 167 
 168 
 169 /*
 170  * Output pins
 171  */
 172 
 173 static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
 174 {
 175         unsigned long     flag;
 176         struct egpio_chip *egpio;
 177         struct egpio_info *ei;
 178         int               pos;
 179         int               reg;
 180         int               shift;
 181 
 182         pr_debug("egpio_set(%s, %d(%d), %d)\n",
 183                         chip->label, offset, offset+chip->base, value);
 184 
 185         egpio = gpiochip_get_data(chip);
 186         ei    = dev_get_drvdata(egpio->dev);
 187         pos   = egpio_pos(ei, offset);
 188         reg   = egpio->reg_start + pos;
 189         shift = pos << ei->reg_shift;
 190 
 191         pr_debug("egpio %s: reg %d = 0x%04x\n", value ? "set" : "clear",
 192                         reg, (egpio->cached_values >> shift) & ei->reg_mask);
 193 
 194         spin_lock_irqsave(&ei->lock, flag);
 195         if (value)
 196                 egpio->cached_values |= (1 << offset);
 197         else
 198                 egpio->cached_values &= ~(1 << offset);
 199         egpio_writew((egpio->cached_values >> shift) & ei->reg_mask, ei, reg);
 200         spin_unlock_irqrestore(&ei->lock, flag);
 201 }
 202 
 203 static int egpio_direction_output(struct gpio_chip *chip,
 204                                         unsigned offset, int value)
 205 {
 206         struct egpio_chip *egpio;
 207 
 208         egpio = gpiochip_get_data(chip);
 209         if (test_bit(offset, &egpio->is_out)) {
 210                 egpio_set(chip, offset, value);
 211                 return 0;
 212         } else {
 213                 return -EINVAL;
 214         }
 215 }
 216 
 217 static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
 218 {
 219         struct egpio_chip *egpio;
 220 
 221         egpio = gpiochip_get_data(chip);
 222 
 223         return !test_bit(offset, &egpio->is_out);
 224 }
 225 
 226 static void egpio_write_cache(struct egpio_info *ei)
 227 {
 228         int               i;
 229         struct egpio_chip *egpio;
 230         int               shift;
 231 
 232         for (i = 0; i < ei->nchips; i++) {
 233                 egpio = &(ei->chip[i]);
 234                 if (!egpio->is_out)
 235                         continue;
 236 
 237                 for (shift = 0; shift < egpio->chip.ngpio;
 238                                 shift += (1<<ei->reg_shift)) {
 239 
 240                         int reg = egpio->reg_start + egpio_pos(ei, shift);
 241 
 242                         if (!((egpio->is_out >> shift) & ei->reg_mask))
 243                                 continue;
 244 
 245                         pr_debug("EGPIO: setting %x to %x, was %x\n", reg,
 246                                 (egpio->cached_values >> shift) & ei->reg_mask,
 247                                 egpio_readw(ei, reg));
 248 
 249                         egpio_writew((egpio->cached_values >> shift)
 250                                         & ei->reg_mask, ei, reg);
 251                 }
 252         }
 253 }
 254 
 255 
 256 /*
 257  * Setup
 258  */
 259 
 260 static int __init egpio_probe(struct platform_device *pdev)
 261 {
 262         struct htc_egpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
 263         struct resource   *res;
 264         struct egpio_info *ei;
 265         struct gpio_chip  *chip;
 266         unsigned int      irq, irq_end;
 267         int               i;
 268         int               ret;
 269 
 270         /* Initialize ei data structure. */
 271         ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL);
 272         if (!ei)
 273                 return -ENOMEM;
 274 
 275         spin_lock_init(&ei->lock);
 276 
 277         /* Find chained irq */
 278         ret = -EINVAL;
 279         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 280         if (res)
 281                 ei->chained_irq = res->start;
 282 
 283         /* Map egpio chip into virtual address space. */
 284         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 285         if (!res)
 286                 goto fail;
 287         ei->base_addr = devm_ioremap_nocache(&pdev->dev, res->start,
 288                                              resource_size(res));
 289         if (!ei->base_addr)
 290                 goto fail;
 291         pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
 292 
 293         if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
 294                 goto fail;
 295         ei->bus_shift = fls(pdata->bus_width - 1) - 3;
 296         pr_debug("bus_shift = %d\n", ei->bus_shift);
 297 
 298         if ((pdata->reg_width != 8) && (pdata->reg_width != 16))
 299                 goto fail;
 300         ei->reg_shift = fls(pdata->reg_width - 1);
 301         pr_debug("reg_shift = %d\n", ei->reg_shift);
 302 
 303         ei->reg_mask = (1 << pdata->reg_width) - 1;
 304 
 305         platform_set_drvdata(pdev, ei);
 306 
 307         ei->nchips = pdata->num_chips;
 308         ei->chip = devm_kcalloc(&pdev->dev,
 309                                 ei->nchips, sizeof(struct egpio_chip),
 310                                 GFP_KERNEL);
 311         if (!ei->chip) {
 312                 ret = -ENOMEM;
 313                 goto fail;
 314         }
 315         for (i = 0; i < ei->nchips; i++) {
 316                 ei->chip[i].reg_start = pdata->chip[i].reg_start;
 317                 ei->chip[i].cached_values = pdata->chip[i].initial_values;
 318                 ei->chip[i].is_out = pdata->chip[i].direction;
 319                 ei->chip[i].dev = &(pdev->dev);
 320                 chip = &(ei->chip[i].chip);
 321                 chip->label = devm_kasprintf(&pdev->dev, GFP_KERNEL,
 322                                              "htc-egpio-%d",
 323                                              i);
 324                 if (!chip->label) {
 325                         ret = -ENOMEM;
 326                         goto fail;
 327                 }
 328                 chip->parent          = &pdev->dev;
 329                 chip->owner           = THIS_MODULE;
 330                 chip->get             = egpio_get;
 331                 chip->set             = egpio_set;
 332                 chip->direction_input = egpio_direction_input;
 333                 chip->direction_output = egpio_direction_output;
 334                 chip->get_direction   = egpio_get_direction;
 335                 chip->base            = pdata->chip[i].gpio_base;
 336                 chip->ngpio           = pdata->chip[i].num_gpios;
 337 
 338                 gpiochip_add_data(chip, &ei->chip[i]);
 339         }
 340 
 341         /* Set initial pin values */
 342         egpio_write_cache(ei);
 343 
 344         ei->irq_start = pdata->irq_base;
 345         ei->nirqs = pdata->num_irqs;
 346         ei->ack_register = pdata->ack_register;
 347 
 348         if (ei->chained_irq) {
 349                 /* Setup irq handlers */
 350                 ei->ack_write = 0xFFFF;
 351                 if (pdata->invert_acks)
 352                         ei->ack_write = 0;
 353                 irq_end = ei->irq_start + ei->nirqs;
 354                 for (irq = ei->irq_start; irq < irq_end; irq++) {
 355                         irq_set_chip_and_handler(irq, &egpio_muxed_chip,
 356                                                  handle_simple_irq);
 357                         irq_set_chip_data(irq, ei);
 358                         irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
 359                 }
 360                 irq_set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
 361                 irq_set_chained_handler_and_data(ei->chained_irq,
 362                                                  egpio_handler, ei);
 363                 ack_irqs(ei);
 364 
 365                 device_init_wakeup(&pdev->dev, 1);
 366         }
 367 
 368         return 0;
 369 
 370 fail:
 371         printk(KERN_ERR "EGPIO failed to setup\n");
 372         return ret;
 373 }
 374 
 375 #ifdef CONFIG_PM
 376 static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
 377 {
 378         struct egpio_info *ei = platform_get_drvdata(pdev);
 379 
 380         if (ei->chained_irq && device_may_wakeup(&pdev->dev))
 381                 enable_irq_wake(ei->chained_irq);
 382         return 0;
 383 }
 384 
 385 static int egpio_resume(struct platform_device *pdev)
 386 {
 387         struct egpio_info *ei = platform_get_drvdata(pdev);
 388 
 389         if (ei->chained_irq && device_may_wakeup(&pdev->dev))
 390                 disable_irq_wake(ei->chained_irq);
 391 
 392         /* Update registers from the cache, in case
 393            the CPLD was powered off during suspend */
 394         egpio_write_cache(ei);
 395         return 0;
 396 }
 397 #else
 398 #define egpio_suspend NULL
 399 #define egpio_resume NULL
 400 #endif
 401 
 402 
 403 static struct platform_driver egpio_driver = {
 404         .driver = {
 405                 .name = "htc-egpio",
 406                 .suppress_bind_attrs = true,
 407         },
 408         .suspend      = egpio_suspend,
 409         .resume       = egpio_resume,
 410 };
 411 
 412 static int __init egpio_init(void)
 413 {
 414         return platform_driver_probe(&egpio_driver, egpio_probe);
 415 }
 416 /* start early for dependencies */
 417 subsys_initcall(egpio_init);

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