summaryrefslogtreecommitdiff
path: root/drivers/misc/m4sensorhub_fusion.c
diff options
context:
space:
mode:
authorViditha Hanumanthareddy <ngjq36@motorola.com>2014-08-07 14:20:40 -0500
committerViditha Hanumanthareddy <ngjq36@motorola.com>2014-08-08 15:28:25 -0500
commita5547c59d1127884c88948f769e80db33a9cb3d5 (patch)
tree8d40cf792c198feb0a821338086cf1ae0620a876 /drivers/misc/m4sensorhub_fusion.c
parent43d49c02672e9ea8ac5d2b85ae215166c195f967 (diff)
downloadolio-linux-3.10-a5547c59d1127884c88948f769e80db33a9cb3d5.tar.xz
olio-linux-3.10-a5547c59d1127884c88948f769e80db33a9cb3d5.zip
IKXCLOCK-3320: Poll for non wakable sensors
Bug : 16656953 All sensors were interrupt based, m4 would interrupt omap when the delay timeout occurs, but to be able mask non wakable sensor interrupts on suspend and resume, we r now moving non wakable sensors to be poll based, the kernel starts a timer for each sensor and reads data from m4 on timer expiry. Change-Id: I39f1a94563f3c4c65b586b63018e9e1afebd0d28
Diffstat (limited to 'drivers/misc/m4sensorhub_fusion.c')
-rw-r--r--drivers/misc/m4sensorhub_fusion.c71
1 files changed, 26 insertions, 45 deletions
diff --git a/drivers/misc/m4sensorhub_fusion.c b/drivers/misc/m4sensorhub_fusion.c
index c8d579fe4fe..f1ce277f2fe 100644
--- a/drivers/misc/m4sensorhub_fusion.c
+++ b/drivers/misc/m4sensorhub_fusion.c
@@ -45,17 +45,20 @@ struct m4fus_driver_data {
struct mutex mutex; /* controls driver entry points */
struct m4sensorhub_fusion_iio_data iiodat[M4FUS_NUM_FUSION_BUFFERS];
+ struct delayed_work m4fus_work;
int16_t samplerate;
int16_t latest_samplerate;
+ int16_t fastest_rate;
uint16_t status;
};
-
-static void m4fus_isr(enum m4sensorhub_irqs int_event, void *handle)
+static void m4fus_work_func(struct work_struct *work)
{
int err = 0;
- struct iio_dev *iio = handle;
- struct m4fus_driver_data *dd = iio_priv(iio);
+ struct m4fus_driver_data *dd = container_of(work,
+ struct m4fus_driver_data,
+ m4fus_work.work);
+ struct iio_dev *iio = platform_get_drvdata(dd->pdev);
int size = 0;
mutex_lock(&(dd->mutex));
@@ -129,6 +132,9 @@ static void m4fus_isr(enum m4sensorhub_irqs int_event, void *handle)
* in this one call (see the M4 passive driver).
*/
iio_push_to_buffers(iio, (unsigned char *)&(dd->iiodat[0]));
+ if (dd->samplerate > 0)
+ schedule_delayed_work(&(dd->m4fus_work),
+ msecs_to_jiffies(dd->samplerate));
m4fus_isr_fail:
if (err < 0)
@@ -145,9 +151,13 @@ static int m4fus_set_samplerate(struct iio_dev *iio, int16_t rate)
struct m4fus_driver_data *dd = iio_priv(iio);
int size = 0;
+ if ((rate >= 0) && (rate <= dd->fastest_rate))
+ rate = dd->fastest_rate;
+
dd->latest_samplerate = rate;
+
if (rate == dd->samplerate)
- goto m4fus_set_samplerate_irq_check;
+ goto m4fus_set_samplerate_fail;
size = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_FUSION_SAMPLERATE);
err = m4sensorhub_reg_write(dd->m4, M4SH_REG_FUSION_SAMPLERATE,
@@ -162,33 +172,10 @@ static int m4fus_set_samplerate(struct iio_dev *iio, int16_t rate)
goto m4fus_set_samplerate_fail;
}
dd->samplerate = rate;
-
-m4fus_set_samplerate_irq_check:
- if (rate >= 0) {
- /* Enable the IRQ if necessary */
- if (!(dd->status & (1 << M4FUS_IRQ_ENABLED_BIT))) {
- err = m4sensorhub_irq_enable(dd->m4,
- M4SH_IRQ_FUSION_DATA_READY);
- if (err < 0) {
- m4fus_err("%s: Failed to enable irq.\n",
- __func__);
- goto m4fus_set_samplerate_fail;
- }
- dd->status = dd->status | (1 << M4FUS_IRQ_ENABLED_BIT);
- }
- } else {
- /* Disable the IRQ if necessary */
- if (dd->status & (1 << M4FUS_IRQ_ENABLED_BIT)) {
- err = m4sensorhub_irq_disable(dd->m4,
- M4SH_IRQ_FUSION_DATA_READY);
- if (err < 0) {
- m4fus_err("%s: Failed to disable irq.\n",
- __func__);
- goto m4fus_set_samplerate_fail;
- }
- dd->status = dd->status & ~(1 << M4FUS_IRQ_ENABLED_BIT);
- }
- }
+ cancel_delayed_work(&(dd->m4fus_work));
+ if (dd->samplerate > 0)
+ schedule_delayed_work(&(dd->m4fus_work),
+ msecs_to_jiffies(rate));
m4fus_set_samplerate_fail:
return err;
@@ -383,6 +370,10 @@ static void m4fus_panic_restore(struct m4sensorhub_data *m4sensorhub,
__func__, err, size);
}
+ cancel_delayed_work(&(dd->m4fus_work));
+ if (dd->samplerate > 0)
+ schedule_delayed_work(&(dd->m4fus_work),
+ msecs_to_jiffies(dd->samplerate));
mutex_unlock(&(dd->mutex));
}
@@ -401,12 +392,7 @@ static int m4fus_driver_init(struct init_calldata *p_arg)
goto m4fus_driver_init_fail;
}
- err = m4sensorhub_irq_register(dd->m4,
- M4SH_IRQ_FUSION_DATA_READY, m4fus_isr, iio, 0);
- if (err < 0) {
- m4fus_err("%s: Failed to register M4 IRQ.\n", __func__);
- goto m4fus_driver_init_fail;
- }
+ INIT_DELAYED_WORK(&(dd->m4fus_work), m4fus_work_func);
err = m4sensorhub_panic_register(dd->m4, PANICHDL_FUSION_RESTORE,
m4fus_panic_restore, dd);
@@ -441,6 +427,7 @@ static int m4fus_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iio);
dd->samplerate = -1; /* We always start disabled */
dd->latest_samplerate = dd->samplerate;
+ dd->fastest_rate = 40;
err = m4fus_create_iiodev(iio); /* iio and dd are freed on fail */
if (err < 0) {
@@ -476,11 +463,7 @@ static int __exit m4fus_remove(struct platform_device *pdev)
goto m4fus_remove_exit;
mutex_lock(&(dd->mutex));
- if (dd->status & (1 << M4FUS_IRQ_ENABLED_BIT)) {
- m4sensorhub_irq_disable(dd->m4, M4SH_IRQ_FUSION_DATA_READY);
- dd->status = dd->status & ~(1 << M4FUS_IRQ_ENABLED_BIT);
- }
- m4sensorhub_irq_unregister(dd->m4, M4SH_IRQ_FUSION_DATA_READY);
+ cancel_delayed_work(&(dd->m4fus_work));
m4sensorhub_unregister_initcall(m4fus_driver_init);
m4fus_remove_iiodev(iio); /* dd is freed here */
@@ -492,10 +475,8 @@ static int m4fus_suspend(struct platform_device *pdev, pm_message_t state)
{
struct iio_dev *iio = platform_get_drvdata(pdev);
struct m4fus_driver_data *dd = iio_priv(iio);
- mutex_lock(&(dd->mutex));
if (m4fus_set_samplerate(iio, dd->latest_samplerate) < 0)
m4fus_err("%s: setrate retry failed\n", __func__);
- mutex_unlock(&(dd->mutex));
return 0;
}