Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 308703
b: refs/heads/master
c: 112a80d
h: refs/heads/master
i:
  308701: 9467229
  308699: b4b94dc
  308695: e28a468
  308687: 171452c
  308671: 587b31a
v: v3
  • Loading branch information
Jonas Aaberg authored and Samuel Ortiz committed May 1, 2012
1 parent 238da46 commit ecfe3c2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7e82d6ff5d2c5e35d1fcb8c673287f7d780a13bb
refs/heads/master: 112a80d29b529d4057777ac2cb4ec15ff5b6d210
38 changes: 31 additions & 7 deletions trunk/drivers/mfd/ab8500-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,13 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
static int ab8500_set_register(struct device *dev, u8 bank,
u8 reg, u8 value)
{
int ret;
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);

return set_register_interruptible(ab8500, bank, reg, value);
atomic_inc(&ab8500->transfer_ongoing);
ret = set_register_interruptible(ab8500, bank, reg, value);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
}

static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
Expand Down Expand Up @@ -192,9 +196,13 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
static int ab8500_get_register(struct device *dev, u8 bank,
u8 reg, u8 *value)
{
int ret;
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);

return get_register_interruptible(ab8500, bank, reg, value);
atomic_inc(&ab8500->transfer_ongoing);
ret = get_register_interruptible(ab8500, bank, reg, value);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
}

static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
Expand Down Expand Up @@ -241,11 +249,14 @@ static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
static int ab8500_mask_and_set_register(struct device *dev,
u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
{
int ret;
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);

return mask_and_set_register_interruptible(ab8500, bank, reg,
bitmask, bitvalues);

atomic_inc(&ab8500->transfer_ongoing);
ret= mask_and_set_register_interruptible(ab8500, bank, reg,
bitmask, bitvalues);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
}

static struct abx500_ops ab8500_ops = {
Expand All @@ -264,6 +275,7 @@ static void ab8500_irq_lock(struct irq_data *data)
struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);

mutex_lock(&ab8500->irq_lock);
atomic_inc(&ab8500->transfer_ongoing);
}

static void ab8500_irq_sync_unlock(struct irq_data *data)
Expand Down Expand Up @@ -292,7 +304,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
}

atomic_dec(&ab8500->transfer_ongoing);
mutex_unlock(&ab8500->irq_lock);
}

Expand Down Expand Up @@ -332,6 +344,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev)

dev_vdbg(ab8500->dev, "interrupt\n");

atomic_inc(&ab8500->transfer_ongoing);

for (i = 0; i < ab8500->mask_size; i++) {
int regoffset = ab8500->irq_reg_offset[i];
int status;
Expand All @@ -355,9 +369,10 @@ static irqreturn_t ab8500_irq(int irq, void *dev)

handle_nested_irq(ab8500->irq_base + line);
value &= ~(1 << bit);

} while (value);
}

atomic_dec(&ab8500->transfer_ongoing);
return IRQ_HANDLED;
}

Expand Down Expand Up @@ -411,6 +426,14 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
}
}

int ab8500_suspend(struct ab8500 *ab8500)
{
if (atomic_read(&ab8500->transfer_ongoing))
return -EINVAL;
else
return 0;
}

/* AB8500 GPIO Resources */
static struct resource __devinitdata ab8500_gpio_resources[] = {
{
Expand Down Expand Up @@ -1059,6 +1082,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)

mutex_init(&ab8500->lock);
mutex_init(&ab8500->irq_lock);
atomic_set(&ab8500->transfer_ongoing, 0);

if (version != AB8500_VERSION_UNDEFINED)
ab8500->version = version;
Expand Down
6 changes: 5 additions & 1 deletion trunk/include/linux/mfd/abx500/ab8500.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef MFD_AB8500_H
#define MFD_AB8500_H

#include <linux/atomic.h>
#include <linux/mutex.h>

struct device;
Expand Down Expand Up @@ -224,6 +225,7 @@ enum ab8500_version {
* @dev: parent device
* @lock: read/write operations lock
* @irq_lock: genirq bus lock
* @transfer_ongoing: 0 if no transfer ongoing
* @irq: irq line
* @version: chip version id (e.g. ab8500 or ab9540)
* @chip_id: chip revision id
Expand All @@ -242,7 +244,7 @@ struct ab8500 {
struct device *dev;
struct mutex lock;
struct mutex irq_lock;

atomic_t transfer_ongoing;
int irq_base;
int irq;
enum ab8500_version version;
Expand Down Expand Up @@ -288,6 +290,8 @@ extern int __devinit ab8500_init(struct ab8500 *ab8500,
enum ab8500_version version);
extern int __devexit ab8500_exit(struct ab8500 *ab8500);

extern int ab8500_suspend(struct ab8500 *ab8500);

static inline int is_ab8500(struct ab8500 *ab)
{
return ab->version == AB8500_VERSION_AB8500;
Expand Down

0 comments on commit ecfe3c2

Please sign in to comment.