* [PATCH V2] Freescale MC13783 PMIC support
@ 2009-08-12 15:05 Sascha Hauer
2009-08-12 15:05 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-arm-kernel, Sascha Hauer
Hi,
This is the second version of the Freescale MC13783 PMIC support.
This series adds support for the Freescale MC13783 PMIC. The MC13783
is connected via SPI, the first patch adds basic support for it in
drivers/mfd. The rest of the patches can be applied independently.
Individual Maintainers are on Cc, the whole series can be found on
lkml and the Arm Linux Kernel mailing list.
Sascha
The following changes since commit ed680c4ad478d0fee9740f7d029087f181346564:
Linus Torvalds (1):
Linux 2.6.31-rc5
are available in the git repository at:
ssh://sha@pasiphae/git/sha/linux-2.6.git mc13783
Luotao Fu (1):
[hwmon] add Freescale MC13783 adc driver
Sascha Hauer (4):
drivers/mfd: Add Freescale MC13783 driver
[input] add mc13783 touchscreen driver
[RTC] Add Freescale MC13783 RTC driver
[regulator] Add a Freescale MC13783 regulator driver
drivers/hwmon/Kconfig | 6 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/mc13783-adc.c | 181 ++++++++++++++
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 222 +++++++++++++++++
drivers/mfd/Kconfig | 9 +
drivers/mfd/Makefile | 2 +
drivers/mfd/mc13783-core.c | 427 ++++++++++++++++++++++++++++++++
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mc13783.c | 410 ++++++++++++++++++++++++++++++
drivers/rtc/Kconfig | 6 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-mc13783.c | 135 ++++++++++
include/linux/mfd/mc13783-private.h | 396 +++++++++++++++++++++++++++++
include/linux/mfd/mc13783.h | 84 +++++++
17 files changed, 1902 insertions(+), 0 deletions(-)
create mode 100644 drivers/hwmon/mc13783-adc.c
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
create mode 100644 drivers/mfd/mc13783-core.c
create mode 100644 drivers/regulator/mc13783.c
create mode 100644 drivers/rtc/rtc-mc13783.c
create mode 100644 include/linux/mfd/mc13783-private.h
create mode 100644 include/linux/mfd/mc13783.h
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver
2009-08-12 15:05 [PATCH V2] Freescale MC13783 PMIC support Sascha Hauer
@ 2009-08-12 15:05 ` Sascha Hauer
2009-08-12 15:05 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Samuel Ortiz, Mark Brown, Liam Girdwood
This driver provides the core Freescale MC13783 support. It
registers the client platform_devices and provides access
to the A/D converter.
Changes since v1:
- use subsys_initcall instead of module_init
- honour origins of the code
- add MC13783 namespace to regulator defines
- use mfd_add_devices to register subdevices
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
---
drivers/mfd/Kconfig | 9 +
drivers/mfd/Makefile | 2 +
drivers/mfd/mc13783-core.c | 427 +++++++++++++++++++++++++++++++++++
include/linux/mfd/mc13783-private.h | 396 ++++++++++++++++++++++++++++++++
include/linux/mfd/mc13783.h | 84 +++++++
5 files changed, 918 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/mc13783-core.c
create mode 100644 include/linux/mfd/mc13783-private.h
create mode 100644 include/linux/mfd/mc13783.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 491ac0f..c4e1fb4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -228,6 +228,15 @@ config MFD_PCF50633
facilities, and registers devices for the various functions
so that function-specific drivers can bind to them.
+config MFD_MC13783
+ tristate "Support Freescale MC13783"
+ select MFD_CORE
+ help
+ Support for the Freescale (Atlas) MC13783 PMIC and audio CODEC.
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the
+ functionality of the device.
+
config PCF50633_ADC
tristate "Support for NXP PCF50633 ADC"
depends on MFD_PCF50633
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 6f8a9a1..7262822 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
+obj-$(CONFIG_MFD_MC13783) += mc13783-core.o
+
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c
new file mode 100644
index 0000000..1165fd0
--- /dev/null
+++ b/drivers/mfd/mc13783-core.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is in parts based on wm8350-core.c and pcf50633-core.c
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/spi/spi.h>
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+
+#define MC13783_MAX_REG_NUM 0x3f
+#define MC13783_FRAME_MASK 0x00ffffff
+#define MC13783_MAX_REG_NUM 0x3f
+#define MC13783_REG_NUM_SHIFT 0x19
+#define MC13783_WRITE_BIT_SHIFT 31
+
+static inline int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
+{
+ struct spi_transfer t = {
+ .tx_buf = (const void *)buf,
+ .rx_buf = buf,
+ .len = len,
+ .cs_change = 0,
+ .delay_usecs = 0,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ if (spi_sync(spi, &m) != 0 || m.status != 0)
+ return -EINVAL;
+ return len - m.actual_length;
+}
+
+static int mc13783_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val)
+{
+ unsigned int frame = 0;
+ int ret = 0;
+
+ if (reg_num > MC13783_MAX_REG_NUM)
+ return -EINVAL;
+
+ frame |= reg_num << MC13783_REG_NUM_SHIFT;
+
+ ret = spi_rw(mc13783->spi_device, (u8 *)&frame, 4);
+
+ *reg_val = frame & MC13783_FRAME_MASK;
+
+ return ret;
+}
+
+static int mc13783_write(struct mc13783 *mc13783, int reg_num, u32 reg_val)
+{
+ unsigned int frame = 0;
+
+ if (reg_num > MC13783_MAX_REG_NUM)
+ return -EINVAL;
+
+ frame |= (1 << MC13783_WRITE_BIT_SHIFT);
+ frame |= reg_num << MC13783_REG_NUM_SHIFT;
+ frame |= reg_val & MC13783_FRAME_MASK;
+
+ return spi_rw(mc13783->spi_device, (u8 *)&frame, 4);
+}
+
+int mc13783_reg_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val)
+{
+ int ret;
+
+ mutex_lock(&mc13783->io_lock);
+ ret = mc13783_read(mc13783, reg_num, reg_val);
+ mutex_unlock(&mc13783->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc13783_reg_read);
+
+int mc13783_reg_write(struct mc13783 *mc13783, int reg_num, u32 reg_val)
+{
+ int ret;
+
+ mutex_lock(&mc13783->io_lock);
+ ret = mc13783_write(mc13783, reg_num, reg_val);
+ mutex_unlock(&mc13783->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc13783_reg_write);
+
+/**
+ * mc13783_set_bits - Bitmask write
+ *
+ * @mc13783: Pointer to mc13783 control structure
+ * @reg: Register to access
+ * @mask: Mask of bits to change
+ * @val: Value to set for masked bits
+ */
+int mc13783_set_bits(struct mc13783 *mc13783, int reg, u32 mask, u32 val)
+{
+ u32 tmp;
+ int ret;
+
+ mutex_lock(&mc13783->io_lock);
+
+ ret = mc13783_read(mc13783, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+ if (ret == 0)
+ ret = mc13783_write(mc13783, reg, tmp);
+
+ mutex_unlock(&mc13783->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc13783_set_bits);
+
+int mc13783_register_irq(struct mc13783 *mc13783, int irq,
+ void (*handler) (int, void *), void *data)
+{
+ if (irq < 0 || irq > MC13783_NUM_IRQ || !handler)
+ return -EINVAL;
+
+ if (WARN_ON(mc13783->irq_handler[irq].handler))
+ return -EBUSY;
+
+ mutex_lock(&mc13783->io_lock);
+ mc13783->irq_handler[irq].handler = handler;
+ mc13783->irq_handler[irq].data = data;
+ mutex_unlock(&mc13783->io_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mc13783_register_irq);
+
+int mc13783_free_irq(struct mc13783 *mc13783, int irq)
+{
+ if (irq < 0 || irq > MC13783_NUM_IRQ)
+ return -EINVAL;
+
+ mutex_lock(&mc13783->io_lock);
+ mc13783->irq_handler[irq].handler = NULL;
+ mutex_unlock(&mc13783->io_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mc13783_free_irq);
+
+static void mc13783_irq_work(struct work_struct *work)
+{
+ struct mc13783 *mc13783 = container_of(work, struct mc13783, work);
+ int i;
+ unsigned int adc_sts;
+
+ /* check if the adc has finished any completion */
+ mc13783_reg_read(mc13783, MC13783_REG_INTERRUPT_STATUS_0, &adc_sts);
+ mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0,
+ adc_sts & MC13783_INT_STAT_ADCDONEI);
+
+ if (adc_sts & MC13783_INT_STAT_ADCDONEI)
+ complete_all(&mc13783->adc_done);
+
+ for (i = 0; i < MC13783_NUM_IRQ; i++)
+ if (mc13783->irq_handler[i].handler)
+ mc13783->irq_handler[i].handler(i,
+ mc13783->irq_handler[i].data);
+ enable_irq(mc13783->irq);
+}
+
+static irqreturn_t mc13783_interrupt(int irq, void *dev_id)
+{
+ struct mc13783 *mc13783 = dev_id;
+
+ disable_irq_nosync(irq);
+
+ schedule_work(&mc13783->work);
+ return IRQ_HANDLED;
+}
+
+/* set adc to ts interrupt mode, which generates touchscreen wakeup interrupt */
+static inline void mc13783_adc_set_ts_irq_mode(struct mc13783 *mc13783)
+{
+ unsigned int reg_adc0, reg_adc1;
+
+ reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0;
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN;
+
+ mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1);
+}
+
+int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
+ unsigned int channel, unsigned int *sample)
+{
+ unsigned int reg_adc0, reg_adc1;
+ int i;
+
+ mutex_lock(&mc13783->adc_conv_lock);
+
+ /* set up auto incrementing anyway to make quick read */
+ reg_adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
+ /* enable the adc, ignore external triggering and set ASC to trigger
+ * conversion */
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN
+ | MC13783_ADC1_ASC;
+
+ /* setup channel number */
+ if (channel > 7)
+ reg_adc1 |= MC13783_ADC1_ADSEL;
+
+ switch (mode) {
+ case MC13783_ADC_MODE_TS:
+ /* enables touch screen reference mode and set touchscreen mode
+ * to position mode */
+ reg_adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1;
+ reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+ break;
+ case MC13783_ADC_MODE_SINGLE_CHAN:
+ reg_adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT;
+ reg_adc1 |= MC13783_ADC1_RAND;
+ break;
+ case MC13783_ADC_MODE_MULT_CHAN:
+ reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1);
+
+ wait_for_completion_interruptible(&mc13783->adc_done);
+
+ for (i = 0; i < 4; i++)
+ mc13783_reg_read(mc13783, MC13783_REG_ADC_2, &sample[i]);
+
+ if (mc13783->ts_active)
+ mc13783_adc_set_ts_irq_mode(mc13783);
+
+ mutex_unlock(&mc13783->adc_conv_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
+
+void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status)
+{
+ mc13783->ts_active = status;
+}
+EXPORT_SYMBOL_GPL(mc13783_adc_set_ts_status);
+
+static int mc13783_check_revision(struct mc13783 *mc13783)
+{
+ u32 rev_id, rev1, rev2, finid, icid;
+
+ mc13783_read(mc13783, MC13783_REG_REVISION, &rev_id);
+
+ rev1 = (rev_id & 0x018) >> 3;
+ rev2 = (rev_id & 0x007);
+ icid = (rev_id & 0x01C0) >> 6;
+ finid = (rev_id & 0x01E00) >> 9;
+
+ /* Ver 0.2 is actually 3.2a. Report as 3.2 */
+ if ((rev1 == 0) && (rev2 == 2))
+ rev1 = 3;
+
+ if (rev1 == 0 || icid != 2) {
+ dev_err(mc13783->dev, "No MC13783 detected.\n");
+ return -ENODEV;
+ }
+
+ mc13783->revision = ((rev1 * 10) + rev2);
+ dev_info(mc13783->dev, "MC13783 Rev %d.%d FinVer %x detected\n", rev1,
+ rev2, finid);
+
+ return 0;
+}
+
+/*
+ * Register a client device. This is non-fatal since there is no need to
+ * fail the entire device init due to a single platform device failing.
+ */
+static void mc13783_client_dev_register(struct mc13783 *mc13783,
+ const char *name)
+{
+ struct mfd_cell cell = {};
+
+ cell.name = name;
+
+ mfd_add_devices(mc13783->dev, -1, &cell, 1, NULL, 0);
+}
+
+static int __devinit mc13783_probe(struct spi_device *spi)
+{
+ struct mc13783 *mc13783;
+ struct mc13783_platform_data *pdata = spi->dev.platform_data;
+ int ret;
+
+ mc13783 = kzalloc(sizeof(struct mc13783), GFP_KERNEL);
+ if (!mc13783)
+ return -ENOMEM;
+
+ dev_set_drvdata(&spi->dev, mc13783);
+ spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
+ spi->bits_per_word = 32;
+ spi_setup(spi);
+
+ mc13783->spi_device = spi;
+ mc13783->dev = &spi->dev;
+ mc13783->irq = spi->irq;
+
+ INIT_WORK(&mc13783->work, mc13783_irq_work);
+ mutex_init(&mc13783->io_lock);
+ mutex_init(&mc13783->adc_conv_lock);
+ init_completion(&mc13783->adc_done);
+
+ if (pdata) {
+ mc13783->flags = pdata->flags;
+ mc13783->regulators = pdata->regulators;
+ mc13783->num_regulators = pdata->num_regulators;
+ }
+
+ if (mc13783_check_revision(mc13783)) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ /* clear and mask all interrupts */
+ mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, 0x00ffffff);
+ mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_0, 0x00ffffff);
+ mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_1, 0x00ffffff);
+ mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_1, 0x00ffffff);
+
+ /* unmask adcdone interrupts */
+ mc13783_set_bits(mc13783, MC13783_REG_INTERRUPT_MASK_0,
+ MC13783_INT_MASK_ADCDONEM, 0);
+
+ ret = request_irq(mc13783->irq, mc13783_interrupt,
+ IRQF_DISABLED | IRQF_TRIGGER_HIGH, "mc13783",
+ mc13783);
+ if (ret)
+ goto err_out;
+
+ if (mc13783->flags & MC13783_USE_CODEC)
+ mc13783_client_dev_register(mc13783, "mc13783-codec");
+ if (mc13783->flags & MC13783_USE_ADC)
+ mc13783_client_dev_register(mc13783, "mc13783-adc");
+ if (mc13783->flags & MC13783_USE_RTC)
+ mc13783_client_dev_register(mc13783, "mc13783-rtc");
+ if (mc13783->flags & MC13783_USE_REGULATOR)
+ mc13783_client_dev_register(mc13783, "mc13783-regulator");
+ if (mc13783->flags & MC13783_USE_TOUCHSCREEN)
+ mc13783_client_dev_register(mc13783, "mc13783-ts");
+
+ return 0;
+
+err_out:
+ kfree(mc13783);
+ return ret;
+}
+
+static int __devexit mc13783_remove(struct spi_device *spi)
+{
+ struct mc13783 *mc13783;
+
+ mc13783 = dev_get_drvdata(&spi->dev);
+
+ free_irq(mc13783->irq, mc13783);
+
+ mfd_remove_devices(&spi->dev);
+
+ return 0;
+}
+
+static struct spi_driver pmic_driver = {
+ .driver = {
+ .name = "mc13783",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = mc13783_probe,
+ .remove = __devexit_p(mc13783_remove),
+};
+
+static int __init pmic_init(void)
+{
+ return spi_register_driver(&pmic_driver);
+}
+subsys_initcall(pmic_init);
+
+static void __exit pmic_exit(void)
+{
+ spi_unregister_driver(&pmic_driver);
+}
+module_exit(pmic_exit);
+
+MODULE_DESCRIPTION("Core/Protocol driver for Freescale MC13783 PMIC");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
+
diff --git a/include/linux/mfd/mc13783-private.h b/include/linux/mfd/mc13783-private.h
new file mode 100644
index 0000000..47e698c
--- /dev/null
+++ b/include/linux/mfd/mc13783-private.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_MFD_MC13783_PRIV_H
+#define __LINUX_MFD_MC13783_PRIV_H
+
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+struct mc13783_irq {
+ void (*handler)(int, void *);
+ void *data;
+};
+
+#define MC13783_NUM_IRQ 2
+#define MC13783_IRQ_TS 0
+#define MC13783_IRQ_REGULATOR 1
+
+#define MC13783_ADC_MODE_TS 1
+#define MC13783_ADC_MODE_SINGLE_CHAN 2
+#define MC13783_ADC_MODE_MULT_CHAN 3
+
+struct mc13783 {
+ int revision;
+ struct device *dev;
+ struct spi_device *spi_device;
+
+ int (*read_dev)(void *data, char reg, int count, u32 *dst);
+ int (*write_dev)(void *data, char reg, int count, const u32 *src);
+
+ struct mutex io_lock;
+ void *io_data;
+ int irq;
+ unsigned int flags;
+
+ struct mc13783_irq irq_handler[MC13783_NUM_IRQ];
+ struct work_struct work;
+ struct completion adc_done;
+ unsigned int ts_active;
+ struct mutex adc_conv_lock;
+
+ struct mc13783_regulator_init_data *regulators;
+ int num_regulators;
+};
+
+int mc13783_reg_read(struct mc13783 *, int reg_num, u32 *);
+int mc13783_reg_write(struct mc13783 *, int, u32);
+int mc13783_set_bits(struct mc13783 *, int, u32, u32);
+int mc13783_free_irq(struct mc13783 *mc13783, int irq);
+int mc13783_register_irq(struct mc13783 *mc13783, int irq,
+ void (*handler) (int, void *), void *data);
+
+#define MC13783_REG_INTERRUPT_STATUS_0 0
+#define MC13783_REG_INTERRUPT_MASK_0 1
+#define MC13783_REG_INTERRUPT_SENSE_0 2
+#define MC13783_REG_INTERRUPT_STATUS_1 3
+#define MC13783_REG_INTERRUPT_MASK_1 4
+#define MC13783_REG_INTERRUPT_SENSE_1 5
+#define MC13783_REG_POWER_UP_MODE_SENSE 6
+#define MC13783_REG_REVISION 7
+#define MC13783_REG_SEMAPHORE 8
+#define MC13783_REG_ARBITRATION_PERIPHERAL_AUDIO 9
+#define MC13783_REG_ARBITRATION_SWITCHERS 10
+#define MC13783_REG_ARBITRATION_REGULATORS_0 11
+#define MC13783_REG_ARBITRATION_REGULATORS_1 12
+#define MC13783_REG_POWER_CONTROL_0 13
+#define MC13783_REG_POWER_CONTROL_1 14
+#define MC13783_REG_POWER_CONTROL_2 15
+#define MC13783_REG_REGEN_ASSIGNMENT 16
+#define MC13783_REG_CONTROL_SPARE 17
+#define MC13783_REG_MEMORY_A 18
+#define MC13783_REG_MEMORY_B 19
+#define MC13783_REG_RTC_TIME 20
+#define MC13783_REG_RTC_ALARM 21
+#define MC13783_REG_RTC_DAY 22
+#define MC13783_REG_RTC_DAY_ALARM 23
+#define MC13783_REG_SWITCHERS_0 24
+#define MC13783_REG_SWITCHERS_1 25
+#define MC13783_REG_SWITCHERS_2 26
+#define MC13783_REG_SWITCHERS_3 27
+#define MC13783_REG_SWITCHERS_4 28
+#define MC13783_REG_SWITCHERS_5 29
+#define MC13783_REG_REGULATOR_SETTING_0 30
+#define MC13783_REG_REGULATOR_SETTING_1 31
+#define MC13783_REG_REGULATOR_MODE_0 32
+#define MC13783_REG_REGULATOR_MODE_1 33
+#define MC13783_REG_POWER_MISCELLANEOUS 34
+#define MC13783_REG_POWER_SPARE 35
+#define MC13783_REG_AUDIO_RX_0 36
+#define MC13783_REG_AUDIO_RX_1 37
+#define MC13783_REG_AUDIO_TX 38
+#define MC13783_REG_AUDIO_SSI_NETWORK 39
+#define MC13783_REG_AUDIO_CODEC 40
+#define MC13783_REG_AUDIO_STEREO_DAC 41
+#define MC13783_REG_AUDIO_SPARE 42
+#define MC13783_REG_ADC_0 43
+#define MC13783_REG_ADC_1 44
+#define MC13783_REG_ADC_2 45
+#define MC13783_REG_ADC_3 46
+#define MC13783_REG_ADC_4 47
+#define MC13783_REG_CHARGER 48
+#define MC13783_REG_USB 49
+#define MC13783_REG_CHARGE_USB_SPARE 50
+#define MC13783_REG_LED_CONTROL_0 51
+#define MC13783_REG_LED_CONTROL_1 52
+#define MC13783_REG_LED_CONTROL_2 53
+#define MC13783_REG_LED_CONTROL_3 54
+#define MC13783_REG_LED_CONTROL_4 55
+#define MC13783_REG_LED_CONTROL_5 56
+#define MC13783_REG_SPARE 57
+#define MC13783_REG_TRIM_0 58
+#define MC13783_REG_TRIM_1 59
+#define MC13783_REG_TEST_0 60
+#define MC13783_REG_TEST_1 61
+#define MC13783_REG_TEST_2 62
+#define MC13783_REG_TEST_3 63
+#define MC13783_REG_NB 64
+
+
+/*
+ * Interrupt Status
+ */
+#define MC13783_INT_STAT_ADCDONEI (1 << 0)
+#define MC13783_INT_STAT_ADCBISDONEI (1 << 1)
+#define MC13783_INT_STAT_TSI (1 << 2)
+#define MC13783_INT_STAT_WHIGHI (1 << 3)
+#define MC13783_INT_STAT_WLOWI (1 << 4)
+#define MC13783_INT_STAT_CHGDETI (1 << 6)
+#define MC13783_INT_STAT_CHGOVI (1 << 7)
+#define MC13783_INT_STAT_CHGREVI (1 << 8)
+#define MC13783_INT_STAT_CHGSHORTI (1 << 9)
+#define MC13783_INT_STAT_CCCVI (1 << 10)
+#define MC13783_INT_STAT_CHGCURRI (1 << 11)
+#define MC13783_INT_STAT_BPONI (1 << 12)
+#define MC13783_INT_STAT_LOBATLI (1 << 13)
+#define MC13783_INT_STAT_LOBATHI (1 << 14)
+#define MC13783_INT_STAT_UDPI (1 << 15)
+#define MC13783_INT_STAT_USBI (1 << 16)
+#define MC13783_INT_STAT_IDI (1 << 19)
+#define MC13783_INT_STAT_Unused (1 << 20)
+#define MC13783_INT_STAT_SE1I (1 << 21)
+#define MC13783_INT_STAT_CKDETI (1 << 22)
+#define MC13783_INT_STAT_UDMI (1 << 23)
+
+/*
+ * Interrupt Mask
+ */
+#define MC13783_INT_MASK_ADCDONEM (1 << 0)
+#define MC13783_INT_MASK_ADCBISDONEM (1 << 1)
+#define MC13783_INT_MASK_TSM (1 << 2)
+#define MC13783_INT_MASK_WHIGHM (1 << 3)
+#define MC13783_INT_MASK_WLOWM (1 << 4)
+#define MC13783_INT_MASK_CHGDETM (1 << 6)
+#define MC13783_INT_MASK_CHGOVM (1 << 7)
+#define MC13783_INT_MASK_CHGREVM (1 << 8)
+#define MC13783_INT_MASK_CHGSHORTM (1 << 9)
+#define MC13783_INT_MASK_CCCVM (1 << 10)
+#define MC13783_INT_MASK_CHGCURRM (1 << 11)
+#define MC13783_INT_MASK_BPONM (1 << 12)
+#define MC13783_INT_MASK_LOBATLM (1 << 13)
+#define MC13783_INT_MASK_LOBATHM (1 << 14)
+#define MC13783_INT_MASK_UDPM (1 << 15)
+#define MC13783_INT_MASK_USBM (1 << 16)
+#define MC13783_INT_MASK_IDM (1 << 19)
+#define MC13783_INT_MASK_SE1M (1 << 21)
+#define MC13783_INT_MASK_CKDETM (1 << 22)
+
+/*
+ * Reg Regulator Mode 0
+ */
+#define MC13783_REGCTRL_VAUDIO_EN (1 << 0)
+#define MC13783_REGCTRL_VAUDIO_STBY (1 << 1)
+#define MC13783_REGCTRL_VAUDIO_MODE (1 << 2)
+#define MC13783_REGCTRL_VIOHI_EN (1 << 3)
+#define MC13783_REGCTRL_VIOHI_STBY (1 << 4)
+#define MC13783_REGCTRL_VIOHI_MODE (1 << 5)
+#define MC13783_REGCTRL_VIOLO_EN (1 << 6)
+#define MC13783_REGCTRL_VIOLO_STBY (1 << 7)
+#define MC13783_REGCTRL_VIOLO_MODE (1 << 8)
+#define MC13783_REGCTRL_VDIG_EN (1 << 9)
+#define MC13783_REGCTRL_VDIG_STBY (1 << 10)
+#define MC13783_REGCTRL_VDIG_MODE (1 << 11)
+#define MC13783_REGCTRL_VGEN_EN (1 << 12)
+#define MC13783_REGCTRL_VGEN_STBY (1 << 13)
+#define MC13783_REGCTRL_VGEN_MODE (1 << 14)
+#define MC13783_REGCTRL_VRFDIG_EN (1 << 15)
+#define MC13783_REGCTRL_VRFDIG_STBY (1 << 16)
+#define MC13783_REGCTRL_VRFDIG_MODE (1 << 17)
+#define MC13783_REGCTRL_VRFREF_EN (1 << 18)
+#define MC13783_REGCTRL_VRFREF_STBY (1 << 19)
+#define MC13783_REGCTRL_VRFREF_MODE (1 << 20)
+#define MC13783_REGCTRL_VRFCP_EN (1 << 21)
+#define MC13783_REGCTRL_VRFCP_STBY (1 << 22)
+#define MC13783_REGCTRL_VRFCP_MODE (1 << 23)
+
+/*
+ * Reg Regulator Mode 1
+ */
+#define MC13783_REGCTRL_VSIM_EN (1 << 0)
+#define MC13783_REGCTRL_VSIM_STBY (1 << 1)
+#define MC13783_REGCTRL_VSIM_MODE (1 << 2)
+#define MC13783_REGCTRL_VESIM_EN (1 << 3)
+#define MC13783_REGCTRL_VESIM_STBY (1 << 4)
+#define MC13783_REGCTRL_VESIM_MODE (1 << 5)
+#define MC13783_REGCTRL_VCAM_EN (1 << 6)
+#define MC13783_REGCTRL_VCAM_STBY (1 << 7)
+#define MC13783_REGCTRL_VCAM_MODE (1 << 8)
+#define MC13783_REGCTRL_VRFBG_EN (1 << 9)
+#define MC13783_REGCTRL_VRFBG_STBY (1 << 10)
+#define MC13783_REGCTRL_VVIB_EN (1 << 11)
+#define MC13783_REGCTRL_VRF1_EN (1 << 12)
+#define MC13783_REGCTRL_VRF1_STBY (1 << 13)
+#define MC13783_REGCTRL_VRF1_MODE (1 << 14)
+#define MC13783_REGCTRL_VRF2_EN (1 << 15)
+#define MC13783_REGCTRL_VRF2_STBY (1 << 16)
+#define MC13783_REGCTRL_VRF2_MODE (1 << 17)
+#define MC13783_REGCTRL_VMMC1_EN (1 << 18)
+#define MC13783_REGCTRL_VMMC1_STBY (1 << 19)
+#define MC13783_REGCTRL_VMMC1_MODE (1 << 20)
+#define MC13783_REGCTRL_VMMC2_EN (1 << 21)
+#define MC13783_REGCTRL_VMMC2_STBY (1 << 22)
+#define MC13783_REGCTRL_VMMC2_MODE (1 << 23)
+
+/*
+ * Reg Regulator Misc.
+ */
+#define MC13783_REGCTRL_GPO1_EN (1 << 6)
+#define MC13783_REGCTRL_GPO2_EN (1 << 8)
+#define MC13783_REGCTRL_GPO3_EN (1 << 10)
+#define MC13783_REGCTRL_GPO4_EN (1 << 12)
+#define MC13783_REGCTRL_VIBPINCTRL (1 << 14)
+
+/*
+ * Reg Switcher 4
+ */
+#define MC13783_SWCTRL_SW1A_MODE (1 << 0)
+#define MC13783_SWCTRL_SW1A_STBY_MODE (1 << 2)
+#define MC13783_SWCTRL_SW1A_DVS_SPEED (1 << 6)
+#define MC13783_SWCTRL_SW1A_PANIC_MODE (1 << 8)
+#define MC13783_SWCTRL_SW1A_SOFTSTART (1 << 9)
+#define MC13783_SWCTRL_SW1B_MODE (1 << 10)
+#define MC13783_SWCTRL_SW1B_STBY_MODE (1 << 12)
+#define MC13783_SWCTRL_SW1B_DVS_SPEED (1 << 14)
+#define MC13783_SWCTRL_SW1B_PANIC_MODE (1 << 16)
+#define MC13783_SWCTRL_SW1B_SOFTSTART (1 << 17)
+#define MC13783_SWCTRL_PLL_EN (1 << 18)
+#define MC13783_SWCTRL_PLL_FACTOR (1 << 19)
+
+/*
+ * Reg Switcher 5
+ */
+#define MC13783_SWCTRL_SW2A_MODE (1 << 0)
+#define MC13783_SWCTRL_SW2A_STBY_MODE (1 << 2)
+#define MC13783_SWCTRL_SW2A_DVS_SPEED (1 << 6)
+#define MC13783_SWCTRL_SW2A_PANIC_MODE (1 << 8)
+#define MC13783_SWCTRL_SW2A_SOFTSTART (1 << 9)
+#define MC13783_SWCTRL_SW2B_MODE (1 << 10)
+#define MC13783_SWCTRL_SW2B_STBY_MODE (1 << 12)
+#define MC13783_SWCTRL_SW2B_DVS_SPEED (1 << 14)
+#define MC13783_SWCTRL_SW2B_PANIC_MODE (1 << 16)
+#define MC13783_SWCTRL_SW2B_SOFTSTART (1 << 17)
+#define MC13783_SWSET_SW3 (1 << 18)
+#define MC13783_SWCTRL_SW3_EN (1 << 20)
+#define MC13783_SWCTRL_SW3_STBY (1 << 21)
+#define MC13783_SWCTRL_SW3_MODE (1 << 22)
+
+/*
+ * ADC/Touch
+ */
+#define MC13783_ADC0_LICELLCON (1 << 0)
+#define MC13783_ADC0_CHRGICON (1 << 1)
+#define MC13783_ADC0_BATICON (1 << 2)
+#define MC13783_ADC0_RTHEN (1 << 3)
+#define MC13783_ADC0_DTHEN (1 << 4)
+#define MC13783_ADC0_UIDEN (1 << 5)
+#define MC13783_ADC0_ADOUTEN (1 << 6)
+#define MC13783_ADC0_ADOUTPER (1 << 7)
+#define MC13783_ADC0_ADREFEN (1 << 10)
+#define MC13783_ADC0_ADREFMODE (1 << 11)
+#define MC13783_ADC0_TSMOD0 (1 << 12)
+#define MC13783_ADC0_TSMOD1 (1 << 13)
+#define MC13783_ADC0_TSMOD2 (1 << 14)
+#define MC13783_ADC0_CHRGRAWDIV (1 << 15)
+#define MC13783_ADC0_ADINC1 (1 << 16)
+#define MC13783_ADC0_ADINC2 (1 << 17)
+#define MC13783_ADC0_WCOMP (1 << 18)
+#define MC13783_ADC0_ADCBIS0 (1 << 23)
+
+#define MC13783_ADC1_ADEN (1 << 0)
+#define MC13783_ADC1_RAND (1 << 1)
+#define MC13783_ADC1_ADSEL (1 << 3)
+#define MC13783_ADC1_TRIGMASK (1 << 4)
+#define MC13783_ADC1_ADA10 (1 << 5)
+#define MC13783_ADC1_ADA11 (1 << 6)
+#define MC13783_ADC1_ADA12 (1 << 7)
+#define MC13783_ADC1_ADA20 (1 << 8)
+#define MC13783_ADC1_ADA21 (1 << 9)
+#define MC13783_ADC1_ADA22 (1 << 10)
+#define MC13783_ADC1_ATO0 (1 << 11)
+#define MC13783_ADC1_ATO1 (1 << 12)
+#define MC13783_ADC1_ATO2 (1 << 13)
+#define MC13783_ADC1_ATO3 (1 << 14)
+#define MC13783_ADC1_ATO4 (1 << 15)
+#define MC13783_ADC1_ATO5 (1 << 16)
+#define MC13783_ADC1_ATO6 (1 << 17)
+#define MC13783_ADC1_ATO7 (1 << 18)
+#define MC13783_ADC1_ATOX (1 << 19)
+#define MC13783_ADC1_ASC (1 << 20)
+#define MC13783_ADC1_ADTRIGIGN (1 << 21)
+#define MC13783_ADC1_ADONESHOT (1 << 22)
+#define MC13783_ADC1_ADCBIS1 (1 << 23)
+
+#define MC13783_ADC1_CHAN0_SHIFT 5
+#define MC13783_ADC1_CHAN1_SHIFT 8
+
+#define MC13783_ADC2_ADD10 (1 << 2)
+#define MC13783_ADC2_ADD11 (1 << 3)
+#define MC13783_ADC2_ADD12 (1 << 4)
+#define MC13783_ADC2_ADD13 (1 << 5)
+#define MC13783_ADC2_ADD14 (1 << 6)
+#define MC13783_ADC2_ADD15 (1 << 7)
+#define MC13783_ADC2_ADD16 (1 << 8)
+#define MC13783_ADC2_ADD17 (1 << 9)
+#define MC13783_ADC2_ADD18 (1 << 10)
+#define MC13783_ADC2_ADD19 (1 << 11)
+#define MC13783_ADC2_ADD20 (1 << 14)
+#define MC13783_ADC2_ADD21 (1 << 15)
+#define MC13783_ADC2_ADD22 (1 << 16)
+#define MC13783_ADC2_ADD23 (1 << 17)
+#define MC13783_ADC2_ADD24 (1 << 18)
+#define MC13783_ADC2_ADD25 (1 << 19)
+#define MC13783_ADC2_ADD26 (1 << 20)
+#define MC13783_ADC2_ADD27 (1 << 21)
+#define MC13783_ADC2_ADD28 (1 << 22)
+#define MC13783_ADC2_ADD29 (1 << 23)
+
+#define MC13783_ADC3_WHIGH0 (1 << 0)
+#define MC13783_ADC3_WHIGH1 (1 << 1)
+#define MC13783_ADC3_WHIGH2 (1 << 2)
+#define MC13783_ADC3_WHIGH3 (1 << 3)
+#define MC13783_ADC3_WHIGH4 (1 << 4)
+#define MC13783_ADC3_WHIGH5 (1 << 5)
+#define MC13783_ADC3_ICID0 (1 << 6)
+#define MC13783_ADC3_ICID1 (1 << 7)
+#define MC13783_ADC3_ICID2 (1 << 8)
+#define MC13783_ADC3_WLOW0 (1 << 9)
+#define MC13783_ADC3_WLOW1 (1 << 10)
+#define MC13783_ADC3_WLOW2 (1 << 11)
+#define MC13783_ADC3_WLOW3 (1 << 12)
+#define MC13783_ADC3_WLOW4 (1 << 13)
+#define MC13783_ADC3_WLOW5 (1 << 14)
+#define MC13783_ADC3_ADCBIS2 (1 << 23)
+
+#define MC13783_ADC4_ADDBIS10 (1 << 2)
+#define MC13783_ADC4_ADDBIS11 (1 << 3)
+#define MC13783_ADC4_ADDBIS12 (1 << 4)
+#define MC13783_ADC4_ADDBIS13 (1 << 5)
+#define MC13783_ADC4_ADDBIS14 (1 << 6)
+#define MC13783_ADC4_ADDBIS15 (1 << 7)
+#define MC13783_ADC4_ADDBIS16 (1 << 8)
+#define MC13783_ADC4_ADDBIS17 (1 << 9)
+#define MC13783_ADC4_ADDBIS18 (1 << 10)
+#define MC13783_ADC4_ADDBIS19 (1 << 11)
+#define MC13783_ADC4_ADDBIS20 (1 << 14)
+#define MC13783_ADC4_ADDBIS21 (1 << 15)
+#define MC13783_ADC4_ADDBIS22 (1 << 16)
+#define MC13783_ADC4_ADDBIS23 (1 << 17)
+#define MC13783_ADC4_ADDBIS24 (1 << 18)
+#define MC13783_ADC4_ADDBIS25 (1 << 19)
+#define MC13783_ADC4_ADDBIS26 (1 << 20)
+#define MC13783_ADC4_ADDBIS27 (1 << 21)
+#define MC13783_ADC4_ADDBIS28 (1 << 22)
+#define MC13783_ADC4_ADDBIS29 (1 << 23)
+
+#endif /* __LINUX_MFD_MC13783_PRIV_H */
+
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h
new file mode 100644
index 0000000..b3a2a72
--- /dev/null
+++ b/include/linux/mfd/mc13783.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __INCLUDE_LINUX_MFD_MC13783_H
+#define __INCLUDE_LINUX_MFD_MC13783_H
+
+struct mc13783;
+struct regulator_init_data;
+
+struct mc13783_regulator_init_data {
+ int id;
+ struct regulator_init_data *init_data;
+};
+
+struct mc13783_platform_data {
+ struct mc13783_regulator_init_data *regulators;
+ int num_regulators;
+ unsigned int flags;
+};
+
+/* mc13783_platform_data flags */
+#define MC13783_USE_TOUCHSCREEN (1 << 0)
+#define MC13783_USE_CODEC (1 << 1)
+#define MC13783_USE_ADC (1 << 2)
+#define MC13783_USE_RTC (1 << 3)
+#define MC13783_USE_REGULATOR (1 << 4)
+
+int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
+ unsigned int channel, unsigned int *sample);
+
+void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status);
+
+#define MC13783_SW_SW1A 0
+#define MC13783_SW_SW1B 1
+#define MC13783_SW_SW2A 2
+#define MC13783_SW_SW2B 3
+#define MC13783_SW_SW3 4
+#define MC13783_SW_PLL 5
+#define MC13783_REGU_VAUDIO 6
+#define MC13783_REGU_VIOHI 7
+#define MC13783_REGU_VIOLO 8
+#define MC13783_REGU_VDIG 9
+#define MC13783_REGU_VGEN 10
+#define MC13783_REGU_VRFDIG 11
+#define MC13783_REGU_VRFREF 12
+#define MC13783_REGU_VRFCP 13
+#define MC13783_REGU_VSIM 14
+#define MC13783_REGU_VESIM 15
+#define MC13783_REGU_VCAM 16
+#define MC13783_REGU_VRFBG 17
+#define MC13783_REGU_VVIB 18
+#define MC13783_REGU_VRF1 19
+#define MC13783_REGU_VRF2 20
+#define MC13783_REGU_VMMC1 21
+#define MC13783_REGU_VMMC2 22
+#define MC13783_REGU_GPO1 23
+#define MC13783_REGU_GPO2 24
+#define MC13783_REGU_GPO3 25
+#define MC13783_REGU_GPO4 26
+#define MC13783_REGU_V1 27
+#define MC13783_REGU_V2 28
+#define MC13783_REGU_V3 29
+#define MC13783_REGU_V4 30
+
+#endif /* __INCLUDE_LINUX_MFD_MC13783_H */
+
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 15:05 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
@ 2009-08-12 15:05 ` Sascha Hauer
2009-08-12 15:05 ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
2009-08-12 16:04 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Dmitry Torokhov
0 siblings, 2 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Dmitry Torokhov, Mark Brown, linux-input
This driver provides support for the touchscreen interface
integrated into the Freescale MC13783.
changes since v1:
- remove unused functions
- use queue_delayed_work instead of queue_work
- report pen events as BTN_TOUCH instead of ABS_PRESSURE
- handle interrupt registration in open/close functions
- do not call input_free_device() on already registered
input_device
- use platform_driver_probe instead of platform_driver_register
- add MODULE_ALIAS
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 222 ++++++++++++++++++++++++++++++++
3 files changed, 235 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 72e2712..7451cf0 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -413,6 +413,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
+config TOUCHSCREEN_MC13783
+ tristate "Freescale MC13783 touchscreen input driver"
+ depends on MFD_MC13783
+ help
+ Say Y here if you have an Freescale MC13783 PMIC on your
+ board and want to use its touchscreen
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mxc_ts.
+
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3e1c5e0..7b79598 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..80163f1
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,222 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME "mc13783-ts"
+
+struct mc13783_ts_priv {
+ struct input_dev *idev;
+ struct mc13783 *mc13783;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+#define TS_MIN 1
+#define TS_MAX 1000
+
+static void mc13783_ts_handler(int irq, void *data)
+{
+ struct mc13783_ts_priv *priv = data;
+ unsigned int sts;
+
+ mc13783_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0, &sts);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0,
+ sts & MC13783_INT_STAT_TSI);
+
+ if (sts & MC13783_INT_STAT_TSI)
+ queue_delayed_work(priv->workq, &priv->work, 0);
+}
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+ int x, y, press = 0;
+
+ x = (priv->sample[2] >> 2) & 0x3ff;
+ y = (priv->sample[3] >> 2) & 0x3ff;
+
+ pr_debug("mc13783_ts: x: %d y: %d\n", x, y);
+
+ if (x > TS_MIN && x < TS_MAX && y > TS_MIN && y < TS_MAX) {
+ press = 1;
+ input_report_abs(priv->idev, ABS_X, x);
+ input_report_abs(priv->idev, ABS_Y, y);
+
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ }
+
+ input_report_key(priv->idev, BTN_TOUCH, press);
+ input_sync(priv->idev);
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+ struct mc13783_ts_priv *priv =
+ container_of(work, struct mc13783_ts_priv, work.work);
+ unsigned int mode = MC13783_ADC_MODE_TS;
+ unsigned int channel = 12;
+ int ret;
+
+ ret = mc13783_adc_do_conversion
+ (priv->mc13783, mode, channel, priv->sample);
+
+ if (!ret)
+ mc13783_ts_report_sample(priv);
+}
+
+static int mc13783_ts_open(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+ int ret;
+
+ ret = mc13783_register_irq(priv->mc13783, MC13783_IRQ_TS,
+ mc13783_ts_handler, priv);
+ if (ret)
+ return ret;
+
+ queue_delayed_work(priv->workq, &priv->work, HZ / 20);
+
+ return 0;
+}
+
+static void mc13783_ts_close(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+
+ mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
+}
+
+static int __devinit mc13783_ts_probe(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv;
+ struct input_dev *idev;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+
+ idev = input_allocate_device();
+ if (!idev) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ priv->idev = idev;
+ idev->name = MC13783_TS_NAME;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
+ idev->open = mc13783_ts_open;
+ idev->close = mc13783_ts_close;
+ input_set_abs_params(idev, ABS_X, TS_MIN, TS_MAX, 0, 0);
+ input_set_abs_params(idev, ABS_Y, TS_MIN, TS_MAX, 0, 0);
+
+ platform_set_drvdata(pdev, priv);
+
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ if (!priv->workq) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ input_set_drvdata(idev, priv);
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_failed_register;
+ }
+
+ /* unmask the ts wakeup interrupt */
+ mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
+ MC13783_INT_MASK_TSM, 0);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 1);
+
+ return 0;
+
+err_failed_register:
+ input_free_device(priv->idev);
+err_input_alloc:
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 0);
+
+ cancel_delayed_work(&priv->work);
+ destroy_workqueue(priv->workq);
+
+ input_unregister_device(priv->idev);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+ .remove = __devexit_p(mc13783_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_TS_NAME,
+ },
+};
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
+}
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+
+module_init(mc13783_ts_init);
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mc13783-touch");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
2009-08-12 15:05 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
@ 2009-08-12 15:05 ` Sascha Hauer
2009-08-12 15:05 ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
2009-08-12 16:42 ` [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Mark Brown
2009-08-12 16:04 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Dmitry Torokhov
1 sibling, 2 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Luotao Fu, Hans de Goede,
Andrew Morton, Eric Piel, lm-sensors
From: Luotao Fu <l.fu@pengutronix.de>
This driver provides support for the ADC integrated into the
Freescale MC13783 PMIC.
Changes since v1:
- add MODULE_ALIAS
- __init -> __devinit in probe function
- use platform_driver_probe instead of platform_driver_register
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Eric Piel <eric.piel@tremplin-utc.net>
Cc: lm-sensors@lm-sensors.org
---
drivers/hwmon/Kconfig | 6 ++
drivers/hwmon/Makefile | 1 +
drivers/hwmon/mc13783-adc.c | 181 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 188 insertions(+), 0 deletions(-)
create mode 100644 drivers/hwmon/mc13783-adc.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2d50166..a7e34fd 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1017,6 +1017,12 @@ config SENSORS_APPLESMC
Say Y here if you have an applicable laptop and want to experience
the awesome power of applesmc.
+config SENSORS_MC13783_ADC
+ tristate "Freescale MC13783 ADC"
+ depends on MFD_MC13783
+ help
+ Support for the ad converter on mc13783 pmic.
+
config HWMON_DEBUG_CHIP
bool "Hardware Monitoring Chip debugging messages"
default n
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index b793dce..9b4e131 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
+obj-$(CONFIG_SENSORS_MC13783_ADC) += mc13783-adc.o
ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
new file mode 100644
index 0000000..87168f9
--- /dev/null
+++ b/drivers/hwmon/mc13783-adc.c
@@ -0,0 +1,181 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 adc.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/hwmon.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_ADC_NAME "mc13783-adc"
+
+struct mc13783_adc_priv {
+ struct mc13783 *mc13783;
+ struct device *hwmon_dev;
+};
+
+static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ return sprintf(buf, "mc13783_adc\n");
+}
+
+static ssize_t mc13783_adc_read(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ unsigned int channel = attr->index;
+ unsigned int res;
+ unsigned int sample[4];
+
+ mc13783_adc_do_conversion(priv->mc13783, MC13783_ADC_MODE_MULT_CHAN,
+ channel, sample);
+
+ channel &= 0x7;
+
+ res = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff;
+
+ return sprintf(buf, "%u\n", res);
+}
+
+static struct sensor_device_attribute mc13783_adc_ctl[] = {
+ SENSOR_ATTR(name, S_IRUGO, mc13783_adc_show_name, NULL, 0),
+ SENSOR_ATTR(in0_input, S_IRUGO, mc13783_adc_read, NULL, 0),
+ SENSOR_ATTR(in1_input, S_IRUGO, mc13783_adc_read, NULL, 1),
+ SENSOR_ATTR(in2_input, S_IRUGO, mc13783_adc_read, NULL, 2),
+ SENSOR_ATTR(in3_input, S_IRUGO, mc13783_adc_read, NULL, 3),
+ SENSOR_ATTR(in4_input, S_IRUGO, mc13783_adc_read, NULL, 4),
+ SENSOR_ATTR(in5_input, S_IRUGO, mc13783_adc_read, NULL, 5),
+ SENSOR_ATTR(in6_input, S_IRUGO, mc13783_adc_read, NULL, 6),
+ SENSOR_ATTR(in7_input, S_IRUGO, mc13783_adc_read, NULL, 7),
+ SENSOR_ATTR(in8_input, S_IRUGO, mc13783_adc_read, NULL, 8),
+ SENSOR_ATTR(in9_input, S_IRUGO, mc13783_adc_read, NULL, 9),
+ SENSOR_ATTR(in10_input, S_IRUGO, mc13783_adc_read, NULL, 10),
+ SENSOR_ATTR(in11_input, S_IRUGO, mc13783_adc_read, NULL, 11),
+ SENSOR_ATTR(in12_input, S_IRUGO, mc13783_adc_read, NULL, 12),
+ SENSOR_ATTR(in13_input, S_IRUGO, mc13783_adc_read, NULL, 13),
+ SENSOR_ATTR(in14_input, S_IRUGO, mc13783_adc_read, NULL, 14),
+ SENSOR_ATTR(in15_input, S_IRUGO, mc13783_adc_read, NULL, 15),
+};
+
+static int __devinit mc13783_adc_probe(struct platform_device *pdev)
+{
+ struct mc13783_adc_priv *priv;
+ int ret, i;
+ int entries;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+
+ entries = ARRAY_SIZE(mc13783_adc_ctl);
+
+ /* last four channels may be occupied by the touchscreen */
+ if (priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)
+ entries -= 4;
+
+ for (i = 0; i < entries; i++) {
+ ret = device_create_file(&pdev->dev,
+ &mc13783_adc_ctl[i].dev_attr);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "device_create_file failed with %d.\n", ret);
+ goto out_err;
+ }
+ }
+
+ priv->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(priv->hwmon_dev)) {
+ ret = PTR_ERR(priv->hwmon_dev);
+ dev_err(&pdev->dev,
+ "hwmon_device_register failed with %d.\n", ret);
+ goto out_err;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+out_err:
+ for (i--; i >= 0; i--)
+ device_remove_file(&pdev->dev, &mc13783_adc_ctl[i].dev_attr);
+
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_adc_remove(struct platform_device *pdev)
+{
+ struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
+ int entries;
+ int i;
+
+ hwmon_device_unregister(&pdev->dev);
+
+ entries = ARRAY_SIZE(mc13783_adc_ctl);
+
+ if (priv->mc13783->flags & MC13783_USE_TOUCHSCREEN)
+ entries -= 4;
+
+ for (i = 0; i < entries; i++)
+ device_remove_file(&pdev->dev, &mc13783_adc_ctl[i].dev_attr);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_adc_driver = {
+ .remove = __devexit_p(mc13783_adc_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_ADC_NAME,
+ },
+};
+
+static int __init mc13783_adc_init(void)
+{
+ return platform_driver_probe(&mc13783_adc_driver, &mc13783_adc_probe);
+}
+
+static void __exit mc13783_adc_exit(void)
+{
+ platform_driver_unregister(&mc13783_adc_driver);
+}
+
+module_init(mc13783_adc_init);
+module_exit(mc13783_adc_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Luotao Fu, <l.fu@pengutronix.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mc13783-adc");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver
2009-08-12 15:05 ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
@ 2009-08-12 15:05 ` Sascha Hauer
2009-08-12 15:05 ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
2009-08-12 16:42 ` [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Mark Brown
1 sibling, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Paul Gortmaker, Alessandro Zummo,
rtc-linux
This driver provides support for the RTC part integrated into
the Freescale MC13783 PMIC.
changes since v1:
- use set_mmss instead of set_time
- fix __devinit / __devexit usage
- use platform_driver_probe instead of platform_driver_register
- add MODULE_ALIAS
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: rtc-linux@googlegroups.com
---
drivers/rtc/Kconfig | 6 ++
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-mc13783.c | 135 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+), 0 deletions(-)
create mode 100644 drivers/rtc/rtc-mc13783.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 81adbdb..e4a242f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -759,4 +759,10 @@ config RTC_DRV_PS3
This driver can also be built as a module. If so, the module
will be called rtc-ps3.
+config RTC_DRV_MC13783
+ depends on MFD_MC13783
+ tristate "Freescale MC13783 RTC"
+ help
+ This enables support for the Freescale MC13783 PMIC RTC
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 3c0f2b2..0c2cea6 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
new file mode 100644
index 0000000..dfa4702
--- /dev/null
+++ b/drivers/rtc/rtc-mc13783.c
@@ -0,0 +1,135 @@
+/*
+ * Real Time Clock driver for Freescale MC13783 PMIC
+ *
+ * (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+struct mc13783_rtc {
+ struct rtc_device *rtc;
+ struct mc13783 *mc13783;
+};
+
+static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ struct mc13783_rtc *priv = dev_get_drvdata(dev);
+ unsigned int seconds, days;
+
+ seconds = secs % 86400;
+ days = secs / 86400;
+
+ mc13783_reg_write(priv->mc13783, MC13783_REG_RTC_TIME, seconds);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_RTC_DAY, days);
+
+ return 0;
+}
+
+static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mc13783_rtc *priv = dev_get_drvdata(dev);
+ unsigned int seconds, days1, days2;
+ unsigned long s1970;
+
+ rtc_tm_to_time(tm, &s1970);
+
+ do {
+ mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_TIME, &seconds);
+ mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_DAY, &days1);
+ mc13783_reg_read(priv->mc13783, MC13783_REG_RTC_DAY, &days2);
+ } while (days1 != days2);
+
+ s1970 = days1 * 86400 + seconds;
+
+ rtc_time_to_tm(s1970, tm);
+
+ return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops mc13783_rtc_ops = {
+ .read_time = mc13783_rtc_read_time,
+ .set_mmss = mc13783_rtc_set_mmss,
+};
+
+static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
+{
+ int err;
+ struct mc13783_rtc *priv;
+
+ priv = kzalloc(sizeof *priv, GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+ platform_set_drvdata(pdev, priv);
+
+ priv->rtc = rtc_device_register(pdev->name,
+ &pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(priv->rtc)) {
+ err = PTR_ERR(priv->rtc);
+ goto exit_kfree;
+ }
+
+ return 0;
+
+exit_kfree:
+ kfree(priv);
+ return err;
+}
+
+static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
+{
+ struct mc13783_rtc *priv = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(priv->rtc);
+ platform_set_drvdata(pdev, NULL);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_rtc_driver = {
+ .remove = __devexit_p(mc13783_rtc_remove),
+ .driver = {
+ .name = "mc13783-rtc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mc13783_rtc_init(void)
+{
+ return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe);
+}
+module_init(mc13783_rtc_init);
+
+static void __exit mc13783_rtc_exit(void)
+{
+ platform_driver_unregister(&mc13783_rtc_driver);
+}
+module_exit(mc13783_rtc_exit);
+
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mc13783-rtc");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
2009-08-12 15:05 ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
@ 2009-08-12 15:05 ` Sascha Hauer
2009-08-13 10:57 ` Liam Girdwood
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 15:05 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-arm-kernel, Sascha Hauer, Mark Brown, Liam Girdwood
This driver provides basic support for the voltage regulators
integrated into the Freescale MC13783 PMIC. It is currently
only possible to enable/disable outputs, not to actually
set the voltage.
changes since v1:
- decrease verbosity
- use subsys_initcall instead of module_init
- use platform_driver_probe instead of platform_driver_register
- add __devexit_p to mc13783_regulator_remove
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/mc13783.c | 410 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 419 insertions(+), 0 deletions(-)
create mode 100644 drivers/regulator/mc13783.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index f431779..69197e9 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -117,4 +117,12 @@ config REGULATOR_LP3971
Say Y here to support the voltage regulators and convertors
on National Semiconductors LP3971 PMIC
+config REGULATOR_MC13783
+ tristate "Support regulators on Freescale MC13783 PMIC"
+ depends on MFD_MC13783
+ help
+ Say y here to support the regulators found on the Freescale MC13783
+ PMIC.
+
endif
+
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 4d762c4..6d45846 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
+obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/mc13783.c b/drivers/regulator/mc13783.c
new file mode 100644
index 0000000..710211f
--- /dev/null
+++ b/drivers/regulator/mc13783.c
@@ -0,0 +1,410 @@
+/*
+ * Regulator Driver for Freescale MC13783 PMIC
+ *
+ * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * 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.
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+struct mc13783_regulator {
+ struct regulator_desc desc;
+ int reg;
+ int enable_bit;
+};
+
+static struct regulator_ops mc13783_regulator_ops;
+
+static struct mc13783_regulator mc13783_regulators[] = {
+ [MC13783_SW_SW3] = {
+ .desc = {
+ .name = "SW_SW3",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_SW_SW3,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_SWITCHERS_5,
+ .enable_bit = MC13783_SWCTRL_SW3_EN,
+ },
+ [MC13783_SW_PLL] = {
+ .desc = {
+ .name = "SW_PLL",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_SW_PLL,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_SWITCHERS_4,
+ .enable_bit = MC13783_SWCTRL_PLL_EN,
+ },
+ [MC13783_REGU_VAUDIO] = {
+ .desc = {
+ .name = "REGU_VAUDIO",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VAUDIO,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VAUDIO_EN,
+ },
+ [MC13783_REGU_VIOHI] = {
+ .desc = {
+ .name = "REGU_VIOHI",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VIOHI,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VIOHI_EN,
+ },
+ [MC13783_REGU_VIOLO] = {
+ .desc = {
+ .name = "REGU_VIOLO",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VIOLO,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VIOLO_EN,
+ },
+ [MC13783_REGU_VDIG] = {
+ .desc = {
+ .name = "REGU_VDIG",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VDIG,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VDIG_EN,
+ },
+ [MC13783_REGU_VGEN] = {
+ .desc = {
+ .name = "REGU_VGEN",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VGEN,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VGEN_EN,
+ },
+ [MC13783_REGU_VRFDIG] = {
+ .desc = {
+ .name = "REGU_VRFDIG",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRFDIG,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VRFDIG_EN,
+ },
+ [MC13783_REGU_VRFREF] = {
+ .desc = {
+ .name = "REGU_VRFREF",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRFREF,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VRFREF_EN,
+ },
+ [MC13783_REGU_VRFCP] = {
+ .desc = {
+ .name = "REGU_VRFCP",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRFCP,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_0,
+ .enable_bit = MC13783_REGCTRL_VRFCP_EN,
+ },
+ [MC13783_REGU_VSIM] = {
+ .desc = {
+ .name = "REGU_VSIM",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VSIM,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VSIM_EN,
+ },
+ [MC13783_REGU_VESIM] = {
+ .desc = {
+ .name = "REGU_VESIM",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VESIM,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VESIM_EN,
+ },
+ [MC13783_REGU_VCAM] = {
+ .desc = {
+ .name = "REGU_VCAM",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VCAM,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VCAM_EN,
+ },
+ [MC13783_REGU_VRFBG] = {
+ .desc = {
+ .name = "REGU_VRFBG",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRFBG,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VRFBG_EN,
+ },
+ [MC13783_REGU_VVIB] = {
+ .desc = {
+ .name = "REGU_VVIB",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VVIB,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VVIB_EN,
+ },
+ [MC13783_REGU_VRF1] = {
+ .desc = {
+ .name = "REGU_VRF1",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRF1,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VRF1_EN,
+ },
+ [MC13783_REGU_VRF2] = {
+ .desc = {
+ .name = "REGU_VRF2",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VRF2,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VRF2_EN,
+ },
+ [MC13783_REGU_VMMC1] = {
+ .desc = {
+ .name = "REGU_VMMC1",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VMMC1,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VMMC1_EN,
+ },
+ [MC13783_REGU_VMMC2] = {
+ .desc = {
+ .name = "REGU_VMMC2",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_VMMC2,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_REGULATOR_MODE_1,
+ .enable_bit = MC13783_REGCTRL_VMMC2_EN,
+ },
+ [MC13783_REGU_GPO1] = {
+ .desc = {
+ .name = "REGU_GPO1",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_GPO1,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_POWER_MISCELLANEOUS,
+ .enable_bit = MC13783_REGCTRL_GPO1_EN,
+ },
+ [MC13783_REGU_GPO2] = {
+ .desc = {
+ .name = "REGU_GPO2",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_GPO2,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_POWER_MISCELLANEOUS,
+ .enable_bit = MC13783_REGCTRL_GPO2_EN,
+ },
+ [MC13783_REGU_GPO3] = {
+ .desc = {
+ .name = "REGU_GPO3",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_GPO3,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_POWER_MISCELLANEOUS,
+ .enable_bit = MC13783_REGCTRL_GPO3_EN,
+ },
+ [MC13783_REGU_GPO4] = {
+ .desc = {
+ .name = "REGU_GPO4",
+ .ops = &mc13783_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = MC13783_REGU_GPO4,
+ .owner = THIS_MODULE,
+ },
+ .reg = MC13783_REG_POWER_MISCELLANEOUS,
+ .enable_bit = MC13783_REGCTRL_GPO4_EN,
+ },
+};
+
+struct mc13783_priv {
+ struct regulator_desc desc[ARRAY_SIZE(mc13783_regulators)];
+ struct mc13783 *mc13783;
+ struct regulator_dev *regulators[0];
+};
+
+static int mc13783_enable(struct regulator_dev *rdev)
+{
+ struct mc13783_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+ return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
+ mc13783_regulators[id].enable_bit,
+ mc13783_regulators[id].enable_bit);
+}
+
+static int mc13783_disable(struct regulator_dev *rdev)
+{
+ struct mc13783_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+ return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
+ mc13783_regulators[id].enable_bit, 0);
+}
+
+static int mc13783_is_enabled(struct regulator_dev *rdev)
+{
+ struct mc13783_priv *priv = rdev_get_drvdata(rdev);
+ int ret, id = rdev_get_id(rdev);
+ unsigned int val;
+
+ ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
+ if (ret)
+ return ret;
+
+ return (val & mc13783_regulators[id].enable_bit) != 0;
+}
+
+static struct regulator_ops mc13783_regulator_ops = {
+ .enable = mc13783_enable,
+ .disable = mc13783_disable,
+ .is_enabled = mc13783_is_enabled,
+};
+
+static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+{
+ struct mc13783_priv *priv;
+ struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
+ struct mc13783_regulator_init_data *init_data;
+ int i, ret;
+
+ dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);
+
+ priv = kzalloc(sizeof(*priv) + mc13783->num_regulators * sizeof(void *),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = mc13783;
+
+ for (i = 0; i < mc13783->num_regulators; i++) {
+ init_data = &mc13783->regulators[i];
+ priv->regulators[i] = regulator_register(
+ &mc13783_regulators[init_data->id].desc,
+ &pdev->dev, init_data->init_data, priv);
+
+ if (IS_ERR(priv->regulators[i])) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ mc13783_regulators[i].desc.name);
+ ret = PTR_ERR(priv->regulators[i]);
+ goto err;
+ }
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+err:
+ while (--i >= 0)
+ regulator_unregister(priv->regulators[i]);
+
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+{
+ struct mc13783_priv *priv = platform_get_drvdata(pdev);
+ struct mc13783 *mc13783 = priv->mc13783;
+ int i;
+
+ for (i = 0; i < mc13783->num_regulators; i++)
+ regulator_unregister(priv->regulators[i]);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_regulator_driver = {
+ .driver = {
+ .name = "mc13783-regulator",
+ .owner = THIS_MODULE,
+ },
+ .remove = __devexit_p(mc13783_regulator_remove),
+};
+
+static int __init mc13783_regulator_init(void)
+{
+ return platform_driver_probe(&mc13783_regulator_driver,
+ mc13783_regulator_probe);
+}
+subsys_initcall(mc13783_regulator_init);
+
+static void __exit mc13783_regulator_exit(void)
+{
+ platform_driver_unregister(&mc13783_regulator_driver);
+}
+module_exit(mc13783_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
+MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC");
+MODULE_ALIAS("platform:mc13783-regulator");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 15:05 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
@ 2009-08-12 16:04 ` Dmitry Torokhov
2009-08-13 12:26 ` Sascha Hauer
1 sibling, 1 reply; 26+ messages in thread
From: Dmitry Torokhov @ 2009-08-12 16:04 UTC (permalink / raw)
To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
On Wed, Aug 12, 2009 at 05:05:28PM +0200, Sascha Hauer wrote:
> This driver provides support for the touchscreen interface
> integrated into the Freescale MC13783.
>
> changes since v1:
>
> - remove unused functions
> - use queue_delayed_work instead of queue_work
> - report pen events as BTN_TOUCH instead of ABS_PRESSURE
> - handle interrupt registration in open/close functions
> - do not call input_free_device() on already registered
> input_device
> - use platform_driver_probe instead of platform_driver_register
BTW, if you are using platform_driver_probe() then __init is OK for
.probe() because all probes will only be run once, when driver loads.
IIRC the ability to discard probe() code was the main reason for
introducing platform_driver_probe().
> +
> + /* unmask the ts wakeup interrupt */
> + mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
> + MC13783_INT_MASK_TSM, 0);
> +
> + mc13783_adc_set_ts_status(priv->mc13783, 1);
> +
I actually expected these bits to go into ->open(); not the request IRQ
stuff...
--
Dmitry
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
2009-08-12 15:05 ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
@ 2009-08-12 16:42 ` Mark Brown
2009-08-13 13:37 ` Sascha Hauer
1 sibling, 1 reply; 26+ messages in thread
From: Mark Brown @ 2009-08-12 16:42 UTC (permalink / raw)
To: Sascha Hauer
Cc: linux-kernel, Eric Piel, Luotao Fu, lm-sensors, Hans de Goede,
Andrew Morton, linux-arm-kernel
On Wed, Aug 12, 2009 at 05:05:29PM +0200, Sascha Hauer wrote:
> ---
> drivers/hwmon/Kconfig | 6 ++
> drivers/hwmon/Makefile | 1 +
> drivers/hwmon/mc13783-adc.c | 181 +++++++++++++++++++++++++++++++++++++++++++
Ideally there should be a Documentation/hwmon describing the chip and
the hwmon features it has.
> + for (i = 0; i < entries; i++) {
> + ret = device_create_file(&pdev->dev,
> + &mc13783_adc_ctl[i].dev_attr);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "device_create_file failed with %d.\n", ret);
> + goto out_err;
> + }
> + }
Could use sysfs_create_group() here.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
2009-08-12 15:05 ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
@ 2009-08-13 10:57 ` Liam Girdwood
2009-08-13 11:21 ` Samuel Ortiz
0 siblings, 1 reply; 26+ messages in thread
From: Liam Girdwood @ 2009-08-13 10:57 UTC (permalink / raw)
To: Sascha Hauer, Samuel Ortiz; +Cc: linux-kernel, linux-arm-kernel, Mark Brown
On Wed, 2009-08-12 at 17:05 +0200, Sascha Hauer wrote:
> This driver provides basic support for the voltage regulators
> integrated into the Freescale MC13783 PMIC. It is currently
> only possible to enable/disable outputs, not to actually
> set the voltage.
>
> changes since v1:
>
> - decrease verbosity
> - use subsys_initcall instead of module_init
> - use platform_driver_probe instead of platform_driver_register
> - add __devexit_p to mc13783_regulator_remove
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> ---
> drivers/regulator/Kconfig | 8 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/mc13783.c | 410 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 419 insertions(+), 0 deletions(-)
> create mode 100644 drivers/regulator/mc13783.c
>
Sascha, I'm happy for this to go via Samuel's mfd tree as it makes life
easier for linux-next and merging.
Samuel, this ok with you ?
Thanks
Liam
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
2009-08-13 10:57 ` Liam Girdwood
@ 2009-08-13 11:21 ` Samuel Ortiz
2009-08-13 11:38 ` Liam Girdwood
0 siblings, 1 reply; 26+ messages in thread
From: Samuel Ortiz @ 2009-08-13 11:21 UTC (permalink / raw)
To: Liam Girdwood; +Cc: Sascha Hauer, linux-kernel, linux-arm-kernel, Mark Brown
On Thu, Aug 13, 2009 at 11:57:06AM +0100, Liam Girdwood wrote:
> On Wed, 2009-08-12 at 17:05 +0200, Sascha Hauer wrote:
> > This driver provides basic support for the voltage regulators
> > integrated into the Freescale MC13783 PMIC. It is currently
> > only possible to enable/disable outputs, not to actually
> > set the voltage.
> >
> > changes since v1:
> >
> > - decrease verbosity
> > - use subsys_initcall instead of module_init
> > - use platform_driver_probe instead of platform_driver_register
> > - add __devexit_p to mc13783_regulator_remove
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> > ---
> > drivers/regulator/Kconfig | 8 +
> > drivers/regulator/Makefile | 1 +
> > drivers/regulator/mc13783.c | 410 +++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 419 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/regulator/mc13783.c
> >
>
> Sascha, I'm happy for this to go via Samuel's mfd tree as it makes life
> easier for linux-next and merging.
>
> Samuel, this ok with you ?
Yes, that's fine. Do we have your SOB there ?
Cheers,
Samuel.
> Thanks
>
> Liam
>
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
2009-08-13 11:21 ` Samuel Ortiz
@ 2009-08-13 11:38 ` Liam Girdwood
0 siblings, 0 replies; 26+ messages in thread
From: Liam Girdwood @ 2009-08-13 11:38 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: Sascha Hauer, linux-kernel, linux-arm-kernel, Mark Brown
On Thu, 2009-08-13 at 13:21 +0200, Samuel Ortiz wrote:
> On Thu, Aug 13, 2009 at 11:57:06AM +0100, Liam Girdwood wrote:
> > On Wed, 2009-08-12 at 17:05 +0200, Sascha Hauer wrote:
> > > This driver provides basic support for the voltage regulators
> > > integrated into the Freescale MC13783 PMIC. It is currently
> > > only possible to enable/disable outputs, not to actually
> > > set the voltage.
> > >
> > > changes since v1:
> > >
> > > - decrease verbosity
> > > - use subsys_initcall instead of module_init
> > > - use platform_driver_probe instead of platform_driver_register
> > > - add __devexit_p to mc13783_regulator_remove
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > > Cc: Liam Girdwood <lrg@slimlogic.co.uk>
> > > ---
> > > drivers/regulator/Kconfig | 8 +
> > > drivers/regulator/Makefile | 1 +
> > > drivers/regulator/mc13783.c | 410 +++++++++++++++++++++++++++++++++++++++++++
> > > 3 files changed, 419 insertions(+), 0 deletions(-)
> > > create mode 100644 drivers/regulator/mc13783.c
> > >
> >
> > Sascha, I'm happy for this to go via Samuel's mfd tree as it makes life
> > easier for linux-next and merging.
> >
> > Samuel, this ok with you ?
> Yes, that's fine. Do we have your SOB there ?
>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Yes, sorry should have added that.
Thanks
Liam
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 16:04 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Dmitry Torokhov
@ 2009-08-13 12:26 ` Sascha Hauer
2009-08-13 15:52 ` Dmitry Torokhov
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-13 12:26 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
On Wed, Aug 12, 2009 at 09:04:38AM -0700, Dmitry Torokhov wrote:
> On Wed, Aug 12, 2009 at 05:05:28PM +0200, Sascha Hauer wrote:
> > This driver provides support for the touchscreen interface
> > integrated into the Freescale MC13783.
> >
> > changes since v1:
> >
> > - remove unused functions
> > - use queue_delayed_work instead of queue_work
> > - report pen events as BTN_TOUCH instead of ABS_PRESSURE
> > - handle interrupt registration in open/close functions
> > - do not call input_free_device() on already registered
> > input_device
> > - use platform_driver_probe instead of platform_driver_register
>
> BTW, if you are using platform_driver_probe() then __init is OK for
> .probe() because all probes will only be run once, when driver loads.
> IIRC the ability to discard probe() code was the main reason for
> introducing platform_driver_probe().
But __devinit should be ok also, right?
>
> > +
> > + /* unmask the ts wakeup interrupt */
> > + mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
> > + MC13783_INT_MASK_TSM, 0);
> > +
> > + mc13783_adc_set_ts_status(priv->mc13783, 1);
> > +
>
> I actually expected these bits to go into ->open(); not the request IRQ
> stuff...
Yes I know, I just found it convenient to request the interrupts there
so that we do not risk getting interrupts nobody is interested in this
moment.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
2009-08-12 16:42 ` [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Mark Brown
@ 2009-08-13 13:37 ` Sascha Hauer
2009-08-13 14:16 ` Mark Brown
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-13 13:37 UTC (permalink / raw)
To: Mark Brown
Cc: linux-kernel, Eric Piel, Luotao Fu, lm-sensors, Hans de Goede,
Andrew Morton, linux-arm-kernel
On Wed, Aug 12, 2009 at 05:42:53PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2009 at 05:05:29PM +0200, Sascha Hauer wrote:
>
> > ---
> > drivers/hwmon/Kconfig | 6 ++
> > drivers/hwmon/Makefile | 1 +
> > drivers/hwmon/mc13783-adc.c | 181 +++++++++++++++++++++++++++++++++++++++++++
>
> Ideally there should be a Documentation/hwmon describing the chip and
> the hwmon features it has.
>
> > + for (i = 0; i < entries; i++) {
> > + ret = device_create_file(&pdev->dev,
> > + &mc13783_adc_ctl[i].dev_attr);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "device_create_file failed with %d.\n", ret);
> > + goto out_err;
> > + }
> > + }
>
> Could use sysfs_create_group() here.
>
Ok, here is an updated version:
commit cb6bff0876a204a0dfceac4dd8d4ea7983b6063e
Author: Luotao Fu <l.fu@pengutronix.de>
Date: Fri Aug 7 15:21:57 2009 +0200
[hwmon] add Freescale MC13783 adc driver
This driver provides support for the ADC integrated into the
Freescale MC13783 PMIC.
Changes since v2:
- Add Documentation Documentation/hwmon/mc13783
- use sysfs_create_group
Changes since v1:
- add MODULE_ALIAS
- __init -> __devinit in probe function
- use platform_driver_probe instead of platform_driver_register
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Eric Piel <eric.piel@tremplin-utc.net>
Cc: lm-sensors@lm-sensors.org
diff --git a/Documentation/hwmon/mc13783 b/Documentation/hwmon/mc13783
new file mode 100644
index 0000000..6f2ac45
--- /dev/null
+++ b/Documentation/hwmon/mc13783
@@ -0,0 +1,50 @@
+Kernel driver mc13783
+=====================
+
+Supported chips:
+ * Freescale Atlas MC13783
+ Prefix: 'mc13783'
+ Datasheet: http://www.freescale.com/files/rf_if/doc/data_sheet/MC13783.pdf?fsrch=1
+
+Authors:
+ Sascha Hauer <s.hauer@pengutronix.de>
+
+Description
+-----------
+
+The Freescale MC13783 is a Power Management and Audio Circuit. Among
+other things it contains a 10bit A/D converter. The converter has 16
+channels which can be used in different modes.
+The A/D converter has a resolution of 2.25mV. Channels 0-4 have
+a dedicated meaning with chip internal scaling applied. Channels 5-7
+can be used as general purpose inputs or alternatively in a dedicated
+mode. Channels 12-15 are occupied by the touchscreen if it's active.
+
+Currently the driver only supports raw channel readout and no alternative
+modes for channels 5-7.
+
+See this table for the meaning of the different channels and their chip
+internal scaling:
+
+Channel Signal Input Range Scaling
+-------------------------------------------------------------------------------
+0 Battery Voltage (BATT) 2.50 – 4.65V -2.40V
+1 Battery Current (BATT – BATTISNS) -50 - 50 mV x20
+2 Application Supply (BP) 2.50 – 4.65V -2.40V
+3 Charger Voltage (CHRGRAW) 0 – 10V / /5
+ 0 – 20V /10
+4 Charger Current (CHRGISNSP-CHRGISNSN) -0.25V – 0.25V X4
+5 General Purpose ADIN5 / Battery Pack Thermistor 0 – 2.30V No
+6 General Purpose ADIN6 / Backup Voltage (LICELL) 0 – 2.30V / No /
+ 1.50 – 3.50V -1.20V
+7 General Purpose ADIN7 / UID / Die Temperature 0 – 2.30V / No /
+ 0 – 2.55V / x0.9 / No
+8 General Purpose ADIN8 0 - 2.30V No
+9 General Purpose ADIN9 0 - 2.30V No
+10 General Purpose ADIN10 0 - 2.30V No
+11 General Purpose ADIN11 0 - 2.30V No
+12 General Purpose TSX1 / Touchscreen X-plate 1 0 - 2.30V No
+13 General Purpose TSX2 / Touchscreen X-plate 2 0 - 2.30V No
+14 General Purpose TSY1 / Touchscreen Y-plate 1 0 - 2.30V No
+15 General Purpose TSY2 / Touchscreen Y-plate 2 0 - 2.30V No
+
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2d50166..a7e34fd 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1017,6 +1017,12 @@ config SENSORS_APPLESMC
Say Y here if you have an applicable laptop and want to experience
the awesome power of applesmc.
+config SENSORS_MC13783_ADC
+ tristate "Freescale MC13783 ADC"
+ depends on MFD_MC13783
+ help
+ Support for the ad converter on mc13783 pmic.
+
config HWMON_DEBUG_CHIP
bool "Hardware Monitoring Chip debugging messages"
default n
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index b793dce..9b4e131 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
+obj-$(CONFIG_SENSORS_MC13783_ADC) += mc13783-adc.o
ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
new file mode 100644
index 0000000..0a768e7
--- /dev/null
+++ b/drivers/hwmon/mc13783-adc.c
@@ -0,0 +1,204 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 adc.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/hwmon.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_ADC_NAME "mc13783-adc"
+
+struct mc13783_adc_priv {
+ struct mc13783 *mc13783;
+ struct device *hwmon_dev;
+};
+
+static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ return sprintf(buf, "mc13783_adc\n");
+}
+
+static ssize_t mc13783_adc_read(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ unsigned int channel = attr->index;
+ unsigned int res;
+ unsigned int sample[4];
+
+ mc13783_adc_do_conversion(priv->mc13783, MC13783_ADC_MODE_MULT_CHAN,
+ channel, sample);
+
+ channel &= 0x7;
+
+ res = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff;
+
+ return sprintf(buf, "%u\n", res);
+}
+
+SENSOR_DEVICE_ATTR(name, S_IRUGO, mc13783_adc_show_name, NULL, 0);
+SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, mc13783_adc_read, NULL, 0);
+SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, mc13783_adc_read, NULL, 1);
+SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read, NULL, 2);
+SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, mc13783_adc_read, NULL, 3);
+SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, mc13783_adc_read, NULL, 4);
+SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read, NULL, 5);
+SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read, NULL, 6);
+SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read, NULL, 7);
+SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read, NULL, 8);
+SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read, NULL, 9);
+SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read, NULL, 10);
+SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read, NULL, 11);
+SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read, NULL, 12);
+SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read, NULL, 13);
+SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read, NULL, 14);
+SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read, NULL, 15);
+
+static struct attribute *mc13783_attr[] =
+{
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in11_input.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group mc13783_group = {
+ .attrs = mc13783_attr,
+};
+
+/* last four channels may be occupied by the touchscreen */
+static struct attribute *mc13783_attr_ts[] =
+{
+ &sensor_dev_attr_in12_input.dev_attr.attr,
+ &sensor_dev_attr_in13_input.dev_attr.attr,
+ &sensor_dev_attr_in14_input.dev_attr.attr,
+ &sensor_dev_attr_in15_input.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group mc13783_group_ts = {
+ .attrs = mc13783_attr_ts,
+};
+
+static int __devinit mc13783_adc_probe(struct platform_device *pdev)
+{
+ struct mc13783_adc_priv *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+
+ /* Register sysfs hooks */
+ ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group);
+ if (ret)
+ goto out_err_create1;
+
+ if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
+ ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts);
+ if (ret)
+ goto out_err_create2;
+
+ priv->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(priv->hwmon_dev)) {
+ ret = PTR_ERR(priv->hwmon_dev);
+ dev_err(&pdev->dev,
+ "hwmon_device_register failed with %d.\n", ret);
+ goto out_err_register;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+out_err_register:
+ if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
+out_err_create2:
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
+out_err_create1:
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_adc_remove(struct platform_device *pdev)
+{
+ struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(&pdev->dev);
+
+ if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
+
+ sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_adc_driver = {
+ .remove = __devexit_p(mc13783_adc_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_ADC_NAME,
+ },
+};
+
+static int __init mc13783_adc_init(void)
+{
+ return platform_driver_probe(&mc13783_adc_driver, &mc13783_adc_probe);
+}
+
+static void __exit mc13783_adc_exit(void)
+{
+ platform_driver_unregister(&mc13783_adc_driver);
+}
+
+module_init(mc13783_adc_init);
+module_exit(mc13783_adc_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Luotao Fu, <l.fu@pengutronix.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mc13783-adc");
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
2009-08-13 13:37 ` Sascha Hauer
@ 2009-08-13 14:16 ` Mark Brown
0 siblings, 0 replies; 26+ messages in thread
From: Mark Brown @ 2009-08-13 14:16 UTC (permalink / raw)
To: Sascha Hauer
Cc: linux-kernel, Eric Piel, Luotao Fu, lm-sensors, Hans de Goede,
Andrew Morton, linux-arm-kernel
On Thu, Aug 13, 2009 at 03:37:47PM +0200, Sascha Hauer wrote:
> +0 Battery Voltage (BATT) 2.50 – 4.65V -2.40V
> +1 Battery Current (BATT – BATTISNS) -50 - 50 mV x20
> +2 Application Supply (BP) 2.50 – 4.65V -2.40V
> +3 Charger Voltage (CHRGRAW) 0 – 10V / /5
> + 0 – 20V /10
> +4 Charger Current (CHRGISNSP-CHRGISNSN) -0.25V – 0.25V X4
> +5 General Purpose ADIN5 / Battery Pack Thermistor 0 – 2.30V No
> +6 General Purpose ADIN6 / Backup Voltage (LICELL) 0 – 2.30V / No /
> + 1.50 – 3.50V -1.20V
> +7 General Purpose ADIN7 / UID / Die Temperature 0 – 2.30V / No /
> + 0 – 2.55V / x0.9 / No
If you can report actual voltages it'd be desirable for the driver to do
the required conversions - it looks like you're just reporting the raw
ADC values?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-13 12:26 ` Sascha Hauer
@ 2009-08-13 15:52 ` Dmitry Torokhov
2009-12-04 19:52 ` [PATCH] " Uwe Kleine-König
0 siblings, 1 reply; 26+ messages in thread
From: Dmitry Torokhov @ 2009-08-13 15:52 UTC (permalink / raw)
To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
On Thu, Aug 13, 2009 at 02:26:48PM +0200, Sascha Hauer wrote:
> On Wed, Aug 12, 2009 at 09:04:38AM -0700, Dmitry Torokhov wrote:
> > On Wed, Aug 12, 2009 at 05:05:28PM +0200, Sascha Hauer wrote:
> > > This driver provides support for the touchscreen interface
> > > integrated into the Freescale MC13783.
> > >
> > > changes since v1:
> > >
> > > - remove unused functions
> > > - use queue_delayed_work instead of queue_work
> > > - report pen events as BTN_TOUCH instead of ABS_PRESSURE
> > > - handle interrupt registration in open/close functions
> > > - do not call input_free_device() on already registered
> > > input_device
> > > - use platform_driver_probe instead of platform_driver_register
> >
> > BTW, if you are using platform_driver_probe() then __init is OK for
> > .probe() because all probes will only be run once, when driver loads.
> > IIRC the ability to discard probe() code was the main reason for
> > introducing platform_driver_probe().
>
> But __devinit should be ok also, right?
>
It is OK but then what is the point of using platform_driver_probe()
instead of platform_driver_register()? The only reason you'd want to use
platform_driver_probe() if you wanted to discard the probe methods but
it will not happen if the are marked __devinit.
> >
> > > +
> > > + /* unmask the ts wakeup interrupt */
> > > + mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
> > > + MC13783_INT_MASK_TSM, 0);
> > > +
> > > + mc13783_adc_set_ts_status(priv->mc13783, 1);
> > > +
> >
> > I actually expected these bits to go into ->open(); not the request IRQ
> > stuff...
>
> Yes I know, I just found it convenient to request the interrupts there
> so that we do not risk getting interrupts nobody is interested in this
> moment.
>
OK, but still, the bits above should be moved to open() as well, right?
--
Dmitry
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] [input] add mc13783 touchscreen driver
2009-08-13 15:52 ` Dmitry Torokhov
@ 2009-12-04 19:52 ` Uwe Kleine-König
2009-12-12 7:42 ` Dmitry Torokhov
0 siblings, 1 reply; 26+ messages in thread
From: Uwe Kleine-König @ 2009-12-04 19:52 UTC (permalink / raw)
To: linux-input
Cc: Sascha Hauer, linux-kernel, linux-arm-kernel, Dmitry Torokhov,
Mark Brown
From: Sascha Hauer <s.hauer@pengutronix.de>
This driver provides support for the touchscreen interface
integrated into the Freescale MC13783.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Luotao Fu <l.fu@pengutronix.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 259 ++++++++++++++++++++++++++++++++
3 files changed, 272 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 8cc453c..cdee9ca 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -425,6 +425,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
+config TOUCHSCREEN_MC13783
+ tristate "Freescale MC13783 touchscreen input driver"
+ depends on MFD_MC13783
+ help
+ Say Y here if you have an Freescale MC13783 PMIC on your
+ board and want to use its touchscreen
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mc13783_ts.
+
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 15fa62c..ac5ecaf 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..a36b2ad
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,259 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de/
+ *
+ * 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.
+ */
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME "mc13783-ts"
+
+#define DEFAULT_SAMPLE_TOLERANCE 300
+
+static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
+module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_tolerance,
+ "If the minimal and maximal value read out for one axis (out "
+ "of three) differ by this value (default: "
+ __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
+ "is supposed to be wrong and is discarded. Set to 0 to "
+ "disable this check.");
+
+struct mc13783_ts_priv {
+ struct input_dev *idev;
+ struct mc13783 *mc13783;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+static irqreturn_t mc13783_ts_handler(int irq, void *data)
+{
+ struct mc13783_ts_priv *priv = data;
+
+ mc13783_ackirq(priv->mc13783, irq);
+
+ queue_delayed_work(priv->workq, &priv->work, 0);
+
+ return IRQ_HANDLED;
+}
+
+#define sort3(a0, a1, a2) ({ \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ if (a1 > a2) \
+ swap(a1, a2); \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ })
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+ int x0, x1, x2, y0, y1, y2;
+ int cr0, cr1;
+
+ /*
+ * the values are 10-bit wide only, but the two least significant
+ * bits are for future 12 bit use and reading yields 0
+ */
+ x0 = priv->sample[0] & 0xfff;
+ x1 = priv->sample[1] & 0xfff;
+ x2 = priv->sample[2] & 0xfff;
+ y0 = priv->sample[3] & 0xfff;
+ y1 = (priv->sample[0] >> 12) & 0xfff;
+ y2 = (priv->sample[1] >> 12) & 0xfff;
+ cr0 = (priv->sample[2] >> 12) & 0xfff;
+ cr1 = (priv->sample[3] >> 12) & 0xfff;
+
+ dev_dbg(&priv->idev->dev, "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) "
+ "cr: (% 4d, % 4d)\n", x0, x1, x2, y0, y1, y2, cr0, cr1);
+
+ sort3(x0, x1, x2);
+ sort3(y0, y1, y2);
+
+ cr0 = (cr0 + cr1) / 2;
+
+ if (!cr0 || !sample_tolerance ||
+ (x2 - x0 < sample_tolerance &&
+ y2 - y0 < sample_tolerance))
+ {
+ /* report the median coordinate and average pressure */
+ if (cr0) {
+ input_report_abs(priv->idev, ABS_X, x1);
+ input_report_abs(priv->idev, ABS_Y, y1);
+
+ dev_dbg(&priv->idev->dev, "report (%d, %d, %d)\n",
+ x1, y1, 0x1000 - cr0);
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ } else
+ dev_dbg(&priv->idev->dev, "report release\n");
+
+ input_report_abs(priv->idev, ABS_PRESSURE,
+ cr0 ? 0x1000 - cr0 : cr0);
+ input_report_key(priv->idev, BTN_TOUCH, !!cr0);
+ input_sync(priv->idev);
+ } else
+ dev_dbg(&priv->idev->dev, "discard event\n");
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+ struct mc13783_ts_priv *priv =
+ container_of(work, struct mc13783_ts_priv, work.work);
+ unsigned int mode = MC13783_ADC_MODE_TS;
+ unsigned int channel = 12;
+ int ret;
+
+ ret = mc13783_adc_do_conversion(priv->mc13783, mode, channel,
+ priv->sample);
+
+ if (!ret)
+ mc13783_ts_report_sample(priv);
+}
+
+static int mc13783_ts_open(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+ int ret;
+
+ mc13783_lock(priv->mc13783);
+
+ mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
+
+ ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+ mc13783_ts_handler, MC13783_TS_NAME, priv);
+ if (ret)
+ goto out;
+
+ ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+ MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+
+out:
+ mc13783_unlock(priv->mc13783);
+
+ return ret;
+}
+
+static void mc13783_ts_close(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+
+ mc13783_lock(priv->mc13783);
+ mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+ MC13783_ADC0_TSMOD_MASK, 0);
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+ mc13783_unlock(priv->mc13783);
+}
+
+static int __init mc13783_ts_probe(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv;
+ struct input_dev *idev;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+
+ idev = input_allocate_device();
+ if (!idev) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ priv->idev = idev;
+ idev->name = MC13783_TS_NAME;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ idev->open = mc13783_ts_open;
+ idev->close = mc13783_ts_close;
+ input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
+
+ platform_set_drvdata(pdev, priv);
+
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ if (!priv->workq) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ input_set_drvdata(idev, priv);
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_failed_register;
+ }
+
+ return 0;
+
+err_failed_register:
+ input_free_device(priv->idev);
+
+err_input_alloc:
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ cancel_delayed_work(&priv->work);
+ destroy_workqueue(priv->workq);
+
+ input_unregister_device(priv->idev);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+ .remove = __devexit_p(mc13783_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_TS_NAME,
+ },
+};
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
+}
+module_init(mc13783_ts_init);
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MC13783_TS_NAME);
--
1.6.5.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] [input] add mc13783 touchscreen driver
2009-12-04 19:52 ` [PATCH] " Uwe Kleine-König
@ 2009-12-12 7:42 ` Dmitry Torokhov
2009-12-15 10:10 ` Uwe Kleine-König
0 siblings, 1 reply; 26+ messages in thread
From: Dmitry Torokhov @ 2009-12-12 7:42 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-input, Sascha Hauer, linux-kernel, linux-arm-kernel, Mark Brown
Hi Uwe,
On Fri, Dec 04, 2009 at 08:52:57PM +0100, Uwe Kleine-König wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
>
> This driver provides support for the touchscreen interface
> integrated into the Freescale MC13783.
>
Unfortunately the driver as presented does not compile because changes
to mc13783 core that are needed by this driver are not in mainline (and
therefore are not in my tree) yet. Do you know when they willbe
submitted to Linus?
At this point we have 2 option - wait till the necessary changes hit
mainline or merge through some other tree. I am OK with merging through
other tree (MFD?) provided that the patch below is applied (just fold it
into original patch). The main changes:
- we should free IRQ if we fail to activate the device. The old code
was returning error from mc13783_ts_open() but was leaving IRQ
registered
- use cancel_delayed_work_sync() instead of cancel_delayed_work(). You
want to make sure that work function is not running. It also should
be called form mc13783_ts_close() and not mc13783_ts_remove()
- miscellaneous formatting changes.
In this case please feel free add:
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Thanks.
--
Dmitry
diff -u b/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
--- b/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -46,6 +46,12 @@
mc13783_ackirq(priv->mc13783, irq);
+ /*
+ * Kick off reading coordinates. Note that if work happens already
+ * be queued for future execution (it rearms itself) it will not
+ * be rescheduled for immediate execution here. However the rearm
+ * delay is HZ / 50 which is acceptable.
+ */
queue_delayed_work(priv->workq, &priv->work, 0);
return IRQ_HANDLED;
@@ -62,6 +68,7 @@
static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
{
+ struct input_dev *idev = priv->idev;
int x0, x1, x2, y0, y1, y2;
int cr0, cr1;
@@ -78,8 +85,9 @@
cr0 = (priv->sample[2] >> 12) & 0xfff;
cr1 = (priv->sample[3] >> 12) & 0xfff;
- dev_dbg(&priv->idev->dev, "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) "
- "cr: (% 4d, % 4d)\n", x0, x1, x2, y0, y1, y2, cr0, cr1);
+ dev_dbg(&idev->dev,
+ "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
+ x0, x1, x2, y0, y1, y2, cr0, cr1);
sort3(x0, x1, x2);
sort3(y0, y1, y2);
@@ -87,26 +95,24 @@
cr0 = (cr0 + cr1) / 2;
if (!cr0 || !sample_tolerance ||
- (x2 - x0 < sample_tolerance &&
- y2 - y0 < sample_tolerance))
- {
+ (x2 - x0 < sample_tolerance && y2 - y0 < sample_tolerance)) {
/* report the median coordinate and average pressure */
if (cr0) {
- input_report_abs(priv->idev, ABS_X, x1);
- input_report_abs(priv->idev, ABS_Y, y1);
+ input_report_abs(idev, ABS_X, x1);
+ input_report_abs(idev, ABS_Y, y1);
- dev_dbg(&priv->idev->dev, "report (%d, %d, %d)\n",
- x1, y1, 0x1000 - cr0);
+ dev_dbg(&idev->dev,
+ "report (%d, %d, %d)\n", x1, y1, 0x1000 - cr0);
queue_delayed_work(priv->workq, &priv->work, HZ / 50);
} else
- dev_dbg(&priv->idev->dev, "report release\n");
+ dev_dbg(&idev->dev, "report release\n");
- input_report_abs(priv->idev, ABS_PRESSURE,
- cr0 ? 0x1000 - cr0 : cr0);
- input_report_key(priv->idev, BTN_TOUCH, !!cr0);
- input_sync(priv->idev);
+ input_report_abs(idev, ABS_PRESSURE,
+ cr0 ? 0x1000 - cr0 : cr0);
+ input_report_key(idev, BTN_TOUCH, cr0);
+ input_sync(idev);
} else
- dev_dbg(&priv->idev->dev, "discard event\n");
+ dev_dbg(&idev->dev, "discard event\n");
}
static void mc13783_ts_work(struct work_struct *work)
@@ -115,13 +121,11 @@
container_of(work, struct mc13783_ts_priv, work.work);
unsigned int mode = MC13783_ADC_MODE_TS;
unsigned int channel = 12;
- int ret;
- ret = mc13783_adc_do_conversion(priv->mc13783, mode, channel,
- priv->sample);
-
- if (!ret)
+ if (mc13783_adc_do_conversion(priv->mc13783,
+ mode, channel, priv->sample) == 0) {
mc13783_ts_report_sample(priv);
+ }
}
static int mc13783_ts_open(struct input_dev *dev)
@@ -140,10 +144,10 @@
ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
-
+ if (ret)
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
out:
mc13783_unlock(priv->mc13783);
-
return ret;
}
@@ -156,65 +160,67 @@
MC13783_ADC0_TSMOD_MASK, 0);
mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
mc13783_unlock(priv->mc13783);
+
+ cancel_delayed_work_sync(&priv->work);
}
static int __init mc13783_ts_probe(struct platform_device *pdev)
{
struct mc13783_ts_priv *priv;
struct input_dev *idev;
- int ret;
+ int error;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ idev = input_allocate_device();
+ if (!priv || !idev) {
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+ priv->idev = idev;
- idev = input_allocate_device();
- if (!idev) {
- ret = -ENOMEM;
- goto err_input_alloc;
+ /*
+ * We need separate workqueue because mc13783_adc_do_conversion
+ * uses keventd and thus would deadlock.
+ */
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ if (!priv->workq) {
+ error = -ENOMEM;
+ goto err_free_mem;
}
- priv->idev = idev;
idev->name = MC13783_TS_NAME;
+ idev->dev.parent = &pdev->dev;
+
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- idev->open = mc13783_ts_open;
- idev->close = mc13783_ts_close;
input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
- platform_set_drvdata(pdev, priv);
-
- INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
-
- priv->workq = create_singlethread_workqueue("mc13783_ts");
- if (!priv->workq) {
- ret = -ENOMEM;
- goto err_input_alloc;
- }
+ idev->open = mc13783_ts_open;
+ idev->close = mc13783_ts_close;
input_set_drvdata(idev, priv);
- ret = input_register_device(priv->idev);
- if (ret) {
+ error = input_register_device(priv->idev);
+ if (error) {
dev_err(&pdev->dev,
- "register input device failed with %d\n", ret);
- goto err_failed_register;
+ "register input device failed with %d\n", error);
+ goto err_destroy_wq;
}
+ platform_set_drvdata(pdev, priv);
return 0;
-err_failed_register:
- input_free_device(priv->idev);
-
-err_input_alloc:
- platform_set_drvdata(pdev, NULL);
+err_destroy_wq:
+ destroy_workqueue(priv->workq);
+err_free_mem:
+ input_free_device(idev);
kfree(priv);
-
- return ret;
+ return error;
}
static int __devexit mc13783_ts_remove(struct platform_device *pdev)
@@ -223,11 +229,8 @@
platform_set_drvdata(pdev, NULL);
- cancel_delayed_work(&priv->work);
destroy_workqueue(priv->workq);
-
input_unregister_device(priv->idev);
-
kfree(priv);
return 0;
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH] [input] add mc13783 touchscreen driver
2009-12-12 7:42 ` Dmitry Torokhov
@ 2009-12-15 10:10 ` Uwe Kleine-König
2009-12-15 16:45 ` Dmitry Torokhov
0 siblings, 1 reply; 26+ messages in thread
From: Uwe Kleine-König @ 2009-12-15 10:10 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, linux-kernel, Sascha Hauer, Dmitry Torokhov, Mark Brown
From: Sascha Hauer <s.hauer@pengutronix.de>
This driver provides support for the touchscreen interface
integrated into the Freescale MC13783.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Luotao Fu <l.fu@pengutronix.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-input@vger.kernel.org
---
Hi Dmitry,
I squashed your changes into this patch, restored my indention style and
simplified error handling in mc13783_ts_probe to assign ret = -ENOMEM
once at the start of the function instead of each error branch.
In the meantime the changes to mc13783-core are merged in Linus' tree,
so it can go via your's.
Best regards and thanks for your review,
Uwe
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 258 ++++++++++++++++++++++++++++++++
3 files changed, 271 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 32fc8ba..dfafc76 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -450,6 +450,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
+config TOUCHSCREEN_MC13783
+ tristate "Freescale MC13783 touchscreen input driver"
+ depends on MFD_MC13783
+ help
+ Say Y here if you have an Freescale MC13783 PMIC on your
+ board and want to use its touchscreen
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mc13783_ts.
+
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f1f59c9..7416bab 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..87de17f
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,258 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de/
+ *
+ * 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.
+ */
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME "mc13783-ts"
+
+#define DEFAULT_SAMPLE_TOLERANCE 300
+
+static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
+module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_tolerance,
+ "If the minimal and maximal value read out for one axis (out "
+ "of three) differ by this value (default: "
+ __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
+ "is supposed to be wrong and is discarded. Set to 0 to "
+ "disable this check.");
+
+struct mc13783_ts_priv {
+ struct input_dev *idev;
+ struct mc13783 *mc13783;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+static irqreturn_t mc13783_ts_handler(int irq, void *data)
+{
+ struct mc13783_ts_priv *priv = data;
+
+ mc13783_ackirq(priv->mc13783, irq);
+
+ /*
+ * Kick off reading coordinates. Note that if work happens already
+ * be queued for future execution (it rearms itself) it will not
+ * be rescheduled for immediate execution here. However the rearm
+ * delay is HZ / 50 which is acceptable.
+ */
+ queue_delayed_work(priv->workq, &priv->work, 0);
+
+ return IRQ_HANDLED;
+}
+
+#define sort3(a0, a1, a2) ({ \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ if (a1 > a2) \
+ swap(a1, a2); \
+ if (a0 > a1) \
+ swap(a0, a1); \
+ })
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+ struct input_dev *idev = priv->idev;
+ int x0, x1, x2, y0, y1, y2;
+ int cr0, cr1;
+
+ /*
+ * the values are 10-bit wide only, but the two least significant
+ * bits are for future 12 bit use and reading yields 0
+ */
+ x0 = priv->sample[0] & 0xfff;
+ x1 = priv->sample[1] & 0xfff;
+ x2 = priv->sample[2] & 0xfff;
+ y0 = priv->sample[3] & 0xfff;
+ y1 = (priv->sample[0] >> 12) & 0xfff;
+ y2 = (priv->sample[1] >> 12) & 0xfff;
+ cr0 = (priv->sample[2] >> 12) & 0xfff;
+ cr1 = (priv->sample[3] >> 12) & 0xfff;
+
+ dev_dbg(&idev->dev,
+ "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
+ x0, x1, x2, y0, y1, y2, cr0, cr1);
+
+ sort3(x0, x1, x2);
+ sort3(y0, y1, y2);
+
+ cr0 = (cr0 + cr1) / 2;
+
+ if (!cr0 || !sample_tolerance ||
+ (x2 - x0 < sample_tolerance &&
+ y2 - y0 < sample_tolerance)) {
+ /* report the median coordinate and average pressure */
+ if (cr0) {
+ input_report_abs(idev, ABS_X, x1);
+ input_report_abs(idev, ABS_Y, y1);
+
+ dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
+ x1, y1, 0x1000 - cr0);
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ } else
+ dev_dbg(&idev->dev, "report release\n");
+
+ input_report_abs(idev, ABS_PRESSURE,
+ cr0 ? 0x1000 - cr0 : cr0);
+ input_report_key(idev, BTN_TOUCH, cr0);
+ input_sync(idev);
+ } else
+ dev_dbg(&idev->dev, "discard event\n");
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+ struct mc13783_ts_priv *priv =
+ container_of(work, struct mc13783_ts_priv, work.work);
+ unsigned int mode = MC13783_ADC_MODE_TS;
+ unsigned int channel = 12;
+
+ if (mc13783_adc_do_conversion(priv->mc13783,
+ mode, channel, priv->sample) == 0)
+ mc13783_ts_report_sample(priv);
+}
+
+static int mc13783_ts_open(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+ int ret;
+
+ mc13783_lock(priv->mc13783);
+
+ mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
+
+ ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+ mc13783_ts_handler, MC13783_TS_NAME, priv);
+ if (ret)
+ goto out;
+
+ ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+ MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+ if (ret)
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+out:
+ mc13783_unlock(priv->mc13783);
+ return ret;
+}
+
+static void mc13783_ts_close(struct input_dev *dev)
+{
+ struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+
+ mc13783_lock(priv->mc13783);
+ mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+ MC13783_ADC0_TSMOD_MASK, 0);
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+ mc13783_unlock(priv->mc13783);
+
+ cancel_delayed_work_sync(&priv->work);
+}
+
+static int __init mc13783_ts_probe(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv;
+ struct input_dev *idev;
+ int ret = -ENOMEM;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ idev = input_allocate_device();
+ if (!priv || !idev)
+ goto err_free_mem;
+
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+ priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+ priv->idev = idev;
+
+ /*
+ * We need separate workqueue because mc13783_adc_do_conversion
+ * uses keventd and thus would deadlock.
+ */
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ if (!priv->workq)
+ goto err_free_mem;
+
+ idev->name = MC13783_TS_NAME;
+ idev->dev.parent = &pdev->dev;
+
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
+
+ idev->open = mc13783_ts_open;
+ idev->close = mc13783_ts_close;
+
+ input_set_drvdata(idev, priv);
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_destroy_wq;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+err_destroy_wq:
+ destroy_workqueue(priv->workq);
+err_free_mem:
+ input_free_device(idev);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ destroy_workqueue(priv->workq);
+ input_unregister_device(priv->idev);
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+ .remove = __devexit_p(mc13783_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_TS_NAME,
+ },
+};
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
+}
+module_init(mc13783_ts_init);
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MC13783_TS_NAME);
--
1.6.5.2
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH] [input] add mc13783 touchscreen driver
2009-12-15 10:10 ` Uwe Kleine-König
@ 2009-12-15 16:45 ` Dmitry Torokhov
0 siblings, 0 replies; 26+ messages in thread
From: Dmitry Torokhov @ 2009-12-15 16:45 UTC (permalink / raw)
To: Uwe Kleine-König; +Cc: linux-input, linux-kernel, Sascha Hauer, Mark Brown
Hi Uwe,
On Tue, Dec 15, 2009 at 11:10:28AM +0100, Uwe Kleine-König wrote:
> Hi Dmitry,
>
> I squashed your changes into this patch, restored my indention style and
> simplified error handling in mc13783_ts_probe to assign ret = -ENOMEM
> once at the start of the function instead of each error branch.
I prefer to have error defined right before we jump because it allows
reader to see explicitely set error condition instead of having to
verify if earlier code set it properly; it also forces you to set error
conditions on every error branch properly (if you forget while adding a
new one compiler will warn you about uninitialized variable), but I
won't insist.
>
> In the meantime the changes to mc13783-core are merged in Linus' tree,
> so it can go via your's.
>
It settled then.
--
Dmitry
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 11:10 ` Sascha Hauer
2009-08-12 11:16 ` Mark Brown
@ 2009-08-12 16:01 ` Dmitry Torokhov
1 sibling, 0 replies; 26+ messages in thread
From: Dmitry Torokhov @ 2009-08-12 16:01 UTC (permalink / raw)
To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
On Wed, Aug 12, 2009 at 01:10:18PM +0200, Sascha Hauer wrote:
> Hi Dmitry
>
> On Tue, Aug 11, 2009 at 07:15:33PM -0700, Dmitry Torokhov wrote:
> > Hi Sascha,
> >
> > On Tue, Aug 11, 2009 at 11:07:44AM +0200, Sascha Hauer wrote:
> > > +
> > > + INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
> > > +
> > > + priv->workq = create_singlethread_workqueue("mc13783_ts");
> >
> > Do you really need a separate workqueue? Would not keventd suffice?
>
> Yes, I do. mc13783_adc_do_conversion() runs in a workqueue aswell. With
> keventd I would deadlock.
>
I see. Then please add a comment why it is needed so nobody is tempted
to doa "cleanup" ;)
--
Dmitry
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 11:16 ` Mark Brown
@ 2009-08-12 11:34 ` Sascha Hauer
0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 11:34 UTC (permalink / raw)
To: Mark Brown; +Cc: Dmitry Torokhov, linux-kernel, linux-arm-kernel, linux-input
On Wed, Aug 12, 2009 at 12:16:46PM +0100, Mark Brown wrote:
> On Wed, Aug 12, 2009 at 01:10:18PM +0200, Sascha Hauer wrote:
> > On Tue, Aug 11, 2009 at 07:15:33PM -0700, Dmitry Torokhov wrote:
>
> > > This device does not appear to privide pressure readings, use BTN_TOUCH
> > > alone to indicate touches instead of fake ABS_PRESSURE event. Yes, I
> > > know that older versions of tslib only recognize ABS_PRESSURE...
>
> > In fact no released version of tslib supports this :( Anyway, fixed.
>
> Android uses this. No idea if they've got tslib or their own thing.
>
tslib supports this in -trunk. Maybe I can trigger a release of tslib
soon. It's a PITA to use trunk versions with build systems.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 11:10 ` Sascha Hauer
@ 2009-08-12 11:16 ` Mark Brown
2009-08-12 11:34 ` Sascha Hauer
2009-08-12 16:01 ` Dmitry Torokhov
1 sibling, 1 reply; 26+ messages in thread
From: Mark Brown @ 2009-08-12 11:16 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Dmitry Torokhov, linux-kernel, linux-arm-kernel, linux-input
On Wed, Aug 12, 2009 at 01:10:18PM +0200, Sascha Hauer wrote:
> On Tue, Aug 11, 2009 at 07:15:33PM -0700, Dmitry Torokhov wrote:
> > This device does not appear to privide pressure readings, use BTN_TOUCH
> > alone to indicate touches instead of fake ABS_PRESSURE event. Yes, I
> > know that older versions of tslib only recognize ABS_PRESSURE...
> In fact no released version of tslib supports this :( Anyway, fixed.
Android uses this. No idea if they've got tslib or their own thing.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-12 2:15 ` Dmitry Torokhov
@ 2009-08-12 11:10 ` Sascha Hauer
2009-08-12 11:16 ` Mark Brown
2009-08-12 16:01 ` Dmitry Torokhov
0 siblings, 2 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-12 11:10 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
Hi Dmitry
On Tue, Aug 11, 2009 at 07:15:33PM -0700, Dmitry Torokhov wrote:
> Hi Sascha,
>
> On Tue, Aug 11, 2009 at 11:07:44AM +0200, Sascha Hauer wrote:
> > This driver provides support for the touchscreen interface
> > integrated into the Freescale MC13783.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Cc: linux-input@vger.kernel.org
> > ---
> > drivers/input/touchscreen/Kconfig | 12 ++
> > drivers/input/touchscreen/Makefile | 1 +
> > drivers/input/touchscreen/mc13783_ts.c | 228 ++++++++++++++++++++++++++++++++
> > 3 files changed, 241 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/input/touchscreen/mc13783_ts.c
> >
> > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> > index 72e2712..7451cf0 100644
> > --- a/drivers/input/touchscreen/Kconfig
> > +++ b/drivers/input/touchscreen/Kconfig
> > @@ -413,6 +413,18 @@ config TOUCHSCREEN_USB_COMPOSITE
> > To compile this driver as a module, choose M here: the
> > module will be called usbtouchscreen.
> >
> > +config TOUCHSCREEN_MC13783
> > + tristate "Freescale MC13783 touchscreen input driver"
> > + depends on MFD_MC13783
> > + help
> > + Say Y here if you have an Freescale MC13783 PMIC on your
> > + board and want to use its touchscreen
> > +
> > + If unsure, say N.
> > +
> > + To compile this driver as a module, choose M here: the
> > + module will be called mxc_ts.
> > +
> > config TOUCHSCREEN_USB_EGALAX
> > default y
> > bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
> > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> > index 3e1c5e0..7b79598 100644
> > --- a/drivers/input/touchscreen/Makefile
> > +++ b/drivers/input/touchscreen/Makefile
> > @@ -20,6 +20,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
> > obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
> > obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
> > obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
> > +obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
> > obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
> > obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
> > obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
> > diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
> > new file mode 100644
> > index 0000000..9dfe280
> > --- /dev/null
> > +++ b/drivers/input/touchscreen/mc13783_ts.c
> > @@ -0,0 +1,228 @@
> > +/*
> > + * Driver for the Freescale Semiconductor MC13783 touchscreen.
> > + *
> > + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
> > + * Copyright (C) 2009 Sascha Hauer, Pengutronix
> > + *
> > + * Initial development of this code was funded by
> > + * Phytec Messtechnik GmbH, http://www.phytec.de
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version 2
> > + * of the License, or (at your option) any later version.
> > + * 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, write to the Free Software Foundation, Inc., 51
> > + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> > + *
> > + */
> > +
> > +#include <linux/mfd/mc13783-private.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/mfd/mc13783.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/delay.h>
> > +#include <linux/input.h>
> > +#include <linux/sched.h>
> > +#include <linux/init.h>
> > +
> > +#define MC13783_TS_NAME "mc13783-ts"
> > +
> > +struct mc13783_ts_priv {
> > + struct input_dev *idev;
> > + struct mc13783 *mc13783;
> > + struct delayed_work work;
> > + struct workqueue_struct *workq;
> > + unsigned int sample[4];
> > +};
> > +
> > +static inline void mc13783_ts_start_conversion(struct mc13783_ts_priv *priv)
> > +{
> > + unsigned int reg_adc0, reg_adc1;
> > +
> > + reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
> > + | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1
> > + | MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
> > + reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADSEL | MC13783_ADC1_ADA22
> > + | MC13783_ADC1_ASC | MC13783_ADC1_ADTRIGIGN;
> > +
> > + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
> > + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
> > +}
>
> I do not see this function used...
>
> > +
> > +static inline void mc13783_ts_set_irq_mode(struct mc13783_ts_priv *priv)
> > +{
> > + unsigned int reg_adc0, reg_adc1;
> > +
> > + reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
> > + | MC13783_ADC0_TSMOD0;
> > + reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN;
> > +
> > + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
> > + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
> > +}
>
> Nor this one...
>
> > +
> > +#define TS_MIN 1
> > +#define TS_MAX 1000
> > +
> > +static void mc13783_ts_handler(int irq, void *data)
> > +{
> > + struct mc13783_ts_priv *priv = data;
> > + unsigned int sts;
> > +
> > + mc13783_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0, &sts);
> > + mc13783_reg_write(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0,
> > + sts & MC13783_INT_STAT_TSI);
> > +
> > + if (sts & MC13783_INT_STAT_TSI)
> > + queue_work(priv->workq, &priv->work.work);
>
> Do not expose the innards of delayed_work, simply do:
>
> queue_delayed_work(priv->workq, &priv->work, 0);
Ok
>
> > +}
> > +
> > +static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
> > +{
> > + int x, y, press = 0;
> > +
> > + x = (priv->sample[2] >> 2) & 0x3ff;
> > + y = (priv->sample[3] >> 2) & 0x3ff;
> > +
> > + pr_debug("mc13783_ts: x: %d y: %d\n", x, y);
> > +
> > + if (x > TS_MIN && x < TS_MAX && y > TS_MIN && y < TS_MAX) {
> > + press = 1;
> > + input_report_abs(priv->idev, ABS_X, x);
> > + input_report_abs(priv->idev, ABS_Y, y);
> > +
> > + queue_delayed_work(priv->workq, &priv->work, HZ / 50);
> > + }
> > +
> > + input_report_abs(priv->idev, ABS_PRESSURE, press);
>
> This device does not appear to privide pressure readings, use BTN_TOUCH
> alone to indicate touches instead of fake ABS_PRESSURE event. Yes, I
> know that older versions of tslib only recognize ABS_PRESSURE...
In fact no released version of tslib supports this :( Anyway, fixed.
>
> > + input_sync(priv->idev);
> > +}
> > +
> > +static void mc13783_ts_work(struct work_struct *work)
> > +{
> > + struct mc13783_ts_priv *priv =
> > + container_of(work, struct mc13783_ts_priv, work.work);
> > + unsigned int mode = MC13783_ADC_MODE_TS;
> > + unsigned int channel = 12;
> > + int ret;
> > +
> > + ret = mc13783_adc_do_conversion
> > + (priv->mc13783, mode, channel, priv->sample);
> > +
> > + if (!ret)
> > + mc13783_ts_report_sample(priv);
> > +}
> > +
> > +static int __init mc13783_ts_probe(struct platform_device *pdev)
>
> No __inits on probe() methods, they are normally __devinit.
Ok
>
> > +{
> > + struct mc13783_ts_priv *priv;
> > + struct input_dev *idev;
> > + int ret;
> > +
> > + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + priv->mc13783 = pdev->dev.platform_data;
> > +
> > + idev = input_allocate_device();
> > + if (!idev) {
> > + ret = -ENOMEM;
> > + goto err_input_alloc;
> > + }
> > +
> > + priv->idev = idev;
> > + idev->name = MC13783_TS_NAME;
> > + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> > + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> > + idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
> > + BIT_MASK(ABS_PRESSURE);
> > +
>
> It is usually a good idea to indicate the range of reported values with
> input_set_abs_params().
Fixed
>
> > + platform_set_drvdata(pdev, priv);
> > +
> > + ret = mc13783_register_irq(priv->mc13783, MC13783_IRQ_TS,
> > + mc13783_ts_handler, priv);
> > + if (ret)
> > + goto err_failed_irq;
> > +
> > + ret = input_register_device(priv->idev);
> > + if (ret) {
> > + dev_err(&pdev->dev,
> > + "register input device failed with %d\n", ret);
> > + goto err_failed_register;
> > + }
> > +
> > + /* unmask the ts wakeup interrupt */
> > + mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
> > + MC13783_INT_MASK_TSM, 0);
> > +
> > + mc13783_adc_set_ts_status(priv->mc13783, 1);
> > +
> > + INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
> > +
> > + priv->workq = create_singlethread_workqueue("mc13783_ts");
>
> Do you really need a separate workqueue? Would not keventd suffice?
Yes, I do. mc13783_adc_do_conversion() runs in a workqueue aswell. With
keventd I would deadlock.
>
> > + queue_delayed_work(priv->workq, &priv->work, HZ / 20);
>
> Starting of the contoller is better done in input_dev->open() method when
> there are uses as opposed to probe() method.
Ok
>
> > +
> > + return 0;
> > +
> > +err_failed_register:
> > + mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
> > +err_failed_irq:
> > + input_free_device(priv->idev);
> > +err_input_alloc:
> > + kfree(priv);
> > +
> > + return ret;
> > +}
> > +
> > +static int __devexit mc13783_ts_remove(struct platform_device *pdev)
> > +{
> > + struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
> > +
> > + mc13783_adc_set_ts_status(priv->mc13783, 0);
> > +
> > + mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
> > +
> > + cancel_delayed_work(&priv->work);
> > + destroy_workqueue(priv->workq);
> > +
> > + input_unregister_device(priv->idev);
> > + input_free_device(priv->idev);
>
> input_free_device() is verboten after unregister.
Ok
>
> > +
> > + kfree(priv);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver mc13783_ts_driver = {
> > + .probe = mc13783_ts_probe,
> > + .remove = __devexit_p(mc13783_ts_remove),
>
> Whitespace damage.
Fixed
>
> > + .driver = {
> > + .owner = THIS_MODULE,
> > + .name = MC13783_TS_NAME,
> > + },
> > +};
> > +
> > +static int __init mc13783_ts_init(void)
> > +{
> > + return platform_driver_register(&mc13783_ts_driver);
> > +}
> > +
> > +static void __exit mc13783_ts_exit(void)
> > +{
> > + platform_driver_unregister(&mc13783_ts_driver);
> > +}
> > +
> > +module_init(mc13783_ts_init);
> > +module_exit(mc13783_ts_exit);
> > +
> > +MODULE_DESCRIPTION("MC13783 input touchscreen driver");
> > +MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
> > +MODULE_LICENSE("GPL");
>
> MODULE_ALIAS()?
Added
Thanks for reviewing
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-11 9:07 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
@ 2009-08-12 2:15 ` Dmitry Torokhov
2009-08-12 11:10 ` Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Dmitry Torokhov @ 2009-08-12 2:15 UTC (permalink / raw)
To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Mark Brown, linux-input
Hi Sascha,
On Tue, Aug 11, 2009 at 11:07:44AM +0200, Sascha Hauer wrote:
> This driver provides support for the touchscreen interface
> integrated into the Freescale MC13783.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: linux-input@vger.kernel.org
> ---
> drivers/input/touchscreen/Kconfig | 12 ++
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/mc13783_ts.c | 228 ++++++++++++++++++++++++++++++++
> 3 files changed, 241 insertions(+), 0 deletions(-)
> create mode 100644 drivers/input/touchscreen/mc13783_ts.c
>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 72e2712..7451cf0 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -413,6 +413,18 @@ config TOUCHSCREEN_USB_COMPOSITE
> To compile this driver as a module, choose M here: the
> module will be called usbtouchscreen.
>
> +config TOUCHSCREEN_MC13783
> + tristate "Freescale MC13783 touchscreen input driver"
> + depends on MFD_MC13783
> + help
> + Say Y here if you have an Freescale MC13783 PMIC on your
> + board and want to use its touchscreen
> +
> + If unsure, say N.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called mxc_ts.
> +
> config TOUCHSCREEN_USB_EGALAX
> default y
> bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 3e1c5e0..7b79598 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
> obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
> obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
> obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
> +obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
> obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
> obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
> obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
> diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
> new file mode 100644
> index 0000000..9dfe280
> --- /dev/null
> +++ b/drivers/input/touchscreen/mc13783_ts.c
> @@ -0,0 +1,228 @@
> +/*
> + * Driver for the Freescale Semiconductor MC13783 touchscreen.
> + *
> + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright (C) 2009 Sascha Hauer, Pengutronix
> + *
> + * Initial development of this code was funded by
> + * Phytec Messtechnik GmbH, http://www.phytec.de
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * 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, write to the Free Software Foundation, Inc., 51
> + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + *
> + */
> +
> +#include <linux/mfd/mc13783-private.h>
> +#include <linux/platform_device.h>
> +#include <linux/mfd/mc13783.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/input.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +
> +#define MC13783_TS_NAME "mc13783-ts"
> +
> +struct mc13783_ts_priv {
> + struct input_dev *idev;
> + struct mc13783 *mc13783;
> + struct delayed_work work;
> + struct workqueue_struct *workq;
> + unsigned int sample[4];
> +};
> +
> +static inline void mc13783_ts_start_conversion(struct mc13783_ts_priv *priv)
> +{
> + unsigned int reg_adc0, reg_adc1;
> +
> + reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
> + | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1
> + | MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
> + reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADSEL | MC13783_ADC1_ADA22
> + | MC13783_ADC1_ASC | MC13783_ADC1_ADTRIGIGN;
> +
> + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
> + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
> +}
I do not see this function used...
> +
> +static inline void mc13783_ts_set_irq_mode(struct mc13783_ts_priv *priv)
> +{
> + unsigned int reg_adc0, reg_adc1;
> +
> + reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
> + | MC13783_ADC0_TSMOD0;
> + reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN;
> +
> + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
> + mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
> +}
Nor this one...
> +
> +#define TS_MIN 1
> +#define TS_MAX 1000
> +
> +static void mc13783_ts_handler(int irq, void *data)
> +{
> + struct mc13783_ts_priv *priv = data;
> + unsigned int sts;
> +
> + mc13783_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0, &sts);
> + mc13783_reg_write(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0,
> + sts & MC13783_INT_STAT_TSI);
> +
> + if (sts & MC13783_INT_STAT_TSI)
> + queue_work(priv->workq, &priv->work.work);
Do not expose the innards of delayed_work, simply do:
queue_delayed_work(priv->workq, &priv->work, 0);
> +}
> +
> +static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
> +{
> + int x, y, press = 0;
> +
> + x = (priv->sample[2] >> 2) & 0x3ff;
> + y = (priv->sample[3] >> 2) & 0x3ff;
> +
> + pr_debug("mc13783_ts: x: %d y: %d\n", x, y);
> +
> + if (x > TS_MIN && x < TS_MAX && y > TS_MIN && y < TS_MAX) {
> + press = 1;
> + input_report_abs(priv->idev, ABS_X, x);
> + input_report_abs(priv->idev, ABS_Y, y);
> +
> + queue_delayed_work(priv->workq, &priv->work, HZ / 50);
> + }
> +
> + input_report_abs(priv->idev, ABS_PRESSURE, press);
This device does not appear to privide pressure readings, use BTN_TOUCH
alone to indicate touches instead of fake ABS_PRESSURE event. Yes, I
know that older versions of tslib only recognize ABS_PRESSURE...
> + input_sync(priv->idev);
> +}
> +
> +static void mc13783_ts_work(struct work_struct *work)
> +{
> + struct mc13783_ts_priv *priv =
> + container_of(work, struct mc13783_ts_priv, work.work);
> + unsigned int mode = MC13783_ADC_MODE_TS;
> + unsigned int channel = 12;
> + int ret;
> +
> + ret = mc13783_adc_do_conversion
> + (priv->mc13783, mode, channel, priv->sample);
> +
> + if (!ret)
> + mc13783_ts_report_sample(priv);
> +}
> +
> +static int __init mc13783_ts_probe(struct platform_device *pdev)
No __inits on probe() methods, they are normally __devinit.
> +{
> + struct mc13783_ts_priv *priv;
> + struct input_dev *idev;
> + int ret;
> +
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->mc13783 = pdev->dev.platform_data;
> +
> + idev = input_allocate_device();
> + if (!idev) {
> + ret = -ENOMEM;
> + goto err_input_alloc;
> + }
> +
> + priv->idev = idev;
> + idev->name = MC13783_TS_NAME;
> + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> + idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
> + BIT_MASK(ABS_PRESSURE);
> +
It is usually a good idea to indicate the range of reported values with
input_set_abs_params().
> + platform_set_drvdata(pdev, priv);
> +
> + ret = mc13783_register_irq(priv->mc13783, MC13783_IRQ_TS,
> + mc13783_ts_handler, priv);
> + if (ret)
> + goto err_failed_irq;
> +
> + ret = input_register_device(priv->idev);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "register input device failed with %d\n", ret);
> + goto err_failed_register;
> + }
> +
> + /* unmask the ts wakeup interrupt */
> + mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
> + MC13783_INT_MASK_TSM, 0);
> +
> + mc13783_adc_set_ts_status(priv->mc13783, 1);
> +
> + INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
> +
> + priv->workq = create_singlethread_workqueue("mc13783_ts");
Do you really need a separate workqueue? Would not keventd suffice?
> + queue_delayed_work(priv->workq, &priv->work, HZ / 20);
Starting of the contoller is better done in input_dev->open() method when
there are uses as opposed to probe() method.
> +
> + return 0;
> +
> +err_failed_register:
> + mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
> +err_failed_irq:
> + input_free_device(priv->idev);
> +err_input_alloc:
> + kfree(priv);
> +
> + return ret;
> +}
> +
> +static int __devexit mc13783_ts_remove(struct platform_device *pdev)
> +{
> + struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
> +
> + mc13783_adc_set_ts_status(priv->mc13783, 0);
> +
> + mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
> +
> + cancel_delayed_work(&priv->work);
> + destroy_workqueue(priv->workq);
> +
> + input_unregister_device(priv->idev);
> + input_free_device(priv->idev);
input_free_device() is verboten after unregister.
> +
> + kfree(priv);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mc13783_ts_driver = {
> + .probe = mc13783_ts_probe,
> + .remove = __devexit_p(mc13783_ts_remove),
Whitespace damage.
> + .driver = {
> + .owner = THIS_MODULE,
> + .name = MC13783_TS_NAME,
> + },
> +};
> +
> +static int __init mc13783_ts_init(void)
> +{
> + return platform_driver_register(&mc13783_ts_driver);
> +}
> +
> +static void __exit mc13783_ts_exit(void)
> +{
> + platform_driver_unregister(&mc13783_ts_driver);
> +}
> +
> +module_init(mc13783_ts_init);
> +module_exit(mc13783_ts_exit);
> +
> +MODULE_DESCRIPTION("MC13783 input touchscreen driver");
> +MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
> +MODULE_LICENSE("GPL");
MODULE_ALIAS()?
--
Dmitry
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 2/5] [input] add mc13783 touchscreen driver
2009-08-11 9:07 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
@ 2009-08-11 9:07 ` Sascha Hauer
2009-08-12 2:15 ` Dmitry Torokhov
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11 9:07 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Dmitry Torokhov, Mark Brown, linux-input
This driver provides support for the touchscreen interface
integrated into the Freescale MC13783.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 228 ++++++++++++++++++++++++++++++++
3 files changed, 241 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 72e2712..7451cf0 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -413,6 +413,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
+config TOUCHSCREEN_MC13783
+ tristate "Freescale MC13783 touchscreen input driver"
+ depends on MFD_MC13783
+ help
+ Say Y here if you have an Freescale MC13783 PMIC on your
+ board and want to use its touchscreen
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mxc_ts.
+
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3e1c5e0..7b79598 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..9dfe280
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,228 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME "mc13783-ts"
+
+struct mc13783_ts_priv {
+ struct input_dev *idev;
+ struct mc13783 *mc13783;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+static inline void mc13783_ts_start_conversion(struct mc13783_ts_priv *priv)
+{
+ unsigned int reg_adc0, reg_adc1;
+
+ reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1
+ | MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADSEL | MC13783_ADC1_ADA22
+ | MC13783_ADC1_ASC | MC13783_ADC1_ADTRIGIGN;
+
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
+}
+
+static inline void mc13783_ts_set_irq_mode(struct mc13783_ts_priv *priv)
+{
+ unsigned int reg_adc0, reg_adc1;
+
+ reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0;
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN;
+
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
+}
+
+#define TS_MIN 1
+#define TS_MAX 1000
+
+static void mc13783_ts_handler(int irq, void *data)
+{
+ struct mc13783_ts_priv *priv = data;
+ unsigned int sts;
+
+ mc13783_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0, &sts);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0,
+ sts & MC13783_INT_STAT_TSI);
+
+ if (sts & MC13783_INT_STAT_TSI)
+ queue_work(priv->workq, &priv->work.work);
+}
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+ int x, y, press = 0;
+
+ x = (priv->sample[2] >> 2) & 0x3ff;
+ y = (priv->sample[3] >> 2) & 0x3ff;
+
+ pr_debug("mc13783_ts: x: %d y: %d\n", x, y);
+
+ if (x > TS_MIN && x < TS_MAX && y > TS_MIN && y < TS_MAX) {
+ press = 1;
+ input_report_abs(priv->idev, ABS_X, x);
+ input_report_abs(priv->idev, ABS_Y, y);
+
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ }
+
+ input_report_abs(priv->idev, ABS_PRESSURE, press);
+ input_sync(priv->idev);
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+ struct mc13783_ts_priv *priv =
+ container_of(work, struct mc13783_ts_priv, work.work);
+ unsigned int mode = MC13783_ADC_MODE_TS;
+ unsigned int channel = 12;
+ int ret;
+
+ ret = mc13783_adc_do_conversion
+ (priv->mc13783, mode, channel, priv->sample);
+
+ if (!ret)
+ mc13783_ts_report_sample(priv);
+}
+
+static int __init mc13783_ts_probe(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv;
+ struct input_dev *idev;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = pdev->dev.platform_data;
+
+ idev = input_allocate_device();
+ if (!idev) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ priv->idev = idev;
+ idev->name = MC13783_TS_NAME;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_PRESSURE);
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = mc13783_register_irq(priv->mc13783, MC13783_IRQ_TS,
+ mc13783_ts_handler, priv);
+ if (ret)
+ goto err_failed_irq;
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_failed_register;
+ }
+
+ /* unmask the ts wakeup interrupt */
+ mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
+ MC13783_INT_MASK_TSM, 0);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 1);
+
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ queue_delayed_work(priv->workq, &priv->work, HZ / 20);
+
+ return 0;
+
+err_failed_register:
+ mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
+err_failed_irq:
+ input_free_device(priv->idev);
+err_input_alloc:
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 0);
+
+ mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
+
+ cancel_delayed_work(&priv->work);
+ destroy_workqueue(priv->workq);
+
+ input_unregister_device(priv->idev);
+ input_free_device(priv->idev);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+ .probe = mc13783_ts_probe,
+ .remove = __devexit_p(mc13783_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_TS_NAME,
+ },
+};
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_register(&mc13783_ts_driver);
+}
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+
+module_init(mc13783_ts_init);
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH 2/5] [input] add mc13783 touchscreen driver
[not found] <1249981166-4210-1-git-send-email-s.hauer@pengutronix.de>
@ 2009-08-11 8:59 ` Sascha Hauer
0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11 8:59 UTC (permalink / raw)
To: linux-kernel
Cc: linux-arm-kernel, Sascha Hauer, Dmitry Torokhov, Mark Brown, linux-input
This driver provides support for the touchscreen interface
integrated into the Freescale MC13783.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: linux-input@vger.kernel.org
---
drivers/input/touchscreen/Kconfig | 12 ++
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/mc13783_ts.c | 228 ++++++++++++++++++++++++++++++++
3 files changed, 241 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/mc13783_ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 72e2712..7451cf0 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -413,6 +413,18 @@ config TOUCHSCREEN_USB_COMPOSITE
To compile this driver as a module, choose M here: the
module will be called usbtouchscreen.
+config TOUCHSCREEN_MC13783
+ tristate "Freescale MC13783 touchscreen input driver"
+ depends on MFD_MC13783
+ help
+ Say Y here if you have an Freescale MC13783 PMIC on your
+ board and want to use its touchscreen
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mxc_ts.
+
config TOUCHSCREEN_USB_EGALAX
default y
bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3e1c5e0..7b79598 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..9dfe280
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,228 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 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, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/mfd/mc13783-private.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME "mc13783-ts"
+
+struct mc13783_ts_priv {
+ struct input_dev *idev;
+ struct mc13783 *mc13783;
+ struct delayed_work work;
+ struct workqueue_struct *workq;
+ unsigned int sample[4];
+};
+
+static inline void mc13783_ts_start_conversion(struct mc13783_ts_priv *priv)
+{
+ unsigned int reg_adc0, reg_adc1;
+
+ reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1
+ | MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADSEL | MC13783_ADC1_ADA22
+ | MC13783_ADC1_ASC | MC13783_ADC1_ADTRIGIGN;
+
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
+}
+
+static inline void mc13783_ts_set_irq_mode(struct mc13783_ts_priv *priv)
+{
+ unsigned int reg_adc0, reg_adc1;
+
+ reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE
+ | MC13783_ADC0_TSMOD0;
+ reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN;
+
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_0, reg_adc0);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_ADC_1, reg_adc1);
+}
+
+#define TS_MIN 1
+#define TS_MAX 1000
+
+static void mc13783_ts_handler(int irq, void *data)
+{
+ struct mc13783_ts_priv *priv = data;
+ unsigned int sts;
+
+ mc13783_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0, &sts);
+ mc13783_reg_write(priv->mc13783, MC13783_REG_INTERRUPT_STATUS_0,
+ sts & MC13783_INT_STAT_TSI);
+
+ if (sts & MC13783_INT_STAT_TSI)
+ queue_work(priv->workq, &priv->work.work);
+}
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+ int x, y, press = 0;
+
+ x = (priv->sample[2] >> 2) & 0x3ff;
+ y = (priv->sample[3] >> 2) & 0x3ff;
+
+ pr_debug("mc13783_ts: x: %d y: %d\n", x, y);
+
+ if (x > TS_MIN && x < TS_MAX && y > TS_MIN && y < TS_MAX) {
+ press = 1;
+ input_report_abs(priv->idev, ABS_X, x);
+ input_report_abs(priv->idev, ABS_Y, y);
+
+ queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+ }
+
+ input_report_abs(priv->idev, ABS_PRESSURE, press);
+ input_sync(priv->idev);
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+ struct mc13783_ts_priv *priv =
+ container_of(work, struct mc13783_ts_priv, work.work);
+ unsigned int mode = MC13783_ADC_MODE_TS;
+ unsigned int channel = 12;
+ int ret;
+
+ ret = mc13783_adc_do_conversion
+ (priv->mc13783, mode, channel, priv->sample);
+
+ if (!ret)
+ mc13783_ts_report_sample(priv);
+}
+
+static int __init mc13783_ts_probe(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv;
+ struct input_dev *idev;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->mc13783 = pdev->dev.platform_data;
+
+ idev = input_allocate_device();
+ if (!idev) {
+ ret = -ENOMEM;
+ goto err_input_alloc;
+ }
+
+ priv->idev = idev;
+ idev->name = MC13783_TS_NAME;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ idev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
+ BIT_MASK(ABS_PRESSURE);
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = mc13783_register_irq(priv->mc13783, MC13783_IRQ_TS,
+ mc13783_ts_handler, priv);
+ if (ret)
+ goto err_failed_irq;
+
+ ret = input_register_device(priv->idev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "register input device failed with %d\n", ret);
+ goto err_failed_register;
+ }
+
+ /* unmask the ts wakeup interrupt */
+ mc13783_set_bits(priv->mc13783, MC13783_REG_INTERRUPT_MASK_0,
+ MC13783_INT_MASK_TSM, 0);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 1);
+
+ INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+
+ priv->workq = create_singlethread_workqueue("mc13783_ts");
+ queue_delayed_work(priv->workq, &priv->work, HZ / 20);
+
+ return 0;
+
+err_failed_register:
+ mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
+err_failed_irq:
+ input_free_device(priv->idev);
+err_input_alloc:
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+ struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+ mc13783_adc_set_ts_status(priv->mc13783, 0);
+
+ mc13783_free_irq(priv->mc13783, MC13783_IRQ_TS);
+
+ cancel_delayed_work(&priv->work);
+ destroy_workqueue(priv->workq);
+
+ input_unregister_device(priv->idev);
+ input_free_device(priv->idev);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+ .probe = mc13783_ts_probe,
+ .remove = __devexit_p(mc13783_ts_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MC13783_TS_NAME,
+ },
+};
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_register(&mc13783_ts_driver);
+}
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+
+module_init(mc13783_ts_init);
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
--
1.6.3.3
^ permalink raw reply related [flat|nested] 26+ messages in thread
end of thread, other threads:[~2009-12-15 16:46 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-12 15:05 [PATCH V2] Freescale MC13783 PMIC support Sascha Hauer
2009-08-12 15:05 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
2009-08-12 15:05 ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
2009-08-13 10:57 ` Liam Girdwood
2009-08-13 11:21 ` Samuel Ortiz
2009-08-13 11:38 ` Liam Girdwood
2009-08-12 16:42 ` [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Mark Brown
2009-08-13 13:37 ` Sascha Hauer
2009-08-13 14:16 ` Mark Brown
2009-08-12 16:04 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Dmitry Torokhov
2009-08-13 12:26 ` Sascha Hauer
2009-08-13 15:52 ` Dmitry Torokhov
2009-12-04 19:52 ` [PATCH] " Uwe Kleine-König
2009-12-12 7:42 ` Dmitry Torokhov
2009-12-15 10:10 ` Uwe Kleine-König
2009-12-15 16:45 ` Dmitry Torokhov
-- strict thread matches above, loose matches on Subject: below --
2009-08-11 9:07 [RFC] Freescale MC13783 PMIC support Sascha Hauer
2009-08-11 9:07 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
2009-08-11 9:07 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
2009-08-12 2:15 ` Dmitry Torokhov
2009-08-12 11:10 ` Sascha Hauer
2009-08-12 11:16 ` Mark Brown
2009-08-12 11:34 ` Sascha Hauer
2009-08-12 16:01 ` Dmitry Torokhov
[not found] <1249981166-4210-1-git-send-email-s.hauer@pengutronix.de>
2009-08-11 8:59 ` Sascha Hauer
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).