Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Support for the GPIO/IRQ expander chips present on several HTC phones.
0003  * These are implemented in CPLD chips present on the board.
0004  *
0005  * Copyright (c) 2007 Kevin O'Connor <kevin@koconnor.net>
0006  * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
0007  *
0008  * This file may be distributed under the terms of the GNU GPL license.
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/errno.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/irq.h>
0015 #include <linux/io.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/platform_data/gpio-htc-egpio.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 #include <linux/init.h>
0021 #include <linux/gpio/driver.h>
0022 
0023 struct egpio_chip {
0024     int              reg_start;
0025     int              cached_values;
0026     unsigned long    is_out;
0027     struct device    *dev;
0028     struct gpio_chip chip;
0029 };
0030 
0031 struct egpio_info {
0032     spinlock_t        lock;
0033 
0034     /* iomem info */
0035     void __iomem      *base_addr;
0036     int               bus_shift;    /* byte shift */
0037     int               reg_shift;    /* bit shift */
0038     int               reg_mask;
0039 
0040     /* irq info */
0041     int               ack_register;
0042     int               ack_write;
0043     u16               irqs_enabled;
0044     uint              irq_start;
0045     int               nirqs;
0046     uint              chained_irq;
0047 
0048     /* egpio info */
0049     struct egpio_chip *chip;
0050     int               nchips;
0051 };
0052 
0053 static inline void egpio_writew(u16 value, struct egpio_info *ei, int reg)
0054 {
0055     writew(value, ei->base_addr + (reg << ei->bus_shift));
0056 }
0057 
0058 static inline u16 egpio_readw(struct egpio_info *ei, int reg)
0059 {
0060     return readw(ei->base_addr + (reg << ei->bus_shift));
0061 }
0062 
0063 /*
0064  * IRQs
0065  */
0066 
0067 static inline void ack_irqs(struct egpio_info *ei)
0068 {
0069     egpio_writew(ei->ack_write, ei, ei->ack_register);
0070     pr_debug("EGPIO ack - write %x to base+%x\n",
0071             ei->ack_write, ei->ack_register << ei->bus_shift);
0072 }
0073 
0074 static void egpio_ack(struct irq_data *data)
0075 {
0076 }
0077 
0078 /* There does not appear to be a way to proactively mask interrupts
0079  * on the egpio chip itself.  So, we simply ignore interrupts that
0080  * aren't desired. */
0081 static void egpio_mask(struct irq_data *data)
0082 {
0083     struct egpio_info *ei = irq_data_get_irq_chip_data(data);
0084     ei->irqs_enabled &= ~(1 << (data->irq - ei->irq_start));
0085     pr_debug("EGPIO mask %d %04x\n", data->irq, ei->irqs_enabled);
0086 }
0087 
0088 static void egpio_unmask(struct irq_data *data)
0089 {
0090     struct egpio_info *ei = irq_data_get_irq_chip_data(data);
0091     ei->irqs_enabled |= 1 << (data->irq - ei->irq_start);
0092     pr_debug("EGPIO unmask %d %04x\n", data->irq, ei->irqs_enabled);
0093 }
0094 
0095 static struct irq_chip egpio_muxed_chip = {
0096     .name       = "htc-egpio",
0097     .irq_ack    = egpio_ack,
0098     .irq_mask   = egpio_mask,
0099     .irq_unmask = egpio_unmask,
0100 };
0101 
0102 static void egpio_handler(struct irq_desc *desc)
0103 {
0104     struct egpio_info *ei = irq_desc_get_handler_data(desc);
0105     int irqpin;
0106 
0107     /* Read current pins. */
0108     unsigned long readval = egpio_readw(ei, ei->ack_register);
0109     pr_debug("IRQ reg: %x\n", (unsigned int)readval);
0110     /* Ack/unmask interrupts. */
0111     ack_irqs(ei);
0112     /* Process all set pins. */
0113     readval &= ei->irqs_enabled;
0114     for_each_set_bit(irqpin, &readval, ei->nirqs) {
0115         /* Run irq handler */
0116         pr_debug("got IRQ %d\n", irqpin);
0117         generic_handle_irq(ei->irq_start + irqpin);
0118     }
0119 }
0120 
0121 static inline int egpio_pos(struct egpio_info *ei, int bit)
0122 {
0123     return bit >> ei->reg_shift;
0124 }
0125 
0126 static inline int egpio_bit(struct egpio_info *ei, int bit)
0127 {
0128     return 1 << (bit & ((1 << ei->reg_shift)-1));
0129 }
0130 
0131 /*
0132  * Input pins
0133  */
0134 
0135 static int egpio_get(struct gpio_chip *chip, unsigned offset)
0136 {
0137     struct egpio_chip *egpio;
0138     struct egpio_info *ei;
0139     unsigned           bit;
0140     int                reg;
0141     int                value;
0142 
0143     pr_debug("egpio_get_value(%d)\n", chip->base + offset);
0144 
0145     egpio = gpiochip_get_data(chip);
0146     ei    = dev_get_drvdata(egpio->dev);
0147     bit   = egpio_bit(ei, offset);
0148     reg   = egpio->reg_start + egpio_pos(ei, offset);
0149 
0150     if (test_bit(offset, &egpio->is_out)) {
0151         return !!(egpio->cached_values & (1 << offset));
0152     } else {
0153         value = egpio_readw(ei, reg);
0154         pr_debug("readw(%p + %x) = %x\n",
0155              ei->base_addr, reg << ei->bus_shift, value);
0156         return !!(value & bit);
0157     }
0158 }
0159 
0160 static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
0161 {
0162     struct egpio_chip *egpio;
0163 
0164     egpio = gpiochip_get_data(chip);
0165     return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
0166 }
0167 
0168 
0169 /*
0170  * Output pins
0171  */
0172 
0173 static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
0174 {
0175     unsigned long     flag;
0176     struct egpio_chip *egpio;
0177     struct egpio_info *ei;
0178     int               pos;
0179     int               reg;
0180     int               shift;
0181 
0182     pr_debug("egpio_set(%s, %d(%d), %d)\n",
0183             chip->label, offset, offset+chip->base, value);
0184 
0185     egpio = gpiochip_get_data(chip);
0186     ei    = dev_get_drvdata(egpio->dev);
0187     pos   = egpio_pos(ei, offset);
0188     reg   = egpio->reg_start + pos;
0189     shift = pos << ei->reg_shift;
0190 
0191     pr_debug("egpio %s: reg %d = 0x%04x\n", value ? "set" : "clear",
0192             reg, (egpio->cached_values >> shift) & ei->reg_mask);
0193 
0194     spin_lock_irqsave(&ei->lock, flag);
0195     if (value)
0196         egpio->cached_values |= (1 << offset);
0197     else
0198         egpio->cached_values &= ~(1 << offset);
0199     egpio_writew((egpio->cached_values >> shift) & ei->reg_mask, ei, reg);
0200     spin_unlock_irqrestore(&ei->lock, flag);
0201 }
0202 
0203 static int egpio_direction_output(struct gpio_chip *chip,
0204                     unsigned offset, int value)
0205 {
0206     struct egpio_chip *egpio;
0207 
0208     egpio = gpiochip_get_data(chip);
0209     if (test_bit(offset, &egpio->is_out)) {
0210         egpio_set(chip, offset, value);
0211         return 0;
0212     } else {
0213         return -EINVAL;
0214     }
0215 }
0216 
0217 static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
0218 {
0219     struct egpio_chip *egpio;
0220 
0221     egpio = gpiochip_get_data(chip);
0222 
0223     if (test_bit(offset, &egpio->is_out))
0224         return GPIO_LINE_DIRECTION_OUT;
0225 
0226     return GPIO_LINE_DIRECTION_IN;
0227 }
0228 
0229 static void egpio_write_cache(struct egpio_info *ei)
0230 {
0231     int               i;
0232     struct egpio_chip *egpio;
0233     int               shift;
0234 
0235     for (i = 0; i < ei->nchips; i++) {
0236         egpio = &(ei->chip[i]);
0237         if (!egpio->is_out)
0238             continue;
0239 
0240         for (shift = 0; shift < egpio->chip.ngpio;
0241                 shift += (1<<ei->reg_shift)) {
0242 
0243             int reg = egpio->reg_start + egpio_pos(ei, shift);
0244 
0245             if (!((egpio->is_out >> shift) & ei->reg_mask))
0246                 continue;
0247 
0248             pr_debug("EGPIO: setting %x to %x, was %x\n", reg,
0249                 (egpio->cached_values >> shift) & ei->reg_mask,
0250                 egpio_readw(ei, reg));
0251 
0252             egpio_writew((egpio->cached_values >> shift)
0253                     & ei->reg_mask, ei, reg);
0254         }
0255     }
0256 }
0257 
0258 
0259 /*
0260  * Setup
0261  */
0262 
0263 static int __init egpio_probe(struct platform_device *pdev)
0264 {
0265     struct htc_egpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
0266     struct resource   *res;
0267     struct egpio_info *ei;
0268     struct gpio_chip  *chip;
0269     unsigned int      irq, irq_end;
0270     int               i;
0271 
0272     /* Initialize ei data structure. */
0273     ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL);
0274     if (!ei)
0275         return -ENOMEM;
0276 
0277     spin_lock_init(&ei->lock);
0278 
0279     /* Find chained irq */
0280     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
0281     if (res)
0282         ei->chained_irq = res->start;
0283 
0284     /* Map egpio chip into virtual address space. */
0285     ei->base_addr = devm_platform_ioremap_resource(pdev, 0);
0286     if (IS_ERR(ei->base_addr))
0287         return PTR_ERR(ei->base_addr);
0288 
0289     if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
0290         return -EINVAL;
0291 
0292     ei->bus_shift = fls(pdata->bus_width - 1) - 3;
0293     pr_debug("bus_shift = %d\n", ei->bus_shift);
0294 
0295     if ((pdata->reg_width != 8) && (pdata->reg_width != 16))
0296         return -EINVAL;
0297 
0298     ei->reg_shift = fls(pdata->reg_width - 1);
0299     pr_debug("reg_shift = %d\n", ei->reg_shift);
0300 
0301     ei->reg_mask = (1 << pdata->reg_width) - 1;
0302 
0303     platform_set_drvdata(pdev, ei);
0304 
0305     ei->nchips = pdata->num_chips;
0306     ei->chip = devm_kcalloc(&pdev->dev,
0307                 ei->nchips, sizeof(struct egpio_chip),
0308                 GFP_KERNEL);
0309     if (!ei->chip)
0310         return -ENOMEM;
0311 
0312     for (i = 0; i < ei->nchips; i++) {
0313         ei->chip[i].reg_start = pdata->chip[i].reg_start;
0314         ei->chip[i].cached_values = pdata->chip[i].initial_values;
0315         ei->chip[i].is_out = pdata->chip[i].direction;
0316         ei->chip[i].dev = &(pdev->dev);
0317         chip = &(ei->chip[i].chip);
0318         chip->label = devm_kasprintf(&pdev->dev, GFP_KERNEL,
0319                          "htc-egpio-%d",
0320                          i);
0321         if (!chip->label)
0322             return -ENOMEM;
0323 
0324         chip->parent          = &pdev->dev;
0325         chip->owner           = THIS_MODULE;
0326         chip->get             = egpio_get;
0327         chip->set             = egpio_set;
0328         chip->direction_input = egpio_direction_input;
0329         chip->direction_output = egpio_direction_output;
0330         chip->get_direction   = egpio_get_direction;
0331         chip->base            = pdata->chip[i].gpio_base;
0332         chip->ngpio           = pdata->chip[i].num_gpios;
0333 
0334         gpiochip_add_data(chip, &ei->chip[i]);
0335     }
0336 
0337     /* Set initial pin values */
0338     egpio_write_cache(ei);
0339 
0340     ei->irq_start = pdata->irq_base;
0341     ei->nirqs = pdata->num_irqs;
0342     ei->ack_register = pdata->ack_register;
0343 
0344     if (ei->chained_irq) {
0345         /* Setup irq handlers */
0346         ei->ack_write = 0xFFFF;
0347         if (pdata->invert_acks)
0348             ei->ack_write = 0;
0349         irq_end = ei->irq_start + ei->nirqs;
0350         for (irq = ei->irq_start; irq < irq_end; irq++) {
0351             irq_set_chip_and_handler(irq, &egpio_muxed_chip,
0352                          handle_simple_irq);
0353             irq_set_chip_data(irq, ei);
0354             irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0355         }
0356         irq_set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
0357         irq_set_chained_handler_and_data(ei->chained_irq,
0358                          egpio_handler, ei);
0359         ack_irqs(ei);
0360 
0361         device_init_wakeup(&pdev->dev, 1);
0362     }
0363 
0364     return 0;
0365 }
0366 
0367 #ifdef CONFIG_PM
0368 static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
0369 {
0370     struct egpio_info *ei = platform_get_drvdata(pdev);
0371 
0372     if (ei->chained_irq && device_may_wakeup(&pdev->dev))
0373         enable_irq_wake(ei->chained_irq);
0374     return 0;
0375 }
0376 
0377 static int egpio_resume(struct platform_device *pdev)
0378 {
0379     struct egpio_info *ei = platform_get_drvdata(pdev);
0380 
0381     if (ei->chained_irq && device_may_wakeup(&pdev->dev))
0382         disable_irq_wake(ei->chained_irq);
0383 
0384     /* Update registers from the cache, in case
0385        the CPLD was powered off during suspend */
0386     egpio_write_cache(ei);
0387     return 0;
0388 }
0389 #else
0390 #define egpio_suspend NULL
0391 #define egpio_resume NULL
0392 #endif
0393 
0394 
0395 static struct platform_driver egpio_driver = {
0396     .driver = {
0397         .name = "htc-egpio",
0398         .suppress_bind_attrs = true,
0399     },
0400     .suspend      = egpio_suspend,
0401     .resume       = egpio_resume,
0402 };
0403 
0404 static int __init egpio_init(void)
0405 {
0406     return platform_driver_probe(&egpio_driver, egpio_probe);
0407 }
0408 /* start early for dependencies */
0409 subsys_initcall(egpio_init);