[linux-yocto] [[PATCH 1/1] pinctrl: baytrail: unmap interrupt when free the gpio pin

chong.yi.chai at intel.com chong.yi.chai at intel.com
Wed Mar 30 20:16:57 PDT 2016


From: "Chai, Chong Yi" <chong.yi.chai at intel.com>

---
 features/soc/baytrail/baytrail.scc                 |   4 +
 ...trail-Serialize-GPIO-registers-access-wit.patch | 256 ++++++++++++++++
 ...trail-enable-platform-device-in-the-absen.patch | 339 +++++++++++++++++++++
 ...trail-setup-IOAPIC-interrupt-for-GPIO-clu.patch |  78 +++++
 ...trail-unmap-interrupt-when-free-the-gpio-.patch |  40 +++
 5 files changed, 717 insertions(+)
 create mode 100644 features/soc/baytrail/pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch
 create mode 100644 features/soc/baytrail/pinctrl-baytrail-enable-platform-device-in-the-absen.patch
 create mode 100644 features/soc/baytrail/pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch
 create mode 100644 features/soc/baytrail/pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch

diff --git a/features/soc/baytrail/baytrail.scc b/features/soc/baytrail/baytrail.scc
index 57c4cd7..b61a2e7 100644
--- a/features/soc/baytrail/baytrail.scc
+++ b/features/soc/baytrail/baytrail.scc
@@ -68,3 +68,7 @@ patch hpet-Fix-checkpatch.pl-warnings.patch
 patch libata-add-curr_xfer_mode-attribute.patch
 patch libata-enable-atapi_an-by-default.patch
 patch libata-handle-HDIO_SET_DMA-HDIO_GET_DMA-ioctl.patch
+patch pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch
+patch pinctrl-baytrail-enable-platform-device-in-the-absen.patch
+patch pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch
+patch pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch
diff --git a/features/soc/baytrail/pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch b/features/soc/baytrail/pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch
new file mode 100644
index 0000000..f4bca99
--- /dev/null
+++ b/features/soc/baytrail/pinctrl-baytrail-Serialize-GPIO-registers-access-wit.patch
@@ -0,0 +1,256 @@
+From 0a5d87717424225324dc7afcc79c305a6b87ac23 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Mon, 18 May 2015 12:49:57 +0800
+Subject: [PATCH 097/164] pinctrl-baytrail: Serialize GPIO registers access
+ with global spinlock
+
+When multiple drivers access the GPIO registers concurrently, it
+may result in unpredictable system behaviour, that is, write
+instructions may be dropped. As to fix this issue, add global
+lock for all reads and writes to serialize GPIO accessing.
+
+Referring to Errata: VLI63, VLT61
+Errata Web-link:
+https://cdiext.intel.com/cdi/edesign-infodesk/EDCDownloader.aspx?id=539130
+
+Version 3:
+- This is a forward ported version of the patch from byt_3.10.61_ltsi_dev
+  0d31cde pinctrl-baytrail: Serialize GPIO registers access with global spinlock
+
+Version 2:
+- This is a forward ported version of the patch from vlv_1.0.1_dev:
+  4b900f5 gpio-byt: Serialize GPIO registers access with global spinlock
+- Removed remaining instances of vg->lock
+
+Signed-off-by: Tan, Jui Nee <jui.nee.tan at intel.com>
+Signed-off-by: Petallo, MauriceX R <mauricex.r.petallo at intel.com>
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/pinctrl/pinctrl-baytrail.c |   57 +++++++++++++++++++++++++-----------
+ 1 files changed, 40 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
+index a2ebed6..0818dbd 100644
+--- a/drivers/pinctrl/pinctrl-baytrail.c
++++ b/drivers/pinctrl/pinctrl-baytrail.c
+@@ -125,11 +125,12 @@ static struct pinctrl_gpio_range byt_ranges[] = {
+ 	},
+ };
+ 
++static DEFINE_SPINLOCK(byt_reg_access_lock);
++
+ struct byt_gpio {
+ 	struct gpio_chip		chip;
+ 	struct irq_domain		*domain;
+ 	struct platform_device		*pdev;
+-	spinlock_t			lock;
+ 	void __iomem			*reg_base;
+ 	struct pinctrl_gpio_range	*range;
+ };
+@@ -171,14 +172,18 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) 
+ 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
+ 	u32 value;
+ 	bool special;
++	unsigned long flags;
+ 
+ 	/*
+ 	 * In most cases, func pin mux 000 means GPIO function.
+ 	 * But, some pins may have func pin mux 001 represents
+ 	 * GPIO function. Only allow user to export pin with
+ 	 * func pin mux preset as GPIO function by BIOS/FW.
+ 	 */
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 	value = readl(reg) & BYT_PIN_MUX;
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
++
+ 	special = is_special_pin(vg, offset);
+ 	if ((special && value != 1) || (!special && value)) {
+ 		dev_err(&vg->pdev->dev,
+@@ -197,11 +202,17 @@ static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
+ 	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+ 	u32 value;
+ 	unsigned int virq;
++	unsigned long flags;
++
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 
+ 	/* clear interrupt triggering */
+ 	value = readl(reg);
+ 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+ 	writel(value, reg);
++
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
++
+ 	virq = irq_find_mapping(vg->domain, offset);
+ 	irq_dispose_mapping(virq);
+ 
+@@ -219,7 +230,8 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
+ 	if (offset >= vg->chip.ngpio)
+ 		return -EINVAL;
+ 
+-	spin_lock_irqsave(&vg->lock, flags);
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
++
+ 	value = readl(reg);
+ 
+ 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
+@@ -244,7 +256,7 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
+ 	}
+ 	writel(value, reg);
+ 
+-	spin_unlock_irqrestore(&vg->lock, flags);
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ 
+ 	return 0;
+ }
+@@ -252,17 +264,23 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
+ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+ 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+-	return readl(reg) & BYT_LEVEL;
++	u32 value;
++	unsigned long flags;
++
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
++	value = readl(reg) & BYT_LEVEL;
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
++
++	return value;
+ }
+ 
+ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ {
+-	struct byt_gpio *vg = to_byt_gpio(chip);
+ 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+ 	unsigned long flags;
+ 	u32 old_val;
+ 
+-	spin_lock_irqsave(&vg->lock, flags);
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 
+ 	old_val = readl(reg);
+ 
+@@ -271,23 +289,22 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ 	else
+ 		writel(old_val & ~BYT_LEVEL, reg);
+ 
+-	spin_unlock_irqrestore(&vg->lock, flags);
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ }
+ 
+ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+ {
+-	struct byt_gpio *vg = to_byt_gpio(chip);
+ 	void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+ 	unsigned long flags;
+ 	u32 value;
+ 
+-	spin_lock_irqsave(&vg->lock, flags);
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 
+ 	value = readl(reg) | BYT_DIR_MASK;
+ 	value &= ~BYT_INPUT_EN;		/* active low */
+ 	writel(value, reg);
+ 
+-	spin_unlock_irqrestore(&vg->lock, flags);
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ 
+ 	return 0;
+ }
+@@ -295,12 +312,11 @@ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+ static int byt_gpio_direction_output(struct gpio_chip *chip,
+ 				     unsigned gpio, int value)
+ {
+-	struct byt_gpio *vg = to_byt_gpio(chip);
+ 	void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
+ 	unsigned long flags;
+ 	u32 reg_val;
+ 
+-	spin_lock_irqsave(&vg->lock, flags);
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 
+ 	reg_val = readl(reg) | BYT_DIR_MASK;
+ 	reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
+@@ -310,7 +326,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
+ 	else
+ 		writel(reg_val & ~BYT_LEVEL, reg);
+ 
+-	spin_unlock_irqrestore(&vg->lock, flags);
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ 
+ 	return 0;
+ }
+@@ -322,7 +338,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+ 	unsigned long flags;
+ 	u32 conf0, val, offs;
+ 
+-	spin_lock_irqsave(&vg->lock, flags);
++	spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 
+ 	for (i = 0; i < vg->chip.ngpio; i++) {
+ 		const char *label;
+@@ -347,7 +363,8 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+ 			   conf0 & BYT_TRIG_POS ? " rise" : "",
+ 			   conf0 & BYT_TRIG_LVL ? " level" : "");
+ 	}
+-	spin_unlock_irqrestore(&vg->lock, flags);
++
++	spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ }
+ 
+ static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+@@ -366,12 +419,15 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+ 	u32 pending;
+ 	unsigned virq;
+ 	int looplimit = 0;
++	unsigned long flags;
+ 
+ 	/* check from GPIO controller which pin triggered the interrupt */
+ 	for (base = 0; base < vg->chip.ngpio; base += 32) {
+ 
+ 		reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
+ 
++		spin_lock_irqsave(&byt_reg_access_lock, flags);
++
+ 		while ((pending = readl(reg))) {
+ 			pin = __ffs(pending);
+ 			mask = BIT(pin);
+@@ -339,6 +419,8 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+ 				break;
+ 			}
+ 		}
++
++		spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ 	}
+ 	chip->irq_eoi(data);
+ }
+@@ -444,14 +466,17 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
+ {
+ 	void __iomem *reg;
+ 	u32 base, value;
++	unsigned long flags;
+ 
+ 	/* clear interrupt status trigger registers */
+ 	for (base = 0; base < vg->chip.ngpio; base += 32) {
+ 		reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
++		spin_lock_irqsave(&byt_reg_access_lock, flags);
+ 		writel(0xffffffff, reg);
+ 		/* make sure trigger bits are cleared, if not then a pin
+ 		   might be misconfigured in bios */
+ 		value = readl(reg);
++		spin_unlock_irqrestore(&byt_reg_access_lock, flags);
+ 		if (value)
+ 			dev_err(&vg->pdev->dev,
+ 				"GPIO interrupt error, pins misconfigured\n");
+@@ -553,8 +578,6 @@ static int byt_gpio_probe(struct platform_device *pdev)
+ 	if (IS_ERR(vg->reg_base))
+ 		return PTR_ERR(vg->reg_base);
+ 
+-	spin_lock_init(&vg->lock);
+-
+ 	gc = &vg->chip;
+ 	gc->label = dev_name(&pdev->dev);
+ 	gc->owner = THIS_MODULE;
+-- 
+1.7.7.6
+
diff --git a/features/soc/baytrail/pinctrl-baytrail-enable-platform-device-in-the-absen.patch b/features/soc/baytrail/pinctrl-baytrail-enable-platform-device-in-the-absen.patch
new file mode 100644
index 0000000..2974a62
--- /dev/null
+++ b/features/soc/baytrail/pinctrl-baytrail-enable-platform-device-in-the-absen.patch
@@ -0,0 +1,339 @@
+From 0bfd2d51551e63d0d3238491f377fa86021880d6 Mon Sep 17 00:00:00 2001
+From: "Chew, Kean Ho" <kean.ho.chew at intel.com>
+Date: Wed, 12 Feb 2014 06:14:33 -0500
+Subject: [PATCH 016/164] pinctrl-baytrail: enable platform device in the
+ absent of ACPI enumeration
+
+This is to cater the need for non-ACPI system whereby
+a platform device has to be created in order to bind
+with the BYT Pinctrl GPIO platform driver.
+
+Conflicts:
+	drivers/pinctrl/Makefile
+
+Signed-off-by: Chew, Kean Ho <kean.ho.chew at intel.com>
+Signed-off-by: Chew, Chiau Ee <chiau.ee.chew at intel.com>
+Signed-off-by: Sreeju Selvaraj <sreeju.armughanx.selvaraj at intel.com>
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/pinctrl/Kconfig                |   19 ++++-
+ drivers/pinctrl/Makefile               |    1 +
+ drivers/pinctrl/pinctrl-baytrail-dev.c |  159 ++++++++++++++++++++++++++++++++
+ drivers/pinctrl/pinctrl-baytrail.c     |   19 +++-
+ include/linux/pinctrl/pinctrl-byt.h    |   16 +++
+ 5 files changed, 209 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/pinctrl/pinctrl-baytrail-dev.c
+ create mode 100644 include/linux/pinctrl/pinctrl-byt.h
+
+diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
+index 1e4e693..d0ce157 100644
+--- a/drivers/pinctrl/Kconfig
++++ b/drivers/pinctrl/Kconfig
+@@ -89,7 +89,7 @@ config PINCTRL_AT91
+ 
+ config PINCTRL_BAYTRAIL
+ 	bool "Intel Baytrail GPIO pin control"
+-	depends on GPIOLIB && ACPI && X86
++	depends on GPIOLIB && X86
+ 	select IRQ_DOMAIN
+ 	help
+ 	  driver for memory mapped GPIO functionality on Intel Baytrail
+@@ -97,7 +97,22 @@ config PINCTRL_BAYTRAIL
+ 	  Most pins are usually muxed to some other functionality by firmware,
+ 	  so only a small amount is available for gpio use.
+ 
+-	  Requires ACPI device enumeration code to set up a platform device.
++	  For ACPI platform, it would require ACPI device enumeration code
++	  to set up a platform device. Else, say yes to PINCTRL_BAYTRAIL_DEVICE
++	  as well to set up platform device in the absent of ACPI enumeration
++	  code.
++
++config PINCTRL_BAYTRAIL_DEVICE
++	bool "Intel Baytrail GPIO pin control Platform Device Emulation"
++	depends on PINCTRL_BAYTRAIL
++	help
++	  This driver is to set up platform device in the absent of ACPI
++	  enumeration.
++
++	  Say yes for non-ACPI platform. This will enable the platform devices
++	  to be created and bind with the BayTrail GPIO pin control platform
++	  driver.
++
+ 
+ config PINCTRL_BCM2835
+ 	bool
+diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
+index 4b83588..29b5ed1 100644
+--- a/drivers/pinctrl/Makefile
++++ b/drivers/pinctrl/Makefile
+@@ -21,6 +21,7 @@ obj-$(CONFIG_PINCTRL_BF60x)	+= pinctrl-adi2-bf60x.o
+ obj-$(CONFIG_PINCTRL_AT91)	+= pinctrl-at91.o
+ obj-$(CONFIG_PINCTRL_BCM2835)	+= pinctrl-bcm2835.o
+ obj-$(CONFIG_PINCTRL_BAYTRAIL)	+= pinctrl-baytrail.o
++obj-$(CONFIG_PINCTRL_BAYTRAIL_DEVICE)	+= pinctrl-baytrail-dev.o
+ obj-$(CONFIG_PINCTRL_CAPRI)	+= pinctrl-capri.o
+ obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
+ obj-$(CONFIG_PINCTRL_IMX1_CORE)	+= pinctrl-imx1-core.o
+diff --git a/drivers/pinctrl/pinctrl-baytrail-dev.c b/drivers/pinctrl/pinctrl-baytrail-dev.c
+new file mode 100644
+index 0000000..6754753
+--- /dev/null
++++ b/drivers/pinctrl/pinctrl-baytrail-dev.c
+@@ -0,0 +1,159 @@
++/*
++ * pinctrl-baytrail-dev.c: BayTrail pinctrl GPIO Platform Device
++ *
++ * (C) Copyright 2013 Intel Corporation
++ * Author: Kean Ho, Chew (kean.ho.chew at intel.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; version 2
++ * of the License.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/bitops.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/seq_file.h>
++#include <linux/pci.h>
++#include <linux/pinctrl/pinctrl-byt.h>
++
++/* PCI Memory Base Access */
++#define PCI_DEVICE_ID_INTEL_BYT_PCU	0x0f1c
++#define NO_REGISTER_SETTINGS	(BIT(0) | BIT(1) | BIT(2))
++
++/* Offsets */
++#define SCORE_OFFSET		0x0
++#define NCORE_OFFSET		0x1000
++#define SUS_OFFSET		0x2000
++#define SCORE_END		0x72C
++#define NCORE_END		0x970
++#define SUS_END			0x98C
++
++static struct byt_pinctrl_port byt_gpio_score_platform_data = {
++	.unique_id = "1",
++};
++
++static struct resource byt_gpio_score_resources[] = {
++	{
++		.start	= 0x0,
++		.end	= 0x0,
++		.flags	= IORESOURCE_MEM,
++		.name	= "io-memory",
++	},
++	{
++		.start	= 49,
++		.end	= 49,
++		.flags	= IORESOURCE_IRQ,
++		.name	= "irq",
++	}
++};
++
++static struct byt_pinctrl_port byt_gpio_ncore_platform_data = {
++	.unique_id = "2",
++};
++
++static struct resource byt_gpio_ncore_resources[] = {
++	{
++		.start	= 0x0,
++		.end	= 0x0,
++		.flags	= IORESOURCE_MEM,
++		.name	= "io-memory",
++	},
++	{
++		.start	= 48,
++		.end	= 48,
++		.flags	= IORESOURCE_IRQ,
++		.name	= "irq",
++	}
++};
++
++static struct byt_pinctrl_port byt_gpio_sus_platform_data = {
++	.unique_id = "3",
++};
++
++static struct resource byt_gpio_sus_resources[] = {
++	{
++		.start	= 0x0,
++		.end	= 0x0,
++		.flags	= IORESOURCE_MEM,
++		.name	= "io-memory",
++	},
++	{
++		.start	= 50,
++		.end	= 50,
++		.flags	= IORESOURCE_IRQ,
++		.name	= "irq",
++	}
++};
++
++static struct platform_device byt_gpio_score_device = {
++	.name			= "byt_gpio",
++	.id			= 0,
++	.num_resources		= ARRAY_SIZE(byt_gpio_score_resources),
++	.resource		= byt_gpio_score_resources,
++	.dev			= {
++		.platform_data	= &byt_gpio_score_platform_data,
++	}
++};
++
++static struct platform_device byt_gpio_ncore_device = {
++	.name			= "byt_gpio",
++	.id			= 1,
++	.num_resources		= ARRAY_SIZE(byt_gpio_ncore_resources),
++	.resource		= byt_gpio_ncore_resources,
++	.dev			= {
++		.platform_data	= &byt_gpio_ncore_platform_data,
++	}
++};
++
++static struct platform_device byt_gpio_sus_device = {
++	.name			= "byt_gpio",
++	.id			= 2,
++	.num_resources		= ARRAY_SIZE(byt_gpio_sus_resources),
++	.resource		= byt_gpio_sus_resources,
++	.dev			= {
++		.platform_data	= &byt_gpio_sus_platform_data,
++	}
++};
++
++static struct platform_device *devices[] __initdata = {
++	&byt_gpio_score_device,
++	&byt_gpio_ncore_device,
++	&byt_gpio_sus_device,
++};
++
++static int __init get_pci_memory_init(void)
++{
++	u32 io_base_add;
++	struct pci_dev *pci_dev;
++	pci_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
++				PCI_DEVICE_ID_INTEL_BYT_PCU,
++				NULL);
++
++	if (pci_dev == NULL) {
++		return -EFAULT;
++	};
++	pci_read_config_dword(pci_dev, 0x4c, &io_base_add);
++	io_base_add &= ~NO_REGISTER_SETTINGS;
++	byt_gpio_score_resources[0].start = io_base_add + SCORE_OFFSET;
++	byt_gpio_score_resources[0].end =
++				io_base_add + SCORE_OFFSET + SCORE_END;
++	byt_gpio_ncore_resources[0].start = io_base_add + NCORE_OFFSET;
++	byt_gpio_ncore_resources[0].end =
++				io_base_add + NCORE_OFFSET + NCORE_END;
++	byt_gpio_sus_resources[0].start = io_base_add + SUS_OFFSET;
++	byt_gpio_sus_resources[0].end = io_base_add + SUS_OFFSET + SUS_END;
++	return 0;
++};
++rootfs_initcall(get_pci_memory_init);
++
++
++static int __init byt_gpio_device_init(void)
++{
++	return platform_add_devices(devices, ARRAY_SIZE(devices));
++};
++device_initcall(byt_gpio_device_init);
+diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
+index 5e230c8..599cbcf 100644
+--- a/drivers/pinctrl/pinctrl-baytrail.c
++++ b/drivers/pinctrl/pinctrl-baytrail.c
+@@ -34,6 +34,7 @@
+ #include <linux/io.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinctrl-byt.h>
+ 
+ /* memory mapped register offsets */
+ #define BYT_CONF0_REG		0x000
+@@ -480,15 +481,19 @@ static int byt_gpio_probe(struct platform_device *pdev)
+ 	struct gpio_chip *gc;
+ 	struct resource *mem_rc, *irq_rc;
+ 	struct device *dev = &pdev->dev;
+-	struct acpi_device *acpi_dev;
+ 	struct pinctrl_gpio_range *range;
+-	acpi_handle handle = ACPI_HANDLE(dev);
+ 	unsigned hwirq;
+ 	int ret;
+ 
++#ifdef CONFIG_PINCTRL_BAYTRAIL_DEVICE
++	struct byt_pinctrl_port *platform_data = dev->platform_data;
++#else
++	struct acpi_device *acpi_dev;
++	acpi_handle handle = ACPI_HANDLE(dev);
++
+ 	if (acpi_bus_get_device(handle, &acpi_dev))
+ 		return -ENODEV;
+-
++#endif
+ 	vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
+ 	if (!vg) {
+ 		dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
+@@ -490,7 +495,11 @@ static int byt_gpio_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	for (range = byt_ranges; range->name; range++) {
++#ifdef CONFIG_PINCTRL_BAYTRAIL_DEVICE
++		if (!strcmp(platform_data->unique_id, range->name)) {
++#else
+ 		if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
++#endif
+ 			vg->chip.ngpio = range->npins;
+ 			vg->range = range;
+ 			break;
+@@ -573,12 +582,14 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
+ 	.runtime_resume = byt_gpio_runtime_resume,
+ };
+ 
++#ifndef CONFIG_PINCTRL_BAYTRAIL_DEVICE
+ static const struct acpi_device_id byt_gpio_acpi_match[] = {
+ 	{ "INT33B2", 0 },
+ 	{ "INT33FC", 0 },
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
++#endif
+ 
+ static int byt_gpio_remove(struct platform_device *pdev)
+ {
+@@ -599,8 +610,10 @@ static struct platform_driver byt_gpio_driver = {
+ 	.driver         = {
+ 		.name   = "byt_gpio",
+ 		.owner  = THIS_MODULE,
++#ifndef CONFIG_PINCTRL_BAYTRAIL_DEVICE
+ 		.pm	= &byt_gpio_pm_ops,
+ 		.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
++#endif
+ 	},
+ };
+ 
+diff --git a/include/linux/pinctrl/pinctrl-byt.h b/include/linux/pinctrl/pinctrl-byt.h
+new file mode 100644
+index 0000000..95db4b9
+--- /dev/null
++++ b/include/linux/pinctrl/pinctrl-byt.h
+@@ -0,0 +1,16 @@
++/*
++ * pinctrl-byt.h: BayTrail GPIO pinctrl header file
++ *
++ * Copyright (C) 2013 Intel Corporation
++ * Author: Chew, Kean Ho <kean.ho.chew at intel.com>
++ *
++ * 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.
++ */
++
++#ifdef CONFIG_PINCTRL_BAYTRAIL_DEVICE
++struct byt_pinctrl_port {
++	char *unique_id;
++};
++#endif
+-- 
+1.7.7.6
+
diff --git a/features/soc/baytrail/pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch b/features/soc/baytrail/pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch
new file mode 100644
index 0000000..c4de301
--- /dev/null
+++ b/features/soc/baytrail/pinctrl-baytrail-setup-IOAPIC-interrupt-for-GPIO-clu.patch
@@ -0,0 +1,78 @@
+From 0a933c448bbf42b1d0407eb81a68ad3b163f6599 Mon Sep 17 00:00:00 2001
+From: "Chew, Kean Ho" <kean.ho.chew at intel.com>
+Date: Tue, 11 Feb 2014 11:25:45 -0500
+Subject: [PATCH 017/164] pinctrl-baytrail: setup IOAPIC interrupt for GPIO
+ clusters on non-ACPI system
+
+BayTrail GPIO NORTH, SOUTH and SUS clusters use IRQ48,
+49 and 50 respectively. On non-ACPI system, we need
+to setup IOAPIC RTE for device that use interrupt
+beyond IRQ23.
+
+Conflicts:
+	drivers/pinctrl/pinctrl-baytrail.c
+
+Signed-off-by: Chew, Kean Ho <kean.ho.chew at intel.com>
+Signed-off-by: Chew, Chiau Ee <chiau.ee.chew at intel.com>
+Signed-off-by: Sreeju Selvaraj <sreeju.armughanx.selvaraj at intel.com>
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/pinctrl/pinctrl-baytrail.c |   35 +++++++++++++++++++++++++++++++++++
+ 1 files changed, 35 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
+index 599cbcf..a2ebed6 100644
+--- a/drivers/pinctrl/pinctrl-baytrail.c
++++ b/drivers/pinctrl/pinctrl-baytrail.c
+@@ -475,6 +475,36 @@ static const struct irq_domain_ops byt_gpio_irq_ops = {
+ 	.map = byt_gpio_irq_map,
+ };
+ 
++#ifdef CONFIG_PINCTRL_BAYTRAIL_DEVICE
++static int byt_gpio_irq_enable(unsigned hwirq, struct platform_device *pdev)
++{
++	struct io_apic_irq_attr irq_attr;
++	struct device *dev = &pdev->dev;
++	/*
++	 *  Since PCI BIOS is not able to provide IRQ mapping to
++	 *  IRQ24 and onward, we need register to ioapic directly
++	 *  and hardcode pci->irq= hwirq
++	 */
++	irq_attr.ioapic = mp_find_ioapic(hwirq);
++	if (irq_attr.ioapic < 0) {
++		dev_err(&pdev->dev,
++			"Unable to locate IOAPIC for IRQ=%d\n", hwirq);
++		return irq_attr.ioapic;
++	}
++	irq_attr.ioapic_pin = hwirq;
++	irq_attr.trigger = 1;	/* level */
++	irq_attr.polarity = 1;	/* active low */
++	io_apic_set_pci_routing(dev, hwirq, &irq_attr);
++	return 0;
++
++}
++#else
++static int byt_gpio_irq_enable(unsigned hwirq, struct platform_device *pdev)
++{
++	return 0;
++}
++#endif
++
+ static int byt_gpio_probe(struct platform_device *pdev)
+ {
+ 	struct byt_gpio *vg;
+@@ -550,6 +580,11 @@ static int byt_gpio_probe(struct platform_device *pdev)
+ 	if (irq_rc && irq_rc->start) {
+ 		hwirq = irq_rc->start;
+ 		gc->to_irq = byt_gpio_to_irq;
++		ret = byt_gpio_irq_enable(hwirq, pdev);
++		if (ret) {
++			dev_err(&pdev->dev, "failed to add GPIO to APIC\n");
++			return ret;
++		}
+ 
+ 		vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
+ 						   &byt_gpio_irq_ops, vg);
+-- 
+1.7.7.6
+
diff --git a/features/soc/baytrail/pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch b/features/soc/baytrail/pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch
new file mode 100644
index 0000000..840f07e
--- /dev/null
+++ b/features/soc/baytrail/pinctrl-baytrail-unmap-interrupt-when-free-the-gpio-.patch
@@ -0,0 +1,40 @@
+From 1d22c7e44b1e8b743622178b02ec1beb3f0bdadf Mon Sep 17 00:00:00 2001
+From: "Chew, Kean Ho" <kean.ho.chew at intel.com>
+Date: Wed, 12 Feb 2014 04:20:41 -0500
+Subject: [PATCH 015/164] pinctrl-baytrail: unmap interrupt when free the gpio
+ pin
+
+In to_irq() callback, we create the hwirq to linux irq
+mapping for the requested GPIO pin. Hence, we unamp
+the mapping when the gpio pin is being released.
+
+Signed-off-by: Chew, Kean Ho <kean.ho.chew at intel.com>
+Signed-off-by: Chew, Chiau Ee <chiau.ee.chew at intel.com>
+Signed-off-by: Sreeju Selvaraj <sreeju.armughanx.selvaraj at intel.com>
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/pinctrl/pinctrl-baytrail.c |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
+index f6ebaa7..5e230c8 100644
+--- a/drivers/pinctrl/pinctrl-baytrail.c
++++ b/drivers/pinctrl/pinctrl-baytrail.c
+@@ -195,11 +195,14 @@ static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
+ 	struct byt_gpio *vg = to_byt_gpio(chip);
+ 	void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
+ 	u32 value;
++	unsigned int virq;
+ 
+ 	/* clear interrupt triggering */
+ 	value = readl(reg);
+ 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+ 	writel(value, reg);
++	virq = irq_find_mapping(vg->domain, offset);
++	irq_dispose_mapping(virq);
+ 
+ 	pm_runtime_put(&vg->pdev->dev);
+ }
+-- 
+1.7.7.6
+
-- 
1.9.1



More information about the linux-yocto mailing list