1*62579266SRabin Vincent /* 2*62579266SRabin Vincent * Copyright (C) ST-Ericsson SA 2010 3*62579266SRabin Vincent * 4*62579266SRabin Vincent * License Terms: GNU General Public License v2 5*62579266SRabin Vincent * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> 6*62579266SRabin Vincent * Author: Rabin Vincent <rabin.vincent@stericsson.com> 7*62579266SRabin Vincent */ 8*62579266SRabin Vincent 9*62579266SRabin Vincent #include <linux/kernel.h> 10*62579266SRabin Vincent #include <linux/slab.h> 11*62579266SRabin Vincent #include <linux/init.h> 12*62579266SRabin Vincent #include <linux/irq.h> 13*62579266SRabin Vincent #include <linux/delay.h> 14*62579266SRabin Vincent #include <linux/interrupt.h> 15*62579266SRabin Vincent #include <linux/module.h> 16*62579266SRabin Vincent #include <linux/platform_device.h> 17*62579266SRabin Vincent #include <linux/mfd/core.h> 18*62579266SRabin Vincent #include <linux/mfd/ab8500.h> 19*62579266SRabin Vincent 20*62579266SRabin Vincent /* 21*62579266SRabin Vincent * Interrupt register offsets 22*62579266SRabin Vincent * Bank : 0x0E 23*62579266SRabin Vincent */ 24*62579266SRabin Vincent #define AB8500_IT_SOURCE1_REG 0x0E00 25*62579266SRabin Vincent #define AB8500_IT_SOURCE2_REG 0x0E01 26*62579266SRabin Vincent #define AB8500_IT_SOURCE3_REG 0x0E02 27*62579266SRabin Vincent #define AB8500_IT_SOURCE4_REG 0x0E03 28*62579266SRabin Vincent #define AB8500_IT_SOURCE5_REG 0x0E04 29*62579266SRabin Vincent #define AB8500_IT_SOURCE6_REG 0x0E05 30*62579266SRabin Vincent #define AB8500_IT_SOURCE7_REG 0x0E06 31*62579266SRabin Vincent #define AB8500_IT_SOURCE8_REG 0x0E07 32*62579266SRabin Vincent #define AB8500_IT_SOURCE19_REG 0x0E12 33*62579266SRabin Vincent #define AB8500_IT_SOURCE20_REG 0x0E13 34*62579266SRabin Vincent #define AB8500_IT_SOURCE21_REG 0x0E14 35*62579266SRabin Vincent #define AB8500_IT_SOURCE22_REG 0x0E15 36*62579266SRabin Vincent #define AB8500_IT_SOURCE23_REG 0x0E16 37*62579266SRabin Vincent #define AB8500_IT_SOURCE24_REG 0x0E17 38*62579266SRabin Vincent 39*62579266SRabin Vincent /* 40*62579266SRabin Vincent * latch registers 41*62579266SRabin Vincent */ 42*62579266SRabin Vincent #define AB8500_IT_LATCH1_REG 0x0E20 43*62579266SRabin Vincent #define AB8500_IT_LATCH2_REG 0x0E21 44*62579266SRabin Vincent #define AB8500_IT_LATCH3_REG 0x0E22 45*62579266SRabin Vincent #define AB8500_IT_LATCH4_REG 0x0E23 46*62579266SRabin Vincent #define AB8500_IT_LATCH5_REG 0x0E24 47*62579266SRabin Vincent #define AB8500_IT_LATCH6_REG 0x0E25 48*62579266SRabin Vincent #define AB8500_IT_LATCH7_REG 0x0E26 49*62579266SRabin Vincent #define AB8500_IT_LATCH8_REG 0x0E27 50*62579266SRabin Vincent #define AB8500_IT_LATCH9_REG 0x0E28 51*62579266SRabin Vincent #define AB8500_IT_LATCH10_REG 0x0E29 52*62579266SRabin Vincent #define AB8500_IT_LATCH19_REG 0x0E32 53*62579266SRabin Vincent #define AB8500_IT_LATCH20_REG 0x0E33 54*62579266SRabin Vincent #define AB8500_IT_LATCH21_REG 0x0E34 55*62579266SRabin Vincent #define AB8500_IT_LATCH22_REG 0x0E35 56*62579266SRabin Vincent #define AB8500_IT_LATCH23_REG 0x0E36 57*62579266SRabin Vincent #define AB8500_IT_LATCH24_REG 0x0E37 58*62579266SRabin Vincent 59*62579266SRabin Vincent /* 60*62579266SRabin Vincent * mask registers 61*62579266SRabin Vincent */ 62*62579266SRabin Vincent 63*62579266SRabin Vincent #define AB8500_IT_MASK1_REG 0x0E40 64*62579266SRabin Vincent #define AB8500_IT_MASK2_REG 0x0E41 65*62579266SRabin Vincent #define AB8500_IT_MASK3_REG 0x0E42 66*62579266SRabin Vincent #define AB8500_IT_MASK4_REG 0x0E43 67*62579266SRabin Vincent #define AB8500_IT_MASK5_REG 0x0E44 68*62579266SRabin Vincent #define AB8500_IT_MASK6_REG 0x0E45 69*62579266SRabin Vincent #define AB8500_IT_MASK7_REG 0x0E46 70*62579266SRabin Vincent #define AB8500_IT_MASK8_REG 0x0E47 71*62579266SRabin Vincent #define AB8500_IT_MASK9_REG 0x0E48 72*62579266SRabin Vincent #define AB8500_IT_MASK10_REG 0x0E49 73*62579266SRabin Vincent #define AB8500_IT_MASK11_REG 0x0E4A 74*62579266SRabin Vincent #define AB8500_IT_MASK12_REG 0x0E4B 75*62579266SRabin Vincent #define AB8500_IT_MASK13_REG 0x0E4C 76*62579266SRabin Vincent #define AB8500_IT_MASK14_REG 0x0E4D 77*62579266SRabin Vincent #define AB8500_IT_MASK15_REG 0x0E4E 78*62579266SRabin Vincent #define AB8500_IT_MASK16_REG 0x0E4F 79*62579266SRabin Vincent #define AB8500_IT_MASK17_REG 0x0E50 80*62579266SRabin Vincent #define AB8500_IT_MASK18_REG 0x0E51 81*62579266SRabin Vincent #define AB8500_IT_MASK19_REG 0x0E52 82*62579266SRabin Vincent #define AB8500_IT_MASK20_REG 0x0E53 83*62579266SRabin Vincent #define AB8500_IT_MASK21_REG 0x0E54 84*62579266SRabin Vincent #define AB8500_IT_MASK22_REG 0x0E55 85*62579266SRabin Vincent #define AB8500_IT_MASK23_REG 0x0E56 86*62579266SRabin Vincent #define AB8500_IT_MASK24_REG 0x0E57 87*62579266SRabin Vincent 88*62579266SRabin Vincent #define AB8500_REV_REG 0x1080 89*62579266SRabin Vincent 90*62579266SRabin Vincent /* 91*62579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 92*62579266SRabin Vincent * numbers are indexed into this array with (num / 8). 93*62579266SRabin Vincent * 94*62579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 95*62579266SRabin Vincent * offset 0. 96*62579266SRabin Vincent */ 97*62579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 98*62579266SRabin Vincent 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, 99*62579266SRabin Vincent }; 100*62579266SRabin Vincent 101*62579266SRabin Vincent static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) 102*62579266SRabin Vincent { 103*62579266SRabin Vincent int ret; 104*62579266SRabin Vincent 105*62579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 106*62579266SRabin Vincent 107*62579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 108*62579266SRabin Vincent if (ret < 0) 109*62579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 110*62579266SRabin Vincent addr, ret); 111*62579266SRabin Vincent 112*62579266SRabin Vincent return ret; 113*62579266SRabin Vincent } 114*62579266SRabin Vincent 115*62579266SRabin Vincent /** 116*62579266SRabin Vincent * ab8500_write() - write an AB8500 register 117*62579266SRabin Vincent * @ab8500: device to write to 118*62579266SRabin Vincent * @addr: address of the register 119*62579266SRabin Vincent * @data: value to write 120*62579266SRabin Vincent */ 121*62579266SRabin Vincent int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) 122*62579266SRabin Vincent { 123*62579266SRabin Vincent int ret; 124*62579266SRabin Vincent 125*62579266SRabin Vincent mutex_lock(&ab8500->lock); 126*62579266SRabin Vincent ret = __ab8500_write(ab8500, addr, data); 127*62579266SRabin Vincent mutex_unlock(&ab8500->lock); 128*62579266SRabin Vincent 129*62579266SRabin Vincent return ret; 130*62579266SRabin Vincent } 131*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_write); 132*62579266SRabin Vincent 133*62579266SRabin Vincent static int __ab8500_read(struct ab8500 *ab8500, u16 addr) 134*62579266SRabin Vincent { 135*62579266SRabin Vincent int ret; 136*62579266SRabin Vincent 137*62579266SRabin Vincent ret = ab8500->read(ab8500, addr); 138*62579266SRabin Vincent if (ret < 0) 139*62579266SRabin Vincent dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 140*62579266SRabin Vincent addr, ret); 141*62579266SRabin Vincent 142*62579266SRabin Vincent dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 143*62579266SRabin Vincent 144*62579266SRabin Vincent return ret; 145*62579266SRabin Vincent } 146*62579266SRabin Vincent 147*62579266SRabin Vincent /** 148*62579266SRabin Vincent * ab8500_read() - read an AB8500 register 149*62579266SRabin Vincent * @ab8500: device to read from 150*62579266SRabin Vincent * @addr: address of the register 151*62579266SRabin Vincent */ 152*62579266SRabin Vincent int ab8500_read(struct ab8500 *ab8500, u16 addr) 153*62579266SRabin Vincent { 154*62579266SRabin Vincent int ret; 155*62579266SRabin Vincent 156*62579266SRabin Vincent mutex_lock(&ab8500->lock); 157*62579266SRabin Vincent ret = __ab8500_read(ab8500, addr); 158*62579266SRabin Vincent mutex_unlock(&ab8500->lock); 159*62579266SRabin Vincent 160*62579266SRabin Vincent return ret; 161*62579266SRabin Vincent } 162*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_read); 163*62579266SRabin Vincent 164*62579266SRabin Vincent /** 165*62579266SRabin Vincent * ab8500_set_bits() - set a bitfield in an AB8500 register 166*62579266SRabin Vincent * @ab8500: device to read from 167*62579266SRabin Vincent * @addr: address of the register 168*62579266SRabin Vincent * @mask: mask of the bitfield to modify 169*62579266SRabin Vincent * @data: value to set to the bitfield 170*62579266SRabin Vincent */ 171*62579266SRabin Vincent int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data) 172*62579266SRabin Vincent { 173*62579266SRabin Vincent int ret; 174*62579266SRabin Vincent 175*62579266SRabin Vincent mutex_lock(&ab8500->lock); 176*62579266SRabin Vincent 177*62579266SRabin Vincent ret = __ab8500_read(ab8500, addr); 178*62579266SRabin Vincent if (ret < 0) 179*62579266SRabin Vincent goto out; 180*62579266SRabin Vincent 181*62579266SRabin Vincent ret &= ~mask; 182*62579266SRabin Vincent ret |= data; 183*62579266SRabin Vincent 184*62579266SRabin Vincent ret = __ab8500_write(ab8500, addr, ret); 185*62579266SRabin Vincent 186*62579266SRabin Vincent out: 187*62579266SRabin Vincent mutex_unlock(&ab8500->lock); 188*62579266SRabin Vincent return ret; 189*62579266SRabin Vincent } 190*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_set_bits); 191*62579266SRabin Vincent 192*62579266SRabin Vincent static void ab8500_irq_lock(unsigned int irq) 193*62579266SRabin Vincent { 194*62579266SRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 195*62579266SRabin Vincent 196*62579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 197*62579266SRabin Vincent } 198*62579266SRabin Vincent 199*62579266SRabin Vincent static void ab8500_irq_sync_unlock(unsigned int irq) 200*62579266SRabin Vincent { 201*62579266SRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 202*62579266SRabin Vincent int i; 203*62579266SRabin Vincent 204*62579266SRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 205*62579266SRabin Vincent u8 old = ab8500->oldmask[i]; 206*62579266SRabin Vincent u8 new = ab8500->mask[i]; 207*62579266SRabin Vincent int reg; 208*62579266SRabin Vincent 209*62579266SRabin Vincent if (new == old) 210*62579266SRabin Vincent continue; 211*62579266SRabin Vincent 212*62579266SRabin Vincent ab8500->oldmask[i] = new; 213*62579266SRabin Vincent 214*62579266SRabin Vincent reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; 215*62579266SRabin Vincent ab8500_write(ab8500, reg, new); 216*62579266SRabin Vincent } 217*62579266SRabin Vincent 218*62579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 219*62579266SRabin Vincent } 220*62579266SRabin Vincent 221*62579266SRabin Vincent static void ab8500_irq_mask(unsigned int irq) 222*62579266SRabin Vincent { 223*62579266SRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 224*62579266SRabin Vincent int offset = irq - ab8500->irq_base; 225*62579266SRabin Vincent int index = offset / 8; 226*62579266SRabin Vincent int mask = 1 << (offset % 8); 227*62579266SRabin Vincent 228*62579266SRabin Vincent ab8500->mask[index] |= mask; 229*62579266SRabin Vincent } 230*62579266SRabin Vincent 231*62579266SRabin Vincent static void ab8500_irq_unmask(unsigned int irq) 232*62579266SRabin Vincent { 233*62579266SRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 234*62579266SRabin Vincent int offset = irq - ab8500->irq_base; 235*62579266SRabin Vincent int index = offset / 8; 236*62579266SRabin Vincent int mask = 1 << (offset % 8); 237*62579266SRabin Vincent 238*62579266SRabin Vincent ab8500->mask[index] &= ~mask; 239*62579266SRabin Vincent } 240*62579266SRabin Vincent 241*62579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 242*62579266SRabin Vincent .name = "ab8500", 243*62579266SRabin Vincent .bus_lock = ab8500_irq_lock, 244*62579266SRabin Vincent .bus_sync_unlock = ab8500_irq_sync_unlock, 245*62579266SRabin Vincent .mask = ab8500_irq_mask, 246*62579266SRabin Vincent .unmask = ab8500_irq_unmask, 247*62579266SRabin Vincent }; 248*62579266SRabin Vincent 249*62579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev) 250*62579266SRabin Vincent { 251*62579266SRabin Vincent struct ab8500 *ab8500 = dev; 252*62579266SRabin Vincent int i; 253*62579266SRabin Vincent 254*62579266SRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 255*62579266SRabin Vincent 256*62579266SRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 257*62579266SRabin Vincent int regoffset = ab8500_irq_regoffset[i]; 258*62579266SRabin Vincent int status; 259*62579266SRabin Vincent 260*62579266SRabin Vincent status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset); 261*62579266SRabin Vincent if (status <= 0) 262*62579266SRabin Vincent continue; 263*62579266SRabin Vincent 264*62579266SRabin Vincent do { 265*62579266SRabin Vincent int bit = __ffs(status); 266*62579266SRabin Vincent int line = i * 8 + bit; 267*62579266SRabin Vincent 268*62579266SRabin Vincent handle_nested_irq(ab8500->irq_base + line); 269*62579266SRabin Vincent status &= ~(1 << bit); 270*62579266SRabin Vincent } while (status); 271*62579266SRabin Vincent } 272*62579266SRabin Vincent 273*62579266SRabin Vincent return IRQ_HANDLED; 274*62579266SRabin Vincent } 275*62579266SRabin Vincent 276*62579266SRabin Vincent static int ab8500_irq_init(struct ab8500 *ab8500) 277*62579266SRabin Vincent { 278*62579266SRabin Vincent int base = ab8500->irq_base; 279*62579266SRabin Vincent int irq; 280*62579266SRabin Vincent 281*62579266SRabin Vincent for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { 282*62579266SRabin Vincent set_irq_chip_data(irq, ab8500); 283*62579266SRabin Vincent set_irq_chip_and_handler(irq, &ab8500_irq_chip, 284*62579266SRabin Vincent handle_simple_irq); 285*62579266SRabin Vincent set_irq_nested_thread(irq, 1); 286*62579266SRabin Vincent #ifdef CONFIG_ARM 287*62579266SRabin Vincent set_irq_flags(irq, IRQF_VALID); 288*62579266SRabin Vincent #else 289*62579266SRabin Vincent set_irq_noprobe(irq); 290*62579266SRabin Vincent #endif 291*62579266SRabin Vincent } 292*62579266SRabin Vincent 293*62579266SRabin Vincent return 0; 294*62579266SRabin Vincent } 295*62579266SRabin Vincent 296*62579266SRabin Vincent static void ab8500_irq_remove(struct ab8500 *ab8500) 297*62579266SRabin Vincent { 298*62579266SRabin Vincent int base = ab8500->irq_base; 299*62579266SRabin Vincent int irq; 300*62579266SRabin Vincent 301*62579266SRabin Vincent for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { 302*62579266SRabin Vincent #ifdef CONFIG_ARM 303*62579266SRabin Vincent set_irq_flags(irq, 0); 304*62579266SRabin Vincent #endif 305*62579266SRabin Vincent set_irq_chip_and_handler(irq, NULL, NULL); 306*62579266SRabin Vincent set_irq_chip_data(irq, NULL); 307*62579266SRabin Vincent } 308*62579266SRabin Vincent } 309*62579266SRabin Vincent 310*62579266SRabin Vincent static struct resource ab8500_gpadc_resources[] = { 311*62579266SRabin Vincent { 312*62579266SRabin Vincent .name = "HW_CONV_END", 313*62579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 314*62579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 315*62579266SRabin Vincent .flags = IORESOURCE_IRQ, 316*62579266SRabin Vincent }, 317*62579266SRabin Vincent { 318*62579266SRabin Vincent .name = "SW_CONV_END", 319*62579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 320*62579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 321*62579266SRabin Vincent .flags = IORESOURCE_IRQ, 322*62579266SRabin Vincent }, 323*62579266SRabin Vincent }; 324*62579266SRabin Vincent 325*62579266SRabin Vincent static struct resource ab8500_rtc_resources[] = { 326*62579266SRabin Vincent { 327*62579266SRabin Vincent .name = "60S", 328*62579266SRabin Vincent .start = AB8500_INT_RTC_60S, 329*62579266SRabin Vincent .end = AB8500_INT_RTC_60S, 330*62579266SRabin Vincent .flags = IORESOURCE_IRQ, 331*62579266SRabin Vincent }, 332*62579266SRabin Vincent { 333*62579266SRabin Vincent .name = "ALARM", 334*62579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 335*62579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 336*62579266SRabin Vincent .flags = IORESOURCE_IRQ, 337*62579266SRabin Vincent }, 338*62579266SRabin Vincent }; 339*62579266SRabin Vincent 340*62579266SRabin Vincent static struct mfd_cell ab8500_devs[] = { 341*62579266SRabin Vincent { 342*62579266SRabin Vincent .name = "ab8500-gpadc", 343*62579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 344*62579266SRabin Vincent .resources = ab8500_gpadc_resources, 345*62579266SRabin Vincent }, 346*62579266SRabin Vincent { 347*62579266SRabin Vincent .name = "ab8500-rtc", 348*62579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 349*62579266SRabin Vincent .resources = ab8500_rtc_resources, 350*62579266SRabin Vincent }, 351*62579266SRabin Vincent { .name = "ab8500-charger", }, 352*62579266SRabin Vincent { .name = "ab8500-audio", }, 353*62579266SRabin Vincent { .name = "ab8500-usb", }, 354*62579266SRabin Vincent { .name = "ab8500-pwm", }, 355*62579266SRabin Vincent }; 356*62579266SRabin Vincent 357*62579266SRabin Vincent int __devinit ab8500_init(struct ab8500 *ab8500) 358*62579266SRabin Vincent { 359*62579266SRabin Vincent struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); 360*62579266SRabin Vincent int ret; 361*62579266SRabin Vincent int i; 362*62579266SRabin Vincent 363*62579266SRabin Vincent if (plat) 364*62579266SRabin Vincent ab8500->irq_base = plat->irq_base; 365*62579266SRabin Vincent 366*62579266SRabin Vincent mutex_init(&ab8500->lock); 367*62579266SRabin Vincent mutex_init(&ab8500->irq_lock); 368*62579266SRabin Vincent 369*62579266SRabin Vincent ret = ab8500_read(ab8500, AB8500_REV_REG); 370*62579266SRabin Vincent if (ret < 0) 371*62579266SRabin Vincent return ret; 372*62579266SRabin Vincent 373*62579266SRabin Vincent /* 374*62579266SRabin Vincent * 0x0 - Early Drop 375*62579266SRabin Vincent * 0x10 - Cut 1.0 376*62579266SRabin Vincent * 0x11 - Cut 1.1 377*62579266SRabin Vincent */ 378*62579266SRabin Vincent if (ret == 0x0 || ret == 0x10 || ret == 0x11) { 379*62579266SRabin Vincent ab8500->revision = ret; 380*62579266SRabin Vincent dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret); 381*62579266SRabin Vincent } else { 382*62579266SRabin Vincent dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret); 383*62579266SRabin Vincent return -EINVAL; 384*62579266SRabin Vincent } 385*62579266SRabin Vincent 386*62579266SRabin Vincent if (plat && plat->init) 387*62579266SRabin Vincent plat->init(ab8500); 388*62579266SRabin Vincent 389*62579266SRabin Vincent /* Clear and mask all interrupts */ 390*62579266SRabin Vincent for (i = 0; i < 10; i++) { 391*62579266SRabin Vincent ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); 392*62579266SRabin Vincent ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); 393*62579266SRabin Vincent } 394*62579266SRabin Vincent 395*62579266SRabin Vincent for (i = 18; i < 24; i++) { 396*62579266SRabin Vincent ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); 397*62579266SRabin Vincent ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); 398*62579266SRabin Vincent } 399*62579266SRabin Vincent 400*62579266SRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) 401*62579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 402*62579266SRabin Vincent 403*62579266SRabin Vincent if (ab8500->irq_base) { 404*62579266SRabin Vincent ret = ab8500_irq_init(ab8500); 405*62579266SRabin Vincent if (ret) 406*62579266SRabin Vincent return ret; 407*62579266SRabin Vincent 408*62579266SRabin Vincent ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, 409*62579266SRabin Vincent IRQF_ONESHOT, "ab8500", ab8500); 410*62579266SRabin Vincent if (ret) 411*62579266SRabin Vincent goto out_removeirq; 412*62579266SRabin Vincent } 413*62579266SRabin Vincent 414*62579266SRabin Vincent ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs, 415*62579266SRabin Vincent ARRAY_SIZE(ab8500_devs), NULL, 416*62579266SRabin Vincent ab8500->irq_base); 417*62579266SRabin Vincent if (ret) 418*62579266SRabin Vincent goto out_freeirq; 419*62579266SRabin Vincent 420*62579266SRabin Vincent return ret; 421*62579266SRabin Vincent 422*62579266SRabin Vincent out_freeirq: 423*62579266SRabin Vincent if (ab8500->irq_base) { 424*62579266SRabin Vincent free_irq(ab8500->irq, ab8500); 425*62579266SRabin Vincent out_removeirq: 426*62579266SRabin Vincent ab8500_irq_remove(ab8500); 427*62579266SRabin Vincent } 428*62579266SRabin Vincent return ret; 429*62579266SRabin Vincent } 430*62579266SRabin Vincent 431*62579266SRabin Vincent int __devexit ab8500_exit(struct ab8500 *ab8500) 432*62579266SRabin Vincent { 433*62579266SRabin Vincent mfd_remove_devices(ab8500->dev); 434*62579266SRabin Vincent if (ab8500->irq_base) { 435*62579266SRabin Vincent free_irq(ab8500->irq, ab8500); 436*62579266SRabin Vincent ab8500_irq_remove(ab8500); 437*62579266SRabin Vincent } 438*62579266SRabin Vincent 439*62579266SRabin Vincent return 0; 440*62579266SRabin Vincent } 441*62579266SRabin Vincent 442*62579266SRabin Vincent MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent"); 443*62579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 444*62579266SRabin Vincent MODULE_LICENSE("GPL v2"); 445