The previous driver depends on a PCI device that is normally hidden by the BIOS, which means it can never bind correctly.
This driver uses the P2SB hide/unhide mechanism cooperatively to pass the PCI BAR address to the gpio platform driver. Original work by Tan, Jui Nee <jui.nee....@intel.com> Signed-off-by: Yong, Jonathan <jonathan.y...@intel.com> --- MAINTAINERS | 5 + drivers/mfd/Makefile | 2 +- drivers/mfd/lpc_ich-apl.c | 46 ++++++++ drivers/mfd/lpc_ich-core.c | 82 ++++++++++++- drivers/pinctrl/intel/Makefile | 1 - drivers/pinctrl/intel/pinctrl-apl-dev.c | 201 -------------------------------- include/linux/pinctrl/pinctrl-apl.h | 33 +++++- 7 files changed, 160 insertions(+), 210 deletions(-) create mode 100644 drivers/mfd/lpc_ich-apl.c delete mode 100644 drivers/pinctrl/intel/pinctrl-apl-dev.c diff --git a/MAINTAINERS b/MAINTAINERS index 5e13b56..66fc822 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2300,6 +2300,11 @@ S: Supported F: drivers/pinctrl/intel/pinctrl-apl-dev.c F: include/linux/pinctrl/pinctrl-apl.h +BROXTON PLATFORM TESTING +M: Yu, Ong Hock <ong.hock...@intel.com> +S: Supported +F: arch/x86/platform/bxt/* + BSG (block layer generic sg v4 driver) M: FUJITA Tomonori <fujita.tomon...@lab.ntt.co.jp> L: linux-s...@vger.kernel.org diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 39e09eb..5c63c8b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -144,7 +144,7 @@ obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o obj-$(CONFIG_LPC_ICH) += lpc_ich.o -lpc_ich-y := lpc_ich-core.o +lpc_ich-y := lpc_ich-core.o lpc_ich-apl.o obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o diff --git a/drivers/mfd/lpc_ich-apl.c b/drivers/mfd/lpc_ich-apl.c new file mode 100644 index 0000000..7e4afff --- /dev/null +++ b/drivers/mfd/lpc_ich-apl.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2015 Intel Corporation. All rights reserved. + * Author: Yong, Jonathan <jonathan.y...@intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/pinctrl/pinctrl-apl.h> +/* Offset data for Apollo Lake GPIO communities */ + +const struct apl_gpio_io_res apl_gpio_io_res_off[apl_pinctrl_max] = { + [apl_pinctrl_n] = { + .start = APL_GPIO_NORTH_OFFSET << 16, + .end = (APL_GPIO_NORTH_OFFSET << 16) + + APL_GPIO_NORTH_END, + .id = "1", + }, + [apl_pinctrl_nw] = { + .start = APL_GPIO_NORTHWEST_OFFSET << 16, + .end = (APL_GPIO_NORTHWEST_OFFSET << 16) + + APL_GPIO_NORTHWEST_END, + .id = "2", + }, + [apl_pinctrl_w] = { + .start = APL_GPIO_WEST_OFFSET << 16, + .end = (APL_GPIO_WEST_OFFSET << 16) + + APL_GPIO_WEST_END, + .id = "3", + }, + [apl_pinctrl_sw] = { + .start = APL_GPIO_SOUTHWEST_OFFSET << 16, + .end = (APL_GPIO_SOUTHWEST_OFFSET << 16) + + APL_GPIO_SOUTHWEST_END, + .id = "4", + }, +}; diff --git a/drivers/mfd/lpc_ich-core.c b/drivers/mfd/lpc_ich-core.c index 20a176b..15b2ac5 100644 --- a/drivers/mfd/lpc_ich-core.c +++ b/drivers/mfd/lpc_ich-core.c @@ -69,6 +69,7 @@ #include <linux/mfd/lpc_ich.h> #include <linux/platform_data/itco_wdt.h> #include <linux/platform_data/sbi_apl.h> +#include <linux/pinctrl/pinctrl-apl.h> #define ACPIBASE 0x40 #define ACPIBASE_GPE_OFF 0x28 @@ -1148,23 +1149,96 @@ wdt_done: return ret; } +#ifdef CONFIG_PINCTRL_APL_DEVICE +static struct resource apl_gpio_res[] = { + {}, + { + .start = 14, + .end = 14, + .flags = IORESOURCE_IRQ, + } +}; + +static struct apl_pinctrl_port apl_pinctrl_pdata; + +static const struct mfd_cell apl_gpio_devices = { + .name = "apl_gpio", + .resources = apl_gpio_res, + .num_resources = ARRAY_SIZE(apl_gpio_res), + .pdata_size = sizeof(apl_pinctrl_pdata), + .platform_data = &apl_pinctrl_pdata, + .ignore_resource_conflicts = true, +}; +#endif + static int lpc_ich_misc(struct pci_dev *dev, enum lpc_chipsets e, struct lpc_ich_priv *priv) { + int ret = -ENODEV; + unsigned int apl_p2sb = PCI_DEVFN(0x0d, 0); +#ifdef CONFIG_PINCTRL_APL_DEVICE + u32 dword; + resource_size_t apl_gpio_base = 0; +#endif + switch (e) { case LPC_APL: sbi_apl_data.name = lpc_ich_cells[LPC_P2SB_APL].name; sbi_apl_data.version = 1; sbi_apl_data.bus = 0; - sbi_apl_data.p2sb = PCI_DEVFN(0x0d, 0); + sbi_apl_data.p2sb = apl_p2sb; sbi_apl_data.lock = &priv->lock; - return mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, &lpc_ich_cells[LPC_P2SB_APL], 1, NULL, 0, NULL); - break; + if (ret) + dev_warn(&dev->dev, + "Failed to add Apollo Lake Sideband\n"); + + /* Apollo lake, has not 1, but 4 gpio controllers, handle it + a bit differently */ +#ifdef CONFIG_PINCTRL_APL_DEVICE + /* unhide and read apl_gpio_base */ + mutex_lock(&priv->lock); + pci_bus_write_config_byte(dev->bus, apl_p2sb, 0xe1, 0x0); + + /* Check if device present */ + pci_bus_read_config_dword(dev->bus, apl_p2sb, 0, + &dword); + if (dword == ~0 || dword == 0) { + mutex_unlock(&priv->lock); + dev_warn(&dev->dev, + "P2SB device access disabled by BIOS?\n"); + goto out_apl_pinctrl; + } + /* Get MMIO BAR */ + apl_gpio_res[0].flags = + lpc_ich_res(&apl_gpio_base, dev->bus, apl_p2sb, 0); + + /* rehide p2sb */ + pci_bus_write_config_byte(dev->bus, apl_p2sb, 0xe1, 0x1); + mutex_unlock(&priv->lock); + + for (dword = apl_pinctrl_n; dword < apl_pinctrl_max; dword++) { + apl_gpio_res[0].start = apl_gpio_base + + apl_gpio_io_res_off[dword].start; + apl_gpio_res[0].end = apl_gpio_base + + apl_gpio_io_res_off[dword].end; + apl_pinctrl_pdata.unique_id = + apl_gpio_io_res_off[dword].id; + ret = mfd_add_devices(&dev->dev, dword, + &apl_gpio_devices, 1, NULL, 0, NULL); + if (ret) + dev_warn(&dev->dev, + "Failed to add Apollo Lake GPIO %u\n", + dword); + } +out_apl_pinctrl: +#endif + return 0; default: break; } - return -ENODEV; + return ret; } static int lpc_ich_probe(struct pci_dev *dev, diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile index 2df696b..03bc68e 100644 --- a/drivers/pinctrl/intel/Makefile +++ b/drivers/pinctrl/intel/Makefile @@ -4,5 +4,4 @@ obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o -obj-$(CONFIG_PINCTRL_APL_DEVICE) += pinctrl-apl-dev.o obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o diff --git a/drivers/pinctrl/intel/pinctrl-apl-dev.c b/drivers/pinctrl/intel/pinctrl-apl-dev.c deleted file mode 100644 index 226ec6a..0000000 --- a/drivers/pinctrl/intel/pinctrl-apl-dev.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * pinctrl-apl-dev.c: APL pinctrl GPIO Platform Device - * - * (C) Copyright 2015 Intel Corporation - * Author: Kean Ho, Chew (kean.ho.c...@intel.com) - * Modified: Tan, Jui Nee (jui.nee....@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-apl.h> - -/* PCI Memory Base Access */ -#define PCI_DEVICE_ID_INTEL_APL_PCU 0x5A92 -#define NO_REGISTER_SETTINGS (BIT(0) | BIT(1) | BIT(2)) - -/* Offsets */ -#define NORTH_OFFSET 0xC5 -#define NORTHWEST_OFFSET 0xC4 -#define WEST_OFFSET 0xC7 -#define SOUTHWEST_OFFSET 0xC0 - -#define NORTH_END (90 * 0x8) -#define NORTHWEST_END (77 * 0x8) -#define WEST_END (47 * 0x8) -#define SOUTHWEST_END (43 * 0x8) - -static struct apl_pinctrl_port apl_gpio_north_platform_data = { - .unique_id = "1", -}; - -static struct resource apl_gpio_north_resources[] = { - { - .start = 0x0, - .end = 0x0, - .flags = IORESOURCE_MEM, - .name = "io-memory", - }, - { - .start = 14, - .end = 14, - .flags = IORESOURCE_IRQ, - .name = "irq", - } -}; - -static struct apl_pinctrl_port apl_gpio_northwest_platform_data = { - .unique_id = "2", -}; - -static struct resource apl_gpio_northwest_resources[] = { - { - .start = 0x0, - .end = 0x0, - .flags = IORESOURCE_MEM, - .name = "io-memory", - }, - { - .start = 14, - .end = 14, - .flags = IORESOURCE_IRQ, - .name = "irq", - } -}; - -static struct apl_pinctrl_port apl_gpio_west_platform_data = { - .unique_id = "3", -}; - -static struct resource apl_gpio_west_resources[] = { - { - .start = 0x0, - .end = 0x0, - .flags = IORESOURCE_MEM, - .name = "io-memory", - }, - { - .start = 14, - .end = 14, - .flags = IORESOURCE_IRQ, - .name = "irq", - } -}; - -static struct apl_pinctrl_port apl_gpio_southwest_platform_data = { - .unique_id = "4", -}; - -static struct resource apl_gpio_southwest_resources[] = { - { - .start = 0x0, - .end = 0x0, - .flags = IORESOURCE_MEM, - .name = "io-memory", - }, - { - .start = 14, - .end = 14, - .flags = IORESOURCE_IRQ, - .name = "irq", - } -}; - -static struct platform_device apl_gpio_north_device = { - .name = "apl_gpio", - .id = 0, - .num_resources = ARRAY_SIZE(apl_gpio_north_resources), - .resource = apl_gpio_north_resources, - .dev = { - .platform_data = &apl_gpio_north_platform_data, - } -}; - -static struct platform_device apl_gpio_northwest_device = { - .name = "apl_gpio", - .id = 1, - .num_resources = ARRAY_SIZE(apl_gpio_northwest_resources), - .resource = apl_gpio_northwest_resources, - .dev = { - .platform_data = &apl_gpio_northwest_platform_data, - } -}; - -static struct platform_device apl_gpio_west_device = { - .name = "apl_gpio", - .id = 2, - .num_resources = ARRAY_SIZE(apl_gpio_west_resources), - .resource = apl_gpio_west_resources, - .dev = { - .platform_data = &apl_gpio_west_platform_data, - } -}; - -static struct platform_device apl_gpio_southwest_device = { - .name = "apl_gpio", - .id = 3, - .num_resources = ARRAY_SIZE(apl_gpio_southwest_resources), - .resource = apl_gpio_southwest_resources, - .dev = { - .platform_data = &apl_gpio_southwest_platform_data, - } -}; - -static struct platform_device *devices[] __initdata = { - &apl_gpio_north_device, - &apl_gpio_northwest_device, - &apl_gpio_west_device, - &apl_gpio_southwest_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_APL_PCU, - NULL); - - if (pci_dev == NULL) - return -EFAULT; - - pci_read_config_dword(pci_dev, 0x10, &io_base_add); - io_base_add &= ~NO_REGISTER_SETTINGS; - apl_gpio_north_resources[0].start = - io_base_add + (NORTH_OFFSET << 16); - apl_gpio_north_resources[0].end = - io_base_add + (NORTH_OFFSET << 16) + NORTH_END; - apl_gpio_northwest_resources[0].start = - io_base_add + (NORTHWEST_OFFSET << 16); - apl_gpio_northwest_resources[0].end = - io_base_add + (NORTHWEST_OFFSET << 16) + NORTHWEST_END; - apl_gpio_west_resources[0].start = - io_base_add + (WEST_OFFSET << 16); - apl_gpio_west_resources[0].end = - io_base_add + (WEST_OFFSET << 16) + WEST_END; - apl_gpio_southwest_resources[0].start = - io_base_add + (SOUTHWEST_OFFSET << 16); - apl_gpio_southwest_resources[0].end = - io_base_add + (SOUTHWEST_OFFSET << 16) + SOUTHWEST_END; - return 0; -}; -rootfs_initcall(get_pci_memory_init); - -static int __init apl_gpio_device_init(void) -{ - return platform_add_devices(devices, ARRAY_SIZE(devices)); -}; -device_initcall(apl_gpio_device_init); diff --git a/include/linux/pinctrl/pinctrl-apl.h b/include/linux/pinctrl/pinctrl-apl.h index d414255..3bfec8a 100644 --- a/include/linux/pinctrl/pinctrl-apl.h +++ b/include/linux/pinctrl/pinctrl-apl.h @@ -10,9 +10,36 @@ * as published by the Free Software Foundation. */ -#ifdef CONFIG_PINCTRL_APL_DEVICE +#include <linux/types.h> + struct apl_pinctrl_port { - char *unique_id; + const char *unique_id; +}; + +enum apl_pinctrl_resource { + apl_pinctrl_n = 0, + apl_pinctrl_nw, + apl_pinctrl_w, + apl_pinctrl_sw, + apl_pinctrl_max, +}; + +/* Offsets */ +#define APL_GPIO_NORTH_OFFSET 0xC5 +#define APL_GPIO_NORTHWEST_OFFSET 0xC4 +#define APL_GPIO_WEST_OFFSET 0xC7 +#define APL_GPIO_SOUTHWEST_OFFSET 0xC0 + +#define APL_GPIO_NORTH_END (90 * 0x8) +#define APL_GPIO_NORTHWEST_END (77 * 0x8) +#define APL_GPIO_WEST_END (47 * 0x8) +#define APL_GPIO_SOUTHWEST_END (43 * 0x8) + +struct apl_gpio_io_res { + resource_size_t start; + resource_size_t end; + const char id[2]; }; -#endif + +extern const struct apl_gpio_io_res apl_gpio_io_res_off[apl_pinctrl_max]; -- 2.7.3 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto