linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 05/14] mfd: PCAP2 driver
       [not found] <20081121160403.073751031@dodger.lab.datenfreihafen.org>
@ 2008-11-21 16:04 ` stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ
       [not found]   ` <20081121160521.016544616-cQQG9CVUopzFITZdfPi31ZcF1vblOVnWhIvA6WVW+J8@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ @ 2008-11-21 16:04 UTC (permalink / raw)
  To: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w, sameo-RWuK6r/cQWRpLGFMi4vTTA
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro, linux-kernel-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: ezx/pcap.diff --]
[-- Type: text/plain, Size: 26783 bytes --]

The PCAP Asic as present on EZX phones is a multi function device with
voltage regulators, irq expander, touch screen controller and audio
codec. It is connected to the processor via SPI, this driver provides
read/write functions to its registers.

Since the last submission we are also using the spi subsystem and
pxa2xx-spi instead of ssp.c directly as before.

Signed-off-by: Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

---
 arch/arm/mach-pxa/Kconfig    |    1 +
 drivers/mfd/Kconfig          |    8 +
 drivers/mfd/Makefile         |    2 +
 drivers/mfd/ezx-pcap.c       |  598 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/ezx-pcap.h |  290 ++++++++++++++++++++
 5 files changed, 899 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index a062235..d64c15a 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -351,6 +351,7 @@ config PXA_EZX
 	select PXA27x
 	select IWMMXT
 	select HAVE_PWM
+	select EZX_PCAP
 
 config MACH_EZX_A780
 	bool "Motorola EZX A780"
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2572773..c8c3e1e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -153,6 +153,14 @@ config MFD_WM8350_I2C
 	  I2C as the control interface.  Additional options must be
 	  selected to enable support for the functionality of the chip.
 
+config EZX_PCAP
+	bool "PCAP Support"
+	depends on PXA_EZX
+	select SPI_PXA2XX
+	help
+	  This enables the PCAP ASIC present on EZX Phones. This is
+	  needed for MMC, TouchScreen, Sound, USB, etc..
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9a5ad8a..cbf32e0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -21,6 +21,8 @@ obj-$(CONFIG_TWL4030_CORE)	+= twl4030-core.o twl4030-irq.o
 
 obj-$(CONFIG_MFD_CORE)		+= mfd-core.o
 
+obj-$(CONFIG_EZX_PCAP)		+= ezx-pcap.o
+
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
new file mode 100644
index 0000000..c660372
--- /dev/null
+++ b/drivers/mfd/ezx-pcap.c
@@ -0,0 +1,598 @@
+/*
+ * Driver for Motorola PCAP2 as present in EZX phones
+ *
+ * Copyright (C) 2006 Harald Welte <laforge-WB6LKoYH/xlAfugRpC6u6w@public.gmane.org>
+ * Copyright (C) 2007-2008 Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/proc_fs.h>
+#include <linux/mfd/ezx-pcap.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/ssp.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-ssp.h>
+#include <mach/mfp-pxa27x.h>
+#include <mach/irqs.h>
+
+struct pcap_chip {
+	struct spi_device *spi;
+	struct work_struct work;
+	struct workqueue_struct *workqueue;
+	void (*adc_done)(void *);
+	void *adc_data;
+};
+static struct pcap_chip pcap;
+
+static LIST_HEAD(event_list);
+static DEFINE_MUTEX(event_lock);
+static DEFINE_MUTEX(adc_lock);
+
+/* IO */
+static int ezx_pcap_putget(u32 *data)
+{
+	struct spi_transfer t;
+	struct spi_message m;
+
+	memset(&t, 0, sizeof t);
+	spi_message_init(&m);
+	t.len = 4;
+	t.tx_buf = (u8 *)data;
+	t.rx_buf = (u8 *)data;
+	t.bits_per_word = 32;
+	spi_message_add_tail(&t, &m);
+	return spi_sync(pcap.spi, &m);
+}
+
+int ezx_pcap_write(u8 reg_num, u32 value)
+{
+	value &= PCAP_REGISTER_VALUE_MASK;
+	value |= PCAP_REGISTER_WRITE_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+	return ezx_pcap_putget(&value);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_write);
+
+int ezx_pcap_read(u8 reg_num, u32 *value)
+{
+	*value = PCAP_REGISTER_READ_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+
+	return ezx_pcap_putget(value);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_read);
+
+/* Voltage regulators */
+int ezx_pcap_set_sw(u8 sw, u8 what, u8 val)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_LOWPWR, &tmp);
+	tmp &= ~(0xf << (sw + what));
+	tmp |= ((val & 0xf) << (sw + what));
+	return ezx_pcap_write(PCAP_REG_LOWPWR, tmp);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_set_sw);
+
+static u8 vreg_table[][5] = {
+	/*		EN	INDEX	MASK	STBY	LOWPWR	*/
+	[V1]	= {	1,	2,	0x7,	18,	0,	},
+	[V2]	= {	5,	6,	0x1,	19,	22,	},
+	[V3]	= {	7,	8,	0x7,	20,	23,	},
+	[V4]	= {	11,	12,	0x7,	21,	24,	},
+	[V5]	= {	15,	16,	0x3,	0xff,	0xff,	},
+	[V6]	= {	1,	0xff,	0x0,	0xff,	0xff,	},
+	/* FIXME: I have no idea of V7-V10 bits -WM */
+	[V7]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V8]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V9]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V10]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[VAUX1]	= {	1,	2,	0x3,	22,	23,	},
+	[VAUX2]	= {	4,	5,	0x3,	0,	1,	},
+	[VAUX3]	= {	7,	8,	0xf,	2,	3,	},
+	[VAUX4]	= {	12,	13,	0x3,	4,	5,	},
+	[VSIM]	= {	17,	18,	0x1,	0xff,	6,	},
+	[VSIM2]	= {	16,	0xff,	0x0,	0xff,	7,	},
+	[VVIB]	= {	19,	20,	0x3,	0xff,	0xff,	},
+	[VC]	= {	0xff,	0xff,	0x0,	24,	0xff,	},
+};
+
+int ezx_pcap_set_vreg(u8 vreg, u8 what, u8 val)
+{
+	struct pcap_platform_data *pdata = pcap.spi->dev.platform_data;
+	u8 reg, shift, mask;
+	u32 tmp;
+
+	switch (vreg) {
+	case V1 ... V5:
+		/* vreg1 is not accessible on port 2 */
+		if (pdata->config & PCAP_SECOND_PORT)
+			return -EINVAL;
+		reg = PCAP_REG_VREG1;
+		break;
+	case V6 ... V10:
+		reg = PCAP_REG_VREG2;
+		break;
+	case VAUX1 ... VC:
+		if ((what == V_LOWPWR || what == V_STBY) && vreg != VAUX1)
+			reg = PCAP_REG_LOWPWR;
+		else
+			reg = PCAP_REG_AUXVREG;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (what) {
+	case V_VAL:
+		shift = vreg_table[vreg][V_VAL];
+		mask = vreg_table[vreg][V_MASK];
+		break;
+	case V_EN:
+	case V_STBY:
+	case V_LOWPWR:
+		shift = vreg_table[vreg][what];
+		mask = 0x1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* invalid setting */
+	if (shift == 0xff || val > mask)
+		return -EINVAL;
+
+	ezx_pcap_read(reg, &tmp);
+	tmp &= ~(mask << shift);
+	tmp |= ((val & mask) << shift);
+	ezx_pcap_write(reg, tmp);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_set_vreg);
+
+/* ADC */
+void ezx_pcap_disable_adc(void)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADEN|PCAP_ADC_BATT_I_ADC|PCAP_ADC_BATT_I_POLARITY);
+	tmp |= (PCAP_ADC_TS_M_STANDBY << PCAP_ADC_TS_M_SHIFT);
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	mutex_unlock(&adc_lock);
+}
+
+static void ezx_pcap_adc_event(struct work_struct *unused)
+{
+	void (*adc_done)(void *);
+	void *adc_data;
+
+	if (!pcap.adc_done)
+		return;
+
+	adc_done = pcap.adc_done;
+	adc_data = pcap.adc_data;
+	pcap.adc_done = pcap.adc_data = NULL;
+
+	/* let caller get the results */
+	adc_done(adc_data);
+}
+
+void ezx_pcap_start_adc(u8 bank, u8 time, u32 flags,
+						void *adc_done, void *adc_data)
+{
+	u32 adc;
+	u32 adr;
+
+	mutex_lock(&adc_lock);
+
+	adc = flags | PCAP_ADC_ADEN;
+
+	if (bank == PCAP_ADC_BANK_1)
+		adc |= PCAP_ADC_AD_SEL1;
+
+	ezx_pcap_write(PCAP_REG_ADC, adc);
+
+	pcap.adc_done = adc_done;
+	pcap.adc_data = adc_data;
+
+	if (time == PCAP_ADC_T_NOW) {
+		ezx_pcap_read(PCAP_REG_ADR, &adr);
+		adr = PCAP_ADR_ASC;
+		ezx_pcap_write(PCAP_REG_ADR, adr);
+		return;
+	}
+
+	if (time == PCAP_ADC_T_IN_BURST)
+		adc |= (PCAP_ADC_ATO_IN_BURST << PCAP_ADC_ATO_SHIFT);
+
+	ezx_pcap_write(PCAP_REG_ADC, adc);
+
+	ezx_pcap_read(PCAP_REG_ADR, &adr);
+	adr &= ~PCAP_ADR_ONESHOT;
+	ezx_pcap_write(PCAP_REG_ADR, adr);
+	adr |= PCAP_ADR_ONESHOT;
+	ezx_pcap_write(PCAP_REG_ADR, adr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_start_adc);
+
+void ezx_pcap_get_adc_channel_result(u8 ch1, u8 ch2, u32 res[])
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADA1_MASK | PCAP_ADC_ADA2_MASK);
+	tmp |= (ch1 << PCAP_ADC_ADA1_SHIFT) | (ch2 << PCAP_ADC_ADA2_SHIFT);
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	ezx_pcap_read(PCAP_REG_ADR, &tmp);
+	res[0] = (tmp & PCAP_ADR_ADD1_MASK) >> PCAP_ADR_ADD1_SHIFT;
+	res[1] = (tmp & PCAP_ADR_ADD2_MASK) >> PCAP_ADR_ADD2_SHIFT;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_get_adc_channel_result);
+
+void ezx_pcap_get_adc_bank_result(u32 res[])
+{
+	int x;
+	u32 tmp[2];
+
+	for (x = 0; x < 7; x += 2) {
+		ezx_pcap_get_adc_channel_result(x, (x+1) % 6, tmp);
+		res[x] = tmp[0];
+		if ((x + 1) < 7)
+			res[x+1] = tmp[1];
+		else
+			res[x+1] = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_get_adc_bank_result);
+
+static void adc_complete(void *data)
+{
+	complete(data);
+}
+
+void ezx_pcap_do_general_adc(u8 bank, u8 ch, u32 *res)
+{
+	u32 tmp[2];
+	DECLARE_COMPLETION_ONSTACK(done);
+
+	ezx_pcap_start_adc(bank, PCAP_ADC_T_NOW, 0, adc_complete, &done);
+	wait_for_completion(&done);
+	ezx_pcap_get_adc_channel_result(ch, 0, tmp);
+	ezx_pcap_disable_adc();
+
+	*res = tmp[0];
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_do_general_adc);
+
+/* event handling */
+static irqreturn_t pcap_irq_handler(int irq, void *dev_id)
+{
+	queue_work(pcap.workqueue, &pcap.work);
+	return IRQ_HANDLED;
+}
+
+static void pcap_work(struct work_struct *_pcap)
+{
+	u32 msr;
+	u32 isr;
+	u32 service;
+	struct pcap_event *cb;
+
+	mutex_lock(&event_lock);
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	ezx_pcap_read(PCAP_REG_ISR, &isr);
+	isr &= ~msr;
+
+	list_for_each_entry(cb, &event_list, node) {
+		service = isr & cb->events;
+		if (service) {
+			ezx_pcap_write(PCAP_REG_ISR, service);
+			cb->callback(service, cb->data);
+		}
+	}
+	mutex_unlock(&event_lock);
+}
+
+void ezx_pcap_mask_event(u32 events)
+{
+	u32 msr;
+
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	msr |= events;
+	ezx_pcap_write(PCAP_REG_MSR, msr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_mask_event);
+
+void ezx_pcap_unmask_event(u32 events)
+{
+	u32 msr;
+
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	msr &= ~events;
+	ezx_pcap_write(PCAP_REG_MSR, msr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_unmask_event);
+
+int ezx_pcap_register_event(u32 events, void *callback, char *label)
+{
+	struct pcap_event *cb;
+
+	cb = kzalloc(sizeof(struct pcap_event), GFP_KERNEL);
+	if (!cb)
+		return -ENOMEM;
+
+	cb->label = label;
+	cb->events = events;
+	cb->callback = callback;
+
+	mutex_lock(&event_lock);
+	list_add_tail(&cb->node, &event_list);
+	mutex_unlock(&event_lock);
+
+	ezx_pcap_unmask_event(events);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_register_event);
+
+int ezx_pcap_unregister_event(u32 events)
+{
+	int ret = -EINVAL;
+	struct pcap_event *cb;
+	struct pcap_event *store;
+
+	ezx_pcap_mask_event(events);
+
+	mutex_lock(&event_lock);
+	list_for_each_entry_safe(cb, store, &event_list, node) {
+		if (cb->events & events) {
+			list_del(&cb->node);
+			kfree(cb);
+			ret = 0;
+		}
+	}
+	mutex_unlock(&event_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_unregister_event);
+
+/* sysfs interface */
+static ssize_t pcap_show_regs(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	unsigned int reg, val;
+	char *p = buf;
+
+	for (reg = 0; reg < 32; reg++) {
+		ezx_pcap_read(reg, &val);
+		p += sprintf(p, "%02d %08x\n", reg, val);
+	}
+	return p - buf;
+}
+
+static ssize_t pcap_store_regs(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	unsigned int reg, val;
+	char *p = (char *)buf;
+
+	while (p < (buf + size)) {
+		if ((sscanf(p, "%u %x\n", &reg, &val) != 2) ||
+			reg < 0 || reg >= 32)
+			return -EINVAL;
+		p = strchr(p, '\n') + 1;
+	}
+
+	p = (char *)buf;
+	while (p < (buf + size)) {
+		sscanf(p, "%u %x\n", &reg, &val);
+		ezx_pcap_write(reg, val);
+		p = strchr(p, '\n') + 1;
+	}
+
+	return size;
+}
+
+static ssize_t pcap_show_adc_coin(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_COIN, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_battery(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_BATT, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_bplus(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_BPLUS, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_mobportb(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_MOBPORTB, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_temperature(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_TEMPERATURE, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_chargerid(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_CHARGER_ID, &res);
+	return sprintf(buf, "%d\n", res);
+}
+
+static DEVICE_ATTR(regs, 0600, pcap_show_regs, pcap_store_regs);
+static DEVICE_ATTR(adc_coin, 0400, pcap_show_adc_coin, NULL);
+static DEVICE_ATTR(adc_battery, 0400, pcap_show_adc_battery, NULL);
+static DEVICE_ATTR(adc_bplus, 0400, pcap_show_adc_bplus, NULL);
+static DEVICE_ATTR(adc_mobportb, 0400, pcap_show_adc_mobportb, NULL);
+static DEVICE_ATTR(adc_temperature, 0400, pcap_show_adc_temperature, NULL);
+static DEVICE_ATTR(adc_chargerid, 0400, pcap_show_adc_chargerid, NULL);
+
+static int ezx_pcap_setup_sysfs(int create)
+{
+	int ret = 0;
+
+	if (!create)
+		goto remove_all;
+
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_regs);
+	if (ret)
+		goto ret;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_coin);
+	if (ret)
+		goto fail1;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_battery);
+	if (ret)
+		goto fail2;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_bplus);
+	if (ret)
+		goto fail3;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_mobportb);
+	if (ret)
+		goto fail4;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_temperature);
+	if (ret)
+		goto fail5;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_chargerid);
+	if (ret)
+		goto fail6;
+
+	goto ret;
+
+remove_all:
+fail6:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_temperature);
+fail5:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_mobportb);
+fail4:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_bplus);
+fail3:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_battery);
+fail2:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_coin);
+fail1:	device_remove_file(&pcap.spi->dev, &dev_attr_regs);
+ret:	return ret;
+}
+
+static int ezx_pcap_remove(struct spi_device *spi)
+{
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+
+	ezx_pcap_setup_sysfs(0);
+	destroy_workqueue(pcap.workqueue);
+	ezx_pcap_unregister_event(PCAP_MASK_ALL_INTERRUPT);
+	free_irq(pdata->irq, NULL);
+
+	return 0;
+}
+
+static int __devinit ezx_pcap_probe(struct spi_device *spi)
+{
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	int ret = -ENODEV;
+
+	if (!pdata)
+		goto ret;
+
+	pcap.spi = spi;
+
+	INIT_WORK(&pcap.work, pcap_work);
+	pcap.workqueue = create_singlethread_workqueue("pcapd");
+	if (!pcap.workqueue) {
+		dev_err(&spi->dev, "cant create pcap thread\n");
+		goto ret;
+	}
+
+	/* redirect interrupts to AP */
+	if (!(pdata->config & PCAP_SECOND_PORT))
+		ezx_pcap_write(PCAP_REG_INT_SEL, PCAP_IRQ_ADCDONE2);
+
+	/* set board-specific settings */
+	if (pdata->init)
+		pdata->init();
+
+	ret = ezx_pcap_setup_sysfs(1);
+	if (ret) {
+		dev_err(&spi->dev, "cant create sysfs files\n");
+		goto wq_destroy;
+	}
+
+	/* mask/ack all PCAP interrupts */
+	ezx_pcap_write(PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT);
+	ezx_pcap_write(PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
+
+	/* register irq for pcap */
+	ret = request_irq(pdata->irq, pcap_irq_handler, IRQF_DISABLED,
+		"PCAP", NULL);
+	if (ret) {
+		dev_err(&spi->dev, "cant request IRQ\n");
+		goto wq_destroy;
+	}
+	set_irq_type(pdata->irq, IRQ_TYPE_EDGE_RISING);
+	set_irq_wake(pdata->irq, 1);
+
+	ezx_pcap_register_event((pdata->config & PCAP_SECOND_PORT) ?
+			PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE,
+			ezx_pcap_adc_event, "ADC");
+	return 0;
+
+wq_destroy:
+	destroy_workqueue(pcap.workqueue);
+ret:
+	return ret;
+}
+
+static struct spi_driver ezxpcap_driver = {
+	.probe  = ezx_pcap_probe,
+	.remove = ezx_pcap_remove,
+	.driver = {
+		.name   = "ezx-pcap",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init ezx_pcap_init(void)
+{
+	return spi_register_driver(&ezxpcap_driver);
+}
+
+static void __exit ezx_pcap_exit(void)
+{
+	spi_unregister_driver(&ezxpcap_driver);
+}
+
+module_init(ezx_pcap_init);
+module_exit(ezx_pcap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h
new file mode 100644
index 0000000..e046ee9
--- /dev/null
+++ b/include/linux/mfd/ezx-pcap.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2007 Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * For further information, please see http://wiki.openezx.org/PCAP2
+ */
+
+#ifndef EZX_PCAP_H
+#define EZX_PCAP_H
+
+struct pcap_platform_data {
+	unsigned int irq;
+	unsigned int config;
+	void (*init) (void);	/* board specific init */
+};
+
+#define PCAP_SECOND_PORT	1
+
+#define PCAP_REGISTER_WRITE_OP_BIT	0x80000000
+#define PCAP_REGISTER_READ_OP_BIT	0x00000000
+
+#define PCAP_REGISTER_VALUE_MASK	0x01ffffff
+#define PCAP_REGISTER_ADDRESS_MASK	0x7c000000
+#define PCAP_REGISTER_ADDRESS_SHIFT	26
+#define PCAP_REGISTER_NUMBER		32
+#define PCAP_CLEAR_INTERRUPT_REGISTER	0x01ffffff
+#define PCAP_MASK_ALL_INTERRUPT		0x01ffffff
+
+/* registers acessible by both pcap ports */
+#define PCAP_REG_ISR		0x0	/* Interrupt Status */
+#define PCAP_REG_MSR		0x1	/* Interrupt Mask */
+#define PCAP_REG_PSTAT		0x2	/* Processor Status */
+#define PCAP_REG_VREG2		0x6	/* Regulator Bank 2 Control */
+#define PCAP_REG_AUXVREG	0x7	/* Auxiliary Regulator Control */
+#define PCAP_REG_BATT		0x8	/* Battery Control */
+#define PCAP_REG_ADC		0x9	/* AD Control */
+#define PCAP_REG_ADR		0xa	/* AD Result */
+#define PCAP_REG_CODEC		0xb	/* Audio Codec Control */
+#define PCAP_REG_RX_AMPS	0xc	/* RX Audio Amplifiers Control */
+#define PCAP_REG_ST_DAC		0xd	/* Stereo DAC Control */
+#define PCAP_REG_BUSCTRL	0x14	/* Connectivity Control */
+#define PCAP_REG_PERIPH		0x15	/* Peripheral Control */
+#define PCAP_REG_LOWPWR		0x18	/* Regulator Low Power Control */
+#define PCAP_REG_TX_AMPS	0x1a	/* TX Audio Amplifiers Control */
+#define PCAP_REG_GP		0x1b	/* General Purpose */
+#define PCAP_REG_TEST1		0x1c
+#define PCAP_REG_TEST2		0x1d
+#define PCAP_REG_VENDOR_TEST1	0x1e
+#define PCAP_REG_VENDOR_TEST2	0x1f
+
+/* registers acessible by pcap port 1 only (a1200, e2 & e6) */
+#define PCAP_REG_INT_SEL	0x3	/* Interrupt Select */
+#define PCAP_REG_SWCTRL		0x4	/* Switching Regulator Control */
+#define PCAP_REG_VREG1		0x5	/* Regulator Bank 1 Control */
+#define PCAP_REG_RTC_TOD	0xe	/* RTC Time of Day */
+#define PCAP_REG_RTC_TODA	0xf	/* RTC Time of Day Alarm */
+#define PCAP_REG_RTC_DAY	0x10	/* RTC Day */
+#define PCAP_REG_RTC_DAYA	0x11	/* RTC Day Alarm */
+#define PCAP_REG_MTRTMR		0x12	/* AD Monitor Timer */
+#define PCAP_REG_PWR		0x13	/* Power Control */
+#define PCAP_REG_AUXVREG_MASK	0x16	/* Auxiliary Regulator Mask */
+#define PCAP_REG_VENDOR_REV	0x17
+#define PCAP_REG_PERIPH_MASK	0x19	/* Peripheral Mask */
+
+/* interrupts - registers 0x0, 0x1, 0x2, 0x3 */
+#define PCAP_IRQ_ADCDONE	(1 << 0)	/* AD Conversion Done Port 1 */
+#define PCAP_IRQ_TS		(1 << 1)	/* Touch Screen */
+#define PCAP_IRQ_1HZ		(1 << 2)	/* 1HZ Timer */
+#define PCAP_IRQ_WH		(1 << 3)	/* "...high"??? */
+#define PCAP_IRQ_WL		(1 << 4)	/* "...low"??? */
+#define PCAP_IRQ_TODA		(1 << 5)	/* RTC Time Of Day?
+						   (see "RTC_TODA") */
+#define PCAP_IRQ_USB4V		(1 << 6)	/* USB OTG */
+#define PCAP_IRQ_ONOFF		(1 << 7)	/* in blob: "ONOFFSNS" */
+#define PCAP_IRQ_ONOFF2		(1 << 8)	/* in blob: "ONOFFSNS2" */
+#define PCAP_IRQ_USB1V		(1 << 9)	/* USB below 1volt???
+						   in blob: "USBDET_1V" */
+#define PCAP_IRQ_MOBPORT	(1 << 10)	/* GSM-related?? ("mobport",
+						   see 958_MotDoc.pdf);
+						   in blob: "MOBSENSB" */
+#define PCAP_IRQ_MB2		(1 << 11)	/* Mic; in blob: "MB2SNS" */
+#define PCAP_IRQ_A1		(1 << 12)	/* Audio jack;
+						   in blob: "A1SNS" */
+#define PCAP_IRQ_ST		(1 << 13)	/* called "MSTB" in blob */
+#define PCAP_IRQ_PC		(1 << 14)
+#define PCAP_IRQ_WARM		(1 << 15)
+#define PCAP_IRQ_EOL		(1 << 16)	/*  battery End Of Life???
+						   (see below);
+						   in blob: "EOL_STAT" */
+#define PCAP_IRQ_CLK		(1 << 17)	/* called "CLK_STAT" in blob */
+#define PCAP_IRQ_SYSRST		(1 << 18)
+#define PCAP_IRQ_DUMMY		(1 << 19)
+#define PCAP_IRQ_ADCDONE2	(1 << 20)	/* AD Conversion Done Port 2 */
+#define PCAP_IRQ_SOFTRESET	(1 << 21)
+#define PCAP_IRQ_MNEXB		(1 << 22)
+
+/* voltage regulators */
+#define V1		0
+#define V2		1
+#define V3		2
+#define V4		3
+#define V5		4
+#define V6		5
+#define V7		6
+#define V8		7
+#define V9		8
+#define V10		9
+#define VAUX1		10
+#define VAUX2		11
+#define VAUX3		12
+#define VAUX4		13
+#define VSIM		14
+#define VSIM2		15
+#define VVIB		16
+#define VC		17
+
+#define V_EN		0
+#define V_VAL		1
+#define V_MASK		2
+#define V_STBY		3
+#define V_LOWPWR	4
+
+#define PCAP_BATT_DAC_MASK		0x000000ff
+#define PCAP_BATT_DAC_SHIFT		0
+#define PCAP_BATT_B_FDBK		(1 << 8)
+#define PCAP_BATT_EXT_ISENSE		(1 << 9)
+#define PCAP_BATT_V_COIN_MASK		0x00003c00
+#define PCAP_BATT_V_COIN_SHIFT		10
+#define PCAP_BATT_I_COIN		(1 << 14)
+#define PCAP_BATT_COIN_CH_EN		(1 << 15)
+#define PCAP_BATT_EOL_SEL_MASK		0x000e0000
+#define PCAP_BATT_EOL_SEL_SHIFT		17
+#define PCAP_BATT_EOL_CMP_EN		(1 << 20)
+#define PCAP_BATT_BATT_DET_EN		(1 << 21)
+#define PCAP_BATT_THERMBIAS_CTRL	(1 << 22)
+
+#define PCAP_ADC_ADEN			(1 << 0)
+#define PCAP_ADC_RAND			(1 << 1)
+#define PCAP_ADC_AD_SEL1		(1 << 2)
+#define PCAP_ADC_AD_SEL2		(1 << 3)
+#define PCAP_ADC_ADA1_MASK		0x00000070
+#define PCAP_ADC_ADA1_SHIFT		4
+#define PCAP_ADC_ADA2_MASK		0x00000380
+#define PCAP_ADC_ADA2_SHIFT		7
+#define PCAP_ADC_ATO_MASK		0x00003c00
+#define PCAP_ADC_ATO_SHIFT		10
+#define PCAP_ADC_ATOX			(1 << 14)
+#define PCAP_ADC_MTR1			(1 << 15)
+#define PCAP_ADC_MTR2			(1 << 16)
+#define PCAP_ADC_TS_M_MASK		0x000e0000
+#define PCAP_ADC_TS_M_SHIFT		17
+#define PCAP_ADC_TS_REF_LOWPWR		(1 << 20)
+#define PCAP_ADC_TS_REFENB		(1 << 21)
+#define PCAP_ADC_BATT_I_POLARITY	(1 << 22)
+#define PCAP_ADC_BATT_I_ADC		(1 << 23)
+
+#define PCAP_ADC_BANK_0			0
+#define PCAP_ADC_BANK_1			1
+/* ADC bank 0 */
+#define PCAP_ADC_CH_COIN		0
+#define PCAP_ADC_CH_BATT		1
+#define PCAP_ADC_CH_BPLUS		2
+#define PCAP_ADC_CH_MOBPORTB		3
+#define PCAP_ADC_CH_TEMPERATURE		4
+#define PCAP_ADC_CH_CHARGER_ID		5
+#define PCAP_ADC_CH_AD6			6
+/* ADC bank 1 */
+#define PCAP_ADC_CH_AD7			0
+#define PCAP_ADC_CH_AD8			1
+#define PCAP_ADC_CH_AD9			2
+#define PCAP_ADC_CH_TS_X1		3
+#define PCAP_ADC_CH_TS_X2		4
+#define PCAP_ADC_CH_TS_Y1		5
+#define PCAP_ADC_CH_TS_Y2		6
+
+#define PCAP_ADC_T_NOW			0
+#define PCAP_ADC_T_IN_BURST		1
+#define PCAP_ADC_T_OUT_BURST		2
+
+#define PCAP_ADC_ATO_IN_BURST		6
+#define PCAP_ADC_ATO_OUT_BURST		0
+
+#define PCAP_ADC_TS_M_XY		1
+#define PCAP_ADC_TS_M_PRESSURE		2
+#define PCAP_ADC_TS_M_PLATE_X		3
+#define PCAP_ADC_TS_M_PLATE_Y		4
+#define PCAP_ADC_TS_M_STANDBY		5
+#define PCAP_ADC_TS_M_NONTS		6
+
+#define PCAP_ADR_ADD1_MASK		0x000003ff
+#define PCAP_ADR_ADD1_SHIFT		0
+#define PCAP_ADR_ADD2_MASK		0x000ffc00
+#define PCAP_ADR_ADD2_SHIFT		10
+#define PCAP_ADR_ADINC1			(1 << 20)
+#define PCAP_ADR_ADINC2			(1 << 21)
+#define PCAP_ADR_ASC			(1 << 22)
+#define PCAP_ADR_ONESHOT		(1 << 23)
+
+#define PCAP_BUSCTRL_FSENB		(1 << 0)
+#define PCAP_BUSCTRL_USB_SUSPEND	(1 << 1)
+#define PCAP_BUSCTRL_USB_PU		(1 << 2)
+#define PCAP_BUSCTRL_USB_PD		(1 << 3)
+#define PCAP_BUSCTRL_VUSB_EN		(1 << 4)
+#define PCAP_BUSCTRL_USB_PS		(1 << 5)
+#define PCAP_BUSCTRL_VUSB_MSTR_EN	(1 << 6)
+#define PCAP_BUSCTRL_VBUS_PD_ENB	(1 << 7)
+#define PCAP_BUSCTRL_CURRLIM		(1 << 8)
+#define PCAP_BUSCTRL_RS232ENB		(1 << 9)
+#define PCAP_BUSCTRL_RS232_DIR		(1 << 10)
+#define PCAP_BUSCTRL_SE0_CONN		(1 << 11)
+#define PCAP_BUSCTRL_USB_PDM		(1 << 12)
+#define PCAP_BUSCTRL_BUS_PRI_ADJ	(1 << 24)
+
+/* leds */
+#define PCAP_LED0		0
+#define PCAP_LED1		1
+#define PCAP_BL0		2
+#define PCAP_BL1		3
+#define PCAP_LED_3MA		0
+#define PCAP_LED_4MA		1
+#define PCAP_LED_5MA		2
+#define PCAP_LED_9MA		3
+#define PCAP_LED_GPIO_VAL_MASK	0x00ffffff
+#define PCAP_LED_GPIO_EN	0x01000000
+#define PCAP_LED_GPIO_INVERT	0x02000000
+#define PCAP_LED_T_MASK		0xf
+#define PCAP_LED_C_MASK		0x3
+#define PCAP_BL_MASK		0x1f
+#define PCAP_BL0_SHIFT		0
+#define PCAP_LED0_EN		(1 << 5)
+#define PCAP_LED1_EN		(1 << 6)
+#define PCAP_LED0_T_SHIFT	7
+#define PCAP_LED1_T_SHIFT	11
+#define PCAP_LED0_C_SHIFT	15
+#define PCAP_LED1_C_SHIFT	17
+#define PCAP_BL1_SHIFT		20
+
+/* RTC */
+#define PCAP_RTC_DAY_MASK	0x3fff
+#define PCAP_RTC_TOD_MASK	0xffff
+#define PCAP_RTC_PC_MASK	0x7
+#define SEC_PER_DAY		86400
+
+/* LOWPWR */
+#define SW1		8
+#define SW2		16
+
+#define SW_MODE		0
+#define SW_VOLTAGE	4
+
+#define SW_VOLTAGE_900	0x0
+#define SW_VOLTAGE_950	0x1
+#define SW_VOLTAGE_1000	0x2
+#define SW_VOLTAGE_1050	0x3
+#define SW_VOLTAGE_1100	0x4
+#define SW_VOLTAGE_1150	0x5
+#define SW_VOLTAGE_1200	0x6
+#define SW_VOLTAGE_1250	0x7
+#define SW_VOLTAGE_1300	0x8
+#define SW_VOLTAGE_1350	0x9
+#define SW_VOLTAGE_1400	0xa
+#define SW_VOLTAGE_1500	0xb
+#define SW_VOLTAGE_1600	0xc
+#define SW_VOLTAGE_1875	0xd
+#define SW_VOLTAGE_2250	0xe
+#define SW_VOLTAGE_4400	0xf
+
+int ezx_pcap_write(u8, u32);
+int ezx_pcap_read(u8, u32 *);
+int ezx_pcap_set_sw(u8, u8, u8);
+int ezx_pcap_set_vreg(u8, u8, u8);
+void ezx_pcap_start_adc(u8, u8, u32, void *, void *);
+void ezx_pcap_get_adc_channel_result(u8, u8, u32[]);
+void ezx_pcap_get_adc_bank_result(u32[]);
+void ezx_pcap_disable_adc(void);
+void ezx_pcap_do_general_adc(u8, u8, u32 *);
+void ezx_pcap_do_batt_adc(int, u32[]);
+int ezx_pcap_register_event(u32, void *, char *);
+int ezx_pcap_unregister_event(u32);
+void ezx_pcap_mask_event(u32);
+void ezx_pcap_unmask_event(u32);
+
+struct pcap_event {
+	struct list_head node;
+	char *label;
+	u32 events;
+	void (*callback) (u32, void *);
+	void *data;
+};
+
+#endif
-- 
tg: (7f0f598..) ezx/pcap (depends on: master)

-- 

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]   ` <20081121160521.016544616-cQQG9CVUopzFITZdfPi31ZcF1vblOVnWhIvA6WVW+J8@public.gmane.org>
@ 2008-11-22  5:25     ` David Brownell
  2008-11-22 14:01       ` [spi-devel-general] " Eric Miao
       [not found]       ` <200811212125.49068.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 2 replies; 16+ messages in thread
From: David Brownell @ 2008-11-22  5:25 UTC (permalink / raw)
  To: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

On Friday 21 November 2008, stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org wrote:
> Since the last submission we are also using the spi subsystem and
> pxa2xx-spi instead of ssp.c directly as before.

I took a quick glance at this and it seemed like it should be
able to build without depending on PXA ... should certainly
not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
either.

It's also worth removing the reverse dependencies ("select X")
from Kconfig; they don't work very well for the things which
those dependencies rely on.

- Dave

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [spi-devel-general] [patch 05/14] mfd: PCAP2 driver
  2008-11-22  5:25     ` David Brownell
@ 2008-11-22 14:01       ` Eric Miao
       [not found]         ` <f17812d70811220601p1d7af668mf3265224179753ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
       [not found]       ` <200811212125.49068.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  1 sibling, 1 reply; 16+ messages in thread
From: Eric Miao @ 2008-11-22 14:01 UTC (permalink / raw)
  To: David Brownell
  Cc: spi-devel-general, stefan, sameo, linux-arm-kernel,
	Daniel Ribeiro, linux-kernel

On Sat, Nov 22, 2008 at 1:25 PM, David Brownell <david-b@pacbell.net> wrote:
> On Friday 21 November 2008, stefan@datenfreihafen.org wrote:
>> Since the last submission we are also using the spi subsystem and
>> pxa2xx-spi instead of ssp.c directly as before.
>
> I took a quick glance at this and it seemed like it should be
> able to build without depending on PXA ... should certainly
> not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
> look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
> either.
>
> It's also worth removing the reverse dependencies ("select X")
> from Kconfig; they don't work very well for the things which
> those dependencies rely on.
>
> - Dave
>

I'm wondering if it call fall into the regulator framework, along with
a hwmon driver with its attributes being exported by sysfs.

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]         ` <f17812d70811220601p1d7af668mf3265224179753ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2008-11-22 15:54           ` Daniel Ribeiro
  2008-11-22 19:08             ` David Brownell
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Ribeiro @ 2008-11-22 15:54 UTC (permalink / raw)
  To: Eric Miao
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Brownell,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ

Em Sáb, 2008-11-22 às 22:01 +0800, Eric Miao escreveu:
> On Sat, Nov 22, 2008 at 1:25 PM, David Brownell <david-b@pacbell.net> wrote:
> > On Friday 21 November 2008, stefan@datenfreihafen.org wrote:
> >> Since the last submission we are also using the spi subsystem and
> >> pxa2xx-spi instead of ssp.c directly as before.
> >
> > I took a quick glance at this and it seemed like it should be
> > able to build without depending on PXA ... should certainly
> > not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
> > look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
> > either.
> >
> > It's also worth removing the reverse dependencies ("select X")
> > from Kconfig; they don't work very well for the things which
> > those dependencies rely on.
> >
> I'm wondering if it call fall into the regulator framework, along with
> a hwmon driver with its attributes being exported by sysfs.

The ADC is also used by the touchscreen driver, and later will be used
for accessory detection (usb otg, charger, EMU (audio and uart on usb
port)).

Currently the only user for the voltage regulators is the MMC, i plan to
use the regulator subsystem when more users arise.

-- 
Daniel Ribeiro


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]       ` <200811212125.49068.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-22 17:12         ` Daniel Ribeiro
  2008-11-22 19:19           ` David Brownell
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Ribeiro @ 2008-11-22 17:12 UTC (permalink / raw)
  To: David Brownell
  Cc: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ

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

Em Sex, 2008-11-21 às 21:25 -0800, David Brownell escreveu:
> I took a quick glance at this and it seemed like it should be
> able to build without depending on PXA ... should certainly
> not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
> look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
> either.
> 
> It's also worth removing the reverse dependencies ("select X")
> from Kconfig; they don't work very well for the things which
> those dependencies rely on.

Above comments are integrated on the attached patch.

-- 
Daniel Ribeiro

[-- Attachment #2: pcap.diff --]
[-- Type: message/rfc822, Size: 26798 bytes --]

From: Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: sameo-RWuK6r/cQWRpLGFMi4vTTA@public.gmane.org
Cc: linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW@public.gmane.org, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: mfd: PCAP driver
Date: Sat, 22 Nov 2008 15:11:49 -0200
Message-ID: <1227373909.19591.65.camel@brutus>

The PCAP Asic as present on EZX phones is a multi function device with
voltage regulators, irq expander, touch screen controller and audio
codec. It is connected to the processor via SPI, this driver provides
read/write functions to its registers.

Since the last submission we are also using the spi subsystem and
pxa2xx-spi instead of ssp.c directly as before.

Signed-off-by: Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

---
 arch/arm/mach-pxa/Kconfig    |    1 +
 drivers/mfd/Kconfig          |    7 +
 drivers/mfd/Makefile         |    2 +
 drivers/mfd/ezx-pcap.c       |  591 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/ezx-pcap.h |  290 +++++++++++++++++++++
 5 files changed, 891 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index a062235..d64c15a 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -351,6 +351,7 @@ config PXA_EZX
 	select PXA27x
 	select IWMMXT
 	select HAVE_PWM
+	select EZX_PCAP
 
 config MACH_EZX_A780
 	bool "Motorola EZX A780"
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2572773..79566c2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -153,6 +153,13 @@ config MFD_WM8350_I2C
 	  I2C as the control interface.  Additional options must be
 	  selected to enable support for the functionality of the chip.
 
+config EZX_PCAP
+	bool "PCAP Support"
+	depends on PXA_EZX
+	help
+	  This enables the PCAP ASIC present on EZX Phones. This is
+	  needed for MMC, TouchScreen, Sound, USB, etc..
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9a5ad8a..cbf32e0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -21,6 +21,8 @@ obj-$(CONFIG_TWL4030_CORE)	+= twl4030-core.o twl4030-irq.o
 
 obj-$(CONFIG_MFD_CORE)		+= mfd-core.o
 
+obj-$(CONFIG_EZX_PCAP)		+= ezx-pcap.o
+
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
new file mode 100644
index 0000000..939f2ac
--- /dev/null
+++ b/drivers/mfd/ezx-pcap.c
@@ -0,0 +1,591 @@
+/*
+ * Driver for Motorola PCAP2 as present in EZX phones
+ *
+ * Copyright (C) 2006 Harald Welte <laforge-WB6LKoYH/xlAfugRpC6u6w@public.gmane.org>
+ * Copyright (C) 2007-2008 Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/proc_fs.h>
+#include <linux/mfd/ezx-pcap.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+
+struct pcap_chip {
+	struct spi_device *spi;
+	struct work_struct work;
+	struct workqueue_struct *workqueue;
+	void (*adc_done)(void *);
+	void *adc_data;
+};
+static struct pcap_chip pcap;
+
+static LIST_HEAD(event_list);
+static DEFINE_MUTEX(event_lock);
+static DEFINE_MUTEX(adc_lock);
+
+/* IO */
+static int ezx_pcap_putget(u32 *data)
+{
+	struct spi_transfer t;
+	struct spi_message m;
+
+	memset(&t, 0, sizeof t);
+	spi_message_init(&m);
+	t.len = 4;
+	t.tx_buf = (u8 *)data;
+	t.rx_buf = (u8 *)data;
+	t.bits_per_word = 32;
+	spi_message_add_tail(&t, &m);
+	return spi_sync(pcap.spi, &m);
+}
+
+int ezx_pcap_write(u8 reg_num, u32 value)
+{
+	value &= PCAP_REGISTER_VALUE_MASK;
+	value |= PCAP_REGISTER_WRITE_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+	return ezx_pcap_putget(&value);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_write);
+
+int ezx_pcap_read(u8 reg_num, u32 *value)
+{
+	*value = PCAP_REGISTER_READ_OP_BIT
+		| (reg_num << PCAP_REGISTER_ADDRESS_SHIFT);
+
+	return ezx_pcap_putget(value);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_read);
+
+/* Voltage regulators */
+int ezx_pcap_set_sw(u8 sw, u8 what, u8 val)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_LOWPWR, &tmp);
+	tmp &= ~(0xf << (sw + what));
+	tmp |= ((val & 0xf) << (sw + what));
+	return ezx_pcap_write(PCAP_REG_LOWPWR, tmp);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_set_sw);
+
+static u8 vreg_table[][5] = {
+	/*		EN	INDEX	MASK	STBY	LOWPWR	*/
+	[V1]	= {	1,	2,	0x7,	18,	0,	},
+	[V2]	= {	5,	6,	0x1,	19,	22,	},
+	[V3]	= {	7,	8,	0x7,	20,	23,	},
+	[V4]	= {	11,	12,	0x7,	21,	24,	},
+	[V5]	= {	15,	16,	0x3,	0xff,	0xff,	},
+	[V6]	= {	1,	0xff,	0x0,	0xff,	0xff,	},
+	/* FIXME: I have no idea of V7-V10 bits -WM */
+	[V7]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V8]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V9]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[V10]	= {	0xff,	0xff,	0x0,	0xff,	0xff,	},
+	[VAUX1]	= {	1,	2,	0x3,	22,	23,	},
+	[VAUX2]	= {	4,	5,	0x3,	0,	1,	},
+	[VAUX3]	= {	7,	8,	0xf,	2,	3,	},
+	[VAUX4]	= {	12,	13,	0x3,	4,	5,	},
+	[VSIM]	= {	17,	18,	0x1,	0xff,	6,	},
+	[VSIM2]	= {	16,	0xff,	0x0,	0xff,	7,	},
+	[VVIB]	= {	19,	20,	0x3,	0xff,	0xff,	},
+	[VC]	= {	0xff,	0xff,	0x0,	24,	0xff,	},
+};
+
+int ezx_pcap_set_vreg(u8 vreg, u8 what, u8 val)
+{
+	struct pcap_platform_data *pdata = pcap.spi->dev.platform_data;
+	u8 reg, shift, mask;
+	u32 tmp;
+
+	switch (vreg) {
+	case V1 ... V5:
+		/* vreg1 is not accessible on port 2 */
+		if (pdata->config & PCAP_SECOND_PORT)
+			return -EINVAL;
+		reg = PCAP_REG_VREG1;
+		break;
+	case V6 ... V10:
+		reg = PCAP_REG_VREG2;
+		break;
+	case VAUX1 ... VC:
+		if ((what == V_LOWPWR || what == V_STBY) && vreg != VAUX1)
+			reg = PCAP_REG_LOWPWR;
+		else
+			reg = PCAP_REG_AUXVREG;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (what) {
+	case V_VAL:
+		shift = vreg_table[vreg][V_VAL];
+		mask = vreg_table[vreg][V_MASK];
+		break;
+	case V_EN:
+	case V_STBY:
+	case V_LOWPWR:
+		shift = vreg_table[vreg][what];
+		mask = 0x1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* invalid setting */
+	if (shift == 0xff || val > mask)
+		return -EINVAL;
+
+	ezx_pcap_read(reg, &tmp);
+	tmp &= ~(mask << shift);
+	tmp |= ((val & mask) << shift);
+	ezx_pcap_write(reg, tmp);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_set_vreg);
+
+/* ADC */
+void ezx_pcap_disable_adc(void)
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADEN|PCAP_ADC_BATT_I_ADC|PCAP_ADC_BATT_I_POLARITY);
+	tmp |= (PCAP_ADC_TS_M_STANDBY << PCAP_ADC_TS_M_SHIFT);
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	mutex_unlock(&adc_lock);
+}
+
+static void ezx_pcap_adc_event(u32 flags, void *data)
+{
+	void (*adc_done)(void *);
+	void *adc_data;
+
+	if (!pcap.adc_done)
+		return;
+
+	adc_done = pcap.adc_done;
+	adc_data = pcap.adc_data;
+	pcap.adc_done = pcap.adc_data = NULL;
+
+	/* let caller get the results */
+	adc_done(adc_data);
+}
+
+void ezx_pcap_start_adc(u8 bank, u8 time, u32 flags,
+						void *adc_done, void *adc_data)
+{
+	u32 adc;
+	u32 adr;
+
+	mutex_lock(&adc_lock);
+
+	adc = flags | PCAP_ADC_ADEN;
+
+	if (bank == PCAP_ADC_BANK_1)
+		adc |= PCAP_ADC_AD_SEL1;
+
+	ezx_pcap_write(PCAP_REG_ADC, adc);
+
+	pcap.adc_done = adc_done;
+	pcap.adc_data = adc_data;
+
+	if (time == PCAP_ADC_T_NOW) {
+		ezx_pcap_read(PCAP_REG_ADR, &adr);
+		adr = PCAP_ADR_ASC;
+		ezx_pcap_write(PCAP_REG_ADR, adr);
+		return;
+	}
+
+	if (time == PCAP_ADC_T_IN_BURST)
+		adc |= (PCAP_ADC_ATO_IN_BURST << PCAP_ADC_ATO_SHIFT);
+
+	ezx_pcap_write(PCAP_REG_ADC, adc);
+
+	ezx_pcap_read(PCAP_REG_ADR, &adr);
+	adr &= ~PCAP_ADR_ONESHOT;
+	ezx_pcap_write(PCAP_REG_ADR, adr);
+	adr |= PCAP_ADR_ONESHOT;
+	ezx_pcap_write(PCAP_REG_ADR, adr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_start_adc);
+
+void ezx_pcap_get_adc_channel_result(u8 ch1, u8 ch2, u32 res[])
+{
+	u32 tmp;
+
+	ezx_pcap_read(PCAP_REG_ADC, &tmp);
+	tmp &= ~(PCAP_ADC_ADA1_MASK | PCAP_ADC_ADA2_MASK);
+	tmp |= (ch1 << PCAP_ADC_ADA1_SHIFT) | (ch2 << PCAP_ADC_ADA2_SHIFT);
+	ezx_pcap_write(PCAP_REG_ADC, tmp);
+	ezx_pcap_read(PCAP_REG_ADR, &tmp);
+	res[0] = (tmp & PCAP_ADR_ADD1_MASK) >> PCAP_ADR_ADD1_SHIFT;
+	res[1] = (tmp & PCAP_ADR_ADD2_MASK) >> PCAP_ADR_ADD2_SHIFT;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_get_adc_channel_result);
+
+void ezx_pcap_get_adc_bank_result(u32 res[])
+{
+	int x;
+	u32 tmp[2];
+
+	for (x = 0; x < 7; x += 2) {
+		ezx_pcap_get_adc_channel_result(x, (x+1) % 6, tmp);
+		res[x] = tmp[0];
+		if ((x + 1) < 7)
+			res[x+1] = tmp[1];
+		else
+			res[x+1] = 0;
+	}
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_get_adc_bank_result);
+
+static void adc_complete(void *data)
+{
+	complete(data);
+}
+
+void ezx_pcap_do_general_adc(u8 bank, u8 ch, u32 *res)
+{
+	u32 tmp[2];
+	DECLARE_COMPLETION_ONSTACK(done);
+
+	ezx_pcap_start_adc(bank, PCAP_ADC_T_NOW, 0, adc_complete, &done);
+	wait_for_completion(&done);
+	ezx_pcap_get_adc_channel_result(ch, 0, tmp);
+	ezx_pcap_disable_adc();
+
+	*res = tmp[0];
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_do_general_adc);
+
+/* event handling */
+static irqreturn_t pcap_irq_handler(int irq, void *dev_id)
+{
+	queue_work(pcap.workqueue, &pcap.work);
+	return IRQ_HANDLED;
+}
+
+static void pcap_work(struct work_struct *_pcap)
+{
+	u32 msr;
+	u32 isr;
+	u32 service;
+	struct pcap_event *cb;
+
+	mutex_lock(&event_lock);
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	ezx_pcap_read(PCAP_REG_ISR, &isr);
+	isr &= ~msr;
+
+	list_for_each_entry(cb, &event_list, node) {
+		service = isr & cb->events;
+		if (service) {
+			ezx_pcap_write(PCAP_REG_ISR, service);
+			cb->callback(service, cb->data);
+		}
+	}
+	mutex_unlock(&event_lock);
+}
+
+void ezx_pcap_mask_event(u32 events)
+{
+	u32 msr;
+
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	msr |= events;
+	ezx_pcap_write(PCAP_REG_MSR, msr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_mask_event);
+
+void ezx_pcap_unmask_event(u32 events)
+{
+	u32 msr;
+
+	ezx_pcap_read(PCAP_REG_MSR, &msr);
+	msr &= ~events;
+	ezx_pcap_write(PCAP_REG_MSR, msr);
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_unmask_event);
+
+int ezx_pcap_register_event(u32 events, void *callback, void *data, char *label)
+{
+	struct pcap_event *cb;
+
+	cb = kzalloc(sizeof(struct pcap_event), GFP_KERNEL);
+	if (!cb)
+		return -ENOMEM;
+
+	cb->label = label;
+	cb->events = events;
+	cb->callback = callback;
+	cb->data = data;
+
+	mutex_lock(&event_lock);
+	list_add_tail(&cb->node, &event_list);
+	mutex_unlock(&event_lock);
+
+	ezx_pcap_unmask_event(events);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_register_event);
+
+int ezx_pcap_unregister_event(u32 events)
+{
+	int ret = -EINVAL;
+	struct pcap_event *cb;
+	struct pcap_event *store;
+
+	ezx_pcap_mask_event(events);
+
+	mutex_lock(&event_lock);
+	list_for_each_entry_safe(cb, store, &event_list, node) {
+		if (cb->events & events) {
+			list_del(&cb->node);
+			kfree(cb);
+			ret = 0;
+		}
+	}
+	mutex_unlock(&event_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ezx_pcap_unregister_event);
+
+/* sysfs interface */
+static ssize_t pcap_show_regs(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	unsigned int reg, val;
+	char *p = buf;
+
+	for (reg = 0; reg < 32; reg++) {
+		ezx_pcap_read(reg, &val);
+		p += sprintf(p, "%02d %08x\n", reg, val);
+	}
+	return p - buf;
+}
+
+static ssize_t pcap_store_regs(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	unsigned int reg, val;
+	char *p = (char *)buf;
+
+	while (p < (buf + size)) {
+		if ((sscanf(p, "%u %x\n", &reg, &val) != 2) ||
+			reg < 0 || reg >= 32)
+			return -EINVAL;
+		p = strchr(p, '\n') + 1;
+	}
+
+	p = (char *)buf;
+	while (p < (buf + size)) {
+		sscanf(p, "%u %x\n", &reg, &val);
+		ezx_pcap_write(reg, val);
+		p = strchr(p, '\n') + 1;
+	}
+
+	return size;
+}
+
+static ssize_t pcap_show_adc_coin(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_COIN, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_battery(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_BATT, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_bplus(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_BPLUS, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_mobportb(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_MOBPORTB, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_temperature(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_TEMPERATURE, &res);
+	return sprintf(buf, "%d\n", res);
+}
+static ssize_t pcap_show_adc_chargerid(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	u32 res;
+
+	ezx_pcap_do_general_adc(PCAP_ADC_BANK_0, PCAP_ADC_CH_CHARGER_ID, &res);
+	return sprintf(buf, "%d\n", res);
+}
+
+static DEVICE_ATTR(regs, 0600, pcap_show_regs, pcap_store_regs);
+static DEVICE_ATTR(adc_coin, 0400, pcap_show_adc_coin, NULL);
+static DEVICE_ATTR(adc_battery, 0400, pcap_show_adc_battery, NULL);
+static DEVICE_ATTR(adc_bplus, 0400, pcap_show_adc_bplus, NULL);
+static DEVICE_ATTR(adc_mobportb, 0400, pcap_show_adc_mobportb, NULL);
+static DEVICE_ATTR(adc_temperature, 0400, pcap_show_adc_temperature, NULL);
+static DEVICE_ATTR(adc_chargerid, 0400, pcap_show_adc_chargerid, NULL);
+
+static int ezx_pcap_setup_sysfs(int create)
+{
+	int ret = 0;
+
+	if (!create)
+		goto remove_all;
+
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_regs);
+	if (ret)
+		goto ret;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_coin);
+	if (ret)
+		goto fail1;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_battery);
+	if (ret)
+		goto fail2;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_bplus);
+	if (ret)
+		goto fail3;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_mobportb);
+	if (ret)
+		goto fail4;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_temperature);
+	if (ret)
+		goto fail5;
+	ret = device_create_file(&pcap.spi->dev, &dev_attr_adc_chargerid);
+	if (ret)
+		goto fail6;
+
+	goto ret;
+
+remove_all:
+fail6:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_temperature);
+fail5:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_mobportb);
+fail4:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_bplus);
+fail3:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_battery);
+fail2:	device_remove_file(&pcap.spi->dev, &dev_attr_adc_coin);
+fail1:	device_remove_file(&pcap.spi->dev, &dev_attr_regs);
+ret:	return ret;
+}
+
+static int ezx_pcap_remove(struct spi_device *spi)
+{
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+
+	ezx_pcap_setup_sysfs(0);
+	destroy_workqueue(pcap.workqueue);
+	ezx_pcap_unregister_event(PCAP_MASK_ALL_INTERRUPT);
+	free_irq(pdata->irq, NULL);
+
+	return 0;
+}
+
+static int __devinit ezx_pcap_probe(struct spi_device *spi)
+{
+	struct pcap_platform_data *pdata = spi->dev.platform_data;
+	int ret = -ENODEV;
+
+	if (!pdata)
+		goto ret;
+
+	pcap.spi = spi;
+
+	INIT_WORK(&pcap.work, pcap_work);
+	pcap.workqueue = create_singlethread_workqueue("pcapd");
+	if (!pcap.workqueue) {
+		dev_err(&spi->dev, "cant create pcap thread\n");
+		goto ret;
+	}
+
+	/* redirect interrupts to AP */
+	if (!(pdata->config & PCAP_SECOND_PORT))
+		ezx_pcap_write(PCAP_REG_INT_SEL, PCAP_IRQ_ADCDONE2);
+
+	/* set board-specific settings */
+	if (pdata->init)
+		pdata->init();
+
+	ret = ezx_pcap_setup_sysfs(1);
+	if (ret) {
+		dev_err(&spi->dev, "cant create sysfs files\n");
+		goto wq_destroy;
+	}
+
+	/* mask/ack all PCAP interrupts */
+	ezx_pcap_write(PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT);
+	ezx_pcap_write(PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
+
+	/* register irq for pcap */
+	ret = request_irq(pdata->irq, pcap_irq_handler, IRQF_DISABLED,
+		"PCAP", NULL);
+	if (ret) {
+		dev_err(&spi->dev, "cant request IRQ\n");
+		goto wq_destroy;
+	}
+	set_irq_type(pdata->irq, IRQ_TYPE_EDGE_RISING);
+	set_irq_wake(pdata->irq, 1);
+
+	ezx_pcap_register_event((pdata->config & PCAP_SECOND_PORT) ?
+			PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE,
+			ezx_pcap_adc_event, NULL, "ADC");
+	return 0;
+
+wq_destroy:
+	destroy_workqueue(pcap.workqueue);
+ret:
+	return ret;
+}
+
+static struct spi_driver ezxpcap_driver = {
+	.probe  = ezx_pcap_probe,
+	.remove = ezx_pcap_remove,
+	.driver = {
+		.name   = "ezx-pcap",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init ezx_pcap_init(void)
+{
+	return spi_register_driver(&ezxpcap_driver);
+}
+
+static void __exit ezx_pcap_exit(void)
+{
+	spi_unregister_driver(&ezxpcap_driver);
+}
+
+module_init(ezx_pcap_init);
+module_exit(ezx_pcap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
+MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver");
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h
new file mode 100644
index 0000000..352ac35
--- /dev/null
+++ b/include/linux/mfd/ezx-pcap.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2007 Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * For further information, please see http://wiki.openezx.org/PCAP2
+ */
+
+#ifndef EZX_PCAP_H
+#define EZX_PCAP_H
+
+struct pcap_platform_data {
+	unsigned int irq;
+	unsigned int config;
+	void (*init) (void);	/* board specific init */
+};
+
+#define PCAP_SECOND_PORT	1
+
+#define PCAP_REGISTER_WRITE_OP_BIT	0x80000000
+#define PCAP_REGISTER_READ_OP_BIT	0x00000000
+
+#define PCAP_REGISTER_VALUE_MASK	0x01ffffff
+#define PCAP_REGISTER_ADDRESS_MASK	0x7c000000
+#define PCAP_REGISTER_ADDRESS_SHIFT	26
+#define PCAP_REGISTER_NUMBER		32
+#define PCAP_CLEAR_INTERRUPT_REGISTER	0x01ffffff
+#define PCAP_MASK_ALL_INTERRUPT		0x01ffffff
+
+/* registers acessible by both pcap ports */
+#define PCAP_REG_ISR		0x0	/* Interrupt Status */
+#define PCAP_REG_MSR		0x1	/* Interrupt Mask */
+#define PCAP_REG_PSTAT		0x2	/* Processor Status */
+#define PCAP_REG_VREG2		0x6	/* Regulator Bank 2 Control */
+#define PCAP_REG_AUXVREG	0x7	/* Auxiliary Regulator Control */
+#define PCAP_REG_BATT		0x8	/* Battery Control */
+#define PCAP_REG_ADC		0x9	/* AD Control */
+#define PCAP_REG_ADR		0xa	/* AD Result */
+#define PCAP_REG_CODEC		0xb	/* Audio Codec Control */
+#define PCAP_REG_RX_AMPS	0xc	/* RX Audio Amplifiers Control */
+#define PCAP_REG_ST_DAC		0xd	/* Stereo DAC Control */
+#define PCAP_REG_BUSCTRL	0x14	/* Connectivity Control */
+#define PCAP_REG_PERIPH		0x15	/* Peripheral Control */
+#define PCAP_REG_LOWPWR		0x18	/* Regulator Low Power Control */
+#define PCAP_REG_TX_AMPS	0x1a	/* TX Audio Amplifiers Control */
+#define PCAP_REG_GP		0x1b	/* General Purpose */
+#define PCAP_REG_TEST1		0x1c
+#define PCAP_REG_TEST2		0x1d
+#define PCAP_REG_VENDOR_TEST1	0x1e
+#define PCAP_REG_VENDOR_TEST2	0x1f
+
+/* registers acessible by pcap port 1 only (a1200, e2 & e6) */
+#define PCAP_REG_INT_SEL	0x3	/* Interrupt Select */
+#define PCAP_REG_SWCTRL		0x4	/* Switching Regulator Control */
+#define PCAP_REG_VREG1		0x5	/* Regulator Bank 1 Control */
+#define PCAP_REG_RTC_TOD	0xe	/* RTC Time of Day */
+#define PCAP_REG_RTC_TODA	0xf	/* RTC Time of Day Alarm */
+#define PCAP_REG_RTC_DAY	0x10	/* RTC Day */
+#define PCAP_REG_RTC_DAYA	0x11	/* RTC Day Alarm */
+#define PCAP_REG_MTRTMR		0x12	/* AD Monitor Timer */
+#define PCAP_REG_PWR		0x13	/* Power Control */
+#define PCAP_REG_AUXVREG_MASK	0x16	/* Auxiliary Regulator Mask */
+#define PCAP_REG_VENDOR_REV	0x17
+#define PCAP_REG_PERIPH_MASK	0x19	/* Peripheral Mask */
+
+/* interrupts - registers 0x0, 0x1, 0x2, 0x3 */
+#define PCAP_IRQ_ADCDONE	(1 << 0)	/* AD Conversion Done Port 1 */
+#define PCAP_IRQ_TS		(1 << 1)	/* Touch Screen */
+#define PCAP_IRQ_1HZ		(1 << 2)	/* 1HZ Timer */
+#define PCAP_IRQ_WH		(1 << 3)	/* "...high"??? */
+#define PCAP_IRQ_WL		(1 << 4)	/* "...low"??? */
+#define PCAP_IRQ_TODA		(1 << 5)	/* RTC Time Of Day?
+						   (see "RTC_TODA") */
+#define PCAP_IRQ_USB4V		(1 << 6)	/* USB OTG */
+#define PCAP_IRQ_ONOFF		(1 << 7)	/* in blob: "ONOFFSNS" */
+#define PCAP_IRQ_ONOFF2		(1 << 8)	/* in blob: "ONOFFSNS2" */
+#define PCAP_IRQ_USB1V		(1 << 9)	/* USB below 1volt???
+						   in blob: "USBDET_1V" */
+#define PCAP_IRQ_MOBPORT	(1 << 10)	/* GSM-related?? ("mobport",
+						   see 958_MotDoc.pdf);
+						   in blob: "MOBSENSB" */
+#define PCAP_IRQ_MB2		(1 << 11)	/* Mic; in blob: "MB2SNS" */
+#define PCAP_IRQ_A1		(1 << 12)	/* Audio jack;
+						   in blob: "A1SNS" */
+#define PCAP_IRQ_ST		(1 << 13)	/* called "MSTB" in blob */
+#define PCAP_IRQ_PC		(1 << 14)
+#define PCAP_IRQ_WARM		(1 << 15)
+#define PCAP_IRQ_EOL		(1 << 16)	/*  battery End Of Life???
+						   (see below);
+						   in blob: "EOL_STAT" */
+#define PCAP_IRQ_CLK		(1 << 17)	/* called "CLK_STAT" in blob */
+#define PCAP_IRQ_SYSRST		(1 << 18)
+#define PCAP_IRQ_DUMMY		(1 << 19)
+#define PCAP_IRQ_ADCDONE2	(1 << 20)	/* AD Conversion Done Port 2 */
+#define PCAP_IRQ_SOFTRESET	(1 << 21)
+#define PCAP_IRQ_MNEXB		(1 << 22)
+
+/* voltage regulators */
+#define V1		0
+#define V2		1
+#define V3		2
+#define V4		3
+#define V5		4
+#define V6		5
+#define V7		6
+#define V8		7
+#define V9		8
+#define V10		9
+#define VAUX1		10
+#define VAUX2		11
+#define VAUX3		12
+#define VAUX4		13
+#define VSIM		14
+#define VSIM2		15
+#define VVIB		16
+#define VC		17
+
+#define V_EN		0
+#define V_VAL		1
+#define V_MASK		2
+#define V_STBY		3
+#define V_LOWPWR	4
+
+#define PCAP_BATT_DAC_MASK		0x000000ff
+#define PCAP_BATT_DAC_SHIFT		0
+#define PCAP_BATT_B_FDBK		(1 << 8)
+#define PCAP_BATT_EXT_ISENSE		(1 << 9)
+#define PCAP_BATT_V_COIN_MASK		0x00003c00
+#define PCAP_BATT_V_COIN_SHIFT		10
+#define PCAP_BATT_I_COIN		(1 << 14)
+#define PCAP_BATT_COIN_CH_EN		(1 << 15)
+#define PCAP_BATT_EOL_SEL_MASK		0x000e0000
+#define PCAP_BATT_EOL_SEL_SHIFT		17
+#define PCAP_BATT_EOL_CMP_EN		(1 << 20)
+#define PCAP_BATT_BATT_DET_EN		(1 << 21)
+#define PCAP_BATT_THERMBIAS_CTRL	(1 << 22)
+
+#define PCAP_ADC_ADEN			(1 << 0)
+#define PCAP_ADC_RAND			(1 << 1)
+#define PCAP_ADC_AD_SEL1		(1 << 2)
+#define PCAP_ADC_AD_SEL2		(1 << 3)
+#define PCAP_ADC_ADA1_MASK		0x00000070
+#define PCAP_ADC_ADA1_SHIFT		4
+#define PCAP_ADC_ADA2_MASK		0x00000380
+#define PCAP_ADC_ADA2_SHIFT		7
+#define PCAP_ADC_ATO_MASK		0x00003c00
+#define PCAP_ADC_ATO_SHIFT		10
+#define PCAP_ADC_ATOX			(1 << 14)
+#define PCAP_ADC_MTR1			(1 << 15)
+#define PCAP_ADC_MTR2			(1 << 16)
+#define PCAP_ADC_TS_M_MASK		0x000e0000
+#define PCAP_ADC_TS_M_SHIFT		17
+#define PCAP_ADC_TS_REF_LOWPWR		(1 << 20)
+#define PCAP_ADC_TS_REFENB		(1 << 21)
+#define PCAP_ADC_BATT_I_POLARITY	(1 << 22)
+#define PCAP_ADC_BATT_I_ADC		(1 << 23)
+
+#define PCAP_ADC_BANK_0			0
+#define PCAP_ADC_BANK_1			1
+/* ADC bank 0 */
+#define PCAP_ADC_CH_COIN		0
+#define PCAP_ADC_CH_BATT		1
+#define PCAP_ADC_CH_BPLUS		2
+#define PCAP_ADC_CH_MOBPORTB		3
+#define PCAP_ADC_CH_TEMPERATURE		4
+#define PCAP_ADC_CH_CHARGER_ID		5
+#define PCAP_ADC_CH_AD6			6
+/* ADC bank 1 */
+#define PCAP_ADC_CH_AD7			0
+#define PCAP_ADC_CH_AD8			1
+#define PCAP_ADC_CH_AD9			2
+#define PCAP_ADC_CH_TS_X1		3
+#define PCAP_ADC_CH_TS_X2		4
+#define PCAP_ADC_CH_TS_Y1		5
+#define PCAP_ADC_CH_TS_Y2		6
+
+#define PCAP_ADC_T_NOW			0
+#define PCAP_ADC_T_IN_BURST		1
+#define PCAP_ADC_T_OUT_BURST		2
+
+#define PCAP_ADC_ATO_IN_BURST		6
+#define PCAP_ADC_ATO_OUT_BURST		0
+
+#define PCAP_ADC_TS_M_XY		1
+#define PCAP_ADC_TS_M_PRESSURE		2
+#define PCAP_ADC_TS_M_PLATE_X		3
+#define PCAP_ADC_TS_M_PLATE_Y		4
+#define PCAP_ADC_TS_M_STANDBY		5
+#define PCAP_ADC_TS_M_NONTS		6
+
+#define PCAP_ADR_ADD1_MASK		0x000003ff
+#define PCAP_ADR_ADD1_SHIFT		0
+#define PCAP_ADR_ADD2_MASK		0x000ffc00
+#define PCAP_ADR_ADD2_SHIFT		10
+#define PCAP_ADR_ADINC1			(1 << 20)
+#define PCAP_ADR_ADINC2			(1 << 21)
+#define PCAP_ADR_ASC			(1 << 22)
+#define PCAP_ADR_ONESHOT		(1 << 23)
+
+#define PCAP_BUSCTRL_FSENB		(1 << 0)
+#define PCAP_BUSCTRL_USB_SUSPEND	(1 << 1)
+#define PCAP_BUSCTRL_USB_PU		(1 << 2)
+#define PCAP_BUSCTRL_USB_PD		(1 << 3)
+#define PCAP_BUSCTRL_VUSB_EN		(1 << 4)
+#define PCAP_BUSCTRL_USB_PS		(1 << 5)
+#define PCAP_BUSCTRL_VUSB_MSTR_EN	(1 << 6)
+#define PCAP_BUSCTRL_VBUS_PD_ENB	(1 << 7)
+#define PCAP_BUSCTRL_CURRLIM		(1 << 8)
+#define PCAP_BUSCTRL_RS232ENB		(1 << 9)
+#define PCAP_BUSCTRL_RS232_DIR		(1 << 10)
+#define PCAP_BUSCTRL_SE0_CONN		(1 << 11)
+#define PCAP_BUSCTRL_USB_PDM		(1 << 12)
+#define PCAP_BUSCTRL_BUS_PRI_ADJ	(1 << 24)
+
+/* leds */
+#define PCAP_LED0		0
+#define PCAP_LED1		1
+#define PCAP_BL0		2
+#define PCAP_BL1		3
+#define PCAP_LED_3MA		0
+#define PCAP_LED_4MA		1
+#define PCAP_LED_5MA		2
+#define PCAP_LED_9MA		3
+#define PCAP_LED_GPIO_VAL_MASK	0x00ffffff
+#define PCAP_LED_GPIO_EN	0x01000000
+#define PCAP_LED_GPIO_INVERT	0x02000000
+#define PCAP_LED_T_MASK		0xf
+#define PCAP_LED_C_MASK		0x3
+#define PCAP_BL_MASK		0x1f
+#define PCAP_BL0_SHIFT		0
+#define PCAP_LED0_EN		(1 << 5)
+#define PCAP_LED1_EN		(1 << 6)
+#define PCAP_LED0_T_SHIFT	7
+#define PCAP_LED1_T_SHIFT	11
+#define PCAP_LED0_C_SHIFT	15
+#define PCAP_LED1_C_SHIFT	17
+#define PCAP_BL1_SHIFT		20
+
+/* RTC */
+#define PCAP_RTC_DAY_MASK	0x3fff
+#define PCAP_RTC_TOD_MASK	0xffff
+#define PCAP_RTC_PC_MASK	0x7
+#define SEC_PER_DAY		86400
+
+/* LOWPWR */
+#define SW1		8
+#define SW2		16
+
+#define SW_MODE		0
+#define SW_VOLTAGE	4
+
+#define SW_VOLTAGE_900	0x0
+#define SW_VOLTAGE_950	0x1
+#define SW_VOLTAGE_1000	0x2
+#define SW_VOLTAGE_1050	0x3
+#define SW_VOLTAGE_1100	0x4
+#define SW_VOLTAGE_1150	0x5
+#define SW_VOLTAGE_1200	0x6
+#define SW_VOLTAGE_1250	0x7
+#define SW_VOLTAGE_1300	0x8
+#define SW_VOLTAGE_1350	0x9
+#define SW_VOLTAGE_1400	0xa
+#define SW_VOLTAGE_1500	0xb
+#define SW_VOLTAGE_1600	0xc
+#define SW_VOLTAGE_1875	0xd
+#define SW_VOLTAGE_2250	0xe
+#define SW_VOLTAGE_4400	0xf
+
+int ezx_pcap_write(u8, u32);
+int ezx_pcap_read(u8, u32 *);
+int ezx_pcap_set_sw(u8, u8, u8);
+int ezx_pcap_set_vreg(u8, u8, u8);
+void ezx_pcap_start_adc(u8, u8, u32, void *, void *);
+void ezx_pcap_get_adc_channel_result(u8, u8, u32[]);
+void ezx_pcap_get_adc_bank_result(u32[]);
+void ezx_pcap_disable_adc(void);
+void ezx_pcap_do_general_adc(u8, u8, u32 *);
+void ezx_pcap_do_batt_adc(int, u32[]);
+int ezx_pcap_register_event(u32, void *, void *, char *);
+int ezx_pcap_unregister_event(u32);
+void ezx_pcap_mask_event(u32);
+void ezx_pcap_unmask_event(u32);
+
+struct pcap_event {
+	struct list_head node;
+	char *label;
+	u32 events;
+	void (*callback) (u32, void *);
+	void *data;
+};
+
+#endif
-- 
tg: (ed31348..) ezx/pcap (depends on: master)

[-- Attachment #3: Type: text/plain, Size: 363 bytes --]

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

[-- Attachment #4: Type: text/plain, Size: 210 bytes --]

_______________________________________________
spi-devel-general mailing list
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

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

* Re: [patch 05/14] mfd: PCAP2 driver
  2008-11-22 15:54           ` Daniel Ribeiro
@ 2008-11-22 19:08             ` David Brownell
       [not found]               ` <200811221108.54331.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2008-11-22 19:08 UTC (permalink / raw)
  To: Daniel Ribeiro, Eric Miao, stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Saturday 22 November 2008, Daniel Ribeiro wrote:
> Em Sáb, 2008-11-22 às 22:01 +0800, Eric Miao escreveu:
> > On Sat, Nov 22, 2008 at 1:25 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote:
> > > On Friday 21 November 2008, stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org wrote:
> > >> Since the last submission we are also using the spi subsystem and
> > >> pxa2xx-spi instead of ssp.c directly as before.
> > >
> > > I took a quick glance at this and it seemed like it should be
> > > able to build without depending on PXA ... should certainly
> > > not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
> > > look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
> > > either.
> > >
> > > It's also worth removing the reverse dependencies ("select X")
> > > from Kconfig; they don't work very well for the things which
> > > those dependencies rely on.
> > >
> > I'm wondering if it call fall into the regulator framework, along with
> > a hwmon driver with its attributes being exported by sysfs.

Make it work like other MFD drivers, with child devices
to encapsulate such functionality ... and drivers specific
to those functionalities.

Such as a regulator framework driver, an RTC, and so on.


> The ADC is also used by the touchscreen driver, and later will be used
> for accessory detection (usb otg, charger, EMU (audio and uart on usb
> port)).

ADC integration may be an interesting little puzzle.

 
> Currently the only user for the voltage regulators is the MMC, i plan to
> use the regulator subsystem when more users arise.
> 



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
  2008-11-22 17:12         ` Daniel Ribeiro
@ 2008-11-22 19:19           ` David Brownell
       [not found]             ` <200811221119.27981.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2008-11-22 19:19 UTC (permalink / raw)
  To: Daniel Ribeiro
  Cc: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ

On Saturday 22 November 2008, Daniel Ribeiro wrote:
> Above comments are integrated on the attached patch. 

Not exactly:

> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -153,6 +153,13 @@ config MFD_WM8350_I2C
>           I2C as the control interface.  Additional options must be
>           selected to enable support for the functionality of the chip.
>  
> +config EZX_PCAP
> +       bool "PCAP Support"
> +       depends on PXA_EZX

It only builds on one platform.  Now, that may make sense if it's
an ASIC currently used only on that platform; it's a "hardware"
dependency.  But it's not a necessary "software" dependency, no
code here seems to rely on PXA hardware, or EZX hardware.

One of the goals of getting drivers into mainline is to get rid
of needless dependencies ... and thereby open the code up to
many more developers.  Some may do nothing more than cleanup;
others will be doing API overhauls, which can be a PITA if you
place needless build dependencies on your code.

Strike that dependency, and depend instead on SPI_MASTER since
that's the only dependency truly required by the build system.

Or tell me I'm wrong, and there's really a reason this code must
not even *build* on x86 systems.


> +       help
> +         This enables the PCAP ASIC present on EZX Phones. This is
> +         needed for MMC, TouchScreen, Sound, USB, etc..
> +
>  endmenu
>  



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]               ` <200811221108.54331.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-22 23:29                 ` Stefan Schmidt
  0 siblings, 0 replies; 16+ messages in thread
From: Stefan Schmidt @ 2008-11-22 23:29 UTC (permalink / raw)
  To: David Brownell
  Cc: Eric Miao, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

Hello.

On Sat, 2008-11-22 at 11:08, David Brownell wrote:
> On Saturday 22 November 2008, Daniel Ribeiro wrote:
> > Em Sáb, 2008-11-22 às 22:01 +0800, Eric Miao escreveu:
> > > On Sat, Nov 22, 2008 at 1:25 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote:
> > > > On Friday 21 November 2008, stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org wrote:
> > > >> Since the last submission we are also using the spi subsystem and
> > > >> pxa2xx-spi instead of ssp.c directly as before.
> > > >
> > > > I took a quick glance at this and it seemed like it should be
> > > > able to build without depending on PXA ... should certainly
> > > > not include <mach/ssp.h> or <mach/regs-ssp.h>, and it doesn't
> > > > look like it needs PXA-specific stuff like <mach/mfp-pxa27x.h>
> > > > either.
> > > >
> > > > It's also worth removing the reverse dependencies ("select X")
> > > > from Kconfig; they don't work very well for the things which
> > > > those dependencies rely on.
> > > >
> > > I'm wondering if it call fall into the regulator framework, along with
> > > a hwmon driver with its attributes being exported by sysfs.
> 
> Make it work like other MFD drivers, with child devices
> to encapsulate such functionality ... and drivers specific
> to those functionalities.
> 
> Such as a regulator framework driver, an RTC, and so on.

We do this already. pcap-rtc, pcap_ts and pcap_leds are later in this set.

As Daniel already pointed out. At the moment MMC is the only user of the voltage
regulator. We plan to add a regulator child device once more users come up.
(Pretty sure they will. :))

> > The ADC is also used by the touchscreen driver, and later will be used
> > for accessory detection (usb otg, charger, EMU (audio and uart on usb
> > port)).
> 
> ADC integration may be an interesting little puzzle.

It will. :/ 

At the moment we are working to have more of the basics done though.

The PXA dep is also almost gone. It's our aim to provide a generic driver here.

regards
Stefan Schmidt

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]             ` <200811221119.27981.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-22 23:33               ` Stefan Schmidt
       [not found]                 ` <20081122233356.GC24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: Stefan Schmidt @ 2008-11-22 23:33 UTC (permalink / raw)
  To: David Brownell
  Cc: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

Hello.

On Sat, 2008-11-22 at 11:19, David Brownell wrote:
> On Saturday 22 November 2008, Daniel Ribeiro wrote:
> >  
> > +config EZX_PCAP
> > +       bool "PCAP Support"
> > +       depends on PXA_EZX
> 
> It only builds on one platform.  Now, that may make sense if it's
> an ASIC currently used only on that platform; it's a "hardware"
> dependency.  But it's not a necessary "software" dependency, no
> code here seems to rely on PXA hardware, or EZX hardware.

It is software and we are on the way fixing it.

> One of the goals of getting drivers into mainline is to get rid
> of needless dependencies ... and thereby open the code up to
> many more developers.  Some may do nothing more than cleanup;
> others will be doing API overhauls, which can be a PITA if you
> place needless build dependencies on your code.

Understand. We have been a bit lazy here, sorry. That is mostly based on the
fact that we have never seen any other linux devices having this chip. Only some
low power feature phones with the P2K OS from Motorola. Anyway, we work on it to
get it more generic now.

> Strike that dependency, and depend instead on SPI_MASTER since
> that's the only dependency truly required by the build system.

Will do.

regards
Stefan Schmidt

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]                 ` <20081122233356.GC24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
@ 2008-11-22 23:58                   ` David Brownell
       [not found]                     ` <200811221558.03915.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2008-11-22 23:58 UTC (permalink / raw)
  To: Stefan Schmidt
  Cc: eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

On Saturday 22 November 2008, Stefan Schmidt wrote:
> > > +config EZX_PCAP
> > > +       bool "PCAP Support"
> > > +       depends on PXA_EZX
> > 
> > It only builds on one platform.  Now, that may make sense if it's
> > an ASIC currently used only on that platform; it's a "hardware"
> > dependency.  But it's not a necessary "software" dependency, no
> > code here seems to rely on PXA hardware, or EZX hardware.
> 
> It is software and we are on the way fixing it.

Good.  I've only seen patch #5 of this series, so I couldn't
tell what else was up.


> > One of the goals of getting drivers into mainline is to get rid
> > of needless dependencies ... and thereby open the code up to
> > many more developers.  Some may do nothing more than cleanup;
> > others will be doing API overhauls, which can be a PITA if you
> > place needless build dependencies on your code.
> 
> Understand. We have been a bit lazy here, sorry. That is mostly based on the
> fact that we have never seen any other linux devices having this chip. Only some
> low power feature phones with the P2K OS from Motorola. Anyway, we work on it to
> get it more generic now.

Looks to me like you're almost all the way there already!  :)

Much like we're doing with the twl4030 family chips ... they're
used on a lot of OMAP3 (and some OMAP2430) boards, and some
build dependencies evolved over the past year or so while
the driver support was maturing out of mainline.  Patches to
remove them are ready now, and should be "cooked" enough to
make the 2.6.29 merge window.

- Dave

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]                     ` <200811221558.03915.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-23  0:33                       ` Stefan Schmidt
       [not found]                         ` <20081123003306.GE24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: Stefan Schmidt @ 2008-11-23  0:33 UTC (permalink / raw)
  To: David Brownell
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

On Sat, 2008-11-22 at 15:58, David Brownell wrote:
> On Saturday 22 November 2008, Stefan Schmidt wrote:
> > > > +config EZX_PCAP
> > > > +       bool "PCAP Support"
> > > > +       depends on PXA_EZX
> > > 
> > > It only builds on one platform.  Now, that may make sense if it's
> > > an ASIC currently used only on that platform; it's a "hardware"
> > > dependency.  But it's not a necessary "software" dependency, no
> > > code here seems to rely on PXA hardware, or EZX hardware.
> > 
> > It is software and we are on the way fixing it.
> 
> Good.  I've only seen patch #5 of this series, so I couldn't
> tell what else was up.

Sorry. This set touched a lot of different subsystems. (ARM, spi, rtc, input,
mfd, ..) The To: and Cc: list gave me quite some headache. :) Next time I make
sure that at least LKML is cc'ed on the whle series so people have a lace to
look at it in one thread.

> > Understand. We have been a bit lazy here, sorry. That is mostly based on the
> > fact that we have never seen any other linux devices having this chip. Only some
> > low power feature phones with the P2K OS from Motorola. Anyway, we work on it to
> > get it more generic now.
> 
> Looks to me like you're almost all the way there already!  :)

We hope so, yes. :) Once we have the EZX/PXA dep gone you are fine with this
patch? All SPI related stuff is ok from you?

> Much like we're doing with the twl4030 family chips ... they're
> used on a lot of OMAP3 (and some OMAP2430) boards, and some
> build dependencies evolved over the past year or so while
> the driver support was maturing out of mainline.

Yeah, pretty similar. We had to start from 2.4 driver code to get in touch with
this chip. Motorola did not offer any docs. Also the usual embedded board
out-of-tree problem. We are doing a lot better now since the last two kernels
though. Better workflow, tools, faster reaction on review and more energy
towards upstream submissions.

regards
Stefan Schmidt

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]                         ` <20081123003306.GE24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
@ 2008-11-23  2:19                           ` David Brownell
       [not found]                             ` <200811221819.53186.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2008-11-23  2:19 UTC (permalink / raw)
  To: Stefan Schmidt
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Daniel Ribeiro

On Saturday 22 November 2008, Stefan Schmidt wrote:
> > 
> > Looks to me like you're almost all the way there already!  :)
> 
> We hope so, yes. :) Once we have the EZX/PXA dep gone you are fine with this
> patch? All SPI related stuff is ok from you?

SPI-specific bits:

 - I'd have to see the patch.  The last one I saw still didn't
   list a SPI_MASTER dependency for the core MFD module.

 - You should make ezx_pcap_write() and ezx_pcap_read() switch
   over to spi_write_then_read(), to ensure it's never doing
   DMA to/from the stack.  I see a byte-order dependency too...

 - For general paranoia, the probe() should abort if pcap.spi is
   already set ... and its cleanup path, plus remove(), should
   null that pointer.

 - If you're going to mark the probe() as __devinit, then mark
   the remove() as __devexit and use __devexit_p() in the driver
   struct.

Other comments about the pcap2 core:

 - The set_vreg() stuff would seem to make more sense in a
   regulator subdevice and driver ... but that's more of a
   general driver structure thing, and might be fixed later.

 - Andrew seems to always want a comment explaining why the
   IRQ handler for I2C and SPI devices needs to queue_work().
   Maybe the threaded IRQ stuff will help there...

 - The mask_event()/unmask_event() stuff looks like you're
   more or less reinventing a baby "struct irq_chip", with
   register_event() instead of request_irq().

 - Those show_regs/store_regs calls would IMO make more sense
   in debugfs than in sysfs.

 - And the ADC sysfs support isn't supporting hwmon models.
   (Neither does the twl4030 ADC support, but that's not been
   submitted for mainline yet either...)

Re the IRQ stuff, this looks more like what i2c/chips/menelaus.c
did than mfd/twl4030-irq.c ... in general I think it's better to
pursue the latter approach, making genirq handle such stuff.
(Even though it's kind of awkward to use it for I2C or SPI based
interrupt controllers just now.)

- Dave

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]                             ` <200811221819.53186.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-23  3:38                               ` Daniel Ribeiro
  2008-11-23  4:59                                 ` David Brownell
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Ribeiro @ 2008-11-23  3:38 UTC (permalink / raw)
  To: David Brownell
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Stefan Schmidt

Em Sáb, 2008-11-22 às 18:19 -0800, David Brownell escreveu:
> SPI-specific bits:
> 
>  - I'd have to see the patch.  The last one I saw still didn't
>    list a SPI_MASTER dependency for the core MFD module.

The next one will.

>  - You should make ezx_pcap_write() and ezx_pcap_read() switch
>    over to spi_write_then_read(), to ensure it's never doing
>    DMA to/from the stack.  I see a byte-order dependency too...

I tried spi_write_then_read before, but it didn't work. I supposed it
was because it was doing 2 transfers as the second transfer rx_buf
always came zeroed. I see that commit
f9b90e39cbc5c4d6ef60022fd1f25d541df0aad1 changed it to do a single
transfer, so i will try it again.

>  - For general paranoia, the probe() should abort if pcap.spi is
>    already set ... and its cleanup path, plus remove(), should
>    null that pointer.

Ok.

>  - If you're going to mark the probe() as __devinit, then mark
>    the remove() as __devexit and use __devexit_p() in the driver
>    struct.

Ok. Shouldn't i use __init instead?

> Other comments about the pcap2 core:

> - Those show_regs/store_regs calls would IMO make more sense
>    in debugfs than in sysfs.

I will just remove those for now.

>  - The set_vreg() stuff would seem to make more sense in a
>    regulator subdevice and driver ... but that's more of a
>    general driver structure thing, and might be fixed later.
> 
>  - Andrew seems to always want a comment explaining why the
>    IRQ handler for I2C and SPI devices needs to queue_work().
>    Maybe the threaded IRQ stuff will help there...
> 
>  - The mask_event()/unmask_event() stuff looks like you're
>    more or less reinventing a baby "struct irq_chip", with
>    register_event() instead of request_irq().

> Re the IRQ stuff, this looks more like what i2c/chips/menelaus.c
> did than mfd/twl4030-irq.c ... in general I think it's better to
> pursue the latter approach, making genirq handle such stuff.
> (Even though it's kind of awkward to use it for I2C or SPI based
> interrupt controllers just now.)

I didn't know i could use genirq with spi. In fact i was using genirq
before, when the driver was using ssp.c. Now, looking at twl4030-irq.c
its clear how i should have done this. Thanks!!

>  - And the ADC sysfs support isn't supporting hwmon models.
>    (Neither does the twl4030 ADC support, but that's not been
>    submitted for mainline yet either...)

I will look into this after i finish the irq stuff.


This is a lot of stuff, thanks for the review. :)

-- 
Daniel Ribeiro


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

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

* Re: [patch 05/14] mfd: PCAP2 driver
  2008-11-23  3:38                               ` Daniel Ribeiro
@ 2008-11-23  4:59                                 ` David Brownell
       [not found]                                   ` <200811222059.59806.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Brownell @ 2008-11-23  4:59 UTC (permalink / raw)
  To: Daniel Ribeiro
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Stefan Schmidt

On Saturday 22 November 2008, Daniel Ribeiro wrote:
> >  - You should make ezx_pcap_write() and ezx_pcap_read() switch
> >    over to spi_write_then_read(), to ensure it's never doing
> >    DMA to/from the stack.  I see a byte-order dependency too...
> 
> I tried spi_write_then_read before, but it didn't work. I supposed it
> was because it was doing 2 transfers as the second transfer rx_buf
> always came zeroed.

You may have been using it wrong.  Also, verify against
current kernels ... there have been bugfixes to pxa2xx_spi.


> I see that commit 
> f9b90e39cbc5c4d6ef60022fd1f25d541df0aad1 changed it to do a single
> transfer, so i will try it again.

Unless it needs the full duplex capability of SPI, then
you should be able to make write_then_read work ... on
the other hand, if you do need full duplex, then you
should address the DMA.  (And byteswapping, either way.)


> >  - If you're going to mark the probe() as __devinit, then mark
> >    the remove() as __devexit and use __devexit_p() in the driver
> >    struct.
> 
> Ok. Shouldn't i use __init instead?

I wouldn't.  There are ways that the probe() could be called
more than once -- e.g. after rebinding either of the relevant
SPI drivers through sysfs, or after rmmod/modprobe of the SPI
master controller driver -- and using an __init annotation
would make that point to memory that's unlikely to still hold
that code.

- Dave

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

* Re: [patch 05/14] mfd: PCAP2 driver
       [not found]                                   ` <200811222059.59806.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
@ 2008-11-23  7:06                                     ` Daniel Ribeiro
  2008-11-23  8:26                                       ` David Brownell
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Ribeiro @ 2008-11-23  7:06 UTC (permalink / raw)
  To: David Brownell
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Stefan Schmidt

Em Sáb, 2008-11-22 às 20:59 -0800, David Brownell escreveu:
> > I tried spi_write_then_read before, but it didn't work. I supposed it
> > was because it was doing 2 transfers as the second transfer rx_buf
> > always came zeroed.
> 
> You may have been using it wrong.  Also, verify against
> current kernels ... there have been bugfixes to pxa2xx_spi.
> 
> > I see that commit 
> > f9b90e39cbc5c4d6ef60022fd1f25d541df0aad1 changed it to do a single
> > transfer, so i will try it again.
> 
> Unless it needs the full duplex capability of SPI, then
> you should be able to make write_then_read work ... on
> the other hand, if you do need full duplex, then you
> should address the DMA.  (And byteswapping, either way.)

Well, i guess it is full duplex, as i set spi_transfer.len to 4 bytes,
write 4 bytes _and_ read 4 bytes to/from the chip.

I'm looking at write_then_read and if I read it correctly, it sends n_tx
bytes of data plus n_rx bytes of nothing, and discards n_tx bytes from
the start of the receive buffer considering only n_rx bytes from the end
of the receive buffer. This is not what i want.

Can you be more descriptive on "address the DMA"? Im not familiar on
what is the issue here.

I will take care of byte swapping for the next patch.

-- 
Daniel Ribeiro


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

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

* Re: [patch 05/14] mfd: PCAP2 driver
  2008-11-23  7:06                                     ` Daniel Ribeiro
@ 2008-11-23  8:26                                       ` David Brownell
  0 siblings, 0 replies; 16+ messages in thread
From: David Brownell @ 2008-11-23  8:26 UTC (permalink / raw)
  To: Daniel Ribeiro
  Cc: Stefan Schmidt, eric.y.miao-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	sameo-RWuK6r/cQWRpLGFMi4vTTA,
	linux-arm-kernel-xIg/pKzrS19vn6HldHNs0ANdhmdF6hFW,
	Stefan Schmidt

On Saturday 22 November 2008, Daniel Ribeiro wrote:
> Can you be more descriptive on "address the DMA"? Im not familiar on
> what is the issue here.

You may not pass stack based buffers -- as you're now doing -- for
the spi_transfer buffers.  Documentation/DMA-mapping.txt is very
clear that such buffers are not DMA-safe, and the SPI kerneldoc is
just as clear that spi_transfer.{tx,rx}_buf memory must be DMA-safe.

- Dave


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

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

end of thread, other threads:[~2008-11-23  8:26 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20081121160403.073751031@dodger.lab.datenfreihafen.org>
2008-11-21 16:04 ` [patch 05/14] mfd: PCAP2 driver stefan-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ
     [not found]   ` <20081121160521.016544616-cQQG9CVUopzFITZdfPi31ZcF1vblOVnWhIvA6WVW+J8@public.gmane.org>
2008-11-22  5:25     ` David Brownell
2008-11-22 14:01       ` [spi-devel-general] " Eric Miao
     [not found]         ` <f17812d70811220601p1d7af668mf3265224179753ab-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-11-22 15:54           ` Daniel Ribeiro
2008-11-22 19:08             ` David Brownell
     [not found]               ` <200811221108.54331.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-22 23:29                 ` Stefan Schmidt
     [not found]       ` <200811212125.49068.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-22 17:12         ` Daniel Ribeiro
2008-11-22 19:19           ` David Brownell
     [not found]             ` <200811221119.27981.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-22 23:33               ` Stefan Schmidt
     [not found]                 ` <20081122233356.GC24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
2008-11-22 23:58                   ` David Brownell
     [not found]                     ` <200811221558.03915.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-23  0:33                       ` Stefan Schmidt
     [not found]                         ` <20081123003306.GE24437-OrPQZGeq07wqhVmZOOOmNx2eb7JE58TQ@public.gmane.org>
2008-11-23  2:19                           ` David Brownell
     [not found]                             ` <200811221819.53186.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-23  3:38                               ` Daniel Ribeiro
2008-11-23  4:59                                 ` David Brownell
     [not found]                                   ` <200811222059.59806.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-11-23  7:06                                     ` Daniel Ribeiro
2008-11-23  8:26                                       ` David Brownell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).