* [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000
@ 2011-10-24 20:21 Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado
` (7 more replies)
0 siblings, 8 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
The following set of patches add spi and device tree support for the cma3000 driver and also
add support for the cmr3000 gyroscope.
v4 of the set.
Changelog:
v4: -Changes propossed by Dmitry Torokhov
v3: -Support for device tree
-Separate read/write spi
v2: -Changes propossed by Jonathan Cameron
-More fixes for the cma3000 driver
Ricardo Ribalda Delgado (6):
input/cma3000_d0x: Support devices without pdata
input/cma3000_d0x: Check silicon version
input/cma3000_d0x: Keep configuration on poweroff
input/cma3000_d0x: Add CMA3000 spi support
Input: add CMR3000 gyrsocope driver
input/cma3000_d0x: Match comment to name of struct
drivers/input/misc/Kconfig | 38 +++-
drivers/input/misc/Makefile | 3 +
drivers/input/misc/cma3000_d0x.c | 100 +++++++-
drivers/input/misc/cma3000_d0x_spi.c | 145 ++++++++++++
drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
drivers/input/misc/cmr3000_d0x.h | 45 ++++
drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
include/linux/input/cma3000.h | 2 +-
include/linux/input/cmr3000.h | 54 +++++
9 files changed, 941 insertions(+), 16 deletions(-)
create mode 100644 drivers/input/misc/cma3000_d0x_spi.c
create mode 100644 drivers/input/misc/cmr3000_d0x.c
create mode 100644 drivers/input/misc/cmr3000_d0x.h
create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
create mode 100644 include/linux/input/cmr3000.h
--
1.7.7
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 2/6] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado
` (6 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
Architectures based on device-tree does not have platform data
associated to the spi/i2c devices. Instead they can have some of
the options embedded in the device tree.
This patch allows the cma3000 driver to get the configuration
from the platform_data, the device tree, or in the wort case,
just use a default configuration.
---
v3: Fixes suggested by Jonathan Cameron
-Code style
v3: Fixes suggested by Jonathan Cameron
-Add support for the device tree
v2: Fixes suggested by Jonathan Cameron
-Spelling
-Simplify pdata!=NULL check
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/input/misc/cma3000_d0x.c | 86 +++++++++++++++++++++++++++++++++-----
1 files changed, 75 insertions(+), 11 deletions(-)
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
index 1633b63..e66036d 100644
--- a/drivers/input/misc/cma3000_d0x.c
+++ b/drivers/input/misc/cma3000_d0x.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/cma3000.h>
+#include <linux/of.h>
#include "cma3000_d0x.h"
@@ -62,9 +63,21 @@
#define BIT_TO_2G 18
#define BIT_TO_8G 71
+static struct cma3000_platform_data cma3000_default_pdata = {
+ .mdthr = 0x8,
+ .mdfftmr = 0x33,
+ .ffthr = 0x8,
+ .mode = CMAMODE_MEAS400,
+ .g_range = CMARANGE_2G,
+ .fuzz_x = BIT_TO_2G,
+ .fuzz_y = BIT_TO_2G,
+ .fuzz_z = BIT_TO_2G,
+ .irqflags = 0,
+};
+
struct cma3000_accl_data {
const struct cma3000_bus_ops *bus_ops;
- const struct cma3000_platform_data *pdata;
+ struct cma3000_platform_data pdata;
struct device *dev;
struct input_dev *input_dev;
@@ -182,7 +195,7 @@ static int cma3000_reset(struct cma3000_accl_data *data)
static int cma3000_poweron(struct cma3000_accl_data *data)
{
- const struct cma3000_platform_data *pdata = data->pdata;
+ struct cma3000_platform_data *pdata = &data->pdata;
u8 ctrl = 0;
int ret;
@@ -280,22 +293,57 @@ void cma3000_resume(struct cma3000_accl_data *data)
}
EXPORT_SYMBOL(cma3000_resume);
+#ifdef CONFIG_OF
+void cma3000_get_pdata_of(struct device *dev, struct cma3000_accl_data *data)
+{
+ const __be32 *property;
+ int len;
+
+ property = of_get_property(dev->of_node, "vti,mdthr", &len);
+ if (property && len == sizeof(int))
+ data->pdata.mdthr = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,mdfftmr", &len);
+ if (property && len == sizeof(int))
+ data->pdata.mdfftmr = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,mode", &len);
+ if (property && len == sizeof(int))
+ data->pdata.mode = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,g_range", &len);
+ if (property && len == sizeof(int))
+ data->pdata.g_range = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_x = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_y = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_z = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,irqflags", &len);
+ if (property && len == sizeof(int))
+ data->pdata.irqflags = be32_to_cpup(property);
+
+ return;
+}
+#endif
+
struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
const struct cma3000_bus_ops *bops)
{
- const struct cma3000_platform_data *pdata = dev->platform_data;
+ struct cma3000_platform_data *pdata;
struct cma3000_accl_data *data;
struct input_dev *input_dev;
int rev;
int error;
- if (!pdata) {
- dev_err(dev, "platform data not found\n");
- error = -EINVAL;
- goto err_out;
- }
-
-
/* if no IRQ return error */
if (irq == 0) {
error = -EINVAL;
@@ -309,10 +357,26 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
goto err_free_mem;
}
+ /*Init platform data*/
+ if (dev->platform_data != NULL) {
+ memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
+ } else {
+ memcpy(&data->pdata, &cma3000_default_pdata,
+ sizeof(data->pdata));
+ #ifdef CONFIG_OF
+ if (dev->of_node != NULL)
+ cma3000_get_pdata_of(dev, data);
+ else
+ dev_info(dev, "platform data not found, using default\n");
+ #else
+ dev_info(dev, "platform data not found, using default\n");
+ #endif
+ }
+ pdata = &data->pdata;
+
data->dev = dev;
data->input_dev = input_dev;
data->bus_ops = bops;
- data->pdata = pdata;
data->irq = irq;
mutex_init(&data->mutex);
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCHv4 2/6] input/cma3000_d0x: Check silicon version
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 3/6] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado
` (5 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
Improve probing of the cma3000 chip, by checking the revision of the
device.
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
---
v4: Add ACKs to patch
v2: Fixes suggested by Jonathan Cameron
-Remove WhoamI pr_info
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/input/misc/cma3000_d0x.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
index e66036d..97e36fa 100644
--- a/drivers/input/misc/cma3000_d0x.c
+++ b/drivers/input/misc/cma3000_d0x.c
@@ -27,6 +27,8 @@
#include "cma3000_d0x.h"
+#define CMA3000_REV 0x10
+
#define CMA3000_WHOAMI 0x00
#define CMA3000_REVID 0x01
#define CMA3000_CTRL 0x02
@@ -420,7 +422,11 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
error = rev;
goto err_free_mem;
}
-
+ if (rev != CMA3000_REV) {
+ error = -EINVAL;
+ pr_err("CMA3000 Accelerometer: Unknown Revision %x\n", rev);
+ goto err_free_mem;
+ }
pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCHv4 3/6] input/cma3000_d0x: Keep configuration on poweroff
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 2/6] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado
` (4 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
When the device goes to poweroff keep the spi/i2c configuration.
Otherwhise the device could not wake up if it was in spi mode.
---
v2: Fixes suggested by Jonathan Cameron
-Code Style
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/input/misc/cma3000_d0x.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
index 97e36fa..35d2577 100644
--- a/drivers/input/misc/cma3000_d0x.c
+++ b/drivers/input/misc/cma3000_d0x.c
@@ -45,6 +45,7 @@
#define CMA3000_RANGE2G (1 << 7)
#define CMA3000_RANGE8G (0 << 7)
#define CMA3000_BUSI2C (0 << 4)
+#define CMA3000_BUSSPI (1 << 4)
#define CMA3000_MODEMASK (7 << 1)
#define CMA3000_GRANGEMASK (1 << 7)
@@ -231,8 +232,11 @@ static int cma3000_poweron(struct cma3000_accl_data *data)
static int cma3000_poweroff(struct cma3000_accl_data *data)
{
int ret;
+ u8 ctrl = CMAMODE_POFF;
- ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
+ ctrl |= data->bus_ops->ctrl_mod;
+
+ ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
msleep(CMA3000_SETDELAY);
return ret;
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
` (2 preceding siblings ...)
2011-10-24 20:21 ` [PATCHv4 3/6] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado
` (3 subsequent siblings)
7 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
Add support for SPI communication.
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
---
v4: Add ACKs to patch
v3: Fixes suggested by Jonathan Cameron
-Separate write/read commands
-Do not check 1/0 mask
-Use spi_w8r8 and spi_write_then_read functions
v2: Fixes suggested by Jonathan Cameron
-Add filename to based on header
-Rename set with write
-Set spi buffers as cache aligned
-Code Style
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/input/misc/Kconfig | 14 +++-
drivers/input/misc/Makefile | 1 +
drivers/input/misc/cma3000_d0x_spi.c | 145 ++++++++++++++++++++++++++++++++++
3 files changed, 158 insertions(+), 2 deletions(-)
create mode 100644 drivers/input/misc/cma3000_d0x_spi.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index c9104bb..b9f2e93 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -496,8 +496,8 @@ config INPUT_CMA3000
Say Y here if you want to use VTI CMA3000_D0x Accelerometer
driver
- This driver currently only supports I2C interface to the
- controller. Also select the I2C method.
+ This driver supports I2C and SPI interface to the
+ controller. Also select the I2C method and/or the SPI method.
If unsure, say N
@@ -514,6 +514,16 @@ config INPUT_CMA3000_I2C
To compile this driver as a module, choose M here: the
module will be called cma3000_d0x_i2c.
+config INPUT_CMA3000_SPI
+ tristate "Support SPI bus connection"
+ depends on INPUT_CMA3000 && SPI
+ help
+ Say Y here if you want to use VTI CMA3000_D0x Accelerometer
+ through SPI interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cma3000_d0x_spi.
+
config INPUT_XEN_KBDDEV_FRONTEND
tristate "Xen virtual keyboard and mouse support"
depends on XEN_FBDEV_FRONTEND
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 299ad5e..7305f6f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
+obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/cma3000_d0x_spi.c b/drivers/input/misc/cma3000_d0x_spi.c
new file mode 100644
index 0000000..c91a552
--- /dev/null
+++ b/drivers/input/misc/cma3000_d0x_spi.c
@@ -0,0 +1,145 @@
+/*
+ * Implements SPI interface for VTI CMA300_D0x Accelerometer driver
+ *
+ * Copyright (C) 2011 Qtechnology
+ * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com>
+ * Based on:
+ * drivers/input/misc/cma3000_d0x_i2c.c by Hemanth V
+ * drivers/input/mis/adxl34x-spi.c by Michael Hennerich
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/input/cma3000.h>
+#include "cma3000_d0x.h"
+
+static int cma3000_spi_write(struct device *dev, u8 reg, u8 val, char *msg)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+ u8 tmp[2];
+
+ tmp[0] = (reg << 2) | 2;
+ tmp[1] = val;
+
+ ret = spi_write_then_read(spi, tmp, sizeof(tmp), NULL, 0);
+ if (ret < 0) {
+ dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cma3000_spi_read(struct device *dev, u8 reg, char *msg)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+ ret = spi_w8r8(spi, reg << 2);
+ if (ret < 0)
+ dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
+
+ return ret;
+}
+
+static const struct cma3000_bus_ops cma3000_spi_bops = {
+ .bustype = BUS_SPI,
+#define CMA3000_BUSSPI (1 << 4)
+ .ctrl_mod = CMA3000_BUSSPI,
+ .read = cma3000_spi_read,
+ .write = cma3000_spi_write,
+};
+
+static int __devinit cma3000_spi_probe(struct spi_device *spi)
+{
+ struct cma3000_accl_data *data;
+
+ data = cma3000_init(&spi->dev, spi->irq, &cma3000_spi_bops);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ spi_set_drvdata(spi, data);
+
+ return 0;
+}
+
+static int __devexit cma3000_spi_remove(struct spi_device *spi)
+{
+ struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
+
+ cma3000_exit(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int cma3000_spi_suspend(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
+
+ cma3000_suspend(data);
+
+ return 0;
+}
+
+static int cma3000_spi_resume(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
+
+ cma3000_resume(data);
+
+ return 0;
+}
+
+static const struct dev_pm_ops cma3000_spi_pm_ops = {
+ .suspend = cma3000_spi_suspend,
+ .resume = cma3000_spi_resume,
+};
+#endif
+
+static SIMPLE_DEV_PM_OPS(cma3000_spi_pm, cma3000_spi_suspend,
+ cma3000_spi_resume);
+
+static struct spi_driver cma3000_driver = {
+ .driver = {
+ .name = "cma3000_d01",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .pm = &cma3000_spi_pm,
+ },
+ .probe = cma3000_spi_probe,
+ .remove = __devexit_p(cma3000_spi_remove),
+};
+
+static int __init cma3000_spi_init(void)
+{
+ return spi_register_driver(&cma3000_driver);
+}
+
+static void __exit cma3000_spi_exit(void)
+{
+ spi_unregister_driver(&cma3000_driver);
+}
+
+module_init(cma3000_spi_init);
+module_exit(cma3000_spi_exit);
+
+MODULE_DESCRIPTION("CMA3000-D0x Accelerometer SPI Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
` (3 preceding siblings ...)
2011-10-24 20:21 ` [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
2011-10-24 21:40 ` Grant Likely
2011-10-24 20:21 ` [PATCHv4 6/6] input/cma3000_d0x: Match comment to name of struct Ricardo Ribalda Delgado
` (2 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
Add support for CMR3000 Tri-axis accelerometer. CMR3000 supports both
I2C/SPI bus communication, currently the driver supports SPI
communication, since I have no hardware to test the I2C communication.
---
v4: Fixes suggested by Dmitry Torokhov
-Do not release the input device until the irq has been released
v3: Fixes suggested by Jonathan Cameron
-Support DT
-Cleaner spi read/write
v2: Fixes suggested by Jonathan Cameron
-Code Stype
-Check pdata!=NULL
-SPI align Cacheline
-More clear based on
-%s/set/write/
-%s/accl/gyro/
-remove READ/SET macros
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/input/misc/Kconfig | 24 ++
drivers/input/misc/Makefile | 2 +
drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
drivers/input/misc/cmr3000_d0x.h | 45 ++++
drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
include/linux/input/cmr3000.h | 54 +++++
6 files changed, 695 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/misc/cmr3000_d0x.c
create mode 100644 drivers/input/misc/cmr3000_d0x.h
create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
create mode 100644 include/linux/input/cmr3000.h
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b9f2e93..7c56f94 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -524,6 +524,30 @@ config INPUT_CMA3000_SPI
To compile this driver as a module, choose M here: the
module will be called cma3000_d0x_spi.
+config INPUT_CMR3000
+ tristate "VTI CMR3000 Tri-axis gyroscope"
+ help
+ Say Y here if you want to use VTI CMR3000_D0x Gyroscope
+ driver
+
+ This driver currently only supports SPI interface to the
+ controller. Also select the SPI method.
+
+ If unsure, say N
+
+ To compile this driver as a module, choose M here: the
+ module will be called cmr3000_d0x.
+
+config INPUT_CMR3000_SPI
+ tristate "Support SPI bus connection"
+ depends on INPUT_CMR3000 && SPI
+ help
+ Say Y here if you want to use VTI CMR3000_D0x Gyroscope
+ through SPI interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cmr3000_d0x_spi.
+
config INPUT_XEN_KBDDEV_FRONTEND
tristate "Xen virtual keyboard and mouse support"
depends on XEN_FBDEV_FRONTEND
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 7305f6f..c7fe09a 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -21,6 +21,8 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
+obj-$(CONFIG_INPUT_CMR3000) += cmr3000_d0x.o
+obj-$(CONFIG_INPUT_CMR3000_SPI) += cmr3000_d0x_spi.o
obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/cmr3000_d0x.c b/drivers/input/misc/cmr3000_d0x.c
new file mode 100644
index 0000000..d046149
--- /dev/null
+++ b/drivers/input/misc/cmr3000_d0x.c
@@ -0,0 +1,426 @@
+/*
+ * VTI CMR3000_D0x Gyroscope driver
+ *
+ * Copyright (C) 2011 Qtechnology
+ * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ * Based on:
+ * drivers/input/misc/cma3000_d0x.c by: Hemanth V
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/cmr3000.h>
+#include <linux/of.h>
+
+#include "cmr3000_d0x.h"
+
+#define CMR3000_REV 0x21
+
+#define CMR3000_WHOAMI 0x00
+#define CMR3000_REVID 0x01
+#define CMR3000_CTRL 0x02
+#define CMR3000_STATUS 0x03
+#define CMR3000_X_LSB 0x0C
+#define CMR3000_X_MSB 0x0D
+#define CMR3000_Y_LSB 0x0E
+#define CMR3000_Y_MSB 0x0F
+#define CMR3000_Z_LSB 0x10
+#define CMR3000_Z_MSB 0x11
+#define CMR3000_I2C_ADDR 0x22
+#define CMR3000_PDR 0x26
+
+#define CMR3000_IRQDIS (1 << 0)
+#define CMR3000_MODEMASK (3 << 1)
+#define CMR3000_BUSI2C (0 << 4)
+#define CMR3000_BUSSPI (1 << 4)
+#define CMR3000_INTLOW (1 << 6)
+#define CMR3000_INTHIGH (0 << 6)
+#define CMR3000_RST (1 << 7)
+
+#define CMRMODE_SHIFT 1
+#define CMRIRQLEVEL_SHIFT 6
+
+#define CMR3000_STATUS_PERR (1 << 0)
+#define CMR3000_STATUS_PORST (1 << 3)
+
+/* Settling time delay in ms */
+#define CMR3000_SETDELAY 30
+
+/*
+ * Bit weights mult/div in dps for bit 0, other bits need
+ * multipy factor 2^n. 11th bit is the sign bit.
+ */
+#define BIT_TO_DPS_MUL 3
+#define BIT_TO_DPS_DIV 32
+
+static struct cmr3000_platform_data cmr3000_default_pdata = {
+ .irq_level = CMR3000_INTHIGH,
+ .mode = CMRMODE_MEAS80,
+ .fuzz_x = 1,
+ .fuzz_y = 1,
+ .fuzz_z = 1,
+ .irqflags = 0,
+};
+
+struct cmr3000_gyro_data {
+ const struct cmr3000_bus_ops *bus_ops;
+ struct cmr3000_platform_data pdata;
+
+ struct device *dev;
+ struct input_dev *input_dev;
+
+ int irq_level;
+ u8 mode;
+
+ int bit_to_mg;
+ int irq;
+
+ struct mutex mutex;
+ bool opened;
+ bool suspended;
+};
+
+static void decode_dps(struct cmr3000_gyro_data *data, int *datax,
+ int *datay, int *dataz)
+{
+ /* Data in 2's complement, convert to dps */
+ *datax = (((s16) ((*datax) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
+ *datay = (((s16) ((*datay) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
+ *dataz = (((s16) ((*dataz) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
+}
+
+static irqreturn_t cmr3000_thread_irq(int irq, void *dev_id)
+{
+ struct cmr3000_gyro_data *data = dev_id;
+ int datax, datay, dataz;
+ u8 mode, intr_status;
+
+ intr_status = data->bus_ops->read(data->dev, CMR3000_STATUS,
+ "irq status");
+ intr_status = data->bus_ops->read(data->dev, CMR3000_CTRL,
+ "control mode");
+ if (intr_status < 0)
+ return IRQ_NONE;
+
+ /* Interrupt not for this device */
+ if (intr_status & CMR3000_IRQDIS)
+ return IRQ_NONE;
+
+ mode = (intr_status & CMR3000_MODEMASK) >> CMRMODE_SHIFT;
+ if ((mode != CMRMODE_MEAS80)
+ && (mode != CMRMODE_MEAS20))
+ return IRQ_NONE;
+
+ datax = (data->bus_ops->read(data->dev, CMR3000_X_MSB, "X_MSB")) << 8;
+ datax |= data->bus_ops->read(data->dev, CMR3000_X_LSB, "X_LSB");
+ datay = (data->bus_ops->read(data->dev, CMR3000_Y_MSB, "Y_MSB")) << 8;
+ datay |= data->bus_ops->read(data->dev, CMR3000_Y_LSB, "Y_LSB");
+ dataz = (data->bus_ops->read(data->dev, CMR3000_Z_MSB, "Z_MSB")) << 8;
+ dataz |= data->bus_ops->read(data->dev, CMR3000_Z_LSB, "Z_LSB");
+
+ /* Device closed */
+ if ((data->mode != CMRMODE_MEAS80)
+ && (data->mode != CMRMODE_MEAS20))
+ return IRQ_NONE;
+
+ /* Decode register values to dps */
+ decode_dps(data, &datax, &datay, &dataz);
+
+ input_report_abs(data->input_dev, ABS_X, datax);
+ input_report_abs(data->input_dev, ABS_Y, datay);
+ input_report_abs(data->input_dev, ABS_Z, dataz);
+ input_sync(data->input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static int cmr3000_poweron(struct cmr3000_gyro_data *data)
+{
+ const struct cmr3000_platform_data *pdata = &data->pdata;
+ u8 ctrl;
+ int ret;
+
+ ctrl = pdata->irq_level << CMRIRQLEVEL_SHIFT;
+ ctrl |= data->mode << CMRMODE_SHIFT;
+ ctrl |= data->bus_ops->ctrl_mod;
+ ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
+ "Mode setting");
+ if (ret < 0)
+ return -EIO;
+
+ msleep(CMR3000_SETDELAY);
+
+ return 0;
+}
+
+static int cmr3000_poweroff(struct cmr3000_gyro_data *data)
+{
+ int ret;
+ u8 ctrl = CMRMODE_POFF;
+
+ ctrl |= data->bus_ops->ctrl_mod;
+ ctrl |= CMR3000_IRQDIS;
+
+ ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
+ "Mode setting");
+ msleep(CMR3000_SETDELAY);
+
+ return ret;
+}
+
+static int cmr3000_reset(struct cmr3000_gyro_data *data)
+{
+ int val;
+
+ /* Reset chip */
+ data->bus_ops->write(data->dev, CMR3000_CTRL, CMR3000_RST, "Reset");
+ mdelay(2);
+
+ /* Settling time delay */
+ val = data->bus_ops->read(data->dev, CMR3000_STATUS, "Status");
+ if (val < 0) {
+ dev_err(data->dev, "Reset failed\n");
+ return val;
+ }
+
+ if (val & CMR3000_STATUS_PERR) {
+ dev_err(data->dev, "Parity Error\n");
+ return -EIO;
+ }
+
+ return cmr3000_poweroff(data);
+}
+
+static int cmr3000_open(struct input_dev *input_dev)
+{
+ struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
+
+ mutex_lock(&data->mutex);
+
+ if (!data->suspended)
+ cmr3000_poweron(data);
+
+ data->opened = true;
+
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+static void cmr3000_close(struct input_dev *input_dev)
+{
+ struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
+
+ mutex_lock(&data->mutex);
+
+ if (!data->suspended)
+ cmr3000_poweroff(data);
+
+ data->opened = false;
+
+ mutex_unlock(&data->mutex);
+}
+
+void cmr3000_suspend(struct cmr3000_gyro_data *data)
+{
+ mutex_lock(&data->mutex);
+
+ if (!data->suspended && data->opened)
+ cmr3000_poweroff(data);
+
+ data->suspended = true;
+
+ mutex_unlock(&data->mutex);
+}
+EXPORT_SYMBOL(cmr3000_suspend);
+
+void cmr3000_resume(struct cmr3000_gyro_data *data)
+{
+ mutex_lock(&data->mutex);
+
+ if (data->suspended && data->opened)
+ cmr3000_poweron(data);
+
+ data->suspended = false;
+
+ mutex_unlock(&data->mutex);
+}
+EXPORT_SYMBOL(cmr3000_resume);
+
+#ifdef CONFIG_OF
+void cmr3000_get_pdata_of(struct device *dev, struct cmr3000_gyro_data *data)
+{
+ const __be32 *property;
+ int len;
+
+ property = of_get_property(dev->of_node, "vti,irq_level", &len);
+ if (property && len == sizeof(int))
+ data->pdata.irq_level = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,mode", &len);
+ if (property && len == sizeof(int))
+ data->pdata.mode = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_x = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_y = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
+ if (property && len == sizeof(int))
+ data->pdata.fuzz_z = be32_to_cpup(property);
+
+ property = of_get_property(dev->of_node, "vti,irqflags", &len);
+ if (property && len == sizeof(int))
+ data->pdata.irqflags = be32_to_cpup(property);
+
+ return;
+}
+#endif
+
+struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
+ const struct cmr3000_bus_ops *bops)
+{
+ struct cmr3000_platform_data *pdata;
+ struct cmr3000_gyro_data *data;
+ struct input_dev *input_dev;
+ int rev;
+ int error;
+
+ /* if no IRQ return error */
+ if (irq == 0) {
+ error = -EINVAL;
+ goto err_out;
+ }
+
+ data = kzalloc(sizeof(struct cmr3000_gyro_data), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!data || !input_dev) {
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ /*Init platform data*/
+ if (dev->platform_data != NULL) {
+ memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
+ } else {
+ memcpy(&data->pdata, &cmr3000_default_pdata,
+ sizeof(data->pdata));
+ #ifdef CONFIG_OF
+ if (dev->of_node != NULL)
+ cmr3000_get_pdata_of(dev, data);
+ else
+ #endif
+ dev_info(dev, "platform data not found, using default\n");
+ }
+ pdata = &data->pdata;
+
+ data->dev = dev;
+ data->input_dev = input_dev;
+ data->bus_ops = bops;
+ data->irq = irq;
+ mutex_init(&data->mutex);
+
+ data->mode = pdata->mode;
+ if ((data->mode != CMRMODE_MEAS80)
+ && (data->mode != CMRMODE_MEAS20)) {
+ data->mode = CMRMODE_MEAS80;
+ dev_warn(dev, "Invalid mode specified, assuming 80Hz\n");
+ }
+
+ data->irq_level = pdata->irq_level;
+ if ((data->irq_level != CMR3000_INTLOW)
+ && (data->irq_level != CMR3000_INTHIGH)) {
+ data->irq_level = CMR3000_INTHIGH;
+ dev_warn(data->dev,
+ "Invalid int level specified, assuming high\n");
+ }
+
+ input_dev->name = "cmr3000-gyroscope";
+ input_dev->id.bustype = bops->bustype;
+ input_dev->open = cmr3000_open;
+ input_dev->close = cmr3000_close;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+
+ input_set_abs_params(input_dev, ABS_X,
+ -CMRRANGE, CMRRANGE, pdata->fuzz_x, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ -CMRRANGE, CMRRANGE, pdata->fuzz_y, 0);
+ input_set_abs_params(input_dev, ABS_Z,
+ -CMRRANGE, CMRRANGE, pdata->fuzz_z, 0);
+
+ input_set_drvdata(input_dev, data);
+
+ error = cmr3000_reset(data);
+ if (error)
+ goto err_free_mem;
+
+ rev = data->bus_ops->read(data->dev, CMR3000_REVID, "Revid");
+ if (rev < 0) {
+ error = rev;
+ goto err_free_mem;
+ }
+ if (rev != CMR3000_REV) {
+ error = -EINVAL;
+ pr_err("CMR3000 Gyroscope: Unknown Revision %x\n", rev);
+ goto err_free_mem;
+ }
+ pr_info("CMR3000 Gyroscope: Revision %x\n", rev);
+
+ error = request_threaded_irq(irq, NULL, cmr3000_thread_irq,
+ pdata->irqflags | IRQF_ONESHOT,
+ "cmr3000_d0x", data);
+ if (error) {
+ dev_err(dev, "request_threaded_irq failed\n");
+ goto err_free_mem;
+ }
+
+ error = input_register_device(data->input_dev);
+ if (error) {
+ dev_err(dev, "Unable to register input device\n");
+ goto err_free_irq;
+ }
+
+ return data;
+
+err_free_irq:
+ free_irq(irq, data);
+err_free_mem:
+ input_free_device(input_dev);
+ kfree(data);
+err_out:
+ return ERR_PTR(error);
+}
+EXPORT_SYMBOL(cmr3000_init);
+
+void cmr3000_exit(struct cmr3000_gyro_data *data)
+{
+ free_irq(data->irq, data);
+ input_unregister_device(data->input_dev);
+ kfree(data);
+}
+EXPORT_SYMBOL(cmr3000_exit);
+
+MODULE_DESCRIPTION("CMR3000-D0x Gyroscope Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
diff --git a/drivers/input/misc/cmr3000_d0x.h b/drivers/input/misc/cmr3000_d0x.h
new file mode 100644
index 0000000..3d0984a
--- /dev/null
+++ b/drivers/input/misc/cmr3000_d0x.h
@@ -0,0 +1,45 @@
+/*
+ * VTI CMR3000_D0x Gyroscpe driver
+ *
+ * Copyright (C) 2011 Qtechnology
+ * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ * Based on:
+ * drivers/input/misc/cma3000_d0x.h by Hemanth V
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _INPUT_CMR3000_H
+#define _INPUT_CMR3000_H
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+struct device;
+struct cmr3000_gyro_data;
+
+struct cmr3000_bus_ops {
+ u16 bustype;
+ u8 ctrl_mod;
+ int (*read) (struct device *, u8, char *);
+ int (*write) (struct device *, u8, u8, char *);
+};
+
+struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
+ const struct cmr3000_bus_ops *bops);
+void cmr3000_exit(struct cmr3000_gyro_data *);
+void cmr3000_suspend(struct cmr3000_gyro_data *);
+void cmr3000_resume(struct cmr3000_gyro_data *);
+
+#endif
diff --git a/drivers/input/misc/cmr3000_d0x_spi.c b/drivers/input/misc/cmr3000_d0x_spi.c
new file mode 100644
index 0000000..7f27fa3
--- /dev/null
+++ b/drivers/input/misc/cmr3000_d0x_spi.c
@@ -0,0 +1,144 @@
+/*
+ * Implements SPI interface for VTI CMR300_D0x Accelerometer driver
+ *
+ * Copyright (C) 2011 Qtechnology
+ * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com>
+ * Based on:
+ * drivers/input/misc/cma3000_d0x_i2c.c by Hemanth V
+ * drivers/input/mis/adxl34x-spi.c by Michael Hennerich
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/input/cmr3000.h>
+#include "cmr3000_d0x.h"
+
+static int cmr3000_spi_write(struct device *dev, u8 reg, u8 val, char *msg)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+ u8 tmp[2];
+
+ tmp[0] = (reg << 2) | 2;
+ tmp[1] = val;
+
+ ret = spi_write_then_read(spi, tmp, sizeof(tmp), NULL, 0);
+ if (ret < 0) {
+ dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int cmr3000_spi_read(struct device *dev, u8 reg, char *msg)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+ ret = spi_w8r8(spi, reg << 2);
+ if (ret < 0)
+ dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
+
+ return ret;
+}
+
+static const struct cmr3000_bus_ops cmr3000_spi_bops = {
+ .bustype = BUS_SPI,
+#define CMR3000_BUSSPI (1 << 4)
+ .ctrl_mod = CMR3000_BUSSPI,
+ .read = cmr3000_spi_read,
+ .write = cmr3000_spi_write,
+};
+
+static int __devinit cmr3000_spi_probe(struct spi_device *spi)
+{
+ struct cmr3000_gyro_data *data;
+
+ data = cmr3000_init(&spi->dev, spi->irq, &cmr3000_spi_bops);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ spi_set_drvdata(spi, data);
+
+ return 0;
+}
+
+static int __devexit cmr3000_spi_remove(struct spi_device *spi)
+{
+ struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
+
+ cmr3000_exit(data);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int cmr3000_spi_suspend(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
+
+ cmr3000_suspend(data);
+
+ return 0;
+}
+
+static int cmr3000_spi_resume(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
+
+ cmr3000_resume(data);
+
+ return 0;
+}
+
+static const struct dev_pm_ops cmr3000_spi_pm_ops = {
+ .suspend = cmr3000_spi_suspend,
+ .resume = cmr3000_spi_resume,
+};
+#endif
+
+static SIMPLE_DEV_PM_OPS(cmr3000_spi_pm, cmr3000_spi_suspend,
+ cmr3000_spi_resume);
+
+static struct spi_driver cmr3000_driver = {
+ .driver = {
+ .name = "cmr3000_d01",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .pm = &cmr3000_spi_pm,
+ },
+ .probe = cmr3000_spi_probe,
+ .remove = __devexit_p(cmr3000_spi_remove),
+};
+
+static int __init cmr3000_spi_init(void)
+{
+ return spi_register_driver(&cmr3000_driver);
+}
+
+static void __exit cmr3000_spi_exit(void)
+{
+ spi_unregister_driver(&cmr3000_driver);
+}
+
+module_init(cmr3000_spi_init);
+module_exit(cmr3000_spi_exit);
+
+MODULE_DESCRIPTION("CMR3000-D0x Gyroscope SPI Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
diff --git a/include/linux/input/cmr3000.h b/include/linux/input/cmr3000.h
new file mode 100644
index 0000000..dfcf9e3
--- /dev/null
+++ b/include/linux/input/cmr3000.h
@@ -0,0 +1,54 @@
+/*
+ * VTI CMR3000_Dxx Gyroscope driver
+ *
+ * Copyright (C) 2011 Qtechnology
+ * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ * Based on:
+ * include/linux/input/cma3000.h by Hemanth V
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LINUX_CMR3000_H
+#define _LINUX_CMR3000_H
+
+#define CMRMODE_DEFAULT 0
+#define CMRMODE_STANDBY 1
+#define CMRMODE_MEAS20 2
+#define CMRMODE_MEAS80 3
+#define CMRMODE_POFF 0
+
+#define CMRIRQLEVEL_LOW 1
+#define CMRIRQLEVEL_HIGH 0
+
+#define CMRRANGE 3072
+
+/**
+ * struct cmr3000_platform_data - CMR3000 Platform data
+ * @fuzz_x: Noise on X Axis
+ * @fuzz_y: Noise on Y Axis
+ * @fuzz_z: Noise on Z Axis
+ * @mode: Operating mode
+ * @irq_level: Irq level
+ */
+struct cmr3000_platform_data {
+ int fuzz_x;
+ int fuzz_y;
+ int fuzz_z;
+ uint8_t irq_level;
+ uint8_t mode;
+ unsigned long irqflags;
+};
+
+#endif
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCHv4 6/6] input/cma3000_d0x: Match comment to name of struct
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
` (4 preceding siblings ...)
2011-10-24 20:21 ` [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado
@ 2011-10-24 20:21 ` Ricardo Ribalda Delgado
[not found] ` <1319487676-27181-2-git-send-email-ricardo.ribalda@gmail.com>
[not found] ` <1319487676-27181-5-git-send-email-ricardo.ribalda@gmail.com>
7 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-24 20:21 UTC (permalink / raw)
To: dmitry.torokhov, grant.likely, sameo, peter.ujfalusi, jic23,
aghayal, david, Shubhrajyoti
Cc: Ricardo Ribalda Delgado
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
---
v4: Add ACKs to patch
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
include/linux/input/cma3000.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/input/cma3000.h b/include/linux/input/cma3000.h
index cbbaac2..e8c28e8 100644
--- a/include/linux/input/cma3000.h
+++ b/include/linux/input/cma3000.h
@@ -33,7 +33,7 @@
#define CMARANGE_8G 8000
/**
- * struct cma3000_i2c_platform_data - CMA3000 Platform data
+ * struct cma3000_platform_data - CMA3000 Platform data
* @fuzz_x: Noise on X Axis
* @fuzz_y: Noise on Y Axis
* @fuzz_z: Noise on Z Axis
--
1.7.7
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
[not found] ` <1319487676-27181-2-git-send-email-ricardo.ribalda@gmail.com>
@ 2011-10-24 21:31 ` Grant Likely
2011-10-25 7:38 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-10-24 21:31 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Mon, Oct 24, 2011 at 10:21:11PM +0200, Ricardo Ribalda Delgado wrote:
> Architectures based on device-tree does not have platform data
> associated to the spi/i2c devices. Instead they can have some of
> the options embedded in the device tree.
>
> This patch allows the cma3000 driver to get the configuration
> from the platform_data, the device tree, or in the wort case,
> just use a default configuration.
>
> ---
Drop this line, git cuts everything below a '---' line from the commit text.
>
> v3: Fixes suggested by Jonathan Cameron
> -Code style
>
> v3: Fixes suggested by Jonathan Cameron
> -Add support for the device tree
>
> v2: Fixes suggested by Jonathan Cameron
> -Spelling
> -Simplify pdata!=NULL check
>
> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
> ---
> drivers/input/misc/cma3000_d0x.c | 86 +++++++++++++++++++++++++++++++++-----
> 1 files changed, 75 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c
> index 1633b63..e66036d 100644
> --- a/drivers/input/misc/cma3000_d0x.c
> +++ b/drivers/input/misc/cma3000_d0x.c
> @@ -23,6 +23,7 @@
> #include <linux/slab.h>
> #include <linux/input.h>
> #include <linux/input/cma3000.h>
> +#include <linux/of.h>
>
> #include "cma3000_d0x.h"
>
> @@ -62,9 +63,21 @@
> #define BIT_TO_2G 18
> #define BIT_TO_8G 71
>
> +static struct cma3000_platform_data cma3000_default_pdata = {
> + .mdthr = 0x8,
> + .mdfftmr = 0x33,
> + .ffthr = 0x8,
> + .mode = CMAMODE_MEAS400,
> + .g_range = CMARANGE_2G,
> + .fuzz_x = BIT_TO_2G,
> + .fuzz_y = BIT_TO_2G,
> + .fuzz_z = BIT_TO_2G,
> + .irqflags = 0,
> +};
> +
> struct cma3000_accl_data {
> const struct cma3000_bus_ops *bus_ops;
> - const struct cma3000_platform_data *pdata;
> + struct cma3000_platform_data pdata;
>
> struct device *dev;
> struct input_dev *input_dev;
> @@ -182,7 +195,7 @@ static int cma3000_reset(struct cma3000_accl_data *data)
>
> static int cma3000_poweron(struct cma3000_accl_data *data)
> {
> - const struct cma3000_platform_data *pdata = data->pdata;
> + struct cma3000_platform_data *pdata = &data->pdata;
> u8 ctrl = 0;
> int ret;
>
> @@ -280,22 +293,57 @@ void cma3000_resume(struct cma3000_accl_data *data)
> }
> EXPORT_SYMBOL(cma3000_resume);
>
> +#ifdef CONFIG_OF
> +void cma3000_get_pdata_of(struct device *dev, struct cma3000_accl_data *data)
> +{
> + const __be32 *property;
> + int len;
> +
> + property = of_get_property(dev->of_node, "vti,mdthr", &len);
> + if (property && len == sizeof(int))
> + data->pdata.mdthr = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,mdfftmr", &len);
> + if (property && len == sizeof(int))
> + data->pdata.mdfftmr = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,mode", &len);
> + if (property && len == sizeof(int))
> + data->pdata.mode = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,g_range", &len);
> + if (property && len == sizeof(int))
> + data->pdata.g_range = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_x = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_y = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_z = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,irqflags", &len);
> + if (property && len == sizeof(int))
> + data->pdata.irqflags = be32_to_cpup(property);
This binding needs documentation before it can be merged.
> +
> + return;
> +}
> +#endif
No of_device_id match table to match against compatible values?
> +
> struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
> const struct cma3000_bus_ops *bops)
> {
> - const struct cma3000_platform_data *pdata = dev->platform_data;
> + struct cma3000_platform_data *pdata;
> struct cma3000_accl_data *data;
> struct input_dev *input_dev;
> int rev;
> int error;
>
> - if (!pdata) {
> - dev_err(dev, "platform data not found\n");
> - error = -EINVAL;
> - goto err_out;
> - }
> -
> -
> /* if no IRQ return error */
> if (irq == 0) {
> error = -EINVAL;
> @@ -309,10 +357,26 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
> goto err_free_mem;
> }
>
> + /*Init platform data*/
> + if (dev->platform_data != NULL) {
> + memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
> + } else {
> + memcpy(&data->pdata, &cma3000_default_pdata,
> + sizeof(data->pdata));
> + #ifdef CONFIG_OF
> + if (dev->of_node != NULL)
> + cma3000_get_pdata_of(dev, data);
> + else
> + dev_info(dev, "platform data not found, using default\n");
> + #else
> + dev_info(dev, "platform data not found, using default\n");
> + #endif
> + }
> + pdata = &data->pdata;
> +
> data->dev = dev;
> data->input_dev = input_dev;
> data->bus_ops = bops;
> - data->pdata = pdata;
> data->irq = irq;
> mutex_init(&data->mutex);
>
> --
> 1.7.7
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
[not found] ` <1319487676-27181-5-git-send-email-ricardo.ribalda@gmail.com>
@ 2011-10-24 21:36 ` Grant Likely
2011-10-25 7:24 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-10-24 21:36 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Mon, Oct 24, 2011 at 10:21:14PM +0200, Ricardo Ribalda Delgado wrote:
> Add support for SPI communication.
>
> Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
Again, drop this line, and acked-by lines should be grouped with the
signed-off-by lines at the end of the commit text.
> v4: Add ACKs to patch
>
> v3: Fixes suggested by Jonathan Cameron
> -Separate write/read commands
> -Do not check 1/0 mask
> -Use spi_w8r8 and spi_write_then_read functions
> v2: Fixes suggested by Jonathan Cameron
> -Add filename to based on header
> -Rename set with write
> -Set spi buffers as cache aligned
> -Code Style
>
> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
> ---
> drivers/input/misc/Kconfig | 14 +++-
> drivers/input/misc/Makefile | 1 +
> drivers/input/misc/cma3000_d0x_spi.c | 145 ++++++++++++++++++++++++++++++++++
> 3 files changed, 158 insertions(+), 2 deletions(-)
> create mode 100644 drivers/input/misc/cma3000_d0x_spi.c
>
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index c9104bb..b9f2e93 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -496,8 +496,8 @@ config INPUT_CMA3000
> Say Y here if you want to use VTI CMA3000_D0x Accelerometer
> driver
>
> - This driver currently only supports I2C interface to the
> - controller. Also select the I2C method.
> + This driver supports I2C and SPI interface to the
> + controller. Also select the I2C method and/or the SPI method.
>
> If unsure, say N
>
> @@ -514,6 +514,16 @@ config INPUT_CMA3000_I2C
> To compile this driver as a module, choose M here: the
> module will be called cma3000_d0x_i2c.
>
> +config INPUT_CMA3000_SPI
> + tristate "Support SPI bus connection"
> + depends on INPUT_CMA3000 && SPI
> + help
> + Say Y here if you want to use VTI CMA3000_D0x Accelerometer
> + through SPI interface.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cma3000_d0x_spi.
> +
> config INPUT_XEN_KBDDEV_FRONTEND
> tristate "Xen virtual keyboard and mouse support"
> depends on XEN_FBDEV_FRONTEND
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index 299ad5e..7305f6f 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
> obj-$(CONFIG_INPUT_CM109) += cm109.o
> obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
> obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
> +obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
> obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
> obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
> diff --git a/drivers/input/misc/cma3000_d0x_spi.c b/drivers/input/misc/cma3000_d0x_spi.c
> new file mode 100644
> index 0000000..c91a552
> --- /dev/null
> +++ b/drivers/input/misc/cma3000_d0x_spi.c
> @@ -0,0 +1,145 @@
> +/*
> + * Implements SPI interface for VTI CMA300_D0x Accelerometer driver
> + *
> + * Copyright (C) 2011 Qtechnology
> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com>
> + * Based on:
> + * drivers/input/misc/cma3000_d0x_i2c.c by Hemanth V
> + * drivers/input/mis/adxl34x-spi.c by Michael Hennerich
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +#include <linux/input/cma3000.h>
> +#include "cma3000_d0x.h"
> +
> +static int cma3000_spi_write(struct device *dev, u8 reg, u8 val, char *msg)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + int ret;
> + u8 tmp[2];
> +
> + tmp[0] = (reg << 2) | 2;
> + tmp[1] = val;
> +
> + ret = spi_write_then_read(spi, tmp, sizeof(tmp), NULL, 0);
> + if (ret < 0) {
> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int cma3000_spi_read(struct device *dev, u8 reg, char *msg)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + int ret;
> +
> + ret = spi_w8r8(spi, reg << 2);
> + if (ret < 0)
> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
> +
> + return ret;
> +}
Mark Brown had posted a generic indirect register read/write library
that I believe is getting merged. Maybe this driver should be using
it?
> +
> +static const struct cma3000_bus_ops cma3000_spi_bops = {
> + .bustype = BUS_SPI,
> +#define CMA3000_BUSSPI (1 << 4)
> + .ctrl_mod = CMA3000_BUSSPI,
> + .read = cma3000_spi_read,
> + .write = cma3000_spi_write,
> +};
> +
> +static int __devinit cma3000_spi_probe(struct spi_device *spi)
> +{
> + struct cma3000_accl_data *data;
> +
> + data = cma3000_init(&spi->dev, spi->irq, &cma3000_spi_bops);
> + if (IS_ERR(data))
> + return PTR_ERR(data);
> +
> + spi_set_drvdata(spi, data);
> +
> + return 0;
> +}
> +
> +static int __devexit cma3000_spi_remove(struct spi_device *spi)
> +{
> + struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
> +
> + cma3000_exit(data);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int cma3000_spi_suspend(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
> +
> + cma3000_suspend(data);
> +
> + return 0;
> +}
> +
> +static int cma3000_spi_resume(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct cma3000_accl_data *data = dev_get_drvdata(&spi->dev);
> +
> + cma3000_resume(data);
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops cma3000_spi_pm_ops = {
> + .suspend = cma3000_spi_suspend,
> + .resume = cma3000_spi_resume,
> +};
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(cma3000_spi_pm, cma3000_spi_suspend,
> + cma3000_spi_resume);
> +
> +static struct spi_driver cma3000_driver = {
> + .driver = {
> + .name = "cma3000_d01",
> + .bus = &spi_bus_type,
Drop the .bus line. The core code does this bit for you.
> + .owner = THIS_MODULE,
> + .pm = &cma3000_spi_pm,
> + },
> + .probe = cma3000_spi_probe,
> + .remove = __devexit_p(cma3000_spi_remove),
> +};
> +
> +static int __init cma3000_spi_init(void)
> +{
> + return spi_register_driver(&cma3000_driver);
> +}
> +
> +static void __exit cma3000_spi_exit(void)
> +{
> + spi_unregister_driver(&cma3000_driver);
> +}
> +
> +module_init(cma3000_spi_init);
> +module_exit(cma3000_spi_exit);
move module_init() directly below the function it registers.
> +
> +MODULE_DESCRIPTION("CMA3000-D0x Accelerometer SPI Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
> --
> 1.7.7
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver
2011-10-24 20:21 ` [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado
@ 2011-10-24 21:40 ` Grant Likely
2011-10-25 7:26 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-10-24 21:40 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Mon, Oct 24, 2011 at 10:21:15PM +0200, Ricardo Ribalda Delgado wrote:
> Add support for CMR3000 Tri-axis accelerometer. CMR3000 supports both
> I2C/SPI bus communication, currently the driver supports SPI
> communication, since I have no hardware to test the I2C communication.
How different is this driver from the cma3000? Is it a cut and paste job?
g.
>
> ---
>
> v4: Fixes suggested by Dmitry Torokhov
> -Do not release the input device until the irq has been released
>
> v3: Fixes suggested by Jonathan Cameron
> -Support DT
> -Cleaner spi read/write
>
> v2: Fixes suggested by Jonathan Cameron
> -Code Stype
> -Check pdata!=NULL
> -SPI align Cacheline
> -More clear based on
> -%s/set/write/
> -%s/accl/gyro/
> -remove READ/SET macros
>
> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
> ---
> drivers/input/misc/Kconfig | 24 ++
> drivers/input/misc/Makefile | 2 +
> drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
> drivers/input/misc/cmr3000_d0x.h | 45 ++++
> drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
> include/linux/input/cmr3000.h | 54 +++++
> 6 files changed, 695 insertions(+), 0 deletions(-)
> create mode 100644 drivers/input/misc/cmr3000_d0x.c
> create mode 100644 drivers/input/misc/cmr3000_d0x.h
> create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
> create mode 100644 include/linux/input/cmr3000.h
>
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index b9f2e93..7c56f94 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -524,6 +524,30 @@ config INPUT_CMA3000_SPI
> To compile this driver as a module, choose M here: the
> module will be called cma3000_d0x_spi.
>
> +config INPUT_CMR3000
> + tristate "VTI CMR3000 Tri-axis gyroscope"
> + help
> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
> + driver
> +
> + This driver currently only supports SPI interface to the
> + controller. Also select the SPI method.
> +
> + If unsure, say N
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cmr3000_d0x.
> +
> +config INPUT_CMR3000_SPI
> + tristate "Support SPI bus connection"
> + depends on INPUT_CMR3000 && SPI
> + help
> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
> + through SPI interface.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cmr3000_d0x_spi.
> +
> config INPUT_XEN_KBDDEV_FRONTEND
> tristate "Xen virtual keyboard and mouse support"
> depends on XEN_FBDEV_FRONTEND
> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> index 7305f6f..c7fe09a 100644
> --- a/drivers/input/misc/Makefile
> +++ b/drivers/input/misc/Makefile
> @@ -21,6 +21,8 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
> obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
> obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
> obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
> +obj-$(CONFIG_INPUT_CMR3000) += cmr3000_d0x.o
> +obj-$(CONFIG_INPUT_CMR3000_SPI) += cmr3000_d0x_spi.o
> obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
> obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
> diff --git a/drivers/input/misc/cmr3000_d0x.c b/drivers/input/misc/cmr3000_d0x.c
> new file mode 100644
> index 0000000..d046149
> --- /dev/null
> +++ b/drivers/input/misc/cmr3000_d0x.c
> @@ -0,0 +1,426 @@
> +/*
> + * VTI CMR3000_D0x Gyroscope driver
> + *
> + * Copyright (C) 2011 Qtechnology
> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
> + *
> + * Based on:
> + * drivers/input/misc/cma3000_d0x.c by: Hemanth V
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/input.h>
> +#include <linux/input/cmr3000.h>
> +#include <linux/of.h>
> +
> +#include "cmr3000_d0x.h"
> +
> +#define CMR3000_REV 0x21
> +
> +#define CMR3000_WHOAMI 0x00
> +#define CMR3000_REVID 0x01
> +#define CMR3000_CTRL 0x02
> +#define CMR3000_STATUS 0x03
> +#define CMR3000_X_LSB 0x0C
> +#define CMR3000_X_MSB 0x0D
> +#define CMR3000_Y_LSB 0x0E
> +#define CMR3000_Y_MSB 0x0F
> +#define CMR3000_Z_LSB 0x10
> +#define CMR3000_Z_MSB 0x11
> +#define CMR3000_I2C_ADDR 0x22
> +#define CMR3000_PDR 0x26
> +
> +#define CMR3000_IRQDIS (1 << 0)
> +#define CMR3000_MODEMASK (3 << 1)
> +#define CMR3000_BUSI2C (0 << 4)
> +#define CMR3000_BUSSPI (1 << 4)
> +#define CMR3000_INTLOW (1 << 6)
> +#define CMR3000_INTHIGH (0 << 6)
> +#define CMR3000_RST (1 << 7)
> +
> +#define CMRMODE_SHIFT 1
> +#define CMRIRQLEVEL_SHIFT 6
> +
> +#define CMR3000_STATUS_PERR (1 << 0)
> +#define CMR3000_STATUS_PORST (1 << 3)
> +
> +/* Settling time delay in ms */
> +#define CMR3000_SETDELAY 30
> +
> +/*
> + * Bit weights mult/div in dps for bit 0, other bits need
> + * multipy factor 2^n. 11th bit is the sign bit.
> + */
> +#define BIT_TO_DPS_MUL 3
> +#define BIT_TO_DPS_DIV 32
> +
> +static struct cmr3000_platform_data cmr3000_default_pdata = {
> + .irq_level = CMR3000_INTHIGH,
> + .mode = CMRMODE_MEAS80,
> + .fuzz_x = 1,
> + .fuzz_y = 1,
> + .fuzz_z = 1,
> + .irqflags = 0,
> +};
> +
> +struct cmr3000_gyro_data {
> + const struct cmr3000_bus_ops *bus_ops;
> + struct cmr3000_platform_data pdata;
> +
> + struct device *dev;
> + struct input_dev *input_dev;
> +
> + int irq_level;
> + u8 mode;
> +
> + int bit_to_mg;
> + int irq;
> +
> + struct mutex mutex;
> + bool opened;
> + bool suspended;
> +};
> +
> +static void decode_dps(struct cmr3000_gyro_data *data, int *datax,
> + int *datay, int *dataz)
> +{
> + /* Data in 2's complement, convert to dps */
> + *datax = (((s16) ((*datax) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> + *datay = (((s16) ((*datay) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> + *dataz = (((s16) ((*dataz) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> +}
> +
> +static irqreturn_t cmr3000_thread_irq(int irq, void *dev_id)
> +{
> + struct cmr3000_gyro_data *data = dev_id;
> + int datax, datay, dataz;
> + u8 mode, intr_status;
> +
> + intr_status = data->bus_ops->read(data->dev, CMR3000_STATUS,
> + "irq status");
> + intr_status = data->bus_ops->read(data->dev, CMR3000_CTRL,
> + "control mode");
> + if (intr_status < 0)
> + return IRQ_NONE;
> +
> + /* Interrupt not for this device */
> + if (intr_status & CMR3000_IRQDIS)
> + return IRQ_NONE;
> +
> + mode = (intr_status & CMR3000_MODEMASK) >> CMRMODE_SHIFT;
> + if ((mode != CMRMODE_MEAS80)
> + && (mode != CMRMODE_MEAS20))
> + return IRQ_NONE;
> +
> + datax = (data->bus_ops->read(data->dev, CMR3000_X_MSB, "X_MSB")) << 8;
> + datax |= data->bus_ops->read(data->dev, CMR3000_X_LSB, "X_LSB");
> + datay = (data->bus_ops->read(data->dev, CMR3000_Y_MSB, "Y_MSB")) << 8;
> + datay |= data->bus_ops->read(data->dev, CMR3000_Y_LSB, "Y_LSB");
> + dataz = (data->bus_ops->read(data->dev, CMR3000_Z_MSB, "Z_MSB")) << 8;
> + dataz |= data->bus_ops->read(data->dev, CMR3000_Z_LSB, "Z_LSB");
> +
> + /* Device closed */
> + if ((data->mode != CMRMODE_MEAS80)
> + && (data->mode != CMRMODE_MEAS20))
> + return IRQ_NONE;
> +
> + /* Decode register values to dps */
> + decode_dps(data, &datax, &datay, &dataz);
> +
> + input_report_abs(data->input_dev, ABS_X, datax);
> + input_report_abs(data->input_dev, ABS_Y, datay);
> + input_report_abs(data->input_dev, ABS_Z, dataz);
> + input_sync(data->input_dev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int cmr3000_poweron(struct cmr3000_gyro_data *data)
> +{
> + const struct cmr3000_platform_data *pdata = &data->pdata;
> + u8 ctrl;
> + int ret;
> +
> + ctrl = pdata->irq_level << CMRIRQLEVEL_SHIFT;
> + ctrl |= data->mode << CMRMODE_SHIFT;
> + ctrl |= data->bus_ops->ctrl_mod;
> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
> + "Mode setting");
> + if (ret < 0)
> + return -EIO;
> +
> + msleep(CMR3000_SETDELAY);
> +
> + return 0;
> +}
> +
> +static int cmr3000_poweroff(struct cmr3000_gyro_data *data)
> +{
> + int ret;
> + u8 ctrl = CMRMODE_POFF;
> +
> + ctrl |= data->bus_ops->ctrl_mod;
> + ctrl |= CMR3000_IRQDIS;
> +
> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
> + "Mode setting");
> + msleep(CMR3000_SETDELAY);
> +
> + return ret;
> +}
> +
> +static int cmr3000_reset(struct cmr3000_gyro_data *data)
> +{
> + int val;
> +
> + /* Reset chip */
> + data->bus_ops->write(data->dev, CMR3000_CTRL, CMR3000_RST, "Reset");
> + mdelay(2);
> +
> + /* Settling time delay */
> + val = data->bus_ops->read(data->dev, CMR3000_STATUS, "Status");
> + if (val < 0) {
> + dev_err(data->dev, "Reset failed\n");
> + return val;
> + }
> +
> + if (val & CMR3000_STATUS_PERR) {
> + dev_err(data->dev, "Parity Error\n");
> + return -EIO;
> + }
> +
> + return cmr3000_poweroff(data);
> +}
> +
> +static int cmr3000_open(struct input_dev *input_dev)
> +{
> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
> +
> + mutex_lock(&data->mutex);
> +
> + if (!data->suspended)
> + cmr3000_poweron(data);
> +
> + data->opened = true;
> +
> + mutex_unlock(&data->mutex);
> +
> + return 0;
> +}
> +
> +static void cmr3000_close(struct input_dev *input_dev)
> +{
> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
> +
> + mutex_lock(&data->mutex);
> +
> + if (!data->suspended)
> + cmr3000_poweroff(data);
> +
> + data->opened = false;
> +
> + mutex_unlock(&data->mutex);
> +}
> +
> +void cmr3000_suspend(struct cmr3000_gyro_data *data)
> +{
> + mutex_lock(&data->mutex);
> +
> + if (!data->suspended && data->opened)
> + cmr3000_poweroff(data);
> +
> + data->suspended = true;
> +
> + mutex_unlock(&data->mutex);
> +}
> +EXPORT_SYMBOL(cmr3000_suspend);
> +
> +void cmr3000_resume(struct cmr3000_gyro_data *data)
> +{
> + mutex_lock(&data->mutex);
> +
> + if (data->suspended && data->opened)
> + cmr3000_poweron(data);
> +
> + data->suspended = false;
> +
> + mutex_unlock(&data->mutex);
> +}
> +EXPORT_SYMBOL(cmr3000_resume);
> +
> +#ifdef CONFIG_OF
> +void cmr3000_get_pdata_of(struct device *dev, struct cmr3000_gyro_data *data)
> +{
> + const __be32 *property;
> + int len;
> +
> + property = of_get_property(dev->of_node, "vti,irq_level", &len);
> + if (property && len == sizeof(int))
> + data->pdata.irq_level = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,mode", &len);
> + if (property && len == sizeof(int))
> + data->pdata.mode = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_x = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_y = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
> + if (property && len == sizeof(int))
> + data->pdata.fuzz_z = be32_to_cpup(property);
> +
> + property = of_get_property(dev->of_node, "vti,irqflags", &len);
> + if (property && len == sizeof(int))
> + data->pdata.irqflags = be32_to_cpup(property);
> +
> + return;
> +}
> +#endif
> +
> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
> + const struct cmr3000_bus_ops *bops)
> +{
> + struct cmr3000_platform_data *pdata;
> + struct cmr3000_gyro_data *data;
> + struct input_dev *input_dev;
> + int rev;
> + int error;
> +
> + /* if no IRQ return error */
> + if (irq == 0) {
> + error = -EINVAL;
> + goto err_out;
> + }
> +
> + data = kzalloc(sizeof(struct cmr3000_gyro_data), GFP_KERNEL);
> + input_dev = input_allocate_device();
> + if (!data || !input_dev) {
> + error = -ENOMEM;
> + goto err_free_mem;
> + }
> +
> + /*Init platform data*/
> + if (dev->platform_data != NULL) {
> + memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
> + } else {
> + memcpy(&data->pdata, &cmr3000_default_pdata,
> + sizeof(data->pdata));
> + #ifdef CONFIG_OF
> + if (dev->of_node != NULL)
> + cmr3000_get_pdata_of(dev, data);
> + else
> + #endif
> + dev_info(dev, "platform data not found, using default\n");
> + }
> + pdata = &data->pdata;
> +
> + data->dev = dev;
> + data->input_dev = input_dev;
> + data->bus_ops = bops;
> + data->irq = irq;
> + mutex_init(&data->mutex);
> +
> + data->mode = pdata->mode;
> + if ((data->mode != CMRMODE_MEAS80)
> + && (data->mode != CMRMODE_MEAS20)) {
> + data->mode = CMRMODE_MEAS80;
> + dev_warn(dev, "Invalid mode specified, assuming 80Hz\n");
> + }
> +
> + data->irq_level = pdata->irq_level;
> + if ((data->irq_level != CMR3000_INTLOW)
> + && (data->irq_level != CMR3000_INTHIGH)) {
> + data->irq_level = CMR3000_INTHIGH;
> + dev_warn(data->dev,
> + "Invalid int level specified, assuming high\n");
> + }
> +
> + input_dev->name = "cmr3000-gyroscope";
> + input_dev->id.bustype = bops->bustype;
> + input_dev->open = cmr3000_open;
> + input_dev->close = cmr3000_close;
> +
> + __set_bit(EV_ABS, input_dev->evbit);
> +
> + input_set_abs_params(input_dev, ABS_X,
> + -CMRRANGE, CMRRANGE, pdata->fuzz_x, 0);
> + input_set_abs_params(input_dev, ABS_Y,
> + -CMRRANGE, CMRRANGE, pdata->fuzz_y, 0);
> + input_set_abs_params(input_dev, ABS_Z,
> + -CMRRANGE, CMRRANGE, pdata->fuzz_z, 0);
> +
> + input_set_drvdata(input_dev, data);
> +
> + error = cmr3000_reset(data);
> + if (error)
> + goto err_free_mem;
> +
> + rev = data->bus_ops->read(data->dev, CMR3000_REVID, "Revid");
> + if (rev < 0) {
> + error = rev;
> + goto err_free_mem;
> + }
> + if (rev != CMR3000_REV) {
> + error = -EINVAL;
> + pr_err("CMR3000 Gyroscope: Unknown Revision %x\n", rev);
> + goto err_free_mem;
> + }
> + pr_info("CMR3000 Gyroscope: Revision %x\n", rev);
> +
> + error = request_threaded_irq(irq, NULL, cmr3000_thread_irq,
> + pdata->irqflags | IRQF_ONESHOT,
> + "cmr3000_d0x", data);
> + if (error) {
> + dev_err(dev, "request_threaded_irq failed\n");
> + goto err_free_mem;
> + }
> +
> + error = input_register_device(data->input_dev);
> + if (error) {
> + dev_err(dev, "Unable to register input device\n");
> + goto err_free_irq;
> + }
> +
> + return data;
> +
> +err_free_irq:
> + free_irq(irq, data);
> +err_free_mem:
> + input_free_device(input_dev);
> + kfree(data);
> +err_out:
> + return ERR_PTR(error);
> +}
> +EXPORT_SYMBOL(cmr3000_init);
> +
> +void cmr3000_exit(struct cmr3000_gyro_data *data)
> +{
> + free_irq(data->irq, data);
> + input_unregister_device(data->input_dev);
> + kfree(data);
> +}
> +EXPORT_SYMBOL(cmr3000_exit);
> +
> +MODULE_DESCRIPTION("CMR3000-D0x Gyroscope Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
> diff --git a/drivers/input/misc/cmr3000_d0x.h b/drivers/input/misc/cmr3000_d0x.h
> new file mode 100644
> index 0000000..3d0984a
> --- /dev/null
> +++ b/drivers/input/misc/cmr3000_d0x.h
> @@ -0,0 +1,45 @@
> +/*
> + * VTI CMR3000_D0x Gyroscpe driver
> + *
> + * Copyright (C) 2011 Qtechnology
> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
> + *
> + * Based on:
> + * drivers/input/misc/cma3000_d0x.h by Hemanth V
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _INPUT_CMR3000_H
> +#define _INPUT_CMR3000_H
> +
> +#include <linux/types.h>
> +#include <linux/input.h>
> +
> +struct device;
> +struct cmr3000_gyro_data;
> +
> +struct cmr3000_bus_ops {
> + u16 bustype;
> + u8 ctrl_mod;
> + int (*read) (struct device *, u8, char *);
> + int (*write) (struct device *, u8, u8, char *);
> +};
> +
> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
> + const struct cmr3000_bus_ops *bops);
> +void cmr3000_exit(struct cmr3000_gyro_data *);
> +void cmr3000_suspend(struct cmr3000_gyro_data *);
> +void cmr3000_resume(struct cmr3000_gyro_data *);
> +
> +#endif
> diff --git a/drivers/input/misc/cmr3000_d0x_spi.c b/drivers/input/misc/cmr3000_d0x_spi.c
> new file mode 100644
> index 0000000..7f27fa3
> --- /dev/null
> +++ b/drivers/input/misc/cmr3000_d0x_spi.c
> @@ -0,0 +1,144 @@
> +/*
> + * Implements SPI interface for VTI CMR300_D0x Accelerometer driver
> + *
> + * Copyright (C) 2011 Qtechnology
> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com>
> + * Based on:
> + * drivers/input/misc/cma3000_d0x_i2c.c by Hemanth V
> + * drivers/input/mis/adxl34x-spi.c by Michael Hennerich
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +#include <linux/input/cmr3000.h>
> +#include "cmr3000_d0x.h"
> +
> +static int cmr3000_spi_write(struct device *dev, u8 reg, u8 val, char *msg)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + int ret;
> + u8 tmp[2];
> +
> + tmp[0] = (reg << 2) | 2;
> + tmp[1] = val;
> +
> + ret = spi_write_then_read(spi, tmp, sizeof(tmp), NULL, 0);
> + if (ret < 0) {
> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
> + return ret;
> + }
> + return 0;
> +}
> +
> +static int cmr3000_spi_read(struct device *dev, u8 reg, char *msg)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + int ret;
> +
> + ret = spi_w8r8(spi, reg << 2);
> + if (ret < 0)
> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
> +
> + return ret;
> +}
> +
> +static const struct cmr3000_bus_ops cmr3000_spi_bops = {
> + .bustype = BUS_SPI,
> +#define CMR3000_BUSSPI (1 << 4)
> + .ctrl_mod = CMR3000_BUSSPI,
> + .read = cmr3000_spi_read,
> + .write = cmr3000_spi_write,
> +};
> +
> +static int __devinit cmr3000_spi_probe(struct spi_device *spi)
> +{
> + struct cmr3000_gyro_data *data;
> +
> + data = cmr3000_init(&spi->dev, spi->irq, &cmr3000_spi_bops);
> + if (IS_ERR(data))
> + return PTR_ERR(data);
> +
> + spi_set_drvdata(spi, data);
> +
> + return 0;
> +}
> +
> +static int __devexit cmr3000_spi_remove(struct spi_device *spi)
> +{
> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
> +
> + cmr3000_exit(data);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int cmr3000_spi_suspend(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
> +
> + cmr3000_suspend(data);
> +
> + return 0;
> +}
> +
> +static int cmr3000_spi_resume(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
> +
> + cmr3000_resume(data);
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops cmr3000_spi_pm_ops = {
> + .suspend = cmr3000_spi_suspend,
> + .resume = cmr3000_spi_resume,
> +};
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(cmr3000_spi_pm, cmr3000_spi_suspend,
> + cmr3000_spi_resume);
> +
> +static struct spi_driver cmr3000_driver = {
> + .driver = {
> + .name = "cmr3000_d01",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + .pm = &cmr3000_spi_pm,
> + },
> + .probe = cmr3000_spi_probe,
> + .remove = __devexit_p(cmr3000_spi_remove),
> +};
> +
> +static int __init cmr3000_spi_init(void)
> +{
> + return spi_register_driver(&cmr3000_driver);
> +}
> +
> +static void __exit cmr3000_spi_exit(void)
> +{
> + spi_unregister_driver(&cmr3000_driver);
> +}
> +
> +module_init(cmr3000_spi_init);
> +module_exit(cmr3000_spi_exit);
> +
> +MODULE_DESCRIPTION("CMR3000-D0x Gyroscope SPI Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
> diff --git a/include/linux/input/cmr3000.h b/include/linux/input/cmr3000.h
> new file mode 100644
> index 0000000..dfcf9e3
> --- /dev/null
> +++ b/include/linux/input/cmr3000.h
> @@ -0,0 +1,54 @@
> +/*
> + * VTI CMR3000_Dxx Gyroscope driver
> + *
> + * Copyright (C) 2011 Qtechnology
> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
> + *
> + * Based on:
> + * include/linux/input/cma3000.h by Hemanth V
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _LINUX_CMR3000_H
> +#define _LINUX_CMR3000_H
> +
> +#define CMRMODE_DEFAULT 0
> +#define CMRMODE_STANDBY 1
> +#define CMRMODE_MEAS20 2
> +#define CMRMODE_MEAS80 3
> +#define CMRMODE_POFF 0
> +
> +#define CMRIRQLEVEL_LOW 1
> +#define CMRIRQLEVEL_HIGH 0
> +
> +#define CMRRANGE 3072
> +
> +/**
> + * struct cmr3000_platform_data - CMR3000 Platform data
> + * @fuzz_x: Noise on X Axis
> + * @fuzz_y: Noise on Y Axis
> + * @fuzz_z: Noise on Z Axis
> + * @mode: Operating mode
> + * @irq_level: Irq level
> + */
> +struct cmr3000_platform_data {
> + int fuzz_x;
> + int fuzz_y;
> + int fuzz_z;
> + uint8_t irq_level;
> + uint8_t mode;
> + unsigned long irqflags;
> +};
> +
> +#endif
> --
> 1.7.7
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-24 21:36 ` [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support Grant Likely
@ 2011-10-25 7:24 ` Ricardo Ribalda Delgado
2011-10-25 8:29 ` Grant Likely
2011-10-25 8:32 ` Jonathan Cameron
0 siblings, 2 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-25 7:24 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Hello Grant
Thanks for your comments. I am fixing the --- problem in all the patches.
>
> Mark Brown had posted a generic indirect register read/write library
> that I believe is getting merged. Maybe this driver should be using
> it?
It is not on linux-next, and also it cannot be used directly, in order
to read you have to do set reg= (reg << 2) | 2; And AFAIK it is not
supported by the regmap
>
> Drop the .bus line. The core code does this bit for you.
Done
>> +module_init(cma3000_spi_init);
>> +module_exit(cma3000_spi_exit);
>
> move module_init() directly below the function it registers.
Also done, but I believe the other is more elegant :)
>
>> +
>> +MODULE_DESCRIPTION("CMA3000-D0x Accelerometer SPI Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
>> --
>> 1.7.7
>>
>
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver
2011-10-24 21:40 ` Grant Likely
@ 2011-10-25 7:26 ` Ricardo Ribalda Delgado
2011-10-25 8:28 ` Grant Likely
0 siblings, 1 reply; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-25 7:26 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Hello Grant
It is similar to the crm, because they came from the same
manufacturer and they share some commands, but that is all.
the crm is a gyroscope and the cma is an accelerometer. I tried to put
both drivers together and the result was a bit too messy, I think it
is easier to understand as two separate drivers, but if you believe
they have to live together and help me making it more understandable,
I have to problem in coding it.
Regards!
On Mon, Oct 24, 2011 at 23:40, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Mon, Oct 24, 2011 at 10:21:15PM +0200, Ricardo Ribalda Delgado wrote:
>> Add support for CMR3000 Tri-axis accelerometer. CMR3000 supports both
>> I2C/SPI bus communication, currently the driver supports SPI
>> communication, since I have no hardware to test the I2C communication.
>
> How different is this driver from the cma3000? Is it a cut and paste job?
>
> g.
>
>>
>> ---
>>
>> v4: Fixes suggested by Dmitry Torokhov
>> -Do not release the input device until the irq has been released
>>
>> v3: Fixes suggested by Jonathan Cameron
>> -Support DT
>> -Cleaner spi read/write
>>
>> v2: Fixes suggested by Jonathan Cameron
>> -Code Stype
>> -Check pdata!=NULL
>> -SPI align Cacheline
>> -More clear based on
>> -%s/set/write/
>> -%s/accl/gyro/
>> -remove READ/SET macros
>>
>> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
>> ---
>> drivers/input/misc/Kconfig | 24 ++
>> drivers/input/misc/Makefile | 2 +
>> drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
>> drivers/input/misc/cmr3000_d0x.h | 45 ++++
>> drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
>> include/linux/input/cmr3000.h | 54 +++++
>> 6 files changed, 695 insertions(+), 0 deletions(-)
>> create mode 100644 drivers/input/misc/cmr3000_d0x.c
>> create mode 100644 drivers/input/misc/cmr3000_d0x.h
>> create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
>> create mode 100644 include/linux/input/cmr3000.h
>>
>> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
>> index b9f2e93..7c56f94 100644
>> --- a/drivers/input/misc/Kconfig
>> +++ b/drivers/input/misc/Kconfig
>> @@ -524,6 +524,30 @@ config INPUT_CMA3000_SPI
>> To compile this driver as a module, choose M here: the
>> module will be called cma3000_d0x_spi.
>>
>> +config INPUT_CMR3000
>> + tristate "VTI CMR3000 Tri-axis gyroscope"
>> + help
>> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
>> + driver
>> +
>> + This driver currently only supports SPI interface to the
>> + controller. Also select the SPI method.
>> +
>> + If unsure, say N
>> +
>> + To compile this driver as a module, choose M here: the
>> + module will be called cmr3000_d0x.
>> +
>> +config INPUT_CMR3000_SPI
>> + tristate "Support SPI bus connection"
>> + depends on INPUT_CMR3000 && SPI
>> + help
>> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
>> + through SPI interface.
>> +
>> + To compile this driver as a module, choose M here: the
>> + module will be called cmr3000_d0x_spi.
>> +
>> config INPUT_XEN_KBDDEV_FRONTEND
>> tristate "Xen virtual keyboard and mouse support"
>> depends on XEN_FBDEV_FRONTEND
>> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
>> index 7305f6f..c7fe09a 100644
>> --- a/drivers/input/misc/Makefile
>> +++ b/drivers/input/misc/Makefile
>> @@ -21,6 +21,8 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
>> obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
>> obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
>> obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
>> +obj-$(CONFIG_INPUT_CMR3000) += cmr3000_d0x.o
>> +obj-$(CONFIG_INPUT_CMR3000_SPI) += cmr3000_d0x_spi.o
>> obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
>> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
>> obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
>> diff --git a/drivers/input/misc/cmr3000_d0x.c b/drivers/input/misc/cmr3000_d0x.c
>> new file mode 100644
>> index 0000000..d046149
>> --- /dev/null
>> +++ b/drivers/input/misc/cmr3000_d0x.c
>> @@ -0,0 +1,426 @@
>> +/*
>> + * VTI CMR3000_D0x Gyroscope driver
>> + *
>> + * Copyright (C) 2011 Qtechnology
>> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
>> + *
>> + * Based on:
>> + * drivers/input/misc/cma3000_d0x.c by: Hemanth V
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/types.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/delay.h>
>> +#include <linux/slab.h>
>> +#include <linux/input.h>
>> +#include <linux/input/cmr3000.h>
>> +#include <linux/of.h>
>> +
>> +#include "cmr3000_d0x.h"
>> +
>> +#define CMR3000_REV 0x21
>> +
>> +#define CMR3000_WHOAMI 0x00
>> +#define CMR3000_REVID 0x01
>> +#define CMR3000_CTRL 0x02
>> +#define CMR3000_STATUS 0x03
>> +#define CMR3000_X_LSB 0x0C
>> +#define CMR3000_X_MSB 0x0D
>> +#define CMR3000_Y_LSB 0x0E
>> +#define CMR3000_Y_MSB 0x0F
>> +#define CMR3000_Z_LSB 0x10
>> +#define CMR3000_Z_MSB 0x11
>> +#define CMR3000_I2C_ADDR 0x22
>> +#define CMR3000_PDR 0x26
>> +
>> +#define CMR3000_IRQDIS (1 << 0)
>> +#define CMR3000_MODEMASK (3 << 1)
>> +#define CMR3000_BUSI2C (0 << 4)
>> +#define CMR3000_BUSSPI (1 << 4)
>> +#define CMR3000_INTLOW (1 << 6)
>> +#define CMR3000_INTHIGH (0 << 6)
>> +#define CMR3000_RST (1 << 7)
>> +
>> +#define CMRMODE_SHIFT 1
>> +#define CMRIRQLEVEL_SHIFT 6
>> +
>> +#define CMR3000_STATUS_PERR (1 << 0)
>> +#define CMR3000_STATUS_PORST (1 << 3)
>> +
>> +/* Settling time delay in ms */
>> +#define CMR3000_SETDELAY 30
>> +
>> +/*
>> + * Bit weights mult/div in dps for bit 0, other bits need
>> + * multipy factor 2^n. 11th bit is the sign bit.
>> + */
>> +#define BIT_TO_DPS_MUL 3
>> +#define BIT_TO_DPS_DIV 32
>> +
>> +static struct cmr3000_platform_data cmr3000_default_pdata = {
>> + .irq_level = CMR3000_INTHIGH,
>> + .mode = CMRMODE_MEAS80,
>> + .fuzz_x = 1,
>> + .fuzz_y = 1,
>> + .fuzz_z = 1,
>> + .irqflags = 0,
>> +};
>> +
>> +struct cmr3000_gyro_data {
>> + const struct cmr3000_bus_ops *bus_ops;
>> + struct cmr3000_platform_data pdata;
>> +
>> + struct device *dev;
>> + struct input_dev *input_dev;
>> +
>> + int irq_level;
>> + u8 mode;
>> +
>> + int bit_to_mg;
>> + int irq;
>> +
>> + struct mutex mutex;
>> + bool opened;
>> + bool suspended;
>> +};
>> +
>> +static void decode_dps(struct cmr3000_gyro_data *data, int *datax,
>> + int *datay, int *dataz)
>> +{
>> + /* Data in 2's complement, convert to dps */
>> + *datax = (((s16) ((*datax) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> + *datay = (((s16) ((*datay) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> + *dataz = (((s16) ((*dataz) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> +}
>> +
>> +static irqreturn_t cmr3000_thread_irq(int irq, void *dev_id)
>> +{
>> + struct cmr3000_gyro_data *data = dev_id;
>> + int datax, datay, dataz;
>> + u8 mode, intr_status;
>> +
>> + intr_status = data->bus_ops->read(data->dev, CMR3000_STATUS,
>> + "irq status");
>> + intr_status = data->bus_ops->read(data->dev, CMR3000_CTRL,
>> + "control mode");
>> + if (intr_status < 0)
>> + return IRQ_NONE;
>> +
>> + /* Interrupt not for this device */
>> + if (intr_status & CMR3000_IRQDIS)
>> + return IRQ_NONE;
>> +
>> + mode = (intr_status & CMR3000_MODEMASK) >> CMRMODE_SHIFT;
>> + if ((mode != CMRMODE_MEAS80)
>> + && (mode != CMRMODE_MEAS20))
>> + return IRQ_NONE;
>> +
>> + datax = (data->bus_ops->read(data->dev, CMR3000_X_MSB, "X_MSB")) << 8;
>> + datax |= data->bus_ops->read(data->dev, CMR3000_X_LSB, "X_LSB");
>> + datay = (data->bus_ops->read(data->dev, CMR3000_Y_MSB, "Y_MSB")) << 8;
>> + datay |= data->bus_ops->read(data->dev, CMR3000_Y_LSB, "Y_LSB");
>> + dataz = (data->bus_ops->read(data->dev, CMR3000_Z_MSB, "Z_MSB")) << 8;
>> + dataz |= data->bus_ops->read(data->dev, CMR3000_Z_LSB, "Z_LSB");
>> +
>> + /* Device closed */
>> + if ((data->mode != CMRMODE_MEAS80)
>> + && (data->mode != CMRMODE_MEAS20))
>> + return IRQ_NONE;
>> +
>> + /* Decode register values to dps */
>> + decode_dps(data, &datax, &datay, &dataz);
>> +
>> + input_report_abs(data->input_dev, ABS_X, datax);
>> + input_report_abs(data->input_dev, ABS_Y, datay);
>> + input_report_abs(data->input_dev, ABS_Z, dataz);
>> + input_sync(data->input_dev);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int cmr3000_poweron(struct cmr3000_gyro_data *data)
>> +{
>> + const struct cmr3000_platform_data *pdata = &data->pdata;
>> + u8 ctrl;
>> + int ret;
>> +
>> + ctrl = pdata->irq_level << CMRIRQLEVEL_SHIFT;
>> + ctrl |= data->mode << CMRMODE_SHIFT;
>> + ctrl |= data->bus_ops->ctrl_mod;
>> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
>> + "Mode setting");
>> + if (ret < 0)
>> + return -EIO;
>> +
>> + msleep(CMR3000_SETDELAY);
>> +
>> + return 0;
>> +}
>> +
>> +static int cmr3000_poweroff(struct cmr3000_gyro_data *data)
>> +{
>> + int ret;
>> + u8 ctrl = CMRMODE_POFF;
>> +
>> + ctrl |= data->bus_ops->ctrl_mod;
>> + ctrl |= CMR3000_IRQDIS;
>> +
>> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
>> + "Mode setting");
>> + msleep(CMR3000_SETDELAY);
>> +
>> + return ret;
>> +}
>> +
>> +static int cmr3000_reset(struct cmr3000_gyro_data *data)
>> +{
>> + int val;
>> +
>> + /* Reset chip */
>> + data->bus_ops->write(data->dev, CMR3000_CTRL, CMR3000_RST, "Reset");
>> + mdelay(2);
>> +
>> + /* Settling time delay */
>> + val = data->bus_ops->read(data->dev, CMR3000_STATUS, "Status");
>> + if (val < 0) {
>> + dev_err(data->dev, "Reset failed\n");
>> + return val;
>> + }
>> +
>> + if (val & CMR3000_STATUS_PERR) {
>> + dev_err(data->dev, "Parity Error\n");
>> + return -EIO;
>> + }
>> +
>> + return cmr3000_poweroff(data);
>> +}
>> +
>> +static int cmr3000_open(struct input_dev *input_dev)
>> +{
>> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
>> +
>> + mutex_lock(&data->mutex);
>> +
>> + if (!data->suspended)
>> + cmr3000_poweron(data);
>> +
>> + data->opened = true;
>> +
>> + mutex_unlock(&data->mutex);
>> +
>> + return 0;
>> +}
>> +
>> +static void cmr3000_close(struct input_dev *input_dev)
>> +{
>> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
>> +
>> + mutex_lock(&data->mutex);
>> +
>> + if (!data->suspended)
>> + cmr3000_poweroff(data);
>> +
>> + data->opened = false;
>> +
>> + mutex_unlock(&data->mutex);
>> +}
>> +
>> +void cmr3000_suspend(struct cmr3000_gyro_data *data)
>> +{
>> + mutex_lock(&data->mutex);
>> +
>> + if (!data->suspended && data->opened)
>> + cmr3000_poweroff(data);
>> +
>> + data->suspended = true;
>> +
>> + mutex_unlock(&data->mutex);
>> +}
>> +EXPORT_SYMBOL(cmr3000_suspend);
>> +
>> +void cmr3000_resume(struct cmr3000_gyro_data *data)
>> +{
>> + mutex_lock(&data->mutex);
>> +
>> + if (data->suspended && data->opened)
>> + cmr3000_poweron(data);
>> +
>> + data->suspended = false;
>> +
>> + mutex_unlock(&data->mutex);
>> +}
>> +EXPORT_SYMBOL(cmr3000_resume);
>> +
>> +#ifdef CONFIG_OF
>> +void cmr3000_get_pdata_of(struct device *dev, struct cmr3000_gyro_data *data)
>> +{
>> + const __be32 *property;
>> + int len;
>> +
>> + property = of_get_property(dev->of_node, "vti,irq_level", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.irq_level = be32_to_cpup(property);
>> +
>> + property = of_get_property(dev->of_node, "vti,mode", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.mode = be32_to_cpup(property);
>> +
>> + property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.fuzz_x = be32_to_cpup(property);
>> +
>> + property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.fuzz_y = be32_to_cpup(property);
>> +
>> + property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.fuzz_z = be32_to_cpup(property);
>> +
>> + property = of_get_property(dev->of_node, "vti,irqflags", &len);
>> + if (property && len == sizeof(int))
>> + data->pdata.irqflags = be32_to_cpup(property);
>> +
>> + return;
>> +}
>> +#endif
>> +
>> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
>> + const struct cmr3000_bus_ops *bops)
>> +{
>> + struct cmr3000_platform_data *pdata;
>> + struct cmr3000_gyro_data *data;
>> + struct input_dev *input_dev;
>> + int rev;
>> + int error;
>> +
>> + /* if no IRQ return error */
>> + if (irq == 0) {
>> + error = -EINVAL;
>> + goto err_out;
>> + }
>> +
>> + data = kzalloc(sizeof(struct cmr3000_gyro_data), GFP_KERNEL);
>> + input_dev = input_allocate_device();
>> + if (!data || !input_dev) {
>> + error = -ENOMEM;
>> + goto err_free_mem;
>> + }
>> +
>> + /*Init platform data*/
>> + if (dev->platform_data != NULL) {
>> + memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
>> + } else {
>> + memcpy(&data->pdata, &cmr3000_default_pdata,
>> + sizeof(data->pdata));
>> + #ifdef CONFIG_OF
>> + if (dev->of_node != NULL)
>> + cmr3000_get_pdata_of(dev, data);
>> + else
>> + #endif
>> + dev_info(dev, "platform data not found, using default\n");
>> + }
>> + pdata = &data->pdata;
>> +
>> + data->dev = dev;
>> + data->input_dev = input_dev;
>> + data->bus_ops = bops;
>> + data->irq = irq;
>> + mutex_init(&data->mutex);
>> +
>> + data->mode = pdata->mode;
>> + if ((data->mode != CMRMODE_MEAS80)
>> + && (data->mode != CMRMODE_MEAS20)) {
>> + data->mode = CMRMODE_MEAS80;
>> + dev_warn(dev, "Invalid mode specified, assuming 80Hz\n");
>> + }
>> +
>> + data->irq_level = pdata->irq_level;
>> + if ((data->irq_level != CMR3000_INTLOW)
>> + && (data->irq_level != CMR3000_INTHIGH)) {
>> + data->irq_level = CMR3000_INTHIGH;
>> + dev_warn(data->dev,
>> + "Invalid int level specified, assuming high\n");
>> + }
>> +
>> + input_dev->name = "cmr3000-gyroscope";
>> + input_dev->id.bustype = bops->bustype;
>> + input_dev->open = cmr3000_open;
>> + input_dev->close = cmr3000_close;
>> +
>> + __set_bit(EV_ABS, input_dev->evbit);
>> +
>> + input_set_abs_params(input_dev, ABS_X,
>> + -CMRRANGE, CMRRANGE, pdata->fuzz_x, 0);
>> + input_set_abs_params(input_dev, ABS_Y,
>> + -CMRRANGE, CMRRANGE, pdata->fuzz_y, 0);
>> + input_set_abs_params(input_dev, ABS_Z,
>> + -CMRRANGE, CMRRANGE, pdata->fuzz_z, 0);
>> +
>> + input_set_drvdata(input_dev, data);
>> +
>> + error = cmr3000_reset(data);
>> + if (error)
>> + goto err_free_mem;
>> +
>> + rev = data->bus_ops->read(data->dev, CMR3000_REVID, "Revid");
>> + if (rev < 0) {
>> + error = rev;
>> + goto err_free_mem;
>> + }
>> + if (rev != CMR3000_REV) {
>> + error = -EINVAL;
>> + pr_err("CMR3000 Gyroscope: Unknown Revision %x\n", rev);
>> + goto err_free_mem;
>> + }
>> + pr_info("CMR3000 Gyroscope: Revision %x\n", rev);
>> +
>> + error = request_threaded_irq(irq, NULL, cmr3000_thread_irq,
>> + pdata->irqflags | IRQF_ONESHOT,
>> + "cmr3000_d0x", data);
>> + if (error) {
>> + dev_err(dev, "request_threaded_irq failed\n");
>> + goto err_free_mem;
>> + }
>> +
>> + error = input_register_device(data->input_dev);
>> + if (error) {
>> + dev_err(dev, "Unable to register input device\n");
>> + goto err_free_irq;
>> + }
>> +
>> + return data;
>> +
>> +err_free_irq:
>> + free_irq(irq, data);
>> +err_free_mem:
>> + input_free_device(input_dev);
>> + kfree(data);
>> +err_out:
>> + return ERR_PTR(error);
>> +}
>> +EXPORT_SYMBOL(cmr3000_init);
>> +
>> +void cmr3000_exit(struct cmr3000_gyro_data *data)
>> +{
>> + free_irq(data->irq, data);
>> + input_unregister_device(data->input_dev);
>> + kfree(data);
>> +}
>> +EXPORT_SYMBOL(cmr3000_exit);
>> +
>> +MODULE_DESCRIPTION("CMR3000-D0x Gyroscope Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
>> diff --git a/drivers/input/misc/cmr3000_d0x.h b/drivers/input/misc/cmr3000_d0x.h
>> new file mode 100644
>> index 0000000..3d0984a
>> --- /dev/null
>> +++ b/drivers/input/misc/cmr3000_d0x.h
>> @@ -0,0 +1,45 @@
>> +/*
>> + * VTI CMR3000_D0x Gyroscpe driver
>> + *
>> + * Copyright (C) 2011 Qtechnology
>> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
>> + *
>> + * Based on:
>> + * drivers/input/misc/cma3000_d0x.h by Hemanth V
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef _INPUT_CMR3000_H
>> +#define _INPUT_CMR3000_H
>> +
>> +#include <linux/types.h>
>> +#include <linux/input.h>
>> +
>> +struct device;
>> +struct cmr3000_gyro_data;
>> +
>> +struct cmr3000_bus_ops {
>> + u16 bustype;
>> + u8 ctrl_mod;
>> + int (*read) (struct device *, u8, char *);
>> + int (*write) (struct device *, u8, u8, char *);
>> +};
>> +
>> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
>> + const struct cmr3000_bus_ops *bops);
>> +void cmr3000_exit(struct cmr3000_gyro_data *);
>> +void cmr3000_suspend(struct cmr3000_gyro_data *);
>> +void cmr3000_resume(struct cmr3000_gyro_data *);
>> +
>> +#endif
>> diff --git a/drivers/input/misc/cmr3000_d0x_spi.c b/drivers/input/misc/cmr3000_d0x_spi.c
>> new file mode 100644
>> index 0000000..7f27fa3
>> --- /dev/null
>> +++ b/drivers/input/misc/cmr3000_d0x_spi.c
>> @@ -0,0 +1,144 @@
>> +/*
>> + * Implements SPI interface for VTI CMR300_D0x Accelerometer driver
>> + *
>> + * Copyright (C) 2011 Qtechnology
>> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com>
>> + * Based on:
>> + * drivers/input/misc/cma3000_d0x_i2c.c by Hemanth V
>> + * drivers/input/mis/adxl34x-spi.c by Michael Hennerich
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/module.h>
>> +#include <linux/spi/spi.h>
>> +#include <linux/input/cmr3000.h>
>> +#include "cmr3000_d0x.h"
>> +
>> +static int cmr3000_spi_write(struct device *dev, u8 reg, u8 val, char *msg)
>> +{
>> + struct spi_device *spi = to_spi_device(dev);
>> + int ret;
>> + u8 tmp[2];
>> +
>> + tmp[0] = (reg << 2) | 2;
>> + tmp[1] = val;
>> +
>> + ret = spi_write_then_read(spi, tmp, sizeof(tmp), NULL, 0);
>> + if (ret < 0) {
>> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
>> + return ret;
>> + }
>> + return 0;
>> +}
>> +
>> +static int cmr3000_spi_read(struct device *dev, u8 reg, char *msg)
>> +{
>> + struct spi_device *spi = to_spi_device(dev);
>> + int ret;
>> +
>> + ret = spi_w8r8(spi, reg << 2);
>> + if (ret < 0)
>> + dev_err(dev, "%s failed (%s, %d)\n", __func__, msg, ret);
>> +
>> + return ret;
>> +}
>> +
>> +static const struct cmr3000_bus_ops cmr3000_spi_bops = {
>> + .bustype = BUS_SPI,
>> +#define CMR3000_BUSSPI (1 << 4)
>> + .ctrl_mod = CMR3000_BUSSPI,
>> + .read = cmr3000_spi_read,
>> + .write = cmr3000_spi_write,
>> +};
>> +
>> +static int __devinit cmr3000_spi_probe(struct spi_device *spi)
>> +{
>> + struct cmr3000_gyro_data *data;
>> +
>> + data = cmr3000_init(&spi->dev, spi->irq, &cmr3000_spi_bops);
>> + if (IS_ERR(data))
>> + return PTR_ERR(data);
>> +
>> + spi_set_drvdata(spi, data);
>> +
>> + return 0;
>> +}
>> +
>> +static int __devexit cmr3000_spi_remove(struct spi_device *spi)
>> +{
>> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
>> +
>> + cmr3000_exit(data);
>> +
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM
>> +static int cmr3000_spi_suspend(struct device *dev)
>> +{
>> + struct spi_device *spi = to_spi_device(dev);
>> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
>> +
>> + cmr3000_suspend(data);
>> +
>> + return 0;
>> +}
>> +
>> +static int cmr3000_spi_resume(struct device *dev)
>> +{
>> + struct spi_device *spi = to_spi_device(dev);
>> + struct cmr3000_gyro_data *data = dev_get_drvdata(&spi->dev);
>> +
>> + cmr3000_resume(data);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct dev_pm_ops cmr3000_spi_pm_ops = {
>> + .suspend = cmr3000_spi_suspend,
>> + .resume = cmr3000_spi_resume,
>> +};
>> +#endif
>> +
>> +static SIMPLE_DEV_PM_OPS(cmr3000_spi_pm, cmr3000_spi_suspend,
>> + cmr3000_spi_resume);
>> +
>> +static struct spi_driver cmr3000_driver = {
>> + .driver = {
>> + .name = "cmr3000_d01",
>> + .bus = &spi_bus_type,
>> + .owner = THIS_MODULE,
>> + .pm = &cmr3000_spi_pm,
>> + },
>> + .probe = cmr3000_spi_probe,
>> + .remove = __devexit_p(cmr3000_spi_remove),
>> +};
>> +
>> +static int __init cmr3000_spi_init(void)
>> +{
>> + return spi_register_driver(&cmr3000_driver);
>> +}
>> +
>> +static void __exit cmr3000_spi_exit(void)
>> +{
>> + spi_unregister_driver(&cmr3000_driver);
>> +}
>> +
>> +module_init(cmr3000_spi_init);
>> +module_exit(cmr3000_spi_exit);
>> +
>> +MODULE_DESCRIPTION("CMR3000-D0x Gyroscope SPI Driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
>> diff --git a/include/linux/input/cmr3000.h b/include/linux/input/cmr3000.h
>> new file mode 100644
>> index 0000000..dfcf9e3
>> --- /dev/null
>> +++ b/include/linux/input/cmr3000.h
>> @@ -0,0 +1,54 @@
>> +/*
>> + * VTI CMR3000_Dxx Gyroscope driver
>> + *
>> + * Copyright (C) 2011 Qtechnology
>> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
>> + *
>> + * Based on:
>> + * include/linux/input/cma3000.h by Hemanth V
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef _LINUX_CMR3000_H
>> +#define _LINUX_CMR3000_H
>> +
>> +#define CMRMODE_DEFAULT 0
>> +#define CMRMODE_STANDBY 1
>> +#define CMRMODE_MEAS20 2
>> +#define CMRMODE_MEAS80 3
>> +#define CMRMODE_POFF 0
>> +
>> +#define CMRIRQLEVEL_LOW 1
>> +#define CMRIRQLEVEL_HIGH 0
>> +
>> +#define CMRRANGE 3072
>> +
>> +/**
>> + * struct cmr3000_platform_data - CMR3000 Platform data
>> + * @fuzz_x: Noise on X Axis
>> + * @fuzz_y: Noise on Y Axis
>> + * @fuzz_z: Noise on Z Axis
>> + * @mode: Operating mode
>> + * @irq_level: Irq level
>> + */
>> +struct cmr3000_platform_data {
>> + int fuzz_x;
>> + int fuzz_y;
>> + int fuzz_z;
>> + uint8_t irq_level;
>> + uint8_t mode;
>> + unsigned long irqflags;
>> +};
>> +
>> +#endif
>> --
>> 1.7.7
>>
>
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
2011-10-24 21:31 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Grant Likely
@ 2011-10-25 7:38 ` Ricardo Ribalda Delgado
2011-10-25 7:46 ` Grant Likely
0 siblings, 1 reply; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-10-25 7:38 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Hello Grant
>> ---
>
> Drop this line, git cuts everything below a '---' line from the commit text.
Done, thanks
>
> This binding needs documentation before it can be merged.
Documentation/input/cma3000_d0x.txt is the right place ?
>
> No of_device_id match table to match against compatible values?
I think it is not needed, the device will be matched against the
driver cma3000_d0x_spi.c and AFAIK on the spi/i2c devices you dont
need the device_id match. But you know much more about this :). Can
you point me to a example where a spi driver uses of_device-id match.
>
>> +
>> struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
>> const struct cma3000_bus_ops *bops)
>> {
>> - const struct cma3000_platform_data *pdata = dev->platform_data;
>> + struct cma3000_platform_data *pdata;
>> struct cma3000_accl_data *data;
>> struct input_dev *input_dev;
>> int rev;
>> int error;
>>
>> - if (!pdata) {
>> - dev_err(dev, "platform data not found\n");
>> - error = -EINVAL;
>> - goto err_out;
>> - }
>> -
>> -
>> /* if no IRQ return error */
>> if (irq == 0) {
>> error = -EINVAL;
>> @@ -309,10 +357,26 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
>> goto err_free_mem;
>> }
>>
>> + /*Init platform data*/
>> + if (dev->platform_data != NULL) {
>> + memcpy(&data->pdata, dev->platform_data, sizeof(data->pdata));
>> + } else {
>> + memcpy(&data->pdata, &cma3000_default_pdata,
>> + sizeof(data->pdata));
>> + #ifdef CONFIG_OF
>> + if (dev->of_node != NULL)
>> + cma3000_get_pdata_of(dev, data);
>> + else
>> + dev_info(dev, "platform data not found, using default\n");
>> + #else
>> + dev_info(dev, "platform data not found, using default\n");
>> + #endif
>> + }
>> + pdata = &data->pdata;
>> +
>> data->dev = dev;
>> data->input_dev = input_dev;
>> data->bus_ops = bops;
>> - data->pdata = pdata;
>> data->irq = irq;
>> mutex_init(&data->mutex);
>>
>> --
>> 1.7.7
>>
>
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
2011-10-25 7:38 ` Ricardo Ribalda Delgado
@ 2011-10-25 7:46 ` Grant Likely
2011-11-02 12:41 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-10-25 7:46 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Tue, Oct 25, 2011 at 9:38 AM, Ricardo Ribalda Delgado
<ricardo.ribalda@gmail.com> wrote:
> Hello Grant
>
>>> ---
>>
>> Drop this line, git cuts everything below a '---' line from the commit text.
>
> Done, thanks
>
>>
>> This binding needs documentation before it can be merged.
>
> Documentation/input/cma3000_d0x.txt is the right place ?
Documentation/devicetree/bindings/input
>> No of_device_id match table to match against compatible values?
>
> I think it is not needed, the device will be matched against the
> driver cma3000_d0x_spi.c and AFAIK on the spi/i2c devices you dont
> need the device_id match. But you know much more about this :). Can
> you point me to a example where a spi driver uses of_device-id match.
Use an of_device_id table. It's the right thing to do.
g.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver
2011-10-25 7:26 ` Ricardo Ribalda Delgado
@ 2011-10-25 8:28 ` Grant Likely
2011-11-02 14:28 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Grant Likely @ 2011-10-25 8:28 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Tue, Oct 25, 2011 at 09:26:10AM +0200, Ricardo Ribalda Delgado wrote:
> Hello Grant
>
> It is similar to the crm, because they came from the same
> manufacturer and they share some commands, but that is all.
>
> the crm is a gyroscope and the cma is an accelerometer. I tried to put
> both drivers together and the result was a bit too messy, I think it
> is easier to understand as two separate drivers, but if you believe
> they have to live together and help me making it more understandable,
> I have to problem in coding it.
Alternately, are there any parts of the cma driver that can be
generalized and used by both? A lot of the driver looks like
boilerplate to me, which I'd rather not see duplicated.
And I've filled in a few more comments below.
g.
>
> Regards!
>
> On Mon, Oct 24, 2011 at 23:40, Grant Likely <grant.likely@secretlab.ca> wrote:
> > On Mon, Oct 24, 2011 at 10:21:15PM +0200, Ricardo Ribalda Delgado wrote:
> >> Add support for CMR3000 Tri-axis accelerometer. CMR3000 supports both
> >> I2C/SPI bus communication, currently the driver supports SPI
> >> communication, since I have no hardware to test the I2C communication.
> >
> > How different is this driver from the cma3000? Is it a cut and paste job?
> >
> > g.
> >
> >>
> >> ---
> >>
> >> v4: Fixes suggested by Dmitry Torokhov
> >> -Do not release the input device until the irq has been released
> >>
> >> v3: Fixes suggested by Jonathan Cameron
> >> -Support DT
> >> -Cleaner spi read/write
> >>
> >> v2: Fixes suggested by Jonathan Cameron
> >> -Code Stype
> >> -Check pdata!=NULL
> >> -SPI align Cacheline
> >> -More clear based on
> >> -%s/set/write/
> >> -%s/accl/gyro/
> >> -remove READ/SET macros
> >>
> >> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
> >> ---
> >> drivers/input/misc/Kconfig | 24 ++
> >> drivers/input/misc/Makefile | 2 +
> >> drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
> >> drivers/input/misc/cmr3000_d0x.h | 45 ++++
> >> drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
> >> include/linux/input/cmr3000.h | 54 +++++
> >> 6 files changed, 695 insertions(+), 0 deletions(-)
> >> create mode 100644 drivers/input/misc/cmr3000_d0x.c
> >> create mode 100644 drivers/input/misc/cmr3000_d0x.h
> >> create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
> >> create mode 100644 include/linux/input/cmr3000.h
> >>
> >> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> >> index b9f2e93..7c56f94 100644
> >> --- a/drivers/input/misc/Kconfig
> >> +++ b/drivers/input/misc/Kconfig
> >> @@ -524,6 +524,30 @@ config INPUT_CMA3000_SPI
> >> To compile this driver as a module, choose M here: the
> >> module will be called cma3000_d0x_spi.
> >>
> >> +config INPUT_CMR3000
> >> + tristate "VTI CMR3000 Tri-axis gyroscope"
> >> + help
> >> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
> >> + driver
> >> +
> >> + This driver currently only supports SPI interface to the
> >> + controller. Also select the SPI method.
> >> +
> >> + If unsure, say N
> >> +
> >> + To compile this driver as a module, choose M here: the
> >> + module will be called cmr3000_d0x.
> >> +
> >> +config INPUT_CMR3000_SPI
> >> + tristate "Support SPI bus connection"
> >> + depends on INPUT_CMR3000 && SPI
> >> + help
> >> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
> >> + through SPI interface.
> >> +
> >> + To compile this driver as a module, choose M here: the
> >> + module will be called cmr3000_d0x_spi.
> >> +
> >> config INPUT_XEN_KBDDEV_FRONTEND
> >> tristate "Xen virtual keyboard and mouse support"
> >> depends on XEN_FBDEV_FRONTEND
> >> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
> >> index 7305f6f..c7fe09a 100644
> >> --- a/drivers/input/misc/Makefile
> >> +++ b/drivers/input/misc/Makefile
> >> @@ -21,6 +21,8 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
> >> obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
> >> obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
> >> obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
> >> +obj-$(CONFIG_INPUT_CMR3000) += cmr3000_d0x.o
> >> +obj-$(CONFIG_INPUT_CMR3000_SPI) += cmr3000_d0x_spi.o
> >> obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
> >> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
> >> obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
> >> diff --git a/drivers/input/misc/cmr3000_d0x.c b/drivers/input/misc/cmr3000_d0x.c
> >> new file mode 100644
> >> index 0000000..d046149
> >> --- /dev/null
> >> +++ b/drivers/input/misc/cmr3000_d0x.c
> >> @@ -0,0 +1,426 @@
> >> +/*
> >> + * VTI CMR3000_D0x Gyroscope driver
> >> + *
> >> + * Copyright (C) 2011 Qtechnology
> >> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
> >> + *
> >> + * Based on:
> >> + * drivers/input/misc/cma3000_d0x.c by: Hemanth V
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify it
> >> + * under the terms of the GNU General Public License version 2 as published by
> >> + * the Free Software Foundation.
> >> + *
> >> + * This program is distributed in the hope that it will be useful, but WITHOUT
> >> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> >> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> >> + * more details.
> >> + *
> >> + * You should have received a copy of the GNU General Public License along with
> >> + * this program. If not, see <http://www.gnu.org/licenses/>.
> >> + */
> >> +
> >> +#include <linux/types.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/input.h>
> >> +#include <linux/input/cmr3000.h>
> >> +#include <linux/of.h>
> >> +
> >> +#include "cmr3000_d0x.h"
> >> +
> >> +#define CMR3000_REV 0x21
> >> +
> >> +#define CMR3000_WHOAMI 0x00
> >> +#define CMR3000_REVID 0x01
> >> +#define CMR3000_CTRL 0x02
> >> +#define CMR3000_STATUS 0x03
> >> +#define CMR3000_X_LSB 0x0C
> >> +#define CMR3000_X_MSB 0x0D
> >> +#define CMR3000_Y_LSB 0x0E
> >> +#define CMR3000_Y_MSB 0x0F
> >> +#define CMR3000_Z_LSB 0x10
> >> +#define CMR3000_Z_MSB 0x11
> >> +#define CMR3000_I2C_ADDR 0x22
> >> +#define CMR3000_PDR 0x26
> >> +
> >> +#define CMR3000_IRQDIS (1 << 0)
> >> +#define CMR3000_MODEMASK (3 << 1)
> >> +#define CMR3000_BUSI2C (0 << 4)
> >> +#define CMR3000_BUSSPI (1 << 4)
> >> +#define CMR3000_INTLOW (1 << 6)
> >> +#define CMR3000_INTHIGH (0 << 6)
> >> +#define CMR3000_RST (1 << 7)
> >> +
> >> +#define CMRMODE_SHIFT 1
> >> +#define CMRIRQLEVEL_SHIFT 6
> >> +
> >> +#define CMR3000_STATUS_PERR (1 << 0)
> >> +#define CMR3000_STATUS_PORST (1 << 3)
> >> +
> >> +/* Settling time delay in ms */
> >> +#define CMR3000_SETDELAY 30
> >> +
> >> +/*
> >> + * Bit weights mult/div in dps for bit 0, other bits need
> >> + * multipy factor 2^n. 11th bit is the sign bit.
> >> + */
> >> +#define BIT_TO_DPS_MUL 3
> >> +#define BIT_TO_DPS_DIV 32
> >> +
> >> +static struct cmr3000_platform_data cmr3000_default_pdata = {
> >> + .irq_level = CMR3000_INTHIGH,
> >> + .mode = CMRMODE_MEAS80,
> >> + .fuzz_x = 1,
> >> + .fuzz_y = 1,
> >> + .fuzz_z = 1,
> >> + .irqflags = 0,
> >> +};
> >> +
> >> +struct cmr3000_gyro_data {
> >> + const struct cmr3000_bus_ops *bus_ops;
> >> + struct cmr3000_platform_data pdata;
> >> +
> >> + struct device *dev;
> >> + struct input_dev *input_dev;
> >> +
> >> + int irq_level;
> >> + u8 mode;
> >> +
> >> + int bit_to_mg;
> >> + int irq;
> >> +
> >> + struct mutex mutex;
> >> + bool opened;
> >> + bool suspended;
> >> +};
> >> +
> >> +static void decode_dps(struct cmr3000_gyro_data *data, int *datax,
> >> + int *datay, int *dataz)
> >> +{
> >> + /* Data in 2's complement, convert to dps */
> >> + *datax = (((s16) ((*datax) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> >> + *datay = (((s16) ((*datay) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> >> + *dataz = (((s16) ((*dataz) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
> >> +}
> >> +
> >> +static irqreturn_t cmr3000_thread_irq(int irq, void *dev_id)
> >> +{
> >> + struct cmr3000_gyro_data *data = dev_id;
> >> + int datax, datay, dataz;
> >> + u8 mode, intr_status;
> >> +
> >> + intr_status = data->bus_ops->read(data->dev, CMR3000_STATUS,
> >> + "irq status");
> >> + intr_status = data->bus_ops->read(data->dev, CMR3000_CTRL,
> >> + "control mode");
> >> + if (intr_status < 0)
> >> + return IRQ_NONE;
> >> +
> >> + /* Interrupt not for this device */
> >> + if (intr_status & CMR3000_IRQDIS)
> >> + return IRQ_NONE;
> >> +
> >> + mode = (intr_status & CMR3000_MODEMASK) >> CMRMODE_SHIFT;
> >> + if ((mode != CMRMODE_MEAS80)
> >> + && (mode != CMRMODE_MEAS20))
> >> + return IRQ_NONE;
> >> +
> >> + datax = (data->bus_ops->read(data->dev, CMR3000_X_MSB, "X_MSB")) << 8;
> >> + datax |= data->bus_ops->read(data->dev, CMR3000_X_LSB, "X_LSB");
> >> + datay = (data->bus_ops->read(data->dev, CMR3000_Y_MSB, "Y_MSB")) << 8;
> >> + datay |= data->bus_ops->read(data->dev, CMR3000_Y_LSB, "Y_LSB");
> >> + dataz = (data->bus_ops->read(data->dev, CMR3000_Z_MSB, "Z_MSB")) << 8;
> >> + dataz |= data->bus_ops->read(data->dev, CMR3000_Z_LSB, "Z_LSB");
> >> +
> >> + /* Device closed */
> >> + if ((data->mode != CMRMODE_MEAS80)
> >> + && (data->mode != CMRMODE_MEAS20))
> >> + return IRQ_NONE;
> >> +
> >> + /* Decode register values to dps */
> >> + decode_dps(data, &datax, &datay, &dataz);
> >> +
> >> + input_report_abs(data->input_dev, ABS_X, datax);
> >> + input_report_abs(data->input_dev, ABS_Y, datay);
> >> + input_report_abs(data->input_dev, ABS_Z, dataz);
> >> + input_sync(data->input_dev);
> >> +
> >> + return IRQ_HANDLED;
> >> +}
> >> +
> >> +static int cmr3000_poweron(struct cmr3000_gyro_data *data)
> >> +{
> >> + const struct cmr3000_platform_data *pdata = &data->pdata;
> >> + u8 ctrl;
> >> + int ret;
> >> +
> >> + ctrl = pdata->irq_level << CMRIRQLEVEL_SHIFT;
> >> + ctrl |= data->mode << CMRMODE_SHIFT;
> >> + ctrl |= data->bus_ops->ctrl_mod;
> >> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
> >> + "Mode setting");
> >> + if (ret < 0)
> >> + return -EIO;
> >> +
> >> + msleep(CMR3000_SETDELAY);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int cmr3000_poweroff(struct cmr3000_gyro_data *data)
> >> +{
> >> + int ret;
> >> + u8 ctrl = CMRMODE_POFF;
> >> +
> >> + ctrl |= data->bus_ops->ctrl_mod;
> >> + ctrl |= CMR3000_IRQDIS;
> >> +
> >> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
> >> + "Mode setting");
> >> + msleep(CMR3000_SETDELAY);
> >> +
> >> + return ret;
> >> +}
> >> +
> >> +static int cmr3000_reset(struct cmr3000_gyro_data *data)
> >> +{
> >> + int val;
> >> +
> >> + /* Reset chip */
> >> + data->bus_ops->write(data->dev, CMR3000_CTRL, CMR3000_RST, "Reset");
> >> + mdelay(2);
> >> +
> >> + /* Settling time delay */
> >> + val = data->bus_ops->read(data->dev, CMR3000_STATUS, "Status");
> >> + if (val < 0) {
> >> + dev_err(data->dev, "Reset failed\n");
> >> + return val;
> >> + }
> >> +
> >> + if (val & CMR3000_STATUS_PERR) {
> >> + dev_err(data->dev, "Parity Error\n");
> >> + return -EIO;
> >> + }
> >> +
> >> + return cmr3000_poweroff(data);
> >> +}
> >> +
> >> +static int cmr3000_open(struct input_dev *input_dev)
> >> +{
> >> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
> >> +
> >> + mutex_lock(&data->mutex);
> >> +
> >> + if (!data->suspended)
> >> + cmr3000_poweron(data);
> >> +
> >> + data->opened = true;
> >> +
> >> + mutex_unlock(&data->mutex);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static void cmr3000_close(struct input_dev *input_dev)
> >> +{
> >> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
> >> +
> >> + mutex_lock(&data->mutex);
> >> +
> >> + if (!data->suspended)
> >> + cmr3000_poweroff(data);
> >> +
> >> + data->opened = false;
> >> +
> >> + mutex_unlock(&data->mutex);
> >> +}
> >> +
> >> +void cmr3000_suspend(struct cmr3000_gyro_data *data)
> >> +{
> >> + mutex_lock(&data->mutex);
> >> +
> >> + if (!data->suspended && data->opened)
> >> + cmr3000_poweroff(data);
> >> +
> >> + data->suspended = true;
> >> +
> >> + mutex_unlock(&data->mutex);
> >> +}
> >> +EXPORT_SYMBOL(cmr3000_suspend);
> >> +
> >> +void cmr3000_resume(struct cmr3000_gyro_data *data)
> >> +{
> >> + mutex_lock(&data->mutex);
> >> +
> >> + if (data->suspended && data->opened)
> >> + cmr3000_poweron(data);
> >> +
> >> + data->suspended = false;
> >> +
> >> + mutex_unlock(&data->mutex);
> >> +}
> >> +EXPORT_SYMBOL(cmr3000_resume);
These four functions bother me. All they are doing is wrapping
poweron/poweroff operation. It makes me wonder what is missing from
core code that makes this song-and-dance necessary (or is there
something available in core code that this driver should be using).
> >> +
> >> +#ifdef CONFIG_OF
> >> +void cmr3000_get_pdata_of(struct device *dev, struct cmr3000_gyro_data *data)
> >> +{
> >> + const __be32 *property;
> >> + int len;
> >> +
> >> + property = of_get_property(dev->of_node, "vti,irq_level", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.irq_level = be32_to_cpup(property);
> >> +
> >> + property = of_get_property(dev->of_node, "vti,mode", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.mode = be32_to_cpup(property);
> >> +
> >> + property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.fuzz_x = be32_to_cpup(property);
> >> +
> >> + property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.fuzz_y = be32_to_cpup(property);
> >> +
> >> + property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.fuzz_z = be32_to_cpup(property);
> >> +
> >> + property = of_get_property(dev->of_node, "vti,irqflags", &len);
> >> + if (property && len == sizeof(int))
> >> + data->pdata.irqflags = be32_to_cpup(property);
> >> +
> >> + return;
> >> +}
> >> +#endif
> >> +
> >> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
> >> + const struct cmr3000_bus_ops *bops)
> >> +{
> >> + struct cmr3000_platform_data *pdata;
> >> + struct cmr3000_gyro_data *data;
> >> + struct input_dev *input_dev;
> >> + int rev;
> >> + int error;
> >> +
> >> + /* if no IRQ return error */
> >> + if (irq == 0) {
> >> + error = -EINVAL;
> >> + goto err_out;
> >> + }
> >> +
> >> + data = kzalloc(sizeof(struct cmr3000_gyro_data), GFP_KERNEL);
Consider devm_kzalloc() so the driver doesn't need to worry about
rewinding it.
Also, use 'sizeof(*data)' it's safer.
g.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-25 7:24 ` Ricardo Ribalda Delgado
@ 2011-10-25 8:29 ` Grant Likely
2011-10-25 8:32 ` Jonathan Cameron
1 sibling, 0 replies; 23+ messages in thread
From: Grant Likely @ 2011-10-25 8:29 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
On Tue, Oct 25, 2011 at 09:24:48AM +0200, Ricardo Ribalda Delgado wrote:
> Hello Grant
>
> Thanks for your comments. I am fixing the --- problem in all the patches.
>
> >
> > Mark Brown had posted a generic indirect register read/write library
> > that I believe is getting merged. Maybe this driver should be using
> > it?
>
> It is not on linux-next, and also it cannot be used directly, in order
> to read you have to do set reg= (reg << 2) | 2; And AFAIK it is not
> supported by the regmap
>
> >
> > Drop the .bus line. The core code does this bit for you.
>
> Done
>
> >> +module_init(cma3000_spi_init);
> >> +module_exit(cma3000_spi_exit);
> >
> > move module_init() directly below the function it registers.
>
> Also done, but I believe the other is more elegant :)
:-p
g.
> >
> >> +
> >> +MODULE_DESCRIPTION("CMA3000-D0x Accelerometer SPI Driver");
> >> +MODULE_LICENSE("GPL");
> >> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
> >> --
> >> 1.7.7
> >>
> >
>
>
>
> --
> Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-25 7:24 ` Ricardo Ribalda Delgado
2011-10-25 8:29 ` Grant Likely
@ 2011-10-25 8:32 ` Jonathan Cameron
2011-10-25 8:36 ` Mark Brown
1 sibling, 1 reply; 23+ messages in thread
From: Jonathan Cameron @ 2011-10-25 8:32 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: Grant Likely, dmitry.torokhov, sameo, peter.ujfalusi, aghayal,
david, Shubhrajyoti, saaguirre, hemanthv, linux-input, LKML,
Mark Brown
On 10/25/11 08:24, Ricardo Ribalda Delgado wrote:
> Hello Grant
>
> Thanks for your comments. I am fixing the --- problem in all the patches.
>
>>
>> Mark Brown had posted a generic indirect register read/write library
>> that I believe is getting merged. Maybe this driver should be using
>> it?
>
> It is not on linux-next, and also it cannot be used directly, in order
> to read you have to do set reg= (reg << 2) | 2; And AFAIK it is not
> supported by the regmap
My gut feeling is it would easy enough to add if it can't currently
be done. Mark?
Gains here are leveraging the bus abstractions from there. There aren't
enough registers to gain from caching etc.
>
>>
>> Drop the .bus line. The core code does this bit for you.
>
> Done
>
>>> +module_init(cma3000_spi_init);
>>> +module_exit(cma3000_spi_exit);
>>
>> move module_init() directly below the function it registers.
>
> Also done, but I believe the other is more elegant :)
>>
>>> +
>>> +MODULE_DESCRIPTION("CMA3000-D0x Accelerometer SPI Driver");
>>> +MODULE_LICENSE("GPL");
>>> +MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
>>> --
>>> 1.7.7
>>>
>>
>
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-25 8:32 ` Jonathan Cameron
@ 2011-10-25 8:36 ` Mark Brown
2011-11-02 12:38 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Mark Brown @ 2011-10-25 8:36 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Ricardo Ribalda Delgado, Grant Likely, dmitry.torokhov, sameo,
peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv,
linux-input, LKML
On Tue, Oct 25, 2011 at 09:32:27AM +0100, Jonathan Cameron wrote:
> On 10/25/11 08:24, Ricardo Ribalda Delgado wrote:
> > It is not on linux-next, and also it cannot be used directly, in order
> > to read you have to do set reg= (reg << 2) | 2; And AFAIK it is not
> > supported by the regmap
> My gut feeling is it would easy enough to add if it can't currently
> be done. Mark?
That should be trivial to add - the | 2 bit is already supported in
-next and will be sent to Linus this merge window, adding the shift is
just a simple matter of programming.
> Gains here are leveraging the bus abstractions from there. There aren't
> enough registers to gain from caching etc.
Depends on the workload more than the number of registers - if you're
able to eliminate enough reads then it can give a bit of a performance
boost. But it's completely optional either way.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-10-25 8:36 ` Mark Brown
@ 2011-11-02 12:38 ` Ricardo Ribalda Delgado
2011-11-02 12:49 ` Mark Brown
0 siblings, 1 reply; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-11-02 12:38 UTC (permalink / raw)
To: Mark Brown
Cc: Jonathan Cameron, Grant Likely, dmitry.torokhov, sameo,
peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv,
linux-input, LKML
Hello Mark
I will wait until your patches arrive to linux-next. And then I will
port mine in top of yours. It will be great to get your feedback then.
Thanks!
On Tue, Oct 25, 2011 at 10:36, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> On Tue, Oct 25, 2011 at 09:32:27AM +0100, Jonathan Cameron wrote:
>> On 10/25/11 08:24, Ricardo Ribalda Delgado wrote:
>
>> > It is not on linux-next, and also it cannot be used directly, in order
>> > to read you have to do set reg= (reg << 2) | 2; And AFAIK it is not
>> > supported by the regmap
>
>> My gut feeling is it would easy enough to add if it can't currently
>> be done. Mark?
>
> That should be trivial to add - the | 2 bit is already supported in
> -next and will be sent to Linus this merge window, adding the shift is
> just a simple matter of programming.
>
>> Gains here are leveraging the bus abstractions from there. There aren't
>> enough registers to gain from caching etc.
>
> Depends on the workload more than the number of registers - if you're
> able to eliminate enough reads then it can give a bit of a performance
> boost. But it's completely optional either way.
>
--
Ricardo Ribalda
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
2011-10-25 7:46 ` Grant Likely
@ 2011-11-02 12:41 ` Ricardo Ribalda Delgado
2011-11-02 14:51 ` Ricardo Ribalda Delgado
0 siblings, 1 reply; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-11-02 12:41 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Hello Grant
Thanks for your feedback
>>> No of_device_id match table to match against compatible values?
>>
>> I think it is not needed, the device will be matched against the
>> driver cma3000_d0x_spi.c and AFAIK on the spi/i2c devices you dont
>> need the device_id match. But you know much more about this :). Can
>> you point me to a example where a spi driver uses of_device-id match.
>
> Use an of_device_id table. It's the right thing to do.
>
Can you point me to a file where of_device_id is used in a spi/i2c
driver? I thought that was only for mmaped drivers....
Thanks!
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support
2011-11-02 12:38 ` Ricardo Ribalda Delgado
@ 2011-11-02 12:49 ` Mark Brown
0 siblings, 0 replies; 23+ messages in thread
From: Mark Brown @ 2011-11-02 12:49 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: Jonathan Cameron, Grant Likely, dmitry.torokhov, sameo,
peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv,
linux-input, LKML
On Wed, Nov 02, 2011 at 01:38:29PM +0100, Ricardo Ribalda Delgado wrote:
Don't top post.
> I will wait until your patches arrive to linux-next. And then I will
> port mine in top of yours. It will be great to get your feedback then.
I've no immediate intention of working on supporting devices like this,
apart from anything else I don't have access to any hardware which needs
this stuff.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver
2011-10-25 8:28 ` Grant Likely
@ 2011-11-02 14:28 ` Ricardo Ribalda Delgado
0 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-11-02 14:28 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Hello Grant
Thanks for your feedback. I think I will remove this patch from the
patchset, I am already in the 5th iteration :S... When the cma
supports devicetree and spi I will try to re-engineer this driver.
Thanks again
On Tue, Oct 25, 2011 at 10:28, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Tue, Oct 25, 2011 at 09:26:10AM +0200, Ricardo Ribalda Delgado wrote:
>> Hello Grant
>>
>> It is similar to the crm, because they came from the same
>> manufacturer and they share some commands, but that is all.
>>
>> the crm is a gyroscope and the cma is an accelerometer. I tried to put
>> both drivers together and the result was a bit too messy, I think it
>> is easier to understand as two separate drivers, but if you believe
>> they have to live together and help me making it more understandable,
>> I have to problem in coding it.
>
> Alternately, are there any parts of the cma driver that can be
> generalized and used by both? A lot of the driver looks like
> boilerplate to me, which I'd rather not see duplicated.
>
> And I've filled in a few more comments below.
>
> g.
>
>>
>> Regards!
>>
>> On Mon, Oct 24, 2011 at 23:40, Grant Likely <grant.likely@secretlab.ca> wrote:
>> > On Mon, Oct 24, 2011 at 10:21:15PM +0200, Ricardo Ribalda Delgado wrote:
>> >> Add support for CMR3000 Tri-axis accelerometer. CMR3000 supports both
>> >> I2C/SPI bus communication, currently the driver supports SPI
>> >> communication, since I have no hardware to test the I2C communication.
>> >
>> > How different is this driver from the cma3000? Is it a cut and paste job?
>> >
>> > g.
>> >
>> >>
>> >> ---
>> >>
>> >> v4: Fixes suggested by Dmitry Torokhov
>> >> -Do not release the input device until the irq has been released
>> >>
>> >> v3: Fixes suggested by Jonathan Cameron
>> >> -Support DT
>> >> -Cleaner spi read/write
>> >>
>> >> v2: Fixes suggested by Jonathan Cameron
>> >> -Code Stype
>> >> -Check pdata!=NULL
>> >> -SPI align Cacheline
>> >> -More clear based on
>> >> -%s/set/write/
>> >> -%s/accl/gyro/
>> >> -remove READ/SET macros
>> >>
>> >> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
>> >> ---
>> >> drivers/input/misc/Kconfig | 24 ++
>> >> drivers/input/misc/Makefile | 2 +
>> >> drivers/input/misc/cmr3000_d0x.c | 426 ++++++++++++++++++++++++++++++++++
>> >> drivers/input/misc/cmr3000_d0x.h | 45 ++++
>> >> drivers/input/misc/cmr3000_d0x_spi.c | 144 ++++++++++++
>> >> include/linux/input/cmr3000.h | 54 +++++
>> >> 6 files changed, 695 insertions(+), 0 deletions(-)
>> >> create mode 100644 drivers/input/misc/cmr3000_d0x.c
>> >> create mode 100644 drivers/input/misc/cmr3000_d0x.h
>> >> create mode 100644 drivers/input/misc/cmr3000_d0x_spi.c
>> >> create mode 100644 include/linux/input/cmr3000.h
>> >>
>> >> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
>> >> index b9f2e93..7c56f94 100644
>> >> --- a/drivers/input/misc/Kconfig
>> >> +++ b/drivers/input/misc/Kconfig
>> >> @@ -524,6 +524,30 @@ config INPUT_CMA3000_SPI
>> >> To compile this driver as a module, choose M here: the
>> >> module will be called cma3000_d0x_spi.
>> >>
>> >> +config INPUT_CMR3000
>> >> + tristate "VTI CMR3000 Tri-axis gyroscope"
>> >> + help
>> >> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
>> >> + driver
>> >> +
>> >> + This driver currently only supports SPI interface to the
>> >> + controller. Also select the SPI method.
>> >> +
>> >> + If unsure, say N
>> >> +
>> >> + To compile this driver as a module, choose M here: the
>> >> + module will be called cmr3000_d0x.
>> >> +
>> >> +config INPUT_CMR3000_SPI
>> >> + tristate "Support SPI bus connection"
>> >> + depends on INPUT_CMR3000 && SPI
>> >> + help
>> >> + Say Y here if you want to use VTI CMR3000_D0x Gyroscope
>> >> + through SPI interface.
>> >> +
>> >> + To compile this driver as a module, choose M here: the
>> >> + module will be called cmr3000_d0x_spi.
>> >> +
>> >> config INPUT_XEN_KBDDEV_FRONTEND
>> >> tristate "Xen virtual keyboard and mouse support"
>> >> depends on XEN_FBDEV_FRONTEND
>> >> diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
>> >> index 7305f6f..c7fe09a 100644
>> >> --- a/drivers/input/misc/Makefile
>> >> +++ b/drivers/input/misc/Makefile
>> >> @@ -21,6 +21,8 @@ obj-$(CONFIG_INPUT_CM109) += cm109.o
>> >> obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
>> >> obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o
>> >> obj-$(CONFIG_INPUT_CMA3000_SPI) += cma3000_d0x_spi.o
>> >> +obj-$(CONFIG_INPUT_CMR3000) += cmr3000_d0x.o
>> >> +obj-$(CONFIG_INPUT_CMR3000_SPI) += cmr3000_d0x_spi.o
>> >> obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o
>> >> obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
>> >> obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
>> >> diff --git a/drivers/input/misc/cmr3000_d0x.c b/drivers/input/misc/cmr3000_d0x.c
>> >> new file mode 100644
>> >> index 0000000..d046149
>> >> --- /dev/null
>> >> +++ b/drivers/input/misc/cmr3000_d0x.c
>> >> @@ -0,0 +1,426 @@
>> >> +/*
>> >> + * VTI CMR3000_D0x Gyroscope driver
>> >> + *
>> >> + * Copyright (C) 2011 Qtechnology
>> >> + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
>> >> + *
>> >> + * Based on:
>> >> + * drivers/input/misc/cma3000_d0x.c by: Hemanth V
>> >> + *
>> >> + * This program is free software; you can redistribute it and/or modify it
>> >> + * under the terms of the GNU General Public License version 2 as published by
>> >> + * the Free Software Foundation.
>> >> + *
>> >> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> >> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> >> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
>> >> + * more details.
>> >> + *
>> >> + * You should have received a copy of the GNU General Public License along with
>> >> + * this program. If not, see <http://www.gnu.org/licenses/>.
>> >> + */
>> >> +
>> >> +#include <linux/types.h>
>> >> +#include <linux/interrupt.h>
>> >> +#include <linux/delay.h>
>> >> +#include <linux/slab.h>
>> >> +#include <linux/input.h>
>> >> +#include <linux/input/cmr3000.h>
>> >> +#include <linux/of.h>
>> >> +
>> >> +#include "cmr3000_d0x.h"
>> >> +
>> >> +#define CMR3000_REV 0x21
>> >> +
>> >> +#define CMR3000_WHOAMI 0x00
>> >> +#define CMR3000_REVID 0x01
>> >> +#define CMR3000_CTRL 0x02
>> >> +#define CMR3000_STATUS 0x03
>> >> +#define CMR3000_X_LSB 0x0C
>> >> +#define CMR3000_X_MSB 0x0D
>> >> +#define CMR3000_Y_LSB 0x0E
>> >> +#define CMR3000_Y_MSB 0x0F
>> >> +#define CMR3000_Z_LSB 0x10
>> >> +#define CMR3000_Z_MSB 0x11
>> >> +#define CMR3000_I2C_ADDR 0x22
>> >> +#define CMR3000_PDR 0x26
>> >> +
>> >> +#define CMR3000_IRQDIS (1 << 0)
>> >> +#define CMR3000_MODEMASK (3 << 1)
>> >> +#define CMR3000_BUSI2C (0 << 4)
>> >> +#define CMR3000_BUSSPI (1 << 4)
>> >> +#define CMR3000_INTLOW (1 << 6)
>> >> +#define CMR3000_INTHIGH (0 << 6)
>> >> +#define CMR3000_RST (1 << 7)
>> >> +
>> >> +#define CMRMODE_SHIFT 1
>> >> +#define CMRIRQLEVEL_SHIFT 6
>> >> +
>> >> +#define CMR3000_STATUS_PERR (1 << 0)
>> >> +#define CMR3000_STATUS_PORST (1 << 3)
>> >> +
>> >> +/* Settling time delay in ms */
>> >> +#define CMR3000_SETDELAY 30
>> >> +
>> >> +/*
>> >> + * Bit weights mult/div in dps for bit 0, other bits need
>> >> + * multipy factor 2^n. 11th bit is the sign bit.
>> >> + */
>> >> +#define BIT_TO_DPS_MUL 3
>> >> +#define BIT_TO_DPS_DIV 32
>> >> +
>> >> +static struct cmr3000_platform_data cmr3000_default_pdata = {
>> >> + .irq_level = CMR3000_INTHIGH,
>> >> + .mode = CMRMODE_MEAS80,
>> >> + .fuzz_x = 1,
>> >> + .fuzz_y = 1,
>> >> + .fuzz_z = 1,
>> >> + .irqflags = 0,
>> >> +};
>> >> +
>> >> +struct cmr3000_gyro_data {
>> >> + const struct cmr3000_bus_ops *bus_ops;
>> >> + struct cmr3000_platform_data pdata;
>> >> +
>> >> + struct device *dev;
>> >> + struct input_dev *input_dev;
>> >> +
>> >> + int irq_level;
>> >> + u8 mode;
>> >> +
>> >> + int bit_to_mg;
>> >> + int irq;
>> >> +
>> >> + struct mutex mutex;
>> >> + bool opened;
>> >> + bool suspended;
>> >> +};
>> >> +
>> >> +static void decode_dps(struct cmr3000_gyro_data *data, int *datax,
>> >> + int *datay, int *dataz)
>> >> +{
>> >> + /* Data in 2's complement, convert to dps */
>> >> + *datax = (((s16) ((*datax) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> >> + *datay = (((s16) ((*datay) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> >> + *dataz = (((s16) ((*dataz) << 2)) * BIT_TO_DPS_MUL) / BIT_TO_DPS_DIV;
>> >> +}
>> >> +
>> >> +static irqreturn_t cmr3000_thread_irq(int irq, void *dev_id)
>> >> +{
>> >> + struct cmr3000_gyro_data *data = dev_id;
>> >> + int datax, datay, dataz;
>> >> + u8 mode, intr_status;
>> >> +
>> >> + intr_status = data->bus_ops->read(data->dev, CMR3000_STATUS,
>> >> + "irq status");
>> >> + intr_status = data->bus_ops->read(data->dev, CMR3000_CTRL,
>> >> + "control mode");
>> >> + if (intr_status < 0)
>> >> + return IRQ_NONE;
>> >> +
>> >> + /* Interrupt not for this device */
>> >> + if (intr_status & CMR3000_IRQDIS)
>> >> + return IRQ_NONE;
>> >> +
>> >> + mode = (intr_status & CMR3000_MODEMASK) >> CMRMODE_SHIFT;
>> >> + if ((mode != CMRMODE_MEAS80)
>> >> + && (mode != CMRMODE_MEAS20))
>> >> + return IRQ_NONE;
>> >> +
>> >> + datax = (data->bus_ops->read(data->dev, CMR3000_X_MSB, "X_MSB")) << 8;
>> >> + datax |= data->bus_ops->read(data->dev, CMR3000_X_LSB, "X_LSB");
>> >> + datay = (data->bus_ops->read(data->dev, CMR3000_Y_MSB, "Y_MSB")) << 8;
>> >> + datay |= data->bus_ops->read(data->dev, CMR3000_Y_LSB, "Y_LSB");
>> >> + dataz = (data->bus_ops->read(data->dev, CMR3000_Z_MSB, "Z_MSB")) << 8;
>> >> + dataz |= data->bus_ops->read(data->dev, CMR3000_Z_LSB, "Z_LSB");
>> >> +
>> >> + /* Device closed */
>> >> + if ((data->mode != CMRMODE_MEAS80)
>> >> + && (data->mode != CMRMODE_MEAS20))
>> >> + return IRQ_NONE;
>> >> +
>> >> + /* Decode register values to dps */
>> >> + decode_dps(data, &datax, &datay, &dataz);
>> >> +
>> >> + input_report_abs(data->input_dev, ABS_X, datax);
>> >> + input_report_abs(data->input_dev, ABS_Y, datay);
>> >> + input_report_abs(data->input_dev, ABS_Z, dataz);
>> >> + input_sync(data->input_dev);
>> >> +
>> >> + return IRQ_HANDLED;
>> >> +}
>> >> +
>> >> +static int cmr3000_poweron(struct cmr3000_gyro_data *data)
>> >> +{
>> >> + const struct cmr3000_platform_data *pdata = &data->pdata;
>> >> + u8 ctrl;
>> >> + int ret;
>> >> +
>> >> + ctrl = pdata->irq_level << CMRIRQLEVEL_SHIFT;
>> >> + ctrl |= data->mode << CMRMODE_SHIFT;
>> >> + ctrl |= data->bus_ops->ctrl_mod;
>> >> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
>> >> + "Mode setting");
>> >> + if (ret < 0)
>> >> + return -EIO;
>> >> +
>> >> + msleep(CMR3000_SETDELAY);
>> >> +
>> >> + return 0;
>> >> +}
>> >> +
>> >> +static int cmr3000_poweroff(struct cmr3000_gyro_data *data)
>> >> +{
>> >> + int ret;
>> >> + u8 ctrl = CMRMODE_POFF;
>> >> +
>> >> + ctrl |= data->bus_ops->ctrl_mod;
>> >> + ctrl |= CMR3000_IRQDIS;
>> >> +
>> >> + ret = data->bus_ops->write(data->dev, CMR3000_CTRL, ctrl,
>> >> + "Mode setting");
>> >> + msleep(CMR3000_SETDELAY);
>> >> +
>> >> + return ret;
>> >> +}
>> >> +
>> >> +static int cmr3000_reset(struct cmr3000_gyro_data *data)
>> >> +{
>> >> + int val;
>> >> +
>> >> + /* Reset chip */
>> >> + data->bus_ops->write(data->dev, CMR3000_CTRL, CMR3000_RST, "Reset");
>> >> + mdelay(2);
>> >> +
>> >> + /* Settling time delay */
>> >> + val = data->bus_ops->read(data->dev, CMR3000_STATUS, "Status");
>> >> + if (val < 0) {
>> >> + dev_err(data->dev, "Reset failed\n");
>> >> + return val;
>> >> + }
>> >> +
>> >> + if (val & CMR3000_STATUS_PERR) {
>> >> + dev_err(data->dev, "Parity Error\n");
>> >> + return -EIO;
>> >> + }
>> >> +
>> >> + return cmr3000_poweroff(data);
>> >> +}
>> >> +
>> >> +static int cmr3000_open(struct input_dev *input_dev)
>> >> +{
>> >> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
>> >> +
>> >> + mutex_lock(&data->mutex);
>> >> +
>> >> + if (!data->suspended)
>> >> + cmr3000_poweron(data);
>> >> +
>> >> + data->opened = true;
>> >> +
>> >> + mutex_unlock(&data->mutex);
>> >> +
>> >> + return 0;
>> >> +}
>> >> +
>> >> +static void cmr3000_close(struct input_dev *input_dev)
>> >> +{
>> >> + struct cmr3000_gyro_data *data = input_get_drvdata(input_dev);
>> >> +
>> >> + mutex_lock(&data->mutex);
>> >> +
>> >> + if (!data->suspended)
>> >> + cmr3000_poweroff(data);
>> >> +
>> >> + data->opened = false;
>> >> +
>> >> + mutex_unlock(&data->mutex);
>> >> +}
>> >> +
>> >> +void cmr3000_suspend(struct cmr3000_gyro_data *data)
>> >> +{
>> >> + mutex_lock(&data->mutex);
>> >> +
>> >> + if (!data->suspended && data->opened)
>> >> + cmr3000_poweroff(data);
>> >> +
>> >> + data->suspended = true;
>> >> +
>> >> + mutex_unlock(&data->mutex);
>> >> +}
>> >> +EXPORT_SYMBOL(cmr3000_suspend);
>> >> +
>> >> +void cmr3000_resume(struct cmr3000_gyro_data *data)
>> >> +{
>> >> + mutex_lock(&data->mutex);
>> >> +
>> >> + if (data->suspended && data->opened)
>> >> + cmr3000_poweron(data);
>> >> +
>> >> + data->suspended = false;
>> >> +
>> >> + mutex_unlock(&data->mutex);
>> >> +}
>> >> +EXPORT_SYMBOL(cmr3000_resume);
>
> These four functions bother me. All they are doing is wrapping
> poweron/poweroff operation. It makes me wonder what is missing from
> core code that makes this song-and-dance necessary (or is there
> something available in core code that this driver should be using).
>
>> >> +
>> >> +#ifdef CONFIG_OF
>> >> +void cmr3000_get_pdata_of(struct device *dev, struct cmr3000_gyro_data *data)
>> >> +{
>> >> + const __be32 *property;
>> >> + int len;
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,irq_level", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.irq_level = be32_to_cpup(property);
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,mode", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.mode = be32_to_cpup(property);
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,fuzz_x", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.fuzz_x = be32_to_cpup(property);
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,fuzz_y", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.fuzz_y = be32_to_cpup(property);
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,fuzz_z", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.fuzz_z = be32_to_cpup(property);
>> >> +
>> >> + property = of_get_property(dev->of_node, "vti,irqflags", &len);
>> >> + if (property && len == sizeof(int))
>> >> + data->pdata.irqflags = be32_to_cpup(property);
>> >> +
>> >> + return;
>> >> +}
>> >> +#endif
>> >> +
>> >> +struct cmr3000_gyro_data *cmr3000_init(struct device *dev, int irq,
>> >> + const struct cmr3000_bus_ops *bops)
>> >> +{
>> >> + struct cmr3000_platform_data *pdata;
>> >> + struct cmr3000_gyro_data *data;
>> >> + struct input_dev *input_dev;
>> >> + int rev;
>> >> + int error;
>> >> +
>> >> + /* if no IRQ return error */
>> >> + if (irq == 0) {
>> >> + error = -EINVAL;
>> >> + goto err_out;
>> >> + }
>> >> +
>> >> + data = kzalloc(sizeof(struct cmr3000_gyro_data), GFP_KERNEL);
>
> Consider devm_kzalloc() so the driver doesn't need to worry about
> rewinding it.
>
> Also, use 'sizeof(*data)' it's safer.
>
> g.
>
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata
2011-11-02 12:41 ` Ricardo Ribalda Delgado
@ 2011-11-02 14:51 ` Ricardo Ribalda Delgado
0 siblings, 0 replies; 23+ messages in thread
From: Ricardo Ribalda Delgado @ 2011-11-02 14:51 UTC (permalink / raw)
To: Grant Likely
Cc: dmitry.torokhov, sameo, peter.ujfalusi, jic23, aghayal, david,
Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel
Ok, found it, and implement it.... Please check the new patchset :)
Thanks
On Wed, Nov 2, 2011 at 13:41, Ricardo Ribalda Delgado
<ricardo.ribalda@gmail.com> wrote:
> Hello Grant
> Thanks for your feedback
>
>>>> No of_device_id match table to match against compatible values?
>>>
>>> I think it is not needed, the device will be matched against the
>>> driver cma3000_d0x_spi.c and AFAIK on the spi/i2c devices you dont
>>> need the device_id match. But you know much more about this :). Can
>>> you point me to a example where a spi driver uses of_device-id match.
>>
>> Use an of_device_id table. It's the right thing to do.
>>
> Can you point me to a file where of_device_id is used in a spi/i2c
> driver? I thought that was only for mmaped drivers....
>
>
> Thanks!
>
>
> --
> Ricardo Ribalda
>
--
Ricardo Ribalda
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2011-11-02 14:52 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-24 20:21 [PATCHv4 0/6] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 2/6] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 3/6] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 5/6] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado
2011-10-24 21:40 ` Grant Likely
2011-10-25 7:26 ` Ricardo Ribalda Delgado
2011-10-25 8:28 ` Grant Likely
2011-11-02 14:28 ` Ricardo Ribalda Delgado
2011-10-24 20:21 ` [PATCHv4 6/6] input/cma3000_d0x: Match comment to name of struct Ricardo Ribalda Delgado
[not found] ` <1319487676-27181-2-git-send-email-ricardo.ribalda@gmail.com>
2011-10-24 21:31 ` [PATCHv4 1/6] input/cma3000_d0x: Support devices without pdata Grant Likely
2011-10-25 7:38 ` Ricardo Ribalda Delgado
2011-10-25 7:46 ` Grant Likely
2011-11-02 12:41 ` Ricardo Ribalda Delgado
2011-11-02 14:51 ` Ricardo Ribalda Delgado
[not found] ` <1319487676-27181-5-git-send-email-ricardo.ribalda@gmail.com>
2011-10-24 21:36 ` [PATCHv4 4/6] input/cma3000_d0x: Add CMA3000 spi support Grant Likely
2011-10-25 7:24 ` Ricardo Ribalda Delgado
2011-10-25 8:29 ` Grant Likely
2011-10-25 8:32 ` Jonathan Cameron
2011-10-25 8:36 ` Mark Brown
2011-11-02 12:38 ` Ricardo Ribalda Delgado
2011-11-02 12:49 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).