* [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 @ 2011-10-18 8:28 Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado ` (7 more replies) 0 siblings, 8 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv 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. Ricardo Ribalda Delgado (5): 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 drivers/input/misc/Kconfig | 38 +++- drivers/input/misc/Makefile | 3 + drivers/input/misc/cma3000_d0x.c | 42 ++++- drivers/input/misc/cma3000_d0x_spi.c | 178 +++++++++++++++ drivers/input/misc/cmr3000_d0x.c | 400 ++++++++++++++++++++++++++++++++++ drivers/input/misc/cmr3000_d0x.h | 45 ++++ drivers/input/misc/cmr3000_d0x_spi.c | 178 +++++++++++++++ include/linux/input/cmr3000.h | 54 +++++ 8 files changed, 932 insertions(+), 6 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] 17+ messages in thread
* [PATCH 1/5] input/cma3000_d0x: Support devices without pdata 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado @ 2011-10-18 8:28 ` Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 2/5] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado ` (6 subsequent siblings) 7 siblings, 0 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv Cc: Ricardo Ribalda Delgado Architechtures based on device-tree does not have platform data associated to the spi/i2c devices. This patch allows those architechtures to use the cma3000 driver with a default configuration. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- drivers/input/misc/cma3000_d0x.c | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 1633b63..2f993d5 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -62,6 +62,18 @@ #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; @@ -283,19 +295,24 @@ EXPORT_SYMBOL(cma3000_resume); 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; + const struct cma3000_platform_data *pdata; struct cma3000_accl_data *data; struct input_dev *input_dev; int rev; int error; + if (!dev->platform_data) { + dev_info(dev, "platform data not found, using default\n"); + pdata = &cma3000_default_pdata; + } else + pdata = dev->platform_data; + 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; -- 1.7.7 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/5] input/cma3000_d0x: Check silicon version 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado @ 2011-10-18 8:28 ` Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado ` (5 subsequent siblings) 7 siblings, 0 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv Cc: Ricardo Ribalda Delgado Improve probing of the cma3000 chip, by checking the revision of the device. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- drivers/input/misc/cma3000_d0x.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 2f993d5..9899742 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -26,6 +26,8 @@ #include "cma3000_d0x.h" +#define CMA3000_REV 0x10 + #define CMA3000_WHOAMI 0x00 #define CMA3000_REVID 0x01 #define CMA3000_CTRL 0x02 @@ -373,9 +375,20 @@ 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); + rev = CMA3000_READ(data, CMA3000_WHOAMI, "WhoamI"); + if (rev < 0) { + error = rev; + goto err_free_mem; + } + pr_info("CMA3000 Accelerometer: WhoamI %x\n", rev); + error = request_threaded_irq(irq, NULL, cma3000_thread_irq, pdata->irqflags | IRQF_ONESHOT, "cma3000_d0x", data); -- 1.7.7 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 2/5] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado @ 2011-10-18 8:28 ` Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado ` (4 subsequent siblings) 7 siblings, 0 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv 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. 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 9899742..15577b7 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -44,6 +44,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) @@ -230,8 +231,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] 17+ messages in thread
* [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado ` (2 preceding siblings ...) 2011-10-18 8:28 ` [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado @ 2011-10-18 8:28 ` Ricardo Ribalda Delgado 2011-10-18 8:44 ` Jonathan Cameron 2011-10-18 8:28 ` [PATCH 5/5] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado ` (3 subsequent siblings) 7 siblings, 1 reply; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv Cc: Ricardo Ribalda Delgado Add support for SPI communication. 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 | 178 ++++++++++++++++++++++++++++++++++ 3 files changed, 191 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..49ad373 --- /dev/null +++ b/drivers/input/misc/cma3000_d0x_spi.c @@ -0,0 +1,178 @@ +/* + * Implements SPI interface for VTI CMA300_D0x Accelerometer driver + * + * Copyright (C) 2011 Qtechnology + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com> + * Based on: + * Hemanth V <hemanthv@ti.com> + * Michael Hennerich <hennerich@blackfin.uclinux.org> + * + * 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" + +enum { DO_READ = 0, DO_WRITE }; + +static int cma3000_spi_cmd(struct spi_device *spi, u8 reg, u8 * val, int cmd, + char *msg) +{ + int ret; + unsigned char tx_buf[2]; + unsigned char rx_buf[2]; + struct spi_transfer t = { + .rx_buf = rx_buf, + .tx_buf = tx_buf, + .len = 2, + }; + struct spi_message m; + + if (cmd == DO_WRITE) { + tx_buf[0] = (reg << 2) | 2; + tx_buf[1] = *val; + } else { + tx_buf[0] = reg << 2; + tx_buf[1] = 0; + } + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(spi, &m); + if (ret < 0) { + dev_err(&spi->dev, "%s failed (%s, %d)\n", __func__, msg, ret); + return ret; + } + if (cmd == DO_READ) + *val = rx_buf[1]; + + if (rx_buf[0] & 0xc1) + dev_err(&spi->dev, + "%s Invalid Zero mask(0x%x)\n", __func__, rx_buf[0]); + + if ((rx_buf[0] & 0x2) != 0x2) + dev_err(&spi->dev, + "%s Invalid One mask (0x%x)\n", __func__, rx_buf[0]); + + return 0; +} + +static int cma3000_spi_set(struct device *dev, u8 reg, u8 val, char *msg) +{ + + struct spi_device *spi = to_spi_device(dev); + + return cma3000_spi_cmd(spi, reg, &val, DO_WRITE, msg); +} + +static int cma3000_spi_read(struct device *dev, u8 reg, char *msg) +{ + struct spi_device *spi = to_spi_device(dev); + int ret; + u8 val; + + ret = cma3000_spi_cmd(spi, reg, &val, DO_READ, msg); + if (ret) + return ret; + return val; +} + +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_set, +}; + +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] 17+ messages in thread
* Re: [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support 2011-10-18 8:28 ` [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado @ 2011-10-18 8:44 ` Jonathan Cameron 0 siblings, 0 replies; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 8:44 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: > Add support for SPI communication. > Fix that cacheline issue and some tidying up and this is fine. > 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 | 178 ++++++++++++++++++++++++++++++++++ > 3 files changed, 191 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..49ad373 > --- /dev/null > +++ b/drivers/input/misc/cma3000_d0x_spi.c > @@ -0,0 +1,178 @@ > +/* > + * Implements SPI interface for VTI CMA300_D0x Accelerometer driver > + * > + * Copyright (C) 2011 Qtechnology > + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com> > + * Based on: You wrote a patch based on some people? You might want to say what was written by these two that you used. > + * Hemanth V <hemanthv@ti.com> > + * Michael Hennerich <hennerich@blackfin.uclinux.org> > + * > + * 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" > + > +enum { DO_READ = 0, DO_WRITE }; > + Looking at this function, I'd have thought it might be simpler to review as separate read and write functions. This is particularly true as there are only two call sites and they are one of each so just roll it into the set and read functions. Passing an error message string in is also very ugly. If you want to report errors then do it at the call sites, not in this fucntion. Also some incorrect spacing so another case for checkpatch. > +static int cma3000_spi_cmd(struct spi_device *spi, u8 reg, u8 * val, int cmd, > + char *msg) > +{ > + int ret; > + unsigned char tx_buf[2]; > + unsigned char rx_buf[2]; Please look up cacheline issues with spi transfers. These need to be dynamically assigned. Easiest is probably just to assign the with kmalloc right here. Otherwise you'll need to put these buffers in an appropriate structure being careful about alignment. > + struct spi_transfer t = { > + .rx_buf = rx_buf, > + .tx_buf = tx_buf, > + .len = 2, > + }; > + struct spi_message m; > + > + if (cmd == DO_WRITE) { > + tx_buf[0] = (reg << 2) | 2; > + tx_buf[1] = *val; > + } else { > + tx_buf[0] = reg << 2; > + tx_buf[1] = 0; > + } > + spi_message_init(&m); > + spi_message_add_tail(&t, &m); > + ret = spi_sync(spi, &m); > + if (ret < 0) { > + dev_err(&spi->dev, "%s failed (%s, %d)\n", __func__, msg, ret); > + return ret; > + } > + if (cmd == DO_READ) > + *val = rx_buf[1]; > + > + if (rx_buf[0] & 0xc1) > + dev_err(&spi->dev, > + "%s Invalid Zero mask(0x%x)\n", __func__, rx_buf[0]); That's a pretty weird and cryptic error message. Does this meant the read failed? If so just say that, we really don't care how it failed! > + > + if ((rx_buf[0] & 0x2) != 0x2) > + dev_err(&spi->dev, > + "%s Invalid One mask (0x%x)\n", __func__, rx_buf[0]); > + > + return 0; > +} > + > +static int cma3000_spi_set(struct device *dev, u8 reg, u8 val, char *msg) > +{ > + > + struct spi_device *spi = to_spi_device(dev); > + > + return cma3000_spi_cmd(spi, reg, &val, DO_WRITE, msg); > +} > + > +static int cma3000_spi_read(struct device *dev, u8 reg, char *msg) > +{ > + struct spi_device *spi = to_spi_device(dev); > + int ret; > + u8 val; > + > + ret = cma3000_spi_cmd(spi, reg, &val, DO_READ, msg); > + if (ret) > + return ret; > + return val; > +} > + > +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_set, why not just call it write and match the semantics here? > +}; > + > +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>"); ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 5/5] Input: add CMR3000 gyrsocope driver 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado ` (3 preceding siblings ...) 2011-10-18 8:28 ` [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado @ 2011-10-18 8:28 ` Ricardo Ribalda Delgado 2011-10-18 8:54 ` Jonathan Cameron [not found] ` <1318926486-10330-2-git-send-email-ricardo.ribalda@gmail.com> ` (2 subsequent siblings) 7 siblings, 1 reply; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 8:28 UTC (permalink / raw) To: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, jic23, hemanthv 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. 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 | 400 ++++++++++++++++++++++++++++++++++ drivers/input/misc/cmr3000_d0x.h | 45 ++++ drivers/input/misc/cmr3000_d0x_spi.c | 178 +++++++++++++++ include/linux/input/cmr3000.h | 54 +++++ 6 files changed, 703 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..5ffe38b --- /dev/null +++ b/drivers/input/misc/cmr3000_d0x.c @@ -0,0 +1,400 @@ +/* + * VTI CMR3000_D0x Gyroscope driver + * + * Copyright (C) 2011 Qtechnology + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com> + * + * Based on: + * Author: Hemanth V <hemanthv@ti.com> + * + * 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 "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 + +/* Delay for clearing interrupt in us */ +#define CMR3000_INTDELAY 44 + +/* + * 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, + .irqflags = 0, + .fuzz_x = 1, + .fuzz_y = 1, + .fuzz_z = 1, +}; + +struct cmr3000_accl_data { + const struct cmr3000_bus_ops *bus_ops; + const 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; +}; + +#define CMR3000_READ(data, reg, msg) \ + (data->bus_ops->read(data->dev, reg, msg)) +#define CMR3000_SET(data, reg, val, msg) \ + ((data)->bus_ops->write(data->dev, reg, val, msg)) + +static void decode_dps(struct cmr3000_accl_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_accl_data *data = dev_id; + int datax, datay, dataz; + u8 mode, intr_status; + + intr_status = CMR3000_READ(data, CMR3000_STATUS, "interrupt status"); + intr_status = CMR3000_READ(data, 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 = (CMR3000_READ(data, CMR3000_X_MSB, "X_MSB")) << 8; + datax |= CMR3000_READ(data, CMR3000_X_LSB, "X_LSB"); + datay = (CMR3000_READ(data, CMR3000_Y_MSB, "Y_MSB")) << 8; + datay |= CMR3000_READ(data, CMR3000_Y_LSB, "Y_LSB"); + dataz = (CMR3000_READ(data, CMR3000_Z_MSB, "Z_MSB")) << 8; + dataz |= CMR3000_READ(data, 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_accl_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 = CMR3000_SET(data, CMR3000_CTRL, ctrl, "Mode setting"); + if (ret < 0) + return -EIO; + + msleep(CMR3000_SETDELAY); + + return 0; +} + +static int cmr3000_poweroff(struct cmr3000_accl_data *data) +{ + int ret; + u8 ctrl = CMRMODE_POFF; + + ctrl |= data->bus_ops->ctrl_mod; + ctrl |= CMR3000_IRQDIS; + + ret = CMR3000_SET(data, CMR3000_CTRL, ctrl, "Mode setting"); + msleep(CMR3000_SETDELAY); + + return ret; +} + +static int cmr3000_reset(struct cmr3000_accl_data *data) +{ + int val; + + /* Reset chip */ + CMR3000_SET(data, CMR3000_CTRL, CMR3000_RST, "Reset"); + mdelay(2); + + /* Settling time delay */ + val = CMR3000_READ(data, 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_accl_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_accl_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_accl_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_accl_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); + +struct cmr3000_accl_data *cmr3000_init(struct device *dev, int irq, + const struct cmr3000_bus_ops *bops) +{ + const struct cmr3000_platform_data *pdata; + struct cmr3000_accl_data *data; + struct input_dev *input_dev; + int rev; + int error; + + if (!dev->platform_data) { + dev_info(dev, "platform data not found, using default\n"); + pdata = &cmr3000_default_pdata; + } else + pdata = dev->platform_data; + + 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; + goto err_out; + } + + data = kzalloc(sizeof(struct cmr3000_accl_data), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!data || !input_dev) { + error = -ENOMEM; + goto err_free_mem; + } + + data->dev = dev; + data->input_dev = input_dev; + data->bus_ops = bops; + data->pdata = pdata; + 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 = CMR3000_READ(data, 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); + + rev = CMR3000_READ(data, CMR3000_WHOAMI, "WhoamI"); + if (rev < 0) { + error = rev; + goto err_free_mem; + } + pr_info("CMR3000 Gyroscope: WhoamI %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_accl_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..604c7d4 --- /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: + * Hemanth V <hemanthv@ti.com> + * + * 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_accl_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_accl_data *cmr3000_init(struct device *dev, int irq, + const struct cmr3000_bus_ops *bops); +void cmr3000_exit(struct cmr3000_accl_data *); +void cmr3000_suspend(struct cmr3000_accl_data *); +void cmr3000_resume(struct cmr3000_accl_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..4ec139c --- /dev/null +++ b/drivers/input/misc/cmr3000_d0x_spi.c @@ -0,0 +1,178 @@ +/* + * Implements SPI interface for VTI CMR300_D0x Accelerometer driver + * + * Copyright (C) 2011 Qtechnology + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com> + * Based on: + * Hemanth V <hemanthv@ti.com> + * Michael Hennerich <hennerich@blackfin.uclinux.org> + * + * 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" + +enum { DO_READ = 0, DO_WRITE }; + +static int cmr3000_spi_cmd(struct spi_device *spi, u8 reg, u8 * val, int cmd, + char *msg) +{ + int ret; + unsigned char tx_buf[2]; + unsigned char rx_buf[2]; + struct spi_transfer t = { + .rx_buf = rx_buf, + .tx_buf = tx_buf, + .len = 2, + }; + struct spi_message m; + + if (cmd == DO_WRITE) { + tx_buf[0] = (reg << 2) | 2; + tx_buf[1] = *val; + } else { + tx_buf[0] = reg << 2; + tx_buf[1] = 0; + } + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(spi, &m); + if (ret < 0) { + dev_err(&spi->dev, "%s failed (%s, %d)\n", __func__, msg, ret); + return ret; + } + if (cmd == DO_READ) + *val = rx_buf[1]; + + if (rx_buf[0] & 0x41) + dev_err(&spi->dev, + "%s Invalid Zero mask(0x%x)\n", __func__, rx_buf[0]); + + if ((rx_buf[0] & 0x2) != 0x2) + dev_err(&spi->dev, + "%s Invalid One mask (0x%x)\n", __func__, rx_buf[0]); + + return 0; +} + +static int cmr3000_spi_set(struct device *dev, u8 reg, u8 val, char *msg) +{ + + struct spi_device *spi = to_spi_device(dev); + + return cmr3000_spi_cmd(spi, reg, &val, DO_WRITE, msg); +} + +static int cmr3000_spi_read(struct device *dev, u8 reg, char *msg) +{ + struct spi_device *spi = to_spi_device(dev); + int ret; + u8 val; + + ret = cmr3000_spi_cmd(spi, reg, &val, DO_READ, msg); + if (ret) + return ret; + return val; +} + +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_set, +}; + +static int __devinit cmr3000_spi_probe(struct spi_device *spi) +{ + struct cmr3000_accl_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_accl_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_accl_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_accl_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..0202100 --- /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> + * + * Copyright (C) 2010 Texas Instruments + * Author: Hemanth V <hemanthv@ti.com> + * + * 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_i2c_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] 17+ messages in thread
* Re: [PATCH 5/5] Input: add CMR3000 gyrsocope driver 2011-10-18 8:28 ` [PATCH 5/5] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado @ 2011-10-18 8:54 ` Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 8:54 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 09:28, 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. > Quick review done below. Quite a bit of overlap with earlier reviews. Sorry I couldn't take a closer look. > 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 | 400 ++++++++++++++++++++++++++++++++++ > drivers/input/misc/cmr3000_d0x.h | 45 ++++ > drivers/input/misc/cmr3000_d0x_spi.c | 178 +++++++++++++++ > include/linux/input/cmr3000.h | 54 +++++ > 6 files changed, 703 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..5ffe38b > --- /dev/null > +++ b/drivers/input/misc/cmr3000_d0x.c > @@ -0,0 +1,400 @@ > +/* > + * VTI CMR3000_D0x Gyroscope driver > + * > + * Copyright (C) 2011 Qtechnology > + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com> > + * > + * Based on: > + * Author: Hemanth V <hemanthv@ti.com> > + * > + * 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 "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 > + > +/* Delay for clearing interrupt in us */ > +#define CMR3000_INTDELAY 44 > + > +/* > + * 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, > + .irqflags = 0, > + .fuzz_x = 1, > + .fuzz_y = 1, > + .fuzz_z = 1, > +}; > + accl? I thought this was a gyro so this seems odd. > +struct cmr3000_accl_data { > + const struct cmr3000_bus_ops *bus_ops; > + const 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; > +}; > + I'd much rather see these done explicity in the code. This sort of macro just obscures the works to save a few lines of code. > +#define CMR3000_READ(data, reg, msg) \ > + (data->bus_ops->read(data->dev, reg, msg)) > +#define CMR3000_SET(data, reg, val, msg) \ > + ((data)->bus_ops->write(data->dev, reg, val, msg)) > + > +static void decode_dps(struct cmr3000_accl_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_accl_data *data = dev_id; > + int datax, datay, dataz; > + u8 mode, intr_status; > + > + intr_status = CMR3000_READ(data, CMR3000_STATUS, "interrupt status"); > + intr_status = CMR3000_READ(data, 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 = (CMR3000_READ(data, CMR3000_X_MSB, "X_MSB")) << 8; > + datax |= CMR3000_READ(data, CMR3000_X_LSB, "X_LSB"); > + datay = (CMR3000_READ(data, CMR3000_Y_MSB, "Y_MSB")) << 8; > + datay |= CMR3000_READ(data, CMR3000_Y_LSB, "Y_LSB"); > + dataz = (CMR3000_READ(data, CMR3000_Z_MSB, "Z_MSB")) << 8; > + dataz |= CMR3000_READ(data, CMR3000_Z_LSB, "Z_LSB"); > + Why are you checking this twice? > + /* 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_accl_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 = CMR3000_SET(data, CMR3000_CTRL, ctrl, "Mode setting"); > + if (ret < 0) > + return -EIO; > + > + msleep(CMR3000_SETDELAY); > + > + return 0; > +} > + > +static int cmr3000_poweroff(struct cmr3000_accl_data *data) > +{ > + int ret; > + u8 ctrl = CMRMODE_POFF; > + > + ctrl |= data->bus_ops->ctrl_mod; > + ctrl |= CMR3000_IRQDIS; No real reason not to do the above in one line. > + > + ret = CMR3000_SET(data, CMR3000_CTRL, ctrl, "Mode setting"); > + msleep(CMR3000_SETDELAY); > + > + return ret; > +} > + > +static int cmr3000_reset(struct cmr3000_accl_data *data) > +{ > + int val; > + > + /* Reset chip */ > + CMR3000_SET(data, CMR3000_CTRL, CMR3000_RST, "Reset"); > + mdelay(2); > + > + /* Settling time delay */ > + val = CMR3000_READ(data, 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_accl_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_accl_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_accl_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_accl_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); > + > +struct cmr3000_accl_data *cmr3000_init(struct device *dev, int irq, > + const struct cmr3000_bus_ops *bops) > +{ > + const struct cmr3000_platform_data *pdata; > + struct cmr3000_accl_data *data; > + struct input_dev *input_dev; > + int rev; > + int error; > + > + if (!dev->platform_data) { > + dev_info(dev, "platform data not found, using default\n"); > + pdata = &cmr3000_default_pdata; > + } else > + pdata = dev->platform_data; > + > + 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; > + goto err_out; > + } > + > + data = kzalloc(sizeof(struct cmr3000_accl_data), GFP_KERNEL); > + input_dev = input_allocate_device(); > + if (!data || !input_dev) { > + error = -ENOMEM; > + goto err_free_mem; > + } > + > + data->dev = dev; > + data->input_dev = input_dev; > + data->bus_ops = bops; > + data->pdata = pdata; > + 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 = CMR3000_READ(data, 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); > + > + rev = CMR3000_READ(data, CMR3000_WHOAMI, "WhoamI"); > + if (rev < 0) { > + error = rev; > + goto err_free_mem; > + } > + pr_info("CMR3000 Gyroscope: WhoamI %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_accl_data *data) > +{ > + free_irq(data->irq, data); > + input_unregister_device(data->input_dev); cleaner to unwind in reverse order of setup unless you have a good reason and that should be commented. > + 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..604c7d4 > --- /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: > + * Hemanth V <hemanthv@ti.com> > + * > + * 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_accl_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_accl_data *cmr3000_init(struct device *dev, int irq, > + const struct cmr3000_bus_ops *bops); > +void cmr3000_exit(struct cmr3000_accl_data *); > +void cmr3000_suspend(struct cmr3000_accl_data *); > +void cmr3000_resume(struct cmr3000_accl_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..4ec139c > --- /dev/null > +++ b/drivers/input/misc/cmr3000_d0x_spi.c > @@ -0,0 +1,178 @@ > +/* > + * Implements SPI interface for VTI CMR300_D0x Accelerometer driver > + * > + * Copyright (C) 2011 Qtechnology > + * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com.com> > + * Based on: > + * Hemanth V <hemanthv@ti.com> > + * Michael Hennerich <hennerich@blackfin.uclinux.org> > + * > + * 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" > + > +enum { DO_READ = 0, DO_WRITE }; > + > +static int cmr3000_spi_cmd(struct spi_device *spi, u8 reg, u8 * val, int cmd, > + char *msg) > +{ > + int ret; Same as with earlier patch on all counts in this function. > + unsigned char tx_buf[2]; > + unsigned char rx_buf[2]; > + struct spi_transfer t = { > + .rx_buf = rx_buf, > + .tx_buf = tx_buf, > + .len = 2, > + }; > + struct spi_message m; > + > + if (cmd == DO_WRITE) { > + tx_buf[0] = (reg << 2) | 2; > + tx_buf[1] = *val; > + } else { > + tx_buf[0] = reg << 2; > + tx_buf[1] = 0; > + } > + spi_message_init(&m); > + spi_message_add_tail(&t, &m); > + ret = spi_sync(spi, &m); > + if (ret < 0) { > + dev_err(&spi->dev, "%s failed (%s, %d)\n", __func__, msg, ret); > + return ret; > + } > + if (cmd == DO_READ) > + *val = rx_buf[1]; > + > + if (rx_buf[0] & 0x41) > + dev_err(&spi->dev, > + "%s Invalid Zero mask(0x%x)\n", __func__, rx_buf[0]); > + > + if ((rx_buf[0] & 0x2) != 0x2) > + dev_err(&spi->dev, > + "%s Invalid One mask (0x%x)\n", __func__, rx_buf[0]); > + > + return 0; > +} > + > +static int cmr3000_spi_set(struct device *dev, u8 reg, u8 val, char *msg) > +{ > + > + struct spi_device *spi = to_spi_device(dev); > + > + return cmr3000_spi_cmd(spi, reg, &val, DO_WRITE, msg); > +} > + > +static int cmr3000_spi_read(struct device *dev, u8 reg, char *msg) > +{ > + struct spi_device *spi = to_spi_device(dev); > + int ret; > + u8 val; > + > + ret = cmr3000_spi_cmd(spi, reg, &val, DO_READ, msg); > + if (ret) > + return ret; > + return val; > +} > + > +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_set, > +}; > + > +static int __devinit cmr3000_spi_probe(struct spi_device *spi) > +{ > + struct cmr3000_accl_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_accl_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_accl_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_accl_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..0202100 > --- /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> > + * > + * Copyright (C) 2010 Texas Instruments > + * Author: Hemanth V <hemanthv@ti.com> > + * > + * 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 > + > +/** Match comment to name fo structure. > + * struct cmr3000_i2c_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 ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Input: add CMR3000 gyrsocope driver 2011-10-18 8:54 ` Jonathan Cameron @ 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 0 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 12:07 UTC (permalink / raw) To: Jonathan Cameron Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel Hello Jonathan On Tue, Oct 18, 2011 at 10:54, Jonathan Cameron <jic23@cam.ac.uk> wrote: > On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: > Quick review done below. Quite a bit of overlap with earlier reviews. > Sorry I couldn't take a closer look. I am fixing also previous errors > accl? I thought this was a gyro so this seems odd. copy paste :), fixing it > I'd much rather see these done explicity in the code. > This sort of macro just obscures the works to save a few lines > of code. >> +#define CMR3000_READ(data, reg, msg) \ >> + (data->bus_ops->read(data->dev, reg, msg)) >> +#define CMR3000_SET(data, reg, val, msg) \ >> + ((data)->bus_ops->write(data->dev, reg, val, msg)) >> + Fixing it >> +void cmr3000_exit(struct cmr3000_accl_data *data) >> +{ >> + free_irq(data->irq, data); >> + input_unregister_device(data->input_dev); > cleaner to unwind in reverse order of setup unless you have > a good reason and that should be commented. Fixing it, and also fixing it on the cma3000 > Match comment to name fo structure. >> + * struct cmr3000_i2c_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; >> +}; Fixing it, and also fixing it on the cma3000 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] 17+ messages in thread
[parent not found: <1318926486-10330-2-git-send-email-ricardo.ribalda@gmail.com>]
* Re: [PATCH 1/5] input/cma3000_d0x: Support devices without pdata [not found] ` <1318926486-10330-2-git-send-email-ricardo.ribalda@gmail.com> @ 2011-10-18 8:32 ` Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 8:32 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: > Architechtures based on device-tree does not have platform data check your spelling. > associated to the spi/i2c devices. > This patch allows those architechtures to use the cma3000 driver with > a default configuration. > > Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > --- > drivers/input/misc/cma3000_d0x.c | 21 +++++++++++++++++++-- > 1 files changed, 19 insertions(+), 2 deletions(-) > > diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c > index 1633b63..2f993d5 100644 > --- a/drivers/input/misc/cma3000_d0x.c > +++ b/drivers/input/misc/cma3000_d0x.c > @@ -62,6 +62,18 @@ > #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, > +}; I'm not that familiar with DT yet, but surely there is a means to supplying the equivalent data? I'd prefer to see that provided here as well. > + > struct cma3000_accl_data { > const struct cma3000_bus_ops *bus_ops; > const struct cma3000_platform_data *pdata; > @@ -283,19 +295,24 @@ EXPORT_SYMBOL(cma3000_resume); > 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; > + const struct cma3000_platform_data *pdata; Leave this line alone.... > struct cma3000_accl_data *data; > struct input_dev *input_dev; > int rev; > int error; > > + if (!dev->platform_data) { > + dev_info(dev, "platform data not found, using default\n"); > + pdata = &cma3000_default_pdata; > + } else > + pdata = dev->platform_data; > + and this becomes if (pdata == NULL) { dev_info(dev, "platform data not found, using default\n"); pdata = &cma3000_default_pdata; } > if (!pdata) { > dev_err(dev, "platform data not found\n"); > error = -EINVAL; > goto err_out; > } This can't happen now so get rid of the test. > > - > /* if no IRQ return error */ > if (irq == 0) { > error = -EINVAL; ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] input/cma3000_d0x: Support devices without pdata 2011-10-18 8:32 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Jonathan Cameron @ 2011-10-18 12:07 ` Ricardo Ribalda Delgado 2011-10-18 12:51 ` Jonathan Cameron 0 siblings, 1 reply; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 12:07 UTC (permalink / raw) To: Jonathan Cameron Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel Hello Jonathan Thanks for your fast reply :) > I'm not that familiar with DT yet, but surely there is a means to supplying > the equivalent data? I'd prefer to see that provided here as well. If you check the file drivers/of/of_spi.c you can see that only reg, spi-cpha, spi-cpol, spi-cs-high, spi-max-freq and irq is imported straight from the DT, that is why I created the default configuration. I can give it a second thought, but I think it wont hurt to have a per-default configuration. >> + >> struct cma3000_accl_data { >> const struct cma3000_bus_ops *bus_ops; >> const struct cma3000_platform_data *pdata; >> @@ -283,19 +295,24 @@ EXPORT_SYMBOL(cma3000_resume); >> 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; >> + const struct cma3000_platform_data *pdata; > Leave this line alone.... >> struct cma3000_accl_data *data; >> struct input_dev *input_dev; >> int rev; >> int error; >> >> + if (!dev->platform_data) { >> + dev_info(dev, "platform data not found, using default\n"); >> + pdata = &cma3000_default_pdata; >> + } else >> + pdata = dev->platform_data; >> + > and this becomes > > if (pdata == NULL) { > dev_info(dev, "platform data not found, using default\n"); > pdata = &cma3000_default_pdata; > } > >> if (!pdata) { >> dev_err(dev, "platform data not found\n"); >> error = -EINVAL; >> goto err_out; >> } > This can't happen now so get rid of the test. >> >> - >> /* if no IRQ return error */ >> if (irq == 0) { >> error = -EINVAL; > > Ready on the new version of the patch. Thanks again -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] input/cma3000_d0x: Support devices without pdata 2011-10-18 12:07 ` Ricardo Ribalda Delgado @ 2011-10-18 12:51 ` Jonathan Cameron 0 siblings, 0 replies; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 12:51 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 13:07, Ricardo Ribalda Delgado wrote: > Hello Jonathan > > Thanks for your fast reply :) > >> I'm not that familiar with DT yet, but surely there is a means to supplying >> the equivalent data? I'd prefer to see that provided here as well. > > If you check the file drivers/of/of_spi.c you can see that only reg, > spi-cpha, spi-cpol, spi-cs-high, spi-max-freq and irq is imported > straight from the DT, that is why I created the default configuration. Sure, for spi, those are all that makes sense, but you ought to be able to use of_get_property to get to whatever else you need? See for example drivers/hwmon/ads1015.c which is an i2c device doing similar stuff. > > I can give it a second thought, but I think it wont hurt to have a > per-default configuration. Indeed, nothing wrong with having a default, but the fact that dt doesn't supply it isn't a good reason to state! > >>> + >>> struct cma3000_accl_data { >>> const struct cma3000_bus_ops *bus_ops; >>> const struct cma3000_platform_data *pdata; >>> @@ -283,19 +295,24 @@ EXPORT_SYMBOL(cma3000_resume); >>> 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; >>> + const struct cma3000_platform_data *pdata; >> Leave this line alone.... >>> struct cma3000_accl_data *data; >>> struct input_dev *input_dev; >>> int rev; >>> int error; >>> >>> + if (!dev->platform_data) { >>> + dev_info(dev, "platform data not found, using default\n"); >>> + pdata = &cma3000_default_pdata; >>> + } else >>> + pdata = dev->platform_data; >>> + >> and this becomes >> >> if (pdata == NULL) { >> dev_info(dev, "platform data not found, using default\n"); >> pdata = &cma3000_default_pdata; >> } >> >>> if (!pdata) { >>> dev_err(dev, "platform data not found\n"); >>> error = -EINVAL; >>> goto err_out; >>> } >> This can't happen now so get rid of the test. >>> >>> - >>> /* if no IRQ return error */ >>> if (irq == 0) { >>> error = -EINVAL; >> >> > > Ready on the new version of the patch. > > > Thanks again > > > ^ permalink raw reply [flat|nested] 17+ messages in thread
[parent not found: <1318926486-10330-3-git-send-email-ricardo.ribalda@gmail.com>]
* Re: [PATCH 2/5] input/cma3000_d0x: Check silicon version [not found] ` <1318926486-10330-3-git-send-email-ricardo.ribalda@gmail.com> @ 2011-10-18 8:34 ` Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 8:34 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: > Improve probing of the cma3000 chip, by checking the revision of the > device. > > Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > --- > drivers/input/misc/cma3000_d0x.c | 15 ++++++++++++++- > 1 files changed, 14 insertions(+), 1 deletions(-) > > diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c > index 2f993d5..9899742 100644 > --- a/drivers/input/misc/cma3000_d0x.c > +++ b/drivers/input/misc/cma3000_d0x.c > @@ -26,6 +26,8 @@ > > #include "cma3000_d0x.h" > > +#define CMA3000_REV 0x10 > + > #define CMA3000_WHOAMI 0x00 > #define CMA3000_REVID 0x01 > #define CMA3000_CTRL 0x02 > @@ -373,9 +375,20 @@ 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); warning perhaps rather than error? > + goto err_free_mem; > + } > pr_info("CMA3000 Accelerometer: Revision %x\n", rev); > > + rev = CMA3000_READ(data, CMA3000_WHOAMI, "WhoamI"); > + if (rev < 0) { > + error = rev; > + goto err_free_mem; > + } > + pr_info("CMA3000 Accelerometer: WhoamI %x\n", rev); > + Patch could do with a statement of why anyone would care about this. > error = request_threaded_irq(irq, NULL, cma3000_thread_irq, > pdata->irqflags | IRQF_ONESHOT, > "cma3000_d0x", data); ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/5] input/cma3000_d0x: Check silicon version 2011-10-18 8:34 ` [PATCH 2/5] input/cma3000_d0x: Check silicon version Jonathan Cameron @ 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 0 replies; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 12:07 UTC (permalink / raw) To: Jonathan Cameron Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel Hello Jonathan >> + if (rev != CMA3000_REV) { >> + error = -EINVAL; >> + pr_err("CMA3000 Accelerometer: Unknown Revision %x\n", rev); > warning perhaps rather than error? IMHO it should be an error. If the revision is different, either you are in front of a unknown chip or the chip is going to behave differently and lead into an unstable system. Better be safe than sorry. > Patch could do with a statement of why anyone would care about this. >> error = request_threaded_irq(irq, NULL, cma3000_thread_irq, >> pdata->irqflags | IRQF_ONESHOT, >> "cma3000_d0x", data); You are right... not so useful information :). Maybe as part of a sysfs file, but definately not as as a printk > > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 17+ messages in thread
[parent not found: <1318926486-10330-4-git-send-email-ricardo.ribalda@gmail.com>]
* Re: [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff [not found] ` <1318926486-10330-4-git-send-email-ricardo.ribalda@gmail.com> @ 2011-10-18 8:35 ` Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 8:35 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: > When the device goes to poweroff keep the spi/i2c configuration. > Otherwhise the device could not wake up if it was in spi mode. > Run checkpatch.pl over these > 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 9899742..15577b7 100644 > --- a/drivers/input/misc/cma3000_d0x.c > +++ b/drivers/input/misc/cma3000_d0x.c > @@ -44,6 +44,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) > > @@ -230,8 +231,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"); no space before comma. > msleep(CMA3000_SETDELAY); > > return ret; ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff 2011-10-18 8:35 ` [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff Jonathan Cameron @ 2011-10-18 12:07 ` Ricardo Ribalda Delgado 2011-10-18 12:45 ` Jonathan Cameron 0 siblings, 1 reply; 17+ messages in thread From: Ricardo Ribalda Delgado @ 2011-10-18 12:07 UTC (permalink / raw) To: Jonathan Cameron Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On Tue, Oct 18, 2011 at 10:35, Jonathan Cameron <jic23@cam.ac.uk> wrote: > On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: >> When the device goes to poweroff keep the spi/i2c configuration. >> Otherwhise the device could not wake up if it was in spi mode. >> > Run checkpatch.pl over these >> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> I did :( ricardo@newpili:~/hacking/linux$ scripts/checkpatch.pl cmr_patches/v1/0003-input-cma3000_d0x-Keep-configuration-on-poweroff.patch total: 0 errors, 0 warnings, 19 lines checked cmr_patches/v1/0003-input-cma3000_d0x-Keep-configuration-on-poweroff.patch has no obvious style problems and is ready for submission. But I fix that right away >> --- >> 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 9899742..15577b7 100644 >> --- a/drivers/input/misc/cma3000_d0x.c >> +++ b/drivers/input/misc/cma3000_d0x.c >> @@ -44,6 +44,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) >> >> @@ -230,8 +231,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"); > no space before comma. >> msleep(CMA3000_SETDELAY); >> >> return ret; > > -- Ricardo Ribalda ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff 2011-10-18 12:07 ` Ricardo Ribalda Delgado @ 2011-10-18 12:45 ` Jonathan Cameron 0 siblings, 0 replies; 17+ messages in thread From: Jonathan Cameron @ 2011-10-18 12:45 UTC (permalink / raw) To: Ricardo Ribalda Delgado Cc: dmitry.torokhov, sameo, peter.ujfalusi, aghayal, david, Shubhrajyoti, saaguirre, hemanthv, linux-input, linux-kernel On 10/18/11 13:07, Ricardo Ribalda Delgado wrote: > On Tue, Oct 18, 2011 at 10:35, Jonathan Cameron <jic23@cam.ac.uk> wrote: >> On 10/18/11 09:28, Ricardo Ribalda Delgado wrote: >>> When the device goes to poweroff keep the spi/i2c configuration. >>> Otherwhise the device could not wake up if it was in spi mode. >>> >> Run checkpatch.pl over these >>> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> > > I did :( > > ricardo@newpili:~/hacking/linux$ scripts/checkpatch.pl > cmr_patches/v1/0003-input-cma3000_d0x-Keep-configuration-on-poweroff.patch > total: 0 errors, 0 warnings, 19 lines checked > > cmr_patches/v1/0003-input-cma3000_d0x-Keep-configuration-on-poweroff.patch > has no obvious style problems and is ready for submission. > > But I fix that right away Curious. checkpatch seems to be getting more flexible... I just assumed it would pick those issues up! > > >>> --- >>> 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 9899742..15577b7 100644 >>> --- a/drivers/input/misc/cma3000_d0x.c >>> +++ b/drivers/input/misc/cma3000_d0x.c >>> @@ -44,6 +44,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) >>> >>> @@ -230,8 +231,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"); >> no space before comma. >>> msleep(CMA3000_SETDELAY); >>> >>> return ret; >> >> > > > ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-10-18 12:51 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-10-18 8:28 [PATCH 0/5] Add spi support for CMA3000 driver and new driver CMR3000 Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 2/5] input/cma3000_d0x: Check silicon version Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff Ricardo Ribalda Delgado 2011-10-18 8:28 ` [PATCH 4/5] input/cma3000_d0x: Add CMA3000 spi support Ricardo Ribalda Delgado 2011-10-18 8:44 ` Jonathan Cameron 2011-10-18 8:28 ` [PATCH 5/5] Input: add CMR3000 gyrsocope driver Ricardo Ribalda Delgado 2011-10-18 8:54 ` Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado [not found] ` <1318926486-10330-2-git-send-email-ricardo.ribalda@gmail.com> 2011-10-18 8:32 ` [PATCH 1/5] input/cma3000_d0x: Support devices without pdata Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 2011-10-18 12:51 ` Jonathan Cameron [not found] ` <1318926486-10330-3-git-send-email-ricardo.ribalda@gmail.com> 2011-10-18 8:34 ` [PATCH 2/5] input/cma3000_d0x: Check silicon version Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado [not found] ` <1318926486-10330-4-git-send-email-ricardo.ribalda@gmail.com> 2011-10-18 8:35 ` [PATCH 3/5] input/cma3000_d0x: Keep configuration on poweroff Jonathan Cameron 2011-10-18 12:07 ` Ricardo Ribalda Delgado 2011-10-18 12:45 ` Jonathan Cameron
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).