···11+These files allow sending arbitrary IPC commands to the PMC/SCU which22+may be dangerous. These will be removed eventually and should not be33+used in any new applications.44+55+What: /sys/bus/platform/devices/INT34D2:00/simplecmd66+Date: Jun 201577+KernelVersion: 4.188+Contact: Mika Westerberg <mika.westerberg@linux.intel.com>99+Description: This interface allows userspace to send an arbitrary1010+ IPC command to the PMC/SCU.1111+1212+ Format: %d %d where first number is command and1313+ second number is subcommand.1414+1515+What: /sys/bus/platform/devices/INT34D2:00/northpeak1616+Date: Jun 20151717+KernelVersion: 4.11818+Contact: Mika Westerberg <mika.westerberg@linux.intel.com>1919+Description: This interface allows userspace to enable and disable2020+ Northpeak through the PMC/SCU.2121+2222+ Format: %u.
+14-9
MAINTAINERS
···84998499S: Maintained85008500F: drivers/platform/x86/intel_atomisp2_pm.c8501850185028502+INTEL BROXTON PMC DRIVER85038503+M: Mika Westerberg <mika.westerberg@linux.intel.com>85048504+M: Zha Qipeng <qipeng.zha@intel.com>85058505+S: Maintained85068506+F: drivers/mfd/intel_pmc_bxt.c85078507+F: include/linux/mfd/intel_pmc_bxt.h85088508+85028509INTEL C600 SERIES SAS CONTROLLER DRIVER85038510M: Intel SCU Linux support <intel-linux-scu@intel.com>85048511M: Artur Paszkiewicz <artur.paszkiewicz@intel.com>···87138706F: include/uapi/linux/mic_ioctl.h87148707F: include/uapi/linux/scif_ioctl.h8715870887098709+INTEL P-Unit IPC DRIVER87108710+M: Zha Qipeng <qipeng.zha@intel.com>87118711+L: platform-driver-x86@vger.kernel.org87128712+S: Maintained87138713+F: arch/x86/include/asm/intel_punit_ipc.h87148714+F: drivers/platform/x86/intel_punit_ipc.c87158715+87168716INTEL PMC CORE DRIVER87178717M: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>87188718M: Vishwanath Somayaji <vishwanath.somayaji@intel.com>87198719L: platform-driver-x86@vger.kernel.org87208720S: Maintained87218721F: drivers/platform/x86/intel_pmc_core*87228722-87238723-INTEL PMC/P-Unit IPC DRIVER87248724-M: Zha Qipeng<qipeng.zha@intel.com>87258725-L: platform-driver-x86@vger.kernel.org87268726-S: Maintained87278727-F: arch/x86/include/asm/intel_pmc_ipc.h87288728-F: arch/x86/include/asm/intel_punit_ipc.h87298729-F: drivers/platform/x86/intel_pmc_ipc.c87308730-F: drivers/platform/x86/intel_punit_ipc.c8731872287328723INTEL PMIC GPIO DRIVERS87338724M: Andy Shevchenko <andy@kernel.org>
+1-1
arch/x86/Kconfig
···595595 select I2C596596 select DW_APB_TIMER597597 select APB_TIMER598598- select INTEL_SCU_IPC598598+ select INTEL_SCU_PCI599599 select MFD_INTEL_MSIC600600 ---help---601601 Select to build a kernel capable of supporting Intel MID (Mobile
···22#ifndef _ASM_X86_INTEL_SCU_IPC_H_33#define _ASM_X86_INTEL_SCU_IPC_H_4455-#include <linux/notifier.h>55+#include <linux/ioport.h>6677-#define IPCMSG_INDIRECT_READ 0x0288-#define IPCMSG_INDIRECT_WRITE 0x0577+struct device;88+struct intel_scu_ipc_dev;991010-#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */1010+/**1111+ * struct intel_scu_ipc_data - Data used to configure SCU IPC1212+ * @mem: Base address of SCU IPC MMIO registers1313+ * @irq: The IRQ number used for SCU (optional)1414+ */1515+struct intel_scu_ipc_data {1616+ struct resource mem;1717+ int irq;1818+};11191212-#define IPCMSG_WARM_RESET 0xF01313-#define IPCMSG_COLD_RESET 0xF11414-#define IPCMSG_SOFT_RESET 0xF21515-#define IPCMSG_COLD_BOOT 0xF32020+struct intel_scu_ipc_dev *2121+__intel_scu_ipc_register(struct device *parent,2222+ const struct intel_scu_ipc_data *scu_data,2323+ struct module *owner);16241717-#define IPCMSG_VRTC 0xFA /* Set vRTC device */1818- /* Command id associated with message IPCMSG_VRTC */1919- #define IPC_CMD_VRTC_SETTIME 1 /* Set time */2020- #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */2525+#define intel_scu_ipc_register(parent, scu_data) \2626+ __intel_scu_ipc_register(parent, scu_data, THIS_MODULE)21272222-/* Read single register */2323-int intel_scu_ipc_ioread8(u16 addr, u8 *data);2828+void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu);24292525-/* Read a vector */2626-int intel_scu_ipc_readv(u16 *addr, u8 *data, int len);3030+struct intel_scu_ipc_dev *3131+__devm_intel_scu_ipc_register(struct device *parent,3232+ const struct intel_scu_ipc_data *scu_data,3333+ struct module *owner);27342828-/* Write single register */2929-int intel_scu_ipc_iowrite8(u16 addr, u8 data);3535+#define devm_intel_scu_ipc_register(parent, scu_data) \3636+ __devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE)30373131-/* Write a vector */3232-int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);3838+struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void);3939+void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu);4040+struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev);33413434-/* Update single register based on the mask */3535-int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);4242+int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr,4343+ u8 *data);4444+int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr,4545+ u8 data);4646+int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr,4747+ u8 *data, size_t len);4848+int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr,4949+ u8 *data, size_t len);36503737-/* Issue commands to the SCU with or without data */3838-int intel_scu_ipc_simple_command(int cmd, int sub);3939-int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,4040- u32 *out, int outlen);5151+int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr,5252+ u8 data, u8 mask);41534242-extern struct blocking_notifier_head intel_scu_notifier;5454+int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,5555+ int sub);5656+int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd,5757+ int sub, const void *in, size_t inlen,5858+ size_t size, void *out, size_t outlen);43594444-static inline void intel_scu_notifier_add(struct notifier_block *nb)6060+static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd,6161+ int sub, const void *in, size_t inlen,6262+ void *out, size_t outlen)4563{4646- blocking_notifier_chain_register(&intel_scu_notifier, nb);6464+ return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen,6565+ inlen, out, outlen);4766}48674949-static inline void intel_scu_notifier_remove(struct notifier_block *nb)5050-{5151- blocking_notifier_chain_unregister(&intel_scu_notifier, nb);5252-}5353-5454-static inline int intel_scu_notifier_post(unsigned long v, void *p)5555-{5656- return blocking_notifier_call_chain(&intel_scu_notifier, v, p);5757-}5858-5959-#define SCU_AVAILABLE 16060-#define SCU_DOWN 26868+#include <asm/intel_scu_ipc_legacy.h>61696270#endif
+91
arch/x86/include/asm/intel_scu_ipc_legacy.h
···11+/* SPDX-License-Identifier: GPL-2.0 */22+#ifndef _ASM_X86_INTEL_SCU_IPC_LEGACY_H_33+#define _ASM_X86_INTEL_SCU_IPC_LEGACY_H_44+55+#include <linux/notifier.h>66+77+#define IPCMSG_INDIRECT_READ 0x0288+#define IPCMSG_INDIRECT_WRITE 0x0599+1010+#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */1111+1212+#define IPCMSG_WARM_RESET 0xF01313+#define IPCMSG_COLD_RESET 0xF11414+#define IPCMSG_SOFT_RESET 0xF21515+#define IPCMSG_COLD_BOOT 0xF31616+1717+#define IPCMSG_VRTC 0xFA /* Set vRTC device */1818+/* Command id associated with message IPCMSG_VRTC */1919+#define IPC_CMD_VRTC_SETTIME 1 /* Set time */2020+#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */2121+2222+/* Don't call these in new code - they will be removed eventually */2323+2424+/* Read single register */2525+static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data)2626+{2727+ return intel_scu_ipc_dev_ioread8(NULL, addr, data);2828+}2929+3030+/* Read a vector */3131+static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len)3232+{3333+ return intel_scu_ipc_dev_readv(NULL, addr, data, len);3434+}3535+3636+/* Write single register */3737+static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data)3838+{3939+ return intel_scu_ipc_dev_iowrite8(NULL, addr, data);4040+}4141+4242+/* Write a vector */4343+static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)4444+{4545+ return intel_scu_ipc_dev_writev(NULL, addr, data, len);4646+}4747+4848+/* Update single register based on the mask */4949+static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask)5050+{5151+ return intel_scu_ipc_dev_update(NULL, addr, data, mask);5252+}5353+5454+/* Issue commands to the SCU with or without data */5555+static inline int intel_scu_ipc_simple_command(int cmd, int sub)5656+{5757+ return intel_scu_ipc_dev_simple_command(NULL, cmd, sub);5858+}5959+6060+static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,6161+ u32 *out, int outlen)6262+{6363+ /* New API takes both inlen and outlen as bytes so convert here */6464+ size_t inbytes = inlen * sizeof(u32);6565+ size_t outbytes = outlen * sizeof(u32);6666+6767+ return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes,6868+ inlen, out, outbytes);6969+}7070+7171+extern struct blocking_notifier_head intel_scu_notifier;7272+7373+static inline void intel_scu_notifier_add(struct notifier_block *nb)7474+{7575+ blocking_notifier_chain_register(&intel_scu_notifier, nb);7676+}7777+7878+static inline void intel_scu_notifier_remove(struct notifier_block *nb)7979+{8080+ blocking_notifier_chain_unregister(&intel_scu_notifier, nb);8181+}8282+8383+static inline int intel_scu_notifier_post(unsigned long v, void *p)8484+{8585+ return blocking_notifier_call_chain(&intel_scu_notifier, v, p);8686+}8787+8888+#define SCU_AVAILABLE 18989+#define SCU_DOWN 29090+9191+#endif
···551551552552config INTEL_SOC_PMIC_BXTWC553553 tristate "Support for Intel Broxton Whiskey Cove PMIC"554554- depends on INTEL_PMC_IPC554554+ depends on MFD_INTEL_PMC_BXT555555 select MFD_CORE556556 select REGMAP_IRQ557557 help···593593 tristate "Support for Intel Merrifield Basin Cove PMIC"594594 depends on GPIOLIB595595 depends on ACPI596596- depends on INTEL_SCU_IPC596596+ depends on INTEL_SCU597597 select MFD_CORE598598 select REGMAP_IRQ599599 help···625625626626config MFD_INTEL_MSIC627627 bool "Intel MSIC"628628- depends on INTEL_SCU_IPC628628+ depends on INTEL_SCU629629 select MFD_CORE630630 help631631 Select this option to enable access to Intel MSIC (Avatele632632 Passage) chip. This chip embeds audio, battery, GPIO, etc.633633 devices used in Intel Medfield platforms.634634+635635+config MFD_INTEL_PMC_BXT636636+ tristate "Intel PMC Driver for Broxton"637637+ depends on X86638638+ depends on X86_PLATFORM_DEVICES639639+ depends on ACPI640640+ select INTEL_SCU_IPC641641+ select MFD_CORE642642+ help643643+ This driver provides support for the PMC (Power Management644644+ Controller) on Intel Broxton and Apollo Lake. The PMC is a645645+ multi-function device that exposes IPC, General Control646646+ Register and P-unit access. In addition this creates devices647647+ for iTCO watchdog and telemetry that are part of the PMC.634648635649config MFD_IPAQ_MICRO636650 bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support"
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * Driver for the Intel Broxton PMC44+ *55+ * (C) Copyright 2014 - 2020 Intel Corporation66+ *77+ * This driver is based on Intel SCU IPC driver (intel_scu_ipc.c) by88+ * Sreedhara DS <sreedhara.ds@intel.com>99+ *1010+ * The PMC (Power Management Controller) running on the ARC processor1111+ * communicates with another entity running in the IA (Intel Architecture)1212+ * core through an IPC (Intel Processor Communications) mechanism which in1313+ * turn sends messages between the IA and the PMC.1414+ */1515+1616+#include <linux/acpi.h>1717+#include <linux/delay.h>1818+#include <linux/errno.h>1919+#include <linux/interrupt.h>2020+#include <linux/io-64-nonatomic-lo-hi.h>2121+#include <linux/mfd/core.h>2222+#include <linux/mfd/intel_pmc_bxt.h>2323+#include <linux/module.h>2424+#include <linux/platform_device.h>2525+#include <linux/platform_data/itco_wdt.h>2626+2727+#include <asm/intel_scu_ipc.h>2828+2929+/* Residency with clock rate at 19.2MHz to usecs */3030+#define S0IX_RESIDENCY_IN_USECS(d, s) \3131+({ \3232+ u64 result = 10ull * ((d) + (s)); \3333+ do_div(result, 192); \3434+ result; \3535+})3636+3737+/* Resources exported from IFWI */3838+#define PLAT_RESOURCE_IPC_INDEX 03939+#define PLAT_RESOURCE_IPC_SIZE 0x10004040+#define PLAT_RESOURCE_GCR_OFFSET 0x10004141+#define PLAT_RESOURCE_GCR_SIZE 0x10004242+#define PLAT_RESOURCE_BIOS_DATA_INDEX 14343+#define PLAT_RESOURCE_BIOS_IFACE_INDEX 24444+#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 34545+#define PLAT_RESOURCE_ISP_DATA_INDEX 44646+#define PLAT_RESOURCE_ISP_IFACE_INDEX 54747+#define PLAT_RESOURCE_GTD_DATA_INDEX 64848+#define PLAT_RESOURCE_GTD_IFACE_INDEX 74949+#define PLAT_RESOURCE_ACPI_IO_INDEX 05050+5151+/*5252+ * BIOS does not create an ACPI device for each PMC function, but5353+ * exports multiple resources from one ACPI device (IPC) for multiple5454+ * functions. This driver is responsible for creating a child device and5555+ * to export resources for those functions.5656+ */5757+#define SMI_EN_OFFSET 0x00405858+#define SMI_EN_SIZE 45959+#define TCO_BASE_OFFSET 0x00606060+#define TCO_REGS_SIZE 166161+#define TELEM_SSRAM_SIZE 2406262+#define TELEM_PMC_SSRAM_OFFSET 0x1b006363+#define TELEM_PUNIT_SSRAM_OFFSET 0x1a006464+6565+/* Commands */6666+#define PMC_NORTHPEAK_CTRL 0xed6767+6868+static inline bool is_gcr_valid(u32 offset)6969+{7070+ return offset < PLAT_RESOURCE_GCR_SIZE - 8;7171+}7272+7373+/**7474+ * intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register7575+ * @pmc: PMC device pointer7676+ * @offset: offset of GCR register from GCR address base7777+ * @data: data pointer for storing the register output7878+ *7979+ * Reads the 64-bit PMC GCR register at given offset.8080+ *8181+ * Return: Negative value on error or 0 on success.8282+ */8383+int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, u64 *data)8484+{8585+ if (!is_gcr_valid(offset))8686+ return -EINVAL;8787+8888+ spin_lock(&pmc->gcr_lock);8989+ *data = readq(pmc->gcr_mem_base + offset);9090+ spin_unlock(&pmc->gcr_lock);9191+9292+ return 0;9393+}9494+EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64);9595+9696+/**9797+ * intel_pmc_gcr_update() - Update PMC GCR register bits9898+ * @pmc: PMC device pointer9999+ * @offset: offset of GCR register from GCR address base100100+ * @mask: bit mask for update operation101101+ * @val: update value102102+ *103103+ * Updates the bits of given GCR register as specified by104104+ * @mask and @val.105105+ *106106+ * Return: Negative value on error or 0 on success.107107+ */108108+int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, u32 mask, u32 val)109109+{110110+ u32 new_val;111111+112112+ if (!is_gcr_valid(offset))113113+ return -EINVAL;114114+115115+ spin_lock(&pmc->gcr_lock);116116+ new_val = readl(pmc->gcr_mem_base + offset);117117+118118+ new_val = (new_val & ~mask) | (val & mask);119119+ writel(new_val, pmc->gcr_mem_base + offset);120120+121121+ new_val = readl(pmc->gcr_mem_base + offset);122122+ spin_unlock(&pmc->gcr_lock);123123+124124+ /* Check whether the bit update is successful */125125+ return (new_val & mask) != (val & mask) ? -EIO : 0;126126+}127127+EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);128128+129129+/**130130+ * intel_pmc_s0ix_counter_read() - Read S0ix residency131131+ * @pmc: PMC device pointer132132+ * @data: Out param that contains current S0ix residency count.133133+ *134134+ * Writes to @data how many usecs the system has been in low-power S0ix135135+ * state.136136+ *137137+ * Return: An error code or 0 on success.138138+ */139139+int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data)140140+{141141+ u64 deep, shlw;142142+143143+ spin_lock(&pmc->gcr_lock);144144+ deep = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_DEEP_S0IX_REG);145145+ shlw = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_SHLW_S0IX_REG);146146+ spin_unlock(&pmc->gcr_lock);147147+148148+ *data = S0IX_RESIDENCY_IN_USECS(deep, shlw);149149+ return 0;150150+}151151+EXPORT_SYMBOL_GPL(intel_pmc_s0ix_counter_read);152152+153153+/**154154+ * simplecmd_store() - Send a simple IPC command155155+ * @dev: Device under the attribute is156156+ * @attr: Attribute in question157157+ * @buf: Buffer holding data to be stored to the attribute158158+ * @count: Number of bytes in @buf159159+ *160160+ * Expects a string with two integers separated with space. These two161161+ * values hold command and subcommand that is send to PMC.162162+ *163163+ * Return: Number number of bytes written (@count) or negative errno in164164+ * case of error.165165+ */166166+static ssize_t simplecmd_store(struct device *dev, struct device_attribute *attr,167167+ const char *buf, size_t count)168168+{169169+ struct intel_pmc_dev *pmc = dev_get_drvdata(dev);170170+ struct intel_scu_ipc_dev *scu = pmc->scu;171171+ int subcmd;172172+ int cmd;173173+ int ret;174174+175175+ ret = sscanf(buf, "%d %d", &cmd, &subcmd);176176+ if (ret != 2) {177177+ dev_err(dev, "Invalid values, expected: cmd subcmd\n");178178+ return -EINVAL;179179+ }180180+181181+ ret = intel_scu_ipc_dev_simple_command(scu, cmd, subcmd);182182+ if (ret)183183+ return ret;184184+185185+ return count;186186+}187187+static DEVICE_ATTR_WO(simplecmd);188188+189189+/**190190+ * northpeak_store() - Enable or disable Northpeak191191+ * @dev: Device under the attribute is192192+ * @attr: Attribute in question193193+ * @buf: Buffer holding data to be stored to the attribute194194+ * @count: Number of bytes in @buf195195+ *196196+ * Expects an unsigned integer. Non-zero enables Northpeak and zero197197+ * disables it.198198+ *199199+ * Return: Number number of bytes written (@count) or negative errno in200200+ * case of error.201201+ */202202+static ssize_t northpeak_store(struct device *dev, struct device_attribute *attr,203203+ const char *buf, size_t count)204204+{205205+ struct intel_pmc_dev *pmc = dev_get_drvdata(dev);206206+ struct intel_scu_ipc_dev *scu = pmc->scu;207207+ unsigned long val;208208+ int subcmd;209209+ int ret;210210+211211+ ret = kstrtoul(buf, 0, &val);212212+ if (ret)213213+ return ret;214214+215215+ /* Northpeak is enabled if subcmd == 1 and disabled if it is 0 */216216+ if (val)217217+ subcmd = 1;218218+ else219219+ subcmd = 0;220220+221221+ ret = intel_scu_ipc_dev_simple_command(scu, PMC_NORTHPEAK_CTRL, subcmd);222222+ if (ret)223223+ return ret;224224+225225+ return count;226226+}227227+static DEVICE_ATTR_WO(northpeak);228228+229229+static struct attribute *intel_pmc_attrs[] = {230230+ &dev_attr_northpeak.attr,231231+ &dev_attr_simplecmd.attr,232232+ NULL233233+};234234+235235+static const struct attribute_group intel_pmc_group = {236236+ .attrs = intel_pmc_attrs,237237+};238238+239239+static const struct attribute_group *intel_pmc_groups[] = {240240+ &intel_pmc_group,241241+ NULL242242+};243243+244244+static struct resource punit_res[6];245245+246246+static struct mfd_cell punit = {247247+ .name = "intel_punit_ipc",248248+ .resources = punit_res,249249+};250250+251251+static struct itco_wdt_platform_data tco_pdata = {252252+ .name = "Apollo Lake SoC",253253+ .version = 5,254254+ .no_reboot_use_pmc = true,255255+};256256+257257+static struct resource tco_res[2];258258+259259+static const struct mfd_cell tco = {260260+ .name = "iTCO_wdt",261261+ .ignore_resource_conflicts = true,262262+ .resources = tco_res,263263+ .num_resources = ARRAY_SIZE(tco_res),264264+ .platform_data = &tco_pdata,265265+ .pdata_size = sizeof(tco_pdata),266266+};267267+268268+static const struct resource telem_res[] = {269269+ DEFINE_RES_MEM(TELEM_PUNIT_SSRAM_OFFSET, TELEM_SSRAM_SIZE),270270+ DEFINE_RES_MEM(TELEM_PMC_SSRAM_OFFSET, TELEM_SSRAM_SIZE),271271+};272272+273273+static const struct mfd_cell telem = {274274+ .name = "intel_telemetry",275275+ .resources = telem_res,276276+ .num_resources = ARRAY_SIZE(telem_res),277277+};278278+279279+static int intel_pmc_get_tco_resources(struct platform_device *pdev)280280+{281281+ struct resource *res;282282+283283+ if (acpi_has_watchdog())284284+ return 0;285285+286286+ res = platform_get_resource(pdev, IORESOURCE_IO,287287+ PLAT_RESOURCE_ACPI_IO_INDEX);288288+ if (!res) {289289+ dev_err(&pdev->dev, "Failed to get IO resource\n");290290+ return -EINVAL;291291+ }292292+293293+ tco_res[0].flags = IORESOURCE_IO;294294+ tco_res[0].start = res->start + TCO_BASE_OFFSET;295295+ tco_res[0].end = tco_res[0].start + TCO_REGS_SIZE - 1;296296+ tco_res[1].flags = IORESOURCE_IO;297297+ tco_res[1].start = res->start + SMI_EN_OFFSET;298298+ tco_res[1].end = tco_res[1].start + SMI_EN_SIZE - 1;299299+300300+ return 0;301301+}302302+303303+static int intel_pmc_get_resources(struct platform_device *pdev,304304+ struct intel_pmc_dev *pmc,305305+ struct intel_scu_ipc_data *scu_data)306306+{307307+ struct resource gcr_res;308308+ size_t npunit_res = 0;309309+ struct resource *res;310310+ int ret;311311+312312+ scu_data->irq = platform_get_irq_optional(pdev, 0);313313+314314+ res = platform_get_resource(pdev, IORESOURCE_MEM,315315+ PLAT_RESOURCE_IPC_INDEX);316316+ if (!res) {317317+ dev_err(&pdev->dev, "Failed to get IPC resource\n");318318+ return -EINVAL;319319+ }320320+321321+ /* IPC registers */322322+ scu_data->mem.flags = res->flags;323323+ scu_data->mem.start = res->start;324324+ scu_data->mem.end = res->start + PLAT_RESOURCE_IPC_SIZE - 1;325325+326326+ /* GCR registers */327327+ gcr_res.flags = res->flags;328328+ gcr_res.start = res->start + PLAT_RESOURCE_GCR_OFFSET;329329+ gcr_res.end = gcr_res.start + PLAT_RESOURCE_GCR_SIZE - 1;330330+331331+ pmc->gcr_mem_base = devm_ioremap_resource(&pdev->dev, &gcr_res);332332+ if (IS_ERR(pmc->gcr_mem_base))333333+ return PTR_ERR(pmc->gcr_mem_base);334334+335335+ /* Only register iTCO watchdog if there is no WDAT ACPI table */336336+ ret = intel_pmc_get_tco_resources(pdev);337337+ if (ret)338338+ return ret;339339+340340+ /* BIOS data register */341341+ res = platform_get_resource(pdev, IORESOURCE_MEM,342342+ PLAT_RESOURCE_BIOS_DATA_INDEX);343343+ if (!res) {344344+ dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS data\n");345345+ return -EINVAL;346346+ }347347+ punit_res[npunit_res++] = *res;348348+349349+ /* BIOS interface register */350350+ res = platform_get_resource(pdev, IORESOURCE_MEM,351351+ PLAT_RESOURCE_BIOS_IFACE_INDEX);352352+ if (!res) {353353+ dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS interface\n");354354+ return -EINVAL;355355+ }356356+ punit_res[npunit_res++] = *res;357357+358358+ /* ISP data register, optional */359359+ res = platform_get_resource(pdev, IORESOURCE_MEM,360360+ PLAT_RESOURCE_ISP_DATA_INDEX);361361+ if (res)362362+ punit_res[npunit_res++] = *res;363363+364364+ /* ISP interface register, optional */365365+ res = platform_get_resource(pdev, IORESOURCE_MEM,366366+ PLAT_RESOURCE_ISP_IFACE_INDEX);367367+ if (res)368368+ punit_res[npunit_res++] = *res;369369+370370+ /* GTD data register, optional */371371+ res = platform_get_resource(pdev, IORESOURCE_MEM,372372+ PLAT_RESOURCE_GTD_DATA_INDEX);373373+ if (res)374374+ punit_res[npunit_res++] = *res;375375+376376+ /* GTD interface register, optional */377377+ res = platform_get_resource(pdev, IORESOURCE_MEM,378378+ PLAT_RESOURCE_GTD_IFACE_INDEX);379379+ if (res)380380+ punit_res[npunit_res++] = *res;381381+382382+ punit.num_resources = npunit_res;383383+384384+ /* Telemetry SSRAM is optional */385385+ res = platform_get_resource(pdev, IORESOURCE_MEM,386386+ PLAT_RESOURCE_TELEM_SSRAM_INDEX);387387+ if (res)388388+ pmc->telem_base = res;389389+390390+ return 0;391391+}392392+393393+static int intel_pmc_create_devices(struct intel_pmc_dev *pmc)394394+{395395+ int ret;396396+397397+ if (!acpi_has_watchdog()) {398398+ ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &tco,399399+ 1, NULL, 0, NULL);400400+ if (ret)401401+ return ret;402402+ }403403+404404+ ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &punit, 1,405405+ NULL, 0, NULL);406406+ if (ret)407407+ return ret;408408+409409+ if (pmc->telem_base) {410410+ ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO,411411+ &telem, 1, pmc->telem_base, 0, NULL);412412+ }413413+414414+ return ret;415415+}416416+417417+static const struct acpi_device_id intel_pmc_acpi_ids[] = {418418+ { "INT34D2" },419419+ { }420420+};421421+MODULE_DEVICE_TABLE(acpi, intel_pmc_acpi_ids);422422+423423+static int intel_pmc_probe(struct platform_device *pdev)424424+{425425+ struct intel_scu_ipc_data scu_data = {};426426+ struct intel_pmc_dev *pmc;427427+ int ret;428428+429429+ pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL);430430+ if (!pmc)431431+ return -ENOMEM;432432+433433+ pmc->dev = &pdev->dev;434434+ spin_lock_init(&pmc->gcr_lock);435435+436436+ ret = intel_pmc_get_resources(pdev, pmc, &scu_data);437437+ if (ret) {438438+ dev_err(&pdev->dev, "Failed to request resources\n");439439+ return ret;440440+ }441441+442442+ pmc->scu = devm_intel_scu_ipc_register(&pdev->dev, &scu_data);443443+ if (IS_ERR(pmc->scu))444444+ return PTR_ERR(pmc->scu);445445+446446+ platform_set_drvdata(pdev, pmc);447447+448448+ ret = intel_pmc_create_devices(pmc);449449+ if (ret)450450+ dev_err(&pdev->dev, "Failed to create PMC devices\n");451451+452452+ return ret;453453+}454454+455455+static struct platform_driver intel_pmc_driver = {456456+ .probe = intel_pmc_probe,457457+ .driver = {458458+ .name = "intel_pmc_bxt",459459+ .acpi_match_table = intel_pmc_acpi_ids,460460+ .dev_groups = intel_pmc_groups,461461+ },462462+};463463+module_platform_driver(intel_pmc_driver);464464+465465+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");466466+MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");467467+MODULE_DESCRIPTION("Intel Broxton PMC driver");468468+MODULE_LICENSE("GPL v2");
+17-17
drivers/mfd/intel_soc_pmic_bxtwc.c
···1515#include <linux/mfd/intel_soc_pmic_bxtwc.h>1616#include <linux/module.h>17171818-#include <asm/intel_pmc_ipc.h>1818+#include <asm/intel_scu_ipc.h>19192020/* PMIC device registers */2121#define REG_ADDR_MASK 0xFF00···57575858/* Whiskey Cove PMIC share same ACPI ID between different platforms */5959#define BROXTON_PMIC_WC_HRV 46060+6161+#define PMC_PMIC_ACCESS 0xFF6262+#define PMC_PMIC_READ 0x06363+#define PMC_PMIC_WRITE 0x160646165enum bxtwc_irqs {6266 BXTWC_PWRBTN_LVL1_IRQ = 0,···292288293289 ipc_in[0] = reg;294290 ipc_in[1] = i2c_addr;295295- ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,296296- PMC_IPC_PMIC_ACCESS_READ,297297- ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);298298- if (ret) {299299- dev_err(pmic->dev, "Failed to read from PMIC\n");291291+ ret = intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,292292+ PMC_PMIC_READ, ipc_in, sizeof(ipc_in),293293+ ipc_out, sizeof(ipc_out));294294+ if (ret)300295 return ret;301301- }296296+302297 *val = ipc_out[0];303298304299 return 0;···306303static int regmap_ipc_byte_reg_write(void *context, unsigned int reg,307304 unsigned int val)308305{309309- int ret;310306 int i2c_addr;311307 u8 ipc_in[3];312308 struct intel_soc_pmic *pmic = context;···323321 ipc_in[0] = reg;324322 ipc_in[1] = i2c_addr;325323 ipc_in[2] = val;326326- ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,327327- PMC_IPC_PMIC_ACCESS_WRITE,328328- ipc_in, sizeof(ipc_in), NULL, 0);329329- if (ret) {330330- dev_err(pmic->dev, "Failed to write to PMIC\n");331331- return ret;332332- }333333-334334- return 0;324324+ return intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS,325325+ PMC_PMIC_WRITE, ipc_in, sizeof(ipc_in),326326+ NULL, 0);335327}336328337329/* sysfs interfaces to r/w PMIC registers, required by initial script */···452456453457 dev_set_drvdata(&pdev->dev, pmic);454458 pmic->dev = &pdev->dev;459459+460460+ pmic->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);461461+ if (!pmic->scu)462462+ return -EPROBE_DEFER;455463456464 pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,457465 &bxtwc_regmap_config);
+8-2
drivers/mfd/intel_soc_pmic_mrfld.c
···7474static int bcove_ipc_byte_reg_read(void *context, unsigned int reg,7575 unsigned int *val)7676{7777+ struct intel_soc_pmic *pmic = context;7778 u8 ipc_out;7879 int ret;79808080- ret = intel_scu_ipc_ioread8(reg, &ipc_out);8181+ ret = intel_scu_ipc_dev_ioread8(pmic->scu, reg, &ipc_out);8182 if (ret)8283 return ret;8384···8988static int bcove_ipc_byte_reg_write(void *context, unsigned int reg,9089 unsigned int val)9190{9191+ struct intel_soc_pmic *pmic = context;9292 u8 ipc_in = val;9393 int ret;94949595- ret = intel_scu_ipc_iowrite8(reg, ipc_in);9595+ ret = intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in);9696 if (ret)9797 return ret;9898···117115118116 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);119117 if (!pmic)118118+ return -ENOMEM;119119+120120+ pmic->scu = devm_intel_scu_ipc_dev_get(dev);121121+ if (!pmic->scu)120122 return -ENOMEM;121123122124 platform_set_drvdata(pdev, pmic);
+27-19
drivers/platform/x86/Kconfig
···12691269config INTEL_BXTWC_PMIC_TMU12701270 tristate "Intel BXT Whiskey Cove TMU Driver"12711271 depends on REGMAP12721272- depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC12721272+ depends on MFD_INTEL_PMC_BXT12731273+ depends on INTEL_SOC_PMIC_BXTWC12731274 ---help---12741275 Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature.12751276 This driver enables the alarm wakeup functionality in the TMU unit···1296129512971296config INTEL_MID_POWER_BUTTON12981297 tristate "power button driver for Intel MID platforms"12991299- depends on INTEL_SCU_IPC && INPUT12981298+ depends on INTEL_SCU && INPUT13001299 help13011300 This driver handles the power button on the Intel MID platforms.13021301···13281327 - LTR Ignore13291328 - MPHY/PLL gating status (Sunrisepoint PCH only)1330132913311331-config INTEL_PMC_IPC13321332- tristate "Intel PMC IPC Driver"13331333- depends on ACPI && PCI13341334- ---help---13351335- This driver provides support for PMC control on some Intel platforms.13361336- The PMC is an ARC processor which defines IPC commands for communication13371337- with other entities in the CPU.13381338-13391330config INTEL_PUNIT_IPC13401331 tristate "Intel P-Unit IPC Driver"13411332 ---help---···13351342 which is used to bridge the communications between kernel and P-Unit.1336134313371344config INTEL_SCU_IPC13381338- bool "Intel SCU IPC Support"13391339- depends on X86_INTEL_MID13401340- default y13411341- ---help---13421342- IPC is used to bridge the communications between kernel and SCU on13431343- some embedded Intel x86 platforms. This is not needed for PC-type13441344- machines.13451345+ bool13461346+13471347+config INTEL_SCU13481348+ bool13491349+ select INTEL_SCU_IPC13501350+13511351+config INTEL_SCU_PCI13521352+ bool "Intel SCU PCI driver"13531353+ depends on PCI13541354+ select INTEL_SCU13551355+ help13561356+ This driver is used to bridge the communications between kernel13571357+ and SCU on some embedded Intel x86 platforms. It also creates13581358+ devices that are connected to the SoC through the SCU.13591359+ Platforms supported:13601360+ Medfield13611361+ Clovertrail13621362+ Merrifield13631363+ Broxton13641364+ Apollo Lake1345136513461366config INTEL_SCU_IPC_UTIL13471367 tristate "Intel SCU IPC utility driver"13481348- depends on INTEL_SCU_IPC13681368+ depends on INTEL_SCU13491369 ---help---13501370 The IPC Util driver provides an interface with the SCU enabling13511371 low level access for debug work and updating the firmware. Say···1366136013671361config INTEL_TELEMETRY13681362 tristate "Intel SoC Telemetry Driver"13691369- depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_6413631363+ depends on X86_6413641364+ depends on MFD_INTEL_PMC_BXT13651365+ depends on INTEL_PUNIT_IPC13701366 ---help---13711367 This driver provides interfaces to configure and use13721368 telemetry for INTEL SoC from APL onwards. It is also
···353353EXPORT_SYMBOL_GPL(telemetry_clear_pltdata);354354355355/**356356- * telemetry_pltconfig_valid() - Checkif platform config is valid356356+ * telemetry_get_pltdata() - Return telemetry platform config357357 *358358- * Usage by other than telemetry module is invalid359359- *360360- * Return: 0 success, < 0 for failure358358+ * May be used by other telemetry modules to get platform specific359359+ * configuration.361360 */362362-int telemetry_pltconfig_valid(void)361361+struct telemetry_plt_config *telemetry_get_pltdata(void)363362{364364- if (telm_core_conf.plt_config)365365- return 0;366366-367367- else368368- return -EINVAL;363363+ return telm_core_conf.plt_config;369364}370370-EXPORT_SYMBOL_GPL(telemetry_pltconfig_valid);365365+EXPORT_SYMBOL_GPL(telemetry_get_pltdata);371366372367static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit,373368 const char **name, int len)
+9-6
drivers/platform/x86/intel_telemetry_debugfs.c
···1515 */1616#include <linux/debugfs.h>1717#include <linux/device.h>1818+#include <linux/mfd/intel_pmc_bxt.h>1819#include <linux/module.h>1920#include <linux/pci.h>2021#include <linux/seq_file.h>···23222423#include <asm/cpu_device_id.h>2524#include <asm/intel-family.h>2626-#include <asm/intel_pmc_ipc.h>2725#include <asm/intel_telemetry.h>28262927#define DRIVER_NAME "telemetry_soc_debugfs"···647647648648static int telem_s0ix_res_get(void *data, u64 *val)649649{650650+ struct telemetry_plt_config *plt_config = telemetry_get_pltdata();650651 u64 s0ix_total_res;651652 int ret;652653653653- ret = intel_pmc_s0ix_counter_read(&s0ix_total_res);654654+ ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &s0ix_total_res);654655 if (ret) {655656 pr_err("Failed to read S0ix residency");656657 return ret;···838837 */839838 if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp &&840839 suspend_deep_ctr_exit == suspend_deep_ctr_temp) {841841- ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_SHLW_S0IX_REG,840840+ struct telemetry_plt_config *plt_config = telemetry_get_pltdata();841841+ struct intel_pmc_dev *pmc = plt_config->pmc;842842+843843+ ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_SHLW_S0IX_REG,842844 &suspend_shlw_res_exit);843845 if (ret < 0)844846 goto out;845847846846- ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_DEEP_S0IX_REG,848848+ ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG,847849 &suspend_deep_res_exit);848850 if (ret < 0)849851 goto out;···914910915911 debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;916912917917- err = telemetry_pltconfig_valid();918918- if (err < 0) {913913+ if (!telemetry_get_pltdata()) {919914 pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");920915 return -ENODEV;921916 }
+48-49
drivers/platform/x86/intel_telemetry_pltdrv.c
···15151616#include <asm/cpu_device_id.h>1717#include <asm/intel-family.h>1818-#include <asm/intel_pmc_ipc.h>1918#include <asm/intel_punit_ipc.h>2019#include <asm/intel_telemetry.h>2120···3435#define TELEM_SSRAM_STARTTIME_OFFSET 83536#define TELEM_SSRAM_EVTLOG_OFFSET 1636373838+#define IOSS_TELEM 0xeb3739#define IOSS_TELEM_EVENT_READ 0x03840#define IOSS_TELEM_EVENT_WRITE 0x13941#define IOSS_TELEM_INFO_READ 0x2···4242#define IOSS_TELEM_TRACE_CTL_WRITE 0x64343#define IOSS_TELEM_EVENT_CTL_READ 0x74444#define IOSS_TELEM_EVENT_CTL_WRITE 0x84545-#define IOSS_TELEM_EVT_CTRL_WRITE_SIZE 0x44646-#define IOSS_TELEM_READ_WORD 0x14747-#define IOSS_TELEM_WRITE_FOURBYTES 0x44845#define IOSS_TELEM_EVT_WRITE_SIZE 0x349465047#define TELEM_INFO_SRAMEVTS_MASK 0xFF00···247250static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index)248251{249252 u32 write_buf;250250- int ret;251253252254 write_buf = evt_id | TELEM_EVENT_ENABLE;253255 write_buf <<= BITS_PER_BYTE;254256 write_buf |= index;255257256256- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,257257- IOSS_TELEM_EVENT_WRITE, (u8 *)&write_buf,258258- IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0);259259-260260- return ret;258258+ return intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,259259+ IOSS_TELEM_EVENT_WRITE, &write_buf,260260+ IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0);261261}262262263263static inline int telemetry_plt_config_pss_event(u32 evt_id, int index)···272278static int telemetry_setup_iossevtconfig(struct telemetry_evtconfig evtconfig,273279 enum telemetry_action action)274280{281281+ struct intel_scu_ipc_dev *scu = telm_conf->scu;275282 u8 num_ioss_evts, ioss_period;276283 int ret, index, idx;277284 u32 *ioss_evtmap;···283288 ioss_evtmap = evtconfig.evtmap;284289285290 /* Get telemetry EVENT CTL */286286- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,291291+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,287292 IOSS_TELEM_EVENT_CTL_READ, NULL, 0,288288- &telem_ctrl, IOSS_TELEM_READ_WORD);293293+ &telem_ctrl, sizeof(telem_ctrl));289294 if (ret) {290295 pr_err("IOSS TELEM_CTRL Read Failed\n");291296 return ret;···294299 /* Disable Telemetry */295300 TELEM_DISABLE(telem_ctrl);296301297297- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,298298- IOSS_TELEM_EVENT_CTL_WRITE,299299- (u8 *)&telem_ctrl,300300- IOSS_TELEM_EVT_CTRL_WRITE_SIZE,301301- NULL, 0);302302+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,303303+ IOSS_TELEM_EVENT_CTL_WRITE, &telem_ctrl,304304+ sizeof(telem_ctrl), NULL, 0);302305 if (ret) {303306 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");304307 return ret;···308315 /* Clear All Events */309316 TELEM_CLEAR_EVENTS(telem_ctrl);310317311311- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,318318+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,312319 IOSS_TELEM_EVENT_CTL_WRITE,313313- (u8 *)&telem_ctrl,314314- IOSS_TELEM_EVT_CTRL_WRITE_SIZE,320320+ &telem_ctrl, sizeof(telem_ctrl),315321 NULL, 0);316322 if (ret) {317323 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");···336344 /* Clear All Events */337345 TELEM_CLEAR_EVENTS(telem_ctrl);338346339339- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,347347+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,340348 IOSS_TELEM_EVENT_CTL_WRITE,341341- (u8 *)&telem_ctrl,342342- IOSS_TELEM_EVT_CTRL_WRITE_SIZE,349349+ &telem_ctrl, sizeof(telem_ctrl),343350 NULL, 0);344351 if (ret) {345352 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");···387396 TELEM_ENABLE_PERIODIC(telem_ctrl);388397 telem_ctrl |= ioss_period;389398390390- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,399399+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,391400 IOSS_TELEM_EVENT_CTL_WRITE,392392- (u8 *)&telem_ctrl,393393- IOSS_TELEM_EVT_CTRL_WRITE_SIZE, NULL, 0);401401+ &telem_ctrl, sizeof(telem_ctrl), NULL, 0);394402 if (ret) {395403 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");396404 return ret;···576586 u32 read_buf, events, event_regs;577587 int ret;578588579579- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_INFO_READ,580580- NULL, 0, &read_buf, IOSS_TELEM_READ_WORD);589589+ ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,590590+ IOSS_TELEM_INFO_READ, NULL, 0,591591+ &read_buf, sizeof(read_buf));581592 if (ret) {582593 dev_err(&pdev->dev, "IOSS TELEM_INFO Read Failed\n");583594 return ret;···672681673682 mutex_lock(&(telm_conf->telem_lock));674683 if (ioss_period) {684684+ struct intel_scu_ipc_dev *scu = telm_conf->scu;685685+675686 if (TELEM_SAMPLE_PERIOD_INVALID(ioss_period)) {676687 pr_err("IOSS Sampling Period Out of Range\n");677688 ret = -EINVAL;···681688 }682689683690 /* Get telemetry EVENT CTL */684684- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,691691+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,685692 IOSS_TELEM_EVENT_CTL_READ, NULL, 0,686686- &telem_ctrl, IOSS_TELEM_READ_WORD);693693+ &telem_ctrl, sizeof(telem_ctrl));687694 if (ret) {688695 pr_err("IOSS TELEM_CTRL Read Failed\n");689696 goto out;···692699 /* Disable Telemetry */693700 TELEM_DISABLE(telem_ctrl);694701695695- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,696696- IOSS_TELEM_EVENT_CTL_WRITE,697697- (u8 *)&telem_ctrl,698698- IOSS_TELEM_EVT_CTRL_WRITE_SIZE,699699- NULL, 0);702702+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,703703+ IOSS_TELEM_EVENT_CTL_WRITE,704704+ &telem_ctrl, sizeof(telem_ctrl),705705+ NULL, 0);700706 if (ret) {701707 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");702708 goto out;···707715 TELEM_ENABLE_PERIODIC(telem_ctrl);708716 telem_ctrl |= ioss_period;709717710710- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,711711- IOSS_TELEM_EVENT_CTL_WRITE,712712- (u8 *)&telem_ctrl,713713- IOSS_TELEM_EVT_CTRL_WRITE_SIZE,714714- NULL, 0);718718+ ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM,719719+ IOSS_TELEM_EVENT_CTL_WRITE,720720+ &telem_ctrl, sizeof(telem_ctrl),721721+ NULL, 0);715722 if (ret) {716723 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");717724 goto out;···10051014 break;1006101510071016 case TELEM_IOSS:10081008- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,10091009- IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,10101010- IOSS_TELEM_READ_WORD);10171017+ ret = intel_scu_ipc_dev_command(telm_conf->scu,10181018+ IOSS_TELEM, IOSS_TELEM_TRACE_CTL_READ,10191019+ NULL, 0, &temp, sizeof(temp));10111020 if (ret) {10121021 pr_err("IOSS TRACE_CTL Read Failed\n");10131022 goto out;···10591068 break;1060106910611070 case TELEM_IOSS:10621062- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,10631063- IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,10641064- IOSS_TELEM_READ_WORD);10711071+ ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,10721072+ IOSS_TELEM_TRACE_CTL_READ,10731073+ NULL, 0, &temp, sizeof(temp));10651074 if (ret) {10661075 pr_err("IOSS TRACE_CTL Read Failed\n");10671076 goto out;···10701079 TELEM_CLEAR_VERBOSITY_BITS(temp);10711080 TELEM_SET_VERBOSITY_BITS(temp, verbosity);1072108110731073- ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,10741074- IOSS_TELEM_TRACE_CTL_WRITE, (u8 *)&temp,10751075- IOSS_TELEM_WRITE_FOURBYTES, NULL, 0);10821082+ ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM,10831083+ IOSS_TELEM_TRACE_CTL_WRITE,10841084+ &temp, sizeof(temp), NULL, 0);10761085 if (ret) {10771086 pr_err("IOSS TRACE_CTL Verbosity Set Failed\n");10781087 goto out;···1115112411161125 telm_conf = (struct telemetry_plt_config *)id->driver_data;1117112611271127+ telm_conf->pmc = dev_get_drvdata(pdev->dev.parent);11281128+11181129 mem = devm_platform_ioremap_resource(pdev, 0);11191130 if (IS_ERR(mem))11201131 return PTR_ERR(mem);···11281135 return PTR_ERR(mem);1129113611301137 telm_conf->ioss_config.regmap = mem;11381138+11391139+ telm_conf->scu = devm_intel_scu_ipc_dev_get(&pdev->dev);11401140+ if (!telm_conf->scu) {11411141+ ret = -EPROBE_DEFER;11421142+ goto out;11431143+ }1131114411321145 mutex_init(&telm_conf->telem_lock);11331146 mutex_init(&telm_conf->telem_trace_lock);
+1-1
drivers/usb/typec/mux/Kconfig
···11111212config TYPEC_MUX_INTEL_PMC1313 tristate "Intel PMC mux control"1414- depends on INTEL_PMC_IPC1414+ depends on INTEL_SCU_IPC1515 select USB_ROLE_SWITCH1616 help1717 Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can
+8-4
drivers/usb/typec/mux/intel_pmc_mux.c
···1515#include <linux/usb/typec_dp.h>1616#include <linux/usb/typec_tbt.h>17171818-#include <asm/intel_pmc_ipc.h>1818+#include <asm/intel_scu_ipc.h>19192020#define PMC_USBC_CMD 0xa72121···9696struct pmc_usb {9797 u8 num_ports;9898 struct device *dev;9999+ struct intel_scu_ipc_dev *ipc;99100 struct pmc_usb_port *port;100101};101102···108107 * Error bit will always be 0 with the USBC command.109108 * Status can be checked from the response message.110109 */111111- intel_pmc_ipc_command(PMC_USBC_CMD, 0, msg, len,112112- (void *)response, 1);113113-110110+ intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg, len,111111+ response, sizeof(response));114112 if (response[2]) {115113 if (response[2] & BIT(1))116114 return -EIO;···369369 sizeof(struct pmc_usb_port), GFP_KERNEL);370370 if (!pmc->port)371371 return -ENOMEM;372372+373373+ pmc->ipc = devm_intel_scu_ipc_dev_get(&pdev->dev);374374+ if (!pmc->ipc)375375+ return -ENODEV;372376373377 pmc->dev = &pdev->dev;374378
+1-1
drivers/usb/typec/tcpm/Kconfig
···4141config TYPEC_WCOVE4242 tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"4343 depends on ACPI4444+ depends on MFD_INTEL_PMC_BXT4445 depends on INTEL_SOC_PMIC4545- depends on INTEL_PMC_IPC4646 depends on BXT_WC_PMIC_OPREGION4747 help4848 This driver adds support for USB Type-C on Intel Broxton platforms
+20-7
drivers/watchdog/iTCO_wdt.c
···6464#include <linux/uaccess.h> /* For copy_to_user/put_user/... */6565#include <linux/io.h> /* For inb/outb/... */6666#include <linux/platform_data/itco_wdt.h>6767+#include <linux/mfd/intel_pmc_bxt.h>67686869#include "iTCO_vendor.h"6970···234233 return val != newval ? -EIO : 0;235234}236235237237-static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p,238238- struct itco_wdt_platform_data *pdata)236236+static int update_no_reboot_bit_pmc(void *priv, bool set)239237{240240- if (pdata->update_no_reboot_bit) {241241- p->update_no_reboot_bit = pdata->update_no_reboot_bit;242242- p->no_reboot_priv = pdata->no_reboot_priv;238238+ struct intel_pmc_dev *pmc = priv;239239+ u32 bits = PMC_CFG_NO_REBOOT_EN;240240+ u32 value = set ? bits : 0;241241+242242+ return intel_pmc_gcr_update(pmc, PMC_GCR_PMC_CFG_REG, bits, value);243243+}244244+245245+static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p,246246+ struct platform_device *pdev,247247+ struct itco_wdt_platform_data *pdata)248248+{249249+ if (pdata->no_reboot_use_pmc) {250250+ struct intel_pmc_dev *pmc = dev_get_drvdata(pdev->dev.parent);251251+252252+ p->update_no_reboot_bit = update_no_reboot_bit_pmc;253253+ p->no_reboot_priv = pmc;243254 return;244255 }245256···491478 return -ENODEV;492479 }493480494494- iTCO_wdt_no_reboot_bit_setup(p, pdata);481481+ iTCO_wdt_no_reboot_bit_setup(p, pdev, pdata);495482496483 /*497484 * Get the Memory-Mapped GCS or PMC register, we need it for the498485 * NO_REBOOT flag (TCO v2 and v3).499486 */500487 if (p->iTCO_version >= 2 && p->iTCO_version < 6 &&501501- !pdata->update_no_reboot_bit) {488488+ !pdata->no_reboot_use_pmc) {502489 p->gcs_pmc_res = platform_get_resource(pdev,503490 IORESOURCE_MEM,504491 ICH_RES_MEM_GCS_PMC);
+37-16
drivers/watchdog/intel-mid_wdt.c
···3333 SCU_WATCHDOG_KEEPALIVE,3434};35353636-static inline int wdt_command(int sub, u32 *in, int inlen)3636+struct mid_wdt {3737+ struct watchdog_device wd;3838+ struct device *dev;3939+ struct intel_scu_ipc_dev *scu;4040+};4141+4242+static inline int4343+wdt_command(struct mid_wdt *mid, int sub, const void *in, size_t inlen, size_t size)3744{3838- return intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0);4545+ struct intel_scu_ipc_dev *scu = mid->scu;4646+4747+ return intel_scu_ipc_dev_command_with_size(scu, IPC_WATCHDOG, sub, in,4848+ inlen, size, NULL, 0);3949}40504151static int wdt_start(struct watchdog_device *wd)4252{4343- struct device *dev = watchdog_get_drvdata(wd);5353+ struct mid_wdt *mid = watchdog_get_drvdata(wd);4454 int ret, in_size;4555 int timeout = wd->timeout;4656 struct ipc_wd_start {···5949 } ipc_wd_start = { timeout - MID_WDT_PRETIMEOUT, timeout };60506151 /*6262- * SCU expects the input size for watchdog IPC to6363- * be based on 4 bytes5252+ * SCU expects the input size for watchdog IPC to be 2 which is the5353+ * size of the structure in dwords. SCU IPC normally takes bytes5454+ * but this is a special case where we specify size to be different5555+ * than inlen.6456 */6557 in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4);66586767- ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size);5959+ ret = wdt_command(mid, SCU_WATCHDOG_START, &ipc_wd_start,6060+ sizeof(ipc_wd_start), in_size);6861 if (ret)6969- dev_crit(dev, "error starting watchdog: %d\n", ret);6262+ dev_crit(mid->dev, "error starting watchdog: %d\n", ret);70637164 return ret;7265}73667467static int wdt_ping(struct watchdog_device *wd)7568{7676- struct device *dev = watchdog_get_drvdata(wd);6969+ struct mid_wdt *mid = watchdog_get_drvdata(wd);7770 int ret;78717979- ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0);7272+ ret = wdt_command(mid, SCU_WATCHDOG_KEEPALIVE, NULL, 0, 0);8073 if (ret)8181- dev_crit(dev, "Error executing keepalive: %d\n", ret);7474+ dev_crit(mid->dev, "Error executing keepalive: %d\n", ret);82758376 return ret;8477}85788679static int wdt_stop(struct watchdog_device *wd)8780{8888- struct device *dev = watchdog_get_drvdata(wd);8181+ struct mid_wdt *mid = watchdog_get_drvdata(wd);8982 int ret;90839191- ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0);8484+ ret = wdt_command(mid, SCU_WATCHDOG_STOP, NULL, 0, 0);9285 if (ret)9393- dev_crit(dev, "Error stopping watchdog: %d\n", ret);8686+ dev_crit(mid->dev, "Error stopping watchdog: %d\n", ret);94879588 return ret;9689}···123110 struct device *dev = &pdev->dev;124111 struct watchdog_device *wdt_dev;125112 struct intel_mid_wdt_pdata *pdata = dev->platform_data;113113+ struct mid_wdt *mid;126114 int ret;127115128116 if (!pdata) {···137123 return ret;138124 }139125140140- wdt_dev = devm_kzalloc(dev, sizeof(*wdt_dev), GFP_KERNEL);141141- if (!wdt_dev)126126+ mid = devm_kzalloc(dev, sizeof(*mid), GFP_KERNEL);127127+ if (!mid)142128 return -ENOMEM;129129+130130+ mid->dev = dev;131131+ wdt_dev = &mid->wd;143132144133 wdt_dev->info = &mid_wdt_info;145134 wdt_dev->ops = &mid_wdt_ops;···152135 wdt_dev->parent = dev;153136154137 watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);155155- watchdog_set_drvdata(wdt_dev, dev);138138+ watchdog_set_drvdata(wdt_dev, mid);156139157140 ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,158141 IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",···161144 dev_err(dev, "error requesting warning irq %d\n", pdata->irq);162145 return ret;163146 }147147+148148+ mid->scu = devm_intel_scu_ipc_dev_get(dev);149149+ if (!mid->scu)150150+ return -EPROBE_DEFER;164151165152 /*166153 * The firmware followed by U-Boot leaves the watchdog running
+53
include/linux/mfd/intel_pmc_bxt.h
···11+/* SPDX-License-Identifier: GPL-2.0 */22+#ifndef MFD_INTEL_PMC_BXT_H33+#define MFD_INTEL_PMC_BXT_H44+55+/* GCR reg offsets from GCR base */66+#define PMC_GCR_PMC_CFG_REG 0x0877+#define PMC_GCR_TELEM_DEEP_S0IX_REG 0x7888+#define PMC_GCR_TELEM_SHLW_S0IX_REG 0x8099+1010+/* PMC_CFG_REG bit masks */1111+#define PMC_CFG_NO_REBOOT_EN BIT(4)1212+1313+/**1414+ * struct intel_pmc_dev - Intel PMC device structure1515+ * @dev: Pointer to the parent PMC device1616+ * @scu: Pointer to the SCU IPC device data structure1717+ * @gcr_mem_base: Virtual base address of GCR (Global Configuration Registers)1818+ * @gcr_lock: Lock used to serialize access to GCR registers1919+ * @telem_base: Pointer to telemetry SSRAM base resource or %NULL if not2020+ * available2121+ */2222+struct intel_pmc_dev {2323+ struct device *dev;2424+ struct intel_scu_ipc_dev *scu;2525+ void __iomem *gcr_mem_base;2626+ spinlock_t gcr_lock;2727+ struct resource *telem_base;2828+};2929+3030+#if IS_ENABLED(CONFIG_MFD_INTEL_PMC_BXT)3131+int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, u64 *data);3232+int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, u32 mask, u32 val);3333+int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data);3434+#else3535+static inline int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset,3636+ u64 *data)3737+{3838+ return -ENOTSUPP;3939+}4040+4141+static inline int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset,4242+ u32 mask, u32 val)4343+{4444+ return -ENOTSUPP;4545+}4646+4747+static inline int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data)4848+{4949+ return -ENOTSUPP;5050+}5151+#endif5252+5353+#endif /* MFD_INTEL_PMC_BXT_H */
+15
include/linux/mfd/intel_soc_pmic.h
···13131414#include <linux/regmap.h>15151616+/**1717+ * struct intel_soc_pmic - Intel SoC PMIC data1818+ * @irq: Master interrupt number of the parent PMIC device1919+ * @regmap: Pointer to the parent PMIC device regmap structure2020+ * @irq_chip_data: IRQ chip data for the PMIC itself2121+ * @irq_chip_data_pwrbtn: Chained IRQ chip data for the Power Button2222+ * @irq_chip_data_tmu: Chained IRQ chip data for the Time Management Unit2323+ * @irq_chip_data_bcu: Chained IRQ chip data for the Burst Control Unit2424+ * @irq_chip_data_adc: Chained IRQ chip data for the General Purpose ADC2525+ * @irq_chip_data_chgr: Chained IRQ chip data for the External Charger2626+ * @irq_chip_data_crit: Chained IRQ chip data for the Critical Event Handler2727+ * @dev: Pointer to the parent PMIC device2828+ * @scu: Pointer to the SCU IPC device data structure2929+ */1630struct intel_soc_pmic {1731 int irq;1832 struct regmap *regmap;···3824 struct regmap_irq_chip_data *irq_chip_data_chgr;3925 struct regmap_irq_chip_data *irq_chip_data_crit;4026 struct device *dev;2727+ struct intel_scu_ipc_dev *scu;4128};42294330int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+7-4
include/linux/platform_data/itco_wdt.h
···1212#define ICH_RES_MEM_OFF 21313#define ICH_RES_MEM_GCS_PMC 014141515+/**1616+ * struct itco_wdt_platform_data - iTCO_wdt platform data1717+ * @name: Name of the platform1818+ * @version: iTCO version1919+ * @no_reboot_use_pmc: Use PMC BXT API to set and clear NO_REBOOT bit2020+ */1521struct itco_wdt_platform_data {1622 char name[32];1723 unsigned int version;1818- /* private data to be passed to update_no_reboot_bit API */1919- void *no_reboot_priv;2020- /* pointer for platform specific no reboot update function */2121- int (*update_no_reboot_bit)(void *priv, bool set);2424+ bool no_reboot_use_pmc;2225};23262427#endif /* _ITCO_WDT_H_ */