aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-core.c
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2012-04-17 03:30:33 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-01 07:33:18 -0400
commit112a80d29b529d4057777ac2cb4ec15ff5b6d210 (patch)
treea649f58551524d4f07c083623ea084b6ecaf5ca1 /drivers/mfd/ab8500-core.c
parent7e82d6ff5d2c5e35d1fcb8c673287f7d780a13bb (diff)
mfd: Deny ab8500 suspend if i2c transfer is ongoing
If we are in the middle of an I2C transfer we need to deny suspend of the AB8500 core. Implement an atomic reference counter for the I2C operations to make sure we don't do this. Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> Reviewed-by: Mattias Wallin <mattias.wallin@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.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index ae67612317a8..eee95606bdbb 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -161,9 +161,13 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
161static int ab8500_set_register(struct device *dev, u8 bank, 161static int ab8500_set_register(struct device *dev, u8 bank,
162 u8 reg, u8 value) 162 u8 reg, u8 value)
163{ 163{
164 int ret;
164 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 165 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
165 166
166 return set_register_interruptible(ab8500, bank, reg, value); 167 atomic_inc(&ab8500->transfer_ongoing);
168 ret = set_register_interruptible(ab8500, bank, reg, value);
169 atomic_dec(&ab8500->transfer_ongoing);
170 return ret;
167} 171}
168 172
169static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 173static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
@@ -192,9 +196,13 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
192static int ab8500_get_register(struct device *dev, u8 bank, 196static int ab8500_get_register(struct device *dev, u8 bank,
193 u8 reg, u8 *value) 197 u8 reg, u8 *value)
194{ 198{
199 int ret;
195 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 200 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
196 201
197 return get_register_interruptible(ab8500, bank, reg, value); 202 atomic_inc(&ab8500->transfer_ongoing);
203 ret = get_register_interruptible(ab8500, bank, reg, value);
204 atomic_dec(&ab8500->transfer_ongoing);
205 return ret;
198} 206}
199 207
200static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 208static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
@@ -241,11 +249,14 @@ out:
241static int ab8500_mask_and_set_register(struct device *dev, 249static int ab8500_mask_and_set_register(struct device *dev,
242 u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 250 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
243{ 251{
252 int ret;
244 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 253 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
245 254
246 return mask_and_set_register_interruptible(ab8500, bank, reg, 255 atomic_inc(&ab8500->transfer_ongoing);
247 bitmask, bitvalues); 256 ret= mask_and_set_register_interruptible(ab8500, bank, reg,
248 257 bitmask, bitvalues);
258 atomic_dec(&ab8500->transfer_ongoing);
259 return ret;
249} 260}
250 261
251static struct abx500_ops ab8500_ops = { 262static struct abx500_ops ab8500_ops = {
@@ -264,6 +275,7 @@ static void ab8500_irq_lock(struct irq_data *data)
264 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 275 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
265 276
266 mutex_lock(&ab8500->irq_lock); 277 mutex_lock(&ab8500->irq_lock);
278 atomic_inc(&ab8500->transfer_ongoing);
267} 279}
268 280
269static void ab8500_irq_sync_unlock(struct irq_data *data) 281static void ab8500_irq_sync_unlock(struct irq_data *data)
@@ -292,7 +304,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
292 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 304 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
293 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 305 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
294 } 306 }
295 307 atomic_dec(&ab8500->transfer_ongoing);
296 mutex_unlock(&ab8500->irq_lock); 308 mutex_unlock(&ab8500->irq_lock);
297} 309}
298 310
@@ -332,6 +344,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
332 344
333 dev_vdbg(ab8500->dev, "interrupt\n"); 345 dev_vdbg(ab8500->dev, "interrupt\n");
334 346
347 atomic_inc(&ab8500->transfer_ongoing);
348
335 for (i = 0; i < ab8500->mask_size; i++) { 349 for (i = 0; i < ab8500->mask_size; i++) {
336 int regoffset = ab8500->irq_reg_offset[i]; 350 int regoffset = ab8500->irq_reg_offset[i];
337 int status; 351 int status;
@@ -355,9 +369,10 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
355 369
356 handle_nested_irq(ab8500->irq_base + line); 370 handle_nested_irq(ab8500->irq_base + line);
357 value &= ~(1 << bit); 371 value &= ~(1 << bit);
372
358 } while (value); 373 } while (value);
359 } 374 }
360 375 atomic_dec(&ab8500->transfer_ongoing);
361 return IRQ_HANDLED; 376 return IRQ_HANDLED;
362} 377}
363 378
@@ -411,6 +426,14 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
411 } 426 }
412} 427}
413 428
429int ab8500_suspend(struct ab8500 *ab8500)
430{
431 if (atomic_read(&ab8500->transfer_ongoing))
432 return -EINVAL;
433 else
434 return 0;
435}
436
414/* AB8500 GPIO Resources */ 437/* AB8500 GPIO Resources */
415static struct resource __devinitdata ab8500_gpio_resources[] = { 438static struct resource __devinitdata ab8500_gpio_resources[] = {
416 { 439 {
@@ -1059,6 +1082,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
1059 1082
1060 mutex_init(&ab8500->lock); 1083 mutex_init(&ab8500->lock);
1061 mutex_init(&ab8500->irq_lock); 1084 mutex_init(&ab8500->irq_lock);
1085 atomic_set(&ab8500->transfer_ongoing, 0);
1062 1086
1063 if (version != AB8500_VERSION_UNDEFINED) 1087 if (version != AB8500_VERSION_UNDEFINED)
1064 ab8500->version = version; 1088 ab8500->version = version;