ab8500-core.c revision f0f05b1c751772d19c9c8f36d75e97b1d9687407
162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent/* 262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Copyright (C) ST-Ericsson SA 2010 362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * 462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * License Terms: GNU General Public License v2 562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> 662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Author: Rabin Vincent <rabin.vincent@stericsson.com> 747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * Changes: Mattias Wallin <mattias.wallin@stericsson.com> 862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 1062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/kernel.h> 1162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/slab.h> 1262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/init.h> 1362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/irq.h> 1462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/delay.h> 1562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/interrupt.h> 1662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/module.h> 1762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/platform_device.h> 1862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/mfd/core.h> 1947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#include <linux/mfd/abx500.h> 2062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#include <linux/mfd/ab8500.h> 21549931f99e030d63a437c23943fd8dc9b7c0e41cSundar R Iyer#include <linux/regulator/ab8500.h> 2262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 2362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent/* 2462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Interrupt register offsets 2562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Bank : 0x0E 2662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 2747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE1_REG 0x00 2847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE2_REG 0x01 2947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE3_REG 0x02 3047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE4_REG 0x03 3147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE5_REG 0x04 3247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE6_REG 0x05 3347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE7_REG 0x06 3447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE8_REG 0x07 3547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE19_REG 0x12 3647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE20_REG 0x13 3747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE21_REG 0x14 3847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE22_REG 0x15 3947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE23_REG 0x16 4047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_SOURCE24_REG 0x17 4162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 4262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent/* 4362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * latch registers 4462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 4547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH1_REG 0x20 4647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH2_REG 0x21 4747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH3_REG 0x22 4847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH4_REG 0x23 4947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH5_REG 0x24 5047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH6_REG 0x25 5147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH7_REG 0x26 5247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH8_REG 0x27 5347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH9_REG 0x28 5447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH10_REG 0x29 5547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH19_REG 0x32 5647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH20_REG 0x33 5747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH21_REG 0x34 5847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH22_REG 0x35 5947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH23_REG 0x36 6047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_LATCH24_REG 0x37 6162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 6262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent/* 6362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * mask registers 6462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 6562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 6647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK1_REG 0x40 6747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK2_REG 0x41 6847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK3_REG 0x42 6947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK4_REG 0x43 7047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK5_REG 0x44 7147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK6_REG 0x45 7247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK7_REG 0x46 7347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK8_REG 0x47 7447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK9_REG 0x48 7547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK10_REG 0x49 7647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK11_REG 0x4A 7747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK12_REG 0x4B 7847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK13_REG 0x4C 7947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK14_REG 0x4D 8047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK15_REG 0x4E 8147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK16_REG 0x4F 8247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK17_REG 0x50 8347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK18_REG 0x51 8447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK19_REG 0x52 8547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK20_REG 0x53 8647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK21_REG 0x54 8747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK22_REG 0x55 8847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK23_REG 0x56 8947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_IT_MASK24_REG 0x57 9047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 9147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin#define AB8500_REV_REG 0x80 9262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 9362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent/* 9462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 9562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * numbers are indexed into this array with (num / 8). 9662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * 9762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 9862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * offset 0. 9962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 10062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 10162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, 10262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent}; 10362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 10447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int ab8500_get_chip_id(struct device *dev) 10547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin{ 10647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 10747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return (int)ab8500->chip_id; 10847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin} 10947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 11047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 11147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 reg, u8 data) 11262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 11362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int ret; 11447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin /* 11547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * Put the u8 bank and u8 register together into a an u16. 11647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 11747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * */ 11847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u16 addr = ((u16)bank) << 8 | reg; 11962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 12062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 12162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 12247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = mutex_lock_interruptible(&ab8500->lock); 12347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret) 12447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return ret; 12547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 12662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ret = ab8500->write(ab8500, addr, data); 12762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret < 0) 12862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 12962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent addr, ret); 13047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin mutex_unlock(&ab8500->lock); 13162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 13262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 13362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 13462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 13547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int ab8500_set_register(struct device *dev, u8 bank, 13647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 reg, u8 value) 13762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 13847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 13962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 14047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return set_register_interruptible(ab8500, bank, reg, value); 14162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 14262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 14347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 14447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 reg, u8 *value) 14562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 14662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int ret; 14747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin /* put the u8 bank and u8 reg together into a an u16. 14847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * bank on higher 8 bits and reg in lower */ 14947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u16 addr = ((u16)bank) << 8 | reg; 15047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 15147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = mutex_lock_interruptible(&ab8500->lock); 15247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret) 15347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return ret; 15462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 15562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ret = ab8500->read(ab8500, addr); 15662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret < 0) 15762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 15862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent addr, ret); 15947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin else 16047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin *value = ret; 16162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 16247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin mutex_unlock(&ab8500->lock); 16362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 16462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 16562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 16662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 16762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 16847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int ab8500_get_register(struct device *dev, u8 bank, 16947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 reg, u8 *value) 17062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 17147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 17262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 17347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return get_register_interruptible(ab8500, bank, reg, value); 17462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 17547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 17647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 17747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 17862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 17962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int ret; 18047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 data; 18147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin /* put the u8 bank and u8 reg together into a an u16. 18247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin * bank on higher 8 bits and reg in lower */ 18347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u16 addr = ((u16)bank) << 8 | reg; 18462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 18547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = mutex_lock_interruptible(&ab8500->lock); 18647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret) 18747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return ret; 18862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 18947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = ab8500->read(ab8500, addr); 19047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret < 0) { 19147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 19247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin addr, ret); 19362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent goto out; 19447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin } 19562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 19647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin data = (u8)ret; 19747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 19862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 19947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = ab8500->write(ab8500, addr, data); 20047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret < 0) 20147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 20247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin addr, ret); 20362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 20447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data); 20562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentout: 20662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mutex_unlock(&ab8500->lock); 20762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 20862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 20947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 21047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic int ab8500_mask_and_set_register(struct device *dev, 21147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 21247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin{ 21347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 21447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 21547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return mask_and_set_register_interruptible(ab8500, bank, reg, 21647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin bitmask, bitvalues); 21747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 21847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin} 21947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 22047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallinstatic struct abx500_ops ab8500_ops = { 22147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .get_chip_id = ab8500_get_chip_id, 22247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .get_register = ab8500_get_register, 22347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .set_register = ab8500_set_register, 22447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .get_register_page = NULL, 22547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .set_register_page = NULL, 22647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 22747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .event_registers_startup_state_get = NULL, 22847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin .startup_irq_enabled = NULL, 22947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin}; 23062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 23162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic void ab8500_irq_lock(unsigned int irq) 23262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 23362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 23462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 23562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mutex_lock(&ab8500->irq_lock); 23662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 23762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 23862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic void ab8500_irq_sync_unlock(unsigned int irq) 23962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 24062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 24162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int i; 24262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 24362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 24462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent u8 old = ab8500->oldmask[i]; 24562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent u8 new = ab8500->mask[i]; 24662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int reg; 24762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 24862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (new == old) 24962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent continue; 25062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 25162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->oldmask[i] = new; 25262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 25362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; 25447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 25562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 25662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 25762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mutex_unlock(&ab8500->irq_lock); 25862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 25962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 26062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic void ab8500_irq_mask(unsigned int irq) 26162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 26262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 26362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int offset = irq - ab8500->irq_base; 26462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int index = offset / 8; 26562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int mask = 1 << (offset % 8); 26662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 26762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->mask[index] |= mask; 26862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 26962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 27062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic void ab8500_irq_unmask(unsigned int irq) 27162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 27262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500 *ab8500 = get_irq_chip_data(irq); 27362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int offset = irq - ab8500->irq_base; 27462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int index = offset / 8; 27562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int mask = 1 << (offset % 8); 27662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 27762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->mask[index] &= ~mask; 27862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 27962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 28062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic struct irq_chip ab8500_irq_chip = { 28162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "ab8500", 28262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .bus_lock = ab8500_irq_lock, 28362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .bus_sync_unlock = ab8500_irq_sync_unlock, 28462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .mask = ab8500_irq_mask, 28562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .unmask = ab8500_irq_unmask, 28662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent}; 28762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 28862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic irqreturn_t ab8500_irq(int irq, void *dev) 28962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 29062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500 *ab8500 = dev; 29162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int i; 29262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 29362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 29462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 29562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 29662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int regoffset = ab8500_irq_regoffset[i]; 29762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int status; 29847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 value; 29962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 30047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 30147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_IT_LATCH1_REG + regoffset, &value); 30247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (status < 0 || value == 0) 30362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent continue; 30462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 30562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent do { 30662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int bit = __ffs(status); 30762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int line = i * 8 + bit; 30862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 30962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent handle_nested_irq(ab8500->irq_base + line); 31047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin value &= ~(1 << bit); 31147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin } while (value); 31262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 31362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 31462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return IRQ_HANDLED; 31562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 31662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 31762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic int ab8500_irq_init(struct ab8500 *ab8500) 31862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 31962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int base = ab8500->irq_base; 32062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int irq; 32162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 32262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { 32362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_chip_data(irq, ab8500); 32462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_chip_and_handler(irq, &ab8500_irq_chip, 32562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent handle_simple_irq); 32662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_nested_thread(irq, 1); 32762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#ifdef CONFIG_ARM 32862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_flags(irq, IRQF_VALID); 32962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#else 33062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_noprobe(irq); 33162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#endif 33262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 33362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 33462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return 0; 33562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 33662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 33762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic void ab8500_irq_remove(struct ab8500 *ab8500) 33862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 33962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int base = ab8500->irq_base; 34062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int irq; 34162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 34262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { 34362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#ifdef CONFIG_ARM 34462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_flags(irq, 0); 34562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent#endif 34662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_chip_and_handler(irq, NULL, NULL); 34762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent set_irq_chip_data(irq, NULL); 34862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 34962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 35062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 35162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic struct resource ab8500_gpadc_resources[] = { 35262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 35362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "HW_CONV_END", 35462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 35562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 35662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .flags = IORESOURCE_IRQ, 35762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 35862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 35962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "SW_CONV_END", 36062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 36162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 36262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .flags = IORESOURCE_IRQ, 36362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 36462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent}; 36562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 36662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic struct resource ab8500_rtc_resources[] = { 36762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 36862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "60S", 36962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .start = AB8500_INT_RTC_60S, 37062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .end = AB8500_INT_RTC_60S, 37162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .flags = IORESOURCE_IRQ, 37262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 37362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 37462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "ALARM", 37562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .start = AB8500_INT_RTC_ALARM, 37662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .end = AB8500_INT_RTC_ALARM, 37762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .flags = IORESOURCE_IRQ, 37862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 37962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent}; 38062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 38177686517977e77d101c8a7b397717df00a88922bSundar R Iyerstatic struct resource ab8500_poweronkey_db_resources[] = { 38277686517977e77d101c8a7b397717df00a88922bSundar R Iyer { 38377686517977e77d101c8a7b397717df00a88922bSundar R Iyer .name = "ONKEY_DBF", 38477686517977e77d101c8a7b397717df00a88922bSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 38577686517977e77d101c8a7b397717df00a88922bSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 38677686517977e77d101c8a7b397717df00a88922bSundar R Iyer .flags = IORESOURCE_IRQ, 38777686517977e77d101c8a7b397717df00a88922bSundar R Iyer }, 38877686517977e77d101c8a7b397717df00a88922bSundar R Iyer { 38977686517977e77d101c8a7b397717df00a88922bSundar R Iyer .name = "ONKEY_DBR", 39077686517977e77d101c8a7b397717df00a88922bSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 39177686517977e77d101c8a7b397717df00a88922bSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 39277686517977e77d101c8a7b397717df00a88922bSundar R Iyer .flags = IORESOURCE_IRQ, 39377686517977e77d101c8a7b397717df00a88922bSundar R Iyer }, 39477686517977e77d101c8a7b397717df00a88922bSundar R Iyer}; 39577686517977e77d101c8a7b397717df00a88922bSundar R Iyer 39662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentstatic struct mfd_cell ab8500_devs[] = { 39762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 39862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "ab8500-gpadc", 39962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 40062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .resources = ab8500_gpadc_resources, 40162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 40262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { 40362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .name = "ab8500-rtc", 40462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 40562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent .resources = ab8500_rtc_resources, 40662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent }, 407f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy { 408f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .name = "ab8500-pwm", 409f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .id = 1, 410f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy }, 411f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy { 412f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .name = "ab8500-pwm", 413f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .id = 2, 414f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy }, 415f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy { 416f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .name = "ab8500-pwm", 417f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy .id = 3, 418f0f05b1c751772d19c9c8f36d75e97b1d9687407Arun Murthy }, 41962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { .name = "ab8500-charger", }, 42062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { .name = "ab8500-audio", }, 42162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent { .name = "ab8500-usb", }, 422549931f99e030d63a437c23943fd8dc9b7c0e41cSundar R Iyer { .name = "ab8500-regulator", }, 42377686517977e77d101c8a7b397717df00a88922bSundar R Iyer { 42477686517977e77d101c8a7b397717df00a88922bSundar R Iyer .name = "ab8500-poweron-key", 42577686517977e77d101c8a7b397717df00a88922bSundar R Iyer .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 42677686517977e77d101c8a7b397717df00a88922bSundar R Iyer .resources = ab8500_poweronkey_db_resources, 42777686517977e77d101c8a7b397717df00a88922bSundar R Iyer }, 42862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent}; 42962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 43062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentint __devinit ab8500_init(struct ab8500 *ab8500) 43162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 43262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); 43362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int ret; 43462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent int i; 43547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin u8 value; 43662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 43762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (plat) 43862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->irq_base = plat->irq_base; 43962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 44062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mutex_init(&ab8500->lock); 44162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mutex_init(&ab8500->irq_lock); 44262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 44347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 44447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_REV_REG, &value); 44562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret < 0) 44662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 44762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 44862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent /* 44962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * 0x0 - Early Drop 45062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * 0x10 - Cut 1.0 45162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent * 0x11 - Cut 1.1 45262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent */ 45347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (value == 0x0 || value == 0x10 || value == 0x11) { 45447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ab8500->revision = value; 45547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); 45662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } else { 45747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value); 45862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return -EINVAL; 45962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 46047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ab8500->chip_id = value; 46162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 46262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (plat && plat->init) 46362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent plat->init(ab8500); 46462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 46562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent /* Clear and mask all interrupts */ 46662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (i = 0; i < 10; i++) { 46747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 46847c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_IT_LATCH1_REG + i, &value); 46947c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 47047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_IT_MASK1_REG + i, 0xff); 47162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 47262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 47362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (i = 18; i < 24; i++) { 47447c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 47547c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_IT_LATCH1_REG + i, &value); 47647c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 47747c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin AB8500_IT_MASK1_REG + i, 0xff); 47862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 47962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 48047c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 48147c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin if (ret) 48247c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin return ret; 48347c1697508f2ec9f6b31ce6c825fe1017871dea6Mattias Wallin 48462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) 48562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 48662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 48762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ab8500->irq_base) { 48862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ret = ab8500_irq_init(ab8500); 48962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret) 49062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 49162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 49262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, 49362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent IRQF_ONESHOT, "ab8500", ab8500); 49462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret) 49562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent goto out_removeirq; 49662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 49762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 498549931f99e030d63a437c23943fd8dc9b7c0e41cSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 49962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ARRAY_SIZE(ab8500_devs), NULL, 50062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500->irq_base); 50162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ret) 50262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent goto out_freeirq; 50362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 50462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 50562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 50662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentout_freeirq: 50762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ab8500->irq_base) { 50862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent free_irq(ab8500->irq, ab8500); 50962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentout_removeirq: 51062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500_irq_remove(ab8500); 51162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 51262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return ret; 51362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 51462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 51562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincentint __devexit ab8500_exit(struct ab8500 *ab8500) 51662579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent{ 51762579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent mfd_remove_devices(ab8500->dev); 51862579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent if (ab8500->irq_base) { 51962579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent free_irq(ab8500->irq, ab8500); 52062579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent ab8500_irq_remove(ab8500); 52162579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent } 52262579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 52362579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent return 0; 52462579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent} 52562579266cf9caca5b999560be2b5ceee42fc4d4dRabin Vincent 52662579266cf9caca5b999560be2b5ceee42fc4d4dRabin VincentMODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent"); 52762579266cf9caca5b999560be2b5ceee42fc4d4dRabin VincentMODULE_DESCRIPTION("AB8500 MFD core"); 52862579266cf9caca5b999560be2b5ceee42fc4d4dRabin VincentMODULE_LICENSE("GPL v2"); 529