summaryrefslogtreecommitdiff
path: root/drivers/misc/vib-gpio.c
diff options
context:
space:
mode:
authorDoug Zobel <dzobel1@motorola.com>2014-05-22 16:03:22 -0500
committerDouglas Zobel <dzobel1@motorola.com>2014-05-22 21:45:41 +0000
commitf0b8dfa7d5127e162e5c0ce1f653ced28800e015 (patch)
treeab45864bed76ee212bd50917fe362d495052a77d /drivers/misc/vib-gpio.c
parent53b3696135313573b60b726675c0721361b956cd (diff)
downloadolio-linux-3.10-f0b8dfa7d5127e162e5c0ce1f653ced28800e015.tar.xz
olio-linux-3.10-f0b8dfa7d5127e162e5c0ce1f653ced28800e015.zip
IKXCLOCK-1246 watch was vibrating continuously
Make IO operations (GPIO & regulator) atomic. Also add more debug logging. Change-Id: Ifba24a6753447a3abce7bd6fe5becb2c431a179f
Diffstat (limited to 'drivers/misc/vib-gpio.c')
-rw-r--r--drivers/misc/vib-gpio.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/misc/vib-gpio.c b/drivers/misc/vib-gpio.c
index a013f214e83..98a17d79b10 100644
--- a/drivers/misc/vib-gpio.c
+++ b/drivers/misc/vib-gpio.c
@@ -33,6 +33,7 @@ struct vib_gpio_data {
struct work_struct vib_work;
struct hrtimer timer;
spinlock_t lock;
+ struct mutex io_mutex; /* protect GPIO & regulator operations */
struct regulator *reg;
int gpio;
@@ -46,20 +47,28 @@ struct vib_gpio_data {
static int power_on(struct vib_gpio_data *vib_data)
{
- if (vib_data->reg)
+ if (vib_data->reg) {
+ dev_dbg(vib_data->dev.dev, "enable regulator\n");
return regulator_enable(vib_data->reg);
+ }
return 0;
}
static int power_off(struct vib_gpio_data *vib_data)
{
- if (vib_data->reg)
+ if (vib_data->reg) {
+ dev_dbg(vib_data->dev.dev, "disable regulator\n");
return regulator_disable(vib_data->reg);
+ }
return 0;
}
static void vib_gpio_set(struct vib_gpio_data *vib_data, int on)
{
+ dev_dbg(vib_data->dev.dev, "%s(%d)\n", __func__, on);
+
+ mutex_lock(&(vib_data->io_mutex));
+
if (on) {
if (!vib_data->vib_power_state) {
power_on(vib_data);
@@ -78,6 +87,8 @@ static void vib_gpio_set(struct vib_gpio_data *vib_data, int on)
vib_data->vib_power_state = 0;
}
}
+
+ mutex_unlock(&(vib_data->io_mutex));
}
static void vib_gpio_update(struct work_struct *work)
@@ -93,6 +104,7 @@ static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
{
struct vib_gpio_data *vib_data =
container_of(timer, struct vib_gpio_data, timer);
+ dev_dbg(vib_data->dev.dev, "Timer expired: disabling vibrator\n");
vib_data->vib_state = 0;
schedule_work(&vib_data->vib_work);
return HRTIMER_NORESTART;
@@ -117,6 +129,8 @@ static void vib_gpio_enable(struct timed_output_dev *dev, int value)
container_of(dev, struct vib_gpio_data, dev);
unsigned long flags;
+ dev_dbg(dev->dev, "Enable vibrator for %dms\n", value);
+
spin_lock_irqsave(&vib_data->lock, flags);
hrtimer_cancel(&vib_data->timer);
@@ -149,6 +163,8 @@ static int vib_gpio_probe(struct platform_device *pdev)
goto err;
}
+ mutex_init(&(vib_data->io_mutex));
+
platform_set_drvdata(pdev, vib_data);
vib_data->gpio = -1;
@@ -207,6 +223,7 @@ static int vib_gpio_probe(struct platform_device *pdev)
reg_put:
regulator_put(vib_data->reg);
+ mutex_destroy(&(vib_data->io_mutex));
free_mem:
kfree(vib_data);
err:
@@ -219,6 +236,7 @@ static int vib_gpio_remove(struct platform_device *pdev)
timed_output_dev_unregister(&vib_data->dev);
regulator_put(vib_data->reg);
+ mutex_destroy(&(vib_data->io_mutex));
kfree(vib_data);
return 0;