aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-core.c
diff options
context:
space:
mode:
authorMattias Wallin <mattias.wallin@stericsson.com>2010-09-10 11:47:56 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-10-28 18:29:19 -0400
commit47c1697508f2ec9f6b31ce6c825fe1017871dea6 (patch)
treee22afa146c3232802abf482caa167e0e2444093b /drivers/mfd/ab8500-core.c
parentf4ebcab36088d45a5e8889e9b63d77e01c808076 (diff)
mfd: Align ab8500 with the abx500 interface
This patch makes the ab8500 mixed signal chip expose the same interface for register access as the ab3100, ab3550 and ab5500 chip. The ab8500_read() and ab8500_write() is removed and replaced with abx500_get_register_interruptible() and abx500_set_register_interruptible(). Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/ab8500-core.c')
-rw-r--r--drivers/mfd/ab8500-core.c281
1 files changed, 166 insertions, 115 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index b8c4b80e4c43..373783146b5e 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -4,6 +4,7 @@
4 * License Terms: GNU General Public License v2 4 * License Terms: GNU General Public License v2
5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> 5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com> 6 * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7 * Changes: Mattias Wallin <mattias.wallin@stericsson.com>
7 */ 8 */
8 9
9#include <linux/kernel.h> 10#include <linux/kernel.h>
@@ -15,6 +16,7 @@
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/platform_device.h> 17#include <linux/platform_device.h>
17#include <linux/mfd/core.h> 18#include <linux/mfd/core.h>
19#include <linux/mfd/abx500.h>
18#include <linux/mfd/ab8500.h> 20#include <linux/mfd/ab8500.h>
19#include <linux/regulator/ab8500.h> 21#include <linux/regulator/ab8500.h>
20 22
@@ -22,71 +24,71 @@
22 * Interrupt register offsets 24 * Interrupt register offsets
23 * Bank : 0x0E 25 * Bank : 0x0E
24 */ 26 */
25#define AB8500_IT_SOURCE1_REG 0x0E00 27#define AB8500_IT_SOURCE1_REG 0x00
26#define AB8500_IT_SOURCE2_REG 0x0E01 28#define AB8500_IT_SOURCE2_REG 0x01
27#define AB8500_IT_SOURCE3_REG 0x0E02 29#define AB8500_IT_SOURCE3_REG 0x02
28#define AB8500_IT_SOURCE4_REG 0x0E03 30#define AB8500_IT_SOURCE4_REG 0x03
29#define AB8500_IT_SOURCE5_REG 0x0E04 31#define AB8500_IT_SOURCE5_REG 0x04
30#define AB8500_IT_SOURCE6_REG 0x0E05 32#define AB8500_IT_SOURCE6_REG 0x05
31#define AB8500_IT_SOURCE7_REG 0x0E06 33#define AB8500_IT_SOURCE7_REG 0x06
32#define AB8500_IT_SOURCE8_REG 0x0E07 34#define AB8500_IT_SOURCE8_REG 0x07
33#define AB8500_IT_SOURCE19_REG 0x0E12 35#define AB8500_IT_SOURCE19_REG 0x12
34#define AB8500_IT_SOURCE20_REG 0x0E13 36#define AB8500_IT_SOURCE20_REG 0x13
35#define AB8500_IT_SOURCE21_REG 0x0E14 37#define AB8500_IT_SOURCE21_REG 0x14
36#define AB8500_IT_SOURCE22_REG 0x0E15 38#define AB8500_IT_SOURCE22_REG 0x15
37#define AB8500_IT_SOURCE23_REG 0x0E16 39#define AB8500_IT_SOURCE23_REG 0x16
38#define AB8500_IT_SOURCE24_REG 0x0E17 40#define AB8500_IT_SOURCE24_REG 0x17
39 41
40/* 42/*
41 * latch registers 43 * latch registers
42 */ 44 */
43#define AB8500_IT_LATCH1_REG 0x0E20 45#define AB8500_IT_LATCH1_REG 0x20
44#define AB8500_IT_LATCH2_REG 0x0E21 46#define AB8500_IT_LATCH2_REG 0x21
45#define AB8500_IT_LATCH3_REG 0x0E22 47#define AB8500_IT_LATCH3_REG 0x22
46#define AB8500_IT_LATCH4_REG 0x0E23 48#define AB8500_IT_LATCH4_REG 0x23
47#define AB8500_IT_LATCH5_REG 0x0E24 49#define AB8500_IT_LATCH5_REG 0x24
48#define AB8500_IT_LATCH6_REG 0x0E25 50#define AB8500_IT_LATCH6_REG 0x25
49#define AB8500_IT_LATCH7_REG 0x0E26 51#define AB8500_IT_LATCH7_REG 0x26
50#define AB8500_IT_LATCH8_REG 0x0E27 52#define AB8500_IT_LATCH8_REG 0x27
51#define AB8500_IT_LATCH9_REG 0x0E28 53#define AB8500_IT_LATCH9_REG 0x28
52#define AB8500_IT_LATCH10_REG 0x0E29 54#define AB8500_IT_LATCH10_REG 0x29
53#define AB8500_IT_LATCH19_REG 0x0E32 55#define AB8500_IT_LATCH19_REG 0x32
54#define AB8500_IT_LATCH20_REG 0x0E33 56#define AB8500_IT_LATCH20_REG 0x33
55#define AB8500_IT_LATCH21_REG 0x0E34 57#define AB8500_IT_LATCH21_REG 0x34
56#define AB8500_IT_LATCH22_REG 0x0E35 58#define AB8500_IT_LATCH22_REG 0x35
57#define AB8500_IT_LATCH23_REG 0x0E36 59#define AB8500_IT_LATCH23_REG 0x36
58#define AB8500_IT_LATCH24_REG 0x0E37 60#define AB8500_IT_LATCH24_REG 0x37
59 61
60/* 62/*
61 * mask registers 63 * mask registers
62 */ 64 */
63 65
64#define AB8500_IT_MASK1_REG 0x0E40 66#define AB8500_IT_MASK1_REG 0x40
65#define AB8500_IT_MASK2_REG 0x0E41 67#define AB8500_IT_MASK2_REG 0x41
66#define AB8500_IT_MASK3_REG 0x0E42 68#define AB8500_IT_MASK3_REG 0x42
67#define AB8500_IT_MASK4_REG 0x0E43 69#define AB8500_IT_MASK4_REG 0x43
68#define AB8500_IT_MASK5_REG 0x0E44 70#define AB8500_IT_MASK5_REG 0x44
69#define AB8500_IT_MASK6_REG 0x0E45 71#define AB8500_IT_MASK6_REG 0x45
70#define AB8500_IT_MASK7_REG 0x0E46 72#define AB8500_IT_MASK7_REG 0x46
71#define AB8500_IT_MASK8_REG 0x0E47 73#define AB8500_IT_MASK8_REG 0x47
72#define AB8500_IT_MASK9_REG 0x0E48 74#define AB8500_IT_MASK9_REG 0x48
73#define AB8500_IT_MASK10_REG 0x0E49 75#define AB8500_IT_MASK10_REG 0x49
74#define AB8500_IT_MASK11_REG 0x0E4A 76#define AB8500_IT_MASK11_REG 0x4A
75#define AB8500_IT_MASK12_REG 0x0E4B 77#define AB8500_IT_MASK12_REG 0x4B
76#define AB8500_IT_MASK13_REG 0x0E4C 78#define AB8500_IT_MASK13_REG 0x4C
77#define AB8500_IT_MASK14_REG 0x0E4D 79#define AB8500_IT_MASK14_REG 0x4D
78#define AB8500_IT_MASK15_REG 0x0E4E 80#define AB8500_IT_MASK15_REG 0x4E
79#define AB8500_IT_MASK16_REG 0x0E4F 81#define AB8500_IT_MASK16_REG 0x4F
80#define AB8500_IT_MASK17_REG 0x0E50 82#define AB8500_IT_MASK17_REG 0x50
81#define AB8500_IT_MASK18_REG 0x0E51 83#define AB8500_IT_MASK18_REG 0x51
82#define AB8500_IT_MASK19_REG 0x0E52 84#define AB8500_IT_MASK19_REG 0x52
83#define AB8500_IT_MASK20_REG 0x0E53 85#define AB8500_IT_MASK20_REG 0x53
84#define AB8500_IT_MASK21_REG 0x0E54 86#define AB8500_IT_MASK21_REG 0x54
85#define AB8500_IT_MASK22_REG 0x0E55 87#define AB8500_IT_MASK22_REG 0x55
86#define AB8500_IT_MASK23_REG 0x0E56 88#define AB8500_IT_MASK23_REG 0x56
87#define AB8500_IT_MASK24_REG 0x0E57 89#define AB8500_IT_MASK24_REG 0x57
88 90
89#define AB8500_REV_REG 0x1080 91#define AB8500_REV_REG 0x80
90 92
91/* 93/*
92 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 94 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
@@ -99,96 +101,132 @@ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
99 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, 101 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21,
100}; 102};
101 103
102static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) 104static int ab8500_get_chip_id(struct device *dev)
105{
106 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
107 return (int)ab8500->chip_id;
108}
109
110static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
111 u8 reg, u8 data)
103{ 112{
104 int ret; 113 int ret;
114 /*
115 * Put the u8 bank and u8 register together into a an u16.
116 * The bank on higher 8 bits and register in lower 8 bits.
117 * */
118 u16 addr = ((u16)bank) << 8 | reg;
105 119
106 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 120 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
107 121
122 ret = mutex_lock_interruptible(&ab8500->lock);
123 if (ret)
124 return ret;
125
108 ret = ab8500->write(ab8500, addr, data); 126 ret = ab8500->write(ab8500, addr, data);
109 if (ret < 0) 127 if (ret < 0)
110 dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 128 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
111 addr, ret); 129 addr, ret);
130 mutex_unlock(&ab8500->lock);
112 131
113 return ret; 132 return ret;
114} 133}
115 134
116/** 135static int ab8500_set_register(struct device *dev, u8 bank,
117 * ab8500_write() - write an AB8500 register 136 u8 reg, u8 value)
118 * @ab8500: device to write to
119 * @addr: address of the register
120 * @data: value to write
121 */
122int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
123{ 137{
124 int ret; 138 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
125
126 mutex_lock(&ab8500->lock);
127 ret = __ab8500_write(ab8500, addr, data);
128 mutex_unlock(&ab8500->lock);
129 139
130 return ret; 140 return set_register_interruptible(ab8500, bank, reg, value);
131} 141}
132EXPORT_SYMBOL_GPL(ab8500_write);
133 142
134static int __ab8500_read(struct ab8500 *ab8500, u16 addr) 143static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
144 u8 reg, u8 *value)
135{ 145{
136 int ret; 146 int ret;
147 /* put the u8 bank and u8 reg together into a an u16.
148 * bank on higher 8 bits and reg in lower */
149 u16 addr = ((u16)bank) << 8 | reg;
150
151 ret = mutex_lock_interruptible(&ab8500->lock);
152 if (ret)
153 return ret;
137 154
138 ret = ab8500->read(ab8500, addr); 155 ret = ab8500->read(ab8500, addr);
139 if (ret < 0) 156 if (ret < 0)
140 dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 157 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
141 addr, ret); 158 addr, ret);
159 else
160 *value = ret;
142 161
162 mutex_unlock(&ab8500->lock);
143 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 163 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
144 164
145 return ret; 165 return ret;
146} 166}
147 167
148/** 168static int ab8500_get_register(struct device *dev, u8 bank,
149 * ab8500_read() - read an AB8500 register 169 u8 reg, u8 *value)
150 * @ab8500: device to read from
151 * @addr: address of the register
152 */
153int ab8500_read(struct ab8500 *ab8500, u16 addr)
154{ 170{
155 int ret; 171 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
156
157 mutex_lock(&ab8500->lock);
158 ret = __ab8500_read(ab8500, addr);
159 mutex_unlock(&ab8500->lock);
160 172
161 return ret; 173 return get_register_interruptible(ab8500, bank, reg, value);
162} 174}
163EXPORT_SYMBOL_GPL(ab8500_read); 175
164 176static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
165/** 177 u8 reg, u8 bitmask, u8 bitvalues)
166 * ab8500_set_bits() - set a bitfield in an AB8500 register
167 * @ab8500: device to read from
168 * @addr: address of the register
169 * @mask: mask of the bitfield to modify
170 * @data: value to set to the bitfield
171 */
172int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data)
173{ 178{
174 int ret; 179 int ret;
180 u8 data;
181 /* put the u8 bank and u8 reg together into a an u16.
182 * bank on higher 8 bits and reg in lower */
183 u16 addr = ((u16)bank) << 8 | reg;
175 184
176 mutex_lock(&ab8500->lock); 185 ret = mutex_lock_interruptible(&ab8500->lock);
186 if (ret)
187 return ret;
177 188
178 ret = __ab8500_read(ab8500, addr); 189 ret = ab8500->read(ab8500, addr);
179 if (ret < 0) 190 if (ret < 0) {
191 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
192 addr, ret);
180 goto out; 193 goto out;
194 }
181 195
182 ret &= ~mask; 196 data = (u8)ret;
183 ret |= data; 197 data = (~bitmask & data) | (bitmask & bitvalues);
184 198
185 ret = __ab8500_write(ab8500, addr, ret); 199 ret = ab8500->write(ab8500, addr, data);
200 if (ret < 0)
201 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
202 addr, ret);
186 203
204 dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data);
187out: 205out:
188 mutex_unlock(&ab8500->lock); 206 mutex_unlock(&ab8500->lock);
189 return ret; 207 return ret;
190} 208}
191EXPORT_SYMBOL_GPL(ab8500_set_bits); 209
210static int ab8500_mask_and_set_register(struct device *dev,
211 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
212{
213 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
214
215 return mask_and_set_register_interruptible(ab8500, bank, reg,
216 bitmask, bitvalues);
217
218}
219
220static struct abx500_ops ab8500_ops = {
221 .get_chip_id = ab8500_get_chip_id,
222 .get_register = ab8500_get_register,
223 .set_register = ab8500_set_register,
224 .get_register_page = NULL,
225 .set_register_page = NULL,
226 .mask_and_set_register = ab8500_mask_and_set_register,
227 .event_registers_startup_state_get = NULL,
228 .startup_irq_enabled = NULL,
229};
192 230
193static void ab8500_irq_lock(unsigned int irq) 231static void ab8500_irq_lock(unsigned int irq)
194{ 232{
@@ -213,7 +251,7 @@ static void ab8500_irq_sync_unlock(unsigned int irq)
213 ab8500->oldmask[i] = new; 251 ab8500->oldmask[i] = new;
214 252
215 reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; 253 reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
216 ab8500_write(ab8500, reg, new); 254 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
217 } 255 }
218 256
219 mutex_unlock(&ab8500->irq_lock); 257 mutex_unlock(&ab8500->irq_lock);
@@ -257,9 +295,11 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
257 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { 295 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
258 int regoffset = ab8500_irq_regoffset[i]; 296 int regoffset = ab8500_irq_regoffset[i];
259 int status; 297 int status;
298 u8 value;
260 299
261 status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset); 300 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
262 if (status <= 0) 301 AB8500_IT_LATCH1_REG + regoffset, &value);
302 if (status < 0 || value == 0)
263 continue; 303 continue;
264 304
265 do { 305 do {
@@ -267,8 +307,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
267 int line = i * 8 + bit; 307 int line = i * 8 + bit;
268 308
269 handle_nested_irq(ab8500->irq_base + line); 309 handle_nested_irq(ab8500->irq_base + line);
270 status &= ~(1 << bit); 310 value &= ~(1 << bit);
271 } while (status); 311 } while (value);
272 } 312 }
273 313
274 return IRQ_HANDLED; 314 return IRQ_HANDLED;
@@ -381,6 +421,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
381 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); 421 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
382 int ret; 422 int ret;
383 int i; 423 int i;
424 u8 value;
384 425
385 if (plat) 426 if (plat)
386 ab8500->irq_base = plat->irq_base; 427 ab8500->irq_base = plat->irq_base;
@@ -388,7 +429,8 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
388 mutex_init(&ab8500->lock); 429 mutex_init(&ab8500->lock);
389 mutex_init(&ab8500->irq_lock); 430 mutex_init(&ab8500->irq_lock);
390 431
391 ret = ab8500_read(ab8500, AB8500_REV_REG); 432 ret = get_register_interruptible(ab8500, AB8500_MISC,
433 AB8500_REV_REG, &value);
392 if (ret < 0) 434 if (ret < 0)
393 return ret; 435 return ret;
394 436
@@ -397,28 +439,37 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
397 * 0x10 - Cut 1.0 439 * 0x10 - Cut 1.0
398 * 0x11 - Cut 1.1 440 * 0x11 - Cut 1.1
399 */ 441 */
400 if (ret == 0x0 || ret == 0x10 || ret == 0x11) { 442 if (value == 0x0 || value == 0x10 || value == 0x11) {
401 ab8500->revision = ret; 443 ab8500->revision = value;
402 dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret); 444 dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
403 } else { 445 } else {
404 dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret); 446 dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
405 return -EINVAL; 447 return -EINVAL;
406 } 448 }
449 ab8500->chip_id = value;
407 450
408 if (plat && plat->init) 451 if (plat && plat->init)
409 plat->init(ab8500); 452 plat->init(ab8500);
410 453
411 /* Clear and mask all interrupts */ 454 /* Clear and mask all interrupts */
412 for (i = 0; i < 10; i++) { 455 for (i = 0; i < 10; i++) {
413 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); 456 get_register_interruptible(ab8500, AB8500_INTERRUPT,
414 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); 457 AB8500_IT_LATCH1_REG + i, &value);
458 set_register_interruptible(ab8500, AB8500_INTERRUPT,
459 AB8500_IT_MASK1_REG + i, 0xff);
415 } 460 }
416 461
417 for (i = 18; i < 24; i++) { 462 for (i = 18; i < 24; i++) {
418 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); 463 get_register_interruptible(ab8500, AB8500_INTERRUPT,
419 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); 464 AB8500_IT_LATCH1_REG + i, &value);
465 set_register_interruptible(ab8500, AB8500_INTERRUPT,
466 AB8500_IT_MASK1_REG + i, 0xff);
420 } 467 }
421 468
469 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
470 if (ret)
471 return ret;
472
422 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) 473 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
423 ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 474 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
424 475