2009-07-03 13:12:28

by Du, Alek

[permalink] [raw]
Subject: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

Changes from v2:
1. Add missed MODULE_DEVICE_TABLE

Changes from v1:
1. driver name changed from lnw.c ==> langwell_gpio.c
2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
3. removed alternative function setting code, it should be called in platform init part.
4. misc. style clean


>From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Tue, 30 Jun 2009 12:13:27 +0800
Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver

The Langwell chip is the IO hub for Intel Moorestown platform which has a
64-pin gpio block device inside. It is exposed as a dedicated PCI device.
We use it to control outside peripheral as well as to do IRQ demuxing. The
gpio block uses MSI to send level type interrupt to IOAPIC.

Signed-off-by: Alek Du <[email protected]>
CC: David Brownell <[email protected]>
---
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/langwell_gpio.c | 318 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 325 insertions(+), 0 deletions(-)
create mode 100644 drivers/gpio/langwell_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3582c39..c9675de 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -167,6 +167,12 @@ config GPIO_BT8XX

If unsure, say N.

+config GPIO_LANGWELL
+ tristate "Intel Moorestown Platform Langwell GPIO support"
+ depends on PCI
+ help
+ Say Y here to support Intel Moorestown platform GPIO.
+
comment "SPI GPIO expanders:"

config GPIO_MAX7301
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ef90203..a267d5d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061) += pl061.o
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
+obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
new file mode 100644
index 0000000..e338baa
--- /dev/null
+++ b/drivers/gpio/langwell_gpio.c
@@ -0,0 +1,318 @@
+/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
+ * Copyright (c) 2008 - 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Moorestown platform Langwell chip.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+struct lnw_gpio_register {
+ u32 GPLR[2];
+ u32 GPDR[2];
+ u32 GPSR[2];
+ u32 GPCR[2];
+ u32 GRER[2];
+ u32 GFER[2];
+ u32 GEDR[2];
+};
+
+struct lnw_gpio {
+ struct gpio_chip chip;
+ struct lnw_gpio_register *reg_base;
+ spinlock_t lock;
+ unsigned irq_base;
+};
+
+static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ u8 reg = offset / 32;
+ void __iomem *gplr;
+
+ gplr = (void __iomem *)(&lnw->reg_base->GPLR[reg]);
+ return readl(gplr) & BIT(offset % 32);
+}
+
+static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ u8 reg = offset / 32;
+ void __iomem *gpsr, *gpcr;
+
+ if (value) {
+ gpsr = (void __iomem *)(&lnw->reg_base->GPSR[reg]);
+ writel(BIT(offset % 32), gpsr);
+ } else {
+ gpcr = (void __iomem *)(&lnw->reg_base->GPCR[reg]);
+ writel(BIT(offset % 32), gpcr);
+ }
+}
+
+static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ u8 reg = offset / 32;
+ u32 value;
+ unsigned long flags;
+ void __iomem *gpdr;
+
+ gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]);
+ spin_lock_irqsave(&lnw->lock, flags);
+ value = readl(gpdr);
+ value &= ~BIT(offset % 32);
+ writel(value, gpdr);
+ spin_unlock_irqrestore(&lnw->lock, flags);
+ return 0;
+}
+
+static int lnw_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ u8 reg = offset / 32;
+ unsigned long flags;
+ void __iomem *gpdr;
+
+ lnw_gpio_set(chip, offset, value);
+ gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]);
+ spin_lock_irqsave(&lnw->lock, flags);
+ value = readl(gpdr);
+ value |= BIT(offset % 32);;
+ writel(value, gpdr);
+ spin_unlock_irqrestore(&lnw->lock, flags);
+ return 0;
+}
+
+static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
+ return lnw->irq_base + offset;
+}
+
+static int lnw_irq_type(unsigned irq, unsigned type)
+{
+ struct lnw_gpio *lnw = get_irq_chip_data(irq);
+ u32 gpio = irq - lnw->irq_base;
+ u8 reg = gpio / 32;
+ unsigned long flags;
+ u32 value;
+ void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]);
+ void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]);
+
+ if (gpio < 0 || gpio > lnw->chip.ngpio)
+ return -EINVAL;
+ spin_lock_irqsave(&lnw->lock, flags);
+ if (type & IRQ_TYPE_EDGE_RISING)
+ value = readl(grer) | BIT(gpio % 32);
+ else
+ value = readl(grer) & (~BIT(gpio % 32));
+ writel(value, grer);
+
+ if (type & IRQ_TYPE_EDGE_FALLING)
+ value = readl(gfer) | BIT(gpio % 32);
+ else
+ value = readl(gfer) & (~BIT(gpio % 32));
+ writel(value, gfer);
+ spin_unlock_irqrestore(&lnw->lock, flags);
+
+ return 0;
+};
+
+static void lnw_irq_unmask(unsigned irq)
+{
+ struct lnw_gpio *lnw = get_irq_chip_data(irq);
+ u32 gpio = irq - lnw->irq_base;
+ u8 reg = gpio / 32;
+ void __iomem *gedr;
+
+ gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]);
+ writel(BIT(gpio % 32), gedr);
+};
+
+static struct irq_chip lnw_irqchip = {
+ .name = "LNW-GPIO",
+ .unmask = lnw_irq_unmask,
+ .set_type = lnw_irq_type,
+};
+
+static struct pci_device_id lnw_gpio_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
+
+static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq);
+ u32 reg, gpio;
+ void __iomem *gedr;
+ u32 gedr_v;
+
+ /* check GPIO controller to check which pin triggered the interrupt */
+ for (reg = 0; reg < lnw->chip.ngpio / 32; reg++) {
+ gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]);
+ gedr_v = readl(gedr);
+ if (!gedr_v)
+ continue;
+ for (gpio = reg*32; gpio < reg*32+32; gpio++) {
+ gedr_v = readl(gedr);
+ if (gedr_v & BIT(gpio % 32)) {
+ pr_debug("pin %d triggered\n", gpio);
+ generic_handle_irq(lnw->irq_base + gpio);
+ }
+ }
+ /* clear the edge detect status bit */
+ writel(gedr_v, gedr);
+ }
+ desc->chip->eoi(irq);
+}
+
+static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void *base;
+ int i;
+ resource_size_t start, len;
+ struct lnw_gpio *lnw;
+ u32 irq_base;
+ u32 gpio_base;
+ int retval = 0;
+
+ retval = pci_enable_device(pdev);
+ if (retval)
+ goto done;
+
+ retval = pci_request_regions(pdev, "langwell_gpio");
+ if (retval) {
+ dev_err(&pdev->dev, "error requesting resources\n");
+ goto err2;
+ }
+ /* get the irq_base from bar1 */
+ start = pci_resource_start(pdev, 1);
+ len = pci_resource_len(pdev, 1);
+ base = ioremap_nocache(start, len);
+ if (!base) {
+ dev_err(&pdev->dev, "error mapping bar1\n");
+ goto err3;
+ }
+ irq_base = *(u32 *)base;
+ gpio_base = *((u32 *)base + 1);
+ /* release the IO mapping, since we already get the info from bar1 */
+ iounmap(base);
+ /* get the register base from bar0 */
+ start = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ base = ioremap_nocache(start, len);
+ if (!base) {
+ dev_err(&pdev->dev, "error mapping bar0\n");
+ retval = -EFAULT;
+ goto err3;
+ }
+
+ lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
+ if (!lnw) {
+ dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
+ retval = -ENOMEM;
+ goto err4;
+ }
+ lnw->reg_base = base;
+ lnw->irq_base = irq_base;
+ lnw->chip.label = dev_name(&pdev->dev);
+ lnw->chip.direction_input = lnw_gpio_direction_input;
+ lnw->chip.direction_output = lnw_gpio_direction_output;
+ lnw->chip.get = lnw_gpio_get;
+ lnw->chip.set = lnw_gpio_set;
+ lnw->chip.to_irq = lnw_gpio_to_irq;
+ lnw->chip.base = gpio_base;
+ lnw->chip.ngpio = 64;
+ lnw->chip.can_sleep = 0;
+ pci_set_drvdata(pdev, lnw);
+ retval = gpiochip_add(&lnw->chip);
+ if (retval) {
+ dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
+ goto err5;
+ }
+ set_irq_data(pdev->irq, lnw);
+ set_irq_chained_handler(pdev->irq, lnw_irq_handler);
+ for (i = 0; i < lnw->chip.ngpio; i++) {
+ set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
+ handle_simple_irq, "demux");
+ set_irq_chip_data(i + lnw->irq_base, lnw);
+ }
+
+ spin_lock_init(&lnw->lock);
+ goto done;
+err5:
+ kfree(lnw);
+err4:
+ iounmap(base);
+err3:
+ pci_release_regions(pdev);
+err2:
+ pci_disable_device(pdev);
+done:
+ return retval;
+}
+
+static void __devexit lnw_gpio_remove(struct pci_dev *pdev)
+{
+ struct lnw_gpio *lnw = (struct lnw_gpio *)pci_get_drvdata(pdev);
+
+ if (gpiochip_remove(&lnw->chip)) {
+ dev_err(&pdev->dev, "langwell gpio driver remove error\n");
+ return;
+ }
+ pci_disable_device(pdev);
+ set_irq_chained_handler(pdev->irq, NULL);
+ pci_release_regions(pdev);
+ iounmap(lnw->reg_base);
+ pci_set_drvdata(pdev, NULL);
+ kfree(lnw);
+}
+
+static struct pci_driver lnw_gpio_driver = {
+ .name = "langwell_gpio",
+ .id_table = lnw_gpio_ids,
+ .probe = lnw_gpio_probe,
+ .remove = lnw_gpio_remove,
+};
+
+static int __init lnw_gpio_init(void)
+{
+ return pci_register_driver(&lnw_gpio_driver);
+}
+
+static void __exit lnw_gpio_exit(void)
+{
+ pci_unregister_driver(&lnw_gpio_driver);
+}
+
+MODULE_AUTHOR("Alek Du <[email protected]>");
+MODULE_DESCRIPTION("Intel Moorestown Platform Langwell chip GPIO driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(lnw_gpio_init);
+module_exit(lnw_gpio_exit);
--
1.6.0.4


2009-07-30 11:00:35

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

On Fri, 3 Jul 2009 21:07:06 +0800 Alek Du <[email protected]> wrote:

> Changes from v2:
> 1. Add missed MODULE_DEVICE_TABLE
>
> Changes from v1:
> 1. driver name changed from lnw.c ==> langwell_gpio.c
> 2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
> 3. removed alternative function setting code, it should be called in platform init part.
> 4. misc. style clean
>
>
> >From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
> From: Alek Du <[email protected]>
> Date: Tue, 30 Jun 2009 12:13:27 +0800
> Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver
>
> The Langwell chip is the IO hub for Intel Moorestown platform which has a
> 64-pin gpio block device inside. It is exposed as a dedicated PCI device.
> We use it to control outside peripheral as well as to do IRQ demuxing. The
> gpio block uses MSI to send level type interrupt to IOAPIC.

The driver breaks the x86-64 allmodconfig build:

ERROR: "irq_to_desc" [drivers/gpio/langwell_gpio.ko] undefined!
ERROR: "set_irq_chip_and_handler_name" [drivers/gpio/langwell_gpio.ko] undefined!
ERROR: "handle_simple_irq" [drivers/gpio/langwell_gpio.ko] undefined!

Does it make any sense to build this driver as a module? If not, it
should be changed to def_bool. If so...



kernel/irq/chip.c | 2 ++
kernel/irq/handle.c | 1 +
2 files changed, 3 insertions(+)

diff -puN kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/handle.c
--- a/kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
+++ a/kernel/irq/handle.c
@@ -192,6 +192,7 @@ struct irq_desc *irq_to_desc(unsigned in

return NULL;
}
+EXPORT_SYMBOL(irq_to_desc);

struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
{
diff -puN kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/chip.c
--- a/kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
+++ a/kernel/irq/chip.c
@@ -340,6 +340,7 @@ handle_simple_irq(unsigned int irq, stru
out_unlock:
spin_unlock(&desc->lock);
}
+EXPORT_SYMBOL(handle_simple_irq);

/**
* handle_level_irq - Level type irq handler
@@ -609,6 +610,7 @@ set_irq_chip_and_handler_name(unsigned i
set_irq_chip(irq, chip);
__set_irq_handler(irq, handle, 0, name);
}
+EXPORT_SYMBOL(set_irq_chip_and_handler_name);

void __init set_irq_noprobe(unsigned int irq)
{
_

2009-07-31 09:03:26

by Du, Alek

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

Andrew,

Sorry for late response. Yes, you are right, there is no meaning to build it as module, it should be changed to bool.
I will submit a new patch soon, I also need a mask handler to irqchip .... otherwise the free_irq will report a error.

Thanks,
Alek




On Thu, 30 Jul 2009 18:59:41 +0800
Andrew Morton <[email protected]> wrote:

> On Fri, 3 Jul 2009 21:07:06 +0800 Alek Du <[email protected]> wrote:
>
> > Changes from v2:
> > 1. Add missed MODULE_DEVICE_TABLE
> >
> > Changes from v1:
> > 1. driver name changed from lnw.c ==> langwell_gpio.c
> > 2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
> > 3. removed alternative function setting code, it should be called in platform init part.
> > 4. misc. style clean
> >
> >
> > >From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
> > From: Alek Du <[email protected]>
> > Date: Tue, 30 Jun 2009 12:13:27 +0800
> > Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver
> >
> > The Langwell chip is the IO hub for Intel Moorestown platform which has a
> > 64-pin gpio block device inside. It is exposed as a dedicated PCI device.
> > We use it to control outside peripheral as well as to do IRQ demuxing. The
> > gpio block uses MSI to send level type interrupt to IOAPIC.
>
> The driver breaks the x86-64 allmodconfig build:
>
> ERROR: "irq_to_desc" [drivers/gpio/langwell_gpio.ko] undefined!
> ERROR: "set_irq_chip_and_handler_name" [drivers/gpio/langwell_gpio.ko] undefined!
> ERROR: "handle_simple_irq" [drivers/gpio/langwell_gpio.ko] undefined!
>
> Does it make any sense to build this driver as a module? If not, it
> should be changed to def_bool. If so...
>
>
>
> kernel/irq/chip.c | 2 ++
> kernel/irq/handle.c | 1 +
> 2 files changed, 3 insertions(+)
>
> diff -puN kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/handle.c
> --- a/kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
> +++ a/kernel/irq/handle.c
> @@ -192,6 +192,7 @@ struct irq_desc *irq_to_desc(unsigned in
>
> return NULL;
> }
> +EXPORT_SYMBOL(irq_to_desc);
>
> struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
> {
> diff -puN kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/chip.c
> --- a/kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
> +++ a/kernel/irq/chip.c
> @@ -340,6 +340,7 @@ handle_simple_irq(unsigned int irq, stru
> out_unlock:
> spin_unlock(&desc->lock);
> }
> +EXPORT_SYMBOL(handle_simple_irq);
>
> /**
> * handle_level_irq - Level type irq handler
> @@ -609,6 +610,7 @@ set_irq_chip_and_handler_name(unsigned i
> set_irq_chip(irq, chip);
> __set_irq_handler(irq, handle, 0, name);
> }
> +EXPORT_SYMBOL(set_irq_chip_and_handler_name);
>
> void __init set_irq_noprobe(unsigned int irq)
> {
> _
>
>

2009-07-31 13:22:58

by Du, Alek

[permalink] [raw]
Subject: [PATCH] mm gpio: Some fixing for Langwell GPIO driver

Andrew,

Here is an incremental patch against gpio-add-intel-moorestown-platform-langwell-chip-gpio-driver.patch in mm tree.
And I think you can revert 2f69806ebbdd67a816ff971ede66ac6597ffb991 export symbols patch now.

BR,
Alek


>From 626bf5fede836670db918d47d38b6956e6f7f759 Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 31 Jul 2009 21:07:44 +0800
Subject: [PATCH] gpio: Some fixing for Langwell GPIO driver

1. remove module support.
2. add a mask handler to irqchip.

Signed-off-by: Alek Du <[email protected]>
---
drivers/gpio/Kconfig | 2 +-
drivers/gpio/langwell_gpio.c | 34 ++++++----------------------------
2 files changed, 7 insertions(+), 29 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c310d67..9748c0c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -174,7 +174,7 @@ config GPIO_BT8XX
If unsure, say N.

config GPIO_LANGWELL
- tristate "Intel Moorestown Platform Langwell GPIO support"
+ bool "Intel Moorestown Platform Langwell GPIO support"
depends on PCI
help
Say Y here to support Intel Moorestown platform GPIO.
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index e338baa..e100583 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -152,8 +152,13 @@ static void lnw_irq_unmask(unsigned irq)
writel(BIT(gpio % 32), gedr);
};

+static void lnw_irq_mask(unsigned irq)
+{
+};
+
static struct irq_chip lnw_irqchip = {
.name = "LNW-GPIO",
+ .mask = lnw_irq_mask,
.unmask = lnw_irq_unmask,
.set_type = lnw_irq_type,
};
@@ -277,27 +282,10 @@ done:
return retval;
}

-static void __devexit lnw_gpio_remove(struct pci_dev *pdev)
-{
- struct lnw_gpio *lnw = (struct lnw_gpio *)pci_get_drvdata(pdev);
-
- if (gpiochip_remove(&lnw->chip)) {
- dev_err(&pdev->dev, "langwell gpio driver remove error\n");
- return;
- }
- pci_disable_device(pdev);
- set_irq_chained_handler(pdev->irq, NULL);
- pci_release_regions(pdev);
- iounmap(lnw->reg_base);
- pci_set_drvdata(pdev, NULL);
- kfree(lnw);
-}
-
static struct pci_driver lnw_gpio_driver = {
.name = "langwell_gpio",
.id_table = lnw_gpio_ids,
.probe = lnw_gpio_probe,
- .remove = lnw_gpio_remove,
};

static int __init lnw_gpio_init(void)
@@ -305,14 +293,4 @@ static int __init lnw_gpio_init(void)
return pci_register_driver(&lnw_gpio_driver);
}

-static void __exit lnw_gpio_exit(void)
-{
- pci_unregister_driver(&lnw_gpio_driver);
-}
-
-MODULE_AUTHOR("Alek Du <[email protected]>");
-MODULE_DESCRIPTION("Intel Moorestown Platform Langwell chip GPIO driver");
-MODULE_LICENSE("GPL v2");
-
-module_init(lnw_gpio_init);
-module_exit(lnw_gpio_exit);
+device_initcall(lnw_gpio_init);
--
1.6.0.4


On Fri, 31 Jul 2009 17:02:10 +0800
Alek Du <[email protected]> wrote:

> Andrew,
>
> Sorry for late response. Yes, you are right, there is no meaning to build it as module, it should be changed to bool.
> I will submit a new patch soon, I also need a mask handler to irqchip .... otherwise the free_irq will report a error.
>
> Thanks,
> Alek
>
>
>
>
> On Thu, 30 Jul 2009 18:59:41 +0800
> Andrew Morton <[email protected]> wrote:
>
> > On Fri, 3 Jul 2009 21:07:06 +0800 Alek Du <[email protected]> wrote:
> >
> > > Changes from v2:
> > > 1. Add missed MODULE_DEVICE_TABLE
> > >
> > > Changes from v1:
> > > 1. driver name changed from lnw.c ==> langwell_gpio.c
> > > 2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
> > > 3. removed alternative function setting code, it should be called in platform init part.
> > > 4. misc. style clean
> > >
> > >
> > > >From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
> > > From: Alek Du <[email protected]>
> > > Date: Tue, 30 Jun 2009 12:13:27 +0800
> > > Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver
> > >
> > > The Langwell chip is the IO hub for Intel Moorestown platform which has a
> > > 64-pin gpio block device inside. It is exposed as a dedicated PCI device.
> > > We use it to control outside peripheral as well as to do IRQ demuxing. The
> > > gpio block uses MSI to send level type interrupt to IOAPIC.
> >
> > The driver breaks the x86-64 allmodconfig build:
> >
> > ERROR: "irq_to_desc" [drivers/gpio/langwell_gpio.ko] undefined!
> > ERROR: "set_irq_chip_and_handler_name" [drivers/gpio/langwell_gpio.ko] undefined!
> > ERROR: "handle_simple_irq" [drivers/gpio/langwell_gpio.ko] undefined!
> >
> > Does it make any sense to build this driver as a module? If not, it
> > should be changed to def_bool. If so...
> >
> >
> >
> > kernel/irq/chip.c | 2 ++
> > kernel/irq/handle.c | 1 +
> > 2 files changed, 3 insertions(+)
> >
> > diff -puN kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/handle.c
> > --- a/kernel/irq/handle.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
> > +++ a/kernel/irq/handle.c
> > @@ -192,6 +192,7 @@ struct irq_desc *irq_to_desc(unsigned in
> >
> > return NULL;
> > }
> > +EXPORT_SYMBOL(irq_to_desc);
> >
> > struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
> > {
> > diff -puN kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch kernel/irq/chip.c
> > --- a/kernel/irq/chip.c~kernel-irq-export-symbols-needed-by-gpio-add-intel-moorestown-platform-langwell-chip-gpio-driverpatch
> > +++ a/kernel/irq/chip.c
> > @@ -340,6 +340,7 @@ handle_simple_irq(unsigned int irq, stru
> > out_unlock:
> > spin_unlock(&desc->lock);
> > }
> > +EXPORT_SYMBOL(handle_simple_irq);
> >
> > /**
> > * handle_level_irq - Level type irq handler
> > @@ -609,6 +610,7 @@ set_irq_chip_and_handler_name(unsigned i
> > set_irq_chip(irq, chip);
> > __set_irq_handler(irq, handle, 0, name);
> > }
> > +EXPORT_SYMBOL(set_irq_chip_and_handler_name);
> >
> > void __init set_irq_noprobe(unsigned int irq)
> > {
> > _
> >
> >

2009-09-17 23:36:50

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

On Fri, 3 Jul 2009 21:07:06 +0800
Alek Du <[email protected]> wrote:

> Changes from v2:
> 1. Add missed MODULE_DEVICE_TABLE
>
> Changes from v1:
> 1. driver name changed from lnw.c ==> langwell_gpio.c
> 2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
> 3. removed alternative function setting code, it should be called in platform init part.
> 4. misc. style clean
>
>
> >From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
> From: Alek Du <[email protected]>
> Date: Tue, 30 Jun 2009 12:13:27 +0800
> Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver
>
> The Langwell chip is the IO hub for Intel Moorestown platform which has a
> 64-pin gpio block device inside. It is exposed as a dedicated PCI device.
> We use it to control outside peripheral as well as to do IRQ demuxing. The
> gpio block uses MSI to send level type interrupt to IOAPIC.

sparc64 allmodconfig:

drivers/gpio/langwell_gpio.c: In function `lnw_irq_type':
drivers/gpio/langwell_gpio.c:117: error: implicit declaration of function `get_irq_chip_data'
drivers/gpio/langwell_gpio.c:117: warning: initialization makes pointer from integer without a cast
drivers/gpio/langwell_gpio.c:128: error: `IRQ_TYPE_EDGE_RISING' undeclared (first use in this function)
drivers/gpio/langwell_gpio.c:128: error: (Each undeclared identifier is reported only once
drivers/gpio/langwell_gpio.c:128: error: for each function it appears in.)
drivers/gpio/langwell_gpio.c:134: error: `IRQ_TYPE_EDGE_FALLING' undeclared (first use in this function)
drivers/gpio/langwell_gpio.c: In function `lnw_irq_unmask':
drivers/gpio/langwell_gpio.c:146: warning: initialization makes pointer from integer without a cast
drivers/gpio/langwell_gpio.c: At top level:
drivers/gpio/langwell_gpio.c:159: error: variable `lnw_irqchip' has initializer but incomplete type
drivers/gpio/langwell_gpio.c:160: error: unknown field `name' specified in initializer
drivers/gpio/langwell_gpio.c:160: warning: excess elements in struct initializer
drivers/gpio/langwell_gpio.c:160: warning: (near initialization for `lnw_irqchip')
drivers/gpio/langwell_gpio.c:161: error: unknown field `mask' specified in initializer
drivers/gpio/langwell_gpio.c:161: warning: excess elements in struct initializer
drivers/gpio/langwell_gpio.c:161: warning: (near initialization for `lnw_irqchip')
drivers/gpio/langwell_gpio.c:162: error: unknown field `unmask' specified in initializer
drivers/gpio/langwell_gpio.c:162: warning: excess elements in struct initializer
drivers/gpio/langwell_gpio.c:162: warning: (near initialization for `lnw_irqchip')
drivers/gpio/langwell_gpio.c:163: error: unknown field `set_type' specified in initializer
drivers/gpio/langwell_gpio.c:163: warning: excess elements in struct initializer
drivers/gpio/langwell_gpio.c:163: warning: (near initialization for `lnw_irqchip')
drivers/gpio/langwell_gpio.c: In function `lnw_irq_handler':
drivers/gpio/langwell_gpio.c:174: error: implicit declaration of function `get_irq_data'
drivers/gpio/langwell_gpio.c:174: warning: cast to pointer from integer of different size
drivers/gpio/langwell_gpio.c:189: error: implicit declaration of function `generic_handle_irq'
drivers/gpio/langwell_gpio.c:195: error: dereferencing pointer to incomplete type
drivers/gpio/langwell_gpio.c: In function `lnw_gpio_probe':
drivers/gpio/langwell_gpio.c:263: error: implicit declaration of function `set_irq_data'
drivers/gpio/langwell_gpio.c:264: error: implicit declaration of function `set_irq_chained_handler'
drivers/gpio/langwell_gpio.c:266: error: implicit declaration of function `set_irq_chip_and_handler_name'
drivers/gpio/langwell_gpio.c:267: error: `handle_simple_irq' undeclared (first use in this function)
drivers/gpio/langwell_gpio.c:268: error: implicit declaration of function `set_irq_chip_data'
drivers/gpio/langwell_gpio.c: At top level:
drivers/gpio/langwell_gpio.c:159: error: storage size of `lnw_irqchip' isn't known

2009-09-18 01:22:54

by Du, Alek

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

Andrew,

Sorry for the inconvenience. I do not have SPARC64 build env., but I think this patch will fix the build issue, I should include <linux/irq.h> by explicit.

>From 5f0f166b37c4313c27de32f6f200bbd0656603b7 Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 18 Sep 2009 09:09:19 +0800
Subject: [PATCH] gpio: Fix Langwell gpio driver build error

Need to include <linux/irq.h> directly ...

Signed-off-by: Alek Du <[email protected]>
---
drivers/gpio/langwell_gpio.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index e100583..10a1172 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/gpio.h>

struct lnw_gpio_register {
--
1.6.0.4


On Fri, 18 Sep 2009 07:36:44 +0800
Andrew Morton <[email protected]> wrote:

> On Fri, 3 Jul 2009 21:07:06 +0800
> Alek Du <[email protected]> wrote:
>
> > Changes from v2:
> > 1. Add missed MODULE_DEVICE_TABLE
> >
> > Changes from v1:
> > 1. driver name changed from lnw.c ==> langwell_gpio.c
> > 2. removed hard coded driver data, now we get it from PCI bar1 (platform init code fills it)
> > 3. removed alternative function setting code, it should be called in platform init part.
> > 4. misc. style clean
> >
> >
> > >From 8eaad3aac8cffda193adcfc4b9fcbb7c461fd4b9 Mon Sep 17 00:00:00 2001
> > From: Alek Du <[email protected]>
> > Date: Tue, 30 Jun 2009 12:13:27 +0800
> > Subject: [PATCH] gpio: add Intel Moorestown Platform Langwell chip gpio driver
> >
> > The Langwell chip is the IO hub for Intel Moorestown platform which has a
> > 64-pin gpio block device inside. It is exposed as a dedicated PCI device.
> > We use it to control outside peripheral as well as to do IRQ demuxing. The
> > gpio block uses MSI to send level type interrupt to IOAPIC.
>
> sparc64 allmodconfig:
>
> drivers/gpio/langwell_gpio.c: In function `lnw_irq_type':
> drivers/gpio/langwell_gpio.c:117: error: implicit declaration of function `get_irq_chip_data'
> drivers/gpio/langwell_gpio.c:117: warning: initialization makes pointer from integer without a cast
> drivers/gpio/langwell_gpio.c:128: error: `IRQ_TYPE_EDGE_RISING' undeclared (first use in this function)
> drivers/gpio/langwell_gpio.c:128: error: (Each undeclared identifier is reported only once
> drivers/gpio/langwell_gpio.c:128: error: for each function it appears in.)
> drivers/gpio/langwell_gpio.c:134: error: `IRQ_TYPE_EDGE_FALLING' undeclared (first use in this function)
> drivers/gpio/langwell_gpio.c: In function `lnw_irq_unmask':
> drivers/gpio/langwell_gpio.c:146: warning: initialization makes pointer from integer without a cast
> drivers/gpio/langwell_gpio.c: At top level:
> drivers/gpio/langwell_gpio.c:159: error: variable `lnw_irqchip' has initializer but incomplete type
> drivers/gpio/langwell_gpio.c:160: error: unknown field `name' specified in initializer
> drivers/gpio/langwell_gpio.c:160: warning: excess elements in struct initializer
> drivers/gpio/langwell_gpio.c:160: warning: (near initialization for `lnw_irqchip')
> drivers/gpio/langwell_gpio.c:161: error: unknown field `mask' specified in initializer
> drivers/gpio/langwell_gpio.c:161: warning: excess elements in struct initializer
> drivers/gpio/langwell_gpio.c:161: warning: (near initialization for `lnw_irqchip')
> drivers/gpio/langwell_gpio.c:162: error: unknown field `unmask' specified in initializer
> drivers/gpio/langwell_gpio.c:162: warning: excess elements in struct initializer
> drivers/gpio/langwell_gpio.c:162: warning: (near initialization for `lnw_irqchip')
> drivers/gpio/langwell_gpio.c:163: error: unknown field `set_type' specified in initializer
> drivers/gpio/langwell_gpio.c:163: warning: excess elements in struct initializer
> drivers/gpio/langwell_gpio.c:163: warning: (near initialization for `lnw_irqchip')
> drivers/gpio/langwell_gpio.c: In function `lnw_irq_handler':
> drivers/gpio/langwell_gpio.c:174: error: implicit declaration of function `get_irq_data'
> drivers/gpio/langwell_gpio.c:174: warning: cast to pointer from integer of different size
> drivers/gpio/langwell_gpio.c:189: error: implicit declaration of function `generic_handle_irq'
> drivers/gpio/langwell_gpio.c:195: error: dereferencing pointer to incomplete type
> drivers/gpio/langwell_gpio.c: In function `lnw_gpio_probe':
> drivers/gpio/langwell_gpio.c:263: error: implicit declaration of function `set_irq_data'
> drivers/gpio/langwell_gpio.c:264: error: implicit declaration of function `set_irq_chained_handler'
> drivers/gpio/langwell_gpio.c:266: error: implicit declaration of function `set_irq_chip_and_handler_name'
> drivers/gpio/langwell_gpio.c:267: error: `handle_simple_irq' undeclared (first use in this function)
> drivers/gpio/langwell_gpio.c:268: error: implicit declaration of function `set_irq_chip_data'
> drivers/gpio/langwell_gpio.c: At top level:
> drivers/gpio/langwell_gpio.c:159: error: storage size of `lnw_irqchip' isn't known
>

2009-09-18 03:38:45

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

On Fri, 18 Sep 2009 09:18:44 +0800 Alek Du <[email protected]> wrote:

> Sorry for the inconvenience. I do not have SPARC64 build env., but I think this patch will fix the build issue, I should include <linux/irq.h> by explicit.
>
> >From 5f0f166b37c4313c27de32f6f200bbd0656603b7 Mon Sep 17 00:00:00 2001
> From: Alek Du <[email protected]>
> Date: Fri, 18 Sep 2009 09:09:19 +0800
> Subject: [PATCH] gpio: Fix Langwell gpio driver build error
>
> Need to include <linux/irq.h> directly ...
>
> Signed-off-by: Alek Du <[email protected]>
> ---
> drivers/gpio/langwell_gpio.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
> index e100583..10a1172 100644
> --- a/drivers/gpio/langwell_gpio.c
> +++ b/drivers/gpio/langwell_gpio.c
> @@ -27,6 +27,7 @@
> #include <linux/interrupt.h>
> #include <linux/init.h>
> #include <linux/io.h>
> +#include <linux/irq.h>
> #include <linux/gpio.h>
>
> struct lnw_gpio_register {

include/linux/irq.h says

/*
* Please do not include this file in generic code. There is currently
* no requirement for any architecture to implement anything held
* within this file.
*
* Thanks. --rmk
*/

but

y:/usr/src/linux-2.6.31> grep -rl 'linux/irq.h' drivers | wc -l
101

Russell, is that rule no longer true?

Thanks.

2009-09-18 07:50:20

by Russell King

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

On Thu, Sep 17, 2009 at 08:38:26PM -0700, Andrew Morton wrote:
> On Fri, 18 Sep 2009 09:18:44 +0800 Alek Du <[email protected]> wrote:
>
> > Sorry for the inconvenience. I do not have SPARC64 build env., but I think this patch will fix the build issue, I should include <linux/irq.h> by explicit.
> >
> > >From 5f0f166b37c4313c27de32f6f200bbd0656603b7 Mon Sep 17 00:00:00 2001
> > From: Alek Du <[email protected]>
> > Date: Fri, 18 Sep 2009 09:09:19 +0800
> > Subject: [PATCH] gpio: Fix Langwell gpio driver build error
> >
> > Need to include <linux/irq.h> directly ...
> >
> > Signed-off-by: Alek Du <[email protected]>
> > ---
> > drivers/gpio/langwell_gpio.c | 1 +
> > 1 files changed, 1 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
> > index e100583..10a1172 100644
> > --- a/drivers/gpio/langwell_gpio.c
> > +++ b/drivers/gpio/langwell_gpio.c
> > @@ -27,6 +27,7 @@
> > #include <linux/interrupt.h>
> > #include <linux/init.h>
> > #include <linux/io.h>
> > +#include <linux/irq.h>
> > #include <linux/gpio.h>
> >
> > struct lnw_gpio_register {
>
> include/linux/irq.h says
>
> /*
> * Please do not include this file in generic code. There is currently
> * no requirement for any architecture to implement anything held
> * within this file.
> *
> * Thanks. --rmk
> */
>
> but
>
> y:/usr/src/linux-2.6.31> grep -rl 'linux/irq.h' drivers | wc -l
> 101
>
> Russell, is that rule no longer true?

Ever since ARM was converted over to genirq, I've given up fighting it.
It does still mean that any arch not using genirq is going to have
problems with these drivers.

I suspect that it's still the case that many of these includes should
be linux/interrupt.h and not linux/irq.h

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of:

2009-09-18 08:02:18

by Du, Alek

[permalink] [raw]
Subject: Re: [PATCH v3] gpio: add Intel Moorestown Platform Langwell chip gpio driver

On Fri, 18 Sep 2009 15:49:51 +0800
Russell King <[email protected]> wrote:

>
> Ever since ARM was converted over to genirq, I've given up fighting it.
> It does still mean that any arch not using genirq is going to have
> problems with these drivers.
>
> I suspect that it's still the case that many of these includes should
> be linux/interrupt.h and not linux/irq.h
>

I have included linux/interrupt.h, but it failed for sparc64 building. So I have to
send the patch to add linux/irq.h.

Thanks,
Alek