···263263config EDAC_PND2264264 tristate "Intel Pondicherry2"265265 depends on PCI && X86_64 && X86_MCE_INTEL266266+ select P2SB if X86266267 help267268 Support for error detection and correction on the Intel268269 Pondicherry2 Integrated Memory Controller. This SoC IP is
+20-42
drivers/edac/pnd2_edac.c
···2828#include <linux/bitmap.h>2929#include <linux/math64.h>3030#include <linux/mod_devicetable.h>3131+#include <linux/platform_data/x86/p2sb.h>3232+3133#include <asm/cpu_device_id.h>3234#include <asm/intel-family.h>3335#include <asm/processor.h>···234232 return U64_LSHIFT(hi.base, 32) | U64_LSHIFT(lo.base, 15);235233}236234237237-static u64 get_sideband_reg_base_addr(void)238238-{239239- struct pci_dev *pdev;240240- u32 hi, lo;241241- u8 hidden;242242-243243- pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x19dd, NULL);244244- if (pdev) {245245- /* Unhide the P2SB device, if it's hidden */246246- pci_read_config_byte(pdev, 0xe1, &hidden);247247- if (hidden)248248- pci_write_config_byte(pdev, 0xe1, 0);249249-250250- pci_read_config_dword(pdev, 0x10, &lo);251251- pci_read_config_dword(pdev, 0x14, &hi);252252- lo &= 0xfffffff0;253253-254254- /* Hide the P2SB device, if it was hidden before */255255- if (hidden)256256- pci_write_config_byte(pdev, 0xe1, hidden);257257-258258- pci_dev_put(pdev);259259- return (U64_LSHIFT(hi, 32) | U64_LSHIFT(lo, 0));260260- } else {261261- return 0xfd000000;262262- }263263-}264264-265235#define DNV_MCHBAR_SIZE 0x8000266236#define DNV_SB_PORT_SIZE 0x10000267237static int dnv_rd_reg(int port, int off, int op, void *data, size_t sz, char *name)268238{269239 struct pci_dev *pdev;270270- char *base;271271- u64 addr;272272- unsigned long size;240240+ void __iomem *base;241241+ struct resource r;242242+ int ret;273243274244 if (op == 4) {275245 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x1980, NULL);···253279 } else {254280 /* MMIO via memory controller hub base address */255281 if (op == 0 && port == 0x4c) {256256- addr = get_mem_ctrl_hub_base_addr();257257- if (!addr)282282+ memset(&r, 0, sizeof(r));283283+284284+ r.start = get_mem_ctrl_hub_base_addr();285285+ if (!r.start)258286 return -ENODEV;259259- size = DNV_MCHBAR_SIZE;287287+ r.end = r.start + DNV_MCHBAR_SIZE - 1;260288 } else {261289 /* MMIO via sideband register base address */262262- addr = get_sideband_reg_base_addr();263263- if (!addr)264264- return -ENODEV;265265- addr += (port << 16);266266- size = DNV_SB_PORT_SIZE;290290+ ret = p2sb_bar(NULL, 0, &r);291291+ if (ret)292292+ return ret;293293+294294+ r.start += (port << 16);295295+ r.end = r.start + DNV_SB_PORT_SIZE - 1;267296 }268297269269- base = ioremap((resource_size_t)addr, size);298298+ base = ioremap(r.start, resource_size(&r));270299 if (!base)271300 return -ENODEV;272301273302 if (sz == 8)274274- *(u32 *)(data + 4) = *(u32 *)(base + off + 4);275275- *(u32 *)data = *(u32 *)(base + off);303303+ *(u64 *)data = readq(base + off);304304+ else305305+ *(u32 *)data = readl(base + off);276306277307 iounmap(base);278308 }
+1
drivers/i2c/busses/Kconfig
···108108config I2C_I801109109 tristate "Intel 82801 (ICH/PCH)"110110 depends on PCI111111+ select P2SB if X86111112 select CHECK_SIGNATURE if X86 && DMI112113 select I2C_SMBUS113114 help
+9-30
drivers/i2c/busses/i2c-i801.c
···111111#include <linux/err.h>112112#include <linux/platform_device.h>113113#include <linux/platform_data/itco_wdt.h>114114+#include <linux/platform_data/x86/p2sb.h>114115#include <linux/pm_runtime.h>115116#include <linux/mutex.h>116117···141140#define TCOBASE 0x050142141#define TCOCTL 0x054143142144144-#define SBREG_BAR 0x10145143#define SBREG_SMBCTRL 0xc6000c146144#define SBREG_SMBCTRL_DNV 0xcf000c147145···14821482 .version = 4,14831483 };14841484 struct resource *res;14851485- unsigned int devfn;14861486- u64 base64_addr;14871487- u32 base_addr;14881488- u8 hidden;14851485+ int ret;1489148614901487 /*14911488 * We must access the NO_REBOOT bit over the Primary to Sideband14921492- * bridge (P2SB). The BIOS prevents the P2SB device from being14931493- * enumerated by the PCI subsystem, so we need to unhide/hide it14941494- * to lookup the P2SB BAR.14891489+ * (P2SB) bridge.14951490 */14961496- pci_lock_rescan_remove();14971497-14981498- devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1);14991499-15001500- /* Unhide the P2SB device, if it is hidden */15011501- pci_bus_read_config_byte(pci_dev->bus, devfn, 0xe1, &hidden);15021502- if (hidden)15031503- pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0);15041504-15051505- pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR, &base_addr);15061506- base64_addr = base_addr & 0xfffffff0;15071507-15081508- pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR + 0x4, &base_addr);15091509- base64_addr |= (u64)base_addr << 32;15101510-15111511- /* Hide the P2SB device, if it was hidden before */15121512- if (hidden)15131513- pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);15141514- pci_unlock_rescan_remove();1515149115161492 res = &tco_res[1];14931493+ ret = p2sb_bar(pci_dev->bus, 0, res);14941494+ if (ret)14951495+ return ERR_PTR(ret);14961496+15171497 if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)15181518- res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;14981498+ res->start += SBREG_SMBCTRL_DNV;15191499 else15201520- res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL;15001500+ res->start += SBREG_SMBCTRL;1521150115221502 res->end = res->start + 3;15231523- res->flags = IORESOURCE_MEM;1524150315251504 return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,15261505 tco_res, 2, &pldata, sizeof(pldata));
+3-3
drivers/leds/simple/Kconfig
···11# SPDX-License-Identifier: GPL-2.0-only22config LEDS_SIEMENS_SIMATIC_IPC33 tristate "LED driver for Siemens Simatic IPCs"44- depends on LEDS_CLASS44+ depends on LEDS_GPIO55 depends on SIEMENS_SIMATIC_IPC66 help77 This option enables support for the LEDs of several Industrial PCs88 from Siemens.991010- To compile this driver as a module, choose M here: the module1111- will be called simatic-ipc-leds.1010+ To compile this driver as a module, choose M here: the modules1111+ will be called simatic-ipc-leds and simatic-ipc-leds-gpio.
···2323#define SIMATIC_IPC_LED_PORT_BASE 0x404E24242525struct simatic_ipc_led {2626- unsigned int value; /* mask for io and offset for mem */2626+ unsigned int value; /* mask for io */2727 char *name;2828 struct led_classdev cdev;2929};···3535 {1 << 6, "yellow:" LED_FUNCTION_STATUS "-2" },3636 {1 << 13, "red:" LED_FUNCTION_STATUS "-3" },3737 {1 << 5, "yellow:" LED_FUNCTION_STATUS "-3" },3838- { }3939-};4040-4141-/* the actual start will be discovered with PCI, 0 is a placeholder */4242-static struct resource simatic_ipc_led_mem_res = DEFINE_RES_MEM_NAMED(0, SZ_4K, KBUILD_MODNAME);4343-4444-static void __iomem *simatic_ipc_led_memory;4545-4646-static struct simatic_ipc_led simatic_ipc_leds_mem[] = {4747- {0x500 + 0x1A0, "red:" LED_FUNCTION_STATUS "-1"},4848- {0x500 + 0x1A8, "green:" LED_FUNCTION_STATUS "-1"},4949- {0x500 + 0x1C8, "red:" LED_FUNCTION_STATUS "-2"},5050- {0x500 + 0x1D0, "green:" LED_FUNCTION_STATUS "-2"},5151- {0x500 + 0x1E0, "red:" LED_FUNCTION_STATUS "-3"},5252- {0x500 + 0x198, "green:" LED_FUNCTION_STATUS "-3"},5338 { }5439};5540···7388 return inw(SIMATIC_IPC_LED_PORT_BASE) & led->value ? LED_OFF : led_cd->max_brightness;7489}75907676-static void simatic_ipc_led_set_mem(struct led_classdev *led_cd,7777- enum led_brightness brightness)7878-{7979- struct simatic_ipc_led *led = cdev_to_led(led_cd);8080- void __iomem *reg = simatic_ipc_led_memory + led->value;8181- u32 val;8282-8383- val = readl(reg);8484- val = (val & ~1) | (brightness == LED_OFF);8585- writel(val, reg);8686-}8787-8888-static enum led_brightness simatic_ipc_led_get_mem(struct led_classdev *led_cd)8989-{9090- struct simatic_ipc_led *led = cdev_to_led(led_cd);9191- void __iomem *reg = simatic_ipc_led_memory + led->value;9292- u32 val;9393-9494- val = readl(reg);9595- return (val & 1) ? LED_OFF : led_cd->max_brightness;9696-}9797-9891static int simatic_ipc_leds_probe(struct platform_device *pdev)9992{10093 const struct simatic_ipc_platform *plat = pdev->dev.platform_data;···80117 struct simatic_ipc_led *ipcled;81118 struct led_classdev *cdev;82119 struct resource *res;8383- void __iomem *reg;8484- int err, type;8585- u32 val;120120+ int err;8612187122 switch (plat->devmode) {88123 case SIMATIC_IPC_DEVICE_227D:···95134 }96135 ipcled = simatic_ipc_leds_io;97136 }9898- type = IORESOURCE_IO;99137 if (!devm_request_region(dev, res->start, resource_size(res), KBUILD_MODNAME)) {100138 dev_err(dev, "Unable to register IO resource at %pR\n", res);101139 return -EBUSY;102140 }103103- break;104104- case SIMATIC_IPC_DEVICE_127E:105105- res = &simatic_ipc_led_mem_res;106106- ipcled = simatic_ipc_leds_mem;107107- type = IORESOURCE_MEM;108108-109109- /* get GPIO base from PCI */110110- res->start = simatic_ipc_get_membase0(PCI_DEVFN(13, 0));111111- if (res->start == 0)112112- return -ENODEV;113113-114114- /* do the final address calculation */115115- res->start = res->start + (0xC5 << 16);116116- res->end += res->start;117117-118118- simatic_ipc_led_memory = devm_ioremap_resource(dev, res);119119- if (IS_ERR(simatic_ipc_led_memory))120120- return PTR_ERR(simatic_ipc_led_memory);121121-122122- /* initialize power/watchdog LED */123123- reg = simatic_ipc_led_memory + 0x500 + 0x1D8; /* PM_WDT_OUT */124124- val = readl(reg);125125- writel(val & ~1, reg);126126-127127- reg = simatic_ipc_led_memory + 0x500 + 0x1C0; /* PM_BIOS_BOOT_N */128128- val = readl(reg);129129- writel(val | 1, reg);130141 break;131142 default:132143 return -ENODEV;···106173107174 while (ipcled->value) {108175 cdev = &ipcled->cdev;109109- if (type == IORESOURCE_MEM) {110110- cdev->brightness_set = simatic_ipc_led_set_mem;111111- cdev->brightness_get = simatic_ipc_led_get_mem;112112- } else {113113- cdev->brightness_set = simatic_ipc_led_set_io;114114- cdev->brightness_get = simatic_ipc_led_get_io;115115- }176176+ cdev->brightness_set = simatic_ipc_led_set_io;177177+ cdev->brightness_get = simatic_ipc_led_get_io;116178 cdev->max_brightness = LED_ON;117179 cdev->name = ipcled->name;118180
+1
drivers/mfd/Kconfig
···572572 tristate "Intel ICH LPC"573573 depends on PCI574574 select MFD_CORE575575+ select P2SB if X86575576 help576577 The LPC bridge function of the Intel ICH provides support for577578 many functional units. This driver provides needed support for
+54-20
drivers/mfd/bcm2835-pm.c
···2525 { .name = "bcm2835-power" },2626};27272828+static int bcm2835_pm_get_pdata(struct platform_device *pdev,2929+ struct bcm2835_pm *pm)3030+{3131+ if (of_find_property(pm->dev->of_node, "reg-names", NULL)) {3232+ struct resource *res;3333+3434+ pm->base = devm_platform_ioremap_resource_byname(pdev, "pm");3535+ if (IS_ERR(pm->base))3636+ return PTR_ERR(pm->base);3737+3838+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "asb");3939+ if (res) {4040+ pm->asb = devm_ioremap_resource(&pdev->dev, res);4141+ if (IS_ERR(pm->asb))4242+ pm->asb = NULL;4343+ }4444+4545+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,4646+ "rpivid_asb");4747+ if (res) {4848+ pm->rpivid_asb = devm_ioremap_resource(&pdev->dev, res);4949+ if (IS_ERR(pm->rpivid_asb))5050+ pm->rpivid_asb = NULL;5151+ }5252+5353+ return 0;5454+ }5555+5656+ /* If no 'reg-names' property is found we can assume we're using old DTB. */5757+ pm->base = devm_platform_ioremap_resource(pdev, 0);5858+ if (IS_ERR(pm->base))5959+ return PTR_ERR(pm->base);6060+6161+ pm->asb = devm_platform_ioremap_resource(pdev, 1);6262+ if (IS_ERR(pm->asb))6363+ pm->asb = NULL;6464+6565+ pm->rpivid_asb = devm_platform_ioremap_resource(pdev, 2);6666+ if (IS_ERR(pm->rpivid_asb))6767+ pm->rpivid_asb = NULL;6868+6969+ return 0;7070+}7171+2872static int bcm2835_pm_probe(struct platform_device *pdev)2973{3030- struct resource *res;3174 struct device *dev = &pdev->dev;3275 struct bcm2835_pm *pm;3376 int ret;···82398340 pm->dev = dev;84418585- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);8686- pm->base = devm_ioremap_resource(dev, res);8787- if (IS_ERR(pm->base))8888- return PTR_ERR(pm->base);4242+ ret = bcm2835_pm_get_pdata(pdev, pm);4343+ if (ret)4444+ return ret;89459046 ret = devm_mfd_add_devices(dev, -1,9147 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs),···9250 if (ret)9351 return ret;94529595- /* We'll use the presence of the AXI ASB regs in the5353+ /*5454+ * We'll use the presence of the AXI ASB regs in the9655 * bcm2835-pm binding as the key for whether we can reference9756 * the full PM register range and support power domains.9857 */9999- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);100100- if (res) {101101- pm->asb = devm_ioremap_resource(dev, res);102102- if (IS_ERR(pm->asb))103103- return PTR_ERR(pm->asb);104104-105105- ret = devm_mfd_add_devices(dev, -1,106106- bcm2835_power_devs,107107- ARRAY_SIZE(bcm2835_power_devs),108108- NULL, 0, NULL);109109- if (ret)110110- return ret;111111- }112112-5858+ if (pm->asb)5959+ return devm_mfd_add_devices(dev, -1, bcm2835_power_devs,6060+ ARRAY_SIZE(bcm2835_power_devs),6161+ NULL, 0, NULL);11362 return 0;11463}1156411665static const struct of_device_id bcm2835_pm_of_match[] = {11766 { .compatible = "brcm,bcm2835-pm-wdt", },11867 { .compatible = "brcm,bcm2835-pm", },6868+ { .compatible = "brcm,bcm2711-pm", },11969 {},12070};12171MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
+125-36
drivers/mfd/lpc_ich.c
···88 * Configuration Registers.99 *1010 * This driver is derived from lpc_sch.1111-1111+ *1212+ * Copyright (c) 2017, 2021-2022 Intel Corporation1213 * Copyright (c) 2011 Extreme Engineering Solution, Inc.1314 * Author: Aaron Sierra <asierra@xes-inc.com>1415 *···4342#include <linux/errno.h>4443#include <linux/acpi.h>4544#include <linux/pci.h>4545+#include <linux/pinctrl/pinctrl.h>4646#include <linux/mfd/core.h>4747#include <linux/mfd/lpc_ich.h>4848#include <linux/platform_data/itco_wdt.h>4949+#include <linux/platform_data/x86/p2sb.h>49505051#define ACPIBASE 0x405152#define ACPIBASE_GPE_OFF 0x28···7370#define SPIBASE_LPT_SZ 5127471#define BCR 0xdc7572#define BCR_WPD BIT(0)7676-7777-#define SPIBASE_APL_SZ 409678737974#define GPIOBASE_ICH0 0x588075#define GPIOCTRL_ICH0 0x5C···144143 .ignore_resource_conflicts = true,145144};146145146146+#define APL_GPIO_NORTH 0147147+#define APL_GPIO_NORTHWEST 1148148+#define APL_GPIO_WEST 2149149+#define APL_GPIO_SOUTHWEST 3150150+#define APL_GPIO_NR_DEVICES 4151151+152152+/* Offset data for Apollo Lake GPIO controllers */153153+static resource_size_t apl_gpio_offsets[APL_GPIO_NR_DEVICES] = {154154+ [APL_GPIO_NORTH] = 0xc50000,155155+ [APL_GPIO_NORTHWEST] = 0xc40000,156156+ [APL_GPIO_WEST] = 0xc70000,157157+ [APL_GPIO_SOUTHWEST] = 0xc00000,158158+};159159+160160+#define APL_GPIO_RESOURCE_SIZE 0x1000161161+162162+#define APL_GPIO_IRQ 14163163+164164+static struct resource apl_gpio_resources[APL_GPIO_NR_DEVICES][2] = {165165+ [APL_GPIO_NORTH] = {166166+ DEFINE_RES_MEM(0, 0),167167+ DEFINE_RES_IRQ(APL_GPIO_IRQ),168168+ },169169+ [APL_GPIO_NORTHWEST] = {170170+ DEFINE_RES_MEM(0, 0),171171+ DEFINE_RES_IRQ(APL_GPIO_IRQ),172172+ },173173+ [APL_GPIO_WEST] = {174174+ DEFINE_RES_MEM(0, 0),175175+ DEFINE_RES_IRQ(APL_GPIO_IRQ),176176+ },177177+ [APL_GPIO_SOUTHWEST] = {178178+ DEFINE_RES_MEM(0, 0),179179+ DEFINE_RES_IRQ(APL_GPIO_IRQ),180180+ },181181+};182182+183183+static const struct mfd_cell apl_gpio_devices[APL_GPIO_NR_DEVICES] = {184184+ [APL_GPIO_NORTH] = {185185+ .name = "apollolake-pinctrl",186186+ .id = APL_GPIO_NORTH,187187+ .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_NORTH]),188188+ .resources = apl_gpio_resources[APL_GPIO_NORTH],189189+ .ignore_resource_conflicts = true,190190+ },191191+ [APL_GPIO_NORTHWEST] = {192192+ .name = "apollolake-pinctrl",193193+ .id = APL_GPIO_NORTHWEST,194194+ .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_NORTHWEST]),195195+ .resources = apl_gpio_resources[APL_GPIO_NORTHWEST],196196+ .ignore_resource_conflicts = true,197197+ },198198+ [APL_GPIO_WEST] = {199199+ .name = "apollolake-pinctrl",200200+ .id = APL_GPIO_WEST,201201+ .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_WEST]),202202+ .resources = apl_gpio_resources[APL_GPIO_WEST],203203+ .ignore_resource_conflicts = true,204204+ },205205+ [APL_GPIO_SOUTHWEST] = {206206+ .name = "apollolake-pinctrl",207207+ .id = APL_GPIO_SOUTHWEST,208208+ .num_resources = ARRAY_SIZE(apl_gpio_resources[APL_GPIO_SOUTHWEST]),209209+ .resources = apl_gpio_resources[APL_GPIO_SOUTHWEST],210210+ .ignore_resource_conflicts = true,211211+ },212212+};147213148214static struct mfd_cell lpc_ich_spi_cell = {149215 .name = "intel-spi",···11541086 return ret;11551087}1156108810891089+static int lpc_ich_init_pinctrl(struct pci_dev *dev)10901090+{10911091+ struct resource base;10921092+ unsigned int i;10931093+ int ret;10941094+10951095+ /* Check, if GPIO has been exported as an ACPI device */10961096+ if (acpi_dev_present("INT3452", NULL, -1))10971097+ return -EEXIST;10981098+10991099+ ret = p2sb_bar(dev->bus, 0, &base);11001100+ if (ret)11011101+ return ret;11021102+11031103+ for (i = 0; i < ARRAY_SIZE(apl_gpio_devices); i++) {11041104+ struct resource *mem = &apl_gpio_resources[i][0];11051105+ resource_size_t offset = apl_gpio_offsets[i];11061106+11071107+ /* Fill MEM resource */11081108+ mem->start = base.start + offset;11091109+ mem->end = base.start + offset + APL_GPIO_RESOURCE_SIZE - 1;11101110+ mem->flags = base.flags;11111111+ }11121112+11131113+ return mfd_add_devices(&dev->dev, 0, apl_gpio_devices,11141114+ ARRAY_SIZE(apl_gpio_devices), NULL, 0, NULL);11151115+}11161116+11571117static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)11581118{11591119 u32 val;···11961100 return val & BYT_BCR_WPD;11971101}1198110211991199-static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)11031103+static bool lpc_ich_set_writeable(struct pci_bus *bus, unsigned int devfn)12001104{12011201- struct pci_dev *pdev = data;12021105 u32 bcr;1203110612041204- pci_read_config_dword(pdev, BCR, &bcr);11071107+ pci_bus_read_config_dword(bus, devfn, BCR, &bcr);12051108 if (!(bcr & BCR_WPD)) {12061109 bcr |= BCR_WPD;12071207- pci_write_config_dword(pdev, BCR, bcr);12081208- pci_read_config_dword(pdev, BCR, &bcr);11101110+ pci_bus_write_config_dword(bus, devfn, BCR, bcr);11111111+ pci_bus_read_config_dword(bus, devfn, BCR, &bcr);12091112 }1210111312111114 return bcr & BCR_WPD;12121115}1213111611171117+static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)11181118+{11191119+ struct pci_dev *pdev = data;11201120+11211121+ return lpc_ich_set_writeable(pdev->bus, pdev->devfn);11221122+}11231123+12141124static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)12151125{12161216- unsigned int spi = PCI_DEVFN(13, 2);12171217- struct pci_bus *bus = data;12181218- u32 bcr;11261126+ struct pci_dev *pdev = data;1219112712201220- pci_bus_read_config_dword(bus, spi, BCR, &bcr);12211221- if (!(bcr & BCR_WPD)) {12221222- bcr |= BCR_WPD;12231223- pci_bus_write_config_dword(bus, spi, BCR, bcr);12241224- pci_bus_read_config_dword(bus, spi, BCR, &bcr);12251225- }12261226-12271227- return bcr & BCR_WPD;11281128+ return lpc_ich_set_writeable(pdev->bus, PCI_DEVFN(13, 2));12281129}1229113012301131static int lpc_ich_init_spi(struct pci_dev *dev)···12301137 struct resource *res = &intel_spi_res[0];12311138 struct intel_spi_boardinfo *info;12321139 u32 spi_base, rcba;11401140+ int ret;1233114112341142 info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);12351143 if (!info)···12611167 }12621168 break;1263116912641264- case INTEL_SPI_BXT: {12651265- unsigned int p2sb = PCI_DEVFN(13, 0);12661266- unsigned int spi = PCI_DEVFN(13, 2);12671267- struct pci_bus *bus = dev->bus;12681268-11701170+ case INTEL_SPI_BXT:12691171 /*12701172 * The P2SB is hidden by BIOS and we need to unhide it in12711173 * order to read BAR of the SPI flash device. Once that is12721174 * done we hide it again.12731175 */12741274- pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x0);12751275- pci_bus_read_config_dword(bus, spi, PCI_BASE_ADDRESS_0,12761276- &spi_base);12771277- if (spi_base != ~0) {12781278- res->start = spi_base & 0xfffffff0;12791279- res->end = res->start + SPIBASE_APL_SZ - 1;11761176+ ret = p2sb_bar(dev->bus, PCI_DEVFN(13, 2), res);11771177+ if (ret)11781178+ return ret;1280117912811281- info->set_writeable = lpc_ich_bxt_set_writeable;12821282- info->data = bus;12831283- }12841284-12851285- pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);11801180+ info->set_writeable = lpc_ich_bxt_set_writeable;11811181+ info->data = dev;12861182 break;12871287- }1288118312891184 default:12901185 return -EINVAL;···1328124513291246 if (lpc_chipset_info[priv->chipset].gpio_version) {13301247 ret = lpc_ich_init_gpio(dev);12481248+ if (!ret)12491249+ cell_added = true;12501250+ }12511251+12521252+ if (priv->chipset == LPC_APL) {12531253+ ret = lpc_ich_init_pinctrl(dev);13311254 if (!ret)13321255 cell_added = true;13331256 }
+6-8
drivers/pinctrl/intel/pinctrl-intel.c
···1641164116421642const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_device *pdev)16431643{16441644+ const struct intel_pinctrl_soc_data * const *table;16441645 const struct intel_pinctrl_soc_data *data = NULL;16451645- const struct intel_pinctrl_soc_data **table;16461646- struct acpi_device *adev;16471647- unsigned int i;1648164616491649- adev = ACPI_COMPANION(&pdev->dev);16501650- if (adev) {16511651- const void *match = device_get_match_data(&pdev->dev);16471647+ table = device_get_match_data(&pdev->dev);16481648+ if (table) {16491649+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);16501650+ unsigned int i;1652165116531653- table = (const struct intel_pinctrl_soc_data **)match;16541652 for (i = 0; table[i]; i++) {16551653 if (!strcmp(adev->pnp.unique_id, table[i]->uid)) {16561654 data = table[i];···16621664 if (!id)16631665 return ERR_PTR(-ENODEV);1664166616651665- table = (const struct intel_pinctrl_soc_data **)id->driver_data;16671667+ table = (const struct intel_pinctrl_soc_data * const *)id->driver_data;16661668 data = table[pdev->id];16671669 }16681670
+12
drivers/platform/x86/intel/Kconfig
···7070 enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y7171 here; it will only load on supported platforms.72727373+config P2SB7474+ bool "Primary to Sideband (P2SB) bridge access support"7575+ depends on PCI7676+ help7777+ The Primary to Sideband (P2SB) bridge is an interface to some7878+ PCI devices connected through it. In particular, SPI NOR controller7979+ in Intel Apollo Lake SoC is one of such devices.8080+8181+ The main purpose of this library is to unhide P2SB device in case8282+ firmware kept it hidden on some platforms in order to access devices8383+ behind it.8484+7385config INTEL_BXTWC_PMIC_TMU7486 tristate "Intel Broxton Whiskey Cove TMU Driver"7587 depends on INTEL_SOC_PMIC_BXTWC
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * Primary to Sideband (P2SB) bridge access support44+ *55+ * Copyright (c) 2017, 2021-2022 Intel Corporation.66+ *77+ * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>88+ * Jonathan Yong <jonathan.yong@intel.com>99+ */1010+1111+#include <linux/bits.h>1212+#include <linux/export.h>1313+#include <linux/pci.h>1414+#include <linux/platform_data/x86/p2sb.h>1515+1616+#include <asm/cpu_device_id.h>1717+#include <asm/intel-family.h>1818+1919+#define P2SBC 0xe02020+#define P2SBC_HIDE BIT(8)2121+2222+static const struct x86_cpu_id p2sb_cpu_ids[] = {2323+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, PCI_DEVFN(13, 0)),2424+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, PCI_DEVFN(31, 1)),2525+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, PCI_DEVFN(31, 1)),2626+ X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, PCI_DEVFN(31, 1)),2727+ X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, PCI_DEVFN(31, 1)),2828+ X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, PCI_DEVFN(31, 1)),2929+ X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, PCI_DEVFN(31, 1)),3030+ {}3131+};3232+3333+static int p2sb_get_devfn(unsigned int *devfn)3434+{3535+ const struct x86_cpu_id *id;3636+3737+ id = x86_match_cpu(p2sb_cpu_ids);3838+ if (!id)3939+ return -ENODEV;4040+4141+ *devfn = (unsigned int)id->driver_data;4242+ return 0;4343+}4444+4545+static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)4646+{4747+ /* Copy resource from the first BAR of the device in question */4848+ *mem = pdev->resource[0];4949+ return 0;5050+}5151+5252+static int p2sb_scan_and_read(struct pci_bus *bus, unsigned int devfn, struct resource *mem)5353+{5454+ struct pci_dev *pdev;5555+ int ret;5656+5757+ pdev = pci_scan_single_device(bus, devfn);5858+ if (!pdev)5959+ return -ENODEV;6060+6161+ ret = p2sb_read_bar0(pdev, mem);6262+6363+ pci_stop_and_remove_bus_device(pdev);6464+ return ret;6565+}6666+6767+/**6868+ * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR6969+ * @bus: PCI bus to communicate with7070+ * @devfn: PCI slot and function to communicate with7171+ * @mem: memory resource to be filled in7272+ *7373+ * The BIOS prevents the P2SB device from being enumerated by the PCI7474+ * subsystem, so we need to unhide and hide it back to lookup the BAR.7575+ *7676+ * if @bus is NULL, the bus 0 in domain 0 will be used.7777+ * If @devfn is 0, it will be replaced by devfn of the P2SB device.7878+ *7979+ * Caller must provide a valid pointer to @mem.8080+ *8181+ * Locking is handled by pci_rescan_remove_lock mutex.8282+ *8383+ * Return:8484+ * 0 on success or appropriate errno value on error.8585+ */8686+int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)8787+{8888+ struct pci_dev *pdev_p2sb;8989+ unsigned int devfn_p2sb;9090+ u32 value = P2SBC_HIDE;9191+ int ret;9292+9393+ /* Get devfn for P2SB device itself */9494+ ret = p2sb_get_devfn(&devfn_p2sb);9595+ if (ret)9696+ return ret;9797+9898+ /* if @bus is NULL, use bus 0 in domain 0 */9999+ bus = bus ?: pci_find_bus(0, 0);100100+101101+ /*102102+ * Prevent concurrent PCI bus scan from seeing the P2SB device and103103+ * removing via sysfs while it is temporarily exposed.104104+ */105105+ pci_lock_rescan_remove();106106+107107+ /* Unhide the P2SB device, if needed */108108+ pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);109109+ if (value & P2SBC_HIDE)110110+ pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);111111+112112+ pdev_p2sb = pci_scan_single_device(bus, devfn_p2sb);113113+ if (devfn)114114+ ret = p2sb_scan_and_read(bus, devfn, mem);115115+ else116116+ ret = p2sb_read_bar0(pdev_p2sb, mem);117117+ pci_stop_and_remove_bus_device(pdev_p2sb);118118+119119+ /* Hide the P2SB device, if it was hidden */120120+ if (value & P2SBC_HIDE)121121+ pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, P2SBC_HIDE);122122+123123+ pci_unlock_rescan_remove();124124+125125+ if (ret)126126+ return ret;127127+128128+ if (mem->flags == 0)129129+ return -ENODEV;130130+131131+ return 0;132132+}133133+EXPORT_SYMBOL_GPL(p2sb_bar);
+4-39
drivers/platform/x86/simatic-ipc.c
···5151{5252 u8 ledmode = SIMATIC_IPC_DEVICE_NONE;5353 u8 wdtmode = SIMATIC_IPC_DEVICE_NONE;5454+ char *pdevname = KBUILD_MODNAME "_leds";5455 int i;55565657 platform_data.devmode = SIMATIC_IPC_DEVICE_NONE;···6564 }66656766 if (ledmode != SIMATIC_IPC_DEVICE_NONE) {6767+ if (ledmode == SIMATIC_IPC_DEVICE_127E)6868+ pdevname = KBUILD_MODNAME "_leds_gpio";6869 platform_data.devmode = ledmode;6970 ipc_led_platform_device =7071 platform_device_register_data(NULL,7171- KBUILD_MODNAME "_leds", PLATFORM_DEVID_NONE,7272+ pdevname, PLATFORM_DEVID_NONE,7273 &platform_data,7374 sizeof(struct simatic_ipc_platform));7475 if (IS_ERR(ipc_led_platform_device))···103100104101 return 0;105102}106106-107107-/* FIXME: this should eventually be done with generic P2SB discovery code108108- * the individual drivers for watchdogs and LEDs access memory that implements109109- * GPIO, but pinctrl will not come up because of missing ACPI entries110110- *111111- * While there is no conflict a cleaner solution would be to somehow bring up112112- * pinctrl even with these ACPI entries missing, and base the drivers on pinctrl.113113- * After which the following function could be dropped, together with the code114114- * poking the memory.115115- */116116-/*117117- * Get membase address from PCI, used in leds and wdt module. Here we read118118- * the bar0. The final address calculation is done in the appropriate modules119119- */120120-u32 simatic_ipc_get_membase0(unsigned int p2sb)121121-{122122- struct pci_bus *bus;123123- u32 bar0 = 0;124124- /*125125- * The GPIO memory is in bar0 of the hidden P2SB device.126126- * Unhide the device to have a quick look at it, before we hide it127127- * again.128128- * Also grab the pci rescan lock so that device does not get discovered129129- * and remapped while it is visible.130130- * This code is inspired by drivers/mfd/lpc_ich.c131131- */132132- bus = pci_find_bus(0, 0);133133- pci_lock_rescan_remove();134134- pci_bus_write_config_byte(bus, p2sb, 0xE1, 0x0);135135- pci_bus_read_config_dword(bus, p2sb, PCI_BASE_ADDRESS_0, &bar0);136136-137137- bar0 &= ~0xf;138138- pci_bus_write_config_byte(bus, p2sb, 0xE1, 0x1);139139- pci_unlock_rescan_remove();140140-141141- return bar0;142142-}143143-EXPORT_SYMBOL(simatic_ipc_get_membase0);144103145104static int __init simatic_ipc_init_module(void)146105{
+48-24
drivers/soc/bcm/bcm2835-power.c
···126126127127#define ASB_AXI_BRDG_ID 0x20128128129129-#define ASB_READ(reg) readl(power->asb + (reg))130130-#define ASB_WRITE(reg, val) writel(PM_PASSWORD | (val), power->asb + (reg))129129+#define BCM2835_BRDG_ID 0x62726467131130132131struct bcm2835_power_domain {133132 struct generic_pm_domain base;···141142 void __iomem *base;142143 /* AXI Async bridge registers. */143144 void __iomem *asb;145145+ /* RPiVid bridge registers. */146146+ void __iomem *rpivid_asb;144147145148 struct genpd_onecell_data pd_xlate;146149 struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];147150 struct reset_controller_dev reset;148151};149152150150-static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)153153+static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)151154{155155+ void __iomem *base = power->asb;152156 u64 start;157157+ u32 val;153158154154- if (!reg)159159+ switch (reg) {160160+ case 0:155161 return 0;162162+ case ASB_V3D_S_CTRL:163163+ case ASB_V3D_M_CTRL:164164+ if (power->rpivid_asb)165165+ base = power->rpivid_asb;166166+ break;167167+ }156168157169 start = ktime_get_ns();158170159171 /* Enable the module's async AXI bridges. */160160- ASB_WRITE(reg, ASB_READ(reg) & ~ASB_REQ_STOP);161161- while (ASB_READ(reg) & ASB_ACK) {172172+ if (enable) {173173+ val = readl(base + reg) & ~ASB_REQ_STOP;174174+ } else {175175+ val = readl(base + reg) | ASB_REQ_STOP;176176+ }177177+ writel(PM_PASSWORD | val, base + reg);178178+179179+ while (readl(base + reg) & ASB_ACK) {162180 cpu_relax();163181 if (ktime_get_ns() - start >= 1000)164182 return -ETIMEDOUT;···184168 return 0;185169}186170171171+static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)172172+{173173+ return bcm2835_asb_control(power, reg, true);174174+}175175+187176static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)188177{189189- u64 start;190190-191191- if (!reg)192192- return 0;193193-194194- start = ktime_get_ns();195195-196196- /* Enable the module's async AXI bridges. */197197- ASB_WRITE(reg, ASB_READ(reg) | ASB_REQ_STOP);198198- while (!(ASB_READ(reg) & ASB_ACK)) {199199- cpu_relax();200200- if (ktime_get_ns() - start >= 1000)201201- return -ETIMEDOUT;202202- }203203-204204- return 0;178178+ return bcm2835_asb_control(power, reg, false);205179}206180207181static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)208182{209183 struct bcm2835_power *power = pd->power;184184+185185+ /* We don't run this on BCM2711 */186186+ if (power->rpivid_asb)187187+ return 0;210188211189 /* Enable functional isolation */212190 PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);···222212 int ret;223213 int inrush;224214 bool powok;215215+216216+ /* We don't run this on BCM2711 */217217+ if (power->rpivid_asb)218218+ return 0;225219226220 /* If it was already powered on by the fw, leave it that way. */227221 if (PM_READ(pm_reg) & PM_POWUP)···640626 power->dev = dev;641627 power->base = pm->base;642628 power->asb = pm->asb;629629+ power->rpivid_asb = pm->rpivid_asb;643630644644- id = ASB_READ(ASB_AXI_BRDG_ID);645645- if (id != 0x62726467 /* "BRDG" */) {631631+ id = readl(power->asb + ASB_AXI_BRDG_ID);632632+ if (id != BCM2835_BRDG_ID /* "BRDG" */) {646633 dev_err(dev, "ASB register ID returned 0x%08x\n", id);647634 return -ENODEV;635635+ }636636+637637+ if (power->rpivid_asb) {638638+ id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);639639+ if (id != BCM2835_BRDG_ID /* "BRDG" */) {640640+ dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",641641+ id);642642+ return -ENODEV;643643+ }648644 }649645650646 power->pd_xlate.domains = devm_kcalloc(dev,
+1
drivers/watchdog/Kconfig
···16471647 tristate "Siemens Simatic IPC Watchdog"16481648 depends on SIEMENS_SIMATIC_IPC16491649 select WATCHDOG_CORE16501650+ select P2SB16501651 help16511652 This driver adds support for several watchdogs found in Industrial16521653 PCs from Siemens.
+8-7
drivers/watchdog/simatic-ipc-wdt.c
···1616#include <linux/kernel.h>1717#include <linux/module.h>1818#include <linux/pci.h>1919+#include <linux/platform_data/x86/p2sb.h>1920#include <linux/platform_data/x86/simatic-ipc-base.h>2021#include <linux/platform_device.h>2122#include <linux/sizes.h>···5554 DEFINE_RES_IO_NAMED(WD_TRIGGER_IOADR, SZ_1,5655 KBUILD_MODNAME " WD_TRIGGER_IOADR");57565858-/* the actual start will be discovered with pci, 0 is a placeholder */5757+/* the actual start will be discovered with p2sb, 0 is a placeholder */5958static struct resource mem_resource =6060- DEFINE_RES_MEM_NAMED(0, SZ_4, "WD_RESET_BASE_ADR");5959+ DEFINE_RES_MEM_NAMED(0, 0, "WD_RESET_BASE_ADR");61606261static u32 wd_timeout_table[] = {2, 4, 6, 8, 16, 32, 48, 64 };6362static void __iomem *wd_reset_base_addr;···151150 struct simatic_ipc_platform *plat = pdev->dev.platform_data;152151 struct device *dev = &pdev->dev;153152 struct resource *res;153153+ int ret;154154155155 switch (plat->devmode) {156156 case SIMATIC_IPC_DEVICE_227E:···192190 if (plat->devmode == SIMATIC_IPC_DEVICE_427E) {193191 res = &mem_resource;194192195195- /* get GPIO base from PCI */196196- res->start = simatic_ipc_get_membase0(PCI_DEVFN(0x1f, 1));197197- if (res->start == 0)198198- return -ENODEV;193193+ ret = p2sb_bar(NULL, 0, res);194194+ if (ret)195195+ return ret;199196200197 /* do the final address calculation */201198 res->start = res->start + (GPIO_COMMUNITY0_PORT_ID << 16) +202199 PAD_CFG_DW0_GPP_A_23;203203- res->end += res->start;200200+ res->end = res->start + SZ_4 - 1;204201205202 wd_reset_base_addr = devm_ioremap_resource(dev, res);206203 if (IS_ERR(wd_reset_base_addr))