Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1 433 lines 12 kB view raw
1/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 * 02110-1301, USA. 16 * 17 */ 18#define pr_fmt(fmt) "%s: " fmt, __func__ 19 20#include <linux/bitmap.h> 21#include <linux/bitops.h> 22#include <linux/gpio.h> 23#include <linux/init.h> 24#include <linux/interrupt.h> 25#include <linux/io.h> 26#include <linux/irq.h> 27#include <linux/module.h> 28#include <linux/platform_device.h> 29#include <linux/spinlock.h> 30 31#include <asm/mach/irq.h> 32 33#include <mach/msm_gpiomux.h> 34#include <mach/msm_iomap.h> 35 36/* Bits of interest in the GPIO_IN_OUT register. 37 */ 38enum { 39 GPIO_IN = 0, 40 GPIO_OUT = 1 41}; 42 43/* Bits of interest in the GPIO_INTR_STATUS register. 44 */ 45enum { 46 INTR_STATUS = 0, 47}; 48 49/* Bits of interest in the GPIO_CFG register. 50 */ 51enum { 52 GPIO_OE = 9, 53}; 54 55/* Bits of interest in the GPIO_INTR_CFG register. 56 * When a GPIO triggers, two separate decisions are made, controlled 57 * by two separate flags. 58 * 59 * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS 60 * register for that GPIO will be updated to reflect the triggering of that 61 * gpio. If this bit is 0, this register will not be updated. 62 * - Second, INTR_ENABLE controls whether an interrupt is triggered. 63 * 64 * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt 65 * can be triggered but the status register will not reflect it. 66 */ 67enum { 68 INTR_ENABLE = 0, 69 INTR_POL_CTL = 1, 70 INTR_DECT_CTL = 2, 71 INTR_RAW_STATUS_EN = 3, 72}; 73 74/* Codes of interest in GPIO_INTR_CFG_SU. 75 */ 76enum { 77 TARGET_PROC_SCORPION = 4, 78 TARGET_PROC_NONE = 7, 79}; 80 81 82#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio))) 83#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio))) 84#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio))) 85#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio))) 86#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio))) 87 88/** 89 * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure 90 * 91 * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By 92 * keeping track of which gpios are unmasked as irq sources, we avoid 93 * having to do readl calls on hundreds of iomapped registers each time 94 * the summary interrupt fires in order to locate the active interrupts. 95 * 96 * @wake_irqs: a bitmap for tracking which interrupt lines are enabled 97 * as wakeup sources. When the device is suspended, interrupts which are 98 * not wakeup sources are disabled. 99 * 100 * @dual_edge_irqs: a bitmap used to track which irqs are configured 101 * as dual-edge, as this is not supported by the hardware and requires 102 * some special handling in the driver. 103 */ 104struct msm_gpio_dev { 105 struct gpio_chip gpio_chip; 106 DECLARE_BITMAP(enabled_irqs, NR_GPIO_IRQS); 107 DECLARE_BITMAP(wake_irqs, NR_GPIO_IRQS); 108 DECLARE_BITMAP(dual_edge_irqs, NR_GPIO_IRQS); 109}; 110 111static DEFINE_SPINLOCK(tlmm_lock); 112 113static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip) 114{ 115 return container_of(chip, struct msm_gpio_dev, gpio_chip); 116} 117 118static inline void set_gpio_bits(unsigned n, void __iomem *reg) 119{ 120 writel(readl(reg) | n, reg); 121} 122 123static inline void clear_gpio_bits(unsigned n, void __iomem *reg) 124{ 125 writel(readl(reg) & ~n, reg); 126} 127 128static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) 129{ 130 return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN); 131} 132 133static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 134{ 135 writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset)); 136} 137 138static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 139{ 140 unsigned long irq_flags; 141 142 spin_lock_irqsave(&tlmm_lock, irq_flags); 143 clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset)); 144 spin_unlock_irqrestore(&tlmm_lock, irq_flags); 145 return 0; 146} 147 148static int msm_gpio_direction_output(struct gpio_chip *chip, 149 unsigned offset, 150 int val) 151{ 152 unsigned long irq_flags; 153 154 spin_lock_irqsave(&tlmm_lock, irq_flags); 155 msm_gpio_set(chip, offset, val); 156 set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset)); 157 spin_unlock_irqrestore(&tlmm_lock, irq_flags); 158 return 0; 159} 160 161static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) 162{ 163 return msm_gpiomux_get(chip->base + offset); 164} 165 166static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) 167{ 168 msm_gpiomux_put(chip->base + offset); 169} 170 171static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 172{ 173 return MSM_GPIO_TO_INT(chip->base + offset); 174} 175 176static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq) 177{ 178 return irq - MSM_GPIO_TO_INT(chip->base); 179} 180 181static struct msm_gpio_dev msm_gpio = { 182 .gpio_chip = { 183 .base = 0, 184 .ngpio = NR_GPIO_IRQS, 185 .direction_input = msm_gpio_direction_input, 186 .direction_output = msm_gpio_direction_output, 187 .get = msm_gpio_get, 188 .set = msm_gpio_set, 189 .to_irq = msm_gpio_to_irq, 190 .request = msm_gpio_request, 191 .free = msm_gpio_free, 192 }, 193}; 194 195/* For dual-edge interrupts in software, since the hardware has no 196 * such support: 197 * 198 * At appropriate moments, this function may be called to flip the polarity 199 * settings of both-edge irq lines to try and catch the next edge. 200 * 201 * The attempt is considered successful if: 202 * - the status bit goes high, indicating that an edge was caught, or 203 * - the input value of the gpio doesn't change during the attempt. 204 * If the value changes twice during the process, that would cause the first 205 * test to fail but would force the second, as two opposite 206 * transitions would cause a detection no matter the polarity setting. 207 * 208 * The do-loop tries to sledge-hammer closed the timing hole between 209 * the initial value-read and the polarity-write - if the line value changes 210 * during that window, an interrupt is lost, the new polarity setting is 211 * incorrect, and the first success test will fail, causing a retry. 212 * 213 * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c. 214 */ 215static void msm_gpio_update_dual_edge_pos(unsigned gpio) 216{ 217 int loop_limit = 100; 218 unsigned val, val2, intstat; 219 220 do { 221 val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); 222 if (val) 223 clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); 224 else 225 set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio)); 226 val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN); 227 intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS); 228 if (intstat || val == val2) 229 return; 230 } while (loop_limit-- > 0); 231 pr_err("dual-edge irq failed to stabilize, " 232 "interrupts dropped. %#08x != %#08x\n", 233 val, val2); 234} 235 236static void msm_gpio_irq_ack(struct irq_data *d) 237{ 238 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); 239 240 writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio)); 241 if (test_bit(gpio, msm_gpio.dual_edge_irqs)) 242 msm_gpio_update_dual_edge_pos(gpio); 243} 244 245static void msm_gpio_irq_mask(struct irq_data *d) 246{ 247 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); 248 unsigned long irq_flags; 249 250 spin_lock_irqsave(&tlmm_lock, irq_flags); 251 writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); 252 clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); 253 __clear_bit(gpio, msm_gpio.enabled_irqs); 254 spin_unlock_irqrestore(&tlmm_lock, irq_flags); 255} 256 257static void msm_gpio_irq_unmask(struct irq_data *d) 258{ 259 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); 260 unsigned long irq_flags; 261 262 spin_lock_irqsave(&tlmm_lock, irq_flags); 263 __set_bit(gpio, msm_gpio.enabled_irqs); 264 set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); 265 writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio)); 266 spin_unlock_irqrestore(&tlmm_lock, irq_flags); 267} 268 269static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) 270{ 271 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); 272 unsigned long irq_flags; 273 uint32_t bits; 274 275 spin_lock_irqsave(&tlmm_lock, irq_flags); 276 277 bits = readl(GPIO_INTR_CFG(gpio)); 278 279 if (flow_type & IRQ_TYPE_EDGE_BOTH) { 280 bits |= BIT(INTR_DECT_CTL); 281 __irq_set_handler_locked(d->irq, handle_edge_irq); 282 if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) 283 __set_bit(gpio, msm_gpio.dual_edge_irqs); 284 else 285 __clear_bit(gpio, msm_gpio.dual_edge_irqs); 286 } else { 287 bits &= ~BIT(INTR_DECT_CTL); 288 __irq_set_handler_locked(d->irq, handle_level_irq); 289 __clear_bit(gpio, msm_gpio.dual_edge_irqs); 290 } 291 292 if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) 293 bits |= BIT(INTR_POL_CTL); 294 else 295 bits &= ~BIT(INTR_POL_CTL); 296 297 writel(bits, GPIO_INTR_CFG(gpio)); 298 299 if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) 300 msm_gpio_update_dual_edge_pos(gpio); 301 302 spin_unlock_irqrestore(&tlmm_lock, irq_flags); 303 304 return 0; 305} 306 307/* 308 * When the summary IRQ is raised, any number of GPIO lines may be high. 309 * It is the job of the summary handler to find all those GPIO lines 310 * which have been set as summary IRQ lines and which are triggered, 311 * and to call their interrupt handlers. 312 */ 313static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc) 314{ 315 unsigned long i; 316 struct irq_chip *chip = irq_desc_get_chip(desc); 317 318 chained_irq_enter(chip, desc); 319 320 for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS); 321 i < NR_GPIO_IRQS; 322 i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) { 323 if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS)) 324 generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip, 325 i)); 326 } 327 328 chained_irq_exit(chip, desc); 329} 330 331static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) 332{ 333 int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); 334 335 if (on) { 336 if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) 337 irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1); 338 set_bit(gpio, msm_gpio.wake_irqs); 339 } else { 340 clear_bit(gpio, msm_gpio.wake_irqs); 341 if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) 342 irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0); 343 } 344 345 return 0; 346} 347 348static struct irq_chip msm_gpio_irq_chip = { 349 .name = "msmgpio", 350 .irq_mask = msm_gpio_irq_mask, 351 .irq_unmask = msm_gpio_irq_unmask, 352 .irq_ack = msm_gpio_irq_ack, 353 .irq_set_type = msm_gpio_irq_set_type, 354 .irq_set_wake = msm_gpio_irq_set_wake, 355}; 356 357static int __devinit msm_gpio_probe(struct platform_device *dev) 358{ 359 int i, irq, ret; 360 361 bitmap_zero(msm_gpio.enabled_irqs, NR_GPIO_IRQS); 362 bitmap_zero(msm_gpio.wake_irqs, NR_GPIO_IRQS); 363 bitmap_zero(msm_gpio.dual_edge_irqs, NR_GPIO_IRQS); 364 msm_gpio.gpio_chip.label = dev->name; 365 ret = gpiochip_add(&msm_gpio.gpio_chip); 366 if (ret < 0) 367 return ret; 368 369 for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) { 370 irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i); 371 irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, 372 handle_level_irq); 373 set_irq_flags(irq, IRQF_VALID); 374 } 375 376 irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ, 377 msm_summary_irq_handler); 378 return 0; 379} 380 381static int __devexit msm_gpio_remove(struct platform_device *dev) 382{ 383 int ret = gpiochip_remove(&msm_gpio.gpio_chip); 384 385 if (ret < 0) 386 return ret; 387 388 irq_set_handler(TLMM_SCSS_SUMMARY_IRQ, NULL); 389 390 return 0; 391} 392 393static struct platform_driver msm_gpio_driver = { 394 .probe = msm_gpio_probe, 395 .remove = __devexit_p(msm_gpio_remove), 396 .driver = { 397 .name = "msmgpio", 398 .owner = THIS_MODULE, 399 }, 400}; 401 402static struct platform_device msm_device_gpio = { 403 .name = "msmgpio", 404 .id = -1, 405}; 406 407static int __init msm_gpio_init(void) 408{ 409 int rc; 410 411 rc = platform_driver_register(&msm_gpio_driver); 412 if (!rc) { 413 rc = platform_device_register(&msm_device_gpio); 414 if (rc) 415 platform_driver_unregister(&msm_gpio_driver); 416 } 417 418 return rc; 419} 420 421static void __exit msm_gpio_exit(void) 422{ 423 platform_device_unregister(&msm_device_gpio); 424 platform_driver_unregister(&msm_gpio_driver); 425} 426 427postcore_initcall(msm_gpio_init); 428module_exit(msm_gpio_exit); 429 430MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); 431MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs"); 432MODULE_LICENSE("GPL v2"); 433MODULE_ALIAS("platform:msmgpio");