aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2013-03-14 19:59:54 +0800
committerHaojian Zhuang <haojian.zhuang@linaro.org>2013-03-14 20:04:44 +0800
commitdd7229d3e5c7bff0a9501632755c5b6b209381ff (patch)
tree5aebebe94704cfd90d3431f40c0ff50194688adb /drivers
parent34d55f032da4e193dc732cb2fbca89eead8d8402 (diff)
mfd: hi6421: use spin lock
Avoid to use mutex lock in rmw operation. Use spin lock with irq disabled instead. Since irq handler also accesses pmic register, we should avoid resource conflict between irq context and kernel context. And append spin lock operation in pmic read/write too. Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/hi6421-pmic-core.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c
index b0e655163f3..4a44057f969 100644
--- a/drivers/mfd/hi6421-pmic-core.c
+++ b/drivers/mfd/hi6421-pmic-core.c
@@ -31,8 +31,6 @@
#include <linux/of_address.h>
#include <linux/mfd/hi6421-pmic.h>
-static DEFINE_MUTEX(reg_lock_mutex);
-
static struct of_device_id of_hi6421_pmic_child_match_tbl[] = {
/* regulators */
{
@@ -54,15 +52,38 @@ static struct of_device_id of_hi6421_pmic_match_tbl[] = {
{ /* end */ }
};
-/* Register Access Helpers, rmw() functions need to run locked */
+u32 hi6421_pmic_read(struct hi6421_pmic *pmic, int reg)
+{
+ unsigned long flags;
+ u32 ret;
+ spin_lock_irqsave(&pmic->lock, flags);
+ ret = readl_relaxed(pmic->regs + (reg << 2));
+ spin_unlock_irqrestore(&pmic->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(hi6421_pmic_read);
+
+void hi6421_pmic_write(struct hi6421_pmic *pmic, int reg, u32 val)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&pmic->lock, flags);
+ writel_relaxed(val, pmic->regs + (reg << 2));
+ spin_unlock_irqrestore(&pmic->lock, flags);
+}
+EXPORT_SYMBOL(hi6421_pmic_write);
+
void hi6421_pmic_rmw(struct hi6421_pmic *pmic, int reg,
- u32 mask, u32 bits)
+ u32 mask, u32 bits)
{
- mutex_lock(&reg_lock_mutex);
- hi6421_pmic_write(pmic, reg, \
- (hi6421_pmic_read(pmic, reg) & ~mask) | (mask & bits));
- mutex_unlock(&reg_lock_mutex);
+ u32 data;
+
+ spin_lock(&pmic->lock);
+ data = readl_relaxed(pmic->regs + (reg << 2)) & ~mask;
+ data |= mask & bits;
+ writel_relaxed(data, pmic->regs);
+ spin_unlock(&pmic->lock);
}
+EXPORT_SYMBOL(hi6421_pmic_rmw);
static int hi6421_pmic_probe(struct platform_device *pdev)
{
@@ -101,6 +122,8 @@ static int hi6421_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmic);
+ spin_lock_init(&pmic->lock);
+
/* set over-current protection debounce 8ms*/
hi6421_pmic_rmw(pmic, OCP_DEB_CTRL_REG, \
OCP_DEB_SEL_MASK | OCP_EN_DEBOUNCE_MASK | OCP_AUTO_STOP_MASK, \