Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'ib-mfd-x86-usb-watchdog-v5.7'

Merge branch 'ib-mfd-x86-usb-watchdog-v5.7' of
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
to avoid conflicts in PDx86.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

+1414 -1323
+22
Documentation/ABI/obsolete/sysfs-driver-intel_pmc_bxt
··· 1 + These files allow sending arbitrary IPC commands to the PMC/SCU which 2 + may be dangerous. These will be removed eventually and should not be 3 + used in any new applications. 4 + 5 + What: /sys/bus/platform/devices/INT34D2:00/simplecmd 6 + Date: Jun 2015 7 + KernelVersion: 4.1 8 + Contact: Mika Westerberg <mika.westerberg@linux.intel.com> 9 + Description: This interface allows userspace to send an arbitrary 10 + IPC command to the PMC/SCU. 11 + 12 + Format: %d %d where first number is command and 13 + second number is subcommand. 14 + 15 + What: /sys/bus/platform/devices/INT34D2:00/northpeak 16 + Date: Jun 2015 17 + KernelVersion: 4.1 18 + Contact: Mika Westerberg <mika.westerberg@linux.intel.com> 19 + Description: This interface allows userspace to enable and disable 20 + Northpeak through the PMC/SCU. 21 + 22 + Format: %u.
+14 -9
MAINTAINERS
··· 8499 8499 S: Maintained 8500 8500 F: drivers/platform/x86/intel_atomisp2_pm.c 8501 8501 8502 + INTEL BROXTON PMC DRIVER 8503 + M: Mika Westerberg <mika.westerberg@linux.intel.com> 8504 + M: Zha Qipeng <qipeng.zha@intel.com> 8505 + S: Maintained 8506 + F: drivers/mfd/intel_pmc_bxt.c 8507 + F: include/linux/mfd/intel_pmc_bxt.h 8508 + 8502 8509 INTEL C600 SERIES SAS CONTROLLER DRIVER 8503 8510 M: Intel SCU Linux support <intel-linux-scu@intel.com> 8504 8511 M: Artur Paszkiewicz <artur.paszkiewicz@intel.com> ··· 8713 8706 F: include/uapi/linux/mic_ioctl.h 8714 8707 F: include/uapi/linux/scif_ioctl.h 8715 8708 8709 + INTEL P-Unit IPC DRIVER 8710 + M: Zha Qipeng <qipeng.zha@intel.com> 8711 + L: platform-driver-x86@vger.kernel.org 8712 + S: Maintained 8713 + F: arch/x86/include/asm/intel_punit_ipc.h 8714 + F: drivers/platform/x86/intel_punit_ipc.c 8715 + 8716 8716 INTEL PMC CORE DRIVER 8717 8717 M: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com> 8718 8718 M: Vishwanath Somayaji <vishwanath.somayaji@intel.com> 8719 8719 L: platform-driver-x86@vger.kernel.org 8720 8720 S: Maintained 8721 8721 F: drivers/platform/x86/intel_pmc_core* 8722 - 8723 - INTEL PMC/P-Unit IPC DRIVER 8724 - M: Zha Qipeng<qipeng.zha@intel.com> 8725 - L: platform-driver-x86@vger.kernel.org 8726 - S: Maintained 8727 - F: arch/x86/include/asm/intel_pmc_ipc.h 8728 - F: arch/x86/include/asm/intel_punit_ipc.h 8729 - F: drivers/platform/x86/intel_pmc_ipc.c 8730 - F: drivers/platform/x86/intel_punit_ipc.c 8731 8722 8732 8723 INTEL PMIC GPIO DRIVERS 8733 8724 M: Andy Shevchenko <andy@kernel.org>
+1 -1
arch/x86/Kconfig
··· 595 595 select I2C 596 596 select DW_APB_TIMER 597 597 select APB_TIMER 598 - select INTEL_SCU_IPC 598 + select INTEL_SCU_PCI 599 599 select MFD_INTEL_MSIC 600 600 ---help--- 601 601 Select to build a kernel capable of supporting Intel MID (Mobile
+6 -3
arch/x86/include/asm/intel-mid.h
··· 88 88 return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL); 89 89 } 90 90 91 + extern void intel_scu_devices_create(void); 92 + extern void intel_scu_devices_destroy(void); 93 + 91 94 #else /* !CONFIG_X86_INTEL_MID */ 92 95 93 96 #define intel_mid_identify_cpu() 0 94 97 #define intel_mid_has_msic() 0 98 + 99 + static inline void intel_scu_devices_create(void) { } 100 + static inline void intel_scu_devices_destroy(void) { } 95 101 96 102 #endif /* !CONFIG_X86_INTEL_MID */ 97 103 ··· 120 114 121 115 #define SFI_MTMR_MAX_NUM 8 122 116 #define SFI_MRTC_MAX 8 123 - 124 - extern void intel_scu_devices_create(void); 125 - extern void intel_scu_devices_destroy(void); 126 117 127 118 /* VRTC timer */ 128 119 #define MRST_VRTC_MAP_SZ 1024
-59
arch/x86/include/asm/intel_pmc_ipc.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _ASM_X86_INTEL_PMC_IPC_H_ 3 - #define _ASM_X86_INTEL_PMC_IPC_H_ 4 - 5 - /* Commands */ 6 - #define PMC_IPC_PMIC_ACCESS 0xFF 7 - #define PMC_IPC_PMIC_ACCESS_READ 0x0 8 - #define PMC_IPC_PMIC_ACCESS_WRITE 0x1 9 - #define PMC_IPC_USB_PWR_CTRL 0xF0 10 - #define PMC_IPC_PMIC_BLACKLIST_SEL 0xEF 11 - #define PMC_IPC_PHY_CONFIG 0xEE 12 - #define PMC_IPC_NORTHPEAK_CTRL 0xED 13 - #define PMC_IPC_PM_DEBUG 0xEC 14 - #define PMC_IPC_PMC_TELEMTRY 0xEB 15 - #define PMC_IPC_PMC_FW_MSG_CTRL 0xEA 16 - 17 - /* IPC return code */ 18 - #define IPC_ERR_NONE 0 19 - #define IPC_ERR_CMD_NOT_SUPPORTED 1 20 - #define IPC_ERR_CMD_NOT_SERVICED 2 21 - #define IPC_ERR_UNABLE_TO_SERVICE 3 22 - #define IPC_ERR_CMD_INVALID 4 23 - #define IPC_ERR_CMD_FAILED 5 24 - #define IPC_ERR_EMSECURITY 6 25 - #define IPC_ERR_UNSIGNEDKERNEL 7 26 - 27 - /* GCR reg offsets from gcr base*/ 28 - #define PMC_GCR_PMC_CFG_REG 0x08 29 - #define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78 30 - #define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80 31 - 32 - #if IS_ENABLED(CONFIG_INTEL_PMC_IPC) 33 - 34 - int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 35 - u32 *out, u32 outlen); 36 - int intel_pmc_s0ix_counter_read(u64 *data); 37 - int intel_pmc_gcr_read64(u32 offset, u64 *data); 38 - 39 - #else 40 - 41 - static inline int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 42 - u32 *out, u32 outlen) 43 - { 44 - return -EINVAL; 45 - } 46 - 47 - static inline int intel_pmc_s0ix_counter_read(u64 *data) 48 - { 49 - return -EINVAL; 50 - } 51 - 52 - static inline int intel_pmc_gcr_read64(u32 offset, u64 *data) 53 - { 54 - return -EINVAL; 55 - } 56 - 57 - #endif /*CONFIG_INTEL_PMC_IPC*/ 58 - 59 - #endif
+49 -41
arch/x86/include/asm/intel_scu_ipc.h
··· 2 2 #ifndef _ASM_X86_INTEL_SCU_IPC_H_ 3 3 #define _ASM_X86_INTEL_SCU_IPC_H_ 4 4 5 - #include <linux/notifier.h> 5 + #include <linux/ioport.h> 6 6 7 - #define IPCMSG_INDIRECT_READ 0x02 8 - #define IPCMSG_INDIRECT_WRITE 0x05 7 + struct device; 8 + struct intel_scu_ipc_dev; 9 9 10 - #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ 10 + /** 11 + * struct intel_scu_ipc_data - Data used to configure SCU IPC 12 + * @mem: Base address of SCU IPC MMIO registers 13 + * @irq: The IRQ number used for SCU (optional) 14 + */ 15 + struct intel_scu_ipc_data { 16 + struct resource mem; 17 + int irq; 18 + }; 11 19 12 - #define IPCMSG_WARM_RESET 0xF0 13 - #define IPCMSG_COLD_RESET 0xF1 14 - #define IPCMSG_SOFT_RESET 0xF2 15 - #define IPCMSG_COLD_BOOT 0xF3 20 + struct intel_scu_ipc_dev * 21 + __intel_scu_ipc_register(struct device *parent, 22 + const struct intel_scu_ipc_data *scu_data, 23 + struct module *owner); 16 24 17 - #define IPCMSG_VRTC 0xFA /* Set vRTC device */ 18 - /* Command id associated with message IPCMSG_VRTC */ 19 - #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ 20 - #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ 25 + #define intel_scu_ipc_register(parent, scu_data) \ 26 + __intel_scu_ipc_register(parent, scu_data, THIS_MODULE) 21 27 22 - /* Read single register */ 23 - int intel_scu_ipc_ioread8(u16 addr, u8 *data); 28 + void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu); 24 29 25 - /* Read a vector */ 26 - int intel_scu_ipc_readv(u16 *addr, u8 *data, int len); 30 + struct intel_scu_ipc_dev * 31 + __devm_intel_scu_ipc_register(struct device *parent, 32 + const struct intel_scu_ipc_data *scu_data, 33 + struct module *owner); 27 34 28 - /* Write single register */ 29 - int intel_scu_ipc_iowrite8(u16 addr, u8 data); 35 + #define devm_intel_scu_ipc_register(parent, scu_data) \ 36 + __devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE) 30 37 31 - /* Write a vector */ 32 - int intel_scu_ipc_writev(u16 *addr, u8 *data, int len); 38 + struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void); 39 + void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu); 40 + struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev); 33 41 34 - /* Update single register based on the mask */ 35 - int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask); 42 + int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, 43 + u8 *data); 44 + int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, 45 + u8 data); 46 + int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, 47 + u8 *data, size_t len); 48 + int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, 49 + u8 *data, size_t len); 36 50 37 - /* Issue commands to the SCU with or without data */ 38 - int intel_scu_ipc_simple_command(int cmd, int sub); 39 - int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 40 - u32 *out, int outlen); 51 + int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, 52 + u8 data, u8 mask); 41 53 42 - extern struct blocking_notifier_head intel_scu_notifier; 54 + int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, 55 + int sub); 56 + int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, 57 + int sub, const void *in, size_t inlen, 58 + size_t size, void *out, size_t outlen); 43 59 44 - static inline void intel_scu_notifier_add(struct notifier_block *nb) 60 + static inline int intel_scu_ipc_dev_command(struct intel_scu_ipc_dev *scu, int cmd, 61 + int sub, const void *in, size_t inlen, 62 + void *out, size_t outlen) 45 63 { 46 - blocking_notifier_chain_register(&intel_scu_notifier, nb); 64 + return intel_scu_ipc_dev_command_with_size(scu, cmd, sub, in, inlen, 65 + inlen, out, outlen); 47 66 } 48 67 49 - static inline void intel_scu_notifier_remove(struct notifier_block *nb) 50 - { 51 - blocking_notifier_chain_unregister(&intel_scu_notifier, nb); 52 - } 53 - 54 - static inline int intel_scu_notifier_post(unsigned long v, void *p) 55 - { 56 - return blocking_notifier_call_chain(&intel_scu_notifier, v, p); 57 - } 58 - 59 - #define SCU_AVAILABLE 1 60 - #define SCU_DOWN 2 68 + #include <asm/intel_scu_ipc_legacy.h> 61 69 62 70 #endif
+91
arch/x86/include/asm/intel_scu_ipc_legacy.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_X86_INTEL_SCU_IPC_LEGACY_H_ 3 + #define _ASM_X86_INTEL_SCU_IPC_LEGACY_H_ 4 + 5 + #include <linux/notifier.h> 6 + 7 + #define IPCMSG_INDIRECT_READ 0x02 8 + #define IPCMSG_INDIRECT_WRITE 0x05 9 + 10 + #define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */ 11 + 12 + #define IPCMSG_WARM_RESET 0xF0 13 + #define IPCMSG_COLD_RESET 0xF1 14 + #define IPCMSG_SOFT_RESET 0xF2 15 + #define IPCMSG_COLD_BOOT 0xF3 16 + 17 + #define IPCMSG_VRTC 0xFA /* Set vRTC device */ 18 + /* Command id associated with message IPCMSG_VRTC */ 19 + #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ 20 + #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ 21 + 22 + /* Don't call these in new code - they will be removed eventually */ 23 + 24 + /* Read single register */ 25 + static inline int intel_scu_ipc_ioread8(u16 addr, u8 *data) 26 + { 27 + return intel_scu_ipc_dev_ioread8(NULL, addr, data); 28 + } 29 + 30 + /* Read a vector */ 31 + static inline int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) 32 + { 33 + return intel_scu_ipc_dev_readv(NULL, addr, data, len); 34 + } 35 + 36 + /* Write single register */ 37 + static inline int intel_scu_ipc_iowrite8(u16 addr, u8 data) 38 + { 39 + return intel_scu_ipc_dev_iowrite8(NULL, addr, data); 40 + } 41 + 42 + /* Write a vector */ 43 + static inline int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) 44 + { 45 + return intel_scu_ipc_dev_writev(NULL, addr, data, len); 46 + } 47 + 48 + /* Update single register based on the mask */ 49 + static inline int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask) 50 + { 51 + return intel_scu_ipc_dev_update(NULL, addr, data, mask); 52 + } 53 + 54 + /* Issue commands to the SCU with or without data */ 55 + static inline int intel_scu_ipc_simple_command(int cmd, int sub) 56 + { 57 + return intel_scu_ipc_dev_simple_command(NULL, cmd, sub); 58 + } 59 + 60 + static inline int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 61 + u32 *out, int outlen) 62 + { 63 + /* New API takes both inlen and outlen as bytes so convert here */ 64 + size_t inbytes = inlen * sizeof(u32); 65 + size_t outbytes = outlen * sizeof(u32); 66 + 67 + return intel_scu_ipc_dev_command_with_size(NULL, cmd, sub, in, inbytes, 68 + inlen, out, outbytes); 69 + } 70 + 71 + extern struct blocking_notifier_head intel_scu_notifier; 72 + 73 + static inline void intel_scu_notifier_add(struct notifier_block *nb) 74 + { 75 + blocking_notifier_chain_register(&intel_scu_notifier, nb); 76 + } 77 + 78 + static inline void intel_scu_notifier_remove(struct notifier_block *nb) 79 + { 80 + blocking_notifier_chain_unregister(&intel_scu_notifier, nb); 81 + } 82 + 83 + static inline int intel_scu_notifier_post(unsigned long v, void *p) 84 + { 85 + return blocking_notifier_call_chain(&intel_scu_notifier, v, p); 86 + } 87 + 88 + #define SCU_AVAILABLE 1 89 + #define SCU_DOWN 2 90 + 91 + #endif
+5 -1
arch/x86/include/asm/intel_telemetry.h
··· 10 10 #define TELEM_MAX_EVENTS_SRAM 28 11 11 #define TELEM_MAX_OS_ALLOCATED_EVENTS 20 12 12 13 + #include <asm/intel_scu_ipc.h> 14 + 13 15 enum telemetry_unit { 14 16 TELEM_PSS = 0, 15 17 TELEM_IOSS, ··· 53 51 struct telemetry_unit_config ioss_config; 54 52 struct mutex telem_trace_lock; 55 53 struct mutex telem_lock; 54 + struct intel_pmc_dev *pmc; 55 + struct intel_scu_ipc_dev *scu; 56 56 bool telem_in_use; 57 57 }; 58 58 ··· 96 92 97 93 int telemetry_clear_pltdata(void); 98 94 99 - int telemetry_pltconfig_valid(void); 95 + struct telemetry_plt_config *telemetry_get_pltdata(void); 100 96 101 97 int telemetry_get_evtname(enum telemetry_unit telem_unit, 102 98 const char **name, int len);
+17 -3
drivers/mfd/Kconfig
··· 551 551 552 552 config INTEL_SOC_PMIC_BXTWC 553 553 tristate "Support for Intel Broxton Whiskey Cove PMIC" 554 - depends on INTEL_PMC_IPC 554 + depends on MFD_INTEL_PMC_BXT 555 555 select MFD_CORE 556 556 select REGMAP_IRQ 557 557 help ··· 593 593 tristate "Support for Intel Merrifield Basin Cove PMIC" 594 594 depends on GPIOLIB 595 595 depends on ACPI 596 - depends on INTEL_SCU_IPC 596 + depends on INTEL_SCU 597 597 select MFD_CORE 598 598 select REGMAP_IRQ 599 599 help ··· 625 625 626 626 config MFD_INTEL_MSIC 627 627 bool "Intel MSIC" 628 - depends on INTEL_SCU_IPC 628 + depends on INTEL_SCU 629 629 select MFD_CORE 630 630 help 631 631 Select this option to enable access to Intel MSIC (Avatele 632 632 Passage) chip. This chip embeds audio, battery, GPIO, etc. 633 633 devices used in Intel Medfield platforms. 634 + 635 + config MFD_INTEL_PMC_BXT 636 + tristate "Intel PMC Driver for Broxton" 637 + depends on X86 638 + depends on X86_PLATFORM_DEVICES 639 + depends on ACPI 640 + select INTEL_SCU_IPC 641 + select MFD_CORE 642 + help 643 + This driver provides support for the PMC (Power Management 644 + Controller) on Intel Broxton and Apollo Lake. The PMC is a 645 + multi-function device that exposes IPC, General Control 646 + Register and P-unit access. In addition this creates devices 647 + for iTCO watchdog and telemetry that are part of the PMC. 634 648 635 649 config MFD_IPAQ_MICRO 636 650 bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support"
+1
drivers/mfd/Makefile
··· 212 212 obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o 213 213 obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o 214 214 obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o 215 + obj-$(CONFIG_MFD_INTEL_PMC_BXT) += intel_pmc_bxt.o 215 216 obj-$(CONFIG_MFD_PALMAS) += palmas.o 216 217 obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o 217 218 obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
+468
drivers/mfd/intel_pmc_bxt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Driver for the Intel Broxton PMC 4 + * 5 + * (C) Copyright 2014 - 2020 Intel Corporation 6 + * 7 + * This driver is based on Intel SCU IPC driver (intel_scu_ipc.c) by 8 + * Sreedhara DS <sreedhara.ds@intel.com> 9 + * 10 + * The PMC (Power Management Controller) running on the ARC processor 11 + * communicates with another entity running in the IA (Intel Architecture) 12 + * core through an IPC (Intel Processor Communications) mechanism which in 13 + * turn sends messages between the IA and the PMC. 14 + */ 15 + 16 + #include <linux/acpi.h> 17 + #include <linux/delay.h> 18 + #include <linux/errno.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/io-64-nonatomic-lo-hi.h> 21 + #include <linux/mfd/core.h> 22 + #include <linux/mfd/intel_pmc_bxt.h> 23 + #include <linux/module.h> 24 + #include <linux/platform_device.h> 25 + #include <linux/platform_data/itco_wdt.h> 26 + 27 + #include <asm/intel_scu_ipc.h> 28 + 29 + /* Residency with clock rate at 19.2MHz to usecs */ 30 + #define S0IX_RESIDENCY_IN_USECS(d, s) \ 31 + ({ \ 32 + u64 result = 10ull * ((d) + (s)); \ 33 + do_div(result, 192); \ 34 + result; \ 35 + }) 36 + 37 + /* Resources exported from IFWI */ 38 + #define PLAT_RESOURCE_IPC_INDEX 0 39 + #define PLAT_RESOURCE_IPC_SIZE 0x1000 40 + #define PLAT_RESOURCE_GCR_OFFSET 0x1000 41 + #define PLAT_RESOURCE_GCR_SIZE 0x1000 42 + #define PLAT_RESOURCE_BIOS_DATA_INDEX 1 43 + #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 44 + #define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3 45 + #define PLAT_RESOURCE_ISP_DATA_INDEX 4 46 + #define PLAT_RESOURCE_ISP_IFACE_INDEX 5 47 + #define PLAT_RESOURCE_GTD_DATA_INDEX 6 48 + #define PLAT_RESOURCE_GTD_IFACE_INDEX 7 49 + #define PLAT_RESOURCE_ACPI_IO_INDEX 0 50 + 51 + /* 52 + * BIOS does not create an ACPI device for each PMC function, but 53 + * exports multiple resources from one ACPI device (IPC) for multiple 54 + * functions. This driver is responsible for creating a child device and 55 + * to export resources for those functions. 56 + */ 57 + #define SMI_EN_OFFSET 0x0040 58 + #define SMI_EN_SIZE 4 59 + #define TCO_BASE_OFFSET 0x0060 60 + #define TCO_REGS_SIZE 16 61 + #define TELEM_SSRAM_SIZE 240 62 + #define TELEM_PMC_SSRAM_OFFSET 0x1b00 63 + #define TELEM_PUNIT_SSRAM_OFFSET 0x1a00 64 + 65 + /* Commands */ 66 + #define PMC_NORTHPEAK_CTRL 0xed 67 + 68 + static inline bool is_gcr_valid(u32 offset) 69 + { 70 + return offset < PLAT_RESOURCE_GCR_SIZE - 8; 71 + } 72 + 73 + /** 74 + * intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register 75 + * @pmc: PMC device pointer 76 + * @offset: offset of GCR register from GCR address base 77 + * @data: data pointer for storing the register output 78 + * 79 + * Reads the 64-bit PMC GCR register at given offset. 80 + * 81 + * Return: Negative value on error or 0 on success. 82 + */ 83 + int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, u64 *data) 84 + { 85 + if (!is_gcr_valid(offset)) 86 + return -EINVAL; 87 + 88 + spin_lock(&pmc->gcr_lock); 89 + *data = readq(pmc->gcr_mem_base + offset); 90 + spin_unlock(&pmc->gcr_lock); 91 + 92 + return 0; 93 + } 94 + EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64); 95 + 96 + /** 97 + * intel_pmc_gcr_update() - Update PMC GCR register bits 98 + * @pmc: PMC device pointer 99 + * @offset: offset of GCR register from GCR address base 100 + * @mask: bit mask for update operation 101 + * @val: update value 102 + * 103 + * Updates the bits of given GCR register as specified by 104 + * @mask and @val. 105 + * 106 + * Return: Negative value on error or 0 on success. 107 + */ 108 + int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, u32 mask, u32 val) 109 + { 110 + u32 new_val; 111 + 112 + if (!is_gcr_valid(offset)) 113 + return -EINVAL; 114 + 115 + spin_lock(&pmc->gcr_lock); 116 + new_val = readl(pmc->gcr_mem_base + offset); 117 + 118 + new_val = (new_val & ~mask) | (val & mask); 119 + writel(new_val, pmc->gcr_mem_base + offset); 120 + 121 + new_val = readl(pmc->gcr_mem_base + offset); 122 + spin_unlock(&pmc->gcr_lock); 123 + 124 + /* Check whether the bit update is successful */ 125 + return (new_val & mask) != (val & mask) ? -EIO : 0; 126 + } 127 + EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); 128 + 129 + /** 130 + * intel_pmc_s0ix_counter_read() - Read S0ix residency 131 + * @pmc: PMC device pointer 132 + * @data: Out param that contains current S0ix residency count. 133 + * 134 + * Writes to @data how many usecs the system has been in low-power S0ix 135 + * state. 136 + * 137 + * Return: An error code or 0 on success. 138 + */ 139 + int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data) 140 + { 141 + u64 deep, shlw; 142 + 143 + spin_lock(&pmc->gcr_lock); 144 + deep = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_DEEP_S0IX_REG); 145 + shlw = readq(pmc->gcr_mem_base + PMC_GCR_TELEM_SHLW_S0IX_REG); 146 + spin_unlock(&pmc->gcr_lock); 147 + 148 + *data = S0IX_RESIDENCY_IN_USECS(deep, shlw); 149 + return 0; 150 + } 151 + EXPORT_SYMBOL_GPL(intel_pmc_s0ix_counter_read); 152 + 153 + /** 154 + * simplecmd_store() - Send a simple IPC command 155 + * @dev: Device under the attribute is 156 + * @attr: Attribute in question 157 + * @buf: Buffer holding data to be stored to the attribute 158 + * @count: Number of bytes in @buf 159 + * 160 + * Expects a string with two integers separated with space. These two 161 + * values hold command and subcommand that is send to PMC. 162 + * 163 + * Return: Number number of bytes written (@count) or negative errno in 164 + * case of error. 165 + */ 166 + static ssize_t simplecmd_store(struct device *dev, struct device_attribute *attr, 167 + const char *buf, size_t count) 168 + { 169 + struct intel_pmc_dev *pmc = dev_get_drvdata(dev); 170 + struct intel_scu_ipc_dev *scu = pmc->scu; 171 + int subcmd; 172 + int cmd; 173 + int ret; 174 + 175 + ret = sscanf(buf, "%d %d", &cmd, &subcmd); 176 + if (ret != 2) { 177 + dev_err(dev, "Invalid values, expected: cmd subcmd\n"); 178 + return -EINVAL; 179 + } 180 + 181 + ret = intel_scu_ipc_dev_simple_command(scu, cmd, subcmd); 182 + if (ret) 183 + return ret; 184 + 185 + return count; 186 + } 187 + static DEVICE_ATTR_WO(simplecmd); 188 + 189 + /** 190 + * northpeak_store() - Enable or disable Northpeak 191 + * @dev: Device under the attribute is 192 + * @attr: Attribute in question 193 + * @buf: Buffer holding data to be stored to the attribute 194 + * @count: Number of bytes in @buf 195 + * 196 + * Expects an unsigned integer. Non-zero enables Northpeak and zero 197 + * disables it. 198 + * 199 + * Return: Number number of bytes written (@count) or negative errno in 200 + * case of error. 201 + */ 202 + static ssize_t northpeak_store(struct device *dev, struct device_attribute *attr, 203 + const char *buf, size_t count) 204 + { 205 + struct intel_pmc_dev *pmc = dev_get_drvdata(dev); 206 + struct intel_scu_ipc_dev *scu = pmc->scu; 207 + unsigned long val; 208 + int subcmd; 209 + int ret; 210 + 211 + ret = kstrtoul(buf, 0, &val); 212 + if (ret) 213 + return ret; 214 + 215 + /* Northpeak is enabled if subcmd == 1 and disabled if it is 0 */ 216 + if (val) 217 + subcmd = 1; 218 + else 219 + subcmd = 0; 220 + 221 + ret = intel_scu_ipc_dev_simple_command(scu, PMC_NORTHPEAK_CTRL, subcmd); 222 + if (ret) 223 + return ret; 224 + 225 + return count; 226 + } 227 + static DEVICE_ATTR_WO(northpeak); 228 + 229 + static struct attribute *intel_pmc_attrs[] = { 230 + &dev_attr_northpeak.attr, 231 + &dev_attr_simplecmd.attr, 232 + NULL 233 + }; 234 + 235 + static const struct attribute_group intel_pmc_group = { 236 + .attrs = intel_pmc_attrs, 237 + }; 238 + 239 + static const struct attribute_group *intel_pmc_groups[] = { 240 + &intel_pmc_group, 241 + NULL 242 + }; 243 + 244 + static struct resource punit_res[6]; 245 + 246 + static struct mfd_cell punit = { 247 + .name = "intel_punit_ipc", 248 + .resources = punit_res, 249 + }; 250 + 251 + static struct itco_wdt_platform_data tco_pdata = { 252 + .name = "Apollo Lake SoC", 253 + .version = 5, 254 + .no_reboot_use_pmc = true, 255 + }; 256 + 257 + static struct resource tco_res[2]; 258 + 259 + static const struct mfd_cell tco = { 260 + .name = "iTCO_wdt", 261 + .ignore_resource_conflicts = true, 262 + .resources = tco_res, 263 + .num_resources = ARRAY_SIZE(tco_res), 264 + .platform_data = &tco_pdata, 265 + .pdata_size = sizeof(tco_pdata), 266 + }; 267 + 268 + static const struct resource telem_res[] = { 269 + DEFINE_RES_MEM(TELEM_PUNIT_SSRAM_OFFSET, TELEM_SSRAM_SIZE), 270 + DEFINE_RES_MEM(TELEM_PMC_SSRAM_OFFSET, TELEM_SSRAM_SIZE), 271 + }; 272 + 273 + static const struct mfd_cell telem = { 274 + .name = "intel_telemetry", 275 + .resources = telem_res, 276 + .num_resources = ARRAY_SIZE(telem_res), 277 + }; 278 + 279 + static int intel_pmc_get_tco_resources(struct platform_device *pdev) 280 + { 281 + struct resource *res; 282 + 283 + if (acpi_has_watchdog()) 284 + return 0; 285 + 286 + res = platform_get_resource(pdev, IORESOURCE_IO, 287 + PLAT_RESOURCE_ACPI_IO_INDEX); 288 + if (!res) { 289 + dev_err(&pdev->dev, "Failed to get IO resource\n"); 290 + return -EINVAL; 291 + } 292 + 293 + tco_res[0].flags = IORESOURCE_IO; 294 + tco_res[0].start = res->start + TCO_BASE_OFFSET; 295 + tco_res[0].end = tco_res[0].start + TCO_REGS_SIZE - 1; 296 + tco_res[1].flags = IORESOURCE_IO; 297 + tco_res[1].start = res->start + SMI_EN_OFFSET; 298 + tco_res[1].end = tco_res[1].start + SMI_EN_SIZE - 1; 299 + 300 + return 0; 301 + } 302 + 303 + static int intel_pmc_get_resources(struct platform_device *pdev, 304 + struct intel_pmc_dev *pmc, 305 + struct intel_scu_ipc_data *scu_data) 306 + { 307 + struct resource gcr_res; 308 + size_t npunit_res = 0; 309 + struct resource *res; 310 + int ret; 311 + 312 + scu_data->irq = platform_get_irq_optional(pdev, 0); 313 + 314 + res = platform_get_resource(pdev, IORESOURCE_MEM, 315 + PLAT_RESOURCE_IPC_INDEX); 316 + if (!res) { 317 + dev_err(&pdev->dev, "Failed to get IPC resource\n"); 318 + return -EINVAL; 319 + } 320 + 321 + /* IPC registers */ 322 + scu_data->mem.flags = res->flags; 323 + scu_data->mem.start = res->start; 324 + scu_data->mem.end = res->start + PLAT_RESOURCE_IPC_SIZE - 1; 325 + 326 + /* GCR registers */ 327 + gcr_res.flags = res->flags; 328 + gcr_res.start = res->start + PLAT_RESOURCE_GCR_OFFSET; 329 + gcr_res.end = gcr_res.start + PLAT_RESOURCE_GCR_SIZE - 1; 330 + 331 + pmc->gcr_mem_base = devm_ioremap_resource(&pdev->dev, &gcr_res); 332 + if (IS_ERR(pmc->gcr_mem_base)) 333 + return PTR_ERR(pmc->gcr_mem_base); 334 + 335 + /* Only register iTCO watchdog if there is no WDAT ACPI table */ 336 + ret = intel_pmc_get_tco_resources(pdev); 337 + if (ret) 338 + return ret; 339 + 340 + /* BIOS data register */ 341 + res = platform_get_resource(pdev, IORESOURCE_MEM, 342 + PLAT_RESOURCE_BIOS_DATA_INDEX); 343 + if (!res) { 344 + dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS data\n"); 345 + return -EINVAL; 346 + } 347 + punit_res[npunit_res++] = *res; 348 + 349 + /* BIOS interface register */ 350 + res = platform_get_resource(pdev, IORESOURCE_MEM, 351 + PLAT_RESOURCE_BIOS_IFACE_INDEX); 352 + if (!res) { 353 + dev_err(&pdev->dev, "Failed to get resource of P-unit BIOS interface\n"); 354 + return -EINVAL; 355 + } 356 + punit_res[npunit_res++] = *res; 357 + 358 + /* ISP data register, optional */ 359 + res = platform_get_resource(pdev, IORESOURCE_MEM, 360 + PLAT_RESOURCE_ISP_DATA_INDEX); 361 + if (res) 362 + punit_res[npunit_res++] = *res; 363 + 364 + /* ISP interface register, optional */ 365 + res = platform_get_resource(pdev, IORESOURCE_MEM, 366 + PLAT_RESOURCE_ISP_IFACE_INDEX); 367 + if (res) 368 + punit_res[npunit_res++] = *res; 369 + 370 + /* GTD data register, optional */ 371 + res = platform_get_resource(pdev, IORESOURCE_MEM, 372 + PLAT_RESOURCE_GTD_DATA_INDEX); 373 + if (res) 374 + punit_res[npunit_res++] = *res; 375 + 376 + /* GTD interface register, optional */ 377 + res = platform_get_resource(pdev, IORESOURCE_MEM, 378 + PLAT_RESOURCE_GTD_IFACE_INDEX); 379 + if (res) 380 + punit_res[npunit_res++] = *res; 381 + 382 + punit.num_resources = npunit_res; 383 + 384 + /* Telemetry SSRAM is optional */ 385 + res = platform_get_resource(pdev, IORESOURCE_MEM, 386 + PLAT_RESOURCE_TELEM_SSRAM_INDEX); 387 + if (res) 388 + pmc->telem_base = res; 389 + 390 + return 0; 391 + } 392 + 393 + static int intel_pmc_create_devices(struct intel_pmc_dev *pmc) 394 + { 395 + int ret; 396 + 397 + if (!acpi_has_watchdog()) { 398 + ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &tco, 399 + 1, NULL, 0, NULL); 400 + if (ret) 401 + return ret; 402 + } 403 + 404 + ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, &punit, 1, 405 + NULL, 0, NULL); 406 + if (ret) 407 + return ret; 408 + 409 + if (pmc->telem_base) { 410 + ret = devm_mfd_add_devices(pmc->dev, PLATFORM_DEVID_AUTO, 411 + &telem, 1, pmc->telem_base, 0, NULL); 412 + } 413 + 414 + return ret; 415 + } 416 + 417 + static const struct acpi_device_id intel_pmc_acpi_ids[] = { 418 + { "INT34D2" }, 419 + { } 420 + }; 421 + MODULE_DEVICE_TABLE(acpi, intel_pmc_acpi_ids); 422 + 423 + static int intel_pmc_probe(struct platform_device *pdev) 424 + { 425 + struct intel_scu_ipc_data scu_data = {}; 426 + struct intel_pmc_dev *pmc; 427 + int ret; 428 + 429 + pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL); 430 + if (!pmc) 431 + return -ENOMEM; 432 + 433 + pmc->dev = &pdev->dev; 434 + spin_lock_init(&pmc->gcr_lock); 435 + 436 + ret = intel_pmc_get_resources(pdev, pmc, &scu_data); 437 + if (ret) { 438 + dev_err(&pdev->dev, "Failed to request resources\n"); 439 + return ret; 440 + } 441 + 442 + pmc->scu = devm_intel_scu_ipc_register(&pdev->dev, &scu_data); 443 + if (IS_ERR(pmc->scu)) 444 + return PTR_ERR(pmc->scu); 445 + 446 + platform_set_drvdata(pdev, pmc); 447 + 448 + ret = intel_pmc_create_devices(pmc); 449 + if (ret) 450 + dev_err(&pdev->dev, "Failed to create PMC devices\n"); 451 + 452 + return ret; 453 + } 454 + 455 + static struct platform_driver intel_pmc_driver = { 456 + .probe = intel_pmc_probe, 457 + .driver = { 458 + .name = "intel_pmc_bxt", 459 + .acpi_match_table = intel_pmc_acpi_ids, 460 + .dev_groups = intel_pmc_groups, 461 + }, 462 + }; 463 + module_platform_driver(intel_pmc_driver); 464 + 465 + MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 466 + MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>"); 467 + MODULE_DESCRIPTION("Intel Broxton PMC driver"); 468 + MODULE_LICENSE("GPL v2");
+17 -17
drivers/mfd/intel_soc_pmic_bxtwc.c
··· 15 15 #include <linux/mfd/intel_soc_pmic_bxtwc.h> 16 16 #include <linux/module.h> 17 17 18 - #include <asm/intel_pmc_ipc.h> 18 + #include <asm/intel_scu_ipc.h> 19 19 20 20 /* PMIC device registers */ 21 21 #define REG_ADDR_MASK 0xFF00 ··· 57 57 58 58 /* Whiskey Cove PMIC share same ACPI ID between different platforms */ 59 59 #define BROXTON_PMIC_WC_HRV 4 60 + 61 + #define PMC_PMIC_ACCESS 0xFF 62 + #define PMC_PMIC_READ 0x0 63 + #define PMC_PMIC_WRITE 0x1 60 64 61 65 enum bxtwc_irqs { 62 66 BXTWC_PWRBTN_LVL1_IRQ = 0, ··· 292 288 293 289 ipc_in[0] = reg; 294 290 ipc_in[1] = i2c_addr; 295 - ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS, 296 - PMC_IPC_PMIC_ACCESS_READ, 297 - ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1); 298 - if (ret) { 299 - dev_err(pmic->dev, "Failed to read from PMIC\n"); 291 + ret = intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS, 292 + PMC_PMIC_READ, ipc_in, sizeof(ipc_in), 293 + ipc_out, sizeof(ipc_out)); 294 + if (ret) 300 295 return ret; 301 - } 296 + 302 297 *val = ipc_out[0]; 303 298 304 299 return 0; ··· 306 303 static int regmap_ipc_byte_reg_write(void *context, unsigned int reg, 307 304 unsigned int val) 308 305 { 309 - int ret; 310 306 int i2c_addr; 311 307 u8 ipc_in[3]; 312 308 struct intel_soc_pmic *pmic = context; ··· 323 321 ipc_in[0] = reg; 324 322 ipc_in[1] = i2c_addr; 325 323 ipc_in[2] = val; 326 - ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS, 327 - PMC_IPC_PMIC_ACCESS_WRITE, 328 - ipc_in, sizeof(ipc_in), NULL, 0); 329 - if (ret) { 330 - dev_err(pmic->dev, "Failed to write to PMIC\n"); 331 - return ret; 332 - } 333 - 334 - return 0; 324 + return intel_scu_ipc_dev_command(pmic->scu, PMC_PMIC_ACCESS, 325 + PMC_PMIC_WRITE, ipc_in, sizeof(ipc_in), 326 + NULL, 0); 335 327 } 336 328 337 329 /* sysfs interfaces to r/w PMIC registers, required by initial script */ ··· 452 456 453 457 dev_set_drvdata(&pdev->dev, pmic); 454 458 pmic->dev = &pdev->dev; 459 + 460 + pmic->scu = devm_intel_scu_ipc_dev_get(&pdev->dev); 461 + if (!pmic->scu) 462 + return -EPROBE_DEFER; 455 463 456 464 pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic, 457 465 &bxtwc_regmap_config);
+8 -2
drivers/mfd/intel_soc_pmic_mrfld.c
··· 74 74 static int bcove_ipc_byte_reg_read(void *context, unsigned int reg, 75 75 unsigned int *val) 76 76 { 77 + struct intel_soc_pmic *pmic = context; 77 78 u8 ipc_out; 78 79 int ret; 79 80 80 - ret = intel_scu_ipc_ioread8(reg, &ipc_out); 81 + ret = intel_scu_ipc_dev_ioread8(pmic->scu, reg, &ipc_out); 81 82 if (ret) 82 83 return ret; 83 84 ··· 89 88 static int bcove_ipc_byte_reg_write(void *context, unsigned int reg, 90 89 unsigned int val) 91 90 { 91 + struct intel_soc_pmic *pmic = context; 92 92 u8 ipc_in = val; 93 93 int ret; 94 94 95 - ret = intel_scu_ipc_iowrite8(reg, ipc_in); 95 + ret = intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in); 96 96 if (ret) 97 97 return ret; 98 98 ··· 117 115 118 116 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 119 117 if (!pmic) 118 + return -ENOMEM; 119 + 120 + pmic->scu = devm_intel_scu_ipc_dev_get(dev); 121 + if (!pmic->scu) 120 122 return -ENOMEM; 121 123 122 124 platform_set_drvdata(pdev, pmic);
+27 -19
drivers/platform/x86/Kconfig
··· 1269 1269 config INTEL_BXTWC_PMIC_TMU 1270 1270 tristate "Intel BXT Whiskey Cove TMU Driver" 1271 1271 depends on REGMAP 1272 - depends on INTEL_SOC_PMIC_BXTWC && INTEL_PMC_IPC 1272 + depends on MFD_INTEL_PMC_BXT 1273 + depends on INTEL_SOC_PMIC_BXTWC 1273 1274 ---help--- 1274 1275 Select this driver to use Intel BXT Whiskey Cove PMIC TMU feature. 1275 1276 This driver enables the alarm wakeup functionality in the TMU unit ··· 1296 1295 1297 1296 config INTEL_MID_POWER_BUTTON 1298 1297 tristate "power button driver for Intel MID platforms" 1299 - depends on INTEL_SCU_IPC && INPUT 1298 + depends on INTEL_SCU && INPUT 1300 1299 help 1301 1300 This driver handles the power button on the Intel MID platforms. 1302 1301 ··· 1328 1327 - LTR Ignore 1329 1328 - MPHY/PLL gating status (Sunrisepoint PCH only) 1330 1329 1331 - config INTEL_PMC_IPC 1332 - tristate "Intel PMC IPC Driver" 1333 - depends on ACPI && PCI 1334 - ---help--- 1335 - This driver provides support for PMC control on some Intel platforms. 1336 - The PMC is an ARC processor which defines IPC commands for communication 1337 - with other entities in the CPU. 1338 - 1339 1330 config INTEL_PUNIT_IPC 1340 1331 tristate "Intel P-Unit IPC Driver" 1341 1332 ---help--- ··· 1335 1342 which is used to bridge the communications between kernel and P-Unit. 1336 1343 1337 1344 config INTEL_SCU_IPC 1338 - bool "Intel SCU IPC Support" 1339 - depends on X86_INTEL_MID 1340 - default y 1341 - ---help--- 1342 - IPC is used to bridge the communications between kernel and SCU on 1343 - some embedded Intel x86 platforms. This is not needed for PC-type 1344 - machines. 1345 + bool 1346 + 1347 + config INTEL_SCU 1348 + bool 1349 + select INTEL_SCU_IPC 1350 + 1351 + config INTEL_SCU_PCI 1352 + bool "Intel SCU PCI driver" 1353 + depends on PCI 1354 + select INTEL_SCU 1355 + help 1356 + This driver is used to bridge the communications between kernel 1357 + and SCU on some embedded Intel x86 platforms. It also creates 1358 + devices that are connected to the SoC through the SCU. 1359 + Platforms supported: 1360 + Medfield 1361 + Clovertrail 1362 + Merrifield 1363 + Broxton 1364 + Apollo Lake 1345 1365 1346 1366 config INTEL_SCU_IPC_UTIL 1347 1367 tristate "Intel SCU IPC utility driver" 1348 - depends on INTEL_SCU_IPC 1368 + depends on INTEL_SCU 1349 1369 ---help--- 1350 1370 The IPC Util driver provides an interface with the SCU enabling 1351 1371 low level access for debug work and updating the firmware. Say ··· 1366 1360 1367 1361 config INTEL_TELEMETRY 1368 1362 tristate "Intel SoC Telemetry Driver" 1369 - depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 1363 + depends on X86_64 1364 + depends on MFD_INTEL_PMC_BXT 1365 + depends on INTEL_PUNIT_IPC 1370 1366 ---help--- 1371 1367 This driver provides interfaces to configure and use 1372 1368 telemetry for INTEL SoC from APL onwards. It is also
+1 -1
drivers/platform/x86/Makefile
··· 138 138 obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o 139 139 obj-$(CONFIG_INTEL_MRFLD_PWRBTN) += intel_mrfld_pwrbtn.o 140 140 obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv.o 141 - obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o 142 141 obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o 143 142 obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 143 + obj-$(CONFIG_INTEL_SCU_PCI) += intel_scu_pcidrv.o 144 144 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o 145 145 obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \ 146 146 intel_telemetry_pltdrv.o \
+11 -4
drivers/platform/x86/intel_mid_powerbtn.c
··· 46 46 unsigned short mirqlvl1_addr; 47 47 unsigned short pbstat_addr; 48 48 u8 pbstat_mask; 49 + struct intel_scu_ipc_dev *scu; 49 50 int (*setup)(struct mid_pb_ddata *ddata); 50 51 }; 51 52 ··· 56 55 int ret; 57 56 u8 pbstat; 58 57 59 - ret = intel_scu_ipc_ioread8(ddata->pbstat_addr, &pbstat); 58 + ret = intel_scu_ipc_dev_ioread8(ddata->scu, ddata->pbstat_addr, 59 + &pbstat); 60 60 if (ret) 61 61 return ret; 62 62 ··· 69 67 70 68 static int mid_irq_ack(struct mid_pb_ddata *ddata) 71 69 { 72 - return intel_scu_ipc_update_register(ddata->mirqlvl1_addr, 0, MSIC_PWRBTNM); 70 + return intel_scu_ipc_dev_update(ddata->scu, ddata->mirqlvl1_addr, 0, 71 + MSIC_PWRBTNM); 73 72 } 74 73 75 74 static int mrfld_setup(struct mid_pb_ddata *ddata) 76 75 { 77 76 /* Unmask the PBIRQ and MPBIRQ on Tangier */ 78 - intel_scu_ipc_update_register(BCOVE_PBIRQ, 0, MSIC_PWRBTNM); 79 - intel_scu_ipc_update_register(BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM); 77 + intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQ, 0, MSIC_PWRBTNM); 78 + intel_scu_ipc_dev_update(ddata->scu, BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM); 80 79 81 80 return 0; 82 81 } ··· 163 160 if (error) 164 161 return error; 165 162 } 163 + 164 + ddata->scu = devm_intel_scu_ipc_dev_get(&pdev->dev); 165 + if (!ddata->scu) 166 + return -EPROBE_DEFER; 166 167 167 168 error = devm_request_threaded_irq(&pdev->dev, irq, NULL, mid_pb_isr, 168 169 IRQF_ONESHOT, DRIVER_NAME, ddata);
-949
drivers/platform/x86/intel_pmc_ipc.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Driver for the Intel PMC IPC mechanism 4 - * 5 - * (C) Copyright 2014-2015 Intel Corporation 6 - * 7 - * This driver is based on Intel SCU IPC driver(intel_scu_ipc.c) by 8 - * Sreedhara DS <sreedhara.ds@intel.com> 9 - * 10 - * PMC running in ARC processor communicates with other entity running in IA 11 - * core through IPC mechanism which in turn messaging between IA core ad PMC. 12 - */ 13 - 14 - #include <linux/acpi.h> 15 - #include <linux/delay.h> 16 - #include <linux/errno.h> 17 - #include <linux/interrupt.h> 18 - #include <linux/io-64-nonatomic-lo-hi.h> 19 - #include <linux/module.h> 20 - #include <linux/pci.h> 21 - #include <linux/platform_device.h> 22 - 23 - #include <asm/intel_pmc_ipc.h> 24 - 25 - #include <linux/platform_data/itco_wdt.h> 26 - 27 - /* 28 - * IPC registers 29 - * The IA write to IPC_CMD command register triggers an interrupt to the ARC, 30 - * The ARC handles the interrupt and services it, writing optional data to 31 - * the IPC1 registers, updates the IPC_STS response register with the status. 32 - */ 33 - #define IPC_CMD 0x00 34 - #define IPC_CMD_MSI BIT(8) 35 - #define IPC_CMD_SIZE 16 36 - #define IPC_CMD_SUBCMD 12 37 - #define IPC_STATUS 0x04 38 - #define IPC_STATUS_IRQ BIT(2) 39 - #define IPC_STATUS_ERR BIT(1) 40 - #define IPC_STATUS_BUSY BIT(0) 41 - #define IPC_SPTR 0x08 42 - #define IPC_DPTR 0x0C 43 - #define IPC_WRITE_BUFFER 0x80 44 - #define IPC_READ_BUFFER 0x90 45 - 46 - /* Residency with clock rate at 19.2MHz to usecs */ 47 - #define S0IX_RESIDENCY_IN_USECS(d, s) \ 48 - ({ \ 49 - u64 result = 10ull * ((d) + (s)); \ 50 - do_div(result, 192); \ 51 - result; \ 52 - }) 53 - 54 - /* 55 - * 16-byte buffer for sending data associated with IPC command. 56 - */ 57 - #define IPC_DATA_BUFFER_SIZE 16 58 - 59 - #define IPC_LOOP_CNT 3000000 60 - #define IPC_MAX_SEC 3 61 - 62 - #define IPC_TRIGGER_MODE_IRQ true 63 - 64 - /* exported resources from IFWI */ 65 - #define PLAT_RESOURCE_IPC_INDEX 0 66 - #define PLAT_RESOURCE_IPC_SIZE 0x1000 67 - #define PLAT_RESOURCE_GCR_OFFSET 0x1000 68 - #define PLAT_RESOURCE_GCR_SIZE 0x1000 69 - #define PLAT_RESOURCE_BIOS_DATA_INDEX 1 70 - #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 71 - #define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3 72 - #define PLAT_RESOURCE_ISP_DATA_INDEX 4 73 - #define PLAT_RESOURCE_ISP_IFACE_INDEX 5 74 - #define PLAT_RESOURCE_GTD_DATA_INDEX 6 75 - #define PLAT_RESOURCE_GTD_IFACE_INDEX 7 76 - #define PLAT_RESOURCE_ACPI_IO_INDEX 0 77 - 78 - /* 79 - * BIOS does not create an ACPI device for each PMC function, 80 - * but exports multiple resources from one ACPI device(IPC) for 81 - * multiple functions. This driver is responsible to create a 82 - * platform device and to export resources for those functions. 83 - */ 84 - #define TCO_DEVICE_NAME "iTCO_wdt" 85 - #define SMI_EN_OFFSET 0x40 86 - #define SMI_EN_SIZE 4 87 - #define TCO_BASE_OFFSET 0x60 88 - #define TCO_REGS_SIZE 16 89 - #define PUNIT_DEVICE_NAME "intel_punit_ipc" 90 - #define TELEMETRY_DEVICE_NAME "intel_telemetry" 91 - #define TELEM_SSRAM_SIZE 240 92 - #define TELEM_PMC_SSRAM_OFFSET 0x1B00 93 - #define TELEM_PUNIT_SSRAM_OFFSET 0x1A00 94 - #define TCO_PMC_OFFSET 0x08 95 - #define TCO_PMC_SIZE 0x04 96 - 97 - /* PMC register bit definitions */ 98 - 99 - /* PMC_CFG_REG bit masks */ 100 - #define PMC_CFG_NO_REBOOT_MASK BIT_MASK(4) 101 - #define PMC_CFG_NO_REBOOT_EN (1 << 4) 102 - #define PMC_CFG_NO_REBOOT_DIS (0 << 4) 103 - 104 - static struct intel_pmc_ipc_dev { 105 - struct device *dev; 106 - void __iomem *ipc_base; 107 - bool irq_mode; 108 - int irq; 109 - int cmd; 110 - struct completion cmd_complete; 111 - 112 - /* The following PMC BARs share the same ACPI device with the IPC */ 113 - resource_size_t acpi_io_base; 114 - int acpi_io_size; 115 - struct platform_device *tco_dev; 116 - 117 - /* gcr */ 118 - void __iomem *gcr_mem_base; 119 - bool has_gcr_regs; 120 - spinlock_t gcr_lock; 121 - 122 - /* punit */ 123 - struct platform_device *punit_dev; 124 - unsigned int punit_res_count; 125 - 126 - /* Telemetry */ 127 - resource_size_t telem_pmc_ssram_base; 128 - resource_size_t telem_punit_ssram_base; 129 - int telem_pmc_ssram_size; 130 - int telem_punit_ssram_size; 131 - u8 telem_res_inval; 132 - struct platform_device *telemetry_dev; 133 - } ipcdev; 134 - 135 - static char *ipc_err_sources[] = { 136 - [IPC_ERR_NONE] = 137 - "no error", 138 - [IPC_ERR_CMD_NOT_SUPPORTED] = 139 - "command not supported", 140 - [IPC_ERR_CMD_NOT_SERVICED] = 141 - "command not serviced", 142 - [IPC_ERR_UNABLE_TO_SERVICE] = 143 - "unable to service", 144 - [IPC_ERR_CMD_INVALID] = 145 - "command invalid", 146 - [IPC_ERR_CMD_FAILED] = 147 - "command failed", 148 - [IPC_ERR_EMSECURITY] = 149 - "Invalid Battery", 150 - [IPC_ERR_UNSIGNEDKERNEL] = 151 - "Unsigned kernel", 152 - }; 153 - 154 - /* Prevent concurrent calls to the PMC */ 155 - static DEFINE_MUTEX(ipclock); 156 - 157 - static inline void ipc_send_command(u32 cmd) 158 - { 159 - ipcdev.cmd = cmd; 160 - if (ipcdev.irq_mode) { 161 - reinit_completion(&ipcdev.cmd_complete); 162 - cmd |= IPC_CMD_MSI; 163 - } 164 - writel(cmd, ipcdev.ipc_base + IPC_CMD); 165 - } 166 - 167 - static inline u32 ipc_read_status(void) 168 - { 169 - return readl(ipcdev.ipc_base + IPC_STATUS); 170 - } 171 - 172 - static inline void ipc_data_writel(u32 data, u32 offset) 173 - { 174 - writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset); 175 - } 176 - 177 - static inline u32 ipc_data_readl(u32 offset) 178 - { 179 - return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 180 - } 181 - 182 - static inline u64 gcr_data_readq(u32 offset) 183 - { 184 - return readq(ipcdev.gcr_mem_base + offset); 185 - } 186 - 187 - static inline int is_gcr_valid(u32 offset) 188 - { 189 - if (!ipcdev.has_gcr_regs) 190 - return -EACCES; 191 - 192 - if (offset > PLAT_RESOURCE_GCR_SIZE) 193 - return -EINVAL; 194 - 195 - return 0; 196 - } 197 - 198 - /** 199 - * intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register 200 - * @offset: offset of GCR register from GCR address base 201 - * @data: data pointer for storing the register output 202 - * 203 - * Reads the 64-bit PMC GCR register at given offset. 204 - * 205 - * Return: negative value on error or 0 on success. 206 - */ 207 - int intel_pmc_gcr_read64(u32 offset, u64 *data) 208 - { 209 - int ret; 210 - 211 - spin_lock(&ipcdev.gcr_lock); 212 - 213 - ret = is_gcr_valid(offset); 214 - if (ret < 0) { 215 - spin_unlock(&ipcdev.gcr_lock); 216 - return ret; 217 - } 218 - 219 - *data = readq(ipcdev.gcr_mem_base + offset); 220 - 221 - spin_unlock(&ipcdev.gcr_lock); 222 - 223 - return 0; 224 - } 225 - EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64); 226 - 227 - /** 228 - * intel_pmc_gcr_update() - Update PMC GCR register bits 229 - * @offset: offset of GCR register from GCR address base 230 - * @mask: bit mask for update operation 231 - * @val: update value 232 - * 233 - * Updates the bits of given GCR register as specified by 234 - * @mask and @val. 235 - * 236 - * Return: negative value on error or 0 on success. 237 - */ 238 - static int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) 239 - { 240 - u32 new_val; 241 - int ret = 0; 242 - 243 - spin_lock(&ipcdev.gcr_lock); 244 - 245 - ret = is_gcr_valid(offset); 246 - if (ret < 0) 247 - goto gcr_ipc_unlock; 248 - 249 - new_val = readl(ipcdev.gcr_mem_base + offset); 250 - 251 - new_val &= ~mask; 252 - new_val |= val & mask; 253 - 254 - writel(new_val, ipcdev.gcr_mem_base + offset); 255 - 256 - new_val = readl(ipcdev.gcr_mem_base + offset); 257 - 258 - /* check whether the bit update is successful */ 259 - if ((new_val & mask) != (val & mask)) { 260 - ret = -EIO; 261 - goto gcr_ipc_unlock; 262 - } 263 - 264 - gcr_ipc_unlock: 265 - spin_unlock(&ipcdev.gcr_lock); 266 - return ret; 267 - } 268 - 269 - static int update_no_reboot_bit(void *priv, bool set) 270 - { 271 - u32 value = set ? PMC_CFG_NO_REBOOT_EN : PMC_CFG_NO_REBOOT_DIS; 272 - 273 - return intel_pmc_gcr_update(PMC_GCR_PMC_CFG_REG, 274 - PMC_CFG_NO_REBOOT_MASK, value); 275 - } 276 - 277 - static int intel_pmc_ipc_check_status(void) 278 - { 279 - int status; 280 - int ret = 0; 281 - 282 - if (ipcdev.irq_mode) { 283 - if (0 == wait_for_completion_timeout( 284 - &ipcdev.cmd_complete, IPC_MAX_SEC * HZ)) 285 - ret = -ETIMEDOUT; 286 - } else { 287 - int loop_count = IPC_LOOP_CNT; 288 - 289 - while ((ipc_read_status() & IPC_STATUS_BUSY) && --loop_count) 290 - udelay(1); 291 - if (loop_count == 0) 292 - ret = -ETIMEDOUT; 293 - } 294 - 295 - status = ipc_read_status(); 296 - if (ret == -ETIMEDOUT) { 297 - dev_err(ipcdev.dev, 298 - "IPC timed out, TS=0x%x, CMD=0x%x\n", 299 - status, ipcdev.cmd); 300 - return ret; 301 - } 302 - 303 - if (status & IPC_STATUS_ERR) { 304 - int i; 305 - 306 - ret = -EIO; 307 - i = (status >> IPC_CMD_SIZE) & 0xFF; 308 - if (i < ARRAY_SIZE(ipc_err_sources)) 309 - dev_err(ipcdev.dev, 310 - "IPC failed: %s, STS=0x%x, CMD=0x%x\n", 311 - ipc_err_sources[i], status, ipcdev.cmd); 312 - else 313 - dev_err(ipcdev.dev, 314 - "IPC failed: unknown, STS=0x%x, CMD=0x%x\n", 315 - status, ipcdev.cmd); 316 - if ((i == IPC_ERR_UNSIGNEDKERNEL) || (i == IPC_ERR_EMSECURITY)) 317 - ret = -EACCES; 318 - } 319 - 320 - return ret; 321 - } 322 - 323 - /** 324 - * intel_pmc_ipc_simple_command() - Simple IPC command 325 - * @cmd: IPC command code. 326 - * @sub: IPC command sub type. 327 - * 328 - * Send a simple IPC command to PMC when don't need to specify 329 - * input/output data and source/dest pointers. 330 - * 331 - * Return: an IPC error code or 0 on success. 332 - */ 333 - static int intel_pmc_ipc_simple_command(int cmd, int sub) 334 - { 335 - int ret; 336 - 337 - mutex_lock(&ipclock); 338 - if (ipcdev.dev == NULL) { 339 - mutex_unlock(&ipclock); 340 - return -ENODEV; 341 - } 342 - ipc_send_command(sub << IPC_CMD_SUBCMD | cmd); 343 - ret = intel_pmc_ipc_check_status(); 344 - mutex_unlock(&ipclock); 345 - 346 - return ret; 347 - } 348 - 349 - /** 350 - * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers 351 - * @cmd: IPC command code. 352 - * @sub: IPC command sub type. 353 - * @in: input data of this IPC command. 354 - * @inlen: input data length in bytes. 355 - * @out: output data of this IPC command. 356 - * @outlen: output data length in dwords. 357 - * @sptr: data writing to SPTR register. 358 - * @dptr: data writing to DPTR register. 359 - * 360 - * Send an IPC command to PMC with input/output data and source/dest pointers. 361 - * 362 - * Return: an IPC error code or 0 on success. 363 - */ 364 - static int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, 365 - u32 outlen, u32 dptr, u32 sptr) 366 - { 367 - u32 wbuf[4] = { 0 }; 368 - int ret; 369 - int i; 370 - 371 - if (inlen > IPC_DATA_BUFFER_SIZE || outlen > IPC_DATA_BUFFER_SIZE / 4) 372 - return -EINVAL; 373 - 374 - mutex_lock(&ipclock); 375 - if (ipcdev.dev == NULL) { 376 - mutex_unlock(&ipclock); 377 - return -ENODEV; 378 - } 379 - memcpy(wbuf, in, inlen); 380 - writel(dptr, ipcdev.ipc_base + IPC_DPTR); 381 - writel(sptr, ipcdev.ipc_base + IPC_SPTR); 382 - /* The input data register is 32bit register and inlen is in Byte */ 383 - for (i = 0; i < ((inlen + 3) / 4); i++) 384 - ipc_data_writel(wbuf[i], 4 * i); 385 - ipc_send_command((inlen << IPC_CMD_SIZE) | 386 - (sub << IPC_CMD_SUBCMD) | cmd); 387 - ret = intel_pmc_ipc_check_status(); 388 - if (!ret) { 389 - /* out is read from 32bit register and outlen is in 32bit */ 390 - for (i = 0; i < outlen; i++) 391 - *out++ = ipc_data_readl(4 * i); 392 - } 393 - mutex_unlock(&ipclock); 394 - 395 - return ret; 396 - } 397 - 398 - /** 399 - * intel_pmc_ipc_command() - IPC command with input/output data 400 - * @cmd: IPC command code. 401 - * @sub: IPC command sub type. 402 - * @in: input data of this IPC command. 403 - * @inlen: input data length in bytes. 404 - * @out: output data of this IPC command. 405 - * @outlen: output data length in dwords. 406 - * 407 - * Send an IPC command to PMC with input/output data. 408 - * 409 - * Return: an IPC error code or 0 on success. 410 - */ 411 - int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, 412 - u32 *out, u32 outlen) 413 - { 414 - return intel_pmc_ipc_raw_cmd(cmd, sub, in, inlen, out, outlen, 0, 0); 415 - } 416 - EXPORT_SYMBOL_GPL(intel_pmc_ipc_command); 417 - 418 - static irqreturn_t ioc(int irq, void *dev_id) 419 - { 420 - int status; 421 - 422 - if (ipcdev.irq_mode) { 423 - status = ipc_read_status(); 424 - writel(status | IPC_STATUS_IRQ, ipcdev.ipc_base + IPC_STATUS); 425 - } 426 - complete(&ipcdev.cmd_complete); 427 - 428 - return IRQ_HANDLED; 429 - } 430 - 431 - static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 432 - { 433 - struct intel_pmc_ipc_dev *pmc = &ipcdev; 434 - int ret; 435 - 436 - /* Only one PMC is supported */ 437 - if (pmc->dev) 438 - return -EBUSY; 439 - 440 - pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; 441 - 442 - spin_lock_init(&ipcdev.gcr_lock); 443 - 444 - ret = pcim_enable_device(pdev); 445 - if (ret) 446 - return ret; 447 - 448 - ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); 449 - if (ret) 450 - return ret; 451 - 452 - init_completion(&pmc->cmd_complete); 453 - 454 - pmc->ipc_base = pcim_iomap_table(pdev)[0]; 455 - 456 - ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", 457 - pmc); 458 - if (ret) { 459 - dev_err(&pdev->dev, "Failed to request irq\n"); 460 - return ret; 461 - } 462 - 463 - pmc->dev = &pdev->dev; 464 - 465 - pci_set_drvdata(pdev, pmc); 466 - 467 - return 0; 468 - } 469 - 470 - static const struct pci_device_id ipc_pci_ids[] = { 471 - {PCI_VDEVICE(INTEL, 0x0a94), 0}, 472 - {PCI_VDEVICE(INTEL, 0x1a94), 0}, 473 - {PCI_VDEVICE(INTEL, 0x5a94), 0}, 474 - { 0,} 475 - }; 476 - MODULE_DEVICE_TABLE(pci, ipc_pci_ids); 477 - 478 - static struct pci_driver ipc_pci_driver = { 479 - .name = "intel_pmc_ipc", 480 - .id_table = ipc_pci_ids, 481 - .probe = ipc_pci_probe, 482 - }; 483 - 484 - static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, 485 - struct device_attribute *attr, 486 - const char *buf, size_t count) 487 - { 488 - int subcmd; 489 - int cmd; 490 - int ret; 491 - 492 - ret = sscanf(buf, "%d %d", &cmd, &subcmd); 493 - if (ret != 2) { 494 - dev_err(dev, "Error args\n"); 495 - return -EINVAL; 496 - } 497 - 498 - ret = intel_pmc_ipc_simple_command(cmd, subcmd); 499 - if (ret) { 500 - dev_err(dev, "command %d error with %d\n", cmd, ret); 501 - return ret; 502 - } 503 - return (ssize_t)count; 504 - } 505 - static DEVICE_ATTR(simplecmd, 0200, NULL, intel_pmc_ipc_simple_cmd_store); 506 - 507 - static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev, 508 - struct device_attribute *attr, 509 - const char *buf, size_t count) 510 - { 511 - unsigned long val; 512 - int subcmd; 513 - int ret; 514 - 515 - ret = kstrtoul(buf, 0, &val); 516 - if (ret) 517 - return ret; 518 - 519 - if (val) 520 - subcmd = 1; 521 - else 522 - subcmd = 0; 523 - ret = intel_pmc_ipc_simple_command(PMC_IPC_NORTHPEAK_CTRL, subcmd); 524 - if (ret) { 525 - dev_err(dev, "command north %d error with %d\n", subcmd, ret); 526 - return ret; 527 - } 528 - return (ssize_t)count; 529 - } 530 - static DEVICE_ATTR(northpeak, 0200, NULL, intel_pmc_ipc_northpeak_store); 531 - 532 - static struct attribute *intel_ipc_attrs[] = { 533 - &dev_attr_northpeak.attr, 534 - &dev_attr_simplecmd.attr, 535 - NULL 536 - }; 537 - 538 - static const struct attribute_group intel_ipc_group = { 539 - .attrs = intel_ipc_attrs, 540 - }; 541 - 542 - static const struct attribute_group *intel_ipc_groups[] = { 543 - &intel_ipc_group, 544 - NULL 545 - }; 546 - 547 - static struct resource punit_res_array[] = { 548 - /* Punit BIOS */ 549 - { 550 - .flags = IORESOURCE_MEM, 551 - }, 552 - { 553 - .flags = IORESOURCE_MEM, 554 - }, 555 - /* Punit ISP */ 556 - { 557 - .flags = IORESOURCE_MEM, 558 - }, 559 - { 560 - .flags = IORESOURCE_MEM, 561 - }, 562 - /* Punit GTD */ 563 - { 564 - .flags = IORESOURCE_MEM, 565 - }, 566 - { 567 - .flags = IORESOURCE_MEM, 568 - }, 569 - }; 570 - 571 - #define TCO_RESOURCE_ACPI_IO 0 572 - #define TCO_RESOURCE_SMI_EN_IO 1 573 - #define TCO_RESOURCE_GCR_MEM 2 574 - static struct resource tco_res[] = { 575 - /* ACPI - TCO */ 576 - { 577 - .flags = IORESOURCE_IO, 578 - }, 579 - /* ACPI - SMI */ 580 - { 581 - .flags = IORESOURCE_IO, 582 - }, 583 - }; 584 - 585 - static struct itco_wdt_platform_data tco_info = { 586 - .name = "Apollo Lake SoC", 587 - .version = 5, 588 - .no_reboot_priv = &ipcdev, 589 - .update_no_reboot_bit = update_no_reboot_bit, 590 - }; 591 - 592 - #define TELEMETRY_RESOURCE_PUNIT_SSRAM 0 593 - #define TELEMETRY_RESOURCE_PMC_SSRAM 1 594 - static struct resource telemetry_res[] = { 595 - /*Telemetry*/ 596 - { 597 - .flags = IORESOURCE_MEM, 598 - }, 599 - { 600 - .flags = IORESOURCE_MEM, 601 - }, 602 - }; 603 - 604 - static int ipc_create_punit_device(void) 605 - { 606 - struct platform_device *pdev; 607 - const struct platform_device_info pdevinfo = { 608 - .parent = ipcdev.dev, 609 - .name = PUNIT_DEVICE_NAME, 610 - .id = -1, 611 - .res = punit_res_array, 612 - .num_res = ipcdev.punit_res_count, 613 - }; 614 - 615 - pdev = platform_device_register_full(&pdevinfo); 616 - if (IS_ERR(pdev)) 617 - return PTR_ERR(pdev); 618 - 619 - ipcdev.punit_dev = pdev; 620 - 621 - return 0; 622 - } 623 - 624 - static int ipc_create_tco_device(void) 625 - { 626 - struct platform_device *pdev; 627 - struct resource *res; 628 - const struct platform_device_info pdevinfo = { 629 - .parent = ipcdev.dev, 630 - .name = TCO_DEVICE_NAME, 631 - .id = -1, 632 - .res = tco_res, 633 - .num_res = ARRAY_SIZE(tco_res), 634 - .data = &tco_info, 635 - .size_data = sizeof(tco_info), 636 - }; 637 - 638 - res = tco_res + TCO_RESOURCE_ACPI_IO; 639 - res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET; 640 - res->end = res->start + TCO_REGS_SIZE - 1; 641 - 642 - res = tco_res + TCO_RESOURCE_SMI_EN_IO; 643 - res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; 644 - res->end = res->start + SMI_EN_SIZE - 1; 645 - 646 - pdev = platform_device_register_full(&pdevinfo); 647 - if (IS_ERR(pdev)) 648 - return PTR_ERR(pdev); 649 - 650 - ipcdev.tco_dev = pdev; 651 - 652 - return 0; 653 - } 654 - 655 - static int ipc_create_telemetry_device(void) 656 - { 657 - struct platform_device *pdev; 658 - struct resource *res; 659 - const struct platform_device_info pdevinfo = { 660 - .parent = ipcdev.dev, 661 - .name = TELEMETRY_DEVICE_NAME, 662 - .id = -1, 663 - .res = telemetry_res, 664 - .num_res = ARRAY_SIZE(telemetry_res), 665 - }; 666 - 667 - res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM; 668 - res->start = ipcdev.telem_punit_ssram_base; 669 - res->end = res->start + ipcdev.telem_punit_ssram_size - 1; 670 - 671 - res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM; 672 - res->start = ipcdev.telem_pmc_ssram_base; 673 - res->end = res->start + ipcdev.telem_pmc_ssram_size - 1; 674 - 675 - pdev = platform_device_register_full(&pdevinfo); 676 - if (IS_ERR(pdev)) 677 - return PTR_ERR(pdev); 678 - 679 - ipcdev.telemetry_dev = pdev; 680 - 681 - return 0; 682 - } 683 - 684 - static int ipc_create_pmc_devices(void) 685 - { 686 - int ret; 687 - 688 - /* If we have ACPI based watchdog use that instead */ 689 - if (!acpi_has_watchdog()) { 690 - ret = ipc_create_tco_device(); 691 - if (ret) { 692 - dev_err(ipcdev.dev, "Failed to add tco platform device\n"); 693 - return ret; 694 - } 695 - } 696 - 697 - ret = ipc_create_punit_device(); 698 - if (ret) { 699 - dev_err(ipcdev.dev, "Failed to add punit platform device\n"); 700 - platform_device_unregister(ipcdev.tco_dev); 701 - return ret; 702 - } 703 - 704 - if (!ipcdev.telem_res_inval) { 705 - ret = ipc_create_telemetry_device(); 706 - if (ret) { 707 - dev_warn(ipcdev.dev, 708 - "Failed to add telemetry platform device\n"); 709 - platform_device_unregister(ipcdev.punit_dev); 710 - platform_device_unregister(ipcdev.tco_dev); 711 - } 712 - } 713 - 714 - return ret; 715 - } 716 - 717 - static int ipc_plat_get_res(struct platform_device *pdev) 718 - { 719 - struct resource *res, *punit_res = punit_res_array; 720 - void __iomem *addr; 721 - int size; 722 - 723 - res = platform_get_resource(pdev, IORESOURCE_IO, 724 - PLAT_RESOURCE_ACPI_IO_INDEX); 725 - if (!res) { 726 - dev_err(&pdev->dev, "Failed to get io resource\n"); 727 - return -ENXIO; 728 - } 729 - size = resource_size(res); 730 - ipcdev.acpi_io_base = res->start; 731 - ipcdev.acpi_io_size = size; 732 - dev_info(&pdev->dev, "io res: %pR\n", res); 733 - 734 - ipcdev.punit_res_count = 0; 735 - 736 - /* This is index 0 to cover BIOS data register */ 737 - res = platform_get_resource(pdev, IORESOURCE_MEM, 738 - PLAT_RESOURCE_BIOS_DATA_INDEX); 739 - if (!res) { 740 - dev_err(&pdev->dev, "Failed to get res of punit BIOS data\n"); 741 - return -ENXIO; 742 - } 743 - punit_res[ipcdev.punit_res_count++] = *res; 744 - dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res); 745 - 746 - /* This is index 1 to cover BIOS interface register */ 747 - res = platform_get_resource(pdev, IORESOURCE_MEM, 748 - PLAT_RESOURCE_BIOS_IFACE_INDEX); 749 - if (!res) { 750 - dev_err(&pdev->dev, "Failed to get res of punit BIOS iface\n"); 751 - return -ENXIO; 752 - } 753 - punit_res[ipcdev.punit_res_count++] = *res; 754 - dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res); 755 - 756 - /* This is index 2 to cover ISP data register, optional */ 757 - res = platform_get_resource(pdev, IORESOURCE_MEM, 758 - PLAT_RESOURCE_ISP_DATA_INDEX); 759 - if (res) { 760 - punit_res[ipcdev.punit_res_count++] = *res; 761 - dev_info(&pdev->dev, "punit ISP data res: %pR\n", res); 762 - } 763 - 764 - /* This is index 3 to cover ISP interface register, optional */ 765 - res = platform_get_resource(pdev, IORESOURCE_MEM, 766 - PLAT_RESOURCE_ISP_IFACE_INDEX); 767 - if (res) { 768 - punit_res[ipcdev.punit_res_count++] = *res; 769 - dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res); 770 - } 771 - 772 - /* This is index 4 to cover GTD data register, optional */ 773 - res = platform_get_resource(pdev, IORESOURCE_MEM, 774 - PLAT_RESOURCE_GTD_DATA_INDEX); 775 - if (res) { 776 - punit_res[ipcdev.punit_res_count++] = *res; 777 - dev_info(&pdev->dev, "punit GTD data res: %pR\n", res); 778 - } 779 - 780 - /* This is index 5 to cover GTD interface register, optional */ 781 - res = platform_get_resource(pdev, IORESOURCE_MEM, 782 - PLAT_RESOURCE_GTD_IFACE_INDEX); 783 - if (res) { 784 - punit_res[ipcdev.punit_res_count++] = *res; 785 - dev_info(&pdev->dev, "punit GTD interface res: %pR\n", res); 786 - } 787 - 788 - res = platform_get_resource(pdev, IORESOURCE_MEM, 789 - PLAT_RESOURCE_IPC_INDEX); 790 - if (!res) { 791 - dev_err(&pdev->dev, "Failed to get ipc resource\n"); 792 - return -ENXIO; 793 - } 794 - size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; 795 - res->end = res->start + size - 1; 796 - 797 - addr = devm_ioremap_resource(&pdev->dev, res); 798 - if (IS_ERR(addr)) 799 - return PTR_ERR(addr); 800 - 801 - ipcdev.ipc_base = addr; 802 - 803 - ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; 804 - dev_info(&pdev->dev, "ipc res: %pR\n", res); 805 - 806 - ipcdev.telem_res_inval = 0; 807 - res = platform_get_resource(pdev, IORESOURCE_MEM, 808 - PLAT_RESOURCE_TELEM_SSRAM_INDEX); 809 - if (!res) { 810 - dev_err(&pdev->dev, "Failed to get telemetry ssram resource\n"); 811 - ipcdev.telem_res_inval = 1; 812 - } else { 813 - ipcdev.telem_punit_ssram_base = res->start + 814 - TELEM_PUNIT_SSRAM_OFFSET; 815 - ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE; 816 - ipcdev.telem_pmc_ssram_base = res->start + 817 - TELEM_PMC_SSRAM_OFFSET; 818 - ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE; 819 - dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res); 820 - } 821 - 822 - return 0; 823 - } 824 - 825 - /** 826 - * intel_pmc_s0ix_counter_read() - Read S0ix residency. 827 - * @data: Out param that contains current S0ix residency count. 828 - * 829 - * Return: an error code or 0 on success. 830 - */ 831 - int intel_pmc_s0ix_counter_read(u64 *data) 832 - { 833 - u64 deep, shlw; 834 - 835 - if (!ipcdev.has_gcr_regs) 836 - return -EACCES; 837 - 838 - deep = gcr_data_readq(PMC_GCR_TELEM_DEEP_S0IX_REG); 839 - shlw = gcr_data_readq(PMC_GCR_TELEM_SHLW_S0IX_REG); 840 - 841 - *data = S0IX_RESIDENCY_IN_USECS(deep, shlw); 842 - 843 - return 0; 844 - } 845 - EXPORT_SYMBOL_GPL(intel_pmc_s0ix_counter_read); 846 - 847 - #ifdef CONFIG_ACPI 848 - static const struct acpi_device_id ipc_acpi_ids[] = { 849 - { "INT34D2", 0}, 850 - { } 851 - }; 852 - MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids); 853 - #endif 854 - 855 - static int ipc_plat_probe(struct platform_device *pdev) 856 - { 857 - int ret; 858 - 859 - ipcdev.dev = &pdev->dev; 860 - ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; 861 - init_completion(&ipcdev.cmd_complete); 862 - spin_lock_init(&ipcdev.gcr_lock); 863 - 864 - ipcdev.irq = platform_get_irq(pdev, 0); 865 - if (ipcdev.irq < 0) 866 - return -EINVAL; 867 - 868 - ret = ipc_plat_get_res(pdev); 869 - if (ret) { 870 - dev_err(&pdev->dev, "Failed to request resource\n"); 871 - return ret; 872 - } 873 - 874 - ret = ipc_create_pmc_devices(); 875 - if (ret) { 876 - dev_err(&pdev->dev, "Failed to create pmc devices\n"); 877 - return ret; 878 - } 879 - 880 - if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, 881 - "intel_pmc_ipc", &ipcdev)) { 882 - dev_err(&pdev->dev, "Failed to request irq\n"); 883 - ret = -EBUSY; 884 - goto err_irq; 885 - } 886 - 887 - ipcdev.has_gcr_regs = true; 888 - 889 - return 0; 890 - 891 - err_irq: 892 - platform_device_unregister(ipcdev.tco_dev); 893 - platform_device_unregister(ipcdev.punit_dev); 894 - platform_device_unregister(ipcdev.telemetry_dev); 895 - 896 - return ret; 897 - } 898 - 899 - static int ipc_plat_remove(struct platform_device *pdev) 900 - { 901 - devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); 902 - platform_device_unregister(ipcdev.tco_dev); 903 - platform_device_unregister(ipcdev.punit_dev); 904 - platform_device_unregister(ipcdev.telemetry_dev); 905 - ipcdev.dev = NULL; 906 - return 0; 907 - } 908 - 909 - static struct platform_driver ipc_plat_driver = { 910 - .remove = ipc_plat_remove, 911 - .probe = ipc_plat_probe, 912 - .driver = { 913 - .name = "pmc-ipc-plat", 914 - .acpi_match_table = ACPI_PTR(ipc_acpi_ids), 915 - .dev_groups = intel_ipc_groups, 916 - }, 917 - }; 918 - 919 - static int __init intel_pmc_ipc_init(void) 920 - { 921 - int ret; 922 - 923 - ret = platform_driver_register(&ipc_plat_driver); 924 - if (ret) { 925 - pr_err("Failed to register PMC ipc platform driver\n"); 926 - return ret; 927 - } 928 - ret = pci_register_driver(&ipc_pci_driver); 929 - if (ret) { 930 - pr_err("Failed to register PMC ipc pci driver\n"); 931 - platform_driver_unregister(&ipc_plat_driver); 932 - return ret; 933 - } 934 - return ret; 935 - } 936 - 937 - static void __exit intel_pmc_ipc_exit(void) 938 - { 939 - pci_unregister_driver(&ipc_pci_driver); 940 - platform_driver_unregister(&ipc_plat_driver); 941 - } 942 - 943 - MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>"); 944 - MODULE_DESCRIPTION("Intel PMC IPC driver"); 945 - MODULE_LICENSE("GPL v2"); 946 - 947 - /* Some modules are dependent on this, so init earlier */ 948 - fs_initcall(intel_pmc_ipc_init); 949 - module_exit(intel_pmc_ipc_exit);
+364 -111
drivers/platform/x86/intel_scu_ipc.c
··· 18 18 #include <linux/errno.h> 19 19 #include <linux/init.h> 20 20 #include <linux/interrupt.h> 21 - #include <linux/pci.h> 22 - #include <linux/pm.h> 23 - #include <linux/sfi.h> 21 + #include <linux/io.h> 22 + #include <linux/module.h> 23 + #include <linux/slab.h> 24 24 25 - #include <asm/intel-mid.h> 26 25 #include <asm/intel_scu_ipc.h> 27 26 28 27 /* IPC defines the following message types */ ··· 54 55 #define IPC_IOC 0x100 /* IPC command register IOC bit */ 55 56 56 57 struct intel_scu_ipc_dev { 57 - struct device *dev; 58 + struct device dev; 59 + struct resource mem; 60 + struct module *owner; 61 + int irq; 58 62 void __iomem *ipc_base; 59 63 struct completion cmd_complete; 60 - u8 irq_mode; 61 64 }; 62 - 63 - static struct intel_scu_ipc_dev ipcdev; /* Only one for now */ 64 65 65 66 #define IPC_STATUS 0x04 66 67 #define IPC_STATUS_IRQ BIT(2) ··· 77 78 /* Timeout in jiffies */ 78 79 #define IPC_TIMEOUT (3 * HZ) 79 80 81 + static struct intel_scu_ipc_dev *ipcdev; /* Only one for now */ 80 82 static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */ 83 + 84 + static struct class intel_scu_ipc_class = { 85 + .name = "intel_scu_ipc", 86 + .owner = THIS_MODULE, 87 + }; 88 + 89 + /** 90 + * intel_scu_ipc_dev_get() - Get SCU IPC instance 91 + * 92 + * The recommended new API takes SCU IPC instance as parameter and this 93 + * function can be called by driver to get the instance. This also makes 94 + * sure the driver providing the IPC functionality cannot be unloaded 95 + * while the caller has the instance. 96 + * 97 + * Call intel_scu_ipc_dev_put() to release the instance. 98 + * 99 + * Returns %NULL if SCU IPC is not currently available. 100 + */ 101 + struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void) 102 + { 103 + struct intel_scu_ipc_dev *scu = NULL; 104 + 105 + mutex_lock(&ipclock); 106 + if (ipcdev) { 107 + get_device(&ipcdev->dev); 108 + /* 109 + * Prevent the IPC provider from being unloaded while it 110 + * is being used. 111 + */ 112 + if (!try_module_get(ipcdev->owner)) 113 + put_device(&ipcdev->dev); 114 + else 115 + scu = ipcdev; 116 + } 117 + 118 + mutex_unlock(&ipclock); 119 + return scu; 120 + } 121 + EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_get); 122 + 123 + /** 124 + * intel_scu_ipc_dev_put() - Put SCU IPC instance 125 + * @scu: SCU IPC instance 126 + * 127 + * This function releases the SCU IPC instance retrieved from 128 + * intel_scu_ipc_dev_get() and allows the driver providing IPC to be 129 + * unloaded. 130 + */ 131 + void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu) 132 + { 133 + if (scu) { 134 + module_put(scu->owner); 135 + put_device(&scu->dev); 136 + } 137 + } 138 + EXPORT_SYMBOL_GPL(intel_scu_ipc_dev_put); 139 + 140 + struct intel_scu_ipc_devres { 141 + struct intel_scu_ipc_dev *scu; 142 + }; 143 + 144 + static void devm_intel_scu_ipc_dev_release(struct device *dev, void *res) 145 + { 146 + struct intel_scu_ipc_devres *dr = res; 147 + struct intel_scu_ipc_dev *scu = dr->scu; 148 + 149 + intel_scu_ipc_dev_put(scu); 150 + } 151 + 152 + /** 153 + * devm_intel_scu_ipc_dev_get() - Allocate managed SCU IPC device 154 + * @dev: Device requesting the SCU IPC device 155 + * 156 + * The recommended new API takes SCU IPC instance as parameter and this 157 + * function can be called by driver to get the instance. This also makes 158 + * sure the driver providing the IPC functionality cannot be unloaded 159 + * while the caller has the instance. 160 + * 161 + * Returns %NULL if SCU IPC is not currently available. 162 + */ 163 + struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev) 164 + { 165 + struct intel_scu_ipc_devres *dr; 166 + struct intel_scu_ipc_dev *scu; 167 + 168 + dr = devres_alloc(devm_intel_scu_ipc_dev_release, sizeof(*dr), GFP_KERNEL); 169 + if (!dr) 170 + return NULL; 171 + 172 + scu = intel_scu_ipc_dev_get(); 173 + if (!scu) { 174 + devres_free(dr); 175 + return NULL; 176 + } 177 + 178 + dr->scu = scu; 179 + devres_add(dev, dr); 180 + 181 + return scu; 182 + } 183 + EXPORT_SYMBOL_GPL(devm_intel_scu_ipc_dev_get); 81 184 82 185 /* 83 186 * Send ipc command ··· 244 143 usleep_range(50, 100); 245 144 } while (time_before(jiffies, end)); 246 145 247 - dev_err(scu->dev, "IPC timed out"); 248 146 return -ETIMEDOUT; 249 147 } 250 148 ··· 252 152 { 253 153 int status; 254 154 255 - if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) { 256 - dev_err(scu->dev, "IPC timed out\n"); 155 + if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) 257 156 return -ETIMEDOUT; 258 - } 259 157 260 158 status = ipc_read_status(scu); 261 159 if (status & IPC_STATUS_ERR) ··· 264 166 265 167 static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) 266 168 { 267 - return scu->irq_mode ? ipc_wait_for_interrupt(scu) : busy_loop(scu); 169 + return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); 268 170 } 269 171 270 172 /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ 271 - static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) 173 + static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 174 + u32 count, u32 op, u32 id) 272 175 { 273 - struct intel_scu_ipc_dev *scu = &ipcdev; 274 176 int nc; 275 177 u32 offset = 0; 276 178 int err; ··· 280 182 memset(cbuf, 0, sizeof(cbuf)); 281 183 282 184 mutex_lock(&ipclock); 283 - 284 - if (scu->dev == NULL) { 185 + if (!scu) 186 + scu = ipcdev; 187 + if (!scu) { 285 188 mutex_unlock(&ipclock); 286 189 return -ENODEV; 287 190 } ··· 321 222 } 322 223 323 224 /** 324 - * intel_scu_ipc_ioread8 - read a word via the SCU 225 + * intel_scu_ipc_dev_ioread8() - Read a byte via the SCU 226 + * @scu: Optional SCU IPC instance 325 227 * @addr: Register on SCU 326 228 * @data: Return pointer for read byte 327 229 * ··· 331 231 * 332 232 * This function may sleep. 333 233 */ 334 - int intel_scu_ipc_ioread8(u16 addr, u8 *data) 234 + int intel_scu_ipc_dev_ioread8(struct intel_scu_ipc_dev *scu, u16 addr, u8 *data) 335 235 { 336 - return pwr_reg_rdwr(&addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 236 + return pwr_reg_rdwr(scu, &addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 337 237 } 338 - EXPORT_SYMBOL(intel_scu_ipc_ioread8); 238 + EXPORT_SYMBOL(intel_scu_ipc_dev_ioread8); 339 239 340 240 /** 341 - * intel_scu_ipc_iowrite8 - write a byte via the SCU 241 + * intel_scu_ipc_dev_iowrite8() - Write a byte via the SCU 242 + * @scu: Optional SCU IPC instance 342 243 * @addr: Register on SCU 343 244 * @data: Byte to write 344 245 * ··· 348 247 * 349 248 * This function may sleep. 350 249 */ 351 - int intel_scu_ipc_iowrite8(u16 addr, u8 data) 250 + int intel_scu_ipc_dev_iowrite8(struct intel_scu_ipc_dev *scu, u16 addr, u8 data) 352 251 { 353 - return pwr_reg_rdwr(&addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 252 + return pwr_reg_rdwr(scu, &addr, &data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 354 253 } 355 - EXPORT_SYMBOL(intel_scu_ipc_iowrite8); 254 + EXPORT_SYMBOL(intel_scu_ipc_dev_iowrite8); 356 255 357 256 /** 358 - * intel_scu_ipc_readvv - read a set of registers 257 + * intel_scu_ipc_dev_readv() - Read a set of registers 258 + * @scu: Optional SCU IPC instance 359 259 * @addr: Register list 360 260 * @data: Bytes to return 361 261 * @len: Length of array ··· 368 266 * 369 267 * This function may sleep. 370 268 */ 371 - int intel_scu_ipc_readv(u16 *addr, u8 *data, int len) 269 + int intel_scu_ipc_dev_readv(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 270 + size_t len) 372 271 { 373 - return pwr_reg_rdwr(addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 272 + return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R); 374 273 } 375 - EXPORT_SYMBOL(intel_scu_ipc_readv); 274 + EXPORT_SYMBOL(intel_scu_ipc_dev_readv); 376 275 377 276 /** 378 - * intel_scu_ipc_writev - write a set of registers 277 + * intel_scu_ipc_dev_writev() - Write a set of registers 278 + * @scu: Optional SCU IPC instance 379 279 * @addr: Register list 380 280 * @data: Bytes to write 381 281 * @len: Length of array ··· 389 285 * 390 286 * This function may sleep. 391 287 */ 392 - int intel_scu_ipc_writev(u16 *addr, u8 *data, int len) 288 + int intel_scu_ipc_dev_writev(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, 289 + size_t len) 393 290 { 394 - return pwr_reg_rdwr(addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 291 + return pwr_reg_rdwr(scu, addr, data, len, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W); 395 292 } 396 - EXPORT_SYMBOL(intel_scu_ipc_writev); 293 + EXPORT_SYMBOL(intel_scu_ipc_dev_writev); 397 294 398 295 /** 399 - * intel_scu_ipc_update_register - r/m/w a register 296 + * intel_scu_ipc_dev_update() - Update a register 297 + * @scu: Optional SCU IPC instance 400 298 * @addr: Register address 401 - * @bits: Bits to update 299 + * @data: Bits to update 402 300 * @mask: Mask of bits to update 403 301 * 404 302 * Read-modify-write power control unit register. The first data argument ··· 411 305 * This function may sleep. Locking between SCU accesses is handled 412 306 * for the caller. 413 307 */ 414 - int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask) 308 + int intel_scu_ipc_dev_update(struct intel_scu_ipc_dev *scu, u16 addr, u8 data, 309 + u8 mask) 415 310 { 416 - u8 data[2] = { bits, mask }; 417 - return pwr_reg_rdwr(&addr, data, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); 311 + u8 tmp[2] = { data, mask }; 312 + return pwr_reg_rdwr(scu, &addr, tmp, 1, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_M); 418 313 } 419 - EXPORT_SYMBOL(intel_scu_ipc_update_register); 314 + EXPORT_SYMBOL(intel_scu_ipc_dev_update); 420 315 421 316 /** 422 - * intel_scu_ipc_simple_command - send a simple command 317 + * intel_scu_ipc_dev_simple_command() - Send a simple command 318 + * @scu: Optional SCU IPC instance 423 319 * @cmd: Command 424 320 * @sub: Sub type 425 321 * ··· 432 324 * This function may sleep. Locking for SCU accesses is handled for the 433 325 * caller. 434 326 */ 435 - int intel_scu_ipc_simple_command(int cmd, int sub) 327 + int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, 328 + int sub) 436 329 { 437 - struct intel_scu_ipc_dev *scu = &ipcdev; 330 + u32 cmdval; 438 331 int err; 439 332 440 333 mutex_lock(&ipclock); 441 - if (scu->dev == NULL) { 334 + if (!scu) 335 + scu = ipcdev; 336 + if (!scu) { 442 337 mutex_unlock(&ipclock); 443 338 return -ENODEV; 444 339 } 445 - ipc_command(scu, sub << 12 | cmd); 340 + scu = ipcdev; 341 + cmdval = sub << 12 | cmd; 342 + ipc_command(scu, cmdval); 446 343 err = intel_scu_ipc_check_status(scu); 447 344 mutex_unlock(&ipclock); 345 + if (err) 346 + dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 448 347 return err; 449 348 } 450 - EXPORT_SYMBOL(intel_scu_ipc_simple_command); 349 + EXPORT_SYMBOL(intel_scu_ipc_dev_simple_command); 451 350 452 351 /** 453 - * intel_scu_ipc_command - command with data 352 + * intel_scu_ipc_command_with_size() - Command with data 353 + * @scu: Optional SCU IPC instance 454 354 * @cmd: Command 455 355 * @sub: Sub type 456 356 * @in: Input data 457 - * @inlen: Input length in dwords 357 + * @inlen: Input length in bytes 358 + * @size: Input size written to the IPC command register in whatever 359 + * units (dword, byte) the particular firmware requires. Normally 360 + * should be the same as @inlen. 458 361 * @out: Output data 459 - * @outlen: Output length in dwords 362 + * @outlen: Output length in bytes 460 363 * 461 364 * Issue a command to the SCU which involves data transfers. Do the 462 365 * data copies under the lock but leave it for the caller to interpret. 463 366 */ 464 - int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, 465 - u32 *out, int outlen) 367 + int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, 368 + int sub, const void *in, size_t inlen, 369 + size_t size, void *out, size_t outlen) 466 370 { 467 - struct intel_scu_ipc_dev *scu = &ipcdev; 371 + size_t outbuflen = DIV_ROUND_UP(outlen, sizeof(u32)); 372 + size_t inbuflen = DIV_ROUND_UP(inlen, sizeof(u32)); 373 + u32 cmdval, inbuf[4] = {}; 468 374 int i, err; 469 375 376 + if (inbuflen > 4 || outbuflen > 4) 377 + return -EINVAL; 378 + 470 379 mutex_lock(&ipclock); 471 - if (scu->dev == NULL) { 380 + if (!scu) 381 + scu = ipcdev; 382 + if (!scu) { 472 383 mutex_unlock(&ipclock); 473 384 return -ENODEV; 474 385 } 475 386 476 - for (i = 0; i < inlen; i++) 477 - ipc_data_writel(scu, *in++, 4 * i); 387 + memcpy(inbuf, in, inlen); 388 + for (i = 0; i < inbuflen; i++) 389 + ipc_data_writel(scu, inbuf[i], 4 * i); 478 390 479 - ipc_command(scu, (inlen << 16) | (sub << 12) | cmd); 391 + cmdval = (size << 16) | (sub << 12) | cmd; 392 + ipc_command(scu, cmdval); 480 393 err = intel_scu_ipc_check_status(scu); 481 394 482 395 if (!err) { 483 - for (i = 0; i < outlen; i++) 484 - *out++ = ipc_data_readl(scu, 4 * i); 396 + u32 outbuf[4] = {}; 397 + 398 + for (i = 0; i < outbuflen; i++) 399 + outbuf[i] = ipc_data_readl(scu, 4 * i); 400 + 401 + memcpy(out, outbuf, outlen); 485 402 } 486 403 487 404 mutex_unlock(&ipclock); 405 + if (err) 406 + dev_err(&scu->dev, "IPC command %#x failed with %d\n", cmdval, err); 488 407 return err; 489 408 } 490 - EXPORT_SYMBOL(intel_scu_ipc_command); 409 + EXPORT_SYMBOL(intel_scu_ipc_dev_command_with_size); 491 410 492 411 /* 493 412 * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1 ··· 534 399 return IRQ_HANDLED; 535 400 } 536 401 537 - /** 538 - * ipc_probe - probe an Intel SCU IPC 539 - * @pdev: the PCI device matching 540 - * @id: entry in the match table 541 - * 542 - * Enable and install an intel SCU IPC. This appears in the PCI space 543 - * but uses some hard coded addresses as well. 544 - */ 545 - static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 402 + static void intel_scu_ipc_release(struct device *dev) 546 403 { 547 - int err; 548 - struct intel_scu_ipc_dev *scu = &ipcdev; 404 + struct intel_scu_ipc_dev *scu; 549 405 550 - if (scu->dev) /* We support only one SCU */ 551 - return -EBUSY; 552 - 553 - err = pcim_enable_device(pdev); 554 - if (err) 555 - return err; 556 - 557 - err = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); 558 - if (err) 559 - return err; 560 - 561 - init_completion(&scu->cmd_complete); 562 - 563 - scu->ipc_base = pcim_iomap_table(pdev)[0]; 564 - 565 - err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc", 566 - scu); 567 - if (err) 568 - return err; 569 - 570 - /* Assign device at last */ 571 - scu->dev = &pdev->dev; 572 - 573 - intel_scu_devices_create(); 574 - 575 - pci_set_drvdata(pdev, scu); 576 - return 0; 406 + scu = container_of(dev, struct intel_scu_ipc_dev, dev); 407 + if (scu->irq > 0) 408 + free_irq(scu->irq, scu); 409 + iounmap(scu->ipc_base); 410 + release_mem_region(scu->mem.start, resource_size(&scu->mem)); 411 + kfree(scu); 577 412 } 578 413 579 - static const struct pci_device_id pci_ids[] = { 580 - { PCI_VDEVICE(INTEL, 0x080e) }, 581 - { PCI_VDEVICE(INTEL, 0x08ea) }, 582 - { PCI_VDEVICE(INTEL, 0x11a0) }, 583 - {} 584 - }; 414 + /** 415 + * __intel_scu_ipc_register() - Register SCU IPC device 416 + * @parent: Parent device 417 + * @scu_data: Data used to configure SCU IPC 418 + * @owner: Module registering the SCU IPC device 419 + * 420 + * Call this function to register SCU IPC mechanism under @parent. 421 + * Returns pointer to the new SCU IPC device or ERR_PTR() in case of 422 + * failure. The caller may use the returned instance if it needs to do 423 + * SCU IPC calls itself. 424 + */ 425 + struct intel_scu_ipc_dev * 426 + __intel_scu_ipc_register(struct device *parent, 427 + const struct intel_scu_ipc_data *scu_data, 428 + struct module *owner) 429 + { 430 + int err; 431 + struct intel_scu_ipc_dev *scu; 432 + void __iomem *ipc_base; 585 433 586 - static struct pci_driver ipc_driver = { 587 - .driver = { 588 - .suppress_bind_attrs = true, 589 - }, 590 - .name = "intel_scu_ipc", 591 - .id_table = pci_ids, 592 - .probe = ipc_probe, 593 - }; 594 - builtin_pci_driver(ipc_driver); 434 + mutex_lock(&ipclock); 435 + /* We support only one IPC */ 436 + if (ipcdev) { 437 + err = -EBUSY; 438 + goto err_unlock; 439 + } 440 + 441 + scu = kzalloc(sizeof(*scu), GFP_KERNEL); 442 + if (!scu) { 443 + err = -ENOMEM; 444 + goto err_unlock; 445 + } 446 + 447 + scu->owner = owner; 448 + scu->dev.parent = parent; 449 + scu->dev.class = &intel_scu_ipc_class; 450 + scu->dev.release = intel_scu_ipc_release; 451 + dev_set_name(&scu->dev, "intel_scu_ipc"); 452 + 453 + if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem), 454 + "intel_scu_ipc")) { 455 + err = -EBUSY; 456 + goto err_free; 457 + } 458 + 459 + ipc_base = ioremap(scu_data->mem.start, resource_size(&scu_data->mem)); 460 + if (!ipc_base) { 461 + err = -ENOMEM; 462 + goto err_release; 463 + } 464 + 465 + scu->ipc_base = ipc_base; 466 + scu->mem = scu_data->mem; 467 + scu->irq = scu_data->irq; 468 + init_completion(&scu->cmd_complete); 469 + 470 + if (scu->irq > 0) { 471 + err = request_irq(scu->irq, ioc, 0, "intel_scu_ipc", scu); 472 + if (err) 473 + goto err_unmap; 474 + } 475 + 476 + /* 477 + * After this point intel_scu_ipc_release() takes care of 478 + * releasing the SCU IPC resources once refcount drops to zero. 479 + */ 480 + err = device_register(&scu->dev); 481 + if (err) { 482 + put_device(&scu->dev); 483 + goto err_unlock; 484 + } 485 + 486 + /* Assign device at last */ 487 + ipcdev = scu; 488 + mutex_unlock(&ipclock); 489 + 490 + return scu; 491 + 492 + err_unmap: 493 + iounmap(ipc_base); 494 + err_release: 495 + release_mem_region(scu_data->mem.start, resource_size(&scu_data->mem)); 496 + err_free: 497 + kfree(scu); 498 + err_unlock: 499 + mutex_unlock(&ipclock); 500 + 501 + return ERR_PTR(err); 502 + } 503 + EXPORT_SYMBOL_GPL(__intel_scu_ipc_register); 504 + 505 + /** 506 + * intel_scu_ipc_unregister() - Unregister SCU IPC 507 + * @scu: SCU IPC handle 508 + * 509 + * This unregisters the SCU IPC device and releases the acquired 510 + * resources once the refcount goes to zero. 511 + */ 512 + void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu) 513 + { 514 + mutex_lock(&ipclock); 515 + if (!WARN_ON(!ipcdev)) { 516 + ipcdev = NULL; 517 + device_unregister(&scu->dev); 518 + } 519 + mutex_unlock(&ipclock); 520 + } 521 + EXPORT_SYMBOL_GPL(intel_scu_ipc_unregister); 522 + 523 + static void devm_intel_scu_ipc_unregister(struct device *dev, void *res) 524 + { 525 + struct intel_scu_ipc_devres *dr = res; 526 + struct intel_scu_ipc_dev *scu = dr->scu; 527 + 528 + intel_scu_ipc_unregister(scu); 529 + } 530 + 531 + /** 532 + * __devm_intel_scu_ipc_register() - Register managed SCU IPC device 533 + * @parent: Parent device 534 + * @scu_data: Data used to configure SCU IPC 535 + * @owner: Module registering the SCU IPC device 536 + * 537 + * Call this function to register managed SCU IPC mechanism under 538 + * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in 539 + * case of failure. The caller may use the returned instance if it needs 540 + * to do SCU IPC calls itself. 541 + */ 542 + struct intel_scu_ipc_dev * 543 + __devm_intel_scu_ipc_register(struct device *parent, 544 + const struct intel_scu_ipc_data *scu_data, 545 + struct module *owner) 546 + { 547 + struct intel_scu_ipc_devres *dr; 548 + struct intel_scu_ipc_dev *scu; 549 + 550 + dr = devres_alloc(devm_intel_scu_ipc_unregister, sizeof(*dr), GFP_KERNEL); 551 + if (!dr) 552 + return NULL; 553 + 554 + scu = __intel_scu_ipc_register(parent, scu_data, owner); 555 + if (IS_ERR(scu)) { 556 + devres_free(dr); 557 + return scu; 558 + } 559 + 560 + dr->scu = scu; 561 + devres_add(parent, dr); 562 + 563 + return scu; 564 + } 565 + EXPORT_SYMBOL_GPL(__devm_intel_scu_ipc_register); 566 + 567 + static int __init intel_scu_ipc_init(void) 568 + { 569 + return class_register(&intel_scu_ipc_class); 570 + } 571 + subsys_initcall(intel_scu_ipc_init); 572 + 573 + static void __exit intel_scu_ipc_exit(void) 574 + { 575 + class_unregister(&intel_scu_ipc_class); 576 + } 577 + module_exit(intel_scu_ipc_exit);
+39 -4
drivers/platform/x86/intel_scu_ipcutil.c
··· 22 22 23 23 static int major; 24 24 25 + struct intel_scu_ipc_dev *scu; 26 + static DEFINE_MUTEX(scu_lock); 27 + 25 28 /* IOCTL commands */ 26 29 #define INTE_SCU_IPC_REGISTER_READ 0 27 30 #define INTE_SCU_IPC_REGISTER_WRITE 1 ··· 55 52 56 53 switch (cmd) { 57 54 case INTE_SCU_IPC_REGISTER_READ: 58 - return intel_scu_ipc_readv(data->addr, data->data, count); 55 + return intel_scu_ipc_dev_readv(scu, data->addr, data->data, count); 59 56 case INTE_SCU_IPC_REGISTER_WRITE: 60 - return intel_scu_ipc_writev(data->addr, data->data, count); 57 + return intel_scu_ipc_dev_writev(scu, data->addr, data->data, count); 61 58 case INTE_SCU_IPC_REGISTER_UPDATE: 62 - return intel_scu_ipc_update_register(data->addr[0], 63 - data->data[0], data->mask); 59 + return intel_scu_ipc_dev_update(scu, data->addr[0], data->data[0], 60 + data->mask); 64 61 default: 65 62 return -ENOTTY; 66 63 } ··· 94 91 return 0; 95 92 } 96 93 94 + static int scu_ipc_open(struct inode *inode, struct file *file) 95 + { 96 + int ret = 0; 97 + 98 + /* Only single open at the time */ 99 + mutex_lock(&scu_lock); 100 + if (scu) { 101 + ret = -EBUSY; 102 + goto unlock; 103 + } 104 + 105 + scu = intel_scu_ipc_dev_get(); 106 + if (!scu) 107 + ret = -ENODEV; 108 + 109 + unlock: 110 + mutex_unlock(&scu_lock); 111 + return ret; 112 + } 113 + 114 + static int scu_ipc_release(struct inode *inode, struct file *file) 115 + { 116 + mutex_lock(&scu_lock); 117 + intel_scu_ipc_dev_put(scu); 118 + scu = NULL; 119 + mutex_unlock(&scu_lock); 120 + 121 + return 0; 122 + } 123 + 97 124 static const struct file_operations scu_ipc_fops = { 98 125 .unlocked_ioctl = scu_ipc_ioctl, 126 + .open = scu_ipc_open, 127 + .release = scu_ipc_release, 99 128 }; 100 129 101 130 static int __init ipc_module_init(void)
+68
drivers/platform/x86/intel_scu_pcidrv.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * PCI driver for the Intel SCU. 4 + * 5 + * Copyright (C) 2008-2010, 2015, 2020 Intel Corporation 6 + * Authors: Sreedhara DS (sreedhara.ds@intel.com) 7 + * Mika Westerberg <mika.westerberg@linux.intel.com> 8 + */ 9 + 10 + #include <linux/errno.h> 11 + #include <linux/init.h> 12 + #include <linux/pci.h> 13 + 14 + #include <asm/intel-mid.h> 15 + #include <asm/intel_scu_ipc.h> 16 + 17 + static int intel_scu_pci_probe(struct pci_dev *pdev, 18 + const struct pci_device_id *id) 19 + { 20 + void (*setup_fn)(void) = (void (*)(void))id->driver_data; 21 + struct intel_scu_ipc_data scu_data = {}; 22 + struct intel_scu_ipc_dev *scu; 23 + int ret; 24 + 25 + ret = pcim_enable_device(pdev); 26 + if (ret) 27 + return ret; 28 + 29 + scu_data.mem = pdev->resource[0]; 30 + scu_data.irq = pdev->irq; 31 + 32 + scu = intel_scu_ipc_register(&pdev->dev, &scu_data); 33 + if (IS_ERR(scu)) 34 + return PTR_ERR(scu); 35 + 36 + if (setup_fn) 37 + setup_fn(); 38 + return 0; 39 + } 40 + 41 + static void intel_mid_scu_setup(void) 42 + { 43 + intel_scu_devices_create(); 44 + } 45 + 46 + static const struct pci_device_id pci_ids[] = { 47 + { PCI_VDEVICE(INTEL, 0x080e), 48 + .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, 49 + { PCI_VDEVICE(INTEL, 0x08ea), 50 + .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, 51 + { PCI_VDEVICE(INTEL, 0x0a94) }, 52 + { PCI_VDEVICE(INTEL, 0x11a0), 53 + .driver_data = (kernel_ulong_t)intel_mid_scu_setup }, 54 + { PCI_VDEVICE(INTEL, 0x1a94) }, 55 + { PCI_VDEVICE(INTEL, 0x5a94) }, 56 + {} 57 + }; 58 + 59 + static struct pci_driver intel_scu_pci_driver = { 60 + .driver = { 61 + .suppress_bind_attrs = true, 62 + }, 63 + .name = "intel_scu", 64 + .id_table = pci_ids, 65 + .probe = intel_scu_pci_probe, 66 + }; 67 + 68 + builtin_pci_driver(intel_scu_pci_driver);
+6 -11
drivers/platform/x86/intel_telemetry_core.c
··· 353 353 EXPORT_SYMBOL_GPL(telemetry_clear_pltdata); 354 354 355 355 /** 356 - * telemetry_pltconfig_valid() - Checkif platform config is valid 356 + * telemetry_get_pltdata() - Return telemetry platform config 357 357 * 358 - * Usage by other than telemetry module is invalid 359 - * 360 - * Return: 0 success, < 0 for failure 358 + * May be used by other telemetry modules to get platform specific 359 + * configuration. 361 360 */ 362 - int telemetry_pltconfig_valid(void) 361 + struct telemetry_plt_config *telemetry_get_pltdata(void) 363 362 { 364 - if (telm_core_conf.plt_config) 365 - return 0; 366 - 367 - else 368 - return -EINVAL; 363 + return telm_core_conf.plt_config; 369 364 } 370 - EXPORT_SYMBOL_GPL(telemetry_pltconfig_valid); 365 + EXPORT_SYMBOL_GPL(telemetry_get_pltdata); 371 366 372 367 static inline int telemetry_get_pssevtname(enum telemetry_unit telem_unit, 373 368 const char **name, int len)
+9 -6
drivers/platform/x86/intel_telemetry_debugfs.c
··· 15 15 */ 16 16 #include <linux/debugfs.h> 17 17 #include <linux/device.h> 18 + #include <linux/mfd/intel_pmc_bxt.h> 18 19 #include <linux/module.h> 19 20 #include <linux/pci.h> 20 21 #include <linux/seq_file.h> ··· 23 22 24 23 #include <asm/cpu_device_id.h> 25 24 #include <asm/intel-family.h> 26 - #include <asm/intel_pmc_ipc.h> 27 25 #include <asm/intel_telemetry.h> 28 26 29 27 #define DRIVER_NAME "telemetry_soc_debugfs" ··· 647 647 648 648 static int telem_s0ix_res_get(void *data, u64 *val) 649 649 { 650 + struct telemetry_plt_config *plt_config = telemetry_get_pltdata(); 650 651 u64 s0ix_total_res; 651 652 int ret; 652 653 653 - ret = intel_pmc_s0ix_counter_read(&s0ix_total_res); 654 + ret = intel_pmc_s0ix_counter_read(plt_config->pmc, &s0ix_total_res); 654 655 if (ret) { 655 656 pr_err("Failed to read S0ix residency"); 656 657 return ret; ··· 838 837 */ 839 838 if (suspend_shlw_ctr_exit == suspend_shlw_ctr_temp && 840 839 suspend_deep_ctr_exit == suspend_deep_ctr_temp) { 841 - ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_SHLW_S0IX_REG, 840 + struct telemetry_plt_config *plt_config = telemetry_get_pltdata(); 841 + struct intel_pmc_dev *pmc = plt_config->pmc; 842 + 843 + ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_SHLW_S0IX_REG, 842 844 &suspend_shlw_res_exit); 843 845 if (ret < 0) 844 846 goto out; 845 847 846 - ret = intel_pmc_gcr_read64(PMC_GCR_TELEM_DEEP_S0IX_REG, 848 + ret = intel_pmc_gcr_read64(pmc, PMC_GCR_TELEM_DEEP_S0IX_REG, 847 849 &suspend_deep_res_exit); 848 850 if (ret < 0) 849 851 goto out; ··· 914 910 915 911 debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data; 916 912 917 - err = telemetry_pltconfig_valid(); 918 - if (err < 0) { 913 + if (!telemetry_get_pltdata()) { 919 914 pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n"); 920 915 return -ENODEV; 921 916 }
+48 -49
drivers/platform/x86/intel_telemetry_pltdrv.c
··· 15 15 16 16 #include <asm/cpu_device_id.h> 17 17 #include <asm/intel-family.h> 18 - #include <asm/intel_pmc_ipc.h> 19 18 #include <asm/intel_punit_ipc.h> 20 19 #include <asm/intel_telemetry.h> 21 20 ··· 34 35 #define TELEM_SSRAM_STARTTIME_OFFSET 8 35 36 #define TELEM_SSRAM_EVTLOG_OFFSET 16 36 37 38 + #define IOSS_TELEM 0xeb 37 39 #define IOSS_TELEM_EVENT_READ 0x0 38 40 #define IOSS_TELEM_EVENT_WRITE 0x1 39 41 #define IOSS_TELEM_INFO_READ 0x2 ··· 42 42 #define IOSS_TELEM_TRACE_CTL_WRITE 0x6 43 43 #define IOSS_TELEM_EVENT_CTL_READ 0x7 44 44 #define IOSS_TELEM_EVENT_CTL_WRITE 0x8 45 - #define IOSS_TELEM_EVT_CTRL_WRITE_SIZE 0x4 46 - #define IOSS_TELEM_READ_WORD 0x1 47 - #define IOSS_TELEM_WRITE_FOURBYTES 0x4 48 45 #define IOSS_TELEM_EVT_WRITE_SIZE 0x3 49 46 50 47 #define TELEM_INFO_SRAMEVTS_MASK 0xFF00 ··· 247 250 static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index) 248 251 { 249 252 u32 write_buf; 250 - int ret; 251 253 252 254 write_buf = evt_id | TELEM_EVENT_ENABLE; 253 255 write_buf <<= BITS_PER_BYTE; 254 256 write_buf |= index; 255 257 256 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 257 - IOSS_TELEM_EVENT_WRITE, (u8 *)&write_buf, 258 - IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0); 259 - 260 - return ret; 258 + return intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 259 + IOSS_TELEM_EVENT_WRITE, &write_buf, 260 + IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0); 261 261 } 262 262 263 263 static inline int telemetry_plt_config_pss_event(u32 evt_id, int index) ··· 272 278 static int telemetry_setup_iossevtconfig(struct telemetry_evtconfig evtconfig, 273 279 enum telemetry_action action) 274 280 { 281 + struct intel_scu_ipc_dev *scu = telm_conf->scu; 275 282 u8 num_ioss_evts, ioss_period; 276 283 int ret, index, idx; 277 284 u32 *ioss_evtmap; ··· 283 288 ioss_evtmap = evtconfig.evtmap; 284 289 285 290 /* Get telemetry EVENT CTL */ 286 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 291 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 287 292 IOSS_TELEM_EVENT_CTL_READ, NULL, 0, 288 - &telem_ctrl, IOSS_TELEM_READ_WORD); 293 + &telem_ctrl, sizeof(telem_ctrl)); 289 294 if (ret) { 290 295 pr_err("IOSS TELEM_CTRL Read Failed\n"); 291 296 return ret; ··· 294 299 /* Disable Telemetry */ 295 300 TELEM_DISABLE(telem_ctrl); 296 301 297 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 298 - IOSS_TELEM_EVENT_CTL_WRITE, 299 - (u8 *)&telem_ctrl, 300 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, 301 - NULL, 0); 302 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 303 + IOSS_TELEM_EVENT_CTL_WRITE, &telem_ctrl, 304 + sizeof(telem_ctrl), NULL, 0); 302 305 if (ret) { 303 306 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 304 307 return ret; ··· 308 315 /* Clear All Events */ 309 316 TELEM_CLEAR_EVENTS(telem_ctrl); 310 317 311 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 318 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 312 319 IOSS_TELEM_EVENT_CTL_WRITE, 313 - (u8 *)&telem_ctrl, 314 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, 320 + &telem_ctrl, sizeof(telem_ctrl), 315 321 NULL, 0); 316 322 if (ret) { 317 323 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); ··· 336 344 /* Clear All Events */ 337 345 TELEM_CLEAR_EVENTS(telem_ctrl); 338 346 339 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 347 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 340 348 IOSS_TELEM_EVENT_CTL_WRITE, 341 - (u8 *)&telem_ctrl, 342 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, 349 + &telem_ctrl, sizeof(telem_ctrl), 343 350 NULL, 0); 344 351 if (ret) { 345 352 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); ··· 387 396 TELEM_ENABLE_PERIODIC(telem_ctrl); 388 397 telem_ctrl |= ioss_period; 389 398 390 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 399 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 391 400 IOSS_TELEM_EVENT_CTL_WRITE, 392 - (u8 *)&telem_ctrl, 393 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, NULL, 0); 401 + &telem_ctrl, sizeof(telem_ctrl), NULL, 0); 394 402 if (ret) { 395 403 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n"); 396 404 return ret; ··· 576 586 u32 read_buf, events, event_regs; 577 587 int ret; 578 588 579 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_INFO_READ, 580 - NULL, 0, &read_buf, IOSS_TELEM_READ_WORD); 589 + ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 590 + IOSS_TELEM_INFO_READ, NULL, 0, 591 + &read_buf, sizeof(read_buf)); 581 592 if (ret) { 582 593 dev_err(&pdev->dev, "IOSS TELEM_INFO Read Failed\n"); 583 594 return ret; ··· 672 681 673 682 mutex_lock(&(telm_conf->telem_lock)); 674 683 if (ioss_period) { 684 + struct intel_scu_ipc_dev *scu = telm_conf->scu; 685 + 675 686 if (TELEM_SAMPLE_PERIOD_INVALID(ioss_period)) { 676 687 pr_err("IOSS Sampling Period Out of Range\n"); 677 688 ret = -EINVAL; ··· 681 688 } 682 689 683 690 /* Get telemetry EVENT CTL */ 684 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 691 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 685 692 IOSS_TELEM_EVENT_CTL_READ, NULL, 0, 686 - &telem_ctrl, IOSS_TELEM_READ_WORD); 693 + &telem_ctrl, sizeof(telem_ctrl)); 687 694 if (ret) { 688 695 pr_err("IOSS TELEM_CTRL Read Failed\n"); 689 696 goto out; ··· 692 699 /* Disable Telemetry */ 693 700 TELEM_DISABLE(telem_ctrl); 694 701 695 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 696 - IOSS_TELEM_EVENT_CTL_WRITE, 697 - (u8 *)&telem_ctrl, 698 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, 699 - NULL, 0); 702 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 703 + IOSS_TELEM_EVENT_CTL_WRITE, 704 + &telem_ctrl, sizeof(telem_ctrl), 705 + NULL, 0); 700 706 if (ret) { 701 707 pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n"); 702 708 goto out; ··· 707 715 TELEM_ENABLE_PERIODIC(telem_ctrl); 708 716 telem_ctrl |= ioss_period; 709 717 710 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 711 - IOSS_TELEM_EVENT_CTL_WRITE, 712 - (u8 *)&telem_ctrl, 713 - IOSS_TELEM_EVT_CTRL_WRITE_SIZE, 714 - NULL, 0); 718 + ret = intel_scu_ipc_dev_command(scu, IOSS_TELEM, 719 + IOSS_TELEM_EVENT_CTL_WRITE, 720 + &telem_ctrl, sizeof(telem_ctrl), 721 + NULL, 0); 715 722 if (ret) { 716 723 pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n"); 717 724 goto out; ··· 1005 1014 break; 1006 1015 1007 1016 case TELEM_IOSS: 1008 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 1009 - IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp, 1010 - IOSS_TELEM_READ_WORD); 1017 + ret = intel_scu_ipc_dev_command(telm_conf->scu, 1018 + IOSS_TELEM, IOSS_TELEM_TRACE_CTL_READ, 1019 + NULL, 0, &temp, sizeof(temp)); 1011 1020 if (ret) { 1012 1021 pr_err("IOSS TRACE_CTL Read Failed\n"); 1013 1022 goto out; ··· 1059 1068 break; 1060 1069 1061 1070 case TELEM_IOSS: 1062 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 1063 - IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp, 1064 - IOSS_TELEM_READ_WORD); 1071 + ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 1072 + IOSS_TELEM_TRACE_CTL_READ, 1073 + NULL, 0, &temp, sizeof(temp)); 1065 1074 if (ret) { 1066 1075 pr_err("IOSS TRACE_CTL Read Failed\n"); 1067 1076 goto out; ··· 1070 1079 TELEM_CLEAR_VERBOSITY_BITS(temp); 1071 1080 TELEM_SET_VERBOSITY_BITS(temp, verbosity); 1072 1081 1073 - ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, 1074 - IOSS_TELEM_TRACE_CTL_WRITE, (u8 *)&temp, 1075 - IOSS_TELEM_WRITE_FOURBYTES, NULL, 0); 1082 + ret = intel_scu_ipc_dev_command(telm_conf->scu, IOSS_TELEM, 1083 + IOSS_TELEM_TRACE_CTL_WRITE, 1084 + &temp, sizeof(temp), NULL, 0); 1076 1085 if (ret) { 1077 1086 pr_err("IOSS TRACE_CTL Verbosity Set Failed\n"); 1078 1087 goto out; ··· 1115 1124 1116 1125 telm_conf = (struct telemetry_plt_config *)id->driver_data; 1117 1126 1127 + telm_conf->pmc = dev_get_drvdata(pdev->dev.parent); 1128 + 1118 1129 mem = devm_platform_ioremap_resource(pdev, 0); 1119 1130 if (IS_ERR(mem)) 1120 1131 return PTR_ERR(mem); ··· 1128 1135 return PTR_ERR(mem); 1129 1136 1130 1137 telm_conf->ioss_config.regmap = mem; 1138 + 1139 + telm_conf->scu = devm_intel_scu_ipc_dev_get(&pdev->dev); 1140 + if (!telm_conf->scu) { 1141 + ret = -EPROBE_DEFER; 1142 + goto out; 1143 + } 1131 1144 1132 1145 mutex_init(&telm_conf->telem_lock); 1133 1146 mutex_init(&telm_conf->telem_trace_lock);
+1 -1
drivers/usb/typec/mux/Kconfig
··· 11 11 12 12 config TYPEC_MUX_INTEL_PMC 13 13 tristate "Intel PMC mux control" 14 - depends on INTEL_PMC_IPC 14 + depends on INTEL_SCU_IPC 15 15 select USB_ROLE_SWITCH 16 16 help 17 17 Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can
+8 -4
drivers/usb/typec/mux/intel_pmc_mux.c
··· 15 15 #include <linux/usb/typec_dp.h> 16 16 #include <linux/usb/typec_tbt.h> 17 17 18 - #include <asm/intel_pmc_ipc.h> 18 + #include <asm/intel_scu_ipc.h> 19 19 20 20 #define PMC_USBC_CMD 0xa7 21 21 ··· 96 96 struct pmc_usb { 97 97 u8 num_ports; 98 98 struct device *dev; 99 + struct intel_scu_ipc_dev *ipc; 99 100 struct pmc_usb_port *port; 100 101 }; 101 102 ··· 108 107 * Error bit will always be 0 with the USBC command. 109 108 * Status can be checked from the response message. 110 109 */ 111 - intel_pmc_ipc_command(PMC_USBC_CMD, 0, msg, len, 112 - (void *)response, 1); 113 - 110 + intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg, len, 111 + response, sizeof(response)); 114 112 if (response[2]) { 115 113 if (response[2] & BIT(1)) 116 114 return -EIO; ··· 369 369 sizeof(struct pmc_usb_port), GFP_KERNEL); 370 370 if (!pmc->port) 371 371 return -ENOMEM; 372 + 373 + pmc->ipc = devm_intel_scu_ipc_dev_get(&pdev->dev); 374 + if (!pmc->ipc) 375 + return -ENODEV; 372 376 373 377 pmc->dev = &pdev->dev; 374 378
+1 -1
drivers/usb/typec/tcpm/Kconfig
··· 41 41 config TYPEC_WCOVE 42 42 tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver" 43 43 depends on ACPI 44 + depends on MFD_INTEL_PMC_BXT 44 45 depends on INTEL_SOC_PMIC 45 - depends on INTEL_PMC_IPC 46 46 depends on BXT_WC_PMIC_OPREGION 47 47 help 48 48 This driver adds support for USB Type-C on Intel Broxton platforms
+20 -7
drivers/watchdog/iTCO_wdt.c
··· 64 64 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 65 65 #include <linux/io.h> /* For inb/outb/... */ 66 66 #include <linux/platform_data/itco_wdt.h> 67 + #include <linux/mfd/intel_pmc_bxt.h> 67 68 68 69 #include "iTCO_vendor.h" 69 70 ··· 234 233 return val != newval ? -EIO : 0; 235 234 } 236 235 237 - static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p, 238 - struct itco_wdt_platform_data *pdata) 236 + static int update_no_reboot_bit_pmc(void *priv, bool set) 239 237 { 240 - if (pdata->update_no_reboot_bit) { 241 - p->update_no_reboot_bit = pdata->update_no_reboot_bit; 242 - p->no_reboot_priv = pdata->no_reboot_priv; 238 + struct intel_pmc_dev *pmc = priv; 239 + u32 bits = PMC_CFG_NO_REBOOT_EN; 240 + u32 value = set ? bits : 0; 241 + 242 + return intel_pmc_gcr_update(pmc, PMC_GCR_PMC_CFG_REG, bits, value); 243 + } 244 + 245 + static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p, 246 + struct platform_device *pdev, 247 + struct itco_wdt_platform_data *pdata) 248 + { 249 + if (pdata->no_reboot_use_pmc) { 250 + struct intel_pmc_dev *pmc = dev_get_drvdata(pdev->dev.parent); 251 + 252 + p->update_no_reboot_bit = update_no_reboot_bit_pmc; 253 + p->no_reboot_priv = pmc; 243 254 return; 244 255 } 245 256 ··· 491 478 return -ENODEV; 492 479 } 493 480 494 - iTCO_wdt_no_reboot_bit_setup(p, pdata); 481 + iTCO_wdt_no_reboot_bit_setup(p, pdev, pdata); 495 482 496 483 /* 497 484 * Get the Memory-Mapped GCS or PMC register, we need it for the 498 485 * NO_REBOOT flag (TCO v2 and v3). 499 486 */ 500 487 if (p->iTCO_version >= 2 && p->iTCO_version < 6 && 501 - !pdata->update_no_reboot_bit) { 488 + !pdata->no_reboot_use_pmc) { 502 489 p->gcs_pmc_res = platform_get_resource(pdev, 503 490 IORESOURCE_MEM, 504 491 ICH_RES_MEM_GCS_PMC);
+37 -16
drivers/watchdog/intel-mid_wdt.c
··· 33 33 SCU_WATCHDOG_KEEPALIVE, 34 34 }; 35 35 36 - static inline int wdt_command(int sub, u32 *in, int inlen) 36 + struct mid_wdt { 37 + struct watchdog_device wd; 38 + struct device *dev; 39 + struct intel_scu_ipc_dev *scu; 40 + }; 41 + 42 + static inline int 43 + wdt_command(struct mid_wdt *mid, int sub, const void *in, size_t inlen, size_t size) 37 44 { 38 - return intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0); 45 + struct intel_scu_ipc_dev *scu = mid->scu; 46 + 47 + return intel_scu_ipc_dev_command_with_size(scu, IPC_WATCHDOG, sub, in, 48 + inlen, size, NULL, 0); 39 49 } 40 50 41 51 static int wdt_start(struct watchdog_device *wd) 42 52 { 43 - struct device *dev = watchdog_get_drvdata(wd); 53 + struct mid_wdt *mid = watchdog_get_drvdata(wd); 44 54 int ret, in_size; 45 55 int timeout = wd->timeout; 46 56 struct ipc_wd_start { ··· 59 49 } ipc_wd_start = { timeout - MID_WDT_PRETIMEOUT, timeout }; 60 50 61 51 /* 62 - * SCU expects the input size for watchdog IPC to 63 - * be based on 4 bytes 52 + * SCU expects the input size for watchdog IPC to be 2 which is the 53 + * size of the structure in dwords. SCU IPC normally takes bytes 54 + * but this is a special case where we specify size to be different 55 + * than inlen. 64 56 */ 65 57 in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4); 66 58 67 - ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size); 59 + ret = wdt_command(mid, SCU_WATCHDOG_START, &ipc_wd_start, 60 + sizeof(ipc_wd_start), in_size); 68 61 if (ret) 69 - dev_crit(dev, "error starting watchdog: %d\n", ret); 62 + dev_crit(mid->dev, "error starting watchdog: %d\n", ret); 70 63 71 64 return ret; 72 65 } 73 66 74 67 static int wdt_ping(struct watchdog_device *wd) 75 68 { 76 - struct device *dev = watchdog_get_drvdata(wd); 69 + struct mid_wdt *mid = watchdog_get_drvdata(wd); 77 70 int ret; 78 71 79 - ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0); 72 + ret = wdt_command(mid, SCU_WATCHDOG_KEEPALIVE, NULL, 0, 0); 80 73 if (ret) 81 - dev_crit(dev, "Error executing keepalive: %d\n", ret); 74 + dev_crit(mid->dev, "Error executing keepalive: %d\n", ret); 82 75 83 76 return ret; 84 77 } 85 78 86 79 static int wdt_stop(struct watchdog_device *wd) 87 80 { 88 - struct device *dev = watchdog_get_drvdata(wd); 81 + struct mid_wdt *mid = watchdog_get_drvdata(wd); 89 82 int ret; 90 83 91 - ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0); 84 + ret = wdt_command(mid, SCU_WATCHDOG_STOP, NULL, 0, 0); 92 85 if (ret) 93 - dev_crit(dev, "Error stopping watchdog: %d\n", ret); 86 + dev_crit(mid->dev, "Error stopping watchdog: %d\n", ret); 94 87 95 88 return ret; 96 89 } ··· 123 110 struct device *dev = &pdev->dev; 124 111 struct watchdog_device *wdt_dev; 125 112 struct intel_mid_wdt_pdata *pdata = dev->platform_data; 113 + struct mid_wdt *mid; 126 114 int ret; 127 115 128 116 if (!pdata) { ··· 137 123 return ret; 138 124 } 139 125 140 - wdt_dev = devm_kzalloc(dev, sizeof(*wdt_dev), GFP_KERNEL); 141 - if (!wdt_dev) 126 + mid = devm_kzalloc(dev, sizeof(*mid), GFP_KERNEL); 127 + if (!mid) 142 128 return -ENOMEM; 129 + 130 + mid->dev = dev; 131 + wdt_dev = &mid->wd; 143 132 144 133 wdt_dev->info = &mid_wdt_info; 145 134 wdt_dev->ops = &mid_wdt_ops; ··· 152 135 wdt_dev->parent = dev; 153 136 154 137 watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT); 155 - watchdog_set_drvdata(wdt_dev, dev); 138 + watchdog_set_drvdata(wdt_dev, mid); 156 139 157 140 ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq, 158 141 IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog", ··· 161 144 dev_err(dev, "error requesting warning irq %d\n", pdata->irq); 162 145 return ret; 163 146 } 147 + 148 + mid->scu = devm_intel_scu_ipc_dev_get(dev); 149 + if (!mid->scu) 150 + return -EPROBE_DEFER; 164 151 165 152 /* 166 153 * The firmware followed by U-Boot leaves the watchdog running
+53
include/linux/mfd/intel_pmc_bxt.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef MFD_INTEL_PMC_BXT_H 3 + #define MFD_INTEL_PMC_BXT_H 4 + 5 + /* GCR reg offsets from GCR base */ 6 + #define PMC_GCR_PMC_CFG_REG 0x08 7 + #define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78 8 + #define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80 9 + 10 + /* PMC_CFG_REG bit masks */ 11 + #define PMC_CFG_NO_REBOOT_EN BIT(4) 12 + 13 + /** 14 + * struct intel_pmc_dev - Intel PMC device structure 15 + * @dev: Pointer to the parent PMC device 16 + * @scu: Pointer to the SCU IPC device data structure 17 + * @gcr_mem_base: Virtual base address of GCR (Global Configuration Registers) 18 + * @gcr_lock: Lock used to serialize access to GCR registers 19 + * @telem_base: Pointer to telemetry SSRAM base resource or %NULL if not 20 + * available 21 + */ 22 + struct intel_pmc_dev { 23 + struct device *dev; 24 + struct intel_scu_ipc_dev *scu; 25 + void __iomem *gcr_mem_base; 26 + spinlock_t gcr_lock; 27 + struct resource *telem_base; 28 + }; 29 + 30 + #if IS_ENABLED(CONFIG_MFD_INTEL_PMC_BXT) 31 + int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, u64 *data); 32 + int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, u32 mask, u32 val); 33 + int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data); 34 + #else 35 + static inline int intel_pmc_gcr_read64(struct intel_pmc_dev *pmc, u32 offset, 36 + u64 *data) 37 + { 38 + return -ENOTSUPP; 39 + } 40 + 41 + static inline int intel_pmc_gcr_update(struct intel_pmc_dev *pmc, u32 offset, 42 + u32 mask, u32 val) 43 + { 44 + return -ENOTSUPP; 45 + } 46 + 47 + static inline int intel_pmc_s0ix_counter_read(struct intel_pmc_dev *pmc, u64 *data) 48 + { 49 + return -ENOTSUPP; 50 + } 51 + #endif 52 + 53 + #endif /* MFD_INTEL_PMC_BXT_H */
+15
include/linux/mfd/intel_soc_pmic.h
··· 13 13 14 14 #include <linux/regmap.h> 15 15 16 + /** 17 + * struct intel_soc_pmic - Intel SoC PMIC data 18 + * @irq: Master interrupt number of the parent PMIC device 19 + * @regmap: Pointer to the parent PMIC device regmap structure 20 + * @irq_chip_data: IRQ chip data for the PMIC itself 21 + * @irq_chip_data_pwrbtn: Chained IRQ chip data for the Power Button 22 + * @irq_chip_data_tmu: Chained IRQ chip data for the Time Management Unit 23 + * @irq_chip_data_bcu: Chained IRQ chip data for the Burst Control Unit 24 + * @irq_chip_data_adc: Chained IRQ chip data for the General Purpose ADC 25 + * @irq_chip_data_chgr: Chained IRQ chip data for the External Charger 26 + * @irq_chip_data_crit: Chained IRQ chip data for the Critical Event Handler 27 + * @dev: Pointer to the parent PMIC device 28 + * @scu: Pointer to the SCU IPC device data structure 29 + */ 16 30 struct intel_soc_pmic { 17 31 int irq; 18 32 struct regmap *regmap; ··· 38 24 struct regmap_irq_chip_data *irq_chip_data_chgr; 39 25 struct regmap_irq_chip_data *irq_chip_data_crit; 40 26 struct device *dev; 27 + struct intel_scu_ipc_dev *scu; 41 28 }; 42 29 43 30 int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
+7 -4
include/linux/platform_data/itco_wdt.h
··· 12 12 #define ICH_RES_MEM_OFF 2 13 13 #define ICH_RES_MEM_GCS_PMC 0 14 14 15 + /** 16 + * struct itco_wdt_platform_data - iTCO_wdt platform data 17 + * @name: Name of the platform 18 + * @version: iTCO version 19 + * @no_reboot_use_pmc: Use PMC BXT API to set and clear NO_REBOOT bit 20 + */ 15 21 struct itco_wdt_platform_data { 16 22 char name[32]; 17 23 unsigned int version; 18 - /* private data to be passed to update_no_reboot_bit API */ 19 - void *no_reboot_priv; 20 - /* pointer for platform specific no reboot update function */ 21 - int (*update_no_reboot_bit)(void *priv, bool set); 24 + bool no_reboot_use_pmc; 22 25 }; 23 26 24 27 #endif /* _ITCO_WDT_H_ */