2012-11-05 15:10:51

by Lee Jones

[permalink] [raw]
Subject: [PATCH 0/8] mfd: Batch together MFD related patches

Hi Sam,

I know you've been busy giving NFC presentations at ELC, but ... :)

All these patches have been on the list in various other patch-sets
for some time and have been reviewed by some key people already. All
other patches from the patch-sets have been taken, so I thought I'd
batch these up for easy review/acceptance.

Documentation/devicetree/bindings/mfd/stmpe.txt | 25 ++++
drivers/mfd/ab8500-core.c | 98 ++++-----------
drivers/mfd/db8500-prcmu.c | 8 +-
drivers/mfd/stmpe.c | 151 ++++++++++++++++-------
include/linux/mfd/stmpe.h | 2 +
5 files changed, 160 insertions(+), 124 deletions(-)


2012-11-05 15:10:55

by Lee Jones

[permalink] [raw]
Subject: [PATCH 1/8] mfd: ab8500-core: Remove unused ab8500-gpio IRQ ranges

The IRQ ranges provided in ab8500-core to be passed on to the
ab8500-gpio driver are not only redundant, but they are also
causing a warning in the boot log. These IRQ ranges, like any
other MFD related IRQ resource are passed though MFD core for
automatic conversion to virtual IRQs; however, MFD core does
not support IRQ mapping of IRQ ranges. Let's just remove them.

Cc: Samuel Ortiz <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/ab8500-core.c | 36 ------------------------------------
1 file changed, 36 deletions(-)

diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77..e7197fe 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -591,38 +591,6 @@ int ab8500_suspend(struct ab8500 *ab8500)
return 0;
}

-/* AB8500 GPIO Resources */
-static struct resource __devinitdata ab8500_gpio_resources[] = {
- {
- .name = "GPIO_INT6",
- .start = AB8500_INT_GPIO6R,
- .end = AB8500_INT_GPIO41F,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-/* AB9540 GPIO Resources */
-static struct resource __devinitdata ab9540_gpio_resources[] = {
- {
- .name = "GPIO_INT6",
- .start = AB8500_INT_GPIO6R,
- .end = AB8500_INT_GPIO41F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "GPIO_INT14",
- .start = AB9540_INT_GPIO50R,
- .end = AB9540_INT_GPIO54R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "GPIO_INT15",
- .start = AB9540_INT_GPIO50F,
- .end = AB9540_INT_GPIO54F,
- .flags = IORESOURCE_IRQ,
- }
-};
-
static struct resource __devinitdata ab8500_gpadc_resources[] = {
{
.name = "HW_CONV_END",
@@ -1065,8 +1033,6 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
{
.name = "ab8500-gpio",
.of_compatible = "stericsson,ab8500-gpio",
- .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
- .resources = ab8500_gpio_resources,
},
{
.name = "ab8500-usb",
@@ -1083,8 +1049,6 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
static struct mfd_cell __devinitdata ab9540_devs[] = {
{
.name = "ab8500-gpio",
- .num_resources = ARRAY_SIZE(ab9540_gpio_resources),
- .resources = ab9540_gpio_resources,
},
{
.name = "ab9540-usb",
--
1.7.9.5

2012-11-05 15:10:59

by Lee Jones

[permalink] [raw]
Subject: [PATCH 3/8] mfd: Provide the STMPE driver with its own IRQ domain

The STMPE driver is yet another IRQ controller which requires its
own IRQ domain. So, we provide it with one.

Cc: Samuel Ortiz <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/stmpe.c | 82 +++++++++++++++++++++++++++------------------
include/linux/mfd/stmpe.h | 2 ++
2 files changed, 52 insertions(+), 32 deletions(-)

diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index ad13cb0..5c8d8f2 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
@@ -757,7 +758,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
int i;

if (variant->id_val == STMPE801_ID) {
- handle_nested_irq(stmpe->irq_base);
+ int base = irq_create_mapping(stmpe->domain, 0);
+
+ handle_nested_irq(base);
return IRQ_HANDLED;
}

@@ -778,8 +781,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
while (status) {
int bit = __ffs(status);
int line = bank * 8 + bit;
+ int nestedirq = irq_create_mapping(stmpe->domain, line);

- handle_nested_irq(stmpe->irq_base + line);
+ handle_nested_irq(nestedirq);
status &= ~(1 << bit);
}

@@ -820,7 +824,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data)
static void stmpe_irq_mask(struct irq_data *data)
{
struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
- int offset = data->irq - stmpe->irq_base;
+ int offset = data->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);

@@ -830,7 +834,7 @@ static void stmpe_irq_mask(struct irq_data *data)
static void stmpe_irq_unmask(struct irq_data *data)
{
struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
- int offset = data->irq - stmpe->irq_base;
+ int offset = data->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);

@@ -845,43 +849,62 @@ static struct irq_chip stmpe_irq_chip = {
.irq_unmask = stmpe_irq_unmask,
};

-static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hwirq)
{
+ struct stmpe *stmpe = d->host_data;
struct irq_chip *chip = NULL;
- int num_irqs = stmpe->variant->num_irqs;
- int base = stmpe->irq_base;
- int irq;

if (stmpe->variant->id_val != STMPE801_ID)
chip = &stmpe_irq_chip;

- for (irq = base; irq < base + num_irqs; irq++) {
- irq_set_chip_data(irq, stmpe);
- irq_set_chip_and_handler(irq, chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
+ irq_set_chip_data(virq, stmpe);
+ irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+ irq_set_nested_thread(virq, 1);
#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
+ set_irq_flags(virq, IRQF_VALID);
#else
- irq_set_noprobe(irq);
+ irq_set_noprobe(virq);
#endif
- }

return 0;
}

-static void stmpe_irq_remove(struct stmpe *stmpe)
+static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
{
- int num_irqs = stmpe->variant->num_irqs;
- int base = stmpe->irq_base;
- int irq;
-
- for (irq = base; irq < base + num_irqs; irq++) {
#ifdef CONFIG_ARM
- set_irq_flags(irq, 0);
+ set_irq_flags(virq, 0);
#endif
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
+ irq_set_chip_and_handler(virq, NULL, NULL);
+ irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops stmpe_irq_ops = {
+ .map = stmpe_irq_map,
+ .unmap = stmpe_irq_unmap,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+{
+ int base = stmpe->irq_base;
+ int num_irqs = stmpe->variant->num_irqs;
+
+ if (base) {
+ stmpe->domain = irq_domain_add_legacy(
+ NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
+ }
+ else {
+ stmpe->domain = irq_domain_add_linear(
+ NULL, num_irqs, &stmpe_irq_ops, stmpe);
+ }
+
+ if (!stmpe->domain) {
+ dev_err(stmpe->dev, "Failed to create irqdomain\n");
+ return -ENOSYS;
}
+
+ return 0;
}

static int __devinit stmpe_chip_init(struct stmpe *stmpe)
@@ -954,7 +977,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base, NULL);
+ NULL, stmpe->irq_base, stmpe->domain);
}

static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -1067,7 +1090,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n",
ret);
- goto out_removeirq;
+ goto free_gpio;
}
}

@@ -1083,9 +1106,6 @@ out_removedevs:
mfd_remove_devices(stmpe->dev);
if (stmpe->irq >= 0)
free_irq(stmpe->irq, stmpe);
-out_removeirq:
- if (stmpe->irq >= 0)
- stmpe_irq_remove(stmpe);
free_gpio:
if (pdata->irq_over_gpio)
gpio_free(pdata->irq_gpio);
@@ -1098,10 +1118,8 @@ int stmpe_remove(struct stmpe *stmpe)
{
mfd_remove_devices(stmpe->dev);

- if (stmpe->irq >= 0) {
+ if (stmpe->irq >= 0)
free_irq(stmpe->irq, stmpe);
- stmpe_irq_remove(stmpe);
- }

if (stmpe->pdata->irq_over_gpio)
gpio_free(stmpe->pdata->irq_gpio);
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index f8d5b4d..15dac79 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -62,6 +62,7 @@ struct stmpe_client_info;
* @lock: lock protecting I/O operations
* @irq_lock: IRQ bus lock
* @dev: device, mostly for dev_dbg()
+ * @irq_domain: IRQ domain
* @client: client - i2c or spi
* @ci: client specific information
* @partnum: part number
@@ -79,6 +80,7 @@ struct stmpe {
struct mutex lock;
struct mutex irq_lock;
struct device *dev;
+ struct irq_domain *domain;
void *client;
struct stmpe_client_info *ci;
enum stmpe_partnum partnum;
--
1.7.9.5

2012-11-05 15:11:05

by Lee Jones

[permalink] [raw]
Subject: [PATCH 5/8] mfd: Enable the STMPE MFD for Device Tree

This patch allows the STMPE Multi-Functional Device to be correctly
initialised when booting with Device Tree support enabled. Its
children are specified by the addition of subordinate devices to the
STMPE node in the Device Tree file.

Cc: Samuel Ortiz <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/stmpe.c | 48 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index e50ebdf..ba157d4 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -885,18 +885,19 @@ static struct irq_domain_ops stmpe_irq_ops = {
.xlate = irq_domain_xlate_twocell,
};

-static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+static int __devinit stmpe_irq_init(struct stmpe *stmpe,
+ struct device_node *np)
{
int base = stmpe->irq_base;
int num_irqs = stmpe->variant->num_irqs;

if (base) {
stmpe->domain = irq_domain_add_legacy(
- NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
+ np, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
}
else {
stmpe->domain = irq_domain_add_linear(
- NULL, num_irqs, &stmpe_irq_ops, stmpe);
+ np, num_irqs, &stmpe_irq_ops, stmpe);
}

if (!stmpe->domain) {
@@ -1016,15 +1017,50 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
return ret;
}

+void __devinit stmpe_of_probe(struct stmpe_platform_data *pdata,
+ struct device_node *np)
+{
+ struct device_node *child;
+
+ of_property_read_u32(np, "st,autosleep-timeout",
+ &pdata->autosleep_timeout);
+
+ pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
+
+ for_each_child_of_node(np, child) {
+ if (!strcmp(child->name, "stmpe_gpio")) {
+ pdata->blocks |= STMPE_BLOCK_GPIO;
+ }
+ if (!strcmp(child->name, "stmpe_keypad")) {
+ pdata->blocks |= STMPE_BLOCK_KEYPAD;
+ }
+ if (!strcmp(child->name, "stmpe_touchscreen")) {
+ pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
+ }
+ if (!strcmp(child->name, "stmpe_adc")) {
+ pdata->blocks |= STMPE_BLOCK_ADC;
+ }
+ }
+}
+
/* Called from client specific probe routines */
int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
{
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
+ struct device_node *np = ci->dev->of_node;
struct stmpe *stmpe;
int ret;

- if (!pdata)
- return -EINVAL;
+ if (!pdata) {
+ if (np) {
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ stmpe_of_probe(pdata, np);
+ } else
+ return -EINVAL;
+ }

stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL);
if (!stmpe)
@@ -1080,7 +1116,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
goto free_gpio;

if (stmpe->irq >= 0) {
- ret = stmpe_irq_init(stmpe);
+ ret = stmpe_irq_init(stmpe, np);
if (ret)
goto free_gpio;

--
1.7.9.5

2012-11-05 15:11:10

by Lee Jones

[permalink] [raw]
Subject: [PATCH 8/8] mfd: Differentiate between u8500 and u9540 TCDM address mapping

The TCDM mappings are quite different from u8500 to u9540. If these
aren't correctly specified for a given board, it will fail to boot.
Here we add the correct TCDM base for the u9540.

Please note that although this patch allows us to boot the u9540,
it doesn't provide us with full enablement. For that, another
patch-set will follow which completely re-vamps the way the PRCMU
is passed TCDM mappings.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/db8500-prcmu.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index e91a6e6..70898c9 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2757,7 +2757,7 @@ static int db8500_irq_init(struct device_node *np)

void __init db8500_prcmu_early_init(void)
{
- if (cpu_is_u8500v2()) {
+ if (cpu_is_u8500v2() || cpu_is_u9540()) {
void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);

if (tcpm_base != NULL) {
@@ -2775,7 +2775,11 @@ void __init db8500_prcmu_early_init(void)
iounmap(tcpm_base);
}

- tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
+ if (cpu_is_u9540())
+ tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
+ SZ_4K + SZ_8K) + SZ_8K;
+ else
+ tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
} else {
pr_err("prcmu: Unsupported chip version\n");
BUG();
--
1.7.9.5

2012-11-05 15:12:07

by Lee Jones

[permalink] [raw]
Subject: [PATCH 7/8] mfd: ab8500-core: Use devm_* memory/IRQ and allocation/free routines

It is better to use devm_* calls, as they allow for easier
and more automatic clean-up. Resources are device allocated,
so when a device is freed, so are all associated resources.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/ab8500-core.c | 62 ++++++++++++++++++---------------------------
1 file changed, 24 insertions(+), 38 deletions(-)

diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index e7197fe..2a69dc2 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1233,7 +1233,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
int i;
u8 value;

- ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
+ ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
if (!ab8500)
return -ENOMEM;

@@ -1243,10 +1243,8 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ab8500->dev = &pdev->dev;

resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!resource) {
- ret = -ENODEV;
- goto out_free_ab8500;
- }
+ if (!resource)
+ return -ENODEV;

ab8500->irq = resource->start;

@@ -1269,7 +1267,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ret = get_register_interruptible(ab8500, AB8500_MISC,
AB8500_IC_NAME_REG, &value);
if (ret < 0)
- goto out_free_ab8500;
+ return ret;

ab8500->version = value;
}
@@ -1277,7 +1275,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ret = get_register_interruptible(ab8500, AB8500_MISC,
AB8500_REV_REG, &value);
if (ret < 0)
- goto out_free_ab8500;
+ return ret;

ab8500->chip_id = value;

@@ -1294,14 +1292,13 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ab8500->mask_size = AB8500_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab8500_irq_regoffset;
}
- ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+ ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
if (!ab8500->mask)
return -ENOMEM;
- ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
- if (!ab8500->oldmask) {
- ret = -ENOMEM;
- goto out_freemask;
- }
+ ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+ if (!ab8500->oldmask)
+ return -ENOMEM;
+
/*
* ab8500 has switched off due to (SWITCH_OFF_STATUS):
* 0x01 Swoff bit programming
@@ -1355,37 +1352,37 @@ static int __devinit ab8500_probe(struct platform_device *pdev)

ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
if (ret)
- goto out_freeoldmask;
+ return ret;

for (i = 0; i < ab8500->mask_size; i++)
ab8500->mask[i] = ab8500->oldmask[i] = 0xff;

ret = ab8500_irq_init(ab8500, np);
if (ret)
- goto out_freeoldmask;
+ return ret;

/* Activate this feature only in ab9540 */
/* till tests are done on ab8500 1p2 or later*/
if (is_ab9540(ab8500)) {
- ret = request_threaded_irq(ab8500->irq, NULL,
- ab8500_hierarchical_irq,
- IRQF_ONESHOT | IRQF_NO_SUSPEND,
- "ab8500", ab8500);
+ ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
+ ab8500_hierarchical_irq,
+ IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ "ab8500", ab8500);
}
else {
- ret = request_threaded_irq(ab8500->irq, NULL,
- ab8500_irq,
- IRQF_ONESHOT | IRQF_NO_SUSPEND,
- "ab8500", ab8500);
+ ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
+ ab8500_irq,
+ IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ "ab8500", ab8500);
if (ret)
- goto out_freeoldmask;
+ return ret;
}

ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
ARRAY_SIZE(abx500_common_devs), NULL,
ab8500->irq_base, ab8500->domain);
if (ret)
- goto out_freeirq;
+ return ret;

if (is_ab9540(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
@@ -1396,14 +1393,14 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
ARRAY_SIZE(ab8500_devs), NULL,
ab8500->irq_base, ab8500->domain);
if (ret)
- goto out_freeirq;
+ return ret;

if (is_ab9540(ab8500) || is_ab8505(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
ARRAY_SIZE(ab9540_ab8505_devs), NULL,
ab8500->irq_base, ab8500->domain);
if (ret)
- goto out_freeirq;
+ return ret;

if (!no_bm) {
/* Add battery management devices */
@@ -1424,17 +1421,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
dev_err(ab8500->dev, "error creating sysfs entries\n");

return ret;
-
-out_freeirq:
- free_irq(ab8500->irq, ab8500);
-out_freeoldmask:
- kfree(ab8500->oldmask);
-out_freemask:
- kfree(ab8500->mask);
-out_free_ab8500:
- kfree(ab8500);
-
- return ret;
}

static int __devexit ab8500_remove(struct platform_device *pdev)
--
1.7.9.5

2012-11-05 15:12:09

by Lee Jones

[permalink] [raw]
Subject: [PATCH 6/8] Documentation: Describe bindings for STMPE Multi-Functional Device driver

Here we add the required documentation for the STMPE Multi-Functional
Device (MFD) Device Tree bindings. It describes all of the bindings
currently supported by the driver.

Cc: Samuel Ortiz <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
Documentation/devicetree/bindings/mfd/stmpe.txt | 25 +++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/stmpe.txt

diff --git a/Documentation/devicetree/bindings/mfd/stmpe.txt b/Documentation/devicetree/bindings/mfd/stmpe.txt
new file mode 100644
index 0000000..8f0aeda
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stmpe.txt
@@ -0,0 +1,25 @@
+* STMPE Multi-Functional Device
+
+Required properties:
+ - compatible : "st,stmpe[811|1601|2401|2403]"
+ - reg : I2C address of the device
+
+Optional properties:
+ - interrupts : The interrupt outputs from the controller
+ - interrupt-controller : Marks the device node as an interrupt controller
+ - interrupt-parent : Specifies which IRQ controller we're connected to
+ - i2c-client-wake : Marks the input device as wakable
+ - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
+
+Example:
+
+ stmpe1601: stmpe1601@40 {
+ compatible = "st,stmpe1601";
+ reg = <0x40>;
+ interrupts = <26 0x4>;
+ interrupt-parent = <&gpio6>;
+ interrupt-controller;
+
+ i2c-client-wake;
+ st,autosleep-timeout = <1024>;
+ };
--
1.7.9.5

2012-11-05 15:12:43

by Lee Jones

[permalink] [raw]
Subject: [PATCH 4/8] mfd: Correct copy and paste mistake in stmpe

When specifying IRQ numbers for the stmpe1601, IRQ defines for the
stmpe24xx were used instead. Fortunately, the defined numbers are
the same, hence why it survived testing. This fix is merely an
aesthetic one.

Cc: Samuel Ortiz <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/stmpe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 5c8d8f2..e50ebdf 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -519,12 +519,12 @@ static const u8 stmpe1601_regs[] = {
static struct stmpe_variant_block stmpe1601_blocks[] = {
{
.cell = &stmpe_gpio_cell,
- .irq = STMPE24XX_IRQ_GPIOC,
+ .irq = STMPE1601_IRQ_GPIOC,
.block = STMPE_BLOCK_GPIO,
},
{
.cell = &stmpe_keypad_cell,
- .irq = STMPE24XX_IRQ_KEYPAD,
+ .irq = STMPE1601_IRQ_KEYPAD,
.block = STMPE_BLOCK_KEYPAD,
},
};
--
1.7.9.5

2012-11-05 15:13:00

by Lee Jones

[permalink] [raw]
Subject: [PATCH 2/8] mfd: Prevent STMPE from abusing mfd_add_devices' irq_base parameter

Originally IRQ incrementers were provided in some template resource
structures for keypad and touchscreen devices. These were passed as
IORESOURCE_IRQs to MFD core in the usual way. The true device IRQs
were instead added to the irq_base when mfd_add_devices was invoked.
This is clearly an abuse of the call, and does not scale when IRQ
Domains are brought into play. Before we can provide the STMPE with
its own IRQ Domain we must first fix this. This patche keeps most
of the driver's structure, keeping the template strategy. However,
instead of providing the IRQ as an increment to irq_base, we
dynamically populate the IORESOURCE_IRQ with the correct device IRQ.

Cc: Samuel Ortiz <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Lee Jones <[email protected]>
---
drivers/mfd/stmpe.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index c94f521..ad13cb0 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -310,14 +310,10 @@ static struct mfd_cell stmpe_gpio_cell_noirq = {
static struct resource stmpe_keypad_resources[] = {
{
.name = "KEYPAD",
- .start = 0,
- .end = 0,
.flags = IORESOURCE_IRQ,
},
{
.name = "KEYPAD_OVER",
- .start = 1,
- .end = 1,
.flags = IORESOURCE_IRQ,
},
};
@@ -397,14 +393,10 @@ static struct stmpe_variant_info stmpe801_noirq = {
static struct resource stmpe_ts_resources[] = {
{
.name = "TOUCH_DET",
- .start = 0,
- .end = 0,
.flags = IORESOURCE_IRQ,
},
{
.name = "FIFO_TH",
- .start = 1,
- .end = 1,
.flags = IORESOURCE_IRQ,
},
};
@@ -959,10 +951,10 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
}

static int __devinit stmpe_add_device(struct stmpe *stmpe,
- struct mfd_cell *cell, int irq)
+ struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base + irq, NULL);
+ NULL, stmpe->irq_base, NULL);
}

static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -970,7 +962,7 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
struct stmpe_variant_info *variant = stmpe->variant;
unsigned int platform_blocks = stmpe->pdata->blocks;
int ret = -EINVAL;
- int i;
+ int i, j;

for (i = 0; i < variant->num_blocks; i++) {
struct stmpe_variant_block *block = &variant->blocks[i];
@@ -978,8 +970,17 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
if (!(platform_blocks & block->block))
continue;

+ for (j = 0; j < block->cell->num_resources; j++) {
+ struct resource *res =
+ (struct resource *) &block->cell->resources[j];
+
+ /* Dynamically fill in a variant's IRQ. */
+ if (res->flags & IORESOURCE_IRQ)
+ res->start = res->end = block->irq + j;
+ }
+
platform_blocks &= ~block->block;
- ret = stmpe_add_device(stmpe, block->cell, block->irq);
+ ret = stmpe_add_device(stmpe, block->cell);
if (ret)
return ret;
}
--
1.7.9.5

2012-11-05 16:16:28

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 1/8] mfd: ab8500-core: Remove unused ab8500-gpio IRQ ranges

On Monday 05 November 2012, Lee Jones wrote:
> The IRQ ranges provided in ab8500-core to be passed on to the
> ab8500-gpio driver are not only redundant, but they are also
> causing a warning in the boot log. These IRQ ranges, like any
> other MFD related IRQ resource are passed though MFD core for
> automatic conversion to virtual IRQs; however, MFD core does
> not support IRQ mapping of IRQ ranges. Let's just remove them.
>
> Cc: Samuel Ortiz <[email protected]>
> Signed-off-by: Lee Jones <[email protected]>

Acked-by: Arnd Bergmann <[email protected]>

2012-11-05 16:33:21

by Lee Jones

[permalink] [raw]
Subject: Re: [PATCH 1/8] mfd: ab8500-core: Remove unused ab8500-gpio IRQ ranges

On Mon, 05 Nov 2012, Arnd Bergmann wrote:

> On Monday 05 November 2012, Lee Jones wrote:
> > The IRQ ranges provided in ab8500-core to be passed on to the
> > ab8500-gpio driver are not only redundant, but they are also
> > causing a warning in the boot log. These IRQ ranges, like any
> > other MFD related IRQ resource are passed though MFD core for
> > automatic conversion to virtual IRQs; however, MFD core does
> > not support IRQ mapping of IRQ ranges. Let's just remove them.
> >
> > Cc: Samuel Ortiz <[email protected]>
> > Signed-off-by: Lee Jones <[email protected]>
>
> Acked-by: Arnd Bergmann <[email protected]>

Whoops, I missed Linus' Tested-by on this patch too, so:

Tested-by: Linus Walleij <[email protected]>

I also forgot to to mention that this should really be going
for the -rcs rather than -next.

Kind regards,
Lee

--
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

2012-11-11 23:33:07

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 0/8] mfd: Batch together MFD related patches

Hi Lee,

On Mon, Nov 05, 2012 at 04:10:28PM +0100, Lee Jones wrote:
> Hi Sam,
>
> I know you've been busy giving NFC presentations at ELC, but ... :)
>
> All these patches have been on the list in various other patch-sets
> for some time and have been reviewed by some key people already. All
> other patches from the patch-sets have been taken, so I thought I'd
> batch these up for easy review/acceptance.
Thanks, much appreciated.
I applied all of them to my for-next branch. I don't think patch #1 is rc
material though, as it only fixes a boot warning and not an actual bug or
regression.

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/