diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mfd/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/mfd/asic3.c | 388 |
2 files changed, 224 insertions, 166 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ae96bd6242f2..260bade0a5ec 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -17,7 +17,7 @@ config MFD_SM501 | |||
| 17 | 17 | ||
| 18 | config MFD_ASIC3 | 18 | config MFD_ASIC3 |
| 19 | bool "Support for Compaq ASIC3" | 19 | bool "Support for Compaq ASIC3" |
| 20 | depends on GENERIC_HARDIRQS && ARM | 20 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM |
| 21 | ---help--- | 21 | ---help--- |
| 22 | This driver supports the ASIC3 multifunction chip found on many | 22 | This driver supports the ASIC3 multifunction chip found on many |
| 23 | PDAs (mainly iPAQ and HTC based ones) | 23 | PDAs (mainly iPAQ and HTC based ones) |
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index ef8a492766a7..3b870e7fb3e1 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | * | 9 | * |
| 10 | * Copyright 2001 Compaq Computer Corporation. | 10 | * Copyright 2001 Compaq Computer Corporation. |
| 11 | * Copyright 2004-2005 Phil Blundell | 11 | * Copyright 2004-2005 Phil Blundell |
| 12 | * Copyright 2007 OpenedHand Ltd. | 12 | * Copyright 2007-2008 OpenedHand Ltd. |
| 13 | * | 13 | * |
| 14 | * Authors: Phil Blundell <pb@handhelds.org>, | 14 | * Authors: Phil Blundell <pb@handhelds.org>, |
| 15 | * Samuel Ortiz <sameo@openedhand.com> | 15 | * Samuel Ortiz <sameo@openedhand.com> |
| @@ -19,12 +19,26 @@ | |||
| 19 | #include <linux/version.h> | 19 | #include <linux/version.h> |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
| 22 | #include <linux/gpio.h> | ||
| 22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 23 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 25 | 26 | ||
| 26 | #include <linux/mfd/asic3.h> | 27 | #include <linux/mfd/asic3.h> |
| 27 | 28 | ||
| 29 | struct asic3 { | ||
| 30 | void __iomem *mapping; | ||
| 31 | unsigned int bus_shift; | ||
| 32 | unsigned int irq_nr; | ||
| 33 | unsigned int irq_base; | ||
| 34 | spinlock_t lock; | ||
| 35 | u16 irq_bothedge[4]; | ||
| 36 | struct gpio_chip gpio; | ||
| 37 | struct device *dev; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); | ||
| 41 | |||
| 28 | static inline void asic3_write_register(struct asic3 *asic, | 42 | static inline void asic3_write_register(struct asic3 *asic, |
| 29 | unsigned int reg, u32 value) | 43 | unsigned int reg, u32 value) |
| 30 | { | 44 | { |
| @@ -41,8 +55,8 @@ static inline u32 asic3_read_register(struct asic3 *asic, | |||
| 41 | 55 | ||
| 42 | /* IRQs */ | 56 | /* IRQs */ |
| 43 | #define MAX_ASIC_ISR_LOOPS 20 | 57 | #define MAX_ASIC_ISR_LOOPS 20 |
| 44 | #define ASIC3_GPIO_Base_INCR \ | 58 | #define ASIC3_GPIO_BASE_INCR \ |
| 45 | (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base) | 59 | (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE) |
| 46 | 60 | ||
| 47 | static void asic3_irq_flip_edge(struct asic3 *asic, | 61 | static void asic3_irq_flip_edge(struct asic3 *asic, |
| 48 | u32 base, int bit) | 62 | u32 base, int bit) |
| @@ -52,10 +66,10 @@ static void asic3_irq_flip_edge(struct asic3 *asic, | |||
| 52 | 66 | ||
| 53 | spin_lock_irqsave(&asic->lock, flags); | 67 | spin_lock_irqsave(&asic->lock, flags); |
| 54 | edge = asic3_read_register(asic, | 68 | edge = asic3_read_register(asic, |
| 55 | base + ASIC3_GPIO_EdgeTrigger); | 69 | base + ASIC3_GPIO_EDGE_TRIGGER); |
| 56 | edge ^= bit; | 70 | edge ^= bit; |
| 57 | asic3_write_register(asic, | 71 | asic3_write_register(asic, |
| 58 | base + ASIC3_GPIO_EdgeTrigger, edge); | 72 | base + ASIC3_GPIO_EDGE_TRIGGER, edge); |
| 59 | spin_unlock_irqrestore(&asic->lock, flags); | 73 | spin_unlock_irqrestore(&asic->lock, flags); |
| 60 | } | 74 | } |
| 61 | 75 | ||
| @@ -75,7 +89,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
| 75 | 89 | ||
| 76 | spin_lock_irqsave(&asic->lock, flags); | 90 | spin_lock_irqsave(&asic->lock, flags); |
| 77 | status = asic3_read_register(asic, | 91 | status = asic3_read_register(asic, |
| 78 | ASIC3_OFFSET(INTR, PIntStat)); | 92 | ASIC3_OFFSET(INTR, P_INT_STAT)); |
| 79 | spin_unlock_irqrestore(&asic->lock, flags); | 93 | spin_unlock_irqrestore(&asic->lock, flags); |
| 80 | 94 | ||
| 81 | /* Check all ten register bits */ | 95 | /* Check all ten register bits */ |
| @@ -87,17 +101,17 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
| 87 | if (status & (1 << bank)) { | 101 | if (status & (1 << bank)) { |
| 88 | unsigned long base, istat; | 102 | unsigned long base, istat; |
| 89 | 103 | ||
| 90 | base = ASIC3_GPIO_A_Base | 104 | base = ASIC3_GPIO_A_BASE |
| 91 | + bank * ASIC3_GPIO_Base_INCR; | 105 | + bank * ASIC3_GPIO_BASE_INCR; |
| 92 | 106 | ||
| 93 | spin_lock_irqsave(&asic->lock, flags); | 107 | spin_lock_irqsave(&asic->lock, flags); |
| 94 | istat = asic3_read_register(asic, | 108 | istat = asic3_read_register(asic, |
| 95 | base + | 109 | base + |
| 96 | ASIC3_GPIO_IntStatus); | 110 | ASIC3_GPIO_INT_STATUS); |
| 97 | /* Clearing IntStatus */ | 111 | /* Clearing IntStatus */ |
| 98 | asic3_write_register(asic, | 112 | asic3_write_register(asic, |
| 99 | base + | 113 | base + |
| 100 | ASIC3_GPIO_IntStatus, 0); | 114 | ASIC3_GPIO_INT_STATUS, 0); |
| 101 | spin_unlock_irqrestore(&asic->lock, flags); | 115 | spin_unlock_irqrestore(&asic->lock, flags); |
| 102 | 116 | ||
| 103 | for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { | 117 | for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { |
| @@ -123,7 +137,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
| 123 | for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { | 137 | for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { |
| 124 | /* They start at bit 4 and go up */ | 138 | /* They start at bit 4 and go up */ |
| 125 | if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { | 139 | if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { |
| 126 | desc = irq_desc + + i; | 140 | desc = irq_desc + asic->irq_base + i; |
| 127 | desc->handle_irq(asic->irq_base + i, | 141 | desc->handle_irq(asic->irq_base + i, |
| 128 | desc); | 142 | desc); |
| 129 | } | 143 | } |
| @@ -131,8 +145,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
| 131 | } | 145 | } |
| 132 | 146 | ||
| 133 | if (iter >= MAX_ASIC_ISR_LOOPS) | 147 | if (iter >= MAX_ASIC_ISR_LOOPS) |
| 134 | printk(KERN_ERR "%s: interrupt processing overrun\n", | 148 | dev_err(asic->dev, "interrupt processing overrun\n"); |
| 135 | __func__); | ||
| 136 | } | 149 | } |
| 137 | 150 | ||
| 138 | static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) | 151 | static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) |
| @@ -141,7 +154,7 @@ static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) | |||
| 141 | 154 | ||
| 142 | n = (irq - asic->irq_base) >> 4; | 155 | n = (irq - asic->irq_base) >> 4; |
| 143 | 156 | ||
| 144 | return (n * (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base)); | 157 | return (n * (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE)); |
| 145 | } | 158 | } |
| 146 | 159 | ||
| 147 | static inline int asic3_irq_to_index(struct asic3 *asic, int irq) | 160 | static inline int asic3_irq_to_index(struct asic3 *asic, int irq) |
| @@ -159,9 +172,9 @@ static void asic3_mask_gpio_irq(unsigned int irq) | |||
| 159 | index = asic3_irq_to_index(asic, irq); | 172 | index = asic3_irq_to_index(asic, irq); |
| 160 | 173 | ||
| 161 | spin_lock_irqsave(&asic->lock, flags); | 174 | spin_lock_irqsave(&asic->lock, flags); |
| 162 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | 175 | val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); |
| 163 | val |= 1 << index; | 176 | val |= 1 << index; |
| 164 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | 177 | asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); |
| 165 | spin_unlock_irqrestore(&asic->lock, flags); | 178 | spin_unlock_irqrestore(&asic->lock, flags); |
| 166 | } | 179 | } |
| 167 | 180 | ||
| @@ -173,15 +186,15 @@ static void asic3_mask_irq(unsigned int irq) | |||
| 173 | 186 | ||
| 174 | spin_lock_irqsave(&asic->lock, flags); | 187 | spin_lock_irqsave(&asic->lock, flags); |
| 175 | regval = asic3_read_register(asic, | 188 | regval = asic3_read_register(asic, |
| 176 | ASIC3_INTR_Base + | 189 | ASIC3_INTR_BASE + |
| 177 | ASIC3_INTR_IntMask); | 190 | ASIC3_INTR_INT_MASK); |
| 178 | 191 | ||
| 179 | regval &= ~(ASIC3_INTMASK_MASK0 << | 192 | regval &= ~(ASIC3_INTMASK_MASK0 << |
| 180 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | 193 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); |
| 181 | 194 | ||
| 182 | asic3_write_register(asic, | 195 | asic3_write_register(asic, |
| 183 | ASIC3_INTR_Base + | 196 | ASIC3_INTR_BASE + |
| 184 | ASIC3_INTR_IntMask, | 197 | ASIC3_INTR_INT_MASK, |
| 185 | regval); | 198 | regval); |
| 186 | spin_unlock_irqrestore(&asic->lock, flags); | 199 | spin_unlock_irqrestore(&asic->lock, flags); |
| 187 | } | 200 | } |
| @@ -196,9 +209,9 @@ static void asic3_unmask_gpio_irq(unsigned int irq) | |||
| 196 | index = asic3_irq_to_index(asic, irq); | 209 | index = asic3_irq_to_index(asic, irq); |
| 197 | 210 | ||
| 198 | spin_lock_irqsave(&asic->lock, flags); | 211 | spin_lock_irqsave(&asic->lock, flags); |
| 199 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | 212 | val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); |
| 200 | val &= ~(1 << index); | 213 | val &= ~(1 << index); |
| 201 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | 214 | asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); |
| 202 | spin_unlock_irqrestore(&asic->lock, flags); | 215 | spin_unlock_irqrestore(&asic->lock, flags); |
| 203 | } | 216 | } |
| 204 | 217 | ||
| @@ -210,15 +223,15 @@ static void asic3_unmask_irq(unsigned int irq) | |||
| 210 | 223 | ||
| 211 | spin_lock_irqsave(&asic->lock, flags); | 224 | spin_lock_irqsave(&asic->lock, flags); |
| 212 | regval = asic3_read_register(asic, | 225 | regval = asic3_read_register(asic, |
| 213 | ASIC3_INTR_Base + | 226 | ASIC3_INTR_BASE + |
| 214 | ASIC3_INTR_IntMask); | 227 | ASIC3_INTR_INT_MASK); |
| 215 | 228 | ||
| 216 | regval |= (ASIC3_INTMASK_MASK0 << | 229 | regval |= (ASIC3_INTMASK_MASK0 << |
| 217 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | 230 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); |
| 218 | 231 | ||
| 219 | asic3_write_register(asic, | 232 | asic3_write_register(asic, |
| 220 | ASIC3_INTR_Base + | 233 | ASIC3_INTR_BASE + |
| 221 | ASIC3_INTR_IntMask, | 234 | ASIC3_INTR_INT_MASK, |
| 222 | regval); | 235 | regval); |
| 223 | spin_unlock_irqrestore(&asic->lock, flags); | 236 | spin_unlock_irqrestore(&asic->lock, flags); |
| 224 | } | 237 | } |
| @@ -236,11 +249,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 236 | 249 | ||
| 237 | spin_lock_irqsave(&asic->lock, flags); | 250 | spin_lock_irqsave(&asic->lock, flags); |
| 238 | level = asic3_read_register(asic, | 251 | level = asic3_read_register(asic, |
| 239 | bank + ASIC3_GPIO_LevelTrigger); | 252 | bank + ASIC3_GPIO_LEVEL_TRIGGER); |
| 240 | edge = asic3_read_register(asic, | 253 | edge = asic3_read_register(asic, |
| 241 | bank + ASIC3_GPIO_EdgeTrigger); | 254 | bank + ASIC3_GPIO_EDGE_TRIGGER); |
| 242 | trigger = asic3_read_register(asic, | 255 | trigger = asic3_read_register(asic, |
| 243 | bank + ASIC3_GPIO_TriggerType); | 256 | bank + ASIC3_GPIO_TRIGGER_TYPE); |
| 244 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; | 257 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; |
| 245 | 258 | ||
| 246 | if (type == IRQT_RISING) { | 259 | if (type == IRQT_RISING) { |
| @@ -251,7 +264,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 251 | edge &= ~bit; | 264 | edge &= ~bit; |
| 252 | } else if (type == IRQT_BOTHEDGE) { | 265 | } else if (type == IRQT_BOTHEDGE) { |
| 253 | trigger |= bit; | 266 | trigger |= bit; |
| 254 | if (asic3_gpio_get_value(asic, irq - asic->irq_base)) | 267 | if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base)) |
| 255 | edge &= ~bit; | 268 | edge &= ~bit; |
| 256 | else | 269 | else |
| 257 | edge |= bit; | 270 | edge |= bit; |
| @@ -268,13 +281,13 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 268 | * be careful to not unmask them if mask was also called. | 281 | * be careful to not unmask them if mask was also called. |
| 269 | * Probably need internal state for mask. | 282 | * Probably need internal state for mask. |
| 270 | */ | 283 | */ |
| 271 | printk(KERN_NOTICE "asic3: irq type not changed.\n"); | 284 | dev_notice(asic->dev, "irq type not changed\n"); |
| 272 | } | 285 | } |
| 273 | asic3_write_register(asic, bank + ASIC3_GPIO_LevelTrigger, | 286 | asic3_write_register(asic, bank + ASIC3_GPIO_LEVEL_TRIGGER, |
| 274 | level); | 287 | level); |
| 275 | asic3_write_register(asic, bank + ASIC3_GPIO_EdgeTrigger, | 288 | asic3_write_register(asic, bank + ASIC3_GPIO_EDGE_TRIGGER, |
| 276 | edge); | 289 | edge); |
| 277 | asic3_write_register(asic, bank + ASIC3_GPIO_TriggerType, | 290 | asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE, |
| 278 | trigger); | 291 | trigger); |
| 279 | spin_unlock_irqrestore(&asic->lock, flags); | 292 | spin_unlock_irqrestore(&asic->lock, flags); |
| 280 | return 0; | 293 | return 0; |
| @@ -295,11 +308,12 @@ static struct irq_chip asic3_irq_chip = { | |||
| 295 | .unmask = asic3_unmask_irq, | 308 | .unmask = asic3_unmask_irq, |
| 296 | }; | 309 | }; |
| 297 | 310 | ||
| 298 | static int asic3_irq_probe(struct platform_device *pdev) | 311 | static int __init asic3_irq_probe(struct platform_device *pdev) |
| 299 | { | 312 | { |
| 300 | struct asic3 *asic = platform_get_drvdata(pdev); | 313 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 301 | unsigned long clksel = 0; | 314 | unsigned long clksel = 0; |
| 302 | unsigned int irq, irq_base; | 315 | unsigned int irq, irq_base; |
| 316 | int map_size; | ||
| 303 | 317 | ||
| 304 | asic->irq_nr = platform_get_irq(pdev, 0); | 318 | asic->irq_nr = platform_get_irq(pdev, 0); |
| 305 | if (asic->irq_nr < 0) | 319 | if (asic->irq_nr < 0) |
| @@ -323,7 +337,7 @@ static int asic3_irq_probe(struct platform_device *pdev) | |||
| 323 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 337 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
| 324 | } | 338 | } |
| 325 | 339 | ||
| 326 | asic3_write_register(asic, ASIC3_OFFSET(INTR, IntMask), | 340 | asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK), |
| 327 | ASIC3_INTMASK_GINTMASK); | 341 | ASIC3_INTMASK_GINTMASK); |
| 328 | 342 | ||
| 329 | set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); | 343 | set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); |
| @@ -350,149 +364,182 @@ static void asic3_irq_remove(struct platform_device *pdev) | |||
| 350 | } | 364 | } |
| 351 | 365 | ||
| 352 | /* GPIOs */ | 366 | /* GPIOs */ |
| 353 | static inline u32 asic3_get_gpio(struct asic3 *asic, unsigned int base, | 367 | static int asic3_gpio_direction(struct gpio_chip *chip, |
| 354 | unsigned int function) | 368 | unsigned offset, int out) |
| 355 | { | ||
| 356 | return asic3_read_register(asic, base + function); | ||
| 357 | } | ||
| 358 | |||
| 359 | static void asic3_set_gpio(struct asic3 *asic, unsigned int base, | ||
| 360 | unsigned int function, u32 bits, u32 val) | ||
| 361 | { | 369 | { |
| 370 | u32 mask = ASIC3_GPIO_TO_MASK(offset), out_reg; | ||
| 371 | unsigned int gpio_base; | ||
| 362 | unsigned long flags; | 372 | unsigned long flags; |
| 373 | struct asic3 *asic; | ||
| 374 | |||
| 375 | asic = container_of(chip, struct asic3, gpio); | ||
| 376 | gpio_base = ASIC3_GPIO_TO_BASE(offset); | ||
| 377 | |||
| 378 | if (gpio_base > ASIC3_GPIO_D_BASE) { | ||
| 379 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", | ||
| 380 | gpio_base, offset); | ||
| 381 | return -EINVAL; | ||
| 382 | } | ||
| 363 | 383 | ||
| 364 | spin_lock_irqsave(&asic->lock, flags); | 384 | spin_lock_irqsave(&asic->lock, flags); |
| 365 | val |= (asic3_read_register(asic, base + function) & ~bits); | ||
| 366 | 385 | ||
| 367 | asic3_write_register(asic, base + function, val); | 386 | out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION); |
| 387 | |||
| 388 | /* Input is 0, Output is 1 */ | ||
| 389 | if (out) | ||
| 390 | out_reg |= mask; | ||
| 391 | else | ||
| 392 | out_reg &= ~mask; | ||
| 393 | |||
| 394 | asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg); | ||
| 395 | |||
| 368 | spin_unlock_irqrestore(&asic->lock, flags); | 396 | spin_unlock_irqrestore(&asic->lock, flags); |
| 397 | |||
| 398 | return 0; | ||
| 399 | |||
| 400 | } | ||
| 401 | |||
| 402 | static int asic3_gpio_direction_input(struct gpio_chip *chip, | ||
| 403 | unsigned offset) | ||
| 404 | { | ||
| 405 | return asic3_gpio_direction(chip, offset, 0); | ||
| 406 | } | ||
| 407 | |||
| 408 | static int asic3_gpio_direction_output(struct gpio_chip *chip, | ||
| 409 | unsigned offset, int value) | ||
| 410 | { | ||
| 411 | return asic3_gpio_direction(chip, offset, 1); | ||
| 369 | } | 412 | } |
| 370 | 413 | ||
| 371 | #define asic3_get_gpio_a(asic, fn) \ | 414 | static int asic3_gpio_get(struct gpio_chip *chip, |
| 372 | asic3_get_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn) | 415 | unsigned offset) |
| 373 | #define asic3_get_gpio_b(asic, fn) \ | ||
| 374 | asic3_get_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn) | ||
| 375 | #define asic3_get_gpio_c(asic, fn) \ | ||
| 376 | asic3_get_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn) | ||
| 377 | #define asic3_get_gpio_d(asic, fn) \ | ||
| 378 | asic3_get_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn) | ||
| 379 | |||
| 380 | #define asic3_set_gpio_a(asic, fn, bits, val) \ | ||
| 381 | asic3_set_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn, bits, val) | ||
| 382 | #define asic3_set_gpio_b(asic, fn, bits, val) \ | ||
| 383 | asic3_set_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn, bits, val) | ||
| 384 | #define asic3_set_gpio_c(asic, fn, bits, val) \ | ||
| 385 | asic3_set_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn, bits, val) | ||
| 386 | #define asic3_set_gpio_d(asic, fn, bits, val) \ | ||
| 387 | asic3_set_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn, bits, val) | ||
| 388 | |||
| 389 | #define asic3_set_gpio_banks(asic, fn, bits, pdata, field) \ | ||
| 390 | do { \ | ||
| 391 | asic3_set_gpio_a((asic), fn, (bits), (pdata)->gpio_a.field); \ | ||
| 392 | asic3_set_gpio_b((asic), fn, (bits), (pdata)->gpio_b.field); \ | ||
| 393 | asic3_set_gpio_c((asic), fn, (bits), (pdata)->gpio_c.field); \ | ||
| 394 | asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ | ||
| 395 | } while (0) | ||
| 396 | |||
| 397 | int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) | ||
| 398 | { | 416 | { |
| 399 | u32 mask = ASIC3_GPIO_bit(gpio); | 417 | unsigned int gpio_base; |
| 400 | 418 | u32 mask = ASIC3_GPIO_TO_MASK(offset); | |
| 401 | switch (gpio >> 4) { | 419 | struct asic3 *asic; |
| 402 | case ASIC3_GPIO_BANK_A: | 420 | |
| 403 | return asic3_get_gpio_a(asic, Status) & mask; | 421 | asic = container_of(chip, struct asic3, gpio); |
| 404 | case ASIC3_GPIO_BANK_B: | 422 | gpio_base = ASIC3_GPIO_TO_BASE(offset); |
| 405 | return asic3_get_gpio_b(asic, Status) & mask; | 423 | |
| 406 | case ASIC3_GPIO_BANK_C: | 424 | if (gpio_base > ASIC3_GPIO_D_BASE) { |
| 407 | return asic3_get_gpio_c(asic, Status) & mask; | 425 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", |
| 408 | case ASIC3_GPIO_BANK_D: | 426 | gpio_base, offset); |
| 409 | return asic3_get_gpio_d(asic, Status) & mask; | ||
| 410 | default: | ||
| 411 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
| 412 | __func__, gpio); | ||
| 413 | return -EINVAL; | 427 | return -EINVAL; |
| 414 | } | 428 | } |
| 429 | |||
| 430 | return asic3_read_register(asic, gpio_base + ASIC3_GPIO_STATUS) & mask; | ||
| 415 | } | 431 | } |
| 416 | EXPORT_SYMBOL(asic3_gpio_get_value); | ||
| 417 | 432 | ||
| 418 | void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) | 433 | static void asic3_gpio_set(struct gpio_chip *chip, |
| 434 | unsigned offset, int value) | ||
| 419 | { | 435 | { |
| 420 | u32 mask = ASIC3_GPIO_bit(gpio); | 436 | u32 mask, out_reg; |
| 421 | u32 bitval = 0; | 437 | unsigned int gpio_base; |
| 422 | if (val) | 438 | unsigned long flags; |
| 423 | bitval = mask; | 439 | struct asic3 *asic; |
| 424 | 440 | ||
| 425 | switch (gpio >> 4) { | 441 | asic = container_of(chip, struct asic3, gpio); |
| 426 | case ASIC3_GPIO_BANK_A: | 442 | gpio_base = ASIC3_GPIO_TO_BASE(offset); |
| 427 | asic3_set_gpio_a(asic, Out, mask, bitval); | 443 | |
| 428 | return; | 444 | if (gpio_base > ASIC3_GPIO_D_BASE) { |
| 429 | case ASIC3_GPIO_BANK_B: | 445 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", |
| 430 | asic3_set_gpio_b(asic, Out, mask, bitval); | 446 | gpio_base, offset); |
| 431 | return; | ||
| 432 | case ASIC3_GPIO_BANK_C: | ||
| 433 | asic3_set_gpio_c(asic, Out, mask, bitval); | ||
| 434 | return; | ||
| 435 | case ASIC3_GPIO_BANK_D: | ||
| 436 | asic3_set_gpio_d(asic, Out, mask, bitval); | ||
| 437 | return; | ||
| 438 | default: | ||
| 439 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
| 440 | __func__, gpio); | ||
| 441 | return; | 447 | return; |
| 442 | } | 448 | } |
| 449 | |||
| 450 | mask = ASIC3_GPIO_TO_MASK(offset); | ||
| 451 | |||
| 452 | spin_lock_irqsave(&asic->lock, flags); | ||
| 453 | |||
| 454 | out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT); | ||
| 455 | |||
| 456 | if (value) | ||
| 457 | out_reg |= mask; | ||
| 458 | else | ||
| 459 | out_reg &= ~mask; | ||
| 460 | |||
| 461 | asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg); | ||
| 462 | |||
| 463 | spin_unlock_irqrestore(&asic->lock, flags); | ||
| 464 | |||
| 465 | return; | ||
| 443 | } | 466 | } |
| 444 | EXPORT_SYMBOL(asic3_gpio_set_value); | ||
| 445 | 467 | ||
| 446 | static int asic3_gpio_probe(struct platform_device *pdev) | 468 | static __init int asic3_gpio_probe(struct platform_device *pdev, |
| 469 | u16 *gpio_config, int num) | ||
| 447 | { | 470 | { |
| 448 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | ||
| 449 | struct asic3 *asic = platform_get_drvdata(pdev); | 471 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 472 | u16 alt_reg[ASIC3_NUM_GPIO_BANKS]; | ||
| 473 | u16 out_reg[ASIC3_NUM_GPIO_BANKS]; | ||
| 474 | u16 dir_reg[ASIC3_NUM_GPIO_BANKS]; | ||
| 475 | int i; | ||
| 476 | |||
| 477 | memzero(alt_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
| 478 | memzero(out_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
| 479 | memzero(dir_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
| 480 | |||
| 481 | /* Enable all GPIOs */ | ||
| 482 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff); | ||
| 483 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, MASK), 0xffff); | ||
| 484 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, MASK), 0xffff); | ||
| 485 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, MASK), 0xffff); | ||
| 486 | |||
| 487 | for (i = 0; i < num; i++) { | ||
| 488 | u8 alt, pin, dir, init, bank_num, bit_num; | ||
| 489 | u16 config = gpio_config[i]; | ||
| 490 | |||
| 491 | pin = ASIC3_CONFIG_GPIO_PIN(config); | ||
| 492 | alt = ASIC3_CONFIG_GPIO_ALT(config); | ||
| 493 | dir = ASIC3_CONFIG_GPIO_DIR(config); | ||
| 494 | init = ASIC3_CONFIG_GPIO_INIT(config); | ||
| 495 | |||
| 496 | bank_num = ASIC3_GPIO_TO_BANK(pin); | ||
| 497 | bit_num = ASIC3_GPIO_TO_BIT(pin); | ||
| 498 | |||
| 499 | alt_reg[bank_num] |= (alt << bit_num); | ||
| 500 | out_reg[bank_num] |= (init << bit_num); | ||
| 501 | dir_reg[bank_num] |= (dir << bit_num); | ||
| 502 | } | ||
| 450 | 503 | ||
| 451 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); | 504 | for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) { |
| 452 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff); | 505 | asic3_write_register(asic, |
| 453 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, Mask), 0xffff); | 506 | ASIC3_BANK_TO_BASE(i) + |
| 454 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, Mask), 0xffff); | 507 | ASIC3_GPIO_DIRECTION, |
| 455 | 508 | dir_reg[i]); | |
| 456 | asic3_set_gpio_a(asic, SleepMask, 0xffff, 0xffff); | 509 | asic3_write_register(asic, |
| 457 | asic3_set_gpio_b(asic, SleepMask, 0xffff, 0xffff); | 510 | ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_OUT, |
| 458 | asic3_set_gpio_c(asic, SleepMask, 0xffff, 0xffff); | 511 | out_reg[i]); |
| 459 | asic3_set_gpio_d(asic, SleepMask, 0xffff, 0xffff); | 512 | asic3_write_register(asic, |
| 460 | 513 | ASIC3_BANK_TO_BASE(i) + | |
| 461 | if (pdata) { | 514 | ASIC3_GPIO_ALT_FUNCTION, |
| 462 | asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init); | 515 | alt_reg[i]); |
| 463 | asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir); | ||
| 464 | asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata, | ||
| 465 | sleep_mask); | ||
| 466 | asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out); | ||
| 467 | asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata, | ||
| 468 | batt_fault_out); | ||
| 469 | asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata, | ||
| 470 | sleep_conf); | ||
| 471 | asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata, | ||
| 472 | alt_function); | ||
| 473 | } | 516 | } |
| 474 | 517 | ||
| 475 | return 0; | 518 | return gpiochip_add(&asic->gpio); |
| 476 | } | 519 | } |
| 477 | 520 | ||
| 478 | static void asic3_gpio_remove(struct platform_device *pdev) | 521 | static int asic3_gpio_remove(struct platform_device *pdev) |
| 479 | { | 522 | { |
| 480 | return; | 523 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 524 | |||
| 525 | return gpiochip_remove(&asic->gpio); | ||
| 481 | } | 526 | } |
| 482 | 527 | ||
| 483 | 528 | ||
| 484 | /* Core */ | 529 | /* Core */ |
| 485 | static int asic3_probe(struct platform_device *pdev) | 530 | static int __init asic3_probe(struct platform_device *pdev) |
| 486 | { | 531 | { |
| 487 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | 532 | struct asic3_platform_data *pdata = pdev->dev.platform_data; |
| 488 | struct asic3 *asic; | 533 | struct asic3 *asic; |
| 489 | struct resource *mem; | 534 | struct resource *mem; |
| 490 | unsigned long clksel; | 535 | unsigned long clksel; |
| 491 | int ret; | 536 | int ret = 0; |
| 492 | 537 | ||
| 493 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); | 538 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); |
| 494 | if (!asic) | 539 | if (asic == NULL) { |
| 540 | printk(KERN_ERR "kzalloc failed\n"); | ||
| 495 | return -ENOMEM; | 541 | return -ENOMEM; |
| 542 | } | ||
| 496 | 543 | ||
| 497 | spin_lock_init(&asic->lock); | 544 | spin_lock_init(&asic->lock); |
| 498 | platform_set_drvdata(pdev, asic); | 545 | platform_set_drvdata(pdev, asic); |
| @@ -501,49 +548,58 @@ static int asic3_probe(struct platform_device *pdev) | |||
| 501 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 548 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 502 | if (!mem) { | 549 | if (!mem) { |
| 503 | ret = -ENOMEM; | 550 | ret = -ENOMEM; |
| 504 | printk(KERN_ERR "asic3: no MEM resource\n"); | 551 | dev_err(asic->dev, "no MEM resource\n"); |
| 505 | goto err_out_1; | 552 | goto out_free; |
| 506 | } | 553 | } |
| 507 | 554 | ||
| 508 | asic->mapping = ioremap(mem->start, PAGE_SIZE); | 555 | map_size = mem->end - mem->start + 1; |
| 556 | asic->mapping = ioremap(mem->start, map_size); | ||
| 509 | if (!asic->mapping) { | 557 | if (!asic->mapping) { |
| 510 | ret = -ENOMEM; | 558 | ret = -ENOMEM; |
| 511 | printk(KERN_ERR "asic3: couldn't ioremap\n"); | 559 | dev_err(asic->dev, "Couldn't ioremap\n"); |
| 512 | goto err_out_1; | 560 | goto out_free; |
| 513 | } | 561 | } |
| 514 | 562 | ||
| 515 | asic->irq_base = pdata->irq_base; | 563 | asic->irq_base = pdata->irq_base; |
| 516 | 564 | ||
| 517 | if (pdata && pdata->bus_shift) | 565 | /* calculate bus shift from mem resource */ |
| 518 | asic->bus_shift = 2 - pdata->bus_shift; | 566 | asic->bus_shift = 2 - (map_size >> 12); |
| 519 | else | ||
| 520 | asic->bus_shift = 0; | ||
| 521 | 567 | ||
| 522 | clksel = 0; | 568 | clksel = 0; |
| 523 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); | 569 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); |
| 524 | 570 | ||
| 525 | ret = asic3_irq_probe(pdev); | 571 | ret = asic3_irq_probe(pdev); |
| 526 | if (ret < 0) { | 572 | if (ret < 0) { |
| 527 | printk(KERN_ERR "asic3: couldn't probe IRQs\n"); | 573 | dev_err(asic->dev, "Couldn't probe IRQs\n"); |
| 528 | goto err_out_2; | 574 | goto out_unmap; |
| 529 | } | 575 | } |
| 530 | asic3_gpio_probe(pdev); | ||
| 531 | 576 | ||
| 532 | if (pdata->children) { | 577 | asic->gpio.base = pdata->gpio_base; |
| 533 | int i; | 578 | asic->gpio.ngpio = ASIC3_NUM_GPIOS; |
| 534 | for (i = 0; i < pdata->n_children; i++) { | 579 | asic->gpio.get = asic3_gpio_get; |
| 535 | pdata->children[i]->dev.parent = &pdev->dev; | 580 | asic->gpio.set = asic3_gpio_set; |
| 536 | platform_device_register(pdata->children[i]); | 581 | asic->gpio.direction_input = asic3_gpio_direction_input; |
| 537 | } | 582 | asic->gpio.direction_output = asic3_gpio_direction_output; |
| 583 | |||
| 584 | ret = asic3_gpio_probe(pdev, | ||
| 585 | pdata->gpio_config, | ||
| 586 | pdata->gpio_config_num); | ||
| 587 | if (ret < 0) { | ||
| 588 | dev_err(asic->dev, "GPIO probe failed\n"); | ||
| 589 | goto out_irq; | ||
| 538 | } | 590 | } |
| 539 | 591 | ||
| 540 | printk(KERN_INFO "ASIC3 Core driver\n"); | 592 | dev_info(asic->dev, "ASIC3 Core driver\n"); |
| 541 | 593 | ||
| 542 | return 0; | 594 | return 0; |
| 543 | 595 | ||
| 544 | err_out_2: | 596 | out_irq: |
| 597 | asic3_irq_remove(pdev); | ||
| 598 | |||
| 599 | out_unmap: | ||
| 545 | iounmap(asic->mapping); | 600 | iounmap(asic->mapping); |
| 546 | err_out_1: | 601 | |
| 602 | out_free: | ||
| 547 | kfree(asic); | 603 | kfree(asic); |
| 548 | 604 | ||
| 549 | return ret; | 605 | return ret; |
| @@ -551,9 +607,12 @@ static int asic3_probe(struct platform_device *pdev) | |||
| 551 | 607 | ||
| 552 | static int asic3_remove(struct platform_device *pdev) | 608 | static int asic3_remove(struct platform_device *pdev) |
| 553 | { | 609 | { |
| 610 | int ret; | ||
| 554 | struct asic3 *asic = platform_get_drvdata(pdev); | 611 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 555 | 612 | ||
| 556 | asic3_gpio_remove(pdev); | 613 | ret = asic3_gpio_remove(pdev); |
| 614 | if (ret < 0) | ||
| 615 | return ret; | ||
| 557 | asic3_irq_remove(pdev); | 616 | asic3_irq_remove(pdev); |
| 558 | 617 | ||
| 559 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); | 618 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); |
| @@ -573,7 +632,6 @@ static struct platform_driver asic3_device_driver = { | |||
| 573 | .driver = { | 632 | .driver = { |
| 574 | .name = "asic3", | 633 | .name = "asic3", |
| 575 | }, | 634 | }, |
| 576 | .probe = asic3_probe, | ||
| 577 | .remove = __devexit_p(asic3_remove), | 635 | .remove = __devexit_p(asic3_remove), |
| 578 | .shutdown = asic3_shutdown, | 636 | .shutdown = asic3_shutdown, |
| 579 | }; | 637 | }; |
| @@ -581,7 +639,7 @@ static struct platform_driver asic3_device_driver = { | |||
| 581 | static int __init asic3_init(void) | 639 | static int __init asic3_init(void) |
| 582 | { | 640 | { |
| 583 | int retval = 0; | 641 | int retval = 0; |
| 584 | retval = platform_driver_register(&asic3_device_driver); | 642 | retval = platform_driver_probe(&asic3_device_driver, asic3_probe); |
| 585 | return retval; | 643 | return retval; |
| 586 | } | 644 | } |
| 587 | 645 | ||
