aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-core.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-02-20 15:42:10 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-03-06 12:46:42 -0500
commit0f620837595145cd42be1c9dc6b619146fbeaf88 (patch)
treec8baef44fa4b407ef897ccd234b91f8d83ac85e3 /drivers/mfd/ab8500-core.c
parent6d95b7fdd0bd2e28ef651da6863d75edca4c2aca (diff)
mfd: Add ab8500 version detection and enforcing
There are currently four different versions of the AB8500 around: AB8500, AB8505, AB9540 and AB8540. Unfortunately: - Some of the chips (AB8500, AB8505, AB9540) cannot read the AB8500_REV_REG register but return errors - Some of them have the same ID value in the hardware register AB8500_REV_REV, for example the first versions of AB8505 and AB9540 have 0xFF in this register - just like the AB8500. So we need to be able to enforce a certain version from the platform. We do this by using the id of the platform device that provides the read/write functions. Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com> Signed-off-by: Alex Macro <alex.macro@stericsson.com> Signed-off-by: Michel Jaouen <michel.jaouen@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/ab8500-core.c')
-rw-r--r--drivers/mfd/ab8500-core.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index d295941c9a3d..3547eee21aa4 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -90,6 +90,7 @@
90#define AB8500_IT_MASK24_REG 0x57 90#define AB8500_IT_MASK24_REG 0x57
91 91
92#define AB8500_REV_REG 0x80 92#define AB8500_REV_REG 0x80
93#define AB8500_IC_NAME_REG 0x82
93#define AB8500_SWITCH_OFF_STATUS 0x00 94#define AB8500_SWITCH_OFF_STATUS 0x00
94 95
95#define AB8500_TURN_ON_STATUS 0x00 96#define AB8500_TURN_ON_STATUS 0x00
@@ -105,6 +106,13 @@ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
105 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 106 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
106}; 107};
107 108
109static const char ab8500_version_str[][7] = {
110 [AB8500_VERSION_AB8500] = "AB8500",
111 [AB8500_VERSION_AB8505] = "AB8505",
112 [AB8500_VERSION_AB9540] = "AB9540",
113 [AB8500_VERSION_AB8540] = "AB8540",
114};
115
108static int ab8500_get_chip_id(struct device *dev) 116static int ab8500_get_chip_id(struct device *dev)
109{ 117{
110 struct ab8500 *ab8500; 118 struct ab8500 *ab8500;
@@ -256,9 +264,12 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
256 if (new == old) 264 if (new == old)
257 continue; 265 continue;
258 266
259 /* Interrupt register 12 doesn't exist prior to version 2.0 */ 267 /*
260 if (ab8500_irq_regoffset[i] == 11 && 268 * Interrupt register 12 doesn't exist prior to AB8500 version
261 ab8500->chip_id < AB8500_CUT2P0) 269 * 2.0
270 */
271 if (ab8500->irq_reg_offset[i] == 11 &&
272 is_ab8500_1p1_or_earlier(ab8500))
262 continue; 273 continue;
263 274
264 ab8500->oldmask[i] = new; 275 ab8500->oldmask[i] = new;
@@ -311,8 +322,11 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
311 int status; 322 int status;
312 u8 value; 323 u8 value;
313 324
314 /* Interrupt register 12 doesn't exist prior to version 2.0 */ 325 /*
315 if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0) 326 * Interrupt register 12 doesn't exist prior to AB8500 version
327 * 2.0
328 */
329 if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
316 continue; 330 continue;
317 331
318 status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 332 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
@@ -857,7 +871,7 @@ static struct attribute_group ab8500_attr_group = {
857 .attrs = ab8500_sysfs_entries, 871 .attrs = ab8500_sysfs_entries,
858}; 872};
859 873
860int __devinit ab8500_init(struct ab8500 *ab8500) 874int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
861{ 875{
862 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); 876 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
863 int ret; 877 int ret;
@@ -870,25 +884,29 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
870 mutex_init(&ab8500->lock); 884 mutex_init(&ab8500->lock);
871 mutex_init(&ab8500->irq_lock); 885 mutex_init(&ab8500->irq_lock);
872 886
887 if (version != AB8500_VERSION_UNDEFINED)
888 ab8500->version = version;
889 else {
890 ret = get_register_interruptible(ab8500, AB8500_MISC,
891 AB8500_IC_NAME_REG, &value);
892 if (ret < 0)
893 return ret;
894
895 ab8500->version = value;
896 }
897
873 ret = get_register_interruptible(ab8500, AB8500_MISC, 898 ret = get_register_interruptible(ab8500, AB8500_MISC,
874 AB8500_REV_REG, &value); 899 AB8500_REV_REG, &value);
875 if (ret < 0) 900 if (ret < 0)
876 return ret; 901 return ret;
877 902
878 switch (value) {
879 case AB8500_CUT1P0:
880 case AB8500_CUT1P1:
881 case AB8500_CUT2P0:
882 case AB8500_CUT3P0:
883 case AB8500_CUT3P3:
884 dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
885 break;
886 default:
887 dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
888 return -EINVAL;
889 }
890 ab8500->chip_id = value; 903 ab8500->chip_id = value;
891 904
905 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
906 ab8500_version_str[ab8500->version],
907 ab8500->chip_id >> 4,
908 ab8500->chip_id & 0x0F);
909
892 /* 910 /*
893 * ab8500 has switched off due to (SWITCH_OFF_STATUS): 911 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
894 * 0x01 Swoff bit programming 912 * 0x01 Swoff bit programming
@@ -912,9 +930,12 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
912 930
913 /* Clear and mask all interrupts */ 931 /* Clear and mask all interrupts */
914 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 932 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
915 /* Interrupt register 12 doesn't exist prior to version 2.0 */ 933 /*
916 if (ab8500_irq_regoffset[i] == 11 && 934 * Interrupt register 12 doesn't exist prior to AB8500 version
917 ab8500->chip_id < AB8500_CUT2P0) 935 * 2.0
936 */
937 if (ab8500->irq_reg_offset[i] == 11 &&
938 is_ab8500_1p1_or_earlier(ab8500))
918 continue; 939 continue;
919 940
920 get_register_interruptible(ab8500, AB8500_INTERRUPT, 941 get_register_interruptible(ab8500, AB8500_INTERRUPT,