From fbfee12274e8dd45b4597b873bda88403179b45b Mon Sep 17 00:00:00 2001
From: imititel <ionel-catalin.mititelu@intel.com>
Date: Fri, 15 Feb 2019 11:32:56 +0100
Subject: [PATCH 8/8] mfd-lpc_ich-Add-a-platform-device-for-pinctrl-denver
Patch-mainline: Not yet, to be clarified with Intel/EB
References: EB PoC
This is to cater the need in non-ACPI system whereby a platform device
has to be created in order to bind with the Denverton pinctrl driver.
Signed-off-by: Chuah, Kim Tatt <kim.tatt.chuah@intel.com>
Signed-off-by: Mititelu, Ionel Catalin <ionel-catalin.mititelu@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
drivers/mfd/lpc_ich.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index cf1120abbf52..9d478a936ac4 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -41,6 +41,7 @@
* document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
* document number 320066-003, 320257-008: EP80597 (IICH)
* document number 324645-001, 324646-001: Cougar Point (CPT)
+ * document number TBD : Denverton SoC (DNV}
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -135,6 +136,24 @@ static struct resource intel_spi_res[] = {
}
};
+static struct resource dnv_gpio_res[] = {
+ /* North GPIO community */
+ {
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_64,
+ },
+ /* South GPIO community */
+ {
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_64,
+ },
+ /* IRQ */
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = 14,
+ .end = 14,
+ },
+};
+
+
static struct mfd_cell lpc_ich_wdt_cell = {
.name = "iTCO_wdt",
.num_resources = ARRAY_SIZE(wdt_ich_res),
@@ -157,6 +176,13 @@ static struct mfd_cell lpc_ich_spi_cell = {
.ignore_resource_conflicts = true,
};
+static struct mfd_cell dnv_gpio_cell = {
+ .name = "denverton-pinctrl",
+ .num_resources = ARRAY_SIZE(dnv_gpio_res),
+ .resources = dnv_gpio_res,
+ .ignore_resource_conflicts = true,
+};
+
/* chipset related info */
enum lpc_chipsets {
LPC_ICH = 0, /* ICH */
@@ -229,6 +255,7 @@ enum lpc_chipsets {
LPC_APL, /* Apollo Lake SoC */
LPC_GLK, /* Gemini Lake SoC */
LPC_COUGARMOUNTAIN,/* Cougar Mountain SoC*/
+ LPC_DNV, /* Denverton SoC */
};
static struct lpc_ich_info lpc_chipset_info[] = {
@@ -565,6 +592,9 @@ static struct lpc_ich_info lpc_chipset_info[] = {
.name = "Cougar Mountain SoC",
.iTCO_version = 3,
},
+ [LPC_DNV] = {
+ .name = "Denverton SoC",
+ },
};
/*
@@ -809,6 +839,7 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa1c7), LPC_LEWISBURG},
{ PCI_VDEVICE(INTEL, 0xa242), LPC_LEWISBURG},
{ PCI_VDEVICE(INTEL, 0xa243), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0x19dc), LPC_DNV},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@@ -1169,6 +1200,48 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
&lpc_ich_spi_cell, 1, NULL, 0, NULL);
}
+static int lpc_ich_init_pinctrl(struct pci_dev *dev)
+{
+ struct lpc_ich_priv *priv = pci_get_drvdata(dev);
+ u32 val;
+
+ switch (priv->chipset) {
+ case LPC_DNV: {
+ unsigned int p2sb = PCI_DEVFN(31, 1);
+ struct pci_bus *bus = dev->bus;
+ /*
+ * The P2SB is hidden by BIOS and we need to unhide it in
+ * order to read BAR of the GPIO controllers. Once that is
+ * done we hide it again.
+ */
+ pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x0);
+ pci_bus_read_config_dword(bus, p2sb, PCI_BASE_ADDRESS_0, &val);
+
+ if (val == ~0)
+ return -ENODEV;
+
+ dnv_gpio_res[0].start = (val & 0xfffffff0) + (0xC2 << 16);
+ dnv_gpio_res[0].end = dnv_gpio_res[0].start + (41 * 0x8) - 1;
+
+ dnv_gpio_res[1].start = (val & 0xfffffff0) + (0xC5 << 16);
+ dnv_gpio_res[1].end = dnv_gpio_res[1].start + (113 * 0x8) - 1;
+
+ pci_bus_read_config_dword(bus, p2sb, PCI_BASE_ADDRESS_1, &val);
+ dnv_gpio_res[0].start |= ((u64)val) << 32;
+ dnv_gpio_res[1].start |= ((u64)val) << 32;
+
+ pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ return mfd_add_devices(&dev->dev, PLATFORM_DEVID_NONE,
+ &dnv_gpio_cell, 1, NULL, 0, NULL);
+}
+
static int lpc_ich_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
@@ -1218,6 +1291,9 @@ static int lpc_ich_probe(struct pci_dev *dev,
cell_added = true;
}
+ if (!lpc_ich_init_pinctrl(dev))
+ cell_added = true;
+
/*
* We only care if at least one or none of the cells registered
* successfully.
--
2.11.0