All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] Freescale MC13783 PMIC support
@ 2009-08-11  9:07 Sascha Hauer
  2009-08-11  9:07 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
  2009-08-11 12:05 ` [RFC] Freescale MC13783 PMIC support Antonio Ospite
  0 siblings, 2 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11  9:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, Sascha Hauer

Hi all,

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.
Please ignore the previous mail which lacked the intrductory mail.

Sascha



The following changes since commit ed680c4ad478d0fee9740f7d029087f181346564:
  Linus Torvalds (1):
        Linux 2.6.31-rc5

are available in the git repository at:

  git://git.pengutronix.de/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 |  228 +++++++++++++++++
 drivers/mfd/Kconfig                    |    8 +
 drivers/mfd/Makefile                   |    2 +
 drivers/mfd/mc13783-core.c             |  440 ++++++++++++++++++++++++++++++++
 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              |  141 ++++++++++
 include/linux/mfd/mc13783-private.h    |  402 +++++++++++++++++++++++++++++
 include/linux/mfd/mc13783.h            |   79 ++++++
 17 files changed, 1927 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-11  9:07 [RFC] Freescale MC13783 PMIC support Sascha Hauer
@ 2009-08-11  9:07 ` Sascha Hauer
  2009-08-11  9:07     ` Sascha Hauer
                     ` (2 more replies)
  2009-08-11 12:05 ` [RFC] Freescale MC13783 PMIC support Antonio Ospite
  1 sibling, 3 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11  9:07 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.

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                 |    8 +
 drivers/mfd/Makefile                |    2 +
 drivers/mfd/mc13783-core.c          |  440 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/mc13783-private.h |  402 ++++++++++++++++++++++++++++++++
 include/linux/mfd/mc13783.h         |   79 +++++++
 5 files changed, 931 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..7212e82 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -228,6 +228,14 @@ 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"
+	help
+	  Support for the Freescale MX13783 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..4db0ab2
--- /dev/null
+++ b/drivers/mfd/mc13783-core.c
@@ -0,0 +1,440 @@
+/*
+ * 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.
+ */
+
+#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/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 platform_device **pdev)
+{
+	int ret;
+
+	*pdev = platform_device_alloc(name, -1);
+	if (pdev == NULL) {
+		dev_err(mc13783->dev, "Failed to allocate %s\n", name);
+		return;
+	}
+
+	(*pdev)->dev.parent = mc13783->dev;
+	(*pdev)->dev.platform_data = mc13783;
+	ret = platform_device_add(*pdev);
+	if (ret) {
+		dev_err(mc13783->dev, "Failed to register %s: %d\n", name, ret);
+		platform_device_put(*pdev);
+		*pdev = NULL;
+	}
+}
+
+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;
+
+	mc13783_client_dev_register(mc13783, "mc13783-codec",
+				       &mc13783->codec);
+	mc13783_client_dev_register(mc13783, "mc13783-adc",
+				       &mc13783->adc);
+	mc13783_client_dev_register(mc13783, "mc13783-rtc",
+				       &mc13783->rtc);
+	mc13783_client_dev_register(mc13783, "mc13783-regulator",
+				       &mc13783->regulator);
+	if (mc13783->flags & MC13783_USE_TOUCHSCREEN)
+		mc13783_client_dev_register(mc13783, "mc13783-ts",
+				       &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);
+
+	platform_device_unregister(mc13783->ts);
+	platform_device_unregister(mc13783->rtc);
+	platform_device_unregister(mc13783->codec);
+	platform_device_unregister(mc13783->adc);
+
+	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);
+}
+module_init(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..d390bb5
--- /dev/null
+++ b/include/linux/mfd/mc13783-private.h
@@ -0,0 +1,402 @@
+/*
+ * 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 platform_device *codec;
+	struct platform_device *ts;
+	struct platform_device *rtc;
+	struct platform_device *adc;
+	struct platform_device *regulator;
+
+	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..a2a7452
--- /dev/null
+++ b/include/linux/mfd/mc13783.h
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+#define MC13783_USE_TOUCHSCREEN (1 << 0)
+
+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;
+};
+
+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	SW_SW1A		0
+#define	SW_SW1B		1
+#define	SW_SW2A		2
+#define	SW_SW2B		3
+#define	SW_SW3		4
+#define	SW_PLL		5
+#define	REGU_VAUDIO	6
+#define	REGU_VIOHI	7
+#define	REGU_VIOLO	8
+#define	REGU_VDIG	9
+#define	REGU_VGEN	10
+#define	REGU_VRFDIG	11
+#define	REGU_VRFREF	12
+#define	REGU_VRFCP	13
+#define	REGU_VSIM	14
+#define	REGU_VESIM	15
+#define	REGU_VCAM	16
+#define	REGU_VRFBG	17
+#define	REGU_VVIB	18
+#define	REGU_VRF1	19
+#define	REGU_VRF2	20
+#define	REGU_VMMC1	21
+#define	REGU_VMMC2	22
+#define	REGU_GPO1	23
+#define	REGU_GPO2	24
+#define	REGU_GPO3	25
+#define	REGU_GPO4	26
+#define	REGU_V1		27
+#define	REGU_V2		28
+#define	REGU_V3		29
+#define	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-11  9:07 ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Sascha Hauer
@ 2009-08-11  9:07     ` Sascha Hauer
  2009-08-11 10:12   ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Mark Brown
  2009-08-11 10:15   ` Mark Brown
  2 siblings, 0 replies; 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
@ 2009-08-11  9:07     ` Sascha Hauer
  0 siblings, 0 replies; 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


-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
  2009-08-11  9:07     ` Sascha Hauer
@ 2009-08-11  9:07       ` Sascha Hauer
  -1 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11  9:07 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.

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..885c009
--- /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 __init 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 = pdev->dev.platform_data;
+
+	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 = {
+	.probe		= mc13783_adc_probe,
+	.remove 	= __devexit_p(mc13783_adc_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= MC13783_ADC_NAME,
+	},
+};
+
+static int __init mc13783_adc_init(void)
+{
+	return platform_driver_register(&mc13783_adc_driver);
+}
+
+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");
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [lm-sensors] [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver
@ 2009-08-11  9:07       ` Sascha Hauer
  0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11  9:07 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.

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..885c009
--- /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 __init 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 = pdev->dev.platform_data;
+
+	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 = {
+	.probe		= mc13783_adc_probe,
+	.remove 	= __devexit_p(mc13783_adc_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= MC13783_ADC_NAME,
+	},
+};
+
+static int __init mc13783_adc_init(void)
+{
+	return platform_driver_register(&mc13783_adc_driver);
+}
+
+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");
-- 
1.6.3.3


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver
  2009-08-11  9:07       ` [lm-sensors] " Sascha Hauer
  (?)
@ 2009-08-11  9:07       ` Sascha Hauer
  2009-08-11  9:07         ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
  -1 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, Paul Gortmaker, Alessandro Zummo,
	rtc-linux

This driver provides support for the RTC part integrated into
the Freescale MC13783 PMIC.

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 |  141 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 148 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..00bf66d 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -78,3 +78,4 @@ obj-$(CONFIG_RTC_DRV_WM8350)	+= rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
 obj-$(CONFIG_RTC_DRV_PS3)	+= rtc-ps3.o
+obj-$(CONFIG_RTC_DRV_MC13783)	+= rtc-mc13783.o
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
new file mode 100644
index 0000000..d1f1192
--- /dev/null
+++ b/drivers/rtc/rtc-mc13783.c
@@ -0,0 +1,141 @@
+/*
+ * 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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+
+struct mc13783_rtc {
+	struct rtc_device *rtc;
+	struct mc13783 *mc13783;
+};
+
+static int mc13783_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	unsigned int seconds, days;
+	unsigned long s1970;
+
+	rtc_tm_to_time(tm, &s1970);
+
+	seconds = s1970 % 86400;
+	days = s1970 / 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 0;
+}
+
+static const struct rtc_class_ops mc13783_rtc_ops = {
+	.read_time	= mc13783_rtc_read_time,
+	.set_time	= mc13783_rtc_set_time,
+};
+
+static int 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 = pdev->dev.platform_data;
+	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 __exit 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 = {
+	.probe		 = mc13783_rtc_probe,
+	.remove		= __exit_p(mc13783_rtc_remove),
+	.driver = {
+		.name	= "mc13783-rtc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mc13783_rtc_init(void)
+{
+	return platform_driver_register(&mc13783_rtc_driver);
+}
+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");
+MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC");
+MODULE_LICENSE("GPL");
-- 
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-11  9:07       ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
@ 2009-08-11  9:07         ` Sascha Hauer
  2009-08-11 10:19           ` Mark Brown
  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, 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.

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..2bf8e6a
--- /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[] = {
+	[SW_SW3] = {
+		.desc = {
+			.name	= "SW_SW3",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_SWITCHERS_5,
+		.enable_bit = MC13783_SWCTRL_SW3_EN,
+	},
+	[SW_PLL] = {
+		.desc = {
+			.name	= "SW_PLL",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= SW_PLL,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_SWITCHERS_4,
+		.enable_bit = MC13783_SWCTRL_PLL_EN,
+	},
+	[REGU_VAUDIO] = {
+		.desc = {
+			.name	= "REGU_VAUDIO",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VAUDIO,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VAUDIO_EN,
+	},
+	[REGU_VIOHI] = {
+		.desc = {
+			.name	= "REGU_VIOHI",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VIOHI,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VIOHI_EN,
+	},
+	[REGU_VIOLO] = {
+		.desc = {
+			.name	= "REGU_VIOLO",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VIOLO,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VIOLO_EN,
+	},
+	[REGU_VDIG] = {
+		.desc = {
+			.name	= "REGU_VDIG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VDIG_EN,
+	},
+	[REGU_VGEN] = {
+		.desc = {
+			.name	= "REGU_VGEN",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VGEN,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VGEN_EN,
+	},
+	[REGU_VRFDIG] = {
+		.desc = {
+			.name	= "REGU_VRFDIG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFDIG_EN,
+	},
+	[REGU_VRFREF] = {
+		.desc = {
+			.name	= "REGU_VRFREF",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFREF_EN,
+	},
+	[REGU_VRFCP] = {
+		.desc = {
+			.name	= "REGU_VRFCP",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFCP,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFCP_EN,
+	},
+	[REGU_VSIM] = {
+		.desc = {
+			.name	= "REGU_VSIM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VSIM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VSIM_EN,
+	},
+	[REGU_VESIM] = {
+		.desc = {
+			.name	= "REGU_VESIM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VESIM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VESIM_EN,
+	},
+	[REGU_VCAM] = {
+		.desc = {
+			.name	= "REGU_VCAM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VCAM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VCAM_EN,
+	},
+	[REGU_VRFBG] = {
+		.desc = {
+			.name	= "REGU_VRFBG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFBG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRFBG_EN,
+	},
+	[REGU_VVIB] = {
+		.desc = {
+			.name	= "REGU_VVIB",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VVIB,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VVIB_EN,
+	},
+	[REGU_VRF1] = {
+		.desc = {
+			.name	= "REGU_VRF1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRF1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRF1_EN,
+	},
+	[REGU_VRF2] = {
+		.desc = {
+			.name	= "REGU_VRF2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRF1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRF2_EN,
+	},
+	[REGU_VMMC1] = {
+		.desc = {
+			.name	= "REGU_VMMC1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VMMC1_EN,
+	},
+	[REGU_VMMC2] = {
+		.desc = {
+			.name	= "REGU_VMMC2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC2,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VMMC2_EN,
+	},
+	[REGU_GPO1] = {
+		.desc = {
+			.name	= "REGU_GPO1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO1_EN,
+	},
+	[REGU_GPO2] = {
+		.desc = {
+			.name	= "REGU_GPO2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO2,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO2_EN,
+	},
+	[REGU_GPO3] = {
+		.desc = {
+			.name	= "REGU_GPO3",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO3,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO3_EN,
+	},
+	[REGU_GPO4] = {
+		.desc = {
+			.name	= "REGU_GPO4",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= 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_info(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_info(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 = pdev->dev.platform_data;
+	struct mc13783_regulator_init_data *init_data;
+	int i, ret;
+
+	dev_info(&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,
+	},
+	.probe		= mc13783_regulator_probe,
+	.remove		= mc13783_regulator_remove,
+};
+
+static int __init mc13783_regulator_init(void)
+{
+	return platform_driver_register(&mc13783_regulator_driver);
+}
+module_init(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 1/5] drivers/mfd: Add Freescale MC13783 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-11 10:12   ` Mark Brown
  2009-08-11 11:38     ` Sascha Hauer
  2009-08-11 10:15   ` Mark Brown
  2 siblings, 1 reply; 26+ messages in thread
From: Mark Brown @ 2009-08-11 10:12 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Liam Girdwood

On Tue, Aug 11, 2009 at 11:07:43AM +0200, Sascha Hauer wrote:

> +/*
> + * 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 platform_device **pdev)

Some of this code is looking distinctly familiar :)

> +#define	SW_SW1A		0
> +#define	SW_SW1B		1

This and the other defines following look like they should probably be
namespaced.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/5] drivers/mfd: Add Freescale MC13783 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-11 10:12   ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Mark Brown
@ 2009-08-11 10:15   ` Mark Brown
  2 siblings, 0 replies; 26+ messages in thread
From: Mark Brown @ 2009-08-11 10:15 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Liam Girdwood

On Tue, Aug 11, 2009 at 11:07:43AM +0200, Sascha Hauer wrote:

> +static int __init pmic_init(void)
> +{
> +	return spi_register_driver(&pmic_driver);
> +}
> +module_init(pmic_init);

This should be subsys_initcall() so that the regulators can come up
early.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
  2009-08-11  9:07         ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
@ 2009-08-11 10:19           ` Mark Brown
  0 siblings, 0 replies; 26+ messages in thread
From: Mark Brown @ 2009-08-11 10:19 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Liam Girdwood

On Tue, Aug 11, 2009 at 11:07:47AM +0200, Sascha Hauer wrote:

This looks basically OK - a few small nitpicks below.

> +static int mc13783_enable(struct regulator_dev *rdev)
> +{
> +	struct mc13783_priv *priv = rdev_get_drvdata(rdev);
> +	int id = rdev_get_id(rdev);
> +
> +	dev_info(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);

This is too verbose - it should be dev_dbg() if anything.

> +static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
> +{
> +	struct mc13783_priv *priv;
> +	struct mc13783 *mc13783 = pdev->dev.platform_data;
> +	struct mc13783_regulator_init_data *init_data;
> +	int i, ret;
> +
> +	dev_info(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);

dev_dbg() please.

> +static int __init mc13783_regulator_init(void)
> +{
> +	return platform_driver_register(&mc13783_regulator_driver);
> +}
> +module_init(mc13783_regulator_init);

This should be subsys_initcall().

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver
  2009-08-11 10:12   ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Mark Brown
@ 2009-08-11 11:38     ` Sascha Hauer
  0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11 11:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-kernel, linux-arm-kernel, Samuel Ortiz, Liam Girdwood

Hi Mark,

On Tue, Aug 11, 2009 at 11:12:40AM +0100, Mark Brown wrote:
> On Tue, Aug 11, 2009 at 11:07:43AM +0200, Sascha Hauer wrote:
> 
> > +/*
> > + * 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 platform_device **pdev)
> 
> Some of this code is looking distinctly familiar :)

Indeed, I added a 'based on' to the header.

> 
> > +#define	SW_SW1A		0
> > +#define	SW_SW1B		1
> 
> This and the other defines following look like they should probably be
> namespaced.

Ok.

Thanks for reviewing. I addressed these comments and the comments you made
to the other patches. I'll delay reposting a bit in case others have
comments aswell.

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: [RFC] Freescale MC13783 PMIC support
  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 12:05 ` Antonio Ospite
  2009-08-11 12:28   ` Mark Brown
  2009-08-11 13:57   ` Sascha Hauer
  1 sibling, 2 replies; 26+ messages in thread
From: Antonio Ospite @ 2009-08-11 12:05 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-kernel, linux-arm-kernel, Daniel Ribeiro

[-- Attachment #1: Type: text/plain, Size: 2305 bytes --]

On Tue, 11 Aug 2009 11:07:42 +0200
Sascha Hauer <s.hauer@pengutronix.de> wrote:

> Hi all,
> 
> 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.
> Please ignore the previous mail which lacked the intrductory mail.
> 
> Sascha
>

Hi Sascha,

the MC13783 is also named Atlas, isn't it?
Maybe you can add this name somewhere in comments or in Kconfig entry
to help greppers and web crawlers.

BTW, I only took a very brief look to some of your patches, and here's
some humble thoughts, sorry if I don't comment patch by patch.

There is a driver queued for inclusion in 2.6.31 for the PCAP2
PMIC, which is quite similar to MC13783. This driver uses the irq_chip
mechanism to expose the PMIC IRQs to be used as general IRQs in
sub-devices drivers (which you call client-devices AFAICS). Also, it
passed all the reviews so maybe you can give it a look to take some
other solution already accepted by reviewers, like passing sub-devices
via platform data (some of the phones which use PCAP2 don't have
touchscreen, for instance), generalize the driver so to handle multiple
PMICs in one system (quite unlikely scenario?), read actual pressure
in TS driver.

The latest (fixed) version of the core and ADC driver is in [1], but you
can find also the regulator and input drivers in [2] which are queued
for 2.6.32, the rtc driver can be found in [3]
(rtc-driver-for-pcap2-pmic-*.patch).

Regards,
   Antonio

[1]
http://git.kernel.org/?p=linux/kernel/git/sameo/mfd-2.6.git;a=blob;f=drivers/mfd/ezx-pcap.c;h=016be4938e4c4baac63168e2c478f335ae162ed9;hb=for-next

[2]
http://git.kernel.org/?p=linux/kernel/git/sameo/mfd-2.6.git;a=summary

[3] http://userweb.kernel.org/~akpm/mmotm/broken-out/

-- 
Antonio Ospite
http://ao2.it

PGP public key ID: 0x4553B001

A: Because it messes up the order in which people normally read text.
   See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC] Freescale MC13783 PMIC support
  2009-08-11 12:05 ` [RFC] Freescale MC13783 PMIC support Antonio Ospite
@ 2009-08-11 12:28   ` Mark Brown
  2009-08-15  1:17     ` Daniel Ribeiro
  2009-08-11 13:57   ` Sascha Hauer
  1 sibling, 1 reply; 26+ messages in thread
From: Mark Brown @ 2009-08-11 12:28 UTC (permalink / raw)
  To: Antonio Ospite
  Cc: Sascha Hauer, linux-kernel, linux-arm-kernel, Daniel Ribeiro

On Tue, Aug 11, 2009 at 02:05:00PM +0200, Antonio Ospite wrote:
> Sascha Hauer <s.hauer@pengutronix.de> wrote:

> There is a driver queued for inclusion in 2.6.31 for the PCAP2
> PMIC, which is quite similar to MC13783. This driver uses the irq_chip
> mechanism to expose the PMIC IRQs to be used as general IRQs in
> sub-devices drivers (which you call client-devices AFAICS). Also, it

Use of the generic IRQ infrastructure in I2C/SPI MFDs is a bit dodgy at
this point - it can be persuaded to work but genirq really doesn't
support it properly since it wants to run with interrupts disabled but
you want interrupts for these slower buses.  It's likely to get resolved
but right now it's safer to work outside the framework in order to avoid
surprises.

> passed all the reviews so maybe you can give it a look to take some
> other solution already accepted by reviewers, like passing sub-devices
> via platform data (some of the phones which use PCAP2 don't have
> touchscreen, for instance), generalize the driver so to handle multiple

There's also the wm831x drivers which do all the subdevice stuff via the
MFD core and are prepared for a transition to genirq once devices like
this are actively supported by it.

> PMICs in one system (quite unlikely scenario?), read actual pressure

It's vanishingly unlikely that you'd see two Atlases in one system - you
might see two PMICs but not two primary PMICs with stuff like battery
chargers on them.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC] Freescale MC13783 PMIC support
  2009-08-11 12:05 ` [RFC] Freescale MC13783 PMIC support Antonio Ospite
  2009-08-11 12:28   ` Mark Brown
@ 2009-08-11 13:57   ` Sascha Hauer
  1 sibling, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2009-08-11 13:57 UTC (permalink / raw)
  To: Antonio Ospite; +Cc: linux-kernel, linux-arm-kernel, Daniel Ribeiro

Hi Antonio,

On Tue, Aug 11, 2009 at 02:05:00PM +0200, Antonio Ospite wrote:
> On Tue, 11 Aug 2009 11:07:42 +0200
> Sascha Hauer <s.hauer@pengutronix.de> wrote:
> 
> > Hi all,
> > 
> > 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.
> > Please ignore the previous mail which lacked the intrductory mail.
> > 
> > Sascha
> >
> 
> Hi Sascha,
> 
> the MC13783 is also named Atlas, isn't it?
> Maybe you can add this name somewhere in comments or in Kconfig entry
> to help greppers and web crawlers.
> 
> BTW, I only took a very brief look to some of your patches, and here's
> some humble thoughts, sorry if I don't comment patch by patch.
> 
> There is a driver queued for inclusion in 2.6.31 for the PCAP2
> PMIC, which is quite similar to MC13783. This driver uses the irq_chip
> mechanism to expose the PMIC IRQs to be used as general IRQs in
> sub-devices drivers (which you call client-devices AFAICS).

I can change the driver if there's consensus to do so.

> Also, it
> passed all the reviews so maybe you can give it a look to take some
> other solution already accepted by reviewers, like passing sub-devices
> via platform data (some of the phones which use PCAP2 don't have
> touchscreen, for instance),

This is indeed a useful feature. What I don't like about the pcap
approach is that the generation of the correct struct pcap_subdev
devices with the correct names is left to the board code.
Maybe we can also use the flags approach I already started with
MC13783_USE_TOUCHSCREEN which can be passed to the platform_data?

> generalize the driver so to handle multiple
> PMICs in one system (quite unlikely scenario?),

All functions take a struct mc13783 * so I think it should work with
multiple PMICs already.

> read actual pressure
> in TS driver.

This is left as an exercise for people who have the hardware which
supports this feature ;)

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     ` Sascha Hauer
  (?)
  (?)
@ 2009-08-12  2:15     ` Dmitry Torokhov
  2009-08-12 11:10       ` Sascha Hauer
  -1 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

* Re: [PATCH 2/5] [input] add mc13783 touchscreen driver
  2009-08-12  2:15     ` [PATCH 2/5] [input] add mc13783 touchscreen driver 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-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 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 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: [RFC] Freescale MC13783 PMIC support
  2009-08-11 12:28   ` Mark Brown
@ 2009-08-15  1:17     ` Daniel Ribeiro
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Ribeiro @ 2009-08-15  1:17 UTC (permalink / raw)
  To: Mark Brown; +Cc: Antonio Ospite, Sascha Hauer, linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 686 bytes --]

Em Ter, 2009-08-11 às 13:28 +0100, Mark Brown escreveu:
> > PMICs in one system (quite unlikely scenario?), read actual pressure
> 
> It's vanishingly unlikely that you'd see two Atlases in one system - you
> might see two PMICs but not two primary PMICs with stuff like battery
> chargers on them.

There are some GSM Phones from Motorola with PCAP2 + MC13883 (based on
MC13783, but with USB and regulator blocks only). On these phones the
battery charging, and USB OTG capabilities of PCAP2 are unused.

All "gen2" devices on http://wiki.openezx.org/Project_devices use PCAP2
+ MC13883. "MotoMAGX" devices use MC13783 only. And "gen1" PCAP2 only.

-- 
Daniel Ribeiro

[-- Attachment #2: Esta é uma parte de mensagem assinada digitalmente --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ 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 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-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

* [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

* [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver
  2009-08-11  8:59     ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
@ 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, 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.

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..2bf8e6a
--- /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[] = {
+	[SW_SW3] = {
+		.desc = {
+			.name	= "SW_SW3",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_SWITCHERS_5,
+		.enable_bit = MC13783_SWCTRL_SW3_EN,
+	},
+	[SW_PLL] = {
+		.desc = {
+			.name	= "SW_PLL",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= SW_PLL,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_SWITCHERS_4,
+		.enable_bit = MC13783_SWCTRL_PLL_EN,
+	},
+	[REGU_VAUDIO] = {
+		.desc = {
+			.name	= "REGU_VAUDIO",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VAUDIO,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VAUDIO_EN,
+	},
+	[REGU_VIOHI] = {
+		.desc = {
+			.name	= "REGU_VIOHI",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VIOHI,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VIOHI_EN,
+	},
+	[REGU_VIOLO] = {
+		.desc = {
+			.name	= "REGU_VIOLO",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VIOLO,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VIOLO_EN,
+	},
+	[REGU_VDIG] = {
+		.desc = {
+			.name	= "REGU_VDIG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VDIG_EN,
+	},
+	[REGU_VGEN] = {
+		.desc = {
+			.name	= "REGU_VGEN",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VGEN,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VGEN_EN,
+	},
+	[REGU_VRFDIG] = {
+		.desc = {
+			.name	= "REGU_VRFDIG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFDIG_EN,
+	},
+	[REGU_VRFREF] = {
+		.desc = {
+			.name	= "REGU_VRFREF",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFDIG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFREF_EN,
+	},
+	[REGU_VRFCP] = {
+		.desc = {
+			.name	= "REGU_VRFCP",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFCP,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_0,
+		.enable_bit = MC13783_REGCTRL_VRFCP_EN,
+	},
+	[REGU_VSIM] = {
+		.desc = {
+			.name	= "REGU_VSIM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VSIM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VSIM_EN,
+	},
+	[REGU_VESIM] = {
+		.desc = {
+			.name	= "REGU_VESIM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VESIM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VESIM_EN,
+	},
+	[REGU_VCAM] = {
+		.desc = {
+			.name	= "REGU_VCAM",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VCAM,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VCAM_EN,
+	},
+	[REGU_VRFBG] = {
+		.desc = {
+			.name	= "REGU_VRFBG",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRFBG,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRFBG_EN,
+	},
+	[REGU_VVIB] = {
+		.desc = {
+			.name	= "REGU_VVIB",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VVIB,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VVIB_EN,
+	},
+	[REGU_VRF1] = {
+		.desc = {
+			.name	= "REGU_VRF1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRF1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRF1_EN,
+	},
+	[REGU_VRF2] = {
+		.desc = {
+			.name	= "REGU_VRF2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VRF1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VRF2_EN,
+	},
+	[REGU_VMMC1] = {
+		.desc = {
+			.name	= "REGU_VMMC1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VMMC1_EN,
+	},
+	[REGU_VMMC2] = {
+		.desc = {
+			.name	= "REGU_VMMC2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_VMMC2,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_REGULATOR_MODE_1,
+		.enable_bit = MC13783_REGCTRL_VMMC2_EN,
+	},
+	[REGU_GPO1] = {
+		.desc = {
+			.name	= "REGU_GPO1",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO1,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO1_EN,
+	},
+	[REGU_GPO2] = {
+		.desc = {
+			.name	= "REGU_GPO2",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO2,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO2_EN,
+	},
+	[REGU_GPO3] = {
+		.desc = {
+			.name	= "REGU_GPO3",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= REGU_GPO3,
+			.owner	= THIS_MODULE,
+		},
+		.reg = MC13783_REG_POWER_MISCELLANEOUS,
+		.enable_bit = MC13783_REGCTRL_GPO3_EN,
+	},
+	[REGU_GPO4] = {
+		.desc = {
+			.name	= "REGU_GPO4",
+			.ops	= &mc13783_regulator_ops,
+			.type	= REGULATOR_VOLTAGE,
+			.id	= 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_info(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_info(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 = pdev->dev.platform_data;
+	struct mc13783_regulator_init_data *init_data;
+	int i, ret;
+
+	dev_info(&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,
+	},
+	.probe		= mc13783_regulator_probe,
+	.remove		= mc13783_regulator_remove,
+};
+
+static int __init mc13783_regulator_init(void)
+{
+	return platform_driver_register(&mc13783_regulator_driver);
+}
+module_init(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

end of thread, other threads:[~2009-08-15  1:17 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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-11  9:07     ` Sascha Hauer
2009-08-11  9:07     ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
2009-08-11  9:07       ` [lm-sensors] " Sascha Hauer
2009-08-11  9:07       ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
2009-08-11  9:07         ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer
2009-08-11 10:19           ` Mark Brown
2009-08-12  2:15     ` [PATCH 2/5] [input] add mc13783 touchscreen driver 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
2009-08-11 10:12   ` [PATCH 1/5] drivers/mfd: Add Freescale MC13783 driver Mark Brown
2009-08-11 11:38     ` Sascha Hauer
2009-08-11 10:15   ` Mark Brown
2009-08-11 12:05 ` [RFC] Freescale MC13783 PMIC support Antonio Ospite
2009-08-11 12:28   ` Mark Brown
2009-08-15  1:17     ` Daniel Ribeiro
2009-08-11 13:57   ` Sascha Hauer
  -- strict thread matches above, loose matches on Subject: below --
2009-08-12 15:05 [PATCH V2] " 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
     [not found] <1249981166-4210-1-git-send-email-s.hauer@pengutronix.de>
2009-08-11  8:59 ` [PATCH 2/5] [input] add mc13783 touchscreen driver Sascha Hauer
2009-08-11  8:59   ` [PATCH 3/5] [hwmon] add Freescale MC13783 adc driver Sascha Hauer
2009-08-11  8:59     ` [PATCH 4/5] [RTC] Add Freescale MC13783 RTC driver Sascha Hauer
2009-08-11  8:59       ` [PATCH 5/5] [regulator] Add a Freescale MC13783 regulator driver Sascha Hauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.