diff options
Diffstat (limited to 'drivers/platform/x86')
52 files changed, 4505 insertions, 8862 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 0258dd879d64..43407e76476b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -475,6 +475,17 @@ config IDEAPAD_LAPTOP This is a driver for Lenovo IdeaPad netbooks contains drivers for rfkill switch, hotkey, fan control and backlight control. +config LENOVO_WMI_HOTKEY_UTILITIES + tristate "Lenovo Hotkey Utility WMI extras driver" + depends on ACPI_WMI + select NEW_LEDS + select LEDS_CLASS + imply IDEAPAD_LAPTOP + help + This driver provides WMI support for Lenovo customized hotkeys function, + such as LED control for audio/mic mute event for Ideapad, YOGA, XiaoXin, + Gaming, ThinkBook and so on. + config LENOVO_YMC tristate "Lenovo Yoga Tablet Mode Control" depends on ACPI_WMI @@ -778,6 +789,23 @@ config BARCO_P50_GPIO To compile this driver as a module, choose M here: the module will be called barco-p50-gpio. +config SAMSUNG_GALAXYBOOK + tristate "Samsung Galaxy Book driver" + depends on ACPI + depends on ACPI_BATTERY + depends on INPUT + depends on LEDS_CLASS + depends on SERIO_I8042 + select ACPI_PLATFORM_PROFILE + select FW_ATTR_CLASS + help + This is a driver for Samsung Galaxy Book series notebooks. It adds + support for the keyboard backlight control, performance mode control, + function keys, and various firmware attributes. + + For more information about this driver, see + <file:Documentation/admin-guide/laptops/samsung-galaxybook.rst>. + config SAMSUNG_LAPTOP tristate "Samsung Laptop driver" depends on RFKILL || RFKILL = n @@ -1012,19 +1040,6 @@ config SERIAL_MULTI_INSTANTIATE To compile this driver as a module, choose M here: the module will be called serial-multi-instantiate. -config MLX_PLATFORM - tristate "Mellanox Technologies platform support" - depends on ACPI && I2C && PCI - select REGMAP - help - This option enables system support for the Mellanox Technologies - platform. The Mellanox systems provide data center networking - solutions based on Virtual Protocol Interconnect (VPI) technology - enable seamless connectivity to 56/100Gb/s InfiniBand or 10/40/56GbE - connection. - - If you have a Mellanox system, say Y or M here. - config TOUCHSCREEN_DMI bool "DMI based touchscreen configuration info" depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e1b142947067..650dfbebb6c8 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_UV_SYSFS) += uv_sysfs.o # IBM Thinkpad and Lenovo obj-$(CONFIG_IBM_RTL) += ibm_rtl.o obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o +obj-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += lenovo-wmi-hotkey-utilities.o obj-$(CONFIG_LENOVO_YMC) += lenovo-ymc.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o @@ -95,8 +96,9 @@ obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o obj-$(CONFIG_BARCO_P50_GPIO) += barco-p50-gpio.o # Samsung -obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o -obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o +obj-$(CONFIG_SAMSUNG_GALAXYBOOK) += samsung-galaxybook.o +obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop.o +obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o # Toshiba obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o @@ -122,7 +124,6 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o # Platform drivers obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o obj-$(CONFIG_SERIAL_MULTI_INSTANTIATE) += serial-multi-instantiate.o -obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o obj-$(CONFIG_X86_ANDROID_TABLETS) += x86-android-tablets/ diff --git a/drivers/platform/x86/amd/Makefile b/drivers/platform/x86/amd/Makefile index 56f62fc9c97b..c6c40bdcbded 100644 --- a/drivers/platform/x86/amd/Makefile +++ b/drivers/platform/x86/amd/Makefile @@ -5,7 +5,7 @@ # obj-$(CONFIG_AMD_3D_VCACHE) += amd_3d_vcache.o -amd_3d_vcache-objs := x3d_vcache.o +amd_3d_vcache-y := x3d_vcache.o obj-$(CONFIG_AMD_PMC) += pmc/ obj-$(CONFIG_AMD_HSMP) += hsmp/ obj-$(CONFIG_AMD_PMF) += pmf/ diff --git a/drivers/platform/x86/amd/hsmp/Kconfig b/drivers/platform/x86/amd/hsmp/Kconfig index 7d10d4462a45..d6f7a62d55b5 100644 --- a/drivers/platform/x86/amd/hsmp/Kconfig +++ b/drivers/platform/x86/amd/hsmp/Kconfig @@ -7,7 +7,7 @@ config AMD_HSMP tristate menu "AMD HSMP Driver" - depends on AMD_NB || COMPILE_TEST + depends on AMD_NODE || COMPILE_TEST config AMD_HSMP_ACPI tristate "AMD HSMP ACPI device driver" diff --git a/drivers/platform/x86/amd/hsmp/Makefile b/drivers/platform/x86/amd/hsmp/Makefile index 3175d8885e87..0759bbcd13f6 100644 --- a/drivers/platform/x86/amd/hsmp/Makefile +++ b/drivers/platform/x86/amd/hsmp/Makefile @@ -5,8 +5,8 @@ # obj-$(CONFIG_AMD_HSMP) += hsmp_common.o -hsmp_common-objs := hsmp.o +hsmp_common-y := hsmp.o obj-$(CONFIG_AMD_HSMP_PLAT) += amd_hsmp.o -amd_hsmp-objs := plat.o +amd_hsmp-y := plat.o obj-$(CONFIG_AMD_HSMP_ACPI) += hsmp_acpi.o -hsmp_acpi-objs := acpi.o +hsmp_acpi-y := acpi.o diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c index 444b43be35a2..c1eccb3c80c5 100644 --- a/drivers/platform/x86/amd/hsmp/acpi.c +++ b/drivers/platform/x86/amd/hsmp/acpi.c @@ -10,7 +10,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <asm/amd_hsmp.h> -#include <asm/amd_nb.h> #include <linux/acpi.h> #include <linux/device.h> @@ -24,6 +23,8 @@ #include <uapi/asm-generic/errno-base.h> +#include <asm/amd_node.h> + #include "hsmp.h" #define DRIVER_NAME "amd_hsmp" @@ -321,8 +322,8 @@ static int hsmp_acpi_probe(struct platform_device *pdev) return -ENOMEM; if (!hsmp_pdev->is_probed) { - hsmp_pdev->num_sockets = amd_nb_num(); - if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) + hsmp_pdev->num_sockets = amd_num_nodes(); + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) return -ENODEV; hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c index 03164e30b3a5..a3ac09a90de4 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.c +++ b/drivers/platform/x86/amd/hsmp/hsmp.c @@ -8,7 +8,6 @@ */ #include <asm/amd_hsmp.h> -#include <asm/amd_nb.h> #include <linux/acpi.h> #include <linux/delay.h> diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h index e852f0a947e4..af8b21f821d6 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.h +++ b/drivers/platform/x86/amd/hsmp/hsmp.h @@ -21,8 +21,6 @@ #define HSMP_ATTR_GRP_NAME_SIZE 10 -#define MAX_AMD_SOCKETS 8 - #define HSMP_CDEV_NAME "hsmp_cdev" #define HSMP_DEVNODE_NAME "hsmp" @@ -41,7 +39,6 @@ struct hsmp_socket { void __iomem *virt_base_addr; struct semaphore hsmp_sem; char name[HSMP_ATTR_GRP_NAME_SIZE]; - struct pci_dev *root; struct device *dev; u16 sock_ind; int (*amd_hsmp_rdwr)(struct hsmp_socket *sock, u32 off, u32 *val, bool rw); diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c index 02ca85762b68..b9782a078dbd 100644 --- a/drivers/platform/x86/amd/hsmp/plat.c +++ b/drivers/platform/x86/amd/hsmp/plat.c @@ -10,14 +10,16 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <asm/amd_hsmp.h> -#include <asm/amd_nb.h> +#include <linux/build_bug.h> #include <linux/device.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/sysfs.h> +#include <asm/amd_node.h> + #include "hsmp.h" #define DRIVER_NAME "amd_hsmp" @@ -34,28 +36,12 @@ #define SMN_HSMP_MSG_RESP 0x0010980 #define SMN_HSMP_MSG_DATA 0x00109E0 -#define HSMP_INDEX_REG 0xc4 -#define HSMP_DATA_REG 0xc8 - static struct hsmp_plat_device *hsmp_pdev; static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset, u32 *value, bool write) { - int ret; - - if (!sock->root) - return -ENODEV; - - ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, - sock->mbinfo.base_addr + offset); - if (ret) - return ret; - - ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value) - : pci_read_config_dword(sock->root, HSMP_DATA_REG, value)); - - return ret; + return amd_smn_hsmp_rdwr(sock->sock_ind, sock->mbinfo.base_addr + offset, value, write); } static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj, @@ -95,7 +81,12 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, * Static array of 8 + 1(for NULL) elements is created below * to create sysfs groups for sockets. * is_bin_visible function is used to show / hide the necessary groups. + * + * Validate the maximum number against MAX_AMD_NUM_NODES. If this changes, + * then the attributes and groups below must be adjusted. */ +static_assert(MAX_AMD_NUM_NODES == 8); + #define HSMP_BIN_ATTR(index, _list) \ static const struct bin_attribute attr##index = { \ .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ @@ -159,10 +150,7 @@ static int init_platform_device(struct device *dev) int ret, i; for (i = 0; i < hsmp_pdev->num_sockets; i++) { - if (!node_to_amd_nb(i)) - return -ENODEV; sock = &hsmp_pdev->sock[i]; - sock->root = node_to_amd_nb(i)->root; sock->sock_ind = i; sock->dev = dev; sock->mbinfo.base_addr = SMN_HSMP_BASE; @@ -305,11 +293,11 @@ static int __init hsmp_plt_init(void) return -ENOMEM; /* - * amd_nb_num() returns number of SMN/DF interfaces present in the system + * amd_num_nodes() returns number of SMN/DF interfaces present in the system * if we have N SMN/DF interfaces that ideally means N sockets */ - hsmp_pdev->num_sockets = amd_nb_num(); - if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) + hsmp_pdev->num_sockets = amd_num_nodes(); + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) return ret; ret = platform_driver_register(&amd_hsmp_driver); diff --git a/drivers/platform/x86/amd/pmc/Makefile b/drivers/platform/x86/amd/pmc/Makefile index 255d94ddf999..bb6905c4cae9 100644 --- a/drivers/platform/x86/amd/pmc/Makefile +++ b/drivers/platform/x86/amd/pmc/Makefile @@ -4,6 +4,6 @@ # AMD Power Management Controller Driver # -amd-pmc-objs := pmc.o pmc-quirks.o mp1_stb.o -obj-$(CONFIG_AMD_PMC) += amd-pmc.o -amd-pmc-$(CONFIG_AMD_MP2_STB) += mp2_stb.o +obj-$(CONFIG_AMD_PMC) += amd-pmc.o +amd-pmc-y := pmc.o pmc-quirks.o mp1_stb.o +amd-pmc-$(CONFIG_AMD_MP2_STB) += mp2_stb.o diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index e6124498b195..d789d6cab794 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -32,70 +32,6 @@ #include "pmc.h" -/* SMU communication registers */ -#define AMD_PMC_REGISTER_RESPONSE 0x980 -#define AMD_PMC_REGISTER_ARGUMENT 0x9BC - -/* PMC Scratch Registers */ -#define AMD_PMC_SCRATCH_REG_CZN 0x94 -#define AMD_PMC_SCRATCH_REG_YC 0xD14 -#define AMD_PMC_SCRATCH_REG_1AH 0xF14 - -/* STB Registers */ -#define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001 -#define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002 -#define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003 - -/* Base address of SMU for mapping physical address to virtual address */ -#define AMD_PMC_MAPPING_SIZE 0x01000 -#define AMD_PMC_BASE_ADDR_OFFSET 0x10000 -#define AMD_PMC_BASE_ADDR_LO 0x13B102E8 -#define AMD_PMC_BASE_ADDR_HI 0x13B102EC -#define AMD_PMC_BASE_ADDR_LO_MASK GENMASK(15, 0) -#define AMD_PMC_BASE_ADDR_HI_MASK GENMASK(31, 20) - -/* SMU Response Codes */ -#define AMD_PMC_RESULT_OK 0x01 -#define AMD_PMC_RESULT_CMD_REJECT_BUSY 0xFC -#define AMD_PMC_RESULT_CMD_REJECT_PREREQ 0xFD -#define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE -#define AMD_PMC_RESULT_FAILED 0xFF - -/* FCH SSC Registers */ -#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30 -#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34 -#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38 -#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C -#define FCH_SSC_MAPPING_SIZE 0x800 -#define FCH_BASE_PHY_ADDR_LOW 0xFED81100 -#define FCH_BASE_PHY_ADDR_HIGH 0x00000000 - -/* SMU Message Definations */ -#define SMU_MSG_GETSMUVERSION 0x02 -#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04 -#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05 -#define SMU_MSG_LOG_START 0x06 -#define SMU_MSG_LOG_RESET 0x07 -#define SMU_MSG_LOG_DUMP_DATA 0x08 -#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09 - -#define PMC_MSG_DELAY_MIN_US 50 -#define RESPONSE_REGISTER_LOOP_MAX 20000 - -#define DELAY_MIN_US 2000 -#define DELAY_MAX_US 3000 - -enum amd_pmc_def { - MSG_TEST = 0x01, - MSG_OS_HINT_PCO, - MSG_OS_HINT_RN, -}; - -struct amd_pmc_bit_map { - const char *name; - u32 bit_mask; -}; - static const struct amd_pmc_bit_map soc15_ip_blk_v2[] = { {"DISPLAY", BIT(0)}, {"CPU", BIT(1)}, @@ -165,23 +101,6 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3 iowrite32(val, dev->regbase + reg_offset); } -struct smu_metrics { - u32 table_version; - u32 hint_count; - u32 s0i3_last_entry_status; - u32 timein_s0i2; - u64 timeentering_s0i3_lastcapture; - u64 timeentering_s0i3_totaltime; - u64 timeto_resume_to_os_lastcapture; - u64 timeto_resume_to_os_totaltime; - u64 timein_s0i3_lastcapture; - u64 timein_s0i3_totaltime; - u64 timein_swdrips_lastcapture; - u64 timein_swdrips_totaltime; - u64 timecondition_notmet_lastcapture[32]; - u64 timecondition_notmet_totaltime[32]; -} __packed; - static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev) { switch (dev->cpu_id) { @@ -247,11 +166,12 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) static int get_metrics_table(struct amd_pmc_dev *pdev, struct smu_metrics *table) { - if (!pdev->smu_virt_addr) { - int ret = amd_pmc_setup_smu_logging(pdev); + int rc; - if (ret) - return ret; + if (!pdev->smu_virt_addr) { + rc = amd_pmc_setup_smu_logging(pdev); + if (rc) + return rc; } if (pdev->cpu_id == AMD_CPU_ID_PCO) @@ -300,10 +220,10 @@ static ssize_t smu_fw_version_show(struct device *d, struct device_attribute *at char *buf) { struct amd_pmc_dev *dev = dev_get_drvdata(d); + int rc; if (!dev->major) { - int rc = amd_pmc_get_smu_version(dev); - + rc = amd_pmc_get_smu_version(dev); if (rc) return rc; } @@ -314,10 +234,10 @@ static ssize_t smu_program_show(struct device *d, struct device_attribute *attr, char *buf) { struct amd_pmc_dev *dev = dev_get_drvdata(d); + int rc; if (!dev->major) { - int rc = amd_pmc_get_smu_version(dev); - + rc = amd_pmc_get_smu_version(dev); if (rc) return rc; } @@ -778,14 +698,14 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { static int amd_pmc_suspend_handler(struct device *dev) { struct amd_pmc_dev *pdev = dev_get_drvdata(dev); + int rc; /* * Must be called only from the same set of dev_pm_ops handlers * as i8042_pm_suspend() is called: currently just from .suspend. */ if (pdev->disable_8042_wakeup && !disable_workarounds) { - int rc = amd_pmc_wa_irq1(pdev); - + rc = amd_pmc_wa_irq1(pdev); if (rc) { dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc); return rc; @@ -808,6 +728,7 @@ static const struct pci_device_id pmc_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SHP) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, { } @@ -823,7 +744,6 @@ static int amd_pmc_probe(struct platform_device *pdev) u32 val; dev->dev = &pdev->dev; - rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) { err = -ENODEV; @@ -831,8 +751,7 @@ static int amd_pmc_probe(struct platform_device *pdev) } dev->cpu_id = rdev->device; - - if (dev->cpu_id == AMD_CPU_ID_SP) { + if (dev->cpu_id == AMD_CPU_ID_SP || dev->cpu_id == AMD_CPU_ID_SHP) { dev_warn_once(dev->dev, "S0i3 is not supported on this hardware\n"); err = -ENODEV; goto err_pci_dev_put; @@ -847,7 +766,6 @@ static int amd_pmc_probe(struct platform_device *pdev) } base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK; - err = amd_smn_read(0, AMD_PMC_BASE_ADDR_HI, &val); if (err) { dev_err(dev->dev, "error reading 0x%x\n", AMD_PMC_BASE_ADDR_HI); @@ -865,7 +783,9 @@ static int amd_pmc_probe(struct platform_device *pdev) goto err_pci_dev_put; } - mutex_init(&dev->lock); + err = devm_mutex_init(dev->dev, &dev->lock); + if (err) + goto err_pci_dev_put; /* Get num of IP blocks within the SoC */ amd_pmc_get_ip_info(dev); @@ -904,7 +824,6 @@ static void amd_pmc_remove(struct platform_device *pdev) pci_dev_put(dev->rdev); if (IS_ENABLED(CONFIG_AMD_MP2_STB)) amd_mp2_stb_deinit(dev); - mutex_destroy(&dev->lock); } static const struct acpi_device_id amd_pmc_acpi_ids[] = { diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h index f43f0253b0f5..62f3e51020fd 100644 --- a/drivers/platform/x86/amd/pmc/pmc.h +++ b/drivers/platform/x86/amd/pmc/pmc.h @@ -14,6 +14,59 @@ #include <linux/types.h> #include <linux/mutex.h> +/* SMU communication registers */ +#define AMD_PMC_REGISTER_RESPONSE 0x980 +#define AMD_PMC_REGISTER_ARGUMENT 0x9BC + +/* PMC Scratch Registers */ +#define AMD_PMC_SCRATCH_REG_CZN 0x94 +#define AMD_PMC_SCRATCH_REG_YC 0xD14 +#define AMD_PMC_SCRATCH_REG_1AH 0xF14 + +/* STB Registers */ +#define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001 +#define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002 +#define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003 + +/* Base address of SMU for mapping physical address to virtual address */ +#define AMD_PMC_MAPPING_SIZE 0x01000 +#define AMD_PMC_BASE_ADDR_OFFSET 0x10000 +#define AMD_PMC_BASE_ADDR_LO 0x13B102E8 +#define AMD_PMC_BASE_ADDR_HI 0x13B102EC +#define AMD_PMC_BASE_ADDR_LO_MASK GENMASK(15, 0) +#define AMD_PMC_BASE_ADDR_HI_MASK GENMASK(31, 20) + +/* SMU Response Codes */ +#define AMD_PMC_RESULT_OK 0x01 +#define AMD_PMC_RESULT_CMD_REJECT_BUSY 0xFC +#define AMD_PMC_RESULT_CMD_REJECT_PREREQ 0xFD +#define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE +#define AMD_PMC_RESULT_FAILED 0xFF + +/* FCH SSC Registers */ +#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30 +#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34 +#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38 +#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C +#define FCH_SSC_MAPPING_SIZE 0x800 +#define FCH_BASE_PHY_ADDR_LOW 0xFED81100 +#define FCH_BASE_PHY_ADDR_HIGH 0x00000000 + +/* SMU Message Definations */ +#define SMU_MSG_GETSMUVERSION 0x02 +#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04 +#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05 +#define SMU_MSG_LOG_START 0x06 +#define SMU_MSG_LOG_RESET 0x07 +#define SMU_MSG_LOG_DUMP_DATA 0x08 +#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09 + +#define PMC_MSG_DELAY_MIN_US 50 +#define RESPONSE_REGISTER_LOOP_MAX 20000 + +#define DELAY_MIN_US 2000 +#define DELAY_MAX_US 3000 + enum s2d_msg_port { MSG_PORT_PMC, MSG_PORT_S2D, @@ -65,6 +118,34 @@ struct amd_pmc_dev { struct stb_arg stb_arg; }; +struct amd_pmc_bit_map { + const char *name; + u32 bit_mask; +}; + +struct smu_metrics { + u32 table_version; + u32 hint_count; + u32 s0i3_last_entry_status; + u32 timein_s0i2; + u64 timeentering_s0i3_lastcapture; + u64 timeentering_s0i3_totaltime; + u64 timeto_resume_to_os_lastcapture; + u64 timeto_resume_to_os_totaltime; + u64 timein_s0i3_lastcapture; + u64 timein_s0i3_totaltime; + u64 timein_swdrips_lastcapture; + u64 timein_swdrips_totaltime; + u64 timecondition_notmet_lastcapture[32]; + u64 timecondition_notmet_totaltime[32]; +} __packed; + +enum amd_pmc_def { + MSG_TEST = 0x01, + MSG_OS_HINT_PCO, + MSG_OS_HINT_RN, +}; + void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev); void amd_pmc_quirks_init(struct amd_pmc_dev *dev); void amd_mp2_stb_init(struct amd_pmc_dev *dev); @@ -79,6 +160,7 @@ void amd_mp2_stb_deinit(struct amd_pmc_dev *dev); #define AMD_CPU_ID_CB 0x14D8 #define AMD_CPU_ID_PS 0x14E8 #define AMD_CPU_ID_SP 0x14A4 +#define AMD_CPU_ID_SHP 0x153A #define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 #define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 #define PCI_DEVICE_ID_AMD_MP2_STB 0x172c diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile index 6b26e48ce8ad..5978464e0eb7 100644 --- a/drivers/platform/x86/amd/pmf/Makefile +++ b/drivers/platform/x86/amd/pmf/Makefile @@ -4,7 +4,7 @@ # AMD Platform Management Framework # -obj-$(CONFIG_AMD_PMF) += amd-pmf.o -amd-pmf-objs := core.o acpi.o sps.o \ - auto-mode.o cnqf.o \ - tee-if.o spc.o +obj-$(CONFIG_AMD_PMF) += amd-pmf.o +amd-pmf-y := core.o acpi.o sps.o \ + auto-mode.o cnqf.o \ + tee-if.o spc.o diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c index dd5780a1d06e..f75f7ecd8cd9 100644 --- a/drivers/platform/x86/amd/pmf/acpi.c +++ b/drivers/platform/x86/amd/pmf/acpi.c @@ -220,7 +220,7 @@ static void apmf_sbios_heartbeat_notify(struct work_struct *work) if (!info) return; - schedule_delayed_work(&dev->heart_beat, msecs_to_jiffies(dev->hb_interval * 1000)); + schedule_delayed_work(&dev->heart_beat, secs_to_jiffies(dev->hb_interval)); kfree(info); } diff --git a/drivers/platform/x86/asus-tf103c-dock.c b/drivers/platform/x86/asus-tf103c-dock.c index ca4670d0dc67..f09a3fc6524a 100644 --- a/drivers/platform/x86/asus-tf103c-dock.c +++ b/drivers/platform/x86/asus-tf103c-dock.c @@ -856,7 +856,7 @@ static int tf103c_dock_probe(struct i2c_client *client) /* 5. Setup irqchip for touchpad IRQ pass-through */ dock->tp_irqchip.name = KBUILD_MODNAME; - dock->tp_irq_domain = irq_domain_add_linear(NULL, 1, &irq_domain_simple_ops, NULL); + dock->tp_irq_domain = irq_domain_create_linear(NULL, 1, &irq_domain_simple_ops, NULL); if (!dock->tp_irq_domain) return -ENOMEM; diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 58754bc5b5b1..abbebd4bfb15 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -69,7 +69,6 @@ #include <linux/hwmon-sysfs.h> #include <linux/power_supply.h> #include <linux/sysfs.h> -#include <linux/fb.h> #include <acpi/video.h> /* ======= */ diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig index d09060aedd3f..f8a0dffcaab7 100644 --- a/drivers/platform/x86/dell/Kconfig +++ b/drivers/platform/x86/dell/Kconfig @@ -18,15 +18,35 @@ config ALIENWARE_WMI tristate "Alienware Special feature control" default m depends on ACPI + depends on ACPI_WMI + depends on DMI depends on LEDS_CLASS depends on NEW_LEDS - depends on ACPI_WMI + help + This is a driver for controlling Alienware WMI driven features. + + On legacy devices, it exposes an interface for controlling the AlienFX + zones on Alienware machines that don't contain a dedicated + AlienFX USB MCU such as the X51 and X51-R2. + + On newer devices, it exposes the AWCC thermal control interface through + known Kernel APIs. + +config ALIENWARE_WMI_LEGACY + bool "Alienware Legacy WMI device driver" + default y + depends on ALIENWARE_WMI + help + Legacy Alienware WMI driver with AlienFX LED control capabilities. + +config ALIENWARE_WMI_WMAX + bool "Alienware WMAX WMI device driver" + default y + depends on ALIENWARE_WMI select ACPI_PLATFORM_PROFILE help - This is a driver for controlling Alienware BIOS driven - features. It exposes an interface for controlling the AlienFX - zones on Alienware machines that don't contain a dedicated AlienFX - USB MCU such as the X51 and X51-R2. + Alienware WMI driver with AlienFX LED, HDMI, amplifier, deep sleep and + AWCC thermal control capabilities. config DCDBAS tristate "Dell Systems Management Base Driver" diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile index bb3cbd470a46..c7501c25e627 100644 --- a/drivers/platform/x86/dell/Makefile +++ b/drivers/platform/x86/dell/Makefile @@ -4,24 +4,27 @@ # Dell x86 Platform-Specific Drivers # -obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o -obj-$(CONFIG_DCDBAS) += dcdbas.o -obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o -obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o -obj-$(CONFIG_DELL_RBU) += dell_rbu.o -obj-$(CONFIG_DELL_PC) += dell-pc.o -obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o -dell-smbios-objs := dell-smbios-base.o -dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o -dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o -obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o -obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o -obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o -obj-$(CONFIG_DELL_WMI) += dell-wmi.o -dell-wmi-objs := dell-wmi-base.o -dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o -obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o -obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o -obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o -obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o -obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/ +obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o +alienware-wmi-y := alienware-wmi-base.o +alienware-wmi-$(CONFIG_ALIENWARE_WMI_LEGACY) += alienware-wmi-legacy.o +alienware-wmi-$(CONFIG_ALIENWARE_WMI_WMAX) += alienware-wmi-wmax.o +obj-$(CONFIG_DCDBAS) += dcdbas.o +obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o +obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o +obj-$(CONFIG_DELL_RBU) += dell_rbu.o +obj-$(CONFIG_DELL_PC) += dell-pc.o +obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +dell-smbios-y := dell-smbios-base.o +dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o +dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o +obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o +obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o +obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o +obj-$(CONFIG_DELL_WMI) += dell-wmi.o +dell-wmi-y := dell-wmi-base.o +dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o +obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o +obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o +obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o +obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o +obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/ diff --git a/drivers/platform/x86/dell/alienware-wmi-base.c b/drivers/platform/x86/dell/alienware-wmi-base.c new file mode 100644 index 000000000000..64562b92314f --- /dev/null +++ b/drivers/platform/x86/dell/alienware-wmi-base.c @@ -0,0 +1,491 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Alienware special feature control + * + * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com> + * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com> + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/acpi.h> +#include <linux/cleanup.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dmi.h> +#include <linux/leds.h> +#include "alienware-wmi.h" + +MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>"); +MODULE_AUTHOR("Kurt Borja <kuurtb@gmail.com>"); +MODULE_DESCRIPTION("Alienware special feature control"); +MODULE_LICENSE("GPL"); + +struct alienfx_quirks *alienfx; + +static struct alienfx_quirks quirk_inspiron5675 = { + .num_zones = 2, + .hdmi_mux = false, + .amplifier = false, + .deepslp = false, +}; + +static struct alienfx_quirks quirk_unknown = { + .num_zones = 2, + .hdmi_mux = false, + .amplifier = false, + .deepslp = false, +}; + +static struct alienfx_quirks quirk_x51_r1_r2 = { + .num_zones = 3, + .hdmi_mux = false, + .amplifier = false, + .deepslp = false, +}; + +static struct alienfx_quirks quirk_x51_r3 = { + .num_zones = 4, + .hdmi_mux = false, + .amplifier = true, + .deepslp = false, +}; + +static struct alienfx_quirks quirk_asm100 = { + .num_zones = 2, + .hdmi_mux = true, + .amplifier = false, + .deepslp = false, +}; + +static struct alienfx_quirks quirk_asm200 = { + .num_zones = 2, + .hdmi_mux = true, + .amplifier = false, + .deepslp = true, +}; + +static struct alienfx_quirks quirk_asm201 = { + .num_zones = 2, + .hdmi_mux = true, + .amplifier = true, + .deepslp = true, +}; + +static int __init dmi_matched(const struct dmi_system_id *dmi) +{ + alienfx = dmi->driver_data; + return 1; +} + +static const struct dmi_system_id alienware_quirks[] __initconst = { + { + .callback = dmi_matched, + .ident = "Alienware ASM100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), + }, + .driver_data = &quirk_asm100, + }, + { + .callback = dmi_matched, + .ident = "Alienware ASM200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), + }, + .driver_data = &quirk_asm200, + }, + { + .callback = dmi_matched, + .ident = "Alienware ASM201", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), + }, + .driver_data = &quirk_asm201, + }, + { + .callback = dmi_matched, + .ident = "Alienware X51 R1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), + }, + .driver_data = &quirk_x51_r1_r2, + }, + { + .callback = dmi_matched, + .ident = "Alienware X51 R2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), + }, + .driver_data = &quirk_x51_r1_r2, + }, + { + .callback = dmi_matched, + .ident = "Alienware X51 R3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), + }, + .driver_data = &quirk_x51_r3, + }, + { + .callback = dmi_matched, + .ident = "Dell Inc. Inspiron 5675", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"), + }, + .driver_data = &quirk_inspiron5675, + }, + {} +}; + +u8 alienware_interface; + +int alienware_wmi_command(struct wmi_device *wdev, u32 method_id, + void *in_args, size_t in_size, u32 *out_data) +{ + struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer in = {in_size, in_args}; + acpi_status ret; + + ret = wmidev_evaluate_method(wdev, 0, method_id, &in, out_data ? &out : NULL); + if (ACPI_FAILURE(ret)) + return -EIO; + + union acpi_object *obj __free(kfree) = out.pointer; + + if (out_data) { + if (obj && obj->type == ACPI_TYPE_INTEGER) + *out_data = (u32)obj->integer.value; + else + return -ENOMSG; + } + + return 0; +} + +/* + * Helpers used for zone control + */ +static int parse_rgb(const char *buf, struct color_platform *colors) +{ + long unsigned int rgb; + int ret; + union color_union { + struct color_platform cp; + int package; + } repackager; + + ret = kstrtoul(buf, 16, &rgb); + if (ret) + return ret; + + /* RGB triplet notation is 24-bit hexadecimal */ + if (rgb > 0xFFFFFF) + return -EINVAL; + + repackager.package = rgb & 0x0f0f0f0f; + pr_debug("alienware-wmi: r: %d g:%d b: %d\n", + repackager.cp.red, repackager.cp.green, repackager.cp.blue); + *colors = repackager.cp; + return 0; +} + +/* + * Individual RGB zone control + */ +static ssize_t zone_show(struct device *dev, struct device_attribute *attr, + char *buf, u8 location) +{ + struct alienfx_priv *priv = dev_get_drvdata(dev); + struct color_platform *colors = &priv->colors[location]; + + return sprintf(buf, "red: %d, green: %d, blue: %d\n", + colors->red, colors->green, colors->blue); + +} + +static ssize_t zone_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count, u8 location) +{ + struct alienfx_priv *priv = dev_get_drvdata(dev); + struct color_platform *colors = &priv->colors[location]; + struct alienfx_platdata *pdata = dev_get_platdata(dev); + int ret; + + ret = parse_rgb(buf, colors); + if (ret) + return ret; + + ret = pdata->ops.upd_led(priv, pdata->wdev, location); + + return ret ? ret : count; +} + +static ssize_t zone00_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return zone_show(dev, attr, buf, 0); +} + +static ssize_t zone00_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return zone_store(dev, attr, buf, count, 0); +} + +static DEVICE_ATTR_RW(zone00); + +static ssize_t zone01_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return zone_show(dev, attr, buf, 1); +} + +static ssize_t zone01_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return zone_store(dev, attr, buf, count, 1); +} + +static DEVICE_ATTR_RW(zone01); + +static ssize_t zone02_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return zone_show(dev, attr, buf, 2); +} + +static ssize_t zone02_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return zone_store(dev, attr, buf, count, 2); +} + +static DEVICE_ATTR_RW(zone02); + +static ssize_t zone03_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return zone_show(dev, attr, buf, 3); +} + +static ssize_t zone03_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return zone_store(dev, attr, buf, count, 3); +} + +static DEVICE_ATTR_RW(zone03); + +/* + * Lighting control state device attribute (Global) + */ +static ssize_t lighting_control_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct alienfx_priv *priv = dev_get_drvdata(dev); + + if (priv->lighting_control_state == LEGACY_BOOTING) + return sysfs_emit(buf, "[booting] running suspend\n"); + else if (priv->lighting_control_state == LEGACY_SUSPEND) + return sysfs_emit(buf, "booting running [suspend]\n"); + + return sysfs_emit(buf, "booting [running] suspend\n"); +} + +static ssize_t lighting_control_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct alienfx_priv *priv = dev_get_drvdata(dev); + u8 val; + + if (strcmp(buf, "booting\n") == 0) + val = LEGACY_BOOTING; + else if (strcmp(buf, "suspend\n") == 0) + val = LEGACY_SUSPEND; + else if (alienware_interface == LEGACY) + val = LEGACY_RUNNING; + else + val = WMAX_RUNNING; + + priv->lighting_control_state = val; + pr_debug("alienware-wmi: updated control state to %d\n", + priv->lighting_control_state); + + return count; +} + +static DEVICE_ATTR_RW(lighting_control_state); + +static umode_t zone_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + if (n < alienfx->num_zones + 1) + return attr->mode; + + return 0; +} + +static bool zone_group_visible(struct kobject *kobj) +{ + return alienfx->num_zones > 0; +} +DEFINE_SYSFS_GROUP_VISIBLE(zone); + +static struct attribute *zone_attrs[] = { + &dev_attr_lighting_control_state.attr, + &dev_attr_zone00.attr, + &dev_attr_zone01.attr, + &dev_attr_zone02.attr, + &dev_attr_zone03.attr, + NULL +}; + +static struct attribute_group zone_attribute_group = { + .name = "rgb_zones", + .is_visible = SYSFS_GROUP_VISIBLE(zone), + .attrs = zone_attrs, +}; + +/* + * LED Brightness (Global) + */ +static void global_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv, + global_led); + struct alienfx_platdata *pdata = dev_get_platdata(&priv->pdev->dev); + int ret; + + priv->global_brightness = brightness; + + ret = pdata->ops.upd_brightness(priv, pdata->wdev, brightness); + if (ret) + pr_err("LED brightness update failed\n"); +} + +static enum led_brightness global_led_get(struct led_classdev *led_cdev) +{ + struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv, + global_led); + + return priv->global_brightness; +} + +/* + * Platform Driver + */ +static int alienfx_probe(struct platform_device *pdev) +{ + struct alienfx_priv *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + if (alienware_interface == WMAX) + priv->lighting_control_state = WMAX_RUNNING; + else + priv->lighting_control_state = LEGACY_RUNNING; + + priv->pdev = pdev; + priv->global_led.name = "alienware::global_brightness"; + priv->global_led.brightness_set = global_led_set; + priv->global_led.brightness_get = global_led_get; + priv->global_led.max_brightness = 0x0F; + priv->global_brightness = priv->global_led.max_brightness; + platform_set_drvdata(pdev, priv); + + return devm_led_classdev_register(&pdev->dev, &priv->global_led); +} + +static const struct attribute_group *alienfx_groups[] = { + &zone_attribute_group, + WMAX_DEV_GROUPS + NULL +}; + +static struct platform_driver platform_driver = { + .driver = { + .name = "alienware-wmi", + .dev_groups = alienfx_groups, + }, + .probe = alienfx_probe, +}; + +static void alienware_alienfx_remove(void *data) +{ + struct platform_device *pdev = data; + + platform_device_unregister(pdev); +} + +int alienware_alienfx_setup(struct alienfx_platdata *pdata) +{ + struct device *dev = &pdata->wdev->dev; + struct platform_device *pdev; + int ret; + + pdev = platform_device_register_data(NULL, "alienware-wmi", + PLATFORM_DEVID_NONE, pdata, + sizeof(*pdata)); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + + dev_set_drvdata(dev, pdev); + ret = devm_add_action_or_reset(dev, alienware_alienfx_remove, pdev); + if (ret) + return ret; + + return 0; +} + +static int __init alienware_wmi_init(void) +{ + int ret; + + dmi_check_system(alienware_quirks); + if (!alienfx) + alienfx = &quirk_unknown; + + ret = platform_driver_register(&platform_driver); + if (ret < 0) + return ret; + + if (wmi_has_guid(WMAX_CONTROL_GUID)) { + alienware_interface = WMAX; + ret = alienware_wmax_wmi_init(); + } else { + alienware_interface = LEGACY; + ret = alienware_legacy_wmi_init(); + } + + if (ret < 0) + platform_driver_unregister(&platform_driver); + + return ret; +} + +module_init(alienware_wmi_init); + +static void __exit alienware_wmi_exit(void) +{ + if (alienware_interface == WMAX) + alienware_wmax_wmi_exit(); + else + alienware_legacy_wmi_exit(); + + platform_driver_unregister(&platform_driver); +} + +module_exit(alienware_wmi_exit); diff --git a/drivers/platform/x86/dell/alienware-wmi-legacy.c b/drivers/platform/x86/dell/alienware-wmi-legacy.c new file mode 100644 index 000000000000..4a84a2fe918b --- /dev/null +++ b/drivers/platform/x86/dell/alienware-wmi-legacy.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Alienware LEGACY WMI device driver + * + * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com> + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/wmi.h> +#include "alienware-wmi.h" + +struct legacy_led_args { + struct color_platform colors; + u8 brightness; + u8 state; +} __packed; + + +/* + * Legacy WMI driver + */ +static int legacy_wmi_update_led(struct alienfx_priv *priv, + struct wmi_device *wdev, u8 location) +{ + struct legacy_led_args legacy_args = { + .colors = priv->colors[location], + .brightness = priv->global_brightness, + .state = 0, + }; + struct acpi_buffer input; + acpi_status status; + + if (legacy_args.state != LEGACY_RUNNING) { + legacy_args.state = priv->lighting_control_state; + + input.length = sizeof(legacy_args); + input.pointer = &legacy_args; + + status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0, + location + 1, &input, NULL); + if (ACPI_FAILURE(status)) + return -EIO; + + return 0; + } + + return alienware_wmi_command(wdev, location + 1, &legacy_args, + sizeof(legacy_args), NULL); +} + +static int legacy_wmi_update_brightness(struct alienfx_priv *priv, + struct wmi_device *wdev, u8 brightness) +{ + return legacy_wmi_update_led(priv, wdev, 0); +} + +static int legacy_wmi_probe(struct wmi_device *wdev, const void *context) +{ + struct alienfx_platdata pdata = { + .wdev = wdev, + .ops = { + .upd_led = legacy_wmi_update_led, + .upd_brightness = legacy_wmi_update_brightness, + }, + }; + + return alienware_alienfx_setup(&pdata); +} + +static const struct wmi_device_id alienware_legacy_device_id_table[] = { + { LEGACY_CONTROL_GUID, NULL }, + { }, +}; +MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table); + +static struct wmi_driver alienware_legacy_wmi_driver = { + .driver = { + .name = "alienware-wmi-alienfx", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = alienware_legacy_device_id_table, + .probe = legacy_wmi_probe, + .no_singleton = true, +}; + +int __init alienware_legacy_wmi_init(void) +{ + return wmi_driver_register(&alienware_legacy_wmi_driver); +} + +void __exit alienware_legacy_wmi_exit(void) +{ + wmi_driver_unregister(&alienware_legacy_wmi_driver); +} diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c new file mode 100644 index 000000000000..3d3014b5adf0 --- /dev/null +++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c @@ -0,0 +1,768 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Alienware WMAX WMI device driver + * + * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com> + * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com> + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/dmi.h> +#include <linux/moduleparam.h> +#include <linux/platform_profile.h> +#include <linux/wmi.h> +#include "alienware-wmi.h" + +#define WMAX_METHOD_HDMI_SOURCE 0x1 +#define WMAX_METHOD_HDMI_STATUS 0x2 +#define WMAX_METHOD_HDMI_CABLE 0x5 +#define WMAX_METHOD_AMPLIFIER_CABLE 0x6 +#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B +#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C +#define WMAX_METHOD_BRIGHTNESS 0x3 +#define WMAX_METHOD_ZONE_CONTROL 0x4 +#define WMAX_METHOD_THERMAL_INFORMATION 0x14 +#define WMAX_METHOD_THERMAL_CONTROL 0x15 +#define WMAX_METHOD_GAME_SHIFT_STATUS 0x25 + +#define WMAX_THERMAL_MODE_GMODE 0xAB + +#define WMAX_FAILURE_CODE 0xFFFFFFFF +#define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4) +#define WMAX_THERMAL_MODE_MASK GENMASK(3, 0) +#define WMAX_SENSOR_ID_MASK BIT(8) + +static bool force_platform_profile; +module_param_unsafe(force_platform_profile, bool, 0); +MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available"); + +static bool force_gmode; +module_param_unsafe(force_gmode, bool, 0); +MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected"); + +struct awcc_quirks { + bool pprof; + bool gmode; +}; + +static struct awcc_quirks g_series_quirks = { + .pprof = true, + .gmode = true, +}; + +static struct awcc_quirks generic_quirks = { + .pprof = true, + .gmode = false, +}; + +static struct awcc_quirks empty_quirks; + +static const struct dmi_system_id awcc_dmi_table[] __initconst = { + { + .ident = "Alienware m16 R1 AMD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"), + }, + .driver_data = &generic_quirks, + }, + { + .ident = "Alienware m17 R5", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), + }, + .driver_data = &generic_quirks, + }, + { + .ident = "Alienware m18 R2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"), + }, + .driver_data = &generic_quirks, + }, + { + .ident = "Alienware x15 R1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"), + }, + .driver_data = &generic_quirks, + }, + { + .ident = "Alienware x17 R2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"), + }, + .driver_data = &generic_quirks, + }, + { + .ident = "Dell Inc. G15 5510", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"), + }, + .driver_data = &g_series_quirks, + }, + { + .ident = "Dell Inc. G15 5511", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"), + }, + .driver_data = &g_series_quirks, + }, + { + .ident = "Dell Inc. G15 5515", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"), + }, + .driver_data = &g_series_quirks, + }, + { + .ident = "Dell Inc. G3 3500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"), + }, + .driver_data = &g_series_quirks, + }, + { + .ident = "Dell Inc. G3 3590", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"), + }, + .driver_data = &g_series_quirks, + }, + { + .ident = "Dell Inc. G5 5500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"), + }, + .driver_data = &g_series_quirks, + }, +}; + +enum WMAX_THERMAL_INFORMATION_OPERATIONS { + WMAX_OPERATION_SYS_DESCRIPTION = 0x02, + WMAX_OPERATION_LIST_IDS = 0x03, + WMAX_OPERATION_CURRENT_PROFILE = 0x0B, +}; + +enum WMAX_THERMAL_CONTROL_OPERATIONS { + WMAX_OPERATION_ACTIVATE_PROFILE = 0x01, +}; + +enum WMAX_GAME_SHIFT_STATUS_OPERATIONS { + WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01, + WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02, +}; + +enum WMAX_THERMAL_TABLES { + WMAX_THERMAL_TABLE_BASIC = 0x90, + WMAX_THERMAL_TABLE_USTT = 0xA0, +}; + +enum wmax_thermal_mode { + THERMAL_MODE_USTT_BALANCED, + THERMAL_MODE_USTT_BALANCED_PERFORMANCE, + THERMAL_MODE_USTT_COOL, + THERMAL_MODE_USTT_QUIET, + THERMAL_MODE_USTT_PERFORMANCE, + THERMAL_MODE_USTT_LOW_POWER, + THERMAL_MODE_BASIC_QUIET, + THERMAL_MODE_BASIC_BALANCED, + THERMAL_MODE_BASIC_BALANCED_PERFORMANCE, + THERMAL_MODE_BASIC_PERFORMANCE, + THERMAL_MODE_LAST, +}; + +struct wmax_led_args { + u32 led_mask; + struct color_platform colors; + u8 state; +} __packed; + +struct wmax_brightness_args { + u32 led_mask; + u32 percentage; +}; + +struct wmax_basic_args { + u8 arg; +}; + +struct wmax_u32_args { + u8 operation; + u8 arg1; + u8 arg2; + u8 arg3; +}; + +struct awcc_priv { + struct wmi_device *wdev; + struct device *ppdev; + enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; +}; + +static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = { + [THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED, + [THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, + [THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL, + [THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET, + [THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, + [THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER, + [THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET, + [THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED, + [THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, + [THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, +}; + +static struct awcc_quirks *awcc; + +/* + * The HDMI mux sysfs node indicates the status of the HDMI input mux. + * It can toggle between standard system GPU output and HDMI input. + */ +static ssize_t cable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args in_args = { + .arg = 0, + }; + u32 out_data; + int ret; + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE, + &in_args, sizeof(in_args), &out_data); + if (!ret) { + if (out_data == 0) + return sysfs_emit(buf, "[unconnected] connected unknown\n"); + else if (out_data == 1) + return sysfs_emit(buf, "unconnected [connected] unknown\n"); + } + + pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret); + return sysfs_emit(buf, "unconnected connected [unknown]\n"); +} + +static ssize_t source_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args in_args = { + .arg = 0, + }; + u32 out_data; + int ret; + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS, + &in_args, sizeof(in_args), &out_data); + if (!ret) { + if (out_data == 1) + return sysfs_emit(buf, "[input] gpu unknown\n"); + else if (out_data == 2) + return sysfs_emit(buf, "input [gpu] unknown\n"); + } + + pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret); + return sysfs_emit(buf, "input gpu [unknown]\n"); +} + +static ssize_t source_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args args; + int ret; + + if (strcmp(buf, "gpu\n") == 0) + args.arg = 1; + else if (strcmp(buf, "input\n") == 0) + args.arg = 2; + else + args.arg = 3; + pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args, + sizeof(args), NULL); + if (ret < 0) + pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret); + + return count; +} + +static DEVICE_ATTR_RO(cable); +static DEVICE_ATTR_RW(source); + +static bool hdmi_group_visible(struct kobject *kobj) +{ + return alienware_interface == WMAX && alienfx->hdmi_mux; +} +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi); + +static struct attribute *hdmi_attrs[] = { + &dev_attr_cable.attr, + &dev_attr_source.attr, + NULL, +}; + +const struct attribute_group wmax_hdmi_attribute_group = { + .name = "hdmi", + .is_visible = SYSFS_GROUP_VISIBLE(hdmi), + .attrs = hdmi_attrs, +}; + +/* + * Alienware GFX amplifier support + * - Currently supports reading cable status + * - Leaving expansion room to possibly support dock/undock events later + */ +static ssize_t status_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args in_args = { + .arg = 0, + }; + u32 out_data; + int ret; + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE, + &in_args, sizeof(in_args), &out_data); + if (!ret) { + if (out_data == 0) + return sysfs_emit(buf, "[unconnected] connected unknown\n"); + else if (out_data == 1) + return sysfs_emit(buf, "unconnected [connected] unknown\n"); + } + + pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret); + return sysfs_emit(buf, "unconnected connected [unknown]\n"); +} + +static DEVICE_ATTR_RO(status); + +static bool amplifier_group_visible(struct kobject *kobj) +{ + return alienware_interface == WMAX && alienfx->amplifier; +} +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier); + +static struct attribute *amplifier_attrs[] = { + &dev_attr_status.attr, + NULL, +}; + +const struct attribute_group wmax_amplifier_attribute_group = { + .name = "amplifier", + .is_visible = SYSFS_GROUP_VISIBLE(amplifier), + .attrs = amplifier_attrs, +}; + +/* + * Deep Sleep Control support + * - Modifies BIOS setting for deep sleep control allowing extra wakeup events + */ +static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args in_args = { + .arg = 0, + }; + u32 out_data; + int ret; + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS, + &in_args, sizeof(in_args), &out_data); + if (!ret) { + if (out_data == 0) + return sysfs_emit(buf, "[disabled] s5 s5_s4\n"); + else if (out_data == 1) + return sysfs_emit(buf, "disabled [s5] s5_s4\n"); + else if (out_data == 2) + return sysfs_emit(buf, "disabled s5 [s5_s4]\n"); + } + + pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret); + return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n"); +} + +static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct alienfx_platdata *pdata = dev_get_platdata(dev); + struct wmax_basic_args args; + int ret; + + if (strcmp(buf, "disabled\n") == 0) + args.arg = 0; + else if (strcmp(buf, "s5\n") == 0) + args.arg = 1; + else + args.arg = 2; + pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); + + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL, + &args, sizeof(args), NULL); + if (!ret) + pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret); + + return count; +} + +static DEVICE_ATTR_RW(deepsleep); + +static bool deepsleep_group_visible(struct kobject *kobj) +{ + return alienware_interface == WMAX && alienfx->deepslp; +} +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep); + +static struct attribute *deepsleep_attrs[] = { + &dev_attr_deepsleep.attr, + NULL, +}; + +const struct attribute_group wmax_deepsleep_attribute_group = { + .name = "deepsleep", + .is_visible = SYSFS_GROUP_VISIBLE(deepsleep), + .attrs = deepsleep_attrs, +}; + +/* + * Thermal Profile control + * - Provides thermal profile control through the Platform Profile API + */ +static bool is_wmax_thermal_code(u32 code) +{ + if (code & WMAX_SENSOR_ID_MASK) + return false; + + if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST) + return false; + + if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC && + (code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET) + return true; + + if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT && + (code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER) + return true; + + return false; +} + +static int wmax_thermal_information(struct wmi_device *wdev, u8 operation, + u8 arg, u32 *out_data) +{ + struct wmax_u32_args in_args = { + .operation = operation, + .arg1 = arg, + .arg2 = 0, + .arg3 = 0, + }; + int ret; + + ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_INFORMATION, + &in_args, sizeof(in_args), out_data); + if (ret < 0) + return ret; + + if (*out_data == WMAX_FAILURE_CODE) + return -EBADRQC; + + return 0; +} + +static int wmax_thermal_control(struct wmi_device *wdev, u8 profile) +{ + struct wmax_u32_args in_args = { + .operation = WMAX_OPERATION_ACTIVATE_PROFILE, + .arg1 = profile, + .arg2 = 0, + .arg3 = 0, + }; + u32 out_data; + int ret; + + ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_CONTROL, + &in_args, sizeof(in_args), &out_data); + if (ret) + return ret; + + if (out_data == WMAX_FAILURE_CODE) + return -EBADRQC; + + return 0; +} + +static int wmax_game_shift_status(struct wmi_device *wdev, u8 operation, + u32 *out_data) +{ + struct wmax_u32_args in_args = { + .operation = operation, + .arg1 = 0, + .arg2 = 0, + .arg3 = 0, + }; + int ret; + + ret = alienware_wmi_command(wdev, WMAX_METHOD_GAME_SHIFT_STATUS, + &in_args, sizeof(in_args), out_data); + if (ret < 0) + return ret; + + if (*out_data == WMAX_FAILURE_CODE) + return -EOPNOTSUPP; + + return 0; +} + +static int thermal_profile_get(struct device *dev, + enum platform_profile_option *profile) +{ + struct awcc_priv *priv = dev_get_drvdata(dev); + u32 out_data; + int ret; + + ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_CURRENT_PROFILE, + 0, &out_data); + + if (ret < 0) + return ret; + + if (out_data == WMAX_THERMAL_MODE_GMODE) { + *profile = PLATFORM_PROFILE_PERFORMANCE; + return 0; + } + + if (!is_wmax_thermal_code(out_data)) + return -ENODATA; + + out_data &= WMAX_THERMAL_MODE_MASK; + *profile = wmax_mode_to_platform_profile[out_data]; + + return 0; +} + +static int thermal_profile_set(struct device *dev, + enum platform_profile_option profile) +{ + struct awcc_priv *priv = dev_get_drvdata(dev); + + if (awcc->gmode) { + u32 gmode_status; + int ret; + + ret = wmax_game_shift_status(priv->wdev, + WMAX_OPERATION_GET_GAME_SHIFT_STATUS, + &gmode_status); + + if (ret < 0) + return ret; + + if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) || + (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) { + ret = wmax_game_shift_status(priv->wdev, + WMAX_OPERATION_TOGGLE_GAME_SHIFT, + &gmode_status); + + if (ret < 0) + return ret; + } + } + + return wmax_thermal_control(priv->wdev, + priv->supported_thermal_profiles[profile]); +} + +static int thermal_profile_probe(void *drvdata, unsigned long *choices) +{ + enum platform_profile_option profile; + struct awcc_priv *priv = drvdata; + enum wmax_thermal_mode mode; + u8 sys_desc[4]; + u32 first_mode; + u32 out_data; + int ret; + + ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_SYS_DESCRIPTION, + 0, (u32 *) &sys_desc); + if (ret < 0) + return ret; + + first_mode = sys_desc[0] + sys_desc[1]; + + for (u32 i = 0; i < sys_desc[3]; i++) { + ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_LIST_IDS, + i + first_mode, &out_data); + + if (ret == -EIO) + return ret; + + if (ret == -EBADRQC) + break; + + if (!is_wmax_thermal_code(out_data)) + continue; + + mode = out_data & WMAX_THERMAL_MODE_MASK; + profile = wmax_mode_to_platform_profile[mode]; + priv->supported_thermal_profiles[profile] = out_data; + + set_bit(profile, choices); + } + + if (bitmap_empty(choices, PLATFORM_PROFILE_LAST)) + return -ENODEV; + + if (awcc->gmode) { + priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] = + WMAX_THERMAL_MODE_GMODE; + + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); + } + + return 0; +} + +static const struct platform_profile_ops awcc_platform_profile_ops = { + .probe = thermal_profile_probe, + .profile_get = thermal_profile_get, + .profile_set = thermal_profile_set, +}; + +static int awcc_platform_profile_init(struct wmi_device *wdev) +{ + struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); + + priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi", + priv, &awcc_platform_profile_ops); + + return PTR_ERR_OR_ZERO(priv->ppdev); +} + +static int alienware_awcc_setup(struct wmi_device *wdev) +{ + struct awcc_priv *priv; + int ret; + + priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->wdev = wdev; + dev_set_drvdata(&wdev->dev, priv); + + if (awcc->pprof) { + ret = awcc_platform_profile_init(wdev); + if (ret) + return ret; + } + + return 0; +} + +/* + * WMAX WMI driver + */ +static int wmax_wmi_update_led(struct alienfx_priv *priv, + struct wmi_device *wdev, u8 location) +{ + struct wmax_led_args in_args = { + .led_mask = 1 << location, + .colors = priv->colors[location], + .state = priv->lighting_control_state, + }; + + return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args, + sizeof(in_args), NULL); +} + +static int wmax_wmi_update_brightness(struct alienfx_priv *priv, + struct wmi_device *wdev, u8 brightness) +{ + struct wmax_brightness_args in_args = { + .led_mask = 0xFF, + .percentage = brightness, + }; + + return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args, + sizeof(in_args), NULL); +} + +static int wmax_wmi_probe(struct wmi_device *wdev, const void *context) +{ + struct alienfx_platdata pdata = { + .wdev = wdev, + .ops = { + .upd_led = wmax_wmi_update_led, + .upd_brightness = wmax_wmi_update_brightness, + }, + }; + int ret; + + if (awcc) + ret = alienware_awcc_setup(wdev); + else + ret = alienware_alienfx_setup(&pdata); + + return ret; +} + +static const struct wmi_device_id alienware_wmax_device_id_table[] = { + { WMAX_CONTROL_GUID, NULL }, + { }, +}; +MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table); + +static struct wmi_driver alienware_wmax_wmi_driver = { + .driver = { + .name = "alienware-wmi-wmax", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = alienware_wmax_device_id_table, + .probe = wmax_wmi_probe, + .no_singleton = true, +}; + +int __init alienware_wmax_wmi_init(void) +{ + const struct dmi_system_id *id; + + id = dmi_first_match(awcc_dmi_table); + if (id) + awcc = id->driver_data; + + if (force_platform_profile) { + if (!awcc) + awcc = &empty_quirks; + + awcc->pprof = true; + } + + if (force_gmode) { + if (awcc) + awcc->gmode = true; + else + pr_warn("force_gmode requires platform profile support\n"); + } + + return wmi_driver_register(&alienware_wmax_wmi_driver); +} + +void __exit alienware_wmax_wmi_exit(void) +{ + wmi_driver_unregister(&alienware_wmax_wmi_driver); +} diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c deleted file mode 100644 index e252e0cf47ef..000000000000 --- a/drivers/platform/x86/dell/alienware-wmi.c +++ /dev/null @@ -1,1249 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Alienware AlienFX control - * - * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/acpi.h> -#include <linux/bitfield.h> -#include <linux/bits.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/platform_profile.h> -#include <linux/dmi.h> -#include <linux/leds.h> - -#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492" -#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" -#define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492" - -#define WMAX_METHOD_HDMI_SOURCE 0x1 -#define WMAX_METHOD_HDMI_STATUS 0x2 -#define WMAX_METHOD_BRIGHTNESS 0x3 -#define WMAX_METHOD_ZONE_CONTROL 0x4 -#define WMAX_METHOD_HDMI_CABLE 0x5 -#define WMAX_METHOD_AMPLIFIER_CABLE 0x6 -#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B -#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C -#define WMAX_METHOD_THERMAL_INFORMATION 0x14 -#define WMAX_METHOD_THERMAL_CONTROL 0x15 -#define WMAX_METHOD_GAME_SHIFT_STATUS 0x25 - -#define WMAX_THERMAL_MODE_GMODE 0xAB - -#define WMAX_FAILURE_CODE 0xFFFFFFFF - -MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>"); -MODULE_DESCRIPTION("Alienware special feature control"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("wmi:" LEGACY_CONTROL_GUID); -MODULE_ALIAS("wmi:" WMAX_CONTROL_GUID); - -static bool force_platform_profile; -module_param_unsafe(force_platform_profile, bool, 0); -MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available"); - -static bool force_gmode; -module_param_unsafe(force_gmode, bool, 0); -MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected"); - -enum INTERFACE_FLAGS { - LEGACY, - WMAX, -}; - -enum LEGACY_CONTROL_STATES { - LEGACY_RUNNING = 1, - LEGACY_BOOTING = 0, - LEGACY_SUSPEND = 3, -}; - -enum WMAX_CONTROL_STATES { - WMAX_RUNNING = 0xFF, - WMAX_BOOTING = 0, - WMAX_SUSPEND = 3, -}; - -enum WMAX_THERMAL_INFORMATION_OPERATIONS { - WMAX_OPERATION_SYS_DESCRIPTION = 0x02, - WMAX_OPERATION_LIST_IDS = 0x03, - WMAX_OPERATION_CURRENT_PROFILE = 0x0B, -}; - -enum WMAX_THERMAL_CONTROL_OPERATIONS { - WMAX_OPERATION_ACTIVATE_PROFILE = 0x01, -}; - -enum WMAX_GAME_SHIFT_STATUS_OPERATIONS { - WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01, - WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02, -}; - -enum WMAX_THERMAL_TABLES { - WMAX_THERMAL_TABLE_BASIC = 0x90, - WMAX_THERMAL_TABLE_USTT = 0xA0, -}; - -enum wmax_thermal_mode { - THERMAL_MODE_USTT_BALANCED, - THERMAL_MODE_USTT_BALANCED_PERFORMANCE, - THERMAL_MODE_USTT_COOL, - THERMAL_MODE_USTT_QUIET, - THERMAL_MODE_USTT_PERFORMANCE, - THERMAL_MODE_USTT_LOW_POWER, - THERMAL_MODE_BASIC_QUIET, - THERMAL_MODE_BASIC_BALANCED, - THERMAL_MODE_BASIC_BALANCED_PERFORMANCE, - THERMAL_MODE_BASIC_PERFORMANCE, - THERMAL_MODE_LAST, -}; - -static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = { - [THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED, - [THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, - [THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL, - [THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET, - [THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, - [THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER, - [THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET, - [THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED, - [THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE, - [THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE, -}; - -struct quirk_entry { - u8 num_zones; - u8 hdmi_mux; - u8 amplifier; - u8 deepslp; - bool thermal; - bool gmode; -}; - -static struct quirk_entry *quirks; - - -static struct quirk_entry quirk_inspiron5675 = { - .num_zones = 2, - .hdmi_mux = 0, - .amplifier = 0, - .deepslp = 0, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_unknown = { - .num_zones = 2, - .hdmi_mux = 0, - .amplifier = 0, - .deepslp = 0, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_x51_r1_r2 = { - .num_zones = 3, - .hdmi_mux = 0, - .amplifier = 0, - .deepslp = 0, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_x51_r3 = { - .num_zones = 4, - .hdmi_mux = 0, - .amplifier = 1, - .deepslp = 0, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_asm100 = { - .num_zones = 2, - .hdmi_mux = 1, - .amplifier = 0, - .deepslp = 0, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_asm200 = { - .num_zones = 2, - .hdmi_mux = 1, - .amplifier = 0, - .deepslp = 1, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_asm201 = { - .num_zones = 2, - .hdmi_mux = 1, - .amplifier = 1, - .deepslp = 1, - .thermal = false, - .gmode = false, -}; - -static struct quirk_entry quirk_g_series = { - .num_zones = 0, - .hdmi_mux = 0, - .amplifier = 0, - .deepslp = 0, - .thermal = true, - .gmode = true, -}; - -static struct quirk_entry quirk_x_series = { - .num_zones = 0, - .hdmi_mux = 0, - .amplifier = 0, - .deepslp = 0, - .thermal = true, - .gmode = false, -}; - -static int __init dmi_matched(const struct dmi_system_id *dmi) -{ - quirks = dmi->driver_data; - return 1; -} - -static const struct dmi_system_id alienware_quirks[] __initconst = { - { - .callback = dmi_matched, - .ident = "Alienware ASM100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), - }, - .driver_data = &quirk_asm100, - }, - { - .callback = dmi_matched, - .ident = "Alienware ASM200", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), - }, - .driver_data = &quirk_asm200, - }, - { - .callback = dmi_matched, - .ident = "Alienware ASM201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), - }, - .driver_data = &quirk_asm201, - }, - { - .callback = dmi_matched, - .ident = "Alienware m16 R1 AMD", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"), - }, - .driver_data = &quirk_x_series, - }, - { - .callback = dmi_matched, - .ident = "Alienware m17 R5", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), - }, - .driver_data = &quirk_x_series, - }, - { - .callback = dmi_matched, - .ident = "Alienware m18 R2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"), - }, - .driver_data = &quirk_x_series, - }, - { - .callback = dmi_matched, - .ident = "Alienware x15 R1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"), - }, - .driver_data = &quirk_x_series, - }, - { - .callback = dmi_matched, - .ident = "Alienware x17 R2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"), - }, - .driver_data = &quirk_x_series, - }, - { - .callback = dmi_matched, - .ident = "Alienware X51 R1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), - }, - .driver_data = &quirk_x51_r1_r2, - }, - { - .callback = dmi_matched, - .ident = "Alienware X51 R2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), - }, - .driver_data = &quirk_x51_r1_r2, - }, - { - .callback = dmi_matched, - .ident = "Alienware X51 R3", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), - }, - .driver_data = &quirk_x51_r3, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G15 5510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G15 5511", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G15 5515", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G3 3500", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G3 3590", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. G5 5500", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"), - }, - .driver_data = &quirk_g_series, - }, - { - .callback = dmi_matched, - .ident = "Dell Inc. Inspiron 5675", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5675"), - }, - .driver_data = &quirk_inspiron5675, - }, - {} -}; - -struct color_platform { - u8 blue; - u8 green; - u8 red; -} __packed; - -struct wmax_brightness_args { - u32 led_mask; - u32 percentage; -}; - -struct wmax_basic_args { - u8 arg; -}; - -struct legacy_led_args { - struct color_platform colors; - u8 brightness; - u8 state; -} __packed; - -struct wmax_led_args { - u32 led_mask; - struct color_platform colors; - u8 state; -} __packed; - -struct wmax_u32_args { - u8 operation; - u8 arg1; - u8 arg2; - u8 arg3; -}; - -static struct platform_device *platform_device; -static struct color_platform colors[4]; -static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; - -static u8 interface; -static u8 lighting_control_state; -static u8 global_brightness; - -/* - * Helpers used for zone control - */ -static int parse_rgb(const char *buf, struct color_platform *colors) -{ - long unsigned int rgb; - int ret; - union color_union { - struct color_platform cp; - int package; - } repackager; - - ret = kstrtoul(buf, 16, &rgb); - if (ret) - return ret; - - /* RGB triplet notation is 24-bit hexadecimal */ - if (rgb > 0xFFFFFF) - return -EINVAL; - - repackager.package = rgb & 0x0f0f0f0f; - pr_debug("alienware-wmi: r: %d g:%d b: %d\n", - repackager.cp.red, repackager.cp.green, repackager.cp.blue); - *colors = repackager.cp; - return 0; -} - -/* - * Individual RGB zone control - */ -static int alienware_update_led(u8 location) -{ - int method_id; - acpi_status status; - char *guid; - struct acpi_buffer input; - struct legacy_led_args legacy_args; - struct wmax_led_args wmax_basic_args; - if (interface == WMAX) { - wmax_basic_args.led_mask = 1 << location; - wmax_basic_args.colors = colors[location]; - wmax_basic_args.state = lighting_control_state; - guid = WMAX_CONTROL_GUID; - method_id = WMAX_METHOD_ZONE_CONTROL; - - input.length = sizeof(wmax_basic_args); - input.pointer = &wmax_basic_args; - } else { - legacy_args.colors = colors[location]; - legacy_args.brightness = global_brightness; - legacy_args.state = 0; - if (lighting_control_state == LEGACY_BOOTING || - lighting_control_state == LEGACY_SUSPEND) { - guid = LEGACY_POWER_CONTROL_GUID; - legacy_args.state = lighting_control_state; - } else - guid = LEGACY_CONTROL_GUID; - method_id = location + 1; - - input.length = sizeof(legacy_args); - input.pointer = &legacy_args; - } - pr_debug("alienware-wmi: guid %s method %d\n", guid, method_id); - - status = wmi_evaluate_method(guid, 0, method_id, &input, NULL); - if (ACPI_FAILURE(status)) - pr_err("alienware-wmi: zone set failure: %u\n", status); - return ACPI_FAILURE(status); -} - -static ssize_t zone_show(struct device *dev, struct device_attribute *attr, - char *buf, u8 location) -{ - return sprintf(buf, "red: %d, green: %d, blue: %d\n", - colors[location].red, colors[location].green, - colors[location].blue); - -} - -static ssize_t zone_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count, u8 location) -{ - int ret; - - ret = parse_rgb(buf, &colors[location]); - if (ret) - return ret; - - ret = alienware_update_led(location); - - return ret ? ret : count; -} - -static ssize_t zone00_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return zone_show(dev, attr, buf, 0); -} - -static ssize_t zone00_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return zone_store(dev, attr, buf, count, 0); -} - -static DEVICE_ATTR_RW(zone00); - -static ssize_t zone01_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return zone_show(dev, attr, buf, 1); -} - -static ssize_t zone01_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return zone_store(dev, attr, buf, count, 1); -} - -static DEVICE_ATTR_RW(zone01); - -static ssize_t zone02_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return zone_show(dev, attr, buf, 2); -} - -static ssize_t zone02_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return zone_store(dev, attr, buf, count, 2); -} - -static DEVICE_ATTR_RW(zone02); - -static ssize_t zone03_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return zone_show(dev, attr, buf, 3); -} - -static ssize_t zone03_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return zone_store(dev, attr, buf, count, 3); -} - -static DEVICE_ATTR_RW(zone03); - -/* - * Lighting control state device attribute (Global) - */ -static ssize_t lighting_control_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - if (lighting_control_state == LEGACY_BOOTING) - return sysfs_emit(buf, "[booting] running suspend\n"); - else if (lighting_control_state == LEGACY_SUSPEND) - return sysfs_emit(buf, "booting running [suspend]\n"); - - return sysfs_emit(buf, "booting [running] suspend\n"); -} - -static ssize_t lighting_control_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u8 val; - - if (strcmp(buf, "booting\n") == 0) - val = LEGACY_BOOTING; - else if (strcmp(buf, "suspend\n") == 0) - val = LEGACY_SUSPEND; - else if (interface == LEGACY) - val = LEGACY_RUNNING; - else - val = WMAX_RUNNING; - - lighting_control_state = val; - pr_debug("alienware-wmi: updated control state to %d\n", - lighting_control_state); - - return count; -} - -static DEVICE_ATTR_RW(lighting_control_state); - -static umode_t zone_attr_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - if (n < quirks->num_zones + 1) - return attr->mode; - - return 0; -} - -static bool zone_group_visible(struct kobject *kobj) -{ - return quirks->num_zones > 0; -} -DEFINE_SYSFS_GROUP_VISIBLE(zone); - -static struct attribute *zone_attrs[] = { - &dev_attr_lighting_control_state.attr, - &dev_attr_zone00.attr, - &dev_attr_zone01.attr, - &dev_attr_zone02.attr, - &dev_attr_zone03.attr, - NULL -}; - -static struct attribute_group zone_attribute_group = { - .name = "rgb_zones", - .is_visible = SYSFS_GROUP_VISIBLE(zone), - .attrs = zone_attrs, -}; - -/* - * LED Brightness (Global) - */ -static int wmax_brightness(int brightness) -{ - acpi_status status; - struct acpi_buffer input; - struct wmax_brightness_args args = { - .led_mask = 0xFF, - .percentage = brightness, - }; - input.length = sizeof(args); - input.pointer = &args; - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0, - WMAX_METHOD_BRIGHTNESS, &input, NULL); - if (ACPI_FAILURE(status)) - pr_err("alienware-wmi: brightness set failure: %u\n", status); - return ACPI_FAILURE(status); -} - -static void global_led_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - int ret; - global_brightness = brightness; - if (interface == WMAX) - ret = wmax_brightness(brightness); - else - ret = alienware_update_led(0); - if (ret) - pr_err("LED brightness update failed\n"); -} - -static enum led_brightness global_led_get(struct led_classdev *led_cdev) -{ - return global_brightness; -} - -static struct led_classdev global_led = { - .brightness_set = global_led_set, - .brightness_get = global_led_get, - .name = "alienware::global_brightness", -}; - -static int alienware_zone_init(struct platform_device *dev) -{ - if (interface == WMAX) { - lighting_control_state = WMAX_RUNNING; - } else if (interface == LEGACY) { - lighting_control_state = LEGACY_RUNNING; - } - global_led.max_brightness = 0x0F; - global_brightness = global_led.max_brightness; - - return led_classdev_register(&dev->dev, &global_led); -} - -static void alienware_zone_exit(struct platform_device *dev) -{ - if (!quirks->num_zones) - return; - - led_classdev_unregister(&global_led); -} - -static acpi_status alienware_wmax_command(void *in_args, size_t in_size, - u32 command, u32 *out_data) -{ - acpi_status status; - union acpi_object *obj; - struct acpi_buffer input; - struct acpi_buffer output; - - input.length = in_size; - input.pointer = in_args; - if (out_data) { - output.length = ACPI_ALLOCATE_BUFFER; - output.pointer = NULL; - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0, - command, &input, &output); - if (ACPI_SUCCESS(status)) { - obj = (union acpi_object *)output.pointer; - if (obj && obj->type == ACPI_TYPE_INTEGER) - *out_data = (u32)obj->integer.value; - } - kfree(output.pointer); - } else { - status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0, - command, &input, NULL); - } - return status; -} - -/* - * The HDMI mux sysfs node indicates the status of the HDMI input mux. - * It can toggle between standard system GPU output and HDMI input. - */ -static ssize_t cable_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct wmax_basic_args in_args = { - .arg = 0, - }; - acpi_status status; - u32 out_data; - - status = - alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_HDMI_CABLE, &out_data); - if (ACPI_SUCCESS(status)) { - if (out_data == 0) - return sysfs_emit(buf, "[unconnected] connected unknown\n"); - else if (out_data == 1) - return sysfs_emit(buf, "unconnected [connected] unknown\n"); - } - pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status); - return sysfs_emit(buf, "unconnected connected [unknown]\n"); -} - -static ssize_t source_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct wmax_basic_args in_args = { - .arg = 0, - }; - acpi_status status; - u32 out_data; - - status = - alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_HDMI_STATUS, &out_data); - - if (ACPI_SUCCESS(status)) { - if (out_data == 1) - return sysfs_emit(buf, "[input] gpu unknown\n"); - else if (out_data == 2) - return sysfs_emit(buf, "input [gpu] unknown\n"); - } - pr_err("alienware-wmi: unknown HDMI source status: %u\n", status); - return sysfs_emit(buf, "input gpu [unknown]\n"); -} - -static ssize_t source_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct wmax_basic_args args; - acpi_status status; - - if (strcmp(buf, "gpu\n") == 0) - args.arg = 1; - else if (strcmp(buf, "input\n") == 0) - args.arg = 2; - else - args.arg = 3; - pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); - - status = alienware_wmax_command(&args, sizeof(args), - WMAX_METHOD_HDMI_SOURCE, NULL); - - if (ACPI_FAILURE(status)) - pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", - status); - return count; -} - -static DEVICE_ATTR_RO(cable); -static DEVICE_ATTR_RW(source); - -static bool hdmi_group_visible(struct kobject *kobj) -{ - return quirks->hdmi_mux; -} -DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi); - -static struct attribute *hdmi_attrs[] = { - &dev_attr_cable.attr, - &dev_attr_source.attr, - NULL, -}; - -static const struct attribute_group hdmi_attribute_group = { - .name = "hdmi", - .is_visible = SYSFS_GROUP_VISIBLE(hdmi), - .attrs = hdmi_attrs, -}; - -/* - * Alienware GFX amplifier support - * - Currently supports reading cable status - * - Leaving expansion room to possibly support dock/undock events later - */ -static ssize_t status_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct wmax_basic_args in_args = { - .arg = 0, - }; - acpi_status status; - u32 out_data; - - status = - alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_AMPLIFIER_CABLE, &out_data); - if (ACPI_SUCCESS(status)) { - if (out_data == 0) - return sysfs_emit(buf, "[unconnected] connected unknown\n"); - else if (out_data == 1) - return sysfs_emit(buf, "unconnected [connected] unknown\n"); - } - pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status); - return sysfs_emit(buf, "unconnected connected [unknown]\n"); -} - -static DEVICE_ATTR_RO(status); - -static bool amplifier_group_visible(struct kobject *kobj) -{ - return quirks->amplifier; -} -DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier); - -static struct attribute *amplifier_attrs[] = { - &dev_attr_status.attr, - NULL, -}; - -static const struct attribute_group amplifier_attribute_group = { - .name = "amplifier", - .is_visible = SYSFS_GROUP_VISIBLE(amplifier), - .attrs = amplifier_attrs, -}; - -/* - * Deep Sleep Control support - * - Modifies BIOS setting for deep sleep control allowing extra wakeup events - */ -static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct wmax_basic_args in_args = { - .arg = 0, - }; - acpi_status status; - u32 out_data; - - status = alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_DEEP_SLEEP_STATUS, &out_data); - if (ACPI_SUCCESS(status)) { - if (out_data == 0) - return sysfs_emit(buf, "[disabled] s5 s5_s4\n"); - else if (out_data == 1) - return sysfs_emit(buf, "disabled [s5] s5_s4\n"); - else if (out_data == 2) - return sysfs_emit(buf, "disabled s5 [s5_s4]\n"); - } - pr_err("alienware-wmi: unknown deep sleep status: %d\n", status); - return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n"); -} - -static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct wmax_basic_args args; - acpi_status status; - - if (strcmp(buf, "disabled\n") == 0) - args.arg = 0; - else if (strcmp(buf, "s5\n") == 0) - args.arg = 1; - else - args.arg = 2; - pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); - - status = alienware_wmax_command(&args, sizeof(args), - WMAX_METHOD_DEEP_SLEEP_CONTROL, NULL); - - if (ACPI_FAILURE(status)) - pr_err("alienware-wmi: deep sleep control failed: results: %u\n", - status); - return count; -} - -static DEVICE_ATTR_RW(deepsleep); - -static bool deepsleep_group_visible(struct kobject *kobj) -{ - return quirks->deepslp; -} -DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep); - -static struct attribute *deepsleep_attrs[] = { - &dev_attr_deepsleep.attr, - NULL, -}; - -static const struct attribute_group deepsleep_attribute_group = { - .name = "deepsleep", - .is_visible = SYSFS_GROUP_VISIBLE(deepsleep), - .attrs = deepsleep_attrs, -}; - -/* - * Thermal Profile control - * - Provides thermal profile control through the Platform Profile API - */ -#define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4) -#define WMAX_THERMAL_MODE_MASK GENMASK(3, 0) -#define WMAX_SENSOR_ID_MASK BIT(8) - -static bool is_wmax_thermal_code(u32 code) -{ - if (code & WMAX_SENSOR_ID_MASK) - return false; - - if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST) - return false; - - if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC && - (code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET) - return true; - - if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT && - (code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER) - return true; - - return false; -} - -static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data) -{ - struct wmax_u32_args in_args = { - .operation = operation, - .arg1 = arg, - .arg2 = 0, - .arg3 = 0, - }; - acpi_status status; - - status = alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_THERMAL_INFORMATION, - out_data); - - if (ACPI_FAILURE(status)) - return -EIO; - - if (*out_data == WMAX_FAILURE_CODE) - return -EBADRQC; - - return 0; -} - -static int wmax_thermal_control(u8 profile) -{ - struct wmax_u32_args in_args = { - .operation = WMAX_OPERATION_ACTIVATE_PROFILE, - .arg1 = profile, - .arg2 = 0, - .arg3 = 0, - }; - acpi_status status; - u32 out_data; - - status = alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_THERMAL_CONTROL, - &out_data); - - if (ACPI_FAILURE(status)) - return -EIO; - - if (out_data == WMAX_FAILURE_CODE) - return -EBADRQC; - - return 0; -} - -static int wmax_game_shift_status(u8 operation, u32 *out_data) -{ - struct wmax_u32_args in_args = { - .operation = operation, - .arg1 = 0, - .arg2 = 0, - .arg3 = 0, - }; - acpi_status status; - - status = alienware_wmax_command(&in_args, sizeof(in_args), - WMAX_METHOD_GAME_SHIFT_STATUS, - out_data); - - if (ACPI_FAILURE(status)) - return -EIO; - - if (*out_data == WMAX_FAILURE_CODE) - return -EOPNOTSUPP; - - return 0; -} - -static int thermal_profile_get(struct device *dev, - enum platform_profile_option *profile) -{ - u32 out_data; - int ret; - - ret = wmax_thermal_information(WMAX_OPERATION_CURRENT_PROFILE, - 0, &out_data); - - if (ret < 0) - return ret; - - if (out_data == WMAX_THERMAL_MODE_GMODE) { - *profile = PLATFORM_PROFILE_PERFORMANCE; - return 0; - } - - if (!is_wmax_thermal_code(out_data)) - return -ENODATA; - - out_data &= WMAX_THERMAL_MODE_MASK; - *profile = wmax_mode_to_platform_profile[out_data]; - - return 0; -} - -static int thermal_profile_set(struct device *dev, - enum platform_profile_option profile) -{ - if (quirks->gmode) { - u32 gmode_status; - int ret; - - ret = wmax_game_shift_status(WMAX_OPERATION_GET_GAME_SHIFT_STATUS, - &gmode_status); - - if (ret < 0) - return ret; - - if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) || - (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) { - ret = wmax_game_shift_status(WMAX_OPERATION_TOGGLE_GAME_SHIFT, - &gmode_status); - - if (ret < 0) - return ret; - } - } - - return wmax_thermal_control(supported_thermal_profiles[profile]); -} - -static int thermal_profile_probe(void *drvdata, unsigned long *choices) -{ - enum platform_profile_option profile; - enum wmax_thermal_mode mode; - u8 sys_desc[4]; - u32 first_mode; - u32 out_data; - int ret; - - ret = wmax_thermal_information(WMAX_OPERATION_SYS_DESCRIPTION, - 0, (u32 *) &sys_desc); - if (ret < 0) - return ret; - - first_mode = sys_desc[0] + sys_desc[1]; - - for (u32 i = 0; i < sys_desc[3]; i++) { - ret = wmax_thermal_information(WMAX_OPERATION_LIST_IDS, - i + first_mode, &out_data); - - if (ret == -EIO) - return ret; - - if (ret == -EBADRQC) - break; - - if (!is_wmax_thermal_code(out_data)) - continue; - - mode = out_data & WMAX_THERMAL_MODE_MASK; - profile = wmax_mode_to_platform_profile[mode]; - supported_thermal_profiles[profile] = out_data; - - set_bit(profile, choices); - } - - if (bitmap_empty(choices, PLATFORM_PROFILE_LAST)) - return -ENODEV; - - if (quirks->gmode) { - supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] = - WMAX_THERMAL_MODE_GMODE; - - set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); - } - - return 0; -} - -static const struct platform_profile_ops awcc_platform_profile_ops = { - .probe = thermal_profile_probe, - .profile_get = thermal_profile_get, - .profile_set = thermal_profile_set, -}; - -static int create_thermal_profile(struct platform_device *platform_device) -{ - struct device *ppdev; - - ppdev = devm_platform_profile_register(&platform_device->dev, "alienware-wmi", - NULL, &awcc_platform_profile_ops); - - return PTR_ERR_OR_ZERO(ppdev); -} - -/* - * Platform Driver - */ -static const struct attribute_group *alienfx_groups[] = { - &zone_attribute_group, - &hdmi_attribute_group, - &lifier_attribute_group, - &deepsleep_attribute_group, - NULL -}; - -static struct platform_driver platform_driver = { - .driver = { - .name = "alienware-wmi", - .dev_groups = alienfx_groups, - }, -}; - -static int __init alienware_wmi_init(void) -{ - int ret; - - if (wmi_has_guid(LEGACY_CONTROL_GUID)) - interface = LEGACY; - else if (wmi_has_guid(WMAX_CONTROL_GUID)) - interface = WMAX; - else { - pr_warn("alienware-wmi: No known WMI GUID found\n"); - return -ENODEV; - } - - dmi_check_system(alienware_quirks); - if (quirks == NULL) - quirks = &quirk_unknown; - - if (force_platform_profile) - quirks->thermal = true; - - if (force_gmode) { - if (quirks->thermal) - quirks->gmode = true; - else - pr_warn("force_gmode requires platform profile support\n"); - } - - ret = platform_driver_register(&platform_driver); - if (ret) - goto fail_platform_driver; - platform_device = platform_device_alloc("alienware-wmi", PLATFORM_DEVID_NONE); - if (!platform_device) { - ret = -ENOMEM; - goto fail_platform_device1; - } - ret = platform_device_add(platform_device); - if (ret) - goto fail_platform_device2; - - if (quirks->thermal) { - ret = create_thermal_profile(platform_device); - if (ret) - goto fail_prep_thermal_profile; - } - - if (quirks->num_zones > 0) { - ret = alienware_zone_init(platform_device); - if (ret) - goto fail_prep_zones; - } - - return 0; - -fail_prep_zones: - alienware_zone_exit(platform_device); -fail_prep_thermal_profile: - platform_device_del(platform_device); -fail_platform_device2: - platform_device_put(platform_device); -fail_platform_device1: - platform_driver_unregister(&platform_driver); -fail_platform_driver: - return ret; -} - -module_init(alienware_wmi_init); - -static void __exit alienware_wmi_exit(void) -{ - alienware_zone_exit(platform_device); - platform_device_unregister(platform_device); - platform_driver_unregister(&platform_driver); -} - -module_exit(alienware_wmi_exit); diff --git a/drivers/platform/x86/dell/alienware-wmi.h b/drivers/platform/x86/dell/alienware-wmi.h new file mode 100644 index 000000000000..68d4242211ae --- /dev/null +++ b/drivers/platform/x86/dell/alienware-wmi.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Alienware WMI special features driver + * + * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com> + * Copyright (C) 2024 Kurt Borja <kuurtb@gmail.com> + */ + +#ifndef _ALIENWARE_WMI_H_ +#define _ALIENWARE_WMI_H_ + +#include <linux/leds.h> +#include <linux/platform_device.h> +#include <linux/wmi.h> + +#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492" +#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" +#define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492" + +enum INTERFACE_FLAGS { + LEGACY, + WMAX, +}; + +enum LEGACY_CONTROL_STATES { + LEGACY_RUNNING = 1, + LEGACY_BOOTING = 0, + LEGACY_SUSPEND = 3, +}; + +enum WMAX_CONTROL_STATES { + WMAX_RUNNING = 0xFF, + WMAX_BOOTING = 0, + WMAX_SUSPEND = 3, +}; + +struct alienfx_quirks { + u8 num_zones; + bool hdmi_mux; + bool amplifier; + bool deepslp; +}; + +struct color_platform { + u8 blue; + u8 green; + u8 red; +} __packed; + +struct alienfx_priv { + struct platform_device *pdev; + struct led_classdev global_led; + struct color_platform colors[4]; + u8 global_brightness; + u8 lighting_control_state; +}; + +struct alienfx_ops { + int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev, + u8 location); + int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev, + u8 brightness); +}; + +struct alienfx_platdata { + struct wmi_device *wdev; + struct alienfx_ops ops; +}; + +extern u8 alienware_interface; +extern struct alienfx_quirks *alienfx; + +int alienware_wmi_command(struct wmi_device *wdev, u32 method_id, + void *in_args, size_t in_size, u32 *out_data); + +int alienware_alienfx_setup(struct alienfx_platdata *pdata); + +#if IS_ENABLED(CONFIG_ALIENWARE_WMI_LEGACY) +int __init alienware_legacy_wmi_init(void); +void __exit alienware_legacy_wmi_exit(void); +#else +static inline int alienware_legacy_wmi_init(void) +{ + return -ENODEV; +} + +static inline void alienware_legacy_wmi_exit(void) +{ +} +#endif + +#if IS_ENABLED(CONFIG_ALIENWARE_WMI_WMAX) +extern const struct attribute_group wmax_hdmi_attribute_group; +extern const struct attribute_group wmax_amplifier_attribute_group; +extern const struct attribute_group wmax_deepsleep_attribute_group; + +#define WMAX_DEV_GROUPS &wmax_hdmi_attribute_group, \ + &wmax_amplifier_attribute_group, \ + &wmax_deepsleep_attribute_group, + +int __init alienware_wmax_wmi_init(void); +void __exit alienware_wmax_wmi_exit(void); +#else +#define WMAX_DEV_GROUPS + +static inline int alienware_wmax_wmi_init(void) +{ + return -ENODEV; +} + + +static inline void alienware_wmax_wmi_exit(void) +{ +} +#endif + +#endif diff --git a/drivers/platform/x86/dell/dell-uart-backlight.c b/drivers/platform/x86/dell/dell-uart-backlight.c index 50002ef13d5d..8f868f845350 100644 --- a/drivers/platform/x86/dell/dell-uart-backlight.c +++ b/drivers/platform/x86/dell/dell-uart-backlight.c @@ -325,7 +325,7 @@ static int dell_uart_bl_serdev_probe(struct serdev_device *serdev) return PTR_ERR_OR_ZERO(dell_bl->bl); } -struct serdev_device_driver dell_uart_bl_serdev_driver = { +static struct serdev_device_driver dell_uart_bl_serdev_driver = { .probe = dell_uart_bl_serdev_probe, .driver = { .name = KBUILD_MODNAME, diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c index e75cd6e1efe6..f27739da380f 100644 --- a/drivers/platform/x86/dell/dell-wmi-ddv.c +++ b/drivers/platform/x86/dell/dell-wmi-ddv.c @@ -104,7 +104,6 @@ struct dell_wmi_ddv_sensors { struct dell_wmi_ddv_data { struct acpi_battery_hook hook; - struct device_attribute temp_attr; struct device_attribute eppid_attr; struct dell_wmi_ddv_sensors fans; struct dell_wmi_ddv_sensors temps; @@ -651,24 +650,6 @@ static int dell_wmi_ddv_battery_index(struct acpi_device *acpi_dev, u32 *index) return kstrtou32(uid_str, 10, index); } -static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct dell_wmi_ddv_data *data = container_of(attr, struct dell_wmi_ddv_data, temp_attr); - u32 index, value; - int ret; - - ret = dell_wmi_ddv_battery_index(to_acpi_device(dev->parent), &index); - if (ret < 0) - return ret; - - ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index, &value); - if (ret < 0) - return ret; - - /* Use 2731 instead of 2731.5 to avoid unnecessary rounding */ - return sysfs_emit(buf, "%d\n", value - 2731); -} - static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dell_wmi_ddv_data *data = container_of(attr, struct dell_wmi_ddv_data, eppid_attr); @@ -695,6 +676,46 @@ static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, cha return ret; } +static int dell_wmi_ddv_get_property(struct power_supply *psy, const struct power_supply_ext *ext, + void *drvdata, enum power_supply_property psp, + union power_supply_propval *val) +{ + struct dell_wmi_ddv_data *data = drvdata; + u32 index, value; + int ret; + + ret = dell_wmi_ddv_battery_index(to_acpi_device(psy->dev.parent), &index); + if (ret < 0) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_TEMP: + ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index, + &value); + if (ret < 0) + return ret; + + /* Use 2732 instead of 2731.5 to avoid unnecessary rounding and to emulate + * the behaviour of the OEM application which seems to round down the result. + */ + val->intval = value - 2732; + return 0; + default: + return -EINVAL; + } +} + +static const enum power_supply_property dell_wmi_ddv_properties[] = { + POWER_SUPPLY_PROP_TEMP, +}; + +static const struct power_supply_ext dell_wmi_ddv_extension = { + .name = DRIVER_NAME, + .properties = dell_wmi_ddv_properties, + .num_properties = ARRAY_SIZE(dell_wmi_ddv_properties), + .get_property = dell_wmi_ddv_get_property, +}; + static int dell_wmi_ddv_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook) { struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook); @@ -706,13 +727,14 @@ static int dell_wmi_ddv_add_battery(struct power_supply *battery, struct acpi_ba if (ret < 0) return 0; - ret = device_create_file(&battery->dev, &data->temp_attr); + ret = device_create_file(&battery->dev, &data->eppid_attr); if (ret < 0) return ret; - ret = device_create_file(&battery->dev, &data->eppid_attr); + ret = power_supply_register_extension(battery, &dell_wmi_ddv_extension, &data->wdev->dev, + data); if (ret < 0) { - device_remove_file(&battery->dev, &data->temp_attr); + device_remove_file(&battery->dev, &data->eppid_attr); return ret; } @@ -724,38 +746,24 @@ static int dell_wmi_ddv_remove_battery(struct power_supply *battery, struct acpi { struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook); - device_remove_file(&battery->dev, &data->temp_attr); device_remove_file(&battery->dev, &data->eppid_attr); + power_supply_unregister_extension(battery, &dell_wmi_ddv_extension); return 0; } -static void dell_wmi_ddv_battery_remove(void *data) -{ - struct acpi_battery_hook *hook = data; - - battery_hook_unregister(hook); -} - static int dell_wmi_ddv_battery_add(struct dell_wmi_ddv_data *data) { data->hook.name = "Dell DDV Battery Extension"; data->hook.add_battery = dell_wmi_ddv_add_battery; data->hook.remove_battery = dell_wmi_ddv_remove_battery; - sysfs_attr_init(&data->temp_attr.attr); - data->temp_attr.attr.name = "temp"; - data->temp_attr.attr.mode = 0444; - data->temp_attr.show = temp_show; - sysfs_attr_init(&data->eppid_attr.attr); data->eppid_attr.attr.name = "eppid"; data->eppid_attr.attr.mode = 0444; data->eppid_attr.show = eppid_show; - battery_hook_register(&data->hook); - - return devm_add_action_or_reset(&data->wdev->dev, dell_wmi_ddv_battery_remove, &data->hook); + return devm_battery_hook_register(&data->wdev->dev, &data->hook); } static int dell_wmi_ddv_buffer_read(struct seq_file *seq, enum dell_ddv_method method) diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/Makefile b/drivers/platform/x86/dell/dell-wmi-sysman/Makefile index 825fb2fbeea8..0a6df449e222 100644 --- a/drivers/platform/x86/dell/dell-wmi-sysman/Makefile +++ b/drivers/platform/x86/dell/dell-wmi-sysman/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman.o -dell-wmi-sysman-objs := sysman.o \ +dell-wmi-sysman-y := sysman.o \ enum-attributes.o \ int-attributes.o \ string-attributes.o \ diff --git a/drivers/platform/x86/hp/hp-bioscfg/Makefile b/drivers/platform/x86/hp/hp-bioscfg/Makefile index 67be0d917753..7d23649b34dc 100644 --- a/drivers/platform/x86/hp/hp-bioscfg/Makefile +++ b/drivers/platform/x86/hp/hp-bioscfg/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_HP_BIOSCFG) := hp-bioscfg.o -hp-bioscfg-objs := bioscfg.o \ +hp-bioscfg-y := bioscfg.o \ biosattr-interface.o \ enum-attributes.o \ int-attributes.o \ diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c index 0b277b7e37dd..13237890fc92 100644 --- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c +++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c @@ -388,16 +388,13 @@ union acpi_object *hp_get_wmiobj_pointer(int instance_id, const char *guid_strin */ int hp_get_instance_count(const char *guid_string) { - union acpi_object *wmi_obj = NULL; - int i = 0; + int ret; - do { - kfree(wmi_obj); - wmi_obj = hp_get_wmiobj_pointer(i, guid_string); - i++; - } while (wmi_obj); + ret = wmi_instance_count(guid_string); + if (ret < 0) + return 0; - return i - 1; + return ret; } /** @@ -448,7 +445,7 @@ int hp_convert_hexstr_to_str(const char *input, u32 input_len, char **str, int * return -ENOMEM; for (i = 0; i < input_len; i += 5) { - strncpy(tmp, input + i, strlen(tmp)); + strscpy(tmp, input + i); if (kstrtol(tmp, 16, &ch) == 0) { // escape char if (ch == '\\' || diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 30bd366d7b58..17a09b7784ed 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -854,6 +854,7 @@ static const struct attribute_group ideapad_attribute_group = { .is_visible = ideapad_is_visible, .attrs = ideapad_attributes }; +__ATTRIBUTE_GROUPS(ideapad_attribute); /* * DYTC Platform profile @@ -1245,21 +1246,6 @@ static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev) } /* - * Platform device - */ -static int ideapad_sysfs_init(struct ideapad_private *priv) -{ - return device_add_group(&priv->platform_device->dev, - &ideapad_attribute_group); -} - -static void ideapad_sysfs_exit(struct ideapad_private *priv) -{ - device_remove_group(&priv->platform_device->dev, - &ideapad_attribute_group); -} - -/* * input device */ #define IDEAPAD_WMI_KEY 0x100 @@ -2175,10 +2161,6 @@ static int ideapad_acpi_add(struct platform_device *pdev) ideapad_check_features(priv); - err = ideapad_sysfs_init(priv); - if (err) - return err; - ideapad_debugfs_init(priv); err = ideapad_input_init(priv); @@ -2265,7 +2247,6 @@ backlight_failed: input_failed: ideapad_debugfs_exit(priv); - ideapad_sysfs_exit(priv); return err; } @@ -2293,7 +2274,6 @@ static void ideapad_acpi_remove(struct platform_device *pdev) ideapad_kbd_bl_exit(priv); ideapad_input_exit(priv); ideapad_debugfs_exit(priv); - ideapad_sysfs_exit(priv); } #ifdef CONFIG_PM_SLEEP @@ -2325,6 +2305,7 @@ static struct platform_driver ideapad_acpi_driver = { .name = "ideapad_acpi", .pm = &ideapad_pm, .acpi_match_table = ACPI_PTR(ideapad_device_ids), + .dev_groups = ideapad_attribute_groups, }, }; diff --git a/drivers/platform/x86/intel/ifs/Makefile b/drivers/platform/x86/intel/ifs/Makefile index 30f035ef5581..c3e417bce9b6 100644 --- a/drivers/platform/x86/intel/ifs/Makefile +++ b/drivers/platform/x86/intel/ifs/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_INTEL_IFS) += intel_ifs.o -intel_ifs-objs := core.o load.o runtest.o sysfs.o +intel_ifs-y := core.o load.o runtest.o sysfs.o diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index 092252eb95a8..30ff8f3ea1f5 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -56,7 +56,7 @@ static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *i static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, struct acpi_resource_gpio *agpio, - const char *func, unsigned long gpio_flags) + const char *con_id, unsigned long gpio_flags) { char *path = agpio->resource_source.string_ptr; struct acpi_device *adev; @@ -71,14 +71,14 @@ static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, if (!adev) return -ENODEV; - *table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, gpio_flags); + *table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], con_id, gpio_flags); return 0; } static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio, - const char *func, unsigned long gpio_flags) + const char *con_id, unsigned long gpio_flags) { int ret; @@ -88,7 +88,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 } ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios], - agpio, func, gpio_flags); + agpio, con_id, gpio_flags); if (ret) return ret; @@ -101,7 +101,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 static struct gpio_desc * skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, struct acpi_resource_gpio *agpio, - const char *func, unsigned long gpio_flags) + const char *con_id, unsigned long gpio_flags) { struct gpio_desc *desc; int ret; @@ -112,12 +112,12 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, return ERR_PTR(-ENOMEM); lookup->dev_id = dev_name(int3472->dev); - ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, gpio_flags); + ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, con_id, gpio_flags); if (ret) return ERR_PTR(ret); gpiod_add_lookup_table(lookup); - desc = devm_gpiod_get(int3472->dev, func, GPIOD_OUT_LOW); + desc = devm_gpiod_get(int3472->dev, con_id, GPIOD_OUT_LOW); gpiod_remove_lookup_table(lookup); return desc; @@ -129,7 +129,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, * @hid: The ACPI HID of the device without the instance number e.g. INT347E * @type_from: The GPIO type from ACPI ?SDT * @type_to: The assigned GPIO type, typically same as @type_from - * @func: The function, e.g. "enable" + * @con_id: The name of the GPIO for the device * @polarity_low: GPIO_ACTIVE_LOW true if the @polarity_low is true, * GPIO_ACTIVE_HIGH otherwise */ @@ -138,15 +138,15 @@ struct int3472_gpio_map { u8 type_from; u8 type_to; bool polarity_low; - const char *func; + const char *con_id; }; static const struct int3472_gpio_map int3472_gpio_map[] = { { "INT347E", INT3472_GPIO_TYPE_RESET, INT3472_GPIO_TYPE_RESET, false, "enable" }, }; -static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type, - const char **func, unsigned long *gpio_flags) +static void int3472_get_con_id_and_polarity(struct acpi_device *adev, u8 *type, + const char **con_id, unsigned long *gpio_flags) { unsigned int i; @@ -165,33 +165,33 @@ static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type, *type = int3472_gpio_map[i].type_to; *gpio_flags = int3472_gpio_map[i].polarity_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; - *func = int3472_gpio_map[i].func; + *con_id = int3472_gpio_map[i].con_id; return; } switch (*type) { case INT3472_GPIO_TYPE_RESET: - *func = "reset"; + *con_id = "reset"; *gpio_flags = GPIO_ACTIVE_LOW; break; case INT3472_GPIO_TYPE_POWERDOWN: - *func = "powerdown"; + *con_id = "powerdown"; *gpio_flags = GPIO_ACTIVE_LOW; break; case INT3472_GPIO_TYPE_CLK_ENABLE: - *func = "clk-enable"; + *con_id = "clk-enable"; *gpio_flags = GPIO_ACTIVE_HIGH; break; case INT3472_GPIO_TYPE_PRIVACY_LED: - *func = "privacy-led"; + *con_id = "privacy-led"; *gpio_flags = GPIO_ACTIVE_HIGH; break; case INT3472_GPIO_TYPE_POWER_ENABLE: - *func = "power-enable"; + *con_id = "power-enable"; *gpio_flags = GPIO_ACTIVE_HIGH; break; default: - *func = "unknown"; + *con_id = "unknown"; *gpio_flags = GPIO_ACTIVE_HIGH; break; } @@ -238,7 +238,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, union acpi_object *obj; struct gpio_desc *gpio; const char *err_msg; - const char *func; + const char *con_id; unsigned long gpio_flags; int ret; @@ -262,26 +262,26 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); - int3472_get_func_and_polarity(int3472->sensor, &type, &func, &gpio_flags); + int3472_get_con_id_and_polarity(int3472->sensor, &type, &con_id, &gpio_flags); pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); /* Pin field is not really used under Windows and wraps around at 8 bits */ if (pin != (agpio->pin_table[0] & 0xff)) dev_dbg(int3472->dev, FW_BUG "%s %s pin number mismatch _DSM %d resource %d\n", - func, agpio->resource_source.string_ptr, pin, agpio->pin_table[0]); + con_id, agpio->resource_source.string_ptr, pin, agpio->pin_table[0]); active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); if (!active_value) gpio_flags ^= GPIO_ACTIVE_LOW; - dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func, + dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", con_id, agpio->resource_source.string_ptr, agpio->pin_table[0], str_high_low(gpio_flags == GPIO_ACTIVE_HIGH)); switch (type) { case INT3472_GPIO_TYPE_RESET: case INT3472_GPIO_TYPE_POWERDOWN: - ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, gpio_flags); + ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, con_id, gpio_flags); if (ret) err_msg = "Failed to map GPIO pin to sensor\n"; @@ -289,7 +289,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, case INT3472_GPIO_TYPE_CLK_ENABLE: case INT3472_GPIO_TYPE_PRIVACY_LED: case INT3472_GPIO_TYPE_POWER_ENABLE: - gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, gpio_flags); + gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, con_id, gpio_flags); if (IS_ERR(gpio)) { ret = PTR_ERR(gpio); err_msg = "Failed to get GPIO\n"; diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile index 389e5419dadf..b148b40d09f5 100644 --- a/drivers/platform/x86/intel/pmc/Makefile +++ b/drivers/platform/x86/intel/pmc/Makefile @@ -4,7 +4,7 @@ # intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \ - icl.o tgl.o adl.o mtl.o arl.o lnl.o + icl.o tgl.o adl.o mtl.o arl.o lnl.o ptl.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv-y := pltdrv.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c index e7878558fd90..9e7dfd6e3310 100644 --- a/drivers/platform/x86/intel/pmc/adl.c +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -11,7 +11,7 @@ #include "core.h" /* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */ -const struct pmc_bit_map adl_pfear_map[] = { +static const struct pmc_bit_map adl_pfear_map[] = { {"SPI/eSPI", BIT(2)}, {"XHCI", BIT(3)}, {"SPA", BIT(4)}, @@ -54,7 +54,7 @@ const struct pmc_bit_map adl_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_adl_pfear_map[] = { +static const struct pmc_bit_map *ext_adl_pfear_map[] = { /* * Check intel_pmc_core_ids[] users of cnp_reg_map for * a list of core SoCs using this. @@ -63,7 +63,7 @@ const struct pmc_bit_map *ext_adl_pfear_map[] = { NULL }; -const struct pmc_bit_map adl_ltr_show_map[] = { +static const struct pmc_bit_map adl_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -100,7 +100,7 @@ const struct pmc_bit_map adl_ltr_show_map[] = { {} }; -const struct pmc_bit_map adl_clocksource_status_map[] = { +static const struct pmc_bit_map adl_clocksource_status_map[] = { {"CLKPART1_OFF_STS", BIT(0)}, {"CLKPART2_OFF_STS", BIT(1)}, {"CLKPART3_OFF_STS", BIT(2)}, @@ -128,7 +128,7 @@ const struct pmc_bit_map adl_clocksource_status_map[] = { {} }; -const struct pmc_bit_map adl_power_gating_status_0_map[] = { +static const struct pmc_bit_map adl_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0)}, {"DMI_PGD0_PG_STS", BIT(1)}, {"ESPISPI_PGD0_PG_STS", BIT(2)}, @@ -158,7 +158,7 @@ const struct pmc_bit_map adl_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map adl_power_gating_status_1_map[] = { +static const struct pmc_bit_map adl_power_gating_status_1_map[] = { {"USBR0_PGD0_PG_STS", BIT(0)}, {"SMT1_PGD0_PG_STS", BIT(2)}, {"CSMERTC_PGD0_PG_STS", BIT(6)}, @@ -170,14 +170,14 @@ const struct pmc_bit_map adl_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map adl_power_gating_status_2_map[] = { +static const struct pmc_bit_map adl_power_gating_status_2_map[] = { {"THC0_PGD0_PG_STS", BIT(7)}, {"THC1_PGD0_PG_STS", BIT(8)}, {"SPF_PGD0_PG_STS", BIT(14)}, {} }; -const struct pmc_bit_map adl_d3_status_0_map[] = { +static const struct pmc_bit_map adl_d3_status_0_map[] = { {"ISH_D3_STS", BIT(2)}, {"LPSS_D3_STS", BIT(3)}, {"XDCI_D3_STS", BIT(4)}, @@ -193,13 +193,13 @@ const struct pmc_bit_map adl_d3_status_0_map[] = { {} }; -const struct pmc_bit_map adl_d3_status_1_map[] = { +static const struct pmc_bit_map adl_d3_status_1_map[] = { {"GBE_D3_STS", BIT(19)}, {"CNVI_D3_STS", BIT(27)}, {} }; -const struct pmc_bit_map adl_d3_status_2_map[] = { +static const struct pmc_bit_map adl_d3_status_2_map[] = { {"CSMERTC_D3_STS", BIT(1)}, {"CSE_D3_STS", BIT(4)}, {"KVMCC_D3_STS", BIT(5)}, @@ -210,20 +210,20 @@ const struct pmc_bit_map adl_d3_status_2_map[] = { {} }; -const struct pmc_bit_map adl_d3_status_3_map[] = { +static const struct pmc_bit_map adl_d3_status_3_map[] = { {"THC0_D3_STS", BIT(14)}, {"THC1_D3_STS", BIT(15)}, {} }; -const struct pmc_bit_map adl_vnn_req_status_0_map[] = { +static const struct pmc_bit_map adl_vnn_req_status_0_map[] = { {"ISH_VNN_REQ_STS", BIT(2)}, {"ESPISPI_VNN_REQ_STS", BIT(18)}, {"DSP_VNN_REQ_STS", BIT(19)}, {} }; -const struct pmc_bit_map adl_vnn_req_status_1_map[] = { +static const struct pmc_bit_map adl_vnn_req_status_1_map[] = { {"NPK_VNN_REQ_STS", BIT(4)}, {"EXI_VNN_REQ_STS", BIT(9)}, {"GBE_VNN_REQ_STS", BIT(19)}, @@ -232,7 +232,7 @@ const struct pmc_bit_map adl_vnn_req_status_1_map[] = { {} }; -const struct pmc_bit_map adl_vnn_req_status_2_map[] = { +static const struct pmc_bit_map adl_vnn_req_status_2_map[] = { {"CSMERTC_VNN_REQ_STS", BIT(1)}, {"CSE_VNN_REQ_STS", BIT(4)}, {"SMT1_VNN_REQ_STS", BIT(8)}, @@ -245,12 +245,12 @@ const struct pmc_bit_map adl_vnn_req_status_2_map[] = { {} }; -const struct pmc_bit_map adl_vnn_req_status_3_map[] = { +static const struct pmc_bit_map adl_vnn_req_status_3_map[] = { {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, {} }; -const struct pmc_bit_map adl_vnn_misc_status_map[] = { +static const struct pmc_bit_map adl_vnn_misc_status_map[] = { {"CPU_C10_REQ_STS", BIT(0)}, {"PCIe_LPM_En_REQ_STS", BIT(3)}, {"ITH_REQ_STS", BIT(5)}, @@ -265,7 +265,7 @@ const struct pmc_bit_map adl_vnn_misc_status_map[] = { {} }; -const struct pmc_bit_map *adl_lpm_maps[] = { +static const struct pmc_bit_map *adl_lpm_maps[] = { adl_clocksource_status_map, adl_power_gating_status_0_map, adl_power_gating_status_1_map, @@ -311,20 +311,8 @@ const struct pmc_reg_map adl_reg_map = { .pson_residency_counter_step = TGL_PSON_RES_COUNTER_STEP, }; -int adl_core_init(struct pmc_dev *pmcdev) -{ - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - int ret; - - pmcdev->suspend = cnl_suspend; - pmcdev->resume = cnl_resume; - - pmc->map = &adl_reg_map; - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - - pmc_core_get_low_power_modes(pmcdev); - - return 0; -} +struct pmc_dev_info adl_pmc_dev = { + .map = &adl_reg_map, + .suspend = cnl_suspend, + .resume = cnl_resume, +}; diff --git a/drivers/platform/x86/intel/pmc/arl.c b/drivers/platform/x86/intel/pmc/arl.c index 05dec4f5019f..320993bd6d31 100644 --- a/drivers/platform/x86/intel/pmc/arl.c +++ b/drivers/platform/x86/intel/pmc/arl.c @@ -16,10 +16,11 @@ #define IOEP_LPM_REQ_GUID 0x5077612 #define SOCS_LPM_REQ_GUID 0x8478657 #define PCHS_LPM_REQ_GUID 0x9684572 +#define SOCM_LPM_REQ_GUID 0x2625030 static const u8 ARL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20}; -const struct pmc_bit_map arl_socs_ltr_show_map[] = { +static const struct pmc_bit_map arl_socs_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -59,7 +60,7 @@ const struct pmc_bit_map arl_socs_ltr_show_map[] = { {} }; -const struct pmc_bit_map arl_socs_clocksource_status_map[] = { +static const struct pmc_bit_map arl_socs_clocksource_status_map[] = { {"AON2_OFF_STS", BIT(0)}, {"AON3_OFF_STS", BIT(1)}, {"AON4_OFF_STS", BIT(2)}, @@ -87,7 +88,7 @@ const struct pmc_bit_map arl_socs_clocksource_status_map[] = { {} }; -const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = { +static const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0)}, {"DMI_PGD0_PG_STS", BIT(1)}, {"ESPISPI_PGD0_PG_STS", BIT(2)}, @@ -123,7 +124,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = { +static const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = { {"USBR0_PGD0_PG_STS", BIT(0)}, {"SUSRAM_PGD0_PG_STS", BIT(1)}, {"SMT1_PGD0_PG_STS", BIT(2)}, @@ -159,7 +160,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = { +static const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = { {"PSF8_PGD0_PG_STS", BIT(0)}, {"FIA_PGD0_PG_STS", BIT(1)}, {"SOC_D2D_PGD3_PG_STS", BIT(2)}, @@ -187,7 +188,7 @@ const struct pmc_bit_map arl_socs_power_gating_status_2_map[] = { {} }; -const struct pmc_bit_map arl_socs_d3_status_2_map[] = { +static const struct pmc_bit_map arl_socs_d3_status_2_map[] = { {"CSMERTC_D3_STS", BIT(1)}, {"SUSRAM_D3_STS", BIT(2)}, {"CSE_D3_STS", BIT(4)}, @@ -206,7 +207,7 @@ const struct pmc_bit_map arl_socs_d3_status_2_map[] = { {} }; -const struct pmc_bit_map arl_socs_d3_status_3_map[] = { +static const struct pmc_bit_map arl_socs_d3_status_3_map[] = { {"GBETSN_D3_STS", BIT(13)}, {"THC0_D3_STS", BIT(14)}, {"THC1_D3_STS", BIT(15)}, @@ -214,13 +215,13 @@ const struct pmc_bit_map arl_socs_d3_status_3_map[] = { {} }; -const struct pmc_bit_map arl_socs_vnn_req_status_3_map[] = { +static const struct pmc_bit_map arl_socs_vnn_req_status_3_map[] = { {"DTS0_VNN_REQ_STS", BIT(7)}, {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, {} }; -const struct pmc_bit_map *arl_socs_lpm_maps[] = { +static const struct pmc_bit_map *arl_socs_lpm_maps[] = { arl_socs_clocksource_status_map, arl_socs_power_gating_status_0_map, arl_socs_power_gating_status_1_map, @@ -238,7 +239,7 @@ const struct pmc_bit_map *arl_socs_lpm_maps[] = { NULL }; -const struct pmc_bit_map arl_socs_pfear_map[] = { +static const struct pmc_bit_map arl_socs_pfear_map[] = { {"RSVD64", BIT(0)}, {"RSVD65", BIT(1)}, {"RSVD66", BIT(2)}, @@ -249,13 +250,13 @@ const struct pmc_bit_map arl_socs_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_arl_socs_pfear_map[] = { +static const struct pmc_bit_map *ext_arl_socs_pfear_map[] = { mtl_socm_pfear_map, arl_socs_pfear_map, NULL }; -const struct pmc_reg_map arl_socs_reg_map = { +static const struct pmc_reg_map arl_socs_reg_map = { .pfear_sts = ext_arl_socs_pfear_map, .ppfear_buckets = ARL_SOCS_PPFEAR_NUM_ENTRIES, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, @@ -283,7 +284,7 @@ const struct pmc_reg_map arl_socs_reg_map = { .pson_residency_counter_step = TGL_PSON_RES_COUNTER_STEP, }; -const struct pmc_bit_map arl_pchs_ltr_show_map[] = { +static const struct pmc_bit_map arl_pchs_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -323,7 +324,7 @@ const struct pmc_bit_map arl_pchs_ltr_show_map[] = { {} }; -const struct pmc_bit_map arl_pchs_clocksource_status_map[] = { +static const struct pmc_bit_map arl_pchs_clocksource_status_map[] = { {"AON2_OFF_STS", BIT(0)}, {"AON3_OFF_STS", BIT(1)}, {"AON4_OFF_STS", BIT(2)}, @@ -358,7 +359,7 @@ const struct pmc_bit_map arl_pchs_clocksource_status_map[] = { {} }; -const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = { +static const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0)}, {"DMI_PGD0_PG_STS", BIT(1)}, {"ESPISPI_PGD0_PG_STS", BIT(2)}, @@ -394,7 +395,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = { +static const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = { {"USBR0_PGD0_PG_STS", BIT(0)}, {"SUSRAM_PGD0_PG_STS", BIT(1)}, {"SMT1_PGD0_PG_STS", BIT(2)}, @@ -430,7 +431,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = { +static const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = { {"U3FPW2_PGD0_PG_STS", BIT(0)}, {"FIA_PGD0_PG_STS", BIT(1)}, {"FIACPCB_X_PGD0_PG_STS", BIT(2)}, @@ -457,7 +458,7 @@ const struct pmc_bit_map arl_pchs_power_gating_status_2_map[] = { {} }; -const struct pmc_bit_map arl_pchs_d3_status_0_map[] = { +static const struct pmc_bit_map arl_pchs_d3_status_0_map[] = { {"SPF_D3_STS", BIT(0)}, {"LPSS_D3_STS", BIT(3)}, {"XDCI_D3_STS", BIT(4)}, @@ -474,7 +475,7 @@ const struct pmc_bit_map arl_pchs_d3_status_0_map[] = { {} }; -const struct pmc_bit_map arl_pchs_d3_status_1_map[] = { +static const struct pmc_bit_map arl_pchs_d3_status_1_map[] = { {"GBETSN1_D3_STS", BIT(14)}, {"GBE_D3_STS", BIT(19)}, {"ITSS_D3_STS", BIT(23)}, @@ -483,7 +484,7 @@ const struct pmc_bit_map arl_pchs_d3_status_1_map[] = { {} }; -const struct pmc_bit_map arl_pchs_d3_status_2_map[] = { +static const struct pmc_bit_map arl_pchs_d3_status_2_map[] = { {"CSMERTC_D3_STS", BIT(1)}, {"SUSRAM_D3_STS", BIT(2)}, {"CSE_D3_STS", BIT(4)}, @@ -504,7 +505,7 @@ const struct pmc_bit_map arl_pchs_d3_status_2_map[] = { {} }; -const struct pmc_bit_map arl_pchs_d3_status_3_map[] = { +static const struct pmc_bit_map arl_pchs_d3_status_3_map[] = { {"ESE_D3_STS", BIT(3)}, {"GBETSN_D3_STS", BIT(13)}, {"THC0_D3_STS", BIT(14)}, @@ -513,13 +514,13 @@ const struct pmc_bit_map arl_pchs_d3_status_3_map[] = { {} }; -const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[] = { +static const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[] = { {"FIA_VNN_REQ_STS", BIT(17)}, {"ESPISPI_VNN_REQ_STS", BIT(18)}, {} }; -const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = { +static const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = { {"NPK_VNN_REQ_STS", BIT(4)}, {"DFXAGG_VNN_REQ_STS", BIT(8)}, {"EXI_VNN_REQ_STS", BIT(9)}, @@ -530,7 +531,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[] = { {} }; -const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = { +static const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = { {"FIA2_VNN_REQ_STS", BIT(0)}, {"CSMERTC_VNN_REQ_STS", BIT(1)}, {"CSE_VNN_REQ_STS", BIT(4)}, @@ -548,7 +549,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[] = { {} }; -const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = { +static const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = { {"ESE_VNN_REQ_STS", BIT(3)}, {"DTS0_VNN_REQ_STS", BIT(7)}, {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, @@ -556,7 +557,7 @@ const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[] = { {} }; -const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = { +static const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = { {"CPU_C10_REQ_STS", BIT(0)}, {"TS_OFF_REQ_STS", BIT(1)}, {"PNDE_MET_REQ_STS", BIT(2)}, @@ -586,7 +587,7 @@ const struct pmc_bit_map arl_pchs_vnn_misc_status_map[] = { {} }; -const struct pmc_bit_map arl_pchs_signal_status_map[] = { +static const struct pmc_bit_map arl_pchs_signal_status_map[] = { {"LSX_Wake0_STS", BIT(0)}, {"LSX_Wake1_STS", BIT(1)}, {"LSX_Wake2_STS", BIT(2)}, @@ -606,7 +607,7 @@ const struct pmc_bit_map arl_pchs_signal_status_map[] = { {} }; -const struct pmc_bit_map *arl_pchs_lpm_maps[] = { +static const struct pmc_bit_map *arl_pchs_lpm_maps[] = { arl_pchs_clocksource_status_map, arl_pchs_power_gating_status_0_map, arl_pchs_power_gating_status_1_map, @@ -624,7 +625,7 @@ const struct pmc_bit_map *arl_pchs_lpm_maps[] = { NULL }; -const struct pmc_reg_map arl_pchs_reg_map = { +static const struct pmc_reg_map arl_pchs_reg_map = { .pfear_sts = ext_arl_socs_pfear_map, .ppfear_buckets = ARL_SOCS_PPFEAR_NUM_ENTRIES, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, @@ -650,6 +651,7 @@ const struct pmc_reg_map arl_pchs_reg_map = { .etr3_offset = ETR3_OFFSET, }; +#define PMC_DEVID_SOCM 0x777f #define PMC_DEVID_SOCS 0xae7f #define PMC_DEVID_IOEP 0x7ecf #define PMC_DEVID_PCHS 0x7f27 @@ -669,11 +671,17 @@ static struct pmc_info arl_pmc_info_list[] = { .devid = PMC_DEVID_PCHS, .map = &arl_pchs_reg_map, }, + { + .guid = SOCM_LPM_REQ_GUID, + .devid = PMC_DEVID_SOCM, + .map = &mtl_socm_reg_map, + }, {} }; #define ARL_NPU_PCI_DEV 0xad1d #define ARL_GNA_PCI_DEV 0xae4c +#define ARL_H_GNA_PCI_DEV 0x774c /* * Set power state of select devices that do not have drivers to D3 * so that they do not block Package C entry. @@ -684,6 +692,12 @@ static void arl_d3_fixup(void) pmc_core_set_device_d3(ARL_GNA_PCI_DEV); } +static void arl_h_d3_fixup(void) +{ + pmc_core_set_device_d3(ARL_NPU_PCI_DEV); + pmc_core_set_device_d3(ARL_H_GNA_PCI_DEV); +} + static int arl_resume(struct pmc_dev *pmcdev) { arl_d3_fixup(); @@ -691,40 +705,41 @@ static int arl_resume(struct pmc_dev *pmcdev) return cnl_resume(pmcdev); } -int arl_core_init(struct pmc_dev *pmcdev) +static int arl_h_resume(struct pmc_dev *pmcdev) { - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; - int ret; - int func = 0; - bool ssram_init = true; + arl_h_d3_fixup(); + + return cnl_resume(pmcdev); +} +static int arl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) +{ arl_d3_fixup(); - pmcdev->suspend = cnl_suspend; - pmcdev->resume = arl_resume; - pmcdev->regmap_list = arl_pmc_info_list; + return generic_core_init(pmcdev, pmc_dev_info); +} - /* - * If ssram init fails use legacy method to at least get the - * primary PMC - */ - ret = pmc_core_ssram_init(pmcdev, func); - if (ret) { - ssram_init = false; - pmc->map = &arl_socs_reg_map; - - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - } - - pmc_core_get_low_power_modes(pmcdev); - pmc_core_punit_pmt_init(pmcdev, ARL_PMT_DMU_GUID); - - if (ssram_init) { - ret = pmc_core_ssram_get_lpm_reqs(pmcdev); - if (ret) - return ret; - } - - return 0; +static int arl_h_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) +{ + arl_h_d3_fixup(); + return generic_core_init(pmcdev, pmc_dev_info); } + +struct pmc_dev_info arl_pmc_dev = { + .pci_func = 0, + .dmu_guid = ARL_PMT_DMU_GUID, + .regmap_list = arl_pmc_info_list, + .map = &arl_socs_reg_map, + .suspend = cnl_suspend, + .resume = arl_resume, + .init = arl_core_init, +}; + +struct pmc_dev_info arl_h_pmc_dev = { + .pci_func = 2, + .dmu_guid = ARL_PMT_DMU_GUID, + .regmap_list = arl_pmc_info_list, + .map = &mtl_socm_reg_map, + .suspend = cnl_suspend, + .resume = arl_h_resume, + .init = arl_h_core_init, +}; diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c index fc5193fdf8a8..2c5af158bbe2 100644 --- a/drivers/platform/x86/intel/pmc/cnp.c +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -88,7 +88,7 @@ const struct pmc_bit_map cnp_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_cnp_pfear_map[] = { +static const struct pmc_bit_map *ext_cnp_pfear_map[] = { /* * Check intel_pmc_core_ids[] users of cnp_reg_map for * a list of core SoCs using this. @@ -97,7 +97,7 @@ const struct pmc_bit_map *ext_cnp_pfear_map[] = { NULL }; -const struct pmc_bit_map cnp_slps0_dbg0_map[] = { +static const struct pmc_bit_map cnp_slps0_dbg0_map[] = { {"AUDIO_D3", BIT(0)}, {"OTG_D3", BIT(1)}, {"XHCI_D3", BIT(2)}, @@ -110,7 +110,7 @@ const struct pmc_bit_map cnp_slps0_dbg0_map[] = { {} }; -const struct pmc_bit_map cnp_slps0_dbg1_map[] = { +static const struct pmc_bit_map cnp_slps0_dbg1_map[] = { {"SDIO_PLL_OFF", BIT(0)}, {"USB2_PLL_OFF", BIT(1)}, {"AUDIO_PLL_OFF", BIT(2)}, @@ -127,7 +127,7 @@ const struct pmc_bit_map cnp_slps0_dbg1_map[] = { {} }; -const struct pmc_bit_map cnp_slps0_dbg2_map[] = { +static const struct pmc_bit_map cnp_slps0_dbg2_map[] = { {"MPHY_CORE_GATED", BIT(0)}, {"CSME_GATED", BIT(1)}, {"USB2_SUS_GATED", BIT(2)}, @@ -274,20 +274,9 @@ int cnl_resume(struct pmc_dev *pmcdev) return pmc_core_resume_common(pmcdev); } -int cnp_core_init(struct pmc_dev *pmcdev) -{ - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - int ret; - - pmcdev->suspend = cnl_suspend; - pmcdev->resume = cnl_resume; - - pmc->map = &cnp_reg_map; - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - - pmc_core_get_low_power_modes(pmcdev); +struct pmc_dev_info cnp_pmc_dev = { + .map = &cnp_reg_map, + .suspend = cnl_suspend, + .resume = cnl_resume, +}; - return 0; -} diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 1ee0fb5f8250..7a1d11f2914f 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -1345,40 +1345,80 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) } } +/* + * When supported, ssram init is used to achieve all available PMCs. + * If ssram init fails, this function uses legacy method to at least get the + * primary PMC. + */ +int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) +{ + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + bool ssram; + int ret; + + pmcdev->suspend = pmc_dev_info->suspend; + pmcdev->resume = pmc_dev_info->resume; + + ssram = pmc_dev_info->regmap_list != NULL; + if (ssram) { + pmcdev->regmap_list = pmc_dev_info->regmap_list; + ret = pmc_core_ssram_init(pmcdev, pmc_dev_info->pci_func); + if (ret) { + dev_warn(&pmcdev->pdev->dev, + "ssram init failed, %d, using legacy init\n", ret); + ssram = false; + } + } + + if (!ssram) { + pmc->map = pmc_dev_info->map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + } + + pmc_core_get_low_power_modes(pmcdev); + if (pmc_dev_info->dmu_guid) + pmc_core_punit_pmt_init(pmcdev, pmc_dev_info->dmu_guid); + + if (ssram) + return pmc_core_ssram_get_lpm_reqs(pmcdev); + + return 0; +} + static const struct x86_cpu_id intel_pmc_core_ids[] = { - X86_MATCH_VFM(INTEL_SKYLAKE_L, spt_core_init), - X86_MATCH_VFM(INTEL_SKYLAKE, spt_core_init), - X86_MATCH_VFM(INTEL_KABYLAKE_L, spt_core_init), - X86_MATCH_VFM(INTEL_KABYLAKE, spt_core_init), - X86_MATCH_VFM(INTEL_CANNONLAKE_L, cnp_core_init), - X86_MATCH_VFM(INTEL_ICELAKE_L, icl_core_init), - X86_MATCH_VFM(INTEL_ICELAKE_NNPI, icl_core_init), - X86_MATCH_VFM(INTEL_COMETLAKE, cnp_core_init), - X86_MATCH_VFM(INTEL_COMETLAKE_L, cnp_core_init), - X86_MATCH_VFM(INTEL_TIGERLAKE_L, tgl_l_core_init), - X86_MATCH_VFM(INTEL_TIGERLAKE, tgl_core_init), - X86_MATCH_VFM(INTEL_ATOM_TREMONT, tgl_l_core_init), - X86_MATCH_VFM(INTEL_ATOM_TREMONT_L, icl_core_init), - X86_MATCH_VFM(INTEL_ROCKETLAKE, tgl_core_init), - X86_MATCH_VFM(INTEL_ALDERLAKE_L, tgl_l_core_init), - X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, tgl_l_core_init), - X86_MATCH_VFM(INTEL_ALDERLAKE, adl_core_init), - X86_MATCH_VFM(INTEL_RAPTORLAKE_P, tgl_l_core_init), - X86_MATCH_VFM(INTEL_RAPTORLAKE, adl_core_init), - X86_MATCH_VFM(INTEL_RAPTORLAKE_S, adl_core_init), - X86_MATCH_VFM(INTEL_METEORLAKE_L, mtl_core_init), - X86_MATCH_VFM(INTEL_ARROWLAKE, arl_core_init), - X86_MATCH_VFM(INTEL_LUNARLAKE_M, lnl_core_init), + X86_MATCH_VFM(INTEL_SKYLAKE_L, &spt_pmc_dev), + X86_MATCH_VFM(INTEL_SKYLAKE, &spt_pmc_dev), + X86_MATCH_VFM(INTEL_KABYLAKE_L, &spt_pmc_dev), + X86_MATCH_VFM(INTEL_KABYLAKE, &spt_pmc_dev), + X86_MATCH_VFM(INTEL_CANNONLAKE_L, &cnp_pmc_dev), + X86_MATCH_VFM(INTEL_ICELAKE_L, &icl_pmc_dev), + X86_MATCH_VFM(INTEL_ICELAKE_NNPI, &icl_pmc_dev), + X86_MATCH_VFM(INTEL_COMETLAKE, &cnp_pmc_dev), + X86_MATCH_VFM(INTEL_COMETLAKE_L, &cnp_pmc_dev), + X86_MATCH_VFM(INTEL_TIGERLAKE_L, &tgl_l_pmc_dev), + X86_MATCH_VFM(INTEL_TIGERLAKE, &tgl_pmc_dev), + X86_MATCH_VFM(INTEL_ATOM_TREMONT, &tgl_l_pmc_dev), + X86_MATCH_VFM(INTEL_ATOM_TREMONT_L, &icl_pmc_dev), + X86_MATCH_VFM(INTEL_ROCKETLAKE, &tgl_pmc_dev), + X86_MATCH_VFM(INTEL_ALDERLAKE_L, &tgl_l_pmc_dev), + X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &tgl_l_pmc_dev), + X86_MATCH_VFM(INTEL_ALDERLAKE, &adl_pmc_dev), + X86_MATCH_VFM(INTEL_RAPTORLAKE_P, &tgl_l_pmc_dev), + X86_MATCH_VFM(INTEL_RAPTORLAKE, &adl_pmc_dev), + X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &adl_pmc_dev), + X86_MATCH_VFM(INTEL_METEORLAKE_L, &mtl_pmc_dev), + X86_MATCH_VFM(INTEL_ARROWLAKE, &arl_pmc_dev), + X86_MATCH_VFM(INTEL_ARROWLAKE_H, &arl_h_pmc_dev), + X86_MATCH_VFM(INTEL_ARROWLAKE_U, &arl_h_pmc_dev), + X86_MATCH_VFM(INTEL_LUNARLAKE_M, &lnl_pmc_dev), + X86_MATCH_VFM(INTEL_PANTHERLAKE_L, &ptl_pmc_dev), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_ids); -static const struct pci_device_id pmc_pci_ids[] = { - { PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) }, - { } -}; - /* * This quirk can be used on those platforms where * the platform BIOS enforces 24Mhz crystal to shutdown @@ -1452,7 +1492,7 @@ static int pmc_core_probe(struct platform_device *pdev) static bool device_initialized; struct pmc_dev *pmcdev; const struct x86_cpu_id *cpu_id; - int (*core_init)(struct pmc_dev *pmcdev); + struct pmc_dev_info *pmc_dev_info; struct pmc *primary_pmc; int ret; @@ -1472,7 +1512,7 @@ static int pmc_core_probe(struct platform_device *pdev) if (!cpu_id) return -ENODEV; - core_init = (int (*)(struct pmc_dev *))cpu_id->driver_data; + pmc_dev_info = (struct pmc_dev_info *)cpu_id->driver_data; /* Primary PMC */ primary_pmc = devm_kzalloc(&pdev->dev, sizeof(*primary_pmc), GFP_KERNEL); @@ -1489,16 +1529,13 @@ static int pmc_core_probe(struct platform_device *pdev) if (!pmcdev->pkgc_res_cnt) return -ENOMEM; - /* - * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here - * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap - * in this case. - */ - if (core_init == spt_core_init && !pci_dev_present(pmc_pci_ids)) - core_init = cnp_core_init; - mutex_init(&pmcdev->lock); - ret = core_init(pmcdev); + + if (pmc_dev_info->init) + ret = pmc_dev_info->init(pmcdev, pmc_dev_info); + else + ret = generic_core_init(pmcdev, pmc_dev_info); + if (ret) { pmc_core_clean_structure(pdev); return ret; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index b9d3291d0bf2..945a1c440cca 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -285,6 +285,14 @@ enum ppfear_regs { #define LNL_PPFEAR_NUM_ENTRIES 12 #define LNL_S0IX_BLOCKER_OFFSET 0x2004 +/* Panther Lake Power Management Controller register offsets */ +#define PTL_LPM_NUM_MAPS 14 +#define PTL_PMC_LTR_SATA2 0x1B90 +#define PTL_PMC_LTR_PMC 0x1BA8 +#define PTL_PMC_LTR_CUR_ASLT 0x1C28 +#define PTL_PMC_LTR_CUR_PLT 0x1C2C +#define PTL_PCD_PMC_MMIO_REG_LEN 0x31A8 + extern const char *pmc_lpm_modes[]; struct pmc_bit_map { @@ -430,178 +438,77 @@ struct pmc_dev { enum pmc_index { PMC_IDX_MAIN, - PMC_IDX_SOC = PMC_IDX_MAIN, PMC_IDX_IOE, PMC_IDX_PCH, PMC_IDX_MAX }; +/** + * struct pmc_dev_info - Structure to keep PMC device info + * @pci_func: Function number of the primary PMC + * @dmu_guid: Die Management Unit GUID + * @regmap_list: Pointer to a list of pmc_info structure that could be + * available for the platform. When set, this field implies + * SSRAM support. + * @map: Pointer to a pmc_reg_map struct that contains platform + * specific attributes of the primary PMC + * @suspend: Function to perform platform specific suspend + * @resume: Function to perform platform specific resume + * @init: Function to perform platform specific init action + */ +struct pmc_dev_info { + u8 pci_func; + u32 dmu_guid; + struct pmc_info *regmap_list; + const struct pmc_reg_map *map; + void (*suspend)(struct pmc_dev *pmcdev); + int (*resume)(struct pmc_dev *pmcdev); + int (*init)(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info); +}; + extern const struct pmc_bit_map msr_map[]; -extern const struct pmc_bit_map spt_pll_map[]; -extern const struct pmc_bit_map spt_mphy_map[]; -extern const struct pmc_bit_map spt_pfear_map[]; -extern const struct pmc_bit_map *ext_spt_pfear_map[]; -extern const struct pmc_bit_map spt_ltr_show_map[]; -extern const struct pmc_reg_map spt_reg_map; extern const struct pmc_bit_map cnp_pfear_map[]; -extern const struct pmc_bit_map *ext_cnp_pfear_map[]; -extern const struct pmc_bit_map cnp_slps0_dbg0_map[]; -extern const struct pmc_bit_map cnp_slps0_dbg1_map[]; -extern const struct pmc_bit_map cnp_slps0_dbg2_map[]; extern const struct pmc_bit_map *cnp_slps0_dbg_maps[]; extern const struct pmc_bit_map cnp_ltr_show_map[]; extern const struct pmc_reg_map cnp_reg_map; -extern const struct pmc_bit_map icl_pfear_map[]; -extern const struct pmc_bit_map *ext_icl_pfear_map[]; -extern const struct pmc_reg_map icl_reg_map; -extern const struct pmc_bit_map tgl_pfear_map[]; -extern const struct pmc_bit_map *ext_tgl_pfear_map[]; -extern const struct pmc_bit_map tgl_clocksource_status_map[]; -extern const struct pmc_bit_map tgl_power_gating_status_map[]; -extern const struct pmc_bit_map tgl_d3_status_map[]; -extern const struct pmc_bit_map tgl_vnn_req_status_map[]; -extern const struct pmc_bit_map tgl_vnn_misc_status_map[]; extern const struct pmc_bit_map tgl_signal_status_map[]; -extern const struct pmc_bit_map *tgl_lpm_maps[]; -extern const struct pmc_reg_map tgl_reg_map; -extern const struct pmc_reg_map tgl_h_reg_map; -extern const struct pmc_bit_map adl_pfear_map[]; -extern const struct pmc_bit_map *ext_adl_pfear_map[]; -extern const struct pmc_bit_map adl_ltr_show_map[]; -extern const struct pmc_bit_map adl_clocksource_status_map[]; -extern const struct pmc_bit_map adl_power_gating_status_0_map[]; -extern const struct pmc_bit_map adl_power_gating_status_1_map[]; -extern const struct pmc_bit_map adl_power_gating_status_2_map[]; -extern const struct pmc_bit_map adl_d3_status_0_map[]; -extern const struct pmc_bit_map adl_d3_status_1_map[]; -extern const struct pmc_bit_map adl_d3_status_2_map[]; -extern const struct pmc_bit_map adl_d3_status_3_map[]; -extern const struct pmc_bit_map adl_vnn_req_status_0_map[]; -extern const struct pmc_bit_map adl_vnn_req_status_1_map[]; -extern const struct pmc_bit_map adl_vnn_req_status_2_map[]; -extern const struct pmc_bit_map adl_vnn_req_status_3_map[]; -extern const struct pmc_bit_map adl_vnn_misc_status_map[]; -extern const struct pmc_bit_map *adl_lpm_maps[]; extern const struct pmc_reg_map adl_reg_map; extern const struct pmc_bit_map mtl_socm_pfear_map[]; -extern const struct pmc_bit_map *ext_mtl_socm_pfear_map[]; -extern const struct pmc_bit_map mtl_socm_ltr_show_map[]; -extern const struct pmc_bit_map mtl_socm_clocksource_status_map[]; -extern const struct pmc_bit_map mtl_socm_power_gating_status_0_map[]; -extern const struct pmc_bit_map mtl_socm_power_gating_status_1_map[]; -extern const struct pmc_bit_map mtl_socm_power_gating_status_2_map[]; extern const struct pmc_bit_map mtl_socm_d3_status_0_map[]; extern const struct pmc_bit_map mtl_socm_d3_status_1_map[]; -extern const struct pmc_bit_map mtl_socm_d3_status_2_map[]; -extern const struct pmc_bit_map mtl_socm_d3_status_3_map[]; extern const struct pmc_bit_map mtl_socm_vnn_req_status_0_map[]; extern const struct pmc_bit_map mtl_socm_vnn_req_status_1_map[]; extern const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[]; -extern const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[]; extern const struct pmc_bit_map mtl_socm_vnn_misc_status_map[]; extern const struct pmc_bit_map mtl_socm_signal_status_map[]; -extern const struct pmc_bit_map *mtl_socm_lpm_maps[]; extern const struct pmc_reg_map mtl_socm_reg_map; -extern const struct pmc_bit_map mtl_ioep_pfear_map[]; -extern const struct pmc_bit_map *ext_mtl_ioep_pfear_map[]; -extern const struct pmc_bit_map mtl_ioep_ltr_show_map[]; -extern const struct pmc_bit_map mtl_ioep_clocksource_status_map[]; -extern const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[]; -extern const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[]; -extern const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[]; -extern const struct pmc_bit_map mtl_ioep_d3_status_0_map[]; -extern const struct pmc_bit_map mtl_ioep_d3_status_1_map[]; -extern const struct pmc_bit_map mtl_ioep_d3_status_2_map[]; -extern const struct pmc_bit_map mtl_ioep_d3_status_3_map[]; -extern const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[]; -extern const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[]; -extern const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[]; -extern const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[]; -extern const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[]; -extern const struct pmc_bit_map *mtl_ioep_lpm_maps[]; extern const struct pmc_reg_map mtl_ioep_reg_map; -extern const struct pmc_bit_map mtl_ioem_pfear_map[]; -extern const struct pmc_bit_map *ext_mtl_ioem_pfear_map[]; -extern const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[]; -extern const struct pmc_bit_map mtl_ioem_vnn_req_status_1_map[]; -extern const struct pmc_bit_map *mtl_ioem_lpm_maps[]; -extern const struct pmc_reg_map mtl_ioem_reg_map; -extern const struct pmc_reg_map lnl_socm_reg_map; - -/* LNL */ -extern const struct pmc_bit_map lnl_ltr_show_map[]; -extern const struct pmc_bit_map lnl_clocksource_status_map[]; -extern const struct pmc_bit_map lnl_power_gating_status_0_map[]; -extern const struct pmc_bit_map lnl_power_gating_status_1_map[]; -extern const struct pmc_bit_map lnl_power_gating_status_2_map[]; -extern const struct pmc_bit_map lnl_d3_status_0_map[]; -extern const struct pmc_bit_map lnl_d3_status_1_map[]; -extern const struct pmc_bit_map lnl_d3_status_2_map[]; -extern const struct pmc_bit_map lnl_d3_status_3_map[]; -extern const struct pmc_bit_map lnl_vnn_req_status_0_map[]; -extern const struct pmc_bit_map lnl_vnn_req_status_1_map[]; -extern const struct pmc_bit_map lnl_vnn_req_status_2_map[]; -extern const struct pmc_bit_map lnl_vnn_req_status_3_map[]; -extern const struct pmc_bit_map lnl_vnn_misc_status_map[]; -extern const struct pmc_bit_map *lnl_lpm_maps[]; -extern const struct pmc_bit_map *lnl_blk_maps[]; -extern const struct pmc_bit_map lnl_pfear_map[]; -extern const struct pmc_bit_map *ext_lnl_pfear_map[]; -extern const struct pmc_bit_map lnl_signal_status_map[]; - -/* ARL */ -extern const struct pmc_bit_map arl_socs_ltr_show_map[]; -extern const struct pmc_bit_map arl_socs_clocksource_status_map[]; -extern const struct pmc_bit_map arl_socs_power_gating_status_0_map[]; -extern const struct pmc_bit_map arl_socs_power_gating_status_1_map[]; -extern const struct pmc_bit_map arl_socs_power_gating_status_2_map[]; -extern const struct pmc_bit_map arl_socs_d3_status_2_map[]; -extern const struct pmc_bit_map arl_socs_d3_status_3_map[]; -extern const struct pmc_bit_map arl_socs_vnn_req_status_3_map[]; -extern const struct pmc_bit_map *arl_socs_lpm_maps[]; -extern const struct pmc_bit_map arl_socs_pfear_map[]; -extern const struct pmc_bit_map *ext_arl_socs_pfear_map[]; -extern const struct pmc_reg_map arl_socs_reg_map; -extern const struct pmc_bit_map arl_pchs_ltr_show_map[]; -extern const struct pmc_bit_map arl_pchs_clocksource_status_map[]; -extern const struct pmc_bit_map arl_pchs_power_gating_status_0_map[]; -extern const struct pmc_bit_map arl_pchs_power_gating_status_1_map[]; -extern const struct pmc_bit_map arl_pchs_power_gating_status_2_map[]; -extern const struct pmc_bit_map arl_pchs_d3_status_0_map[]; -extern const struct pmc_bit_map arl_pchs_d3_status_1_map[]; -extern const struct pmc_bit_map arl_pchs_d3_status_2_map[]; -extern const struct pmc_bit_map arl_pchs_d3_status_3_map[]; -extern const struct pmc_bit_map arl_pchs_vnn_req_status_0_map[]; -extern const struct pmc_bit_map arl_pchs_vnn_req_status_1_map[]; -extern const struct pmc_bit_map arl_pchs_vnn_req_status_2_map[]; -extern const struct pmc_bit_map arl_pchs_vnn_req_status_3_map[]; -extern const struct pmc_bit_map arl_pchs_vnn_misc_status_map[]; -extern const struct pmc_bit_map arl_pchs_signal_status_map[]; -extern const struct pmc_bit_map *arl_pchs_lpm_maps[]; -extern const struct pmc_reg_map arl_pchs_reg_map; - -extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); -extern int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev); + +void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); +int pmc_core_ssram_get_lpm_reqs(struct pmc_dev *pmcdev); int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); int pmc_core_resume_common(struct pmc_dev *pmcdev); int get_primary_reg_base(struct pmc *pmc); -extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); -extern void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid); -extern void pmc_core_set_device_d3(unsigned int device); - -extern int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func); - -int spt_core_init(struct pmc_dev *pmcdev); -int cnp_core_init(struct pmc_dev *pmcdev); -int icl_core_init(struct pmc_dev *pmcdev); -int tgl_core_init(struct pmc_dev *pmcdev); -int tgl_l_core_init(struct pmc_dev *pmcdev); -int tgl_core_generic_init(struct pmc_dev *pmcdev, int pch_tp); -int adl_core_init(struct pmc_dev *pmcdev); -int mtl_core_init(struct pmc_dev *pmcdev); -int arl_core_init(struct pmc_dev *pmcdev); -int lnl_core_init(struct pmc_dev *pmcdev); +void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev); +void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid); +void pmc_core_set_device_d3(unsigned int device); + +int pmc_core_ssram_init(struct pmc_dev *pmcdev, int func); + +int generic_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info); + +extern struct pmc_dev_info spt_pmc_dev; +extern struct pmc_dev_info cnp_pmc_dev; +extern struct pmc_dev_info icl_pmc_dev; +extern struct pmc_dev_info tgl_l_pmc_dev; +extern struct pmc_dev_info tgl_pmc_dev; +extern struct pmc_dev_info adl_pmc_dev; +extern struct pmc_dev_info mtl_pmc_dev; +extern struct pmc_dev_info arl_pmc_dev; +extern struct pmc_dev_info arl_h_pmc_dev; +extern struct pmc_dev_info lnl_pmc_dev; +extern struct pmc_dev_info ptl_pmc_dev; void cnl_suspend(struct pmc_dev *pmcdev); int cnl_resume(struct pmc_dev *pmcdev); diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c index 71b0fd6cb7d8..db7ed15bf863 100644 --- a/drivers/platform/x86/intel/pmc/icl.c +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -10,7 +10,7 @@ #include "core.h" -const struct pmc_bit_map icl_pfear_map[] = { +static const struct pmc_bit_map icl_pfear_map[] = { {"RES_65", BIT(0)}, {"RES_66", BIT(1)}, {"RES_67", BIT(2)}, @@ -22,7 +22,7 @@ const struct pmc_bit_map icl_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_icl_pfear_map[] = { +static const struct pmc_bit_map *ext_icl_pfear_map[] = { /* * Check intel_pmc_core_ids[] users of icl_reg_map for * a list of core SoCs using this. @@ -32,7 +32,7 @@ const struct pmc_bit_map *ext_icl_pfear_map[] = { NULL }; -const struct pmc_reg_map icl_reg_map = { +static const struct pmc_reg_map icl_reg_map = { .pfear_sts = ext_icl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = ICL_PMC_SLP_S0_RES_COUNTER_STEP, @@ -50,18 +50,6 @@ const struct pmc_reg_map icl_reg_map = { .etr3_offset = ETR3_OFFSET, }; -int icl_core_init(struct pmc_dev *pmcdev) -{ - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - int ret; - - pmc->map = &icl_reg_map; - - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - - pmc_core_get_low_power_modes(pmcdev); - - return ret; -} +struct pmc_dev_info icl_pmc_dev = { + .map = &icl_reg_map, +}; diff --git a/drivers/platform/x86/intel/pmc/lnl.c b/drivers/platform/x86/intel/pmc/lnl.c index be029f12cdf4..da513c234714 100644 --- a/drivers/platform/x86/intel/pmc/lnl.c +++ b/drivers/platform/x86/intel/pmc/lnl.c @@ -13,7 +13,7 @@ #include "core.h" -const struct pmc_bit_map lnl_ltr_show_map[] = { +static const struct pmc_bit_map lnl_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -55,7 +55,7 @@ const struct pmc_bit_map lnl_ltr_show_map[] = { {} }; -const struct pmc_bit_map lnl_power_gating_status_0_map[] = { +static const struct pmc_bit_map lnl_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0), 0}, {"FUSE_OSSE_PGD0_PG_STS", BIT(1), 0}, {"ESPISPI_PGD0_PG_STS", BIT(2), 0}, @@ -91,7 +91,7 @@ const struct pmc_bit_map lnl_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map lnl_power_gating_status_1_map[] = { +static const struct pmc_bit_map lnl_power_gating_status_1_map[] = { {"USBR0_PGD0_PG_STS", BIT(0), 1}, {"SUSRAM_PGD0_PG_STS", BIT(1), 1}, {"SMT1_PGD0_PG_STS", BIT(2), 1}, @@ -127,7 +127,7 @@ const struct pmc_bit_map lnl_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map lnl_power_gating_status_2_map[] = { +static const struct pmc_bit_map lnl_power_gating_status_2_map[] = { {"PSF8_PGD0_PG_STS", BIT(0), 0}, {"SBR16B2_PGD0_PG_STS", BIT(1), 0}, {"D2D_IPU_PGD0_PG_STS", BIT(2), 1}, @@ -163,7 +163,7 @@ const struct pmc_bit_map lnl_power_gating_status_2_map[] = { {} }; -const struct pmc_bit_map lnl_d3_status_0_map[] = { +static const struct pmc_bit_map lnl_d3_status_0_map[] = { {"LPSS_D3_STS", BIT(3), 1}, {"XDCI_D3_STS", BIT(4), 1}, {"XHCI_D3_STS", BIT(5), 1}, @@ -175,7 +175,7 @@ const struct pmc_bit_map lnl_d3_status_0_map[] = { {} }; -const struct pmc_bit_map lnl_d3_status_1_map[] = { +static const struct pmc_bit_map lnl_d3_status_1_map[] = { {"OSSE_SMT1_D3_STS", BIT(7), 0}, {"GBE_D3_STS", BIT(19), 0}, {"ITSS_D3_STS", BIT(23), 0}, @@ -185,7 +185,7 @@ const struct pmc_bit_map lnl_d3_status_1_map[] = { {} }; -const struct pmc_bit_map lnl_d3_status_2_map[] = { +static const struct pmc_bit_map lnl_d3_status_2_map[] = { {"ESE_D3_STS", BIT(0), 0}, {"CSMERTC_D3_STS", BIT(1), 0}, {"SUSRAM_D3_STS", BIT(2), 0}, @@ -205,7 +205,7 @@ const struct pmc_bit_map lnl_d3_status_2_map[] = { {} }; -const struct pmc_bit_map lnl_d3_status_3_map[] = { +static const struct pmc_bit_map lnl_d3_status_3_map[] = { {"THC0_D3_STS", BIT(14), 1}, {"THC1_D3_STS", BIT(15), 1}, {"OSSE_SMT3_D3_STS", BIT(21), 0}, @@ -213,14 +213,14 @@ const struct pmc_bit_map lnl_d3_status_3_map[] = { {} }; -const struct pmc_bit_map lnl_vnn_req_status_0_map[] = { +static const struct pmc_bit_map lnl_vnn_req_status_0_map[] = { {"LPSS_VNN_REQ_STS", BIT(3), 1}, {"OSSE_VNN_REQ_STS", BIT(15), 1}, {"ESPISPI_VNN_REQ_STS", BIT(18), 1}, {} }; -const struct pmc_bit_map lnl_vnn_req_status_1_map[] = { +static const struct pmc_bit_map lnl_vnn_req_status_1_map[] = { {"NPK_VNN_REQ_STS", BIT(4), 1}, {"OSSE_SMT1_VNN_REQ_STS", BIT(7), 1}, {"DFXAGG_VNN_REQ_STS", BIT(8), 0}, @@ -232,7 +232,7 @@ const struct pmc_bit_map lnl_vnn_req_status_1_map[] = { {} }; -const struct pmc_bit_map lnl_vnn_req_status_2_map[] = { +static const struct pmc_bit_map lnl_vnn_req_status_2_map[] = { {"eSE_VNN_REQ_STS", BIT(0), 1}, {"CSMERTC_VNN_REQ_STS", BIT(1), 1}, {"CSE_VNN_REQ_STS", BIT(4), 1}, @@ -249,14 +249,14 @@ const struct pmc_bit_map lnl_vnn_req_status_2_map[] = { {} }; -const struct pmc_bit_map lnl_vnn_req_status_3_map[] = { +static const struct pmc_bit_map lnl_vnn_req_status_3_map[] = { {"DISP_SHIM_VNN_REQ_STS", BIT(2), 0}, {"DTS0_VNN_REQ_STS", BIT(7), 0}, {"GPIOCOM5_VNN_REQ_STS", BIT(11), 2}, {} }; -const struct pmc_bit_map lnl_vnn_misc_status_map[] = { +static const struct pmc_bit_map lnl_vnn_misc_status_map[] = { {"CPU_C10_REQ_STS", BIT(0), 0}, {"TS_OFF_REQ_STS", BIT(1), 0}, {"PNDE_MET_REQ_STS", BIT(2), 1}, @@ -292,7 +292,7 @@ const struct pmc_bit_map lnl_vnn_misc_status_map[] = { {} }; -const struct pmc_bit_map lnl_clocksource_status_map[] = { +static const struct pmc_bit_map lnl_clocksource_status_map[] = { {"AON2_OFF_STS", BIT(0), 0}, {"AON3_OFF_STS", BIT(1), 1}, {"AON4_OFF_STS", BIT(2), 1}, @@ -317,7 +317,7 @@ const struct pmc_bit_map lnl_clocksource_status_map[] = { {} }; -const struct pmc_bit_map lnl_signal_status_map[] = { +static const struct pmc_bit_map lnl_signal_status_map[] = { {"LSX_Wake0_STS", BIT(0), 0}, {"LSX_Wake1_STS", BIT(1), 0}, {"LSX_Wake2_STS", BIT(2), 0}, @@ -337,7 +337,7 @@ const struct pmc_bit_map lnl_signal_status_map[] = { {} }; -const struct pmc_bit_map lnl_rsc_status_map[] = { +static const struct pmc_bit_map lnl_rsc_status_map[] = { {"Memory", 0, 1}, {"PSF0", 0, 1}, {"PSF4", 0, 1}, @@ -349,7 +349,7 @@ const struct pmc_bit_map lnl_rsc_status_map[] = { {} }; -const struct pmc_bit_map *lnl_lpm_maps[] = { +static const struct pmc_bit_map *lnl_lpm_maps[] = { lnl_clocksource_status_map, lnl_power_gating_status_0_map, lnl_power_gating_status_1_map, @@ -367,7 +367,7 @@ const struct pmc_bit_map *lnl_lpm_maps[] = { NULL }; -const struct pmc_bit_map *lnl_blk_maps[] = { +static const struct pmc_bit_map *lnl_blk_maps[] = { lnl_power_gating_status_0_map, lnl_power_gating_status_1_map, lnl_power_gating_status_2_map, @@ -386,7 +386,7 @@ const struct pmc_bit_map *lnl_blk_maps[] = { NULL }; -const struct pmc_bit_map lnl_pfear_map[] = { +static const struct pmc_bit_map lnl_pfear_map[] = { {"PMC_0", BIT(0)}, {"FUSE_OSSE", BIT(1)}, {"ESPISPI", BIT(2)}, @@ -498,12 +498,12 @@ const struct pmc_bit_map lnl_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_lnl_pfear_map[] = { +static const struct pmc_bit_map *ext_lnl_pfear_map[] = { lnl_pfear_map, NULL }; -const struct pmc_reg_map lnl_socm_reg_map = { +static const struct pmc_reg_map lnl_socm_reg_map = { .pfear_sts = ext_lnl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, @@ -550,22 +550,15 @@ static int lnl_resume(struct pmc_dev *pmcdev) return cnl_resume(pmcdev); } -int lnl_core_init(struct pmc_dev *pmcdev) +static int lnl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) { - int ret; - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; - lnl_d3_fixup(); - - pmcdev->suspend = cnl_suspend; - pmcdev->resume = lnl_resume; - - pmc->map = &lnl_socm_reg_map; - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - - pmc_core_get_low_power_modes(pmcdev); - - return 0; + return generic_core_init(pmcdev, pmc_dev_info); } + +struct pmc_dev_info lnl_pmc_dev = { + .map = &lnl_socm_reg_map, + .suspend = cnl_suspend, + .resume = lnl_resume, + .init = lnl_core_init, +}; diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c index 02949fed76e9..8862829694a7 100644 --- a/drivers/platform/x86/intel/pmc/mtl.c +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -102,12 +102,12 @@ const struct pmc_bit_map mtl_socm_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = { +static const struct pmc_bit_map *ext_mtl_socm_pfear_map[] = { mtl_socm_pfear_map, NULL }; -const struct pmc_bit_map mtl_socm_ltr_show_map[] = { +static const struct pmc_bit_map mtl_socm_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -141,7 +141,7 @@ const struct pmc_bit_map mtl_socm_ltr_show_map[] = { {} }; -const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { +static const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { {"AON2_OFF_STS", BIT(0)}, {"AON3_OFF_STS", BIT(1)}, {"AON4_OFF_STS", BIT(2)}, @@ -167,7 +167,7 @@ const struct pmc_bit_map mtl_socm_clocksource_status_map[] = { {} }; -const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { +static const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0)}, {"DMI_PGD0_PG_STS", BIT(1)}, {"ESPISPI_PGD0_PG_STS", BIT(2)}, @@ -203,7 +203,7 @@ const struct pmc_bit_map mtl_socm_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { +static const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { {"USBR0_PGD0_PG_STS", BIT(0)}, {"SUSRAM_PGD0_PG_STS", BIT(1)}, {"SMT1_PGD0_PG_STS", BIT(2)}, @@ -239,7 +239,7 @@ const struct pmc_bit_map mtl_socm_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = { +static const struct pmc_bit_map mtl_socm_power_gating_status_2_map[] = { {"PSF8_PGD0_PG_STS", BIT(0)}, {"FIA_PGD0_PG_STS", BIT(1)}, {"SOC_D2D_PGD1_PG_STS", BIT(2)}, @@ -291,7 +291,7 @@ const struct pmc_bit_map mtl_socm_d3_status_1_map[] = { {} }; -const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { +static const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { {"GNA_D3_STS", BIT(0)}, {"CSMERTC_D3_STS", BIT(1)}, {"SUSRAM_D3_STS", BIT(2)}, @@ -310,7 +310,7 @@ const struct pmc_bit_map mtl_socm_d3_status_2_map[] = { {} }; -const struct pmc_bit_map mtl_socm_d3_status_3_map[] = { +static const struct pmc_bit_map mtl_socm_d3_status_3_map[] = { {"ESE_D3_STS", BIT(2)}, {"GBETSN_D3_STS", BIT(13)}, {"THC0_D3_STS", BIT(14)}, @@ -353,7 +353,7 @@ const struct pmc_bit_map mtl_socm_vnn_req_status_2_map[] = { {} }; -const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = { +static const struct pmc_bit_map mtl_socm_vnn_req_status_3_map[] = { {"ESE_VNN_REQ_STS", BIT(2)}, {"DTS0_VNN_REQ_STS", BIT(7)}, {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, @@ -432,7 +432,7 @@ const struct pmc_bit_map mtl_socm_signal_status_map[] = { {} }; -const struct pmc_bit_map *mtl_socm_lpm_maps[] = { +static const struct pmc_bit_map *mtl_socm_lpm_maps[] = { mtl_socm_clocksource_status_map, mtl_socm_power_gating_status_0_map, mtl_socm_power_gating_status_1_map, @@ -476,7 +476,7 @@ const struct pmc_reg_map mtl_socm_reg_map = { .lpm_reg_index = MTL_LPM_REG_INDEX, }; -const struct pmc_bit_map mtl_ioep_pfear_map[] = { +static const struct pmc_bit_map mtl_ioep_pfear_map[] = { {"PMC_0", BIT(0)}, {"OPI", BIT(1)}, {"TCSS", BIT(2)}, @@ -563,12 +563,12 @@ const struct pmc_bit_map mtl_ioep_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = { +static const struct pmc_bit_map *ext_mtl_ioep_pfear_map[] = { mtl_ioep_pfear_map, NULL }; -const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { +static const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, {"SATA", CNP_PMC_LTR_SATA}, @@ -600,7 +600,7 @@ const struct pmc_bit_map mtl_ioep_ltr_show_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { +static const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { {"AON2_OFF_STS", BIT(0)}, {"AON3_OFF_STS", BIT(1)}, {"AON4_OFF_STS", BIT(2)}, @@ -623,7 +623,7 @@ const struct pmc_bit_map mtl_ioep_clocksource_status_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { +static const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { {"PMC_PGD0_PG_STS", BIT(0)}, {"DMI_PGD0_PG_STS", BIT(1)}, {"TCSS_PGD0_PG_STS", BIT(2)}, @@ -650,7 +650,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_0_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { +static const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { {"PSF9_PGD0_PG_STS", BIT(0)}, {"MPFPW4_PGD0_PG_STS", BIT(1)}, {"SBR0_PGD0_PG_STS", BIT(8)}, @@ -668,7 +668,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { +static const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { {"FIA_PGD0_PG_STS", BIT(1)}, {"FIA_P_PGD0_PG_STS", BIT(3)}, {"TAM_PGD0_PG_STS", BIT(4)}, @@ -680,7 +680,7 @@ const struct pmc_bit_map mtl_ioep_power_gating_status_2_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { +static const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { {"SPF_D3_STS", BIT(0)}, {"SPA_D3_STS", BIT(12)}, {"SPB_D3_STS", BIT(13)}, @@ -691,43 +691,43 @@ const struct pmc_bit_map mtl_ioep_d3_status_0_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = { +static const struct pmc_bit_map mtl_ioep_d3_status_1_map[] = { {"GBETSN1_D3_STS", BIT(14)}, {"P2S_D3_STS", BIT(24)}, {} }; -const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = { +static const struct pmc_bit_map mtl_ioep_d3_status_2_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = { +static const struct pmc_bit_map mtl_ioep_d3_status_3_map[] = { {"GBETSN_D3_STS", BIT(13)}, {"ACE_D3_STS", BIT(23)}, {} }; -const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = { +static const struct pmc_bit_map mtl_ioep_vnn_req_status_0_map[] = { {"FIA_VNN_REQ_STS", BIT(17)}, {} }; -const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = { +static const struct pmc_bit_map mtl_ioep_vnn_req_status_1_map[] = { {"DFXAGG_VNN_REQ_STS", BIT(8)}, {} }; -const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = { +static const struct pmc_bit_map mtl_ioep_vnn_req_status_2_map[] = { {} }; -const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = { +static const struct pmc_bit_map mtl_ioep_vnn_req_status_3_map[] = { {"DTS0_VNN_REQ_STS", BIT(7)}, {"DISP_VNN_REQ_STS", BIT(19)}, {} }; -const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { +static const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { {"CPU_C10_REQ_STS", BIT(0)}, {"TS_OFF_REQ_STS", BIT(1)}, {"PNDE_MET_REQ_STS", BIT(2)}, @@ -762,7 +762,7 @@ const struct pmc_bit_map mtl_ioep_vnn_misc_status_map[] = { {} }; -const struct pmc_bit_map *mtl_ioep_lpm_maps[] = { +static const struct pmc_bit_map *mtl_ioep_lpm_maps[] = { mtl_ioep_clocksource_status_map, mtl_ioep_power_gating_status_0_map, mtl_ioep_power_gating_status_1_map, @@ -800,7 +800,7 @@ const struct pmc_reg_map mtl_ioep_reg_map = { .lpm_reg_index = MTL_LPM_REG_INDEX, }; -const struct pmc_bit_map mtl_ioem_pfear_map[] = { +static const struct pmc_bit_map mtl_ioem_pfear_map[] = { {"PMC_0", BIT(0)}, {"OPI", BIT(1)}, {"TCSS", BIT(2)}, @@ -887,12 +887,12 @@ const struct pmc_bit_map mtl_ioem_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = { +static const struct pmc_bit_map *ext_mtl_ioem_pfear_map[] = { mtl_ioem_pfear_map, NULL }; -const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { +static const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { {"PSF9_PGD0_PG_STS", BIT(0)}, {"MPFPW4_PGD0_PG_STS", BIT(1)}, {"SBR0_PGD0_PG_STS", BIT(8)}, @@ -909,7 +909,7 @@ const struct pmc_bit_map mtl_ioem_power_gating_status_1_map[] = { {} }; -const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { +static const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { mtl_ioep_clocksource_status_map, mtl_ioep_power_gating_status_0_map, mtl_ioem_power_gating_status_1_map, @@ -927,7 +927,7 @@ const struct pmc_bit_map *mtl_ioem_lpm_maps[] = { NULL }; -const struct pmc_reg_map mtl_ioem_reg_map = { +static const struct pmc_reg_map mtl_ioem_reg_map = { .regmap_length = MTL_IOE_PMC_MMIO_REG_LEN, .pfear_sts = ext_mtl_ioem_pfear_map, .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, @@ -990,39 +990,18 @@ static int mtl_resume(struct pmc_dev *pmcdev) return cnl_resume(pmcdev); } -int mtl_core_init(struct pmc_dev *pmcdev) +static int mtl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) { - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC]; - int ret; - int func = 2; - bool ssram_init = true; - mtl_d3_fixup(); - - pmcdev->suspend = cnl_suspend; - pmcdev->resume = mtl_resume; - pmcdev->regmap_list = mtl_pmc_info_list; - - /* - * If ssram init fails use legacy method to at least get the - * primary PMC - */ - ret = pmc_core_ssram_init(pmcdev, func); - if (ret) { - ssram_init = false; - dev_warn(&pmcdev->pdev->dev, - "ssram init failed, %d, using legacy init\n", ret); - pmc->map = &mtl_socm_reg_map; - ret = get_primary_reg_base(pmc); - if (ret) - return ret; - } - - pmc_core_get_low_power_modes(pmcdev); - pmc_core_punit_pmt_init(pmcdev, MTL_PMT_DMU_GUID); - - if (ssram_init) - return pmc_core_ssram_get_lpm_reqs(pmcdev); - - return 0; + return generic_core_init(pmcdev, pmc_dev_info); } + +struct pmc_dev_info mtl_pmc_dev = { + .pci_func = 2, + .dmu_guid = MTL_PMT_DMU_GUID, + .regmap_list = mtl_pmc_info_list, + .map = &mtl_socm_reg_map, + .suspend = cnl_suspend, + .resume = mtl_resume, + .init = mtl_core_init, +}; diff --git a/drivers/platform/x86/intel/pmc/ptl.c b/drivers/platform/x86/intel/pmc/ptl.c new file mode 100644 index 000000000000..394515af60d6 --- /dev/null +++ b/drivers/platform/x86/intel/pmc/ptl.c @@ -0,0 +1,550 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Panther Lake PCH. + * + * Copyright (c) 2025, Intel Corporation. + */ + +#include <linux/pci.h> + +#include "core.h" + +static const struct pmc_bit_map ptl_pcdp_pfear_map[] = { + {"PMC_0", BIT(0)}, + {"FUSE_OSSE", BIT(1)}, + {"ESPISPI", BIT(2)}, + {"XHCI", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"MPFPW2", BIT(6)}, + {"GBE", BIT(7)}, + + {"SBR16B20", BIT(0)}, + {"SBR8B20", BIT(1)}, + {"SBR16B21", BIT(2)}, + {"DBG_SBR16B", BIT(3)}, + {"OSSE_HOTHAM", BIT(4)}, + {"D2D_DISP_1", BIT(5)}, + {"LPSS", BIT(6)}, + {"LPC", BIT(7)}, + + {"SMB", BIT(0)}, + {"ISH", BIT(1)}, + {"SBR16B2", BIT(2)}, + {"NPK_0", BIT(3)}, + {"D2D_NOC_1", BIT(4)}, + {"SBR8B2", BIT(5)}, + {"FUSE", BIT(6)}, + {"SBR16B0", BIT(7)}, + + {"PSF0", BIT(0)}, + {"XDCI", BIT(1)}, + {"EXI", BIT(2)}, + {"CSE", BIT(3)}, + {"KVMCC", BIT(4)}, + {"PMT", BIT(5)}, + {"CLINK", BIT(6)}, + {"PTIO", BIT(7)}, + + {"USBR0", BIT(0)}, + {"SUSRAM", BIT(1)}, + {"SMT1", BIT(2)}, + {"MPFPW1", BIT(3)}, + {"SMS2", BIT(4)}, + {"SMS1", BIT(5)}, + {"CSMERTC", BIT(6)}, + {"CSMEPSF", BIT(7)}, + + {"D2D_NOC_0", BIT(0)}, + {"ESE", BIT(1)}, + {"P2SB8B", BIT(2)}, + {"SBR16B7", BIT(3)}, + {"SBR16B3", BIT(4)}, + {"OSSE_SMT1", BIT(5)}, + {"D2D_DISP", BIT(6)}, + {"DBG_SBR", BIT(7)}, + + {"U3FPW1", BIT(0)}, + {"FIA_X", BIT(1)}, + {"PSF4", BIT(2)}, + {"CNVI", BIT(3)}, + {"UFSX2", BIT(4)}, + {"ENDBG", BIT(5)}, + {"DBC", BIT(6)}, + {"FIA_PG", BIT(7)}, + + {"D2D_IPU", BIT(0)}, + {"NPK1", BIT(1)}, + {"FIACPCB_X", BIT(2)}, + {"SBR8B4", BIT(3)}, + {"DBG_PSF", BIT(4)}, + {"PSF6", BIT(5)}, + {"UFSPW1", BIT(6)}, + {"FIA_U", BIT(7)}, + + {"PSF8", BIT(0)}, + {"SBR16B4", BIT(1)}, + {"SBR16B5", BIT(2)}, + {"FIACPCB_U", BIT(3)}, + {"TAM", BIT(4)}, + {"D2D_NOC_2", BIT(5)}, + {"TBTLSX", BIT(6)}, + {"THC0", BIT(7)}, + + {"THC1", BIT(0)}, + {"PMC_1", BIT(1)}, + {"SBR8B1", BIT(2)}, + {"TCSS", BIT(3)}, + {"DISP_PGA", BIT(4)}, + {"SBR16B1", BIT(5)}, + {"SBRG", BIT(6)}, + {"PSF5", BIT(7)}, + + {"P2SB16B", BIT(0)}, + {"ACE_0", BIT(1)}, + {"ACE_1", BIT(2)}, + {"ACE_2", BIT(3)}, + {"ACE_3", BIT(4)}, + {"ACE_4", BIT(5)}, + {"ACE_5", BIT(6)}, + {"ACE_6", BIT(7)}, + + {"ACE_7", BIT(0)}, + {"ACE_8", BIT(1)}, + {"ACE_9", BIT(2)}, + {"ACE_10", BIT(3)}, + {"FIACPCB_PG", BIT(4)}, + {"SBR16B6", BIT(5)}, + {"OSSE", BIT(6)}, + {"SBR8B0", BIT(7)}, + {} +}; + +static const struct pmc_bit_map *ext_ptl_pcdp_pfear_map[] = { + ptl_pcdp_pfear_map, + NULL +}; + +static const struct pmc_bit_map ptl_pcdp_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", PTL_PMC_LTR_SATA2}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", MTL_PMC_LTR_SPG}, + {"ESE", MTL_PMC_LTR_ESE}, + {"IOE_PMC", MTL_PMC_LTR_IOE_PMC}, + {"DMI3", ARL_PMC_LTR_DMI3}, + {"OSSE", LNL_PMC_LTR_OSSE}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", PTL_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", PTL_PMC_LTR_CUR_ASLT}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_clocksource_status_map[] = { + {"AON2_OFF_STS", BIT(0), 1}, + {"AON3_OFF_STS", BIT(1), 0}, + {"AON4_OFF_STS", BIT(2), 1}, + {"AON5_OFF_STS", BIT(3), 1}, + {"AON1_OFF_STS", BIT(4), 0}, + {"XTAL_LVM_OFF_STS", BIT(5), 0}, + {"MPFPW1_0_PLL_OFF_STS", BIT(6), 1}, + {"USB3_PLL_OFF_STS", BIT(8), 1}, + {"AON3_SPL_OFF_STS", BIT(9), 1}, + {"MPFPW2_0_PLL_OFF_STS", BIT(12), 1}, + {"XTAL_AGGR_OFF_STS", BIT(17), 1}, + {"USB2_PLL_OFF_STS", BIT(18), 0}, + {"SAF_PLL_OFF_STS", BIT(19), 1}, + {"SE_TCSS_PLL_OFF_STS", BIT(20), 1}, + {"DDI_PLL_OFF_STS", BIT(21), 1}, + {"FILTER_PLL_OFF_STS", BIT(22), 1}, + {"ACE_PLL_OFF_STS", BIT(24), 0}, + {"FABRIC_PLL_OFF_STS", BIT(25), 1}, + {"SOC_PLL_OFF_STS", BIT(26), 1}, + {"REF_PLL_OFF_STS", BIT(28), 1}, + {"IMG_PLL_OFF_STS", BIT(29), 1}, + {"RTC_PLL_OFF_STS", BIT(31), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0), 0}, + {"FUSE_OSSE_PGD0_PG_STS", BIT(1), 0}, + {"ESPISPI_PGD0_PG_STS", BIT(2), 0}, + {"XHCI_PGD0_PG_STS", BIT(3), 1}, + {"SPA_PGD0_PG_STS", BIT(4), 1}, + {"SPB_PGD0_PG_STS", BIT(5), 1}, + {"MPFPW2_PGD0_PG_STS", BIT(6), 0}, + {"GBE_PGD0_PG_STS", BIT(7), 1}, + {"SBR16B20_PGD0_PG_STS", BIT(8), 0}, + {"SBR8B20_PGD0_PG_STS", BIT(9), 0}, + {"SBR16B21_PGD0_PG_STS", BIT(10), 0}, + {"DBG_PGD0_PG_STS", BIT(11), 0}, + {"OSSE_HOTHAM_PGD0_PG_STS", BIT(12), 1}, + {"D2D_DISP_PGD1_PG_STS", BIT(13), 1}, + {"LPSS_PGD0_PG_STS", BIT(14), 1}, + {"LPC_PGD0_PG_STS", BIT(15), 0}, + {"SMB_PGD0_PG_STS", BIT(16), 0}, + {"ISH_PGD0_PG_STS", BIT(17), 0}, + {"SBR16B2_PGD0_PG_STS", BIT(18), 0}, + {"NPK_PGD0_PG_STS", BIT(19), 0}, + {"D2D_NOC_PGD1_PG_STS", BIT(20), 1}, + {"SBR8B2_PGD0_PG_STS", BIT(21), 0}, + {"FUSE_PGD0_PG_STS", BIT(22), 0}, + {"SBR16B0_PGD0_PG_STS", BIT(23), 0}, + {"PSF0_PGD0_PG_STS", BIT(24), 0}, + {"XDCI_PGD0_PG_STS", BIT(25), 1}, + {"EXI_PGD0_PG_STS", BIT(26), 0}, + {"CSE_PGD0_PG_STS", BIT(27), 1}, + {"KVMCC_PGD0_PG_STS", BIT(28), 1}, + {"PMT_PGD0_PG_STS", BIT(29), 1}, + {"CLINK_PGD0_PG_STS", BIT(30), 1}, + {"PTIO_PGD0_PG_STS", BIT(31), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_power_gating_status_1_map[] = { + {"USBR0_PGD0_PG_STS", BIT(0), 1}, + {"SUSRAM_PGD0_PG_STS", BIT(1), 1}, + {"SMT1_PGD0_PG_STS", BIT(2), 1}, + {"MPFPW1_PGD0_PG_STS", BIT(3), 0}, + {"SMS2_PGD0_PG_STS", BIT(4), 1}, + {"SMS1_PGD0_PG_STS", BIT(5), 1}, + {"CSMERTC_PGD0_PG_STS", BIT(6), 0}, + {"CSMEPSF_PGD0_PG_STS", BIT(7), 0}, + {"D2D_NOC_PGD0_PG_STS", BIT(8), 0}, + {"ESE_PGD0_PG_STS", BIT(9), 1}, + {"P2SB8B_PGD0_PG_STS", BIT(10), 1}, + {"SBR16B7_PGD0_PG_STS", BIT(11), 0}, + {"SBR16B3_PGD0_PG_STS", BIT(12), 0}, + {"OSSE_SMT1_PGD0_PG_STS", BIT(13), 1}, + {"D2D_DISP_PGD0_PG_STS", BIT(14), 1}, + {"DBG_SBR_PGD0_PG_STS", BIT(15), 0}, + {"U3FPW1_PGD0_PG_STS", BIT(16), 0}, + {"FIA_X_PGD0_PG_STS", BIT(17), 0}, + {"PSF4_PGD0_PG_STS", BIT(18), 0}, + {"CNVI_PGD0_PG_STS", BIT(19), 0}, + {"UFSX2_PGD0_PG_STS", BIT(20), 1}, + {"ENDBG_PGD0_PG_STS", BIT(21), 0}, + {"DBC_PGD0_PG_STS", BIT(22), 0}, + {"FIA_PG_PGD0_PG_STS", BIT(23), 0}, + {"D2D_IPU_PGD0_PG_STS", BIT(24), 1}, + {"NPK_PGD1_PG_STS", BIT(25), 0}, + {"FIACPCB_X_PGD0_PG_STS", BIT(26), 0}, + {"SBR8B4_PGD0_PG_STS", BIT(27), 0}, + {"DBG_PSF_PGD0_PG_STS", BIT(28), 0}, + {"PSF6_PGD0_PG_STS", BIT(29), 0}, + {"UFSPW1_PGD0_PG_STS", BIT(30), 0}, + {"FIA_U_PGD0_PG_STS", BIT(31), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_power_gating_status_2_map[] = { + {"PSF8_PGD0_PG_STS", BIT(0), 0}, + {"SBR16B4_PGD0_PG_STS", BIT(1), 0}, + {"SBR16B5_PGD0_PG_STS", BIT(2), 0}, + {"FIACPCB_U_PGD0_PG_STS", BIT(3), 0}, + {"TAM_PGD0_PG_STS", BIT(4), 1}, + {"D2D_NOC_PGD0_PG_STS", BIT(5), 1}, + {"TBTLSX_PGD0_PG_STS", BIT(6), 1}, + {"THC0_PGD0_PG_STS", BIT(7), 1}, + {"THC1_PGD0_PG_STS", BIT(8), 1}, + {"PMC_PGD1_PG_STS", BIT(9), 0}, + {"SBR8B1_PGD0_PG_STS", BIT(10), 0}, + {"TCSS_PGD0_PG_STS", BIT(11), 0}, + {"DISP_PGA_PGD0_PG_STS", BIT(12), 0}, + {"SBR16B1_PGD0_PG_STS", BIT(13), 0}, + {"SBRG_PGD0_PG_STS", BIT(14), 0}, + {"PSF5_PGD0_PG_STS", BIT(15), 0}, + {"P2SB16B_PGD0_PG_STS", BIT(16), 1}, + {"ACE_PGD0_PG_STS", BIT(17), 0}, + {"ACE_PGD1_PG_STS", BIT(18), 0}, + {"ACE_PGD2_PG_STS", BIT(19), 0}, + {"ACE_PGD3_PG_STS", BIT(20), 0}, + {"ACE_PGD4_PG_STS", BIT(21), 0}, + {"ACE_PGD5_PG_STS", BIT(22), 0}, + {"ACE_PGD6_PG_STS", BIT(23), 0}, + {"ACE_PGD7_PG_STS", BIT(24), 0}, + {"ACE_PGD8_PG_STS", BIT(25), 0}, + {"ACE_PGD9_PG_STS", BIT(26), 0}, + {"ACE_PGD10_PG_STS", BIT(27), 0}, + {"FIACPCB_PG_PGD0_PG_STS", BIT(28), 0}, + {"SBR16B6_PGD0_PG_STS", BIT(29), 0}, + {"OSSE_PGD0_PG_STS", BIT(30), 1}, + {"SBR8B0_PGD0_PG_STS", BIT(31), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_d3_status_0_map[] = { + {"LPSS_D3_STS", BIT(3), 1}, + {"XDCI_D3_STS", BIT(4), 1}, + {"XHCI_D3_STS", BIT(5), 1}, + {"OSSE_D3_STS", BIT(6), 0}, + {"SPA_D3_STS", BIT(12), 0}, + {"SPB_D3_STS", BIT(13), 0}, + {"ESPISPI_D3_STS", BIT(18), 0}, + {"PSTH_D3_STS", BIT(21), 0}, + {"OSSE_SMT1_D3_STS", BIT(30), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_d3_status_1_map[] = { + {"GBE_D3_STS", BIT(19), 0}, + {"ITSS_D3_STS", BIT(23), 0}, + {"CNVI_D3_STS", BIT(27), 0}, + {"UFSX2_D3_STS", BIT(28), 1}, + {"OSSE_HOTHAM_D3_STS", BIT(29), 0}, + {"ESE_D3_STS", BIT(30), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_d3_status_2_map[] = { + {"CSMERTC_D3_STS", BIT(1), 0}, + {"SUSRAM_D3_STS", BIT(2), 0}, + {"CSE_D3_STS", BIT(4), 0}, + {"KVMCC_D3_STS", BIT(5), 0}, + {"USBR0_D3_STS", BIT(6), 0}, + {"ISH_D3_STS", BIT(7), 0}, + {"SMT1_D3_STS", BIT(8), 0}, + {"SMT2_D3_STS", BIT(9), 0}, + {"SMT3_D3_STS", BIT(10), 0}, + {"OSSE_SMT2_D3_STS", BIT(12), 0}, + {"CLINK_D3_STS", BIT(14), 0}, + {"PTIO_D3_STS", BIT(16), 0}, + {"PMT_D3_STS", BIT(17), 0}, + {"SMS1_D3_STS", BIT(18), 0}, + {"SMS2_D3_STS", BIT(19), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_d3_status_3_map[] = { + {"THC0_D3_STS", BIT(14), 1}, + {"THC1_D3_STS", BIT(15), 1}, + {"OSSE_SMT3_D3_STS", BIT(18), 0}, + {"ACE_D3_STS", BIT(23), 0}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_vnn_req_status_0_map[] = { + {"LPSS_VNN_REQ_STS", BIT(3), 1}, + {"OSSE_VNN_REQ_STS", BIT(6), 1}, + {"ESPISPI_VNN_REQ_STS", BIT(18), 1}, + {"OSSE_SMT1_VNN_REQ_STS", BIT(30), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_vnn_req_status_1_map[] = { + {"NPK_VNN_REQ_STS", BIT(4), 1}, + {"DFXAGG_VNN_REQ_STS", BIT(8), 0}, + {"EXI_VNN_REQ_STS", BIT(9), 1}, + {"P2D_VNN_REQ_STS", BIT(18), 1}, + {"GBE_VNN_REQ_STS", BIT(19), 1}, + {"SMB_VNN_REQ_STS", BIT(25), 1}, + {"LPC_VNN_REQ_STS", BIT(26), 0}, + {"ESE_VNN_REQ_STS", BIT(30), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_vnn_req_status_2_map[] = { + {"CSMERTC_VNN_REQ_STS", BIT(1), 1}, + {"CSE_VNN_REQ_STS", BIT(4), 1}, + {"ISH_VNN_REQ_STS", BIT(7), 1}, + {"SMT1_VNN_REQ_STS", BIT(8), 1}, + {"CLINK_VNN_REQ_STS", BIT(14), 1}, + {"SMS1_VNN_REQ_STS", BIT(18), 1}, + {"SMS2_VNN_REQ_STS", BIT(19), 1}, + {"GPIOCOM4_VNN_REQ_STS", BIT(20), 1}, + {"GPIOCOM3_VNN_REQ_STS", BIT(21), 1}, + {"GPIOCOM1_VNN_REQ_STS", BIT(23), 1}, + {"GPIOCOM0_VNN_REQ_STS", BIT(24), 1}, + {"DISP_SHIM_VNN_REQ_STS", BIT(26), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_vnn_req_status_3_map[] = { + {"DTS0_VNN_REQ_STS", BIT(7), 0}, + {"GPIOCOM5_VNN_REQ_STS", BIT(11), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0), 0}, + {"TS_OFF_REQ_STS", BIT(1), 0}, + {"PNDE_MET_REQ_STS", BIT(2), 1}, + {"PG5_PMA0_REQ_STS", BIT(3), 0}, + {"FW_THROTTLE_ALLOWED_REQ_STS", BIT(4), 0}, + {"VNN_SOC_REQ_STS", BIT(6), 1}, + {"ISH_VNNAON_REQ_STS", BIT(7), 0}, + {"D2D_NOC_CFI_QACTIVE_REQ_STS", BIT(8), 1}, + {"D2D_NOC_GPSB_QACTIVE_REQ_STS", BIT(9), 1}, + {"D2D_IPU_QACTIVE_REQ_STS", BIT(10), 1}, + {"PLT_GREATER_REQ_STS", BIT(11), 1}, + {"ALL_SBR_IDLE_REQ_STS", BIT(12), 0}, + {"PMC_IDLE_FB_OCP_REQ_STS", BIT(13), 0}, + {"PM_SYNC_STATES_REQ_STS", BIT(14), 0}, + {"EA_REQ_STS", BIT(15), 0}, + {"MPHY_CORE_OFF_REQ_STS", BIT(16), 0}, + {"BRK_EV_EN_REQ_STS", BIT(17), 0}, + {"AUTO_DEMO_EN_REQ_STS", BIT(18), 0}, + {"ITSS_CLK_SRC_REQ_STS", BIT(19), 1}, + {"ARC_IDLE_REQ_STS", BIT(21), 0}, + {"PG5_PMA1_REQ_STS", BIT(22), 0}, + {"FIA_DEEP_PM_REQ_STS", BIT(23), 0}, + {"XDCI_ATTACHED_REQ_STS", BIT(24), 1}, + {"ARC_INTERRUPT_WAKE_REQ_STS", BIT(25), 0}, + {"D2D_DISP_DDI_QACTIVE_REQ_STS", BIT(26), 1}, + {"PRE_WAKE0_REQ_STS", BIT(27), 1}, + {"PRE_WAKE1_REQ_STS", BIT(28), 1}, + {"PRE_WAKE2_REQ_STS", BIT(29), 1}, + {"D2D_DISP_EDP_QACTIVE_REQ_STS", BIT(31), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_signal_status_map[] = { + {"LSX_Wake0_STS", BIT(0), 0}, + {"LSX_Wake1_STS", BIT(1), 0}, + {"LSX_Wake2_STS", BIT(2), 0}, + {"LSX_Wake3_STS", BIT(3), 0}, + {"LSX_Wake4_STS", BIT(4), 0}, + {"LSX_Wake5_STS", BIT(5), 0}, + {"LSX_Wake6_STS", BIT(6), 0}, + {"LSX_Wake7_STS", BIT(7), 0}, + {"LPSS_Wake0_STS", BIT(8), 1}, + {"LPSS_Wake1_STS", BIT(9), 1}, + {"Int_Timer_SS_Wake0_STS", BIT(10), 1}, + {"Int_Timer_SS_Wake1_STS", BIT(11), 1}, + {"Int_Timer_SS_Wake2_STS", BIT(12), 1}, + {"Int_Timer_SS_Wake3_STS", BIT(13), 1}, + {"Int_Timer_SS_Wake4_STS", BIT(14), 1}, + {"Int_Timer_SS_Wake5_STS", BIT(15), 1}, + {} +}; + +static const struct pmc_bit_map ptl_pcdp_rsc_status_map[] = { + {"Memory", 0, 1}, + {"PSF0", 0, 1}, + {"PSF4", 0, 1}, + {"PSF5", 0, 1}, + {"PSF6", 0, 1}, + {"PSF8", 0, 1}, + {"SAF_CFI_LINK", 0, 1}, + {"SB", 0, 1}, + {} +}; + +static const struct pmc_bit_map *ptl_pcdp_lpm_maps[] = { + ptl_pcdp_clocksource_status_map, + ptl_pcdp_power_gating_status_0_map, + ptl_pcdp_power_gating_status_1_map, + ptl_pcdp_power_gating_status_2_map, + ptl_pcdp_d3_status_0_map, + ptl_pcdp_d3_status_1_map, + ptl_pcdp_d3_status_2_map, + ptl_pcdp_d3_status_3_map, + ptl_pcdp_vnn_req_status_0_map, + ptl_pcdp_vnn_req_status_1_map, + ptl_pcdp_vnn_req_status_2_map, + ptl_pcdp_vnn_req_status_3_map, + ptl_pcdp_vnn_misc_status_map, + ptl_pcdp_signal_status_map, + NULL +}; + +static const struct pmc_bit_map *ptl_pcdp_blk_maps[] = { + ptl_pcdp_power_gating_status_0_map, + ptl_pcdp_power_gating_status_1_map, + ptl_pcdp_power_gating_status_2_map, + ptl_pcdp_rsc_status_map, + ptl_pcdp_vnn_req_status_0_map, + ptl_pcdp_vnn_req_status_1_map, + ptl_pcdp_vnn_req_status_2_map, + ptl_pcdp_vnn_req_status_3_map, + ptl_pcdp_d3_status_0_map, + ptl_pcdp_d3_status_1_map, + ptl_pcdp_d3_status_2_map, + ptl_pcdp_d3_status_3_map, + ptl_pcdp_clocksource_status_map, + ptl_pcdp_vnn_misc_status_map, + ptl_pcdp_signal_status_map, + NULL +}; + +static const struct pmc_reg_map ptl_pcdp_reg_map = { + .pfear_sts = ext_ptl_pcdp_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, + .ltr_show_sts = ptl_pcdp_ltr_show_map, + .msr_sts = msr_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = PTL_PCD_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = LNL_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .lpm_num_maps = PTL_LPM_NUM_MAPS, + .ltr_ignore_max = LNL_NUM_IP_IGN_ALLOWED, + .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, + .etr3_offset = ETR3_OFFSET, + .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, + .lpm_priority_offset = MTL_LPM_PRI_OFFSET, + .lpm_en_offset = MTL_LPM_EN_OFFSET, + .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, + .lpm_sts = ptl_pcdp_lpm_maps, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, + .s0ix_blocker_maps = ptl_pcdp_blk_maps, + .s0ix_blocker_offset = LNL_S0IX_BLOCKER_OFFSET, +}; + +#define PTL_NPU_PCI_DEV 0xb03e +#define PTL_IPU_PCI_DEV 0xb05d + +/* + * Set power state of select devices that do not have drivers to D3 + * so that they do not block Package C entry. + */ +static void ptl_d3_fixup(void) +{ + pmc_core_set_device_d3(PTL_IPU_PCI_DEV); + pmc_core_set_device_d3(PTL_NPU_PCI_DEV); +} + +static int ptl_resume(struct pmc_dev *pmcdev) +{ + ptl_d3_fixup(); + return cnl_resume(pmcdev); +} + +static int ptl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) +{ + ptl_d3_fixup(); + return generic_core_init(pmcdev, pmc_dev_info); +} + +struct pmc_dev_info ptl_pmc_dev = { + .map = &ptl_pcdp_reg_map, + .suspend = cnl_suspend, + .resume = ptl_resume, + .init = ptl_core_init, +}; diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c index ab993a69e33e..b50534aa2cba 100644 --- a/drivers/platform/x86/intel/pmc/spt.c +++ b/drivers/platform/x86/intel/pmc/spt.c @@ -8,9 +8,11 @@ * */ +#include <linux/pci.h> + #include "core.h" -const struct pmc_bit_map spt_pll_map[] = { +static const struct pmc_bit_map spt_pll_map[] = { {"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0}, {"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1}, {"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2}, @@ -18,7 +20,7 @@ const struct pmc_bit_map spt_pll_map[] = { {} }; -const struct pmc_bit_map spt_mphy_map[] = { +static const struct pmc_bit_map spt_mphy_map[] = { {"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0}, {"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1}, {"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2}, @@ -38,7 +40,7 @@ const struct pmc_bit_map spt_mphy_map[] = { {} }; -const struct pmc_bit_map spt_pfear_map[] = { +static const struct pmc_bit_map spt_pfear_map[] = { {"PMC", SPT_PMC_BIT_PMC}, {"OPI-DMI", SPT_PMC_BIT_OPI}, {"SPI / eSPI", SPT_PMC_BIT_SPI}, @@ -82,7 +84,7 @@ const struct pmc_bit_map spt_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_spt_pfear_map[] = { +static const struct pmc_bit_map *ext_spt_pfear_map[] = { /* * Check intel_pmc_core_ids[] users of spt_reg_map for * a list of core SoCs using this. @@ -91,7 +93,7 @@ const struct pmc_bit_map *ext_spt_pfear_map[] = { NULL }; -const struct pmc_bit_map spt_ltr_show_map[] = { +static const struct pmc_bit_map spt_ltr_show_map[] = { {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, {"SATA", SPT_PMC_LTR_SATA}, @@ -116,7 +118,7 @@ const struct pmc_bit_map spt_ltr_show_map[] = { {} }; -const struct pmc_reg_map spt_reg_map = { +static const struct pmc_reg_map spt_reg_map = { .pfear_sts = ext_spt_pfear_map, .mphy_sts = spt_mphy_map, .pll_sts = spt_pll_map, @@ -134,18 +136,25 @@ const struct pmc_reg_map spt_reg_map = { .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, }; -int spt_core_init(struct pmc_dev *pmcdev) -{ - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; - int ret; - - pmc->map = &spt_reg_map; - - ret = get_primary_reg_base(pmc); - if (ret) - return ret; +static const struct pci_device_id spt_pmc_pci_id[] = { + { PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) }, + { } +}; - pmc_core_get_low_power_modes(pmcdev); +static int spt_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) +{ + /* + * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here + * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap + * in this case. + */ + if (!pci_dev_present(spt_pmc_pci_id)) + return generic_core_init(pmcdev, &cnp_pmc_dev); - return ret; + return generic_core_init(pmcdev, pmc_dev_info); } + +struct pmc_dev_info spt_pmc_dev = { + .map = &spt_reg_map, + .init = spt_core_init, +}; diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c index e0580de18077..02e731ed3391 100644 --- a/drivers/platform/x86/intel/pmc/tgl.c +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -18,7 +18,7 @@ enum pch_type { PCH_LP }; -const struct pmc_bit_map tgl_pfear_map[] = { +static const struct pmc_bit_map tgl_pfear_map[] = { {"PSF9", BIT(0)}, {"RES_66", BIT(1)}, {"RES_67", BIT(2)}, @@ -29,7 +29,7 @@ const struct pmc_bit_map tgl_pfear_map[] = { {} }; -const struct pmc_bit_map *ext_tgl_pfear_map[] = { +static const struct pmc_bit_map *ext_tgl_pfear_map[] = { /* * Check intel_pmc_core_ids[] users of tgl_reg_map for * a list of core SoCs using this. @@ -39,7 +39,7 @@ const struct pmc_bit_map *ext_tgl_pfear_map[] = { NULL }; -const struct pmc_bit_map tgl_clocksource_status_map[] = { +static const struct pmc_bit_map tgl_clocksource_status_map[] = { {"USB2PLL_OFF_STS", BIT(18)}, {"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)}, {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, @@ -55,7 +55,7 @@ const struct pmc_bit_map tgl_clocksource_status_map[] = { {} }; -const struct pmc_bit_map tgl_power_gating_status_map[] = { +static const struct pmc_bit_map tgl_power_gating_status_map[] = { {"CSME_PG_STS", BIT(0)}, {"SATA_PG_STS", BIT(1)}, {"xHCI_PG_STS", BIT(2)}, @@ -83,7 +83,7 @@ const struct pmc_bit_map tgl_power_gating_status_map[] = { {} }; -const struct pmc_bit_map tgl_d3_status_map[] = { +static const struct pmc_bit_map tgl_d3_status_map[] = { {"ADSP_D3_STS", BIT(0)}, {"SATA_D3_STS", BIT(1)}, {"xHCI0_D3_STS", BIT(2)}, @@ -98,7 +98,7 @@ const struct pmc_bit_map tgl_d3_status_map[] = { {} }; -const struct pmc_bit_map tgl_vnn_req_status_map[] = { +static const struct pmc_bit_map tgl_vnn_req_status_map[] = { {"GPIO_COM0_VNN_REQ_STS", BIT(1)}, {"GPIO_COM1_VNN_REQ_STS", BIT(2)}, {"GPIO_COM2_VNN_REQ_STS", BIT(3)}, @@ -123,7 +123,7 @@ const struct pmc_bit_map tgl_vnn_req_status_map[] = { {} }; -const struct pmc_bit_map tgl_vnn_misc_status_map[] = { +static const struct pmc_bit_map tgl_vnn_misc_status_map[] = { {"CPU_C10_REQ_STS_0", BIT(0)}, {"PCIe_LPM_En_REQ_STS_3", BIT(3)}, {"ITH_REQ_STS_5", BIT(5)}, @@ -175,7 +175,7 @@ const struct pmc_bit_map tgl_signal_status_map[] = { {} }; -const struct pmc_bit_map *tgl_lpm_maps[] = { +static const struct pmc_bit_map *tgl_lpm_maps[] = { tgl_clocksource_status_map, tgl_power_gating_status_map, tgl_d3_status_map, @@ -185,7 +185,7 @@ const struct pmc_bit_map *tgl_lpm_maps[] = { NULL }; -const struct pmc_reg_map tgl_reg_map = { +static const struct pmc_reg_map tgl_reg_map = { .pfear_sts = ext_tgl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, @@ -210,7 +210,7 @@ const struct pmc_reg_map tgl_reg_map = { .etr3_offset = ETR3_OFFSET, }; -const struct pmc_reg_map tgl_h_reg_map = { +static const struct pmc_reg_map tgl_h_reg_map = { .pfear_sts = ext_tgl_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, @@ -285,35 +285,28 @@ free_acpi_obj: ACPI_FREE(out_obj); } -int tgl_l_core_init(struct pmc_dev *pmcdev) +static int tgl_core_init(struct pmc_dev *pmcdev, struct pmc_dev_info *pmc_dev_info) { - return tgl_core_generic_init(pmcdev, PCH_LP); -} - -int tgl_core_init(struct pmc_dev *pmcdev) -{ - return tgl_core_generic_init(pmcdev, PCH_H); -} - -int tgl_core_generic_init(struct pmc_dev *pmcdev, int pch_tp) -{ - struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; int ret; - if (pch_tp == PCH_H) - pmc->map = &tgl_h_reg_map; - else - pmc->map = &tgl_reg_map; - - pmcdev->suspend = cnl_suspend; - pmcdev->resume = cnl_resume; - - ret = get_primary_reg_base(pmc); + ret = generic_core_init(pmcdev, pmc_dev_info); if (ret) return ret; - pmc_core_get_low_power_modes(pmcdev); pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); - return 0; } + +struct pmc_dev_info tgl_l_pmc_dev = { + .map = &tgl_reg_map, + .suspend = cnl_suspend, + .resume = cnl_resume, + .init = tgl_core_init, +}; + +struct pmc_dev_info tgl_pmc_dev = { + .map = &tgl_h_reg_map, + .suspend = cnl_suspend, + .resume = cnl_resume, + .init = tgl_core_init, +}; diff --git a/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c b/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c new file mode 100644 index 000000000000..89153afd7015 --- /dev/null +++ b/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Lenovo Super Hotkey Utility WMI extras driver for Ideapad laptop + * + * Copyright (C) 2025 Lenovo + */ + +#include <linux/cleanup.h> +#include <linux/dev_printk.h> +#include <linux/device.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/wmi.h> + +/* Lenovo Super Hotkey WMI GUIDs */ +#define LUD_WMI_METHOD_GUID "CE6C0974-0407-4F50-88BA-4FC3B6559AD8" + +/* Lenovo Utility Data WMI method_id */ +#define WMI_LUD_GET_SUPPORT 1 +#define WMI_LUD_SET_FEATURE 2 + +#define WMI_LUD_GET_MICMUTE_LED_VER 20 +#define WMI_LUD_GET_AUDIOMUTE_LED_VER 26 + +#define WMI_LUD_SUPPORT_MICMUTE_LED_VER 25 +#define WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER 27 + +/* Input parameters to mute/unmute audio LED and Mic LED */ +struct wmi_led_args { + u8 id; + u8 subid; + u16 value; +}; + +/* Values of input parameters to SetFeature of audio LED and Mic LED */ +enum hotkey_set_feature { + MIC_MUTE_LED_ON = 1, + MIC_MUTE_LED_OFF = 2, + AUDIO_MUTE_LED_ON = 4, + AUDIO_MUTE_LED_OFF = 5, +}; + +#define LSH_ACPI_LED_MAX 2 + +struct lenovo_super_hotkey_wmi_private { + struct led_classdev cdev[LSH_ACPI_LED_MAX]; + struct wmi_device *led_wdev; +}; + +enum mute_led_type { + MIC_MUTE, + AUDIO_MUTE, +}; + +static int lsh_wmi_mute_led_set(enum mute_led_type led_type, struct led_classdev *led_cdev, + enum led_brightness brightness) + +{ + struct lenovo_super_hotkey_wmi_private *wpriv = container_of(led_cdev, + struct lenovo_super_hotkey_wmi_private, cdev[led_type]); + struct wmi_led_args led_arg = {0, 0, 0}; + struct acpi_buffer input; + acpi_status status; + + switch (led_type) { + case MIC_MUTE: + led_arg.id = brightness == LED_ON ? MIC_MUTE_LED_ON : MIC_MUTE_LED_OFF; + break; + case AUDIO_MUTE: + led_arg.id = brightness == LED_ON ? AUDIO_MUTE_LED_ON : AUDIO_MUTE_LED_OFF; + break; + default: + return -EINVAL; + } + + input.length = sizeof(led_arg); + input.pointer = &led_arg; + status = wmidev_evaluate_method(wpriv->led_wdev, 0, WMI_LUD_SET_FEATURE, &input, NULL); + if (ACPI_FAILURE(status)) + return -EIO; + + return 0; +} + +static int lsh_wmi_audiomute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) + +{ + return lsh_wmi_mute_led_set(AUDIO_MUTE, led_cdev, brightness); +} + +static int lsh_wmi_micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + return lsh_wmi_mute_led_set(MIC_MUTE, led_cdev, brightness); +} + +static int lenovo_super_hotkey_wmi_led_init(enum mute_led_type led_type, struct device *dev) +{ + struct lenovo_super_hotkey_wmi_private *wpriv = dev_get_drvdata(dev); + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer input; + int led_version, err = 0; + unsigned int wmiarg; + acpi_status status; + + switch (led_type) { + case MIC_MUTE: + wmiarg = WMI_LUD_GET_MICMUTE_LED_VER; + break; + case AUDIO_MUTE: + wmiarg = WMI_LUD_GET_AUDIOMUTE_LED_VER; + break; + default: + return -EINVAL; + } + + input.length = sizeof(wmiarg); + input.pointer = &wmiarg; + status = wmidev_evaluate_method(wpriv->led_wdev, 0, WMI_LUD_GET_SUPPORT, &input, &output); + if (ACPI_FAILURE(status)) + return -EIO; + + union acpi_object *obj __free(kfree) = output.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + led_version = obj->integer.value; + else + return -EIO; + + wpriv->cdev[led_type].max_brightness = LED_ON; + wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME; + + switch (led_type) { + case MIC_MUTE: + if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER) + return -EIO; + + wpriv->cdev[led_type].name = "platform::micmute"; + wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_micmute_led_set; + wpriv->cdev[led_type].default_trigger = "audio-micmute"; + break; + case AUDIO_MUTE: + if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER) + return -EIO; + + wpriv->cdev[led_type].name = "platform::mute"; + wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_audiomute_led_set; + wpriv->cdev[led_type].default_trigger = "audio-mute"; + break; + default: + dev_err(dev, "Unknown LED type %d\n", led_type); + return -EINVAL; + } + + err = devm_led_classdev_register(dev, &wpriv->cdev[led_type]); + if (err < 0) { + dev_err(dev, "Could not register mute LED %d : %d\n", led_type, err); + return err; + } + return 0; +} + +static int lenovo_super_hotkey_wmi_leds_setup(struct device *dev) +{ + int err; + + err = lenovo_super_hotkey_wmi_led_init(MIC_MUTE, dev); + if (err) + return err; + + err = lenovo_super_hotkey_wmi_led_init(AUDIO_MUTE, dev); + if (err) + return err; + + return 0; +} + +static int lenovo_super_hotkey_wmi_probe(struct wmi_device *wdev, const void *context) +{ + struct lenovo_super_hotkey_wmi_private *wpriv; + + wpriv = devm_kzalloc(&wdev->dev, sizeof(*wpriv), GFP_KERNEL); + if (!wpriv) + return -ENOMEM; + + dev_set_drvdata(&wdev->dev, wpriv); + wpriv->led_wdev = wdev; + return lenovo_super_hotkey_wmi_leds_setup(&wdev->dev); +} + +static const struct wmi_device_id lenovo_super_hotkey_wmi_id_table[] = { + { LUD_WMI_METHOD_GUID, NULL }, /* Utility data */ + { } +}; + +MODULE_DEVICE_TABLE(wmi, lenovo_super_hotkey_wmi_id_table); + +static struct wmi_driver lenovo_wmi_hotkey_utilities_driver = { + .driver = { + .name = "lenovo_wmi_hotkey_utilities", + .probe_type = PROBE_PREFER_ASYNCHRONOUS + }, + .id_table = lenovo_super_hotkey_wmi_id_table, + .probe = lenovo_super_hotkey_wmi_probe, + .no_singleton = true, +}; + +module_wmi_driver(lenovo_wmi_hotkey_utilities_driver); + +MODULE_AUTHOR("Jackie Dong <dongeg1@lenovo.com>"); +MODULE_DESCRIPTION("Lenovo Super Hotkey Utility WMI extras driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c b/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c index a96b215cd2c5..25933cd018d1 100644 --- a/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c +++ b/drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c @@ -219,7 +219,7 @@ static int yt2_1380_fc_serdev_probe(struct serdev_device *serdev) return 0; } -struct serdev_device_driver yt2_1380_fc_serdev_driver = { +static struct serdev_device_driver yt2_1380_fc_serdev_driver = { .probe = yt2_1380_fc_serdev_probe, .driver = { .name = KBUILD_MODNAME, diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c deleted file mode 100644 index 9c7f30a47f1f..000000000000 --- a/drivers/platform/x86/mlx-platform.c +++ /dev/null @@ -1,6666 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 -/* - * Mellanox platform driver - * - * Copyright (C) 2016-2018 Mellanox Technologies - * Copyright (C) 2016-2018 Vadim Pasternak <vadimp@mellanox.com> - */ - -#include <linux/device.h> -#include <linux/dmi.h> -#include <linux/i2c.h> -#include <linux/i2c-mux.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/platform_data/i2c-mux-reg.h> -#include <linux/platform_data/mlxreg.h> -#include <linux/reboot.h> -#include <linux/regmap.h> - -#define MLX_PLAT_DEVICE_NAME "mlxplat" - -/* LPC bus IO offsets */ -#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 -#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 -#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 -#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 -#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 -#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03 -#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET 0x04 -#define MLXPLAT_CPLD_LPC_REG_CPLD1_PN1_OFFSET 0x05 -#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET 0x06 -#define MLXPLAT_CPLD_LPC_REG_CPLD2_PN1_OFFSET 0x07 -#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET 0x08 -#define MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET 0x09 -#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET 0x0a -#define MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET 0x0b -#define MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET 0x17 -#define MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET 0x19 -#define MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET 0x1c -#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d -#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e -#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f -#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 -#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 -#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 -#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 -#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 -#define MLXPLAT_CPLD_LPC_REG_LED6_OFFSET 0x25 -#define MLXPLAT_CPLD_LPC_REG_LED7_OFFSET 0x26 -#define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION 0x2a -#define MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET 0x2b -#define MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET 0x2d -#define MLXPLAT_CPLD_LPC_REG_GP0_OFFSET 0x2e -#define MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET 0x2f -#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 -#define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31 -#define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32 -#define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET 0x33 -#define MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE 0x34 -#define MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET 0x35 -#define MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET 0x36 -#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 -#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a -#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b -#define MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET 0x3c -#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 -#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 -#define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 -#define MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET 0x43 -#define MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET 0x44 -#define MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET 0x45 -#define MLXPLAT_CPLD_LPC_REG_BRD_OFFSET 0x47 -#define MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET 0x48 -#define MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET 0x49 -#define MLXPLAT_CPLD_LPC_REG_GWP_OFFSET 0x4a -#define MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET 0x4b -#define MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET 0x4c -#define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 -#define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51 -#define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52 -#define MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET 0x53 -#define MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET 0x54 -#define MLXPLAT_CPLD_LPC_REG_ASIC2_MASK_OFFSET 0x55 -#define MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET 0x56 -#define MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET 0x57 -#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 -#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 -#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a -#define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64 -#define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65 -#define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66 -#define MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET 0x70 -#define MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET 0x71 -#define MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET 0x72 -#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 -#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 -#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a -#define MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET 0x8e -#define MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET 0x8f -#define MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET 0x90 -#define MLXPLAT_CPLD_LPC_REG_EROT_OFFSET 0x91 -#define MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET 0x92 -#define MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET 0x93 -#define MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET 0x94 -#define MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET 0x95 -#define MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET 0x96 -#define MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET 0x97 -#define MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET 0x98 -#define MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET 0x99 -#define MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET 0x9a -#define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET 0x9b -#define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c -#define MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET 0x9d -#define MLXPLAT_CPLD_LPC_REG_LC_PG_EVENT_OFFSET 0x9e -#define MLXPLAT_CPLD_LPC_REG_LC_PG_MASK_OFFSET 0x9f -#define MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET 0xa0 -#define MLXPLAT_CPLD_LPC_REG_LC_RD_EVENT_OFFSET 0xa1 -#define MLXPLAT_CPLD_LPC_REG_LC_RD_MASK_OFFSET 0xa2 -#define MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET 0xa3 -#define MLXPLAT_CPLD_LPC_REG_LC_SN_EVENT_OFFSET 0xa4 -#define MLXPLAT_CPLD_LPC_REG_LC_SN_MASK_OFFSET 0xa5 -#define MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET 0xa6 -#define MLXPLAT_CPLD_LPC_REG_LC_OK_EVENT_OFFSET 0xa7 -#define MLXPLAT_CPLD_LPC_REG_LC_OK_MASK_OFFSET 0xa8 -#define MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET 0xa9 -#define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa -#define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab -#define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 -#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0xb6 -#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0xb7 -#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0xb8 -#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9 -#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 -#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 -#define MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET 0xc4 -#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 -#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8 -#define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9 -#define MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET 0xcb -#define MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET 0xcd -#define MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET 0xce -#define MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET 0xcf -#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1 -#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2 -#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3 -#define MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET 0xd9 -#define MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET 0xdb -#define MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET 0xda -#define MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET 0xdc -#define MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET 0xdd -#define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde -#define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf -#define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0 -#define MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET 0xe1 -#define MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET 0xe2 -#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 -#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 -#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5 -#define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET 0xe6 -#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 -#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 -#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 -#define MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET 0xea -#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xeb -#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xec -#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xed -#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee -#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef -#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0 -#define MLXPLAT_CPLD_LPC_REG_TACHO13_OFFSET 0xf1 -#define MLXPLAT_CPLD_LPC_REG_TACHO14_OFFSET 0xf2 -#define MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET 0xf3 -#define MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET 0xf4 -#define MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET 0xf5 -#define MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET 0xf6 -#define MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET 0xf7 -#define MLXPLAT_CPLD_LPC_REG_TACHO_SPEED_OFFSET 0xf8 -#define MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET 0xf9 -#define MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET 0xfa -#define MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET 0xfb -#define MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET 0xfc -#define MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET 0xfd -#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 - -#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL -#define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ - MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET) | \ - MLXPLAT_CPLD_LPC_PIO_OFFSET) -#define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ - MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET) | \ - MLXPLAT_CPLD_LPC_PIO_OFFSET) -#define MLXPLAT_CPLD_LPC_REG3 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ - MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET) | \ - MLXPLAT_CPLD_LPC_PIO_OFFSET) -#define MLXPLAT_CPLD_LPC_REG4 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ - MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET) | \ - MLXPLAT_CPLD_LPC_PIO_OFFSET) - -/* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */ -#define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF 0x04 -#define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08 -#define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08 -#define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40 -#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \ - MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ - MLXPLAT_CPLD_AGGR_FAN_MASK_DEF) -#define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01 -#define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04 -#define MLXPLAT_CPLD_AGGR_MASK_COMEX BIT(0) -#define MLXPLAT_CPLD_AGGR_MASK_LC BIT(3) -#define MLXPLAT_CPLD_AGGR_MASK_MODULAR (MLXPLAT_CPLD_AGGR_MASK_NG_DEF | \ - MLXPLAT_CPLD_AGGR_MASK_COMEX | \ - MLXPLAT_CPLD_AGGR_MASK_LC) -#define MLXPLAT_CPLD_AGGR_MASK_LC_PRSNT BIT(0) -#define MLXPLAT_CPLD_AGGR_MASK_LC_RDY BIT(1) -#define MLXPLAT_CPLD_AGGR_MASK_LC_PG BIT(2) -#define MLXPLAT_CPLD_AGGR_MASK_LC_SCRD BIT(3) -#define MLXPLAT_CPLD_AGGR_MASK_LC_SYNC BIT(4) -#define MLXPLAT_CPLD_AGGR_MASK_LC_ACT BIT(5) -#define MLXPLAT_CPLD_AGGR_MASK_LC_SDWN BIT(6) -#define MLXPLAT_CPLD_AGGR_MASK_LC_LOW (MLXPLAT_CPLD_AGGR_MASK_LC_PRSNT | \ - MLXPLAT_CPLD_AGGR_MASK_LC_RDY | \ - MLXPLAT_CPLD_AGGR_MASK_LC_PG | \ - MLXPLAT_CPLD_AGGR_MASK_LC_SCRD | \ - MLXPLAT_CPLD_AGGR_MASK_LC_SYNC | \ - MLXPLAT_CPLD_AGGR_MASK_LC_ACT | \ - MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) -#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 -#define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2) -#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT GENMASK(5, 4) -#define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) -#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) -#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) -#define MLXPLAT_CPLD_PSU_EXT_MASK GENMASK(3, 0) -#define MLXPLAT_CPLD_PWR_EXT_MASK GENMASK(3, 0) -#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) -#define MLXPLAT_CPLD_ASIC_MASK GENMASK(1, 0) -#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(6, 0) -#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4) -#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) -#define MLXPLAT_CPLD_VOLTREG_UPD_MASK GENMASK(5, 4) -#define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) -#define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) -#define MLXPLAT_CPLD_FU_CAP_MASK GENMASK(1, 0) -#define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) -#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6) -#define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) -#define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) -#define MLXPLAT_CPLD_INTRUSION_MASK BIT(6) -#define MLXPLAT_CPLD_PWM_PG_MASK BIT(7) -#define MLXPLAT_CPLD_L1_CHA_HEALTH_MASK (MLXPLAT_CPLD_THERMAL1_PDB_MASK | \ - MLXPLAT_CPLD_THERMAL2_PDB_MASK | \ - MLXPLAT_CPLD_INTRUSION_MASK |\ - MLXPLAT_CPLD_PWM_PG_MASK) -#define MLXPLAT_CPLD_I2C_CAP_BIT 0x04 -#define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT) -#define MLXPLAT_CPLD_SYS_RESET_MASK BIT(0) - -/* Masks for aggregation for comex carriers */ -#define MLXPLAT_CPLD_AGGR_MASK_CARRIER BIT(1) -#define MLXPLAT_CPLD_AGGR_MASK_CARR_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \ - MLXPLAT_CPLD_AGGR_MASK_CARRIER) -#define MLXPLAT_CPLD_LOW_AGGRCX_MASK 0xc1 - -/* Masks for aggregation for modular systems */ -#define MLXPLAT_CPLD_LPC_LC_MASK GENMASK(7, 0) - -#define MLXPLAT_CPLD_HALT_MASK BIT(3) -#define MLXPLAT_CPLD_RESET_MASK GENMASK(7, 1) - -/* Default I2C parent bus number */ -#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1 - -/* Maximum number of possible physical buses equipped on system */ -#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16 -#define MLXPLAT_CPLD_MAX_PHYS_EXT_ADAPTER_NUM 24 - -/* Number of channels in group */ -#define MLXPLAT_CPLD_GRP_CHNL_NUM 8 - -/* Start channel numbers */ -#define MLXPLAT_CPLD_CH1 2 -#define MLXPLAT_CPLD_CH2 10 -#define MLXPLAT_CPLD_CH3 18 -#define MLXPLAT_CPLD_CH2_ETH_MODULAR 3 -#define MLXPLAT_CPLD_CH3_ETH_MODULAR 43 -#define MLXPLAT_CPLD_CH4_ETH_MODULAR 51 -#define MLXPLAT_CPLD_CH2_RACK_SWITCH 18 -#define MLXPLAT_CPLD_CH2_NG800 34 - -/* Number of LPC attached MUX platform devices */ -#define MLXPLAT_CPLD_LPC_MUX_DEVS 4 - -/* Hotplug devices adapter numbers */ -#define MLXPLAT_CPLD_NR_NONE -1 -#define MLXPLAT_CPLD_PSU_DEFAULT_NR 10 -#define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4 -#define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11 -#define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12 -#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13 -#define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14 -#define MLXPLAT_CPLD_NR_ASIC 3 -#define MLXPLAT_CPLD_NR_LC_BASE 34 - -#define MLXPLAT_CPLD_NR_LC_SET(nr) (MLXPLAT_CPLD_NR_LC_BASE + (nr)) -#define MLXPLAT_CPLD_LC_ADDR 0x32 - -/* Masks and default values for watchdogs */ -#define MLXPLAT_CPLD_WD1_CLEAR_MASK GENMASK(7, 1) -#define MLXPLAT_CPLD_WD2_CLEAR_MASK (GENMASK(7, 0) & ~BIT(1)) - -#define MLXPLAT_CPLD_WD_TYPE1_TO_MASK GENMASK(7, 4) -#define MLXPLAT_CPLD_WD_TYPE2_TO_MASK 0 -#define MLXPLAT_CPLD_WD_RESET_ACT_MASK GENMASK(7, 1) -#define MLXPLAT_CPLD_WD_FAN_ACT_MASK (GENMASK(7, 0) & ~BIT(4)) -#define MLXPLAT_CPLD_WD_COUNT_ACT_MASK (GENMASK(7, 0) & ~BIT(7)) -#define MLXPLAT_CPLD_WD_CPBLTY_MASK (GENMASK(7, 0) & ~BIT(6)) -#define MLXPLAT_CPLD_WD_DFLT_TIMEOUT 30 -#define MLXPLAT_CPLD_WD3_DFLT_TIMEOUT 600 -#define MLXPLAT_CPLD_WD_MAX_DEVS 2 - -#define MLXPLAT_CPLD_LPC_SYSIRQ 17 - -/* Minimum power required for turning on Ethernet modular system (WATT) */ -#define MLXPLAT_CPLD_ETH_MODULAR_PWR_MIN 50 - -/* Default value for PWM control register for rack switch system */ -#define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4 - -#define MLXPLAT_I2C_MAIN_BUS_NOTIFIED 0x01 -#define MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED 0x02 - -/* Lattice FPGA PCI configuration */ -#define PCI_VENDOR_ID_LATTICE 0x1204 -#define PCI_DEVICE_ID_LATTICE_I2C_BRIDGE 0x9c2f -#define PCI_DEVICE_ID_LATTICE_JTAG_BRIDGE 0x9c30 -#define PCI_DEVICE_ID_LATTICE_LPC_BRIDGE 0x9c32 - -/* mlxplat_priv - platform private data - * @pdev_i2c - i2c controller platform device - * @pdev_mux - array of mux platform devices - * @pdev_hotplug - hotplug platform devices - * @pdev_led - led platform devices - * @pdev_io_regs - register access platform devices - * @pdev_fan - FAN platform devices - * @pdev_wd - array of watchdog platform devices - * @regmap: device register map - * @hotplug_resources: system hotplug resources - * @hotplug_resources_size: size of system hotplug resources - * @hi2c_main_init_status: init status of I2C main bus - * @irq_fpga: FPGA IRQ number - */ -struct mlxplat_priv { - struct platform_device *pdev_i2c; - struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS]; - struct platform_device *pdev_hotplug; - struct platform_device *pdev_led; - struct platform_device *pdev_io_regs; - struct platform_device *pdev_fan; - struct platform_device *pdev_wd[MLXPLAT_CPLD_WD_MAX_DEVS]; - void *regmap; - struct resource *hotplug_resources; - unsigned int hotplug_resources_size; - u8 i2c_main_init_status; - int irq_fpga; -}; - -static struct platform_device *mlxplat_dev; -static int mlxplat_i2c_main_completion_notify(void *handle, int id); -static void __iomem *i2c_bridge_addr, *jtag_bridge_addr; - -/* Regions for LPC I2C controller and LPC base register space */ -static const struct resource mlxplat_lpc_resources[] = { - [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR, - MLXPLAT_CPLD_LPC_IO_RANGE, - "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO), - [1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR, - MLXPLAT_CPLD_LPC_IO_RANGE, - "mlxplat_cpld_lpc_regs", - IORESOURCE_IO), -}; - -/* Platform systems default i2c data */ -static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_default_data = { - .completion_notify = mlxplat_i2c_main_completion_notify, -}; - -/* Platform i2c next generation systems data */ -static struct mlxreg_core_data mlxplat_mlxcpld_i2c_ng_items_data[] = { - { - .reg = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .mask = MLXPLAT_CPLD_I2C_CAP_MASK, - .bit = MLXPLAT_CPLD_I2C_CAP_BIT, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_i2c_ng_items[] = { - { - .data = mlxplat_mlxcpld_i2c_ng_items_data, - }, -}; - -/* Platform next generation systems i2c data */ -static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_ng_data = { - .items = mlxplat_mlxcpld_i2c_ng_items, - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_I2C, - .completion_notify = mlxplat_i2c_main_completion_notify, -}; - -/* Platform default channels */ -static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = { - { - MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2, - MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 + - 5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7 - }, - { - MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2, - MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 + - 5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7 - }, -}; - -/* Platform channels for MSN21xx system family */ -static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - -/* Platform mux data */ -static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = { - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH1, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, - .reg_size = 1, - .idle_in_use = 1, - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH2, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, - .reg_size = 1, - .idle_in_use = 1, - }, - -}; - -/* Platform mux configuration variables */ -static int mlxplat_max_adap_num; -static int mlxplat_mux_num; -static struct i2c_mux_reg_platform_data *mlxplat_mux_data; -static struct notifier_block *mlxplat_reboot_nb; - -/* Platform extended mux data */ -static struct i2c_mux_reg_platform_data mlxplat_extended_mux_data[] = { - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH1, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, - .reg_size = 1, - .idle_in_use = 1, - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH2, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG3, - .reg_size = 1, - .idle_in_use = 1, - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH3, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, - .reg_size = 1, - .idle_in_use = 1, - }, - -}; - -/* Platform channels for modular system family */ -static const int mlxplat_modular_upper_channel[] = { 1 }; -static const int mlxplat_modular_channels[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40 -}; - -/* Platform modular mux data */ -static struct i2c_mux_reg_platform_data mlxplat_modular_mux_data[] = { - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH1, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG4, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_modular_upper_channel, - .n_values = ARRAY_SIZE(mlxplat_modular_upper_channel), - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH2_ETH_MODULAR, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_modular_channels, - .n_values = ARRAY_SIZE(mlxplat_modular_channels), - }, - { - .parent = MLXPLAT_CPLD_CH1, - .base_nr = MLXPLAT_CPLD_CH3_ETH_MODULAR, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG3, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_msn21xx_channels, - .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH4_ETH_MODULAR, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_msn21xx_channels, - .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), - }, -}; - -/* Platform channels for rack switch system family */ -static const int mlxplat_rack_switch_channels[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -}; - -/* Platform rack switch mux data */ -static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = { - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH1, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_rack_switch_channels, - .n_values = ARRAY_SIZE(mlxplat_rack_switch_channels), - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH2_RACK_SWITCH, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_msn21xx_channels, - .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), - }, - -}; - -/* Platform channels for ng800 system family */ -static const int mlxplat_ng800_channels[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 -}; - -/* Platform ng800 mux data */ -static struct i2c_mux_reg_platform_data mlxplat_ng800_mux_data[] = { - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH1, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_ng800_channels, - .n_values = ARRAY_SIZE(mlxplat_ng800_channels), - }, - { - .parent = 1, - .base_nr = MLXPLAT_CPLD_CH2_NG800, - .write_only = 1, - .reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2, - .reg_size = 1, - .idle_in_use = 1, - .values = mlxplat_msn21xx_channels, - .n_values = ARRAY_SIZE(mlxplat_msn21xx_channels), - }, - -}; - -/* Platform hotplug devices */ -static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { - { - I2C_BOARD_INFO("dps460", 0x59), - }, - { - I2C_BOARD_INFO("dps460", 0x58), - }, -}; - -static struct i2c_board_info mlxplat_mlxcpld_ext_pwr[] = { - { - I2C_BOARD_INFO("dps460", 0x5b), - }, - { - I2C_BOARD_INFO("dps460", 0x5a), - }, -}; - -static struct i2c_board_info mlxplat_mlxcpld_pwr_ng800[] = { - { - I2C_BOARD_INFO("dps460", 0x59), - }, - { - I2C_BOARD_INFO("dps460", 0x5a), - }, -}; - -static struct i2c_board_info mlxplat_mlxcpld_fan[] = { - { - I2C_BOARD_INFO("24c32", 0x50), - }, - { - I2C_BOARD_INFO("24c32", 0x50), - }, - { - I2C_BOARD_INFO("24c32", 0x50), - }, - { - I2C_BOARD_INFO("24c32", 0x50), - }, -}; - -/* Platform hotplug comex carrier system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_comex_psu_items_data[] = { - { - .label = "psu1", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu2", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -/* Platform hotplug default data */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { - { - .label = "psu1", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu2", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_wc_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_ng800_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr_ng800[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { - { - .label = "fan1", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0], - .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR, - }, - { - .label = "fan2", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1], - .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR, - }, - { - .label = "fan3", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2], - .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR, - }, - { - .label = "fan4", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3], - .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = { - { - .label = "asic1", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_asic2_items_data[] = { - { - .label = "asic2", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { - { - .data = mlxplat_mlxcpld_default_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_comex_items[] = { - { - .data = mlxplat_mlxcpld_comex_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_CARRIER, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_CARRIER, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_CARRIER, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = { - .items = mlxplat_mlxcpld_default_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_default_wc_items[] = { - { - .data = mlxplat_mlxcpld_comex_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_CARRIER, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_pwr_wc_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_CARRIER, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_wc_data = { - .items = mlxplat_mlxcpld_default_wc_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_wc_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_comex_data = { - .items = mlxplat_mlxcpld_comex_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_comex_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_CARR_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGRCX_MASK, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -/* Platform hotplug MSN21xx system family data */ -static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = { - { - .data = mlxplat_mlxcpld_msn21xx_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { - .items = mlxplat_mlxcpld_msn21xx_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug msn274x system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = { - { - .label = "psu1", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu2", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = { - { - .label = "fan1", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan2", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan3", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(2), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan4", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(3), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = { - { - .data = mlxplat_mlxcpld_msn274x_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_msn274x_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = { - .items = mlxplat_mlxcpld_msn274x_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug MSN201x system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = { - { - .data = mlxplat_mlxcpld_msn201x_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = { - .items = mlxplat_mlxcpld_msn201x_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug next generation system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { - { - .label = "psu1", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu2", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = { - { - .label = "fan1", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan2", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(1), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan3", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(2), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan4", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(3), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan5", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(4), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan6", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(5), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "fan7", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = BIT(6), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(6), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = { - { - .data = mlxplat_mlxcpld_default_ng_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = { - .items = mlxplat_mlxcpld_default_ng_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug extended system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_ext_psu_items_data[] = { - { - .label = "psu1", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu2", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu3", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(2), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "psu4", - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = BIT(3), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_ext_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr3", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr4", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_ext_items[] = { - { - .data = mlxplat_mlxcpld_ext_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_ext_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, - { - .data = mlxplat_mlxcpld_default_asic2_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic2_items_data), - .inversed = 0, - .health = true, - } -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_ng800_items[] = { - { - .data = mlxplat_mlxcpld_default_ng_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_pwr_ng800_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_ng800_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), - .inversed = 0, - .health = true, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { - .items = mlxplat_mlxcpld_ext_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_ext_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ng800_data = { - .items = mlxplat_mlxcpld_ng800_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_ng800_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_pwr_items_data[] = { - { - .label = "pwr1", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr2", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr3", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, - { - .label = "pwr4", - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_lc_act = { - .irq = MLXPLAT_CPLD_LPC_SYSIRQ, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_asic_items_data[] = { - { - .label = "asic1", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct i2c_board_info mlxplat_mlxcpld_lc_i2c_dev[] = { - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, - { - I2C_BOARD_INFO("mlxreg-lc", MLXPLAT_CPLD_LC_ADDR), - .platform_data = &mlxplat_mlxcpld_lc_act, - }, -}; - -static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_modular_lc_notifier[] = { - { - .identity = "lc1", - }, - { - .identity = "lc2", - }, - { - .identity = "lc3", - }, - { - .identity = "lc4", - }, - { - .identity = "lc5", - }, - { - .identity = "lc6", - }, - { - .identity = "lc7", - }, - { - .identity = "lc8", - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_pr_items_data[] = { - { - .label = "lc1_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_present", - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_ver_items_data[] = { - { - .label = "lc1_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(0), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(1), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(2), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(3), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(4), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(5), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(6), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_verified", - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = BIT(7), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .reg_sync = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .reg_pwr = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .reg_ena = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_pg_data[] = { - { - .label = "lc1_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_powered", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_ready_data[] = { - { - .label = "lc1_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_ready", - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_synced_data[] = { - { - .label = "lc1_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_synced", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_act_data[] = { - { - .label = "lc1_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_active", - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_modular_lc_sd_data[] = { - { - .label = "lc1_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[0], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(0), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[0], - .slot = 1, - }, - { - .label = "lc2_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[1], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(1), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[1], - .slot = 2, - }, - { - .label = "lc3_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(2), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[2], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(2), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[2], - .slot = 3, - }, - { - .label = "lc4_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(3), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[3], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(3), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[3], - .slot = 4, - }, - { - .label = "lc5_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(4), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[4], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(4), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[4], - .slot = 5, - }, - { - .label = "lc6_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(5), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[5], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(5), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[5], - .slot = 6, - }, - { - .label = "lc7_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(6), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[6], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(6), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[6], - .slot = 7, - }, - { - .label = "lc8_shutdown", - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = BIT(7), - .hpdev.brdinfo = &mlxplat_mlxcpld_lc_i2c_dev[7], - .hpdev.nr = MLXPLAT_CPLD_NR_LC_SET(7), - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_modular_lc_notifier[7], - .slot = 8, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_modular_items[] = { - { - .data = mlxplat_mlxcpld_ext_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_asic_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_asic_items_data), - .inversed = 0, - .health = true, - }, - { - .data = mlxplat_mlxcpld_modular_lc_pr_items_data, - .kind = MLXREG_HOTPLUG_LC_PRESENT, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_pr_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_ver_items_data, - .kind = MLXREG_HOTPLUG_LC_VERIFIED, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_ver_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_pg_data, - .kind = MLXREG_HOTPLUG_LC_POWERED, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_pg_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_ready_data, - .kind = MLXREG_HOTPLUG_LC_READY, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_ready_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_synced_data, - .kind = MLXREG_HOTPLUG_LC_SYNCED, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_synced_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_act_data, - .kind = MLXREG_HOTPLUG_LC_ACTIVE, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_act_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_modular_lc_sd_data, - .kind = MLXREG_HOTPLUG_LC_THERMAL, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_LC, - .reg = MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET, - .mask = MLXPLAT_CPLD_LPC_LC_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_modular_lc_sd_data), - .inversed = 0, - .health = false, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_modular_data = { - .items = mlxplat_mlxcpld_modular_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_modular_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_MODULAR, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug for NVLink blade systems family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_global_wp_items_data[] = { - { - .label = "global_wp_grant", - .reg = MLXPLAT_CPLD_LPC_REG_GWP_OFFSET, - .mask = MLXPLAT_CPLD_GWP_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_chassis_blade_items[] = { - { - .data = mlxplat_mlxcpld_global_wp_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_GWP_OFFSET, - .mask = MLXPLAT_CPLD_GWP_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_global_wp_items_data), - .inversed = 0, - .health = false, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_chassis_blade_data = { - .items = mlxplat_mlxcpld_chassis_blade_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_chassis_blade_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Platform hotplug for switch systems family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_erot_ap_items_data[] = { - { - .label = "erot1_ap", - .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "erot2_ap", - .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_erot_error_items_data[] = { - { - .label = "erot1_error", - .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, - .mask = BIT(0), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "erot2_error", - .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, - .mask = BIT(1), - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_rack_switch_items[] = { - { - .data = mlxplat_mlxcpld_ext_psu_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, - .mask = MLXPLAT_CPLD_PSU_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_ext_pwr_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, - .mask = MLXPLAT_CPLD_PWR_EXT_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - .count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data), - .inversed = 0, - .health = false, - }, - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_erot_ap_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, - .mask = MLXPLAT_CPLD_EROT_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_erot_error_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, - .mask = MLXPLAT_CPLD_EROT_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data), - .inversed = 1, - .health = false, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { - .items = mlxplat_mlxcpld_rack_switch_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_rack_switch_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, -}; - -/* Callback performs graceful shutdown after notification about power button event */ -static int -mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_kind kind, - u8 action) -{ - if (action) { - dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); - kernel_power_off(); - } - - return 0; -} - -static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_pwr_events_notifier = { - .user_handler = mlxplat_mlxcpld_l1_switch_pwr_events_handler, -}; - -/* Platform hotplug for l1 switch systems family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_pwr_events_items_data[] = { - { - .label = "power_button", - .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, - .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_pwr_events_notifier, - }, -}; - -/* Callback activates latch reset flow after notification about intrusion event */ -static int -mlxplat_mlxcpld_l1_switch_intrusion_events_handler(void *handle, enum mlxreg_hotplug_kind kind, - u8 action) -{ - struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); - u32 regval; - int err; - - err = regmap_read(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ®val); - if (err) - goto fail_regmap_read; - - if (action) { - dev_info(&mlxplat_dev->dev, "Detected intrusion - system latch is opened"); - err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - regval | MLXPLAT_CPLD_LATCH_RST_MASK); - } else { - dev_info(&mlxplat_dev->dev, "System latch is properly closed"); - err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - regval & ~MLXPLAT_CPLD_LATCH_RST_MASK); - } - - if (err) - goto fail_regmap_write; - - return 0; - -fail_regmap_read: -fail_regmap_write: - dev_err(&mlxplat_dev->dev, "Register access failed"); - return err; -} - -static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_intrusion_events_notifier = { - .user_handler = mlxplat_mlxcpld_l1_switch_intrusion_events_handler, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_health_events_items_data[] = { - { - .label = "thermal1_pdb", - .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, - .mask = MLXPLAT_CPLD_THERMAL1_PDB_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "thermal2_pdb", - .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, - .mask = MLXPLAT_CPLD_THERMAL2_PDB_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, - { - .label = "intrusion", - .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, - .mask = MLXPLAT_CPLD_INTRUSION_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - .hpdev.action = MLXREG_HOTPLUG_DEVICE_NO_ACTION, - .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_intrusion_events_notifier, - }, - { - .label = "pwm_pg", - .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, - .mask = MLXPLAT_CPLD_PWM_PG_MASK, - .hpdev.nr = MLXPLAT_CPLD_NR_NONE, - }, -}; - -static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { - { - .data = mlxplat_mlxcpld_default_ng_fan_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - .mask = MLXPLAT_CPLD_FAN_NG_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_erot_ap_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET, - .mask = MLXPLAT_CPLD_EROT_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_erot_error_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET, - .mask = MLXPLAT_CPLD_EROT_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_l1_switch_pwr_events_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, - .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), - .inversed = 1, - .health = false, - }, - { - .data = mlxplat_mlxcpld_l1_switch_health_events_items_data, - .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, - .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, - .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), - .inversed = 1, - .health = false, - .ind = 8, - }, -}; - -static -struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_l1_switch_data = { - .items = mlxplat_mlxcpld_l1_switch_events_items, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_events_items), - .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, - .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX, - .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT, -}; - -/* Platform led default data */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "psu:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan1:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan2:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan3:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan3:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan4:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan4:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_led_data = { - .data = mlxplat_mlxcpld_default_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data), -}; - -/* Platform led default data for water cooling */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_led_wc_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "psu:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_led_wc_data = { - .data = mlxplat_mlxcpld_default_led_wc_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_wc_data), -}; - -/* Platform led default data for water cooling Ethernet switch blade */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_led_eth_wc_blade_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_led_eth_wc_blade_data = { - .data = mlxplat_mlxcpld_default_led_eth_wc_blade_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_eth_wc_blade_data), -}; - -/* Platform led MSN21xx system family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "fan:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "psu1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "psu1:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "psu2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu2:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "uid:blue", - .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = { - .data = mlxplat_mlxcpld_msn21xx_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data), -}; - -/* Platform led for default data for 200GbE systems */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "psu:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan1:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan2:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan3:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan3:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan4:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan4:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan5:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan5:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan6:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "fan6:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "fan7:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(6), - }, - { - .label = "fan7:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(6), - }, - { - .label = "uid:blue", - .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = { - .data = mlxplat_mlxcpld_default_ng_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data), -}; - -/* Platform led for Comex based 100GbE systems */ -static struct mlxreg_core_data mlxplat_mlxcpld_comex_100G_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "psu:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan1:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan2:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan3:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan3:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan4:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan4:red", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "uid:blue", - .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_comex_100G_led_data = { - .data = mlxplat_mlxcpld_comex_100G_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_comex_100G_led_data), -}; - -/* Platform led for data for modular systems */ -static struct mlxreg_core_data mlxplat_mlxcpld_modular_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "psu:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "psu:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - }, - { - .label = "fan1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan1:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan2:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan3:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan3:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan4:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan4:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan5:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan5:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan6:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "fan6:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "fan7:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(6), - }, - { - .label = "fan7:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(6), - }, - { - .label = "uid:blue", - .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan_front:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "fan_front:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED6_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "mgmt:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED7_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "mgmt:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED7_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_modular_led_data = { - .data = mlxplat_mlxcpld_modular_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_modular_led_data), -}; - -/* Platform led data for chassis system */ -static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_led_data[] = { - { - .label = "status:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, - { - .label = "status:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK - }, - { - .label = "fan1:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan1:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(0), - }, - { - .label = "fan2:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan2:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(1), - }, - { - .label = "fan3:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan3:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(2), - }, - { - .label = "fan4:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan4:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(3), - }, - { - .label = "fan5:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan5:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(4), - }, - { - .label = "fan6:green", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "fan6:orange", - .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, - .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, - .bit = BIT(5), - }, - { - .label = "uid:blue", - .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, - .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_l1_switch_led_data = { - .data = mlxplat_mlxcpld_l1_switch_led_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_led_data), -}; - -/* Platform register access default */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { - { - .label = "cpld1_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld1_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld2_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld1_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "reset_long_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_short_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_ref", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_main_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_sw_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_fw_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_hotswap_or_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_asic_thermal", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "psu1_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0200, - }, - { - .label = "psu2_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0200, - }, - { - .label = "pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "pwr_down", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "select_iio", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "asic_health", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .bit = 1, - .mode = 0444, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { - .data = mlxplat_mlxcpld_default_regs_io_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), -}; - -/* Platform register access MSN21xx, MSN201x, MSN274x systems families data */ -static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { - { - .label = "cpld1_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld1_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld2_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld1_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "reset_long_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_short_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_ref", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_sw_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_main_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_asic_thermal", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_hotswap_or_halt", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_sff_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "psu1_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0200, - }, - { - .label = "psu2_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0200, - }, - { - .label = "pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "pwr_down", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "select_iio", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "asic_health", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .bit = 1, - .mode = 0444, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { - .data = mlxplat_mlxcpld_msn21xx_regs_io_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), -}; - -/* Platform register access for next generation systems families data */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { - { - .label = "cpld1_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld3_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld4_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld5_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld1_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld2_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld3_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld4_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld5_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld1_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld3_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld4_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld5_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "asic_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "asic2_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "erot1_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "erot2_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, - { - .label = "clk_brd_prog_en", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0644, - .secured = 1, - }, - { - .label = "erot1_recovery", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "erot2_recovery", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, - { - .label = "erot1_wp", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - .secured = 1, - }, - { - .label = "erot2_wp", - .reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - .secured = 1, - }, - { - .label = "reset_long_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_short_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_ref", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_swb_dc_dc_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_from_asic", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_swb_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_asic_thermal", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "reset_sw_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_comex_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_platform", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_soc", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_comex_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_pwr_converter_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_system", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_sw_pwr_off", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_comex_thermal", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_reload_bios", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_ac_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_ac_ok_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "psu1_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0200, - }, - { - .label = "psu2_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0200, - }, - { - .label = "pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "pwr_down", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "deep_pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0200, - }, - { - .label = "latch_reset", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0200, - }, - { - .label = "jtag_cap", - .reg = MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET, - .mask = MLXPLAT_CPLD_FU_CAP_MASK, - .bit = 1, - .mode = 0444, - }, - { - .label = "jtag_enable", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "dbg1", - .reg = MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0644, - }, - { - .label = "dbg2", - .reg = MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0644, - }, - { - .label = "dbg3", - .reg = MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0644, - }, - { - .label = "dbg4", - .reg = MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0644, - }, - { - .label = "asic_health", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .bit = 1, - .mode = 0444, - }, - { - .label = "asic2_health", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .bit = 1, - .mode = 0444, - }, - { - .label = "fan_dir", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "bios_safe_mode", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "bios_active_image", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "bios_auth_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "bios_upgrade_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "voltreg_update_status", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET, - .mask = MLXPLAT_CPLD_VOLTREG_UPD_MASK, - .bit = 5, - .mode = 0444, - }, - { - .label = "pwr_converter_prog_en", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0644, - .secured = 1, - }, - { - .label = "vpd_wp", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0644, - }, - { - .label = "pcie_asic_reset_dis", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "erot1_ap_reset", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "erot2_ap_reset", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "lid_open", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "clk_brd1_boot_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "clk_brd2_boot_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "clk_brd_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "asic_pg_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "spi_chnl_select", - .reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT, - .mask = GENMASK(7, 0), - .bit = 1, - .mode = 0644, - }, - { - .label = "config1", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config2", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config3", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "ufm_version", - .reg = MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = { - .data = mlxplat_mlxcpld_default_ng_regs_io_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data), -}; - -/* Platform register access for modular systems families data */ -static struct mlxreg_core_data mlxplat_mlxcpld_modular_regs_io_data[] = { - { - .label = "cpld1_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld3_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld4_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld1_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld2_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld3_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld4_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld1_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld2_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld3_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld4_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "lc1_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0644, - }, - { - .label = "lc2_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0644, - }, - { - .label = "lc3_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0644, - }, - { - .label = "lc4_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0644, - }, - { - .label = "lc5_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "lc6_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - }, - { - .label = "lc7_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "lc8_enable", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, - { - .label = "reset_long_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_short_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_fu", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_mgmt_dc_dc_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_sys_comex_bios", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_sw_reset", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_reload", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_comex_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_platform", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_soc", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_pwr_off_from_carrier", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "reset_swb_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_swb_aux_pwr_or_fu", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_swb_dc_dc_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_swb_12v_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_system", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_thermal_spc_or_pciesw", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "bios_safe_mode", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "bios_active_image", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "bios_auth_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "bios_upgrade_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "voltreg_update_status", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET, - .mask = MLXPLAT_CPLD_VOLTREG_UPD_MASK, - .bit = 5, - .mode = 0444, - }, - { - .label = "vpd_wp", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0644, - }, - { - .label = "pcie_asic_reset_dis", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "shutdown_unlock", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - }, - { - .label = "lc1_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0200, - }, - { - .label = "lc2_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0200, - }, - { - .label = "lc3_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "lc4_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "lc5_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0200, - }, - { - .label = "lc6_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0200, - }, - { - .label = "lc7_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0200, - }, - { - .label = "lc8_rst_mask", - .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0200, - }, - { - .label = "psu1_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0200, - }, - { - .label = "psu2_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0200, - }, - { - .label = "pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "pwr_down", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "psu3_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0200, - }, - { - .label = "psu4_on", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0200, - }, - { - .label = "auto_power_mode", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "pm_mgmt_en", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, - { - .label = "jtag_enable", - .reg = MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE, - .mask = GENMASK(3, 0), - .bit = 1, - .mode = 0644, - }, - { - .label = "safe_bios_dis", - .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - }, - { - .label = "safe_bios_dis_wp", - .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - }, - { - .label = "asic_health", - .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, - .mask = MLXPLAT_CPLD_ASIC_MASK, - .bit = 1, - .mode = 0444, - }, - { - .label = "fan_dir", - .reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "lc1_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0644, - }, - { - .label = "lc2_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0644, - }, - { - .label = "lc3_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0644, - }, - { - .label = "lc4_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0644, - }, - { - .label = "lc5_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "lc6_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0644, - }, - { - .label = "lc7_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0644, - }, - { - .label = "lc8_pwr", - .reg = MLXPLAT_CPLD_LPC_REG_LC_PWR_ON, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0644, - }, - { - .label = "config1", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config2", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config3", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "ufm_version", - .reg = MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_modular_regs_io_data = { - .data = mlxplat_mlxcpld_modular_regs_io_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_modular_regs_io_data), -}; - -/* Platform register access for chassis blade systems family data */ -static struct mlxreg_core_data mlxplat_mlxcpld_chassis_blade_regs_io_data[] = { - { - .label = "cpld1_version", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "cpld1_pn", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, - .bit = GENMASK(15, 0), - .mode = 0444, - .regnum = 2, - }, - { - .label = "cpld1_version_min", - .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "reset_aux_pwr_or_ref", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_from_comex", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_comex_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_platform", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "reset_soc", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_comex_wd", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_voltmon_upgrade_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "reset_system", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(1), - .mode = 0444, - }, - { - .label = "reset_sw_pwr_off", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0444, - }, - { - .label = "reset_comex_thermal", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0444, - }, - { - .label = "reset_reload_bios", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "reset_ac_pwr_fail", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "reset_long_pwr_pb", - .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "pwr_cycle", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(2), - .mode = 0200, - }, - { - .label = "pwr_down", - .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0200, - }, - { - .label = "global_wp_request", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0644, - }, - { - .label = "jtag_enable", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "comm_chnl_ready", - .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0200, - }, - { - .label = "bios_safe_mode", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0444, - }, - { - .label = "bios_active_image", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(5), - .mode = 0444, - }, - { - .label = "bios_auth_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .mode = 0444, - }, - { - .label = "bios_upgrade_fail", - .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(7), - .mode = 0444, - }, - { - .label = "voltreg_update_status", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET, - .mask = MLXPLAT_CPLD_VOLTREG_UPD_MASK, - .bit = 5, - .mode = 0444, - }, - { - .label = "vpd_wp", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(3), - .mode = 0644, - }, - { - .label = "pcie_asic_reset_dis", - .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(4), - .mode = 0644, - }, - { - .label = "global_wp_response", - .reg = MLXPLAT_CPLD_LPC_REG_GWP_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(0), - .mode = 0444, - }, - { - .label = "config1", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config2", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "config3", - .reg = MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, - { - .label = "ufm_version", - .reg = MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET, - .bit = GENMASK(7, 0), - .mode = 0444, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_chassis_blade_regs_io_data = { - .data = mlxplat_mlxcpld_chassis_blade_regs_io_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_chassis_blade_regs_io_data), -}; - -/* Platform FAN default */ -static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { - { - .label = "pwm1", - .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, - }, - { - .label = "pwm2", - .reg = MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET, - }, - { - .label = "pwm3", - .reg = MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET, - }, - { - .label = "pwm4", - .reg = MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET, - }, - { - .label = "tacho1", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(0), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - - }, - { - .label = "tacho2", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(1), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho3", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(2), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho4", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(3), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho5", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(4), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho6", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(5), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho7", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(6), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho8", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, - .bit = BIT(7), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho9", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(0), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho10", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(1), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho11", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(2), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho12", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(3), - .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, - }, - { - .label = "tacho13", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO13_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(4), - }, - { - .label = "tacho14", - .reg = MLXPLAT_CPLD_LPC_REG_TACHO14_OFFSET, - .mask = GENMASK(7, 0), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, - .bit = BIT(5), - }, - { - .label = "conf", - .capability = MLXPLAT_CPLD_LPC_REG_TACHO_SPEED_OFFSET, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_default_fan_data = { - .data = mlxplat_mlxcpld_default_fan_data, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data), - .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, -}; - -/* Watchdog type1: hardware implementation version1 - * (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140 systems). - */ -static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type1[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK, - .bit = 0, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET, - .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK, - .bit = 0, - }, - { - .label = "reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .bit = 6, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type1[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK, - .bit = 4, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET, - .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK, - .bit = 1, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type1[] = { - { - .data = mlxplat_mlxcpld_wd_main_regs_type1, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type1), - .version = MLX_WDT_TYPE1, - .identity = "mlx-wdt-main", - }, - { - .data = mlxplat_mlxcpld_wd_aux_regs_type1, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type1), - .version = MLX_WDT_TYPE1, - .identity = "mlx-wdt-aux", - }, -}; - -/* Watchdog type2: hardware implementation version 2 - * (all systems except (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140). - */ -static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type2[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK, - .bit = 0, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT, - }, - { - .label = "timeleft", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK, - .bit = 0, - }, - { - .label = "reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .bit = 6, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type2[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK, - .bit = 4, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT, - }, - { - .label = "timeleft", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK, - .bit = 4, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type2[] = { - { - .data = mlxplat_mlxcpld_wd_main_regs_type2, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type2), - .version = MLX_WDT_TYPE2, - .identity = "mlx-wdt-main", - }, - { - .data = mlxplat_mlxcpld_wd_aux_regs_type2, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type2), - .version = MLX_WDT_TYPE2, - .identity = "mlx-wdt-aux", - }, -}; - -/* Watchdog type3: hardware implementation version 3 - * Can be on all systems. It's differentiated by WD capability bit. - * Old systems (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140) - * still have only one main watchdog. - */ -static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type3[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK, - .bit = 0, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD3_DFLT_TIMEOUT, - }, - { - .label = "timeleft", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK, - .bit = 0, - }, - { - .label = "reset", - .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, - .mask = GENMASK(7, 0) & ~BIT(6), - .bit = 6, - }, -}; - -static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type3[] = { - { - .label = "action", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK, - .bit = 4, - }, - { - .label = "timeout", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - .health_cntr = MLXPLAT_CPLD_WD3_DFLT_TIMEOUT, - }, - { - .label = "timeleft", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET, - .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK, - }, - { - .label = "ping", - .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, - .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK, - .bit = 4, - }, -}; - -static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type3[] = { - { - .data = mlxplat_mlxcpld_wd_main_regs_type3, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type3), - .version = MLX_WDT_TYPE3, - .identity = "mlx-wdt-main", - }, - { - .data = mlxplat_mlxcpld_wd_aux_regs_type3, - .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type3), - .version = MLX_WDT_TYPE3, - .identity = "mlx-wdt-aux", - }, -}; - -static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED6_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED7_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: - case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: - return true; - } - return false; -} - -static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED6_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED7_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: - case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: - case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO13_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO14_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO_SPEED_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET: - return true; - } - return false; -} - -static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_VER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_PN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_PN1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED6_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LED7_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: - case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: - case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_HEALTH_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_ASIC2_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET: - case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PG_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_RD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_OK_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SN_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET: - case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON: - case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET: - case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT: - case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET: - case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET: - case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_I2C_CH4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD4_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CPLD5_MVER_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO13_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO14_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_TACHO_SPEED_OFFSET: - case MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET: - case MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET: - case MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET: - case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET: - return true; - } - return false; -} - -static const struct reg_default mlxplat_mlxcpld_regmap_default[] = { - { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET, 0x00 }, -}; - -static const struct reg_default mlxplat_mlxcpld_regmap_ng[] = { - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET, 0x00 }, -}; - -static const struct reg_default mlxplat_mlxcpld_regmap_comex_default[] = { - { MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET, - MLXPLAT_CPLD_LOW_AGGRCX_MASK }, - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, -}; - -static const struct reg_default mlxplat_mlxcpld_regmap_ng400[] = { - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, -}; - -static const struct reg_default mlxplat_mlxcpld_regmap_rack_switch[] = { - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT }, - { MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, -}; - -static const struct reg_default mlxplat_mlxcpld_regmap_eth_modular[] = { - { MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 0x61 }, - { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 }, - { MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET, - MLXPLAT_CPLD_AGGR_MASK_LC_LOW }, -}; - -struct mlxplat_mlxcpld_regmap_context { - void __iomem *base; -}; - -static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx; - -static int -mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val) -{ - struct mlxplat_mlxcpld_regmap_context *ctx = context; - - *val = ioread8(ctx->base + reg); - return 0; -} - -static int -mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val) -{ - struct mlxplat_mlxcpld_regmap_context *ctx = context; - - iowrite8(val, ctx->base + reg); - return 0; -} - -static const struct regmap_config mlxplat_mlxcpld_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_default, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_ng, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_ng), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static const struct regmap_config mlxplat_mlxcpld_regmap_config_comex = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_comex_default, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_comex_default), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng400 = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_ng400, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_ng400), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static const struct regmap_config mlxplat_mlxcpld_regmap_config_rack_switch = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_rack_switch, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_rack_switch), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = { - .reg_bits = 8, - .val_bits = 8, - .max_register = 255, - .cache_type = REGCACHE_FLAT, - .writeable_reg = mlxplat_mlxcpld_writeable_reg, - .readable_reg = mlxplat_mlxcpld_readable_reg, - .volatile_reg = mlxplat_mlxcpld_volatile_reg, - .reg_defaults = mlxplat_mlxcpld_regmap_eth_modular, - .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_eth_modular), - .reg_read = mlxplat_mlxcpld_reg_read, - .reg_write = mlxplat_mlxcpld_reg_write, -}; - -static struct resource mlxplat_mlxcpld_resources[] = { - [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"), -}; - -static struct mlxreg_core_hotplug_platform_data *mlxplat_i2c; -static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; -static struct mlxreg_core_platform_data *mlxplat_led; -static struct mlxreg_core_platform_data *mlxplat_regs_io; -static struct mlxreg_core_platform_data *mlxplat_fan; -static struct mlxreg_core_platform_data - *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; -static const struct regmap_config *mlxplat_regmap_config; -static struct pci_dev *lpc_bridge; -static struct pci_dev *i2c_bridge; -static struct pci_dev *jtag_bridge; - -/* Platform default reset function */ -static int mlxplat_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) -{ - struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); - u32 regval; - int ret; - - ret = regmap_read(priv->regmap, MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET, ®val); - - if (action == SYS_RESTART && !ret && regval & MLXPLAT_CPLD_SYS_RESET_MASK) - regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET, - MLXPLAT_CPLD_RESET_MASK); - - return NOTIFY_DONE; -} - -static struct notifier_block mlxplat_reboot_default_nb = { - .notifier_call = mlxplat_reboot_notifier, -}; - -/* Platform default poweroff function */ -static void mlxplat_poweroff(void) -{ - struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); - - if (mlxplat_reboot_nb) - unregister_reboot_notifier(mlxplat_reboot_nb); - regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, MLXPLAT_CPLD_HALT_MASK); - kernel_halt(); -} - -static int __init mlxplat_register_platform_device(void) -{ - mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1, - mlxplat_lpc_resources, - ARRAY_SIZE(mlxplat_lpc_resources)); - if (IS_ERR(mlxplat_dev)) - return PTR_ERR(mlxplat_dev); - else - return 1; -} - -static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_default_channels[i]; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_default_channels[i]); - } - mlxplat_hotplug = &mlxplat_mlxcpld_default_data; - mlxplat_hotplug->deferred_nr = - mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_led_data; - mlxplat_regs_io = &mlxplat_default_regs_io_data; - mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_default_wc_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_default_channels[i]; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_default_channels[i]); - } - mlxplat_hotplug = &mlxplat_mlxcpld_default_wc_data; - mlxplat_hotplug->deferred_nr = - mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_led_wc_data; - mlxplat_regs_io = &mlxplat_default_regs_io_data; - mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_default_eth_wc_blade_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_default_wc_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_led_eth_wc_blade_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_msn21xx_led_data; - mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; - mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_led_data; - mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; - mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; - mlxplat_hotplug->deferred_nr = - mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_msn21xx_led_data; - mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; - mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_ng_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_comex_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_EXT_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_extended_mux_data); - mlxplat_mux_data = mlxplat_extended_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_comex_data; - mlxplat_hotplug->deferred_nr = MLXPLAT_CPLD_MAX_PHYS_EXT_ADAPTER_NUM; - mlxplat_led = &mlxplat_comex_100G_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_default_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_comex; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_ng400_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_hotplug = &mlxplat_mlxcpld_ext_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_ng_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng400; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_modular_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_modular_mux_data); - mlxplat_mux_data = mlxplat_modular_mux_data; - mlxplat_hotplug = &mlxplat_mlxcpld_modular_data; - mlxplat_hotplug->deferred_nr = MLXPLAT_CPLD_CH4_ETH_MODULAR; - mlxplat_led = &mlxplat_modular_led_data; - mlxplat_regs_io = &mlxplat_modular_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_eth_modular; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_chassis_blade_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_mux_data); - mlxplat_mux_data = mlxplat_default_mux_data; - mlxplat_hotplug = &mlxplat_mlxcpld_chassis_blade_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - for (i = 0; i < mlxplat_mux_num; i++) { - mlxplat_mux_data[i].values = mlxplat_msn21xx_channels; - mlxplat_mux_data[i].n_values = - ARRAY_SIZE(mlxplat_msn21xx_channels); - } - mlxplat_regs_io = &mlxplat_chassis_blade_regs_io_data; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng400; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data); - mlxplat_mux_data = mlxplat_rack_switch_mux_data; - mlxplat_hotplug = &mlxplat_mlxcpld_rack_switch_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_ng_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_ng800_mux_data); - mlxplat_mux_data = mlxplat_ng800_mux_data; - mlxplat_hotplug = &mlxplat_mlxcpld_ng800_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_ng_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng400; - - return mlxplat_register_platform_device(); -} - -static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) -{ - int i; - - mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; - mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data); - mlxplat_mux_data = mlxplat_rack_switch_mux_data; - mlxplat_hotplug = &mlxplat_mlxcpld_l1_switch_data; - mlxplat_hotplug->deferred_nr = - mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_l1_switch_led_data; - mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; - mlxplat_fan = &mlxplat_default_fan_data; - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; - pm_power_off = mlxplat_poweroff; - mlxplat_reboot_nb = &mlxplat_reboot_default_nb; - - return mlxplat_register_platform_device(); -} - -static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { - { - .callback = mlxplat_dmi_default_wc_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI138"), - }, - }, - { - .callback = mlxplat_dmi_default_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"), - }, - }, - { - .callback = mlxplat_dmi_msn21xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"), - }, - }, - { - .callback = mlxplat_dmi_msn274x_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"), - }, - }, - { - .callback = mlxplat_dmi_msn201x_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"), - }, - }, - { - .callback = mlxplat_dmi_default_eth_wc_blade_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI139"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0007"), - }, - }, - { - .callback = mlxplat_dmi_comex_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0009"), - }, - }, - { - .callback = mlxplat_dmi_rack_switch_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI142"), - }, - }, - { - .callback = mlxplat_dmi_ng400_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"), - }, - }, - { - .callback = mlxplat_dmi_modular_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0011"), - }, - }, - { - .callback = mlxplat_dmi_ng800_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0013"), - }, - }, - { - .callback = mlxplat_dmi_chassis_blade_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0015"), - }, - }, - { - .callback = mlxplat_dmi_l1_switch_matched, - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "VMOD0017"), - }, - }, - { - .callback = mlxplat_dmi_msn274x_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN274"), - }, - }, - { - .callback = mlxplat_dmi_default_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"), - }, - }, - { - .callback = mlxplat_dmi_default_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"), - }, - }, - { - .callback = mlxplat_dmi_default_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSB"), - }, - }, - { - .callback = mlxplat_dmi_default_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSX"), - }, - }, - { - .callback = mlxplat_dmi_msn21xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"), - }, - }, - { - .callback = mlxplat_dmi_msn201x_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN201"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"), - }, - }, - { - .callback = mlxplat_dmi_qmb7xx_matched, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"), - }, - }, - { } -}; - -MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table); - -static int mlxplat_mlxcpld_verify_bus_topology(int *nr) -{ - struct i2c_adapter *search_adap; - int i, shift = 0; - - /* Scan adapters from expected id to verify it is free. */ - *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; - for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i < - mlxplat_max_adap_num; i++) { - search_adap = i2c_get_adapter(i); - if (search_adap) { - i2c_put_adapter(search_adap); - continue; - } - - /* Return if expected parent adapter is free. */ - if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR) - return 0; - break; - } - - /* Return with error if free id for adapter is not found. */ - if (i == mlxplat_max_adap_num) - return -ENODEV; - - /* Shift adapter ids, since expected parent adapter is not free. */ - *nr = i; - for (i = 0; i < mlxplat_mux_num; i++) { - shift = *nr - mlxplat_mux_data[i].parent; - mlxplat_mux_data[i].parent = *nr; - mlxplat_mux_data[i].base_nr += shift; - } - - if (shift > 0) - mlxplat_hotplug->shift_nr = shift; - - return 0; -} - -static int mlxplat_mlxcpld_check_wd_capability(void *regmap) -{ - u32 regval; - int i, rc; - - rc = regmap_read(regmap, MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, - ®val); - if (rc) - return rc; - - if (!(regval & ~MLXPLAT_CPLD_WD_CPBLTY_MASK)) { - for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type3); i++) { - if (mlxplat_wd_data[i]) - mlxplat_wd_data[i] = - &mlxplat_mlxcpld_wd_set_type3[i]; - } - } - - return 0; -} - -static int mlxplat_lpc_cpld_device_init(struct resource **hotplug_resources, - unsigned int *hotplug_resources_size) -{ - int err; - - mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, - mlxplat_lpc_resources[1].start, 1); - if (!mlxplat_mlxcpld_regmap_ctx.base) { - err = -ENOMEM; - goto fail_devm_ioport_map; - } - - *hotplug_resources = mlxplat_mlxcpld_resources; - *hotplug_resources_size = ARRAY_SIZE(mlxplat_mlxcpld_resources); - - return 0; - -fail_devm_ioport_map: - return err; -} - -static void mlxplat_lpc_cpld_device_exit(void) -{ -} - -static int -mlxplat_pci_fpga_device_init(unsigned int device, const char *res_name, struct pci_dev **pci_bridge, - void __iomem **pci_bridge_addr) -{ - void __iomem *pci_mem_addr; - struct pci_dev *pci_dev; - int err; - - pci_dev = pci_get_device(PCI_VENDOR_ID_LATTICE, device, NULL); - if (!pci_dev) - return -ENODEV; - - err = pci_enable_device(pci_dev); - if (err) { - dev_err(&pci_dev->dev, "pci_enable_device failed with error %d\n", err); - goto fail_pci_enable_device; - } - - err = pci_request_region(pci_dev, 0, res_name); - if (err) { - dev_err(&pci_dev->dev, "pci_request_regions failed with error %d\n", err); - goto fail_pci_request_regions; - } - - err = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); - if (err) { - err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32)); - if (err) { - dev_err(&pci_dev->dev, "dma_set_mask failed with error %d\n", err); - goto fail_pci_set_dma_mask; - } - } - - pci_set_master(pci_dev); - - pci_mem_addr = devm_ioremap(&pci_dev->dev, pci_resource_start(pci_dev, 0), - pci_resource_len(pci_dev, 0)); - if (!pci_mem_addr) { - dev_err(&mlxplat_dev->dev, "ioremap failed\n"); - err = -EIO; - goto fail_ioremap; - } - - *pci_bridge = pci_dev; - *pci_bridge_addr = pci_mem_addr; - - return 0; - -fail_ioremap: -fail_pci_set_dma_mask: - pci_release_regions(pci_dev); -fail_pci_request_regions: - pci_disable_device(pci_dev); -fail_pci_enable_device: - pci_dev_put(pci_dev); - return err; -} - -static void -mlxplat_pci_fpga_device_exit(struct pci_dev *pci_bridge, - void __iomem *pci_bridge_addr) -{ - iounmap(pci_bridge_addr); - pci_release_regions(pci_bridge); - pci_disable_device(pci_bridge); - pci_dev_put(pci_bridge); -} - -static int -mlxplat_pci_fpga_devices_init(struct resource **hotplug_resources, - unsigned int *hotplug_resources_size) -{ - int err; - - err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_LPC_BRIDGE, - "mlxplat_lpc_bridge", &lpc_bridge, - &mlxplat_mlxcpld_regmap_ctx.base); - if (err) - goto mlxplat_pci_fpga_device_init_lpc_fail; - - err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_I2C_BRIDGE, - "mlxplat_i2c_bridge", &i2c_bridge, - &i2c_bridge_addr); - if (err) - goto mlxplat_pci_fpga_device_init_i2c_fail; - - err = mlxplat_pci_fpga_device_init(PCI_DEVICE_ID_LATTICE_JTAG_BRIDGE, - "mlxplat_jtag_bridge", &jtag_bridge, - &jtag_bridge_addr); - if (err) - goto mlxplat_pci_fpga_device_init_jtag_fail; - - return 0; - -mlxplat_pci_fpga_device_init_jtag_fail: - mlxplat_pci_fpga_device_exit(i2c_bridge, i2c_bridge_addr); -mlxplat_pci_fpga_device_init_i2c_fail: - mlxplat_pci_fpga_device_exit(lpc_bridge, mlxplat_mlxcpld_regmap_ctx.base); -mlxplat_pci_fpga_device_init_lpc_fail: - return err; -} - -static void mlxplat_pci_fpga_devices_exit(void) -{ - mlxplat_pci_fpga_device_exit(jtag_bridge, jtag_bridge_addr); - mlxplat_pci_fpga_device_exit(i2c_bridge, i2c_bridge_addr); - mlxplat_pci_fpga_device_exit(lpc_bridge, mlxplat_mlxcpld_regmap_ctx.base); -} - -static int -mlxplat_logicdev_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size) -{ - int err; - - err = mlxplat_pci_fpga_devices_init(hotplug_resources, hotplug_resources_size); - if (err == -ENODEV) - return mlxplat_lpc_cpld_device_init(hotplug_resources, hotplug_resources_size); - - return err; -} - -static void mlxplat_logicdev_exit(void) -{ - if (lpc_bridge) - mlxplat_pci_fpga_devices_exit(); - else - mlxplat_lpc_cpld_device_exit(); -} - -static int mlxplat_platdevs_init(struct mlxplat_priv *priv) -{ - int i = 0, err; - - /* Add hotplug driver */ - if (mlxplat_hotplug) { - mlxplat_hotplug->regmap = priv->regmap; - if (priv->irq_fpga) - mlxplat_hotplug->irq = priv->irq_fpga; - priv->pdev_hotplug = - platform_device_register_resndata(&mlxplat_dev->dev, - "mlxreg-hotplug", PLATFORM_DEVID_NONE, - priv->hotplug_resources, - priv->hotplug_resources_size, - mlxplat_hotplug, sizeof(*mlxplat_hotplug)); - if (IS_ERR(priv->pdev_hotplug)) { - err = PTR_ERR(priv->pdev_hotplug); - goto fail_platform_hotplug_register; - } - } - - /* Add LED driver. */ - if (mlxplat_led) { - mlxplat_led->regmap = priv->regmap; - priv->pdev_led = - platform_device_register_resndata(&mlxplat_dev->dev, "leds-mlxreg", - PLATFORM_DEVID_NONE, NULL, 0, mlxplat_led, - sizeof(*mlxplat_led)); - if (IS_ERR(priv->pdev_led)) { - err = PTR_ERR(priv->pdev_led); - goto fail_platform_leds_register; - } - } - - /* Add registers io access driver. */ - if (mlxplat_regs_io) { - mlxplat_regs_io->regmap = priv->regmap; - priv->pdev_io_regs = platform_device_register_resndata(&mlxplat_dev->dev, - "mlxreg-io", - PLATFORM_DEVID_NONE, NULL, - 0, mlxplat_regs_io, - sizeof(*mlxplat_regs_io)); - if (IS_ERR(priv->pdev_io_regs)) { - err = PTR_ERR(priv->pdev_io_regs); - goto fail_platform_io_register; - } - } - - /* Add FAN driver. */ - if (mlxplat_fan) { - mlxplat_fan->regmap = priv->regmap; - priv->pdev_fan = platform_device_register_resndata(&mlxplat_dev->dev, "mlxreg-fan", - PLATFORM_DEVID_NONE, NULL, 0, - mlxplat_fan, - sizeof(*mlxplat_fan)); - if (IS_ERR(priv->pdev_fan)) { - err = PTR_ERR(priv->pdev_fan); - goto fail_platform_fan_register; - } - } - - /* Add WD drivers. */ - err = mlxplat_mlxcpld_check_wd_capability(priv->regmap); - if (err) - goto fail_platform_wd_register; - for (i = 0; i < MLXPLAT_CPLD_WD_MAX_DEVS; i++) { - if (mlxplat_wd_data[i]) { - mlxplat_wd_data[i]->regmap = priv->regmap; - priv->pdev_wd[i] = - platform_device_register_resndata(&mlxplat_dev->dev, "mlx-wdt", i, - NULL, 0, mlxplat_wd_data[i], - sizeof(*mlxplat_wd_data[i])); - if (IS_ERR(priv->pdev_wd[i])) { - err = PTR_ERR(priv->pdev_wd[i]); - goto fail_platform_wd_register; - } - } - } - - return 0; - -fail_platform_wd_register: - while (--i >= 0) - platform_device_unregister(priv->pdev_wd[i]); -fail_platform_fan_register: - if (mlxplat_regs_io) - platform_device_unregister(priv->pdev_io_regs); -fail_platform_io_register: - if (mlxplat_led) - platform_device_unregister(priv->pdev_led); -fail_platform_leds_register: - if (mlxplat_hotplug) - platform_device_unregister(priv->pdev_hotplug); -fail_platform_hotplug_register: - return err; -} - -static void mlxplat_platdevs_exit(struct mlxplat_priv *priv) -{ - int i; - - for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) - platform_device_unregister(priv->pdev_wd[i]); - if (priv->pdev_fan) - platform_device_unregister(priv->pdev_fan); - if (priv->pdev_io_regs) - platform_device_unregister(priv->pdev_io_regs); - if (priv->pdev_led) - platform_device_unregister(priv->pdev_led); - if (priv->pdev_hotplug) - platform_device_unregister(priv->pdev_hotplug); -} - -static int -mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent, - struct i2c_adapter *adapters[]) -{ - struct mlxplat_priv *priv = handle; - - return mlxplat_platdevs_init(priv); -} - -static int mlxplat_i2c_mux_topology_init(struct mlxplat_priv *priv) -{ - int i, err; - - if (!priv->pdev_i2c) { - priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_NOTIFIED; - return 0; - } - - priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED; - for (i = 0; i < mlxplat_mux_num; i++) { - priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev, - "i2c-mux-reg", i, NULL, 0, - &mlxplat_mux_data[i], - sizeof(mlxplat_mux_data[i])); - if (IS_ERR(priv->pdev_mux[i])) { - err = PTR_ERR(priv->pdev_mux[i]); - goto fail_platform_mux_register; - } - } - - return mlxplat_i2c_mux_complition_notify(priv, NULL, NULL); - -fail_platform_mux_register: - while (--i >= 0) - platform_device_unregister(priv->pdev_mux[i]); - return err; -} - -static void mlxplat_i2c_mux_topology_exit(struct mlxplat_priv *priv) -{ - int i; - - for (i = mlxplat_mux_num - 1; i >= 0 ; i--) { - if (priv->pdev_mux[i]) - platform_device_unregister(priv->pdev_mux[i]); - } -} - -static int mlxplat_i2c_main_completion_notify(void *handle, int id) -{ - struct mlxplat_priv *priv = handle; - - return mlxplat_i2c_mux_topology_init(priv); -} - -static int mlxplat_i2c_main_init(struct mlxplat_priv *priv) -{ - int nr, err; - - if (!mlxplat_i2c) - return 0; - - err = mlxplat_mlxcpld_verify_bus_topology(&nr); - if (nr < 0) - goto fail_mlxplat_mlxcpld_verify_bus_topology; - - nr = (nr == mlxplat_max_adap_num) ? -1 : nr; - mlxplat_i2c->regmap = priv->regmap; - mlxplat_i2c->handle = priv; - - /* Set mapped base address of I2C-LPC bridge over PCIe */ - if (lpc_bridge) - mlxplat_i2c->addr = i2c_bridge_addr; - priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld", - nr, priv->hotplug_resources, - priv->hotplug_resources_size, - mlxplat_i2c, sizeof(*mlxplat_i2c)); - if (IS_ERR(priv->pdev_i2c)) { - err = PTR_ERR(priv->pdev_i2c); - goto fail_platform_i2c_register; - } - - if (priv->i2c_main_init_status == MLXPLAT_I2C_MAIN_BUS_NOTIFIED) { - err = mlxplat_i2c_mux_topology_init(priv); - if (err) - goto fail_mlxplat_i2c_mux_topology_init; - } - - return 0; - -fail_mlxplat_i2c_mux_topology_init: - platform_device_unregister(priv->pdev_i2c); -fail_platform_i2c_register: -fail_mlxplat_mlxcpld_verify_bus_topology: - return err; -} - -static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv) -{ - mlxplat_platdevs_exit(priv); - mlxplat_i2c_mux_topology_exit(priv); - if (priv->pdev_i2c) - platform_device_unregister(priv->pdev_i2c); -} - -static int mlxplat_probe(struct platform_device *pdev) -{ - unsigned int hotplug_resources_size = 0; - struct resource *hotplug_resources = NULL; - struct acpi_device *acpi_dev; - struct mlxplat_priv *priv; - int irq_fpga = 0, i, err; - - acpi_dev = ACPI_COMPANION(&pdev->dev); - if (acpi_dev) { - irq_fpga = acpi_dev_gpio_irq_get(acpi_dev, 0); - if (irq_fpga < 0) - return -ENODEV; - mlxplat_dev = pdev; - } - - err = mlxplat_logicdev_init(&hotplug_resources, &hotplug_resources_size); - if (err) - return err; - - priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv), - GFP_KERNEL); - if (!priv) { - err = -ENOMEM; - goto fail_alloc; - } - platform_set_drvdata(mlxplat_dev, priv); - priv->hotplug_resources = hotplug_resources; - priv->hotplug_resources_size = hotplug_resources_size; - priv->irq_fpga = irq_fpga; - - if (!mlxplat_regmap_config) - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config; - - priv->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, - &mlxplat_mlxcpld_regmap_ctx, - mlxplat_regmap_config); - if (IS_ERR(priv->regmap)) { - err = PTR_ERR(priv->regmap); - goto fail_alloc; - } - - /* Set default registers. */ - for (i = 0; i < mlxplat_regmap_config->num_reg_defaults; i++) { - err = regmap_write(priv->regmap, - mlxplat_regmap_config->reg_defaults[i].reg, - mlxplat_regmap_config->reg_defaults[i].def); - if (err) - goto fail_regmap_write; - } - - err = mlxplat_i2c_main_init(priv); - if (err) - goto fail_mlxplat_i2c_main_init; - - /* Sync registers with hardware. */ - regcache_mark_dirty(priv->regmap); - err = regcache_sync(priv->regmap); - if (err) - goto fail_regcache_sync; - - if (mlxplat_reboot_nb) { - err = register_reboot_notifier(mlxplat_reboot_nb); - if (err) - goto fail_register_reboot_notifier; - } - - return 0; - -fail_register_reboot_notifier: -fail_regcache_sync: - mlxplat_i2c_main_exit(priv); -fail_mlxplat_i2c_main_init: -fail_regmap_write: -fail_alloc: - mlxplat_logicdev_exit(); - - return err; -} - -static void mlxplat_remove(struct platform_device *pdev) -{ - struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); - - if (pm_power_off) - pm_power_off = NULL; - if (mlxplat_reboot_nb) - unregister_reboot_notifier(mlxplat_reboot_nb); - mlxplat_i2c_main_exit(priv); - mlxplat_logicdev_exit(); -} - -static const struct acpi_device_id mlxplat_acpi_table[] = { - { "MLNXBF49", 0 }, - {} -}; -MODULE_DEVICE_TABLE(acpi, mlxplat_acpi_table); - -static struct platform_driver mlxplat_driver = { - .driver = { - .name = "mlxplat", - .acpi_match_table = mlxplat_acpi_table, - .probe_type = PROBE_FORCE_SYNCHRONOUS, - }, - .probe = mlxplat_probe, - .remove = mlxplat_remove, -}; - -static int __init mlxplat_init(void) -{ - int err; - - if (!dmi_check_system(mlxplat_dmi_table)) - return -ENODEV; - - err = platform_driver_register(&mlxplat_driver); - if (err) - return err; - return 0; -} -module_init(mlxplat_init); - -static void __exit mlxplat_exit(void) -{ - if (mlxplat_dev) - platform_device_unregister(mlxplat_dev); - - platform_driver_unregister(&mlxplat_driver); -} -module_exit(mlxplat_exit); - -MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>"); -MODULE_DESCRIPTION("Mellanox platform driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/platform/x86/samsung-galaxybook.c b/drivers/platform/x86/samsung-galaxybook.c new file mode 100644 index 000000000000..5878a351993e --- /dev/null +++ b/drivers/platform/x86/samsung-galaxybook.c @@ -0,0 +1,1425 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Samsung Galaxy Book driver + * + * Copyright (c) 2025 Joshua Grisham <josh@joshuagrisham.com> + * + * With contributions to the SCAI ACPI device interface: + * Copyright (c) 2024 Giulio Girardi <giulio.girardi@protechgroup.it> + * + * Implementation inspired by existing x86 platform drivers. + * Thank you to the authors! + */ + +#include <linux/acpi.h> +#include <linux/bits.h> +#include <linux/err.h> +#include <linux/i8042.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/platform_profile.h> +#include <linux/serio.h> +#include <linux/sysfs.h> +#include <linux/uuid.h> +#include <linux/workqueue.h> +#include <acpi/battery.h> +#include "firmware_attributes_class.h" + +#define DRIVER_NAME "samsung-galaxybook" + +struct samsung_galaxybook { + struct platform_device *platform; + struct acpi_device *acpi; + + struct device *fw_attrs_dev; + struct kset *fw_attrs_kset; + /* block in case firmware attributes are updated in multiple threads */ + struct mutex fw_attr_lock; + + bool has_kbd_backlight; + bool has_block_recording; + bool has_performance_mode; + + struct led_classdev kbd_backlight; + struct work_struct kbd_backlight_hotkey_work; + /* block in case brightness updated using hotkey and another thread */ + struct mutex kbd_backlight_lock; + + void *i8042_filter_ptr; + + struct work_struct block_recording_hotkey_work; + struct input_dev *camera_lens_cover_switch; + + struct acpi_battery_hook battery_hook; + + u8 profile_performance_modes[PLATFORM_PROFILE_LAST]; +}; + +enum galaxybook_fw_attr_id { + GB_ATTR_POWER_ON_LID_OPEN, + GB_ATTR_USB_CHARGING, + GB_ATTR_BLOCK_RECORDING, +}; + +static const char * const galaxybook_fw_attr_name[] = { + [GB_ATTR_POWER_ON_LID_OPEN] = "power_on_lid_open", + [GB_ATTR_USB_CHARGING] = "usb_charging", + [GB_ATTR_BLOCK_RECORDING] = "block_recording", +}; + +static const char * const galaxybook_fw_attr_desc[] = { + [GB_ATTR_POWER_ON_LID_OPEN] = "Power On Lid Open", + [GB_ATTR_USB_CHARGING] = "USB Charging", + [GB_ATTR_BLOCK_RECORDING] = "Block Recording", +}; + +#define GB_ATTR_LANGUAGE_CODE "en_US.UTF-8" + +struct galaxybook_fw_attr { + struct samsung_galaxybook *galaxybook; + enum galaxybook_fw_attr_id fw_attr_id; + struct attribute_group attr_group; + struct kobj_attribute display_name; + struct kobj_attribute current_value; + int (*get_value)(struct samsung_galaxybook *galaxybook, bool *value); + int (*set_value)(struct samsung_galaxybook *galaxybook, const bool value); +}; + +struct sawb { + u16 safn; + u16 sasb; + u8 rflg; + union { + struct { + u8 gunm; + u8 guds[250]; + } __packed; + struct { + u8 caid[16]; + u8 fncn; + u8 subn; + u8 iob0; + u8 iob1; + u8 iob2; + u8 iob3; + u8 iob4; + u8 iob5; + u8 iob6; + u8 iob7; + u8 iob8; + u8 iob9; + } __packed; + struct { + u8 iob_prefix[18]; + u8 iobs[10]; + } __packed; + } __packed; +} __packed; + +#define GB_SAWB_LEN_SETTINGS 0x15 +#define GB_SAWB_LEN_PERFORMANCE_MODE 0x100 + +#define GB_SAFN 0x5843 + +#define GB_SASB_KBD_BACKLIGHT 0x78 +#define GB_SASB_POWER_MANAGEMENT 0x7a +#define GB_SASB_USB_CHARGING_GET 0x67 +#define GB_SASB_USB_CHARGING_SET 0x68 +#define GB_SASB_NOTIFICATIONS 0x86 +#define GB_SASB_BLOCK_RECORDING 0x8a +#define GB_SASB_PERFORMANCE_MODE 0x91 + +#define GB_SAWB_RFLG_POS 4 +#define GB_SAWB_GB_GUNM_POS 5 + +#define GB_RFLG_SUCCESS 0xaa +#define GB_GUNM_FAIL 0xff + +#define GB_GUNM_FEATURE_ENABLE 0xbb +#define GB_GUNM_FEATURE_ENABLE_SUCCESS 0xdd +#define GB_GUDS_FEATURE_ENABLE 0xaa +#define GB_GUDS_FEATURE_ENABLE_SUCCESS 0xcc + +#define GB_GUNM_GET 0x81 +#define GB_GUNM_SET 0x82 + +#define GB_GUNM_POWER_MANAGEMENT 0x82 + +#define GB_GUNM_USB_CHARGING_GET 0x80 +#define GB_GUNM_USB_CHARGING_ON 0x81 +#define GB_GUNM_USB_CHARGING_OFF 0x80 +#define GB_GUDS_POWER_ON_LID_OPEN 0xa3 +#define GB_GUDS_POWER_ON_LID_OPEN_GET 0x81 +#define GB_GUDS_POWER_ON_LID_OPEN_SET 0x80 +#define GB_GUDS_BATTERY_CHARGE_CONTROL 0xe9 +#define GB_GUDS_BATTERY_CHARGE_CONTROL_GET 0x91 +#define GB_GUDS_BATTERY_CHARGE_CONTROL_SET 0x90 +#define GB_GUNM_ACPI_NOTIFY_ENABLE 0x80 +#define GB_GUDS_ACPI_NOTIFY_ENABLE 0x02 + +#define GB_BLOCK_RECORDING_ON 0x0 +#define GB_BLOCK_RECORDING_OFF 0x1 + +#define GB_FNCN_PERFORMANCE_MODE 0x51 +#define GB_SUBN_PERFORMANCE_MODE_LIST 0x01 +#define GB_SUBN_PERFORMANCE_MODE_GET 0x02 +#define GB_SUBN_PERFORMANCE_MODE_SET 0x03 + +/* guid 8246028d-8bca-4a55-ba0f-6f1e6b921b8f */ +static const guid_t performance_mode_guid = + GUID_INIT(0x8246028d, 0x8bca, 0x4a55, 0xba, 0x0f, 0x6f, 0x1e, 0x6b, 0x92, 0x1b, 0x8f); +#define GB_PERFORMANCE_MODE_GUID performance_mode_guid + +#define GB_PERFORMANCE_MODE_FANOFF 0xb +#define GB_PERFORMANCE_MODE_LOWNOISE 0xa +#define GB_PERFORMANCE_MODE_OPTIMIZED 0x0 +#define GB_PERFORMANCE_MODE_OPTIMIZED_V2 0x2 +#define GB_PERFORMANCE_MODE_PERFORMANCE 0x1 +#define GB_PERFORMANCE_MODE_PERFORMANCE_V2 0x15 +#define GB_PERFORMANCE_MODE_ULTRA 0x16 +#define GB_PERFORMANCE_MODE_IGNORE1 0x14 +#define GB_PERFORMANCE_MODE_IGNORE2 0xc + +#define GB_ACPI_METHOD_ENABLE "SDLS" +#define GB_ACPI_METHOD_ENABLE_ON 1 +#define GB_ACPI_METHOD_ENABLE_OFF 0 +#define GB_ACPI_METHOD_SETTINGS "CSFI" +#define GB_ACPI_METHOD_PERFORMANCE_MODE "CSXI" + +#define GB_KBD_BACKLIGHT_MAX_BRIGHTNESS 3 + +#define GB_ACPI_NOTIFY_BATTERY_STATE_CHANGED 0x61 +#define GB_ACPI_NOTIFY_DEVICE_ON_TABLE 0x6c +#define GB_ACPI_NOTIFY_DEVICE_OFF_TABLE 0x6d +#define GB_ACPI_NOTIFY_HOTKEY_PERFORMANCE_MODE 0x70 + +#define GB_KEY_KBD_BACKLIGHT_KEYDOWN 0x2c +#define GB_KEY_KBD_BACKLIGHT_KEYUP 0xac +#define GB_KEY_BLOCK_RECORDING_KEYDOWN 0x1f +#define GB_KEY_BLOCK_RECORDING_KEYUP 0x9f +#define GB_KEY_BATTERY_NOTIFY_KEYUP 0xf +#define GB_KEY_BATTERY_NOTIFY_KEYDOWN 0x8f + +/* + * Optional features which have been determined as not supported on a particular + * device will return GB_NOT_SUPPORTED from their init function. Positive + * EOPNOTSUPP is used as the underlying value instead of negative to + * differentiate this return code from valid upstream failures. + */ +#define GB_NOT_SUPPORTED EOPNOTSUPP /* Galaxy Book feature not supported */ + +/* + * ACPI method handling + */ + +static int galaxybook_acpi_method(struct samsung_galaxybook *galaxybook, acpi_string method, + struct sawb *buf, size_t len) +{ + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object in_obj, *out_obj; + struct acpi_object_list input; + acpi_status status; + int err; + + in_obj.type = ACPI_TYPE_BUFFER; + in_obj.buffer.length = len; + in_obj.buffer.pointer = (u8 *)buf; + + input.count = 1; + input.pointer = &in_obj; + + status = acpi_evaluate_object_typed(galaxybook->acpi->handle, method, &input, &output, + ACPI_TYPE_BUFFER); + + if (ACPI_FAILURE(status)) { + dev_err(&galaxybook->acpi->dev, "failed to execute method %s; got %s\n", + method, acpi_format_exception(status)); + return -EIO; + } + + out_obj = output.pointer; + + if (out_obj->buffer.length != len || out_obj->buffer.length < GB_SAWB_GB_GUNM_POS + 1) { + dev_err(&galaxybook->acpi->dev, + "failed to execute %s; response length mismatch\n", + method); + err = -EPROTO; + goto out_free; + } + if (out_obj->buffer.pointer[GB_SAWB_RFLG_POS] != GB_RFLG_SUCCESS) { + dev_err(&galaxybook->acpi->dev, + "failed to execute %s; device did not respond with success code 0x%x\n", + method, GB_RFLG_SUCCESS); + err = -ENXIO; + goto out_free; + } + if (out_obj->buffer.pointer[GB_SAWB_GB_GUNM_POS] == GB_GUNM_FAIL) { + dev_err(&galaxybook->acpi->dev, + "failed to execute %s; device responded with failure code 0x%x\n", + method, GB_GUNM_FAIL); + err = -ENXIO; + goto out_free; + } + + memcpy(buf, out_obj->buffer.pointer, len); + err = 0; + +out_free: + kfree(out_obj); + return err; +} + +static int galaxybook_enable_acpi_feature(struct samsung_galaxybook *galaxybook, const u16 sasb) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = sasb; + buf.gunm = GB_GUNM_FEATURE_ENABLE; + buf.guds[0] = GB_GUDS_FEATURE_ENABLE; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + if (buf.gunm != GB_GUNM_FEATURE_ENABLE_SUCCESS && + buf.guds[0] != GB_GUDS_FEATURE_ENABLE_SUCCESS) + return -ENODEV; + + return 0; +} + +/* + * Keyboard Backlight + */ + +static int kbd_backlight_acpi_get(struct samsung_galaxybook *galaxybook, + enum led_brightness *brightness) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_KBD_BACKLIGHT; + buf.gunm = GB_GUNM_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + *brightness = buf.gunm; + + return 0; +} + +static int kbd_backlight_acpi_set(struct samsung_galaxybook *galaxybook, + const enum led_brightness brightness) +{ + struct sawb buf = {}; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_KBD_BACKLIGHT; + buf.gunm = GB_GUNM_SET; + + buf.guds[0] = brightness; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); +} + +static enum led_brightness kbd_backlight_show(struct led_classdev *led) +{ + struct samsung_galaxybook *galaxybook = + container_of(led, struct samsung_galaxybook, kbd_backlight); + enum led_brightness brightness; + int err; + + err = kbd_backlight_acpi_get(galaxybook, &brightness); + if (err) + return err; + + return brightness; +} + +static int kbd_backlight_store(struct led_classdev *led, + const enum led_brightness brightness) +{ + struct samsung_galaxybook *galaxybook = + container_of_const(led, struct samsung_galaxybook, kbd_backlight); + + return kbd_backlight_acpi_set(galaxybook, brightness); +} + +static int galaxybook_kbd_backlight_init(struct samsung_galaxybook *galaxybook) +{ + struct led_init_data init_data = {}; + enum led_brightness brightness; + int err; + + err = devm_mutex_init(&galaxybook->platform->dev, &galaxybook->kbd_backlight_lock); + if (err) + return err; + + err = galaxybook_enable_acpi_feature(galaxybook, GB_SASB_KBD_BACKLIGHT); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to enable kbd_backlight feature, error %d\n", err); + return GB_NOT_SUPPORTED; + } + + err = kbd_backlight_acpi_get(galaxybook, &brightness); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to get initial kbd_backlight brightness, error %d\n", err); + return GB_NOT_SUPPORTED; + } + + init_data.devicename = DRIVER_NAME; + init_data.default_label = ":" LED_FUNCTION_KBD_BACKLIGHT; + init_data.devname_mandatory = true; + + galaxybook->kbd_backlight.brightness_get = kbd_backlight_show; + galaxybook->kbd_backlight.brightness_set_blocking = kbd_backlight_store; + galaxybook->kbd_backlight.flags = LED_BRIGHT_HW_CHANGED; + galaxybook->kbd_backlight.max_brightness = GB_KBD_BACKLIGHT_MAX_BRIGHTNESS; + + return devm_led_classdev_register_ext(&galaxybook->platform->dev, + &galaxybook->kbd_backlight, &init_data); +} + +/* + * Battery Extension (adds charge_control_end_threshold to the battery device) + */ + +static int charge_control_end_threshold_acpi_get(struct samsung_galaxybook *galaxybook, u8 *value) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_POWER_MANAGEMENT; + buf.gunm = GB_GUNM_POWER_MANAGEMENT; + buf.guds[0] = GB_GUDS_BATTERY_CHARGE_CONTROL; + buf.guds[1] = GB_GUDS_BATTERY_CHARGE_CONTROL_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + *value = buf.guds[1]; + + return 0; +} + +static int charge_control_end_threshold_acpi_set(struct samsung_galaxybook *galaxybook, u8 value) +{ + struct sawb buf = {}; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_POWER_MANAGEMENT; + buf.gunm = GB_GUNM_POWER_MANAGEMENT; + buf.guds[0] = GB_GUDS_BATTERY_CHARGE_CONTROL; + buf.guds[1] = GB_GUDS_BATTERY_CHARGE_CONTROL_SET; + buf.guds[2] = value; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); +} + +static int galaxybook_battery_ext_property_get(struct power_supply *psy, + const struct power_supply_ext *ext, + void *ext_data, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct samsung_galaxybook *galaxybook = ext_data; + int err; + + if (psp != POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD) + return -EINVAL; + + err = charge_control_end_threshold_acpi_get(galaxybook, (u8 *)&val->intval); + if (err) + return err; + + /* + * device stores "no end threshold" as 0 instead of 100; + * if device has 0, report 100 + */ + if (val->intval == 0) + val->intval = 100; + + return 0; +} + +static int galaxybook_battery_ext_property_set(struct power_supply *psy, + const struct power_supply_ext *ext, + void *ext_data, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct samsung_galaxybook *galaxybook = ext_data; + u8 value; + + if (psp != POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD) + return -EINVAL; + + value = val->intval; + + if (value < 1 || value > 100) + return -EINVAL; + + /* + * device stores "no end threshold" as 0 instead of 100; + * if setting to 100, send 0 + */ + if (value == 100) + value = 0; + + return charge_control_end_threshold_acpi_set(galaxybook, value); +} + +static int galaxybook_battery_ext_property_is_writeable(struct power_supply *psy, + const struct power_supply_ext *ext, + void *ext_data, + enum power_supply_property psp) +{ + if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD) + return true; + + return false; +} + +static const enum power_supply_property galaxybook_battery_properties[] = { + POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, +}; + +static const struct power_supply_ext galaxybook_battery_ext = { + .name = DRIVER_NAME, + .properties = galaxybook_battery_properties, + .num_properties = ARRAY_SIZE(galaxybook_battery_properties), + .get_property = galaxybook_battery_ext_property_get, + .set_property = galaxybook_battery_ext_property_set, + .property_is_writeable = galaxybook_battery_ext_property_is_writeable, +}; + +static int galaxybook_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook) +{ + struct samsung_galaxybook *galaxybook = + container_of(hook, struct samsung_galaxybook, battery_hook); + + return power_supply_register_extension(battery, &galaxybook_battery_ext, + &battery->dev, galaxybook); +} + +static int galaxybook_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook) +{ + power_supply_unregister_extension(battery, &galaxybook_battery_ext); + return 0; +} + +static int galaxybook_battery_threshold_init(struct samsung_galaxybook *galaxybook) +{ + u8 value; + int err; + + err = charge_control_end_threshold_acpi_get(galaxybook, &value); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to get initial battery charge end threshold, error %d\n", err); + return 0; + } + + galaxybook->battery_hook.add_battery = galaxybook_battery_add; + galaxybook->battery_hook.remove_battery = galaxybook_battery_remove; + galaxybook->battery_hook.name = "Samsung Galaxy Book Battery Extension"; + + return devm_battery_hook_register(&galaxybook->platform->dev, &galaxybook->battery_hook); +} + +/* + * Platform Profile / Performance mode + */ + +static int performance_mode_acpi_get(struct samsung_galaxybook *galaxybook, u8 *performance_mode) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_PERFORMANCE_MODE; + export_guid(buf.caid, &GB_PERFORMANCE_MODE_GUID); + buf.fncn = GB_FNCN_PERFORMANCE_MODE; + buf.subn = GB_SUBN_PERFORMANCE_MODE_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_PERFORMANCE_MODE, + &buf, GB_SAWB_LEN_PERFORMANCE_MODE); + if (err) + return err; + + *performance_mode = buf.iob0; + + return 0; +} + +static int performance_mode_acpi_set(struct samsung_galaxybook *galaxybook, + const u8 performance_mode) +{ + struct sawb buf = {}; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_PERFORMANCE_MODE; + export_guid(buf.caid, &GB_PERFORMANCE_MODE_GUID); + buf.fncn = GB_FNCN_PERFORMANCE_MODE; + buf.subn = GB_SUBN_PERFORMANCE_MODE_SET; + buf.iob0 = performance_mode; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_PERFORMANCE_MODE, + &buf, GB_SAWB_LEN_PERFORMANCE_MODE); +} + +static int get_performance_mode_profile(struct samsung_galaxybook *galaxybook, + const u8 performance_mode, + enum platform_profile_option *profile) +{ + switch (performance_mode) { + case GB_PERFORMANCE_MODE_FANOFF: + *profile = PLATFORM_PROFILE_LOW_POWER; + break; + case GB_PERFORMANCE_MODE_LOWNOISE: + *profile = PLATFORM_PROFILE_QUIET; + break; + case GB_PERFORMANCE_MODE_OPTIMIZED: + case GB_PERFORMANCE_MODE_OPTIMIZED_V2: + *profile = PLATFORM_PROFILE_BALANCED; + break; + case GB_PERFORMANCE_MODE_PERFORMANCE: + case GB_PERFORMANCE_MODE_PERFORMANCE_V2: + case GB_PERFORMANCE_MODE_ULTRA: + *profile = PLATFORM_PROFILE_PERFORMANCE; + break; + case GB_PERFORMANCE_MODE_IGNORE1: + case GB_PERFORMANCE_MODE_IGNORE2: + return -EOPNOTSUPP; + default: + dev_warn(&galaxybook->platform->dev, + "unrecognized performance mode 0x%x\n", performance_mode); + return -EOPNOTSUPP; + } + + return 0; +} + +static int galaxybook_platform_profile_get(struct device *dev, + enum platform_profile_option *profile) +{ + struct samsung_galaxybook *galaxybook = dev_get_drvdata(dev); + u8 performance_mode; + int err; + + err = performance_mode_acpi_get(galaxybook, &performance_mode); + if (err) + return err; + + return get_performance_mode_profile(galaxybook, performance_mode, profile); +} + +static int galaxybook_platform_profile_set(struct device *dev, + enum platform_profile_option profile) +{ + struct samsung_galaxybook *galaxybook = dev_get_drvdata(dev); + + return performance_mode_acpi_set(galaxybook, + galaxybook->profile_performance_modes[profile]); +} + +static int galaxybook_platform_profile_probe(void *drvdata, unsigned long *choices) +{ + struct samsung_galaxybook *galaxybook = drvdata; + u8 *perfmodes = galaxybook->profile_performance_modes; + enum platform_profile_option profile; + struct sawb buf = {}; + unsigned int i; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_PERFORMANCE_MODE; + export_guid(buf.caid, &GB_PERFORMANCE_MODE_GUID); + buf.fncn = GB_FNCN_PERFORMANCE_MODE; + buf.subn = GB_SUBN_PERFORMANCE_MODE_LIST; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_PERFORMANCE_MODE, + &buf, GB_SAWB_LEN_PERFORMANCE_MODE); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to get supported performance modes, error %d\n", err); + return err; + } + + /* set initial default profile performance mode values */ + perfmodes[PLATFORM_PROFILE_LOW_POWER] = GB_PERFORMANCE_MODE_FANOFF; + perfmodes[PLATFORM_PROFILE_QUIET] = GB_PERFORMANCE_MODE_LOWNOISE; + perfmodes[PLATFORM_PROFILE_BALANCED] = GB_PERFORMANCE_MODE_OPTIMIZED; + perfmodes[PLATFORM_PROFILE_PERFORMANCE] = GB_PERFORMANCE_MODE_PERFORMANCE; + + /* + * Value returned in iob0 will have the number of supported performance + * modes per device. The performance mode values will then be given as a + * list after this (iob1-iobX). Loop through the supported values and + * enable their mapped platform_profile choice, overriding "legacy" + * values along the way if a non-legacy value exists. + */ + for (i = 1; i <= buf.iob0; i++) { + err = get_performance_mode_profile(galaxybook, buf.iobs[i], &profile); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "ignoring unmapped performance mode 0x%x\n", buf.iobs[i]); + continue; + } + switch (buf.iobs[i]) { + case GB_PERFORMANCE_MODE_OPTIMIZED_V2: + perfmodes[profile] = GB_PERFORMANCE_MODE_OPTIMIZED_V2; + break; + case GB_PERFORMANCE_MODE_PERFORMANCE_V2: + /* only update if not already overwritten by Ultra */ + if (perfmodes[profile] != GB_PERFORMANCE_MODE_ULTRA) + perfmodes[profile] = GB_PERFORMANCE_MODE_PERFORMANCE_V2; + break; + case GB_PERFORMANCE_MODE_ULTRA: + perfmodes[profile] = GB_PERFORMANCE_MODE_ULTRA; + break; + default: + break; + } + set_bit(profile, choices); + dev_dbg(&galaxybook->platform->dev, + "setting platform profile %d to use performance mode 0x%x\n", + profile, perfmodes[profile]); + } + + /* initialize performance_mode using balanced's mapped value */ + if (test_bit(PLATFORM_PROFILE_BALANCED, choices)) + return performance_mode_acpi_set(galaxybook, perfmodes[PLATFORM_PROFILE_BALANCED]); + + return 0; +} + +static const struct platform_profile_ops galaxybook_platform_profile_ops = { + .probe = galaxybook_platform_profile_probe, + .profile_get = galaxybook_platform_profile_get, + .profile_set = galaxybook_platform_profile_set, +}; + +static int galaxybook_platform_profile_init(struct samsung_galaxybook *galaxybook) +{ + struct device *platform_profile_dev; + u8 performance_mode; + int err; + + err = performance_mode_acpi_get(galaxybook, &performance_mode); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to get initial performance mode, error %d\n", err); + return GB_NOT_SUPPORTED; + } + + platform_profile_dev = devm_platform_profile_register(&galaxybook->platform->dev, + DRIVER_NAME, galaxybook, + &galaxybook_platform_profile_ops); + + return PTR_ERR_OR_ZERO(platform_profile_dev); +} + +/* + * Firmware Attributes + */ + +/* Power on lid open (device should power on when lid is opened) */ + +static int power_on_lid_open_acpi_get(struct samsung_galaxybook *galaxybook, bool *value) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_POWER_MANAGEMENT; + buf.gunm = GB_GUNM_POWER_MANAGEMENT; + buf.guds[0] = GB_GUDS_POWER_ON_LID_OPEN; + buf.guds[1] = GB_GUDS_POWER_ON_LID_OPEN_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + *value = buf.guds[1]; + + return 0; +} + +static int power_on_lid_open_acpi_set(struct samsung_galaxybook *galaxybook, const bool value) +{ + struct sawb buf = {}; + + lockdep_assert_held(&galaxybook->fw_attr_lock); + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_POWER_MANAGEMENT; + buf.gunm = GB_GUNM_POWER_MANAGEMENT; + buf.guds[0] = GB_GUDS_POWER_ON_LID_OPEN; + buf.guds[1] = GB_GUDS_POWER_ON_LID_OPEN_SET; + buf.guds[2] = value ? 1 : 0; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); +} + +/* USB Charging (USB ports can provide power when device is powered off) */ + +static int usb_charging_acpi_get(struct samsung_galaxybook *galaxybook, bool *value) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_USB_CHARGING_GET; + buf.gunm = GB_GUNM_USB_CHARGING_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + *value = buf.gunm == 1; + + return 0; +} + +static int usb_charging_acpi_set(struct samsung_galaxybook *galaxybook, const bool value) +{ + struct sawb buf = {}; + + lockdep_assert_held(&galaxybook->fw_attr_lock); + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_USB_CHARGING_SET; + buf.gunm = value ? GB_GUNM_USB_CHARGING_ON : GB_GUNM_USB_CHARGING_OFF; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); +} + +/* Block recording (blocks access to camera and microphone) */ + +static int block_recording_acpi_get(struct samsung_galaxybook *galaxybook, bool *value) +{ + struct sawb buf = {}; + int err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_BLOCK_RECORDING; + buf.gunm = GB_GUNM_GET; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + *value = buf.gunm == GB_BLOCK_RECORDING_ON; + + return 0; +} + +static int block_recording_acpi_set(struct samsung_galaxybook *galaxybook, const bool value) +{ + struct sawb buf = {}; + int err; + + lockdep_assert_held(&galaxybook->fw_attr_lock); + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_BLOCK_RECORDING; + buf.gunm = GB_GUNM_SET; + buf.guds[0] = value ? GB_BLOCK_RECORDING_ON : GB_BLOCK_RECORDING_OFF; + + err = galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); + if (err) + return err; + + input_report_switch(galaxybook->camera_lens_cover_switch, + SW_CAMERA_LENS_COVER, value ? 1 : 0); + input_sync(galaxybook->camera_lens_cover_switch); + + return 0; +} + +static int galaxybook_block_recording_init(struct samsung_galaxybook *galaxybook) +{ + bool value; + int err; + + err = galaxybook_enable_acpi_feature(galaxybook, GB_SASB_BLOCK_RECORDING); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to initialize block_recording, error %d\n", err); + return GB_NOT_SUPPORTED; + } + + guard(mutex)(&galaxybook->fw_attr_lock); + + err = block_recording_acpi_get(galaxybook, &value); + if (err) { + dev_dbg(&galaxybook->platform->dev, + "failed to get initial block_recording state, error %d\n", err); + return GB_NOT_SUPPORTED; + } + + galaxybook->camera_lens_cover_switch = + devm_input_allocate_device(&galaxybook->platform->dev); + if (!galaxybook->camera_lens_cover_switch) + return -ENOMEM; + + galaxybook->camera_lens_cover_switch->name = "Samsung Galaxy Book Camera Lens Cover"; + galaxybook->camera_lens_cover_switch->phys = DRIVER_NAME "/input0"; + galaxybook->camera_lens_cover_switch->id.bustype = BUS_HOST; + + input_set_capability(galaxybook->camera_lens_cover_switch, EV_SW, SW_CAMERA_LENS_COVER); + + err = input_register_device(galaxybook->camera_lens_cover_switch); + if (err) + return err; + + input_report_switch(galaxybook->camera_lens_cover_switch, + SW_CAMERA_LENS_COVER, value ? 1 : 0); + input_sync(galaxybook->camera_lens_cover_switch); + + return 0; +} + +/* Firmware Attributes setup */ + +static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "enumeration\n"); +} + +static struct kobj_attribute fw_attr_type = __ATTR_RO(type); + +static ssize_t default_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "0\n"); +} + +static struct kobj_attribute fw_attr_default_value = __ATTR_RO(default_value); + +static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "0;1\n"); +} + +static struct kobj_attribute fw_attr_possible_values = __ATTR_RO(possible_values); + +static ssize_t display_name_language_code_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", GB_ATTR_LANGUAGE_CODE); +} + +static struct kobj_attribute fw_attr_display_name_language_code = + __ATTR_RO(display_name_language_code); + +static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct galaxybook_fw_attr *fw_attr = + container_of(attr, struct galaxybook_fw_attr, display_name); + + return sysfs_emit(buf, "%s\n", galaxybook_fw_attr_desc[fw_attr->fw_attr_id]); +} + +static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct galaxybook_fw_attr *fw_attr = + container_of(attr, struct galaxybook_fw_attr, current_value); + bool value; + int err; + + err = fw_attr->get_value(fw_attr->galaxybook, &value); + if (err) + return err; + + return sysfs_emit(buf, "%u\n", value); +} + +static ssize_t current_value_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct galaxybook_fw_attr *fw_attr = + container_of(attr, struct galaxybook_fw_attr, current_value); + struct samsung_galaxybook *galaxybook = fw_attr->galaxybook; + bool value; + int err; + + if (!count) + return -EINVAL; + + err = kstrtobool(buf, &value); + if (err) + return err; + + guard(mutex)(&galaxybook->fw_attr_lock); + + err = fw_attr->set_value(galaxybook, value); + if (err) + return err; + + return count; +} + +#define NUM_FW_ATTR_ENUM_ATTRS 6 + +static int galaxybook_fw_attr_init(struct samsung_galaxybook *galaxybook, + const enum galaxybook_fw_attr_id fw_attr_id, + int (*get_value)(struct samsung_galaxybook *galaxybook, + bool *value), + int (*set_value)(struct samsung_galaxybook *galaxybook, + const bool value)) +{ + struct galaxybook_fw_attr *fw_attr; + struct attribute **attrs; + + fw_attr = devm_kzalloc(&galaxybook->platform->dev, sizeof(*fw_attr), GFP_KERNEL); + if (!fw_attr) + return -ENOMEM; + + attrs = devm_kcalloc(&galaxybook->platform->dev, NUM_FW_ATTR_ENUM_ATTRS + 1, + sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return -ENOMEM; + + attrs[0] = &fw_attr_type.attr; + attrs[1] = &fw_attr_default_value.attr; + attrs[2] = &fw_attr_possible_values.attr; + attrs[3] = &fw_attr_display_name_language_code.attr; + + sysfs_attr_init(&fw_attr->display_name.attr); + fw_attr->display_name.attr.name = "display_name"; + fw_attr->display_name.attr.mode = 0444; + fw_attr->display_name.show = display_name_show; + attrs[4] = &fw_attr->display_name.attr; + + sysfs_attr_init(&fw_attr->current_value.attr); + fw_attr->current_value.attr.name = "current_value"; + fw_attr->current_value.attr.mode = 0644; + fw_attr->current_value.show = current_value_show; + fw_attr->current_value.store = current_value_store; + attrs[5] = &fw_attr->current_value.attr; + + attrs[6] = NULL; + + fw_attr->galaxybook = galaxybook; + fw_attr->fw_attr_id = fw_attr_id; + fw_attr->attr_group.name = galaxybook_fw_attr_name[fw_attr_id]; + fw_attr->attr_group.attrs = attrs; + fw_attr->get_value = get_value; + fw_attr->set_value = set_value; + + return sysfs_create_group(&galaxybook->fw_attrs_kset->kobj, &fw_attr->attr_group); +} + +static void galaxybook_kset_unregister(void *data) +{ + struct kset *kset = data; + + kset_unregister(kset); +} + +static void galaxybook_fw_attrs_dev_unregister(void *data) +{ + struct device *fw_attrs_dev = data; + + device_unregister(fw_attrs_dev); +} + +static int galaxybook_fw_attrs_init(struct samsung_galaxybook *galaxybook) +{ + bool value; + int err; + + err = devm_mutex_init(&galaxybook->platform->dev, &galaxybook->fw_attr_lock); + if (err) + return err; + + galaxybook->fw_attrs_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), + NULL, "%s", DRIVER_NAME); + if (IS_ERR(galaxybook->fw_attrs_dev)) + return PTR_ERR(galaxybook->fw_attrs_dev); + + err = devm_add_action_or_reset(&galaxybook->platform->dev, + galaxybook_fw_attrs_dev_unregister, + galaxybook->fw_attrs_dev); + if (err) + return err; + + galaxybook->fw_attrs_kset = kset_create_and_add("attributes", NULL, + &galaxybook->fw_attrs_dev->kobj); + if (!galaxybook->fw_attrs_kset) + return -ENOMEM; + err = devm_add_action_or_reset(&galaxybook->platform->dev, + galaxybook_kset_unregister, galaxybook->fw_attrs_kset); + if (err) + return err; + + err = power_on_lid_open_acpi_get(galaxybook, &value); + if (!err) { + err = galaxybook_fw_attr_init(galaxybook, + GB_ATTR_POWER_ON_LID_OPEN, + &power_on_lid_open_acpi_get, + &power_on_lid_open_acpi_set); + if (err) + return err; + } + + err = usb_charging_acpi_get(galaxybook, &value); + if (!err) { + err = galaxybook_fw_attr_init(galaxybook, + GB_ATTR_USB_CHARGING, + &usb_charging_acpi_get, + &usb_charging_acpi_set); + if (err) + return err; + } + + err = galaxybook_block_recording_init(galaxybook); + if (err == GB_NOT_SUPPORTED) + return 0; + else if (err) + return err; + + galaxybook->has_block_recording = true; + + return galaxybook_fw_attr_init(galaxybook, + GB_ATTR_BLOCK_RECORDING, + &block_recording_acpi_get, + &block_recording_acpi_set); +} + +/* + * Hotkeys and notifications + */ + +static void galaxybook_kbd_backlight_hotkey_work(struct work_struct *work) +{ + struct samsung_galaxybook *galaxybook = + from_work(galaxybook, work, kbd_backlight_hotkey_work); + int brightness; + int err; + + guard(mutex)(&galaxybook->kbd_backlight_lock); + + brightness = galaxybook->kbd_backlight.brightness; + if (brightness < galaxybook->kbd_backlight.max_brightness) + brightness++; + else + brightness = 0; + + err = led_set_brightness_sync(&galaxybook->kbd_backlight, brightness); + if (err) { + dev_err(&galaxybook->platform->dev, + "failed to set kbd_backlight brightness, error %d\n", err); + return; + } + + led_classdev_notify_brightness_hw_changed(&galaxybook->kbd_backlight, brightness); +} + +static void galaxybook_block_recording_hotkey_work(struct work_struct *work) +{ + struct samsung_galaxybook *galaxybook = + from_work(galaxybook, work, block_recording_hotkey_work); + bool value; + int err; + + guard(mutex)(&galaxybook->fw_attr_lock); + + err = block_recording_acpi_get(galaxybook, &value); + if (err) { + dev_err(&galaxybook->platform->dev, + "failed to get block_recording, error %d\n", err); + return; + } + + err = block_recording_acpi_set(galaxybook, !value); + if (err) + dev_err(&galaxybook->platform->dev, + "failed to set block_recording, error %d\n", err); +} + +static bool galaxybook_i8042_filter(unsigned char data, unsigned char str, struct serio *port, + void *context) +{ + struct samsung_galaxybook *galaxybook = context; + static bool extended; + + if (str & I8042_STR_AUXDATA) + return false; + + if (data == 0xe0) { + extended = true; + return true; + } else if (extended) { + extended = false; + switch (data) { + case GB_KEY_KBD_BACKLIGHT_KEYDOWN: + return true; + case GB_KEY_KBD_BACKLIGHT_KEYUP: + if (galaxybook->has_kbd_backlight) + schedule_work(&galaxybook->kbd_backlight_hotkey_work); + return true; + + case GB_KEY_BLOCK_RECORDING_KEYDOWN: + return true; + case GB_KEY_BLOCK_RECORDING_KEYUP: + if (galaxybook->has_block_recording) + schedule_work(&galaxybook->block_recording_hotkey_work); + return true; + + /* battery notification already sent to battery + SCAI device */ + case GB_KEY_BATTERY_NOTIFY_KEYUP: + case GB_KEY_BATTERY_NOTIFY_KEYDOWN: + return true; + + default: + /* + * Report the previously filtered e0 before continuing + * with the next non-filtered byte. + */ + serio_interrupt(port, 0xe0, 0); + return false; + } + } + + return false; +} + +static void galaxybook_i8042_filter_remove(void *data) +{ + struct samsung_galaxybook *galaxybook = data; + + i8042_remove_filter(galaxybook_i8042_filter); + cancel_work_sync(&galaxybook->kbd_backlight_hotkey_work); + cancel_work_sync(&galaxybook->block_recording_hotkey_work); +} + +static int galaxybook_i8042_filter_install(struct samsung_galaxybook *galaxybook) +{ + int err; + + if (!galaxybook->has_kbd_backlight && !galaxybook->has_block_recording) + return 0; + + INIT_WORK(&galaxybook->kbd_backlight_hotkey_work, + galaxybook_kbd_backlight_hotkey_work); + INIT_WORK(&galaxybook->block_recording_hotkey_work, + galaxybook_block_recording_hotkey_work); + + err = i8042_install_filter(galaxybook_i8042_filter, galaxybook); + if (err) + return err; + + return devm_add_action_or_reset(&galaxybook->platform->dev, + galaxybook_i8042_filter_remove, galaxybook); +} + +/* + * ACPI device setup + */ + +static void galaxybook_acpi_notify(acpi_handle handle, u32 event, void *data) +{ + struct samsung_galaxybook *galaxybook = data; + + switch (event) { + case GB_ACPI_NOTIFY_BATTERY_STATE_CHANGED: + case GB_ACPI_NOTIFY_DEVICE_ON_TABLE: + case GB_ACPI_NOTIFY_DEVICE_OFF_TABLE: + break; + case GB_ACPI_NOTIFY_HOTKEY_PERFORMANCE_MODE: + if (galaxybook->has_performance_mode) + platform_profile_cycle(); + break; + default: + dev_warn(&galaxybook->platform->dev, + "unknown ACPI notification event: 0x%x\n", event); + } + + acpi_bus_generate_netlink_event(DRIVER_NAME, dev_name(&galaxybook->platform->dev), + event, 1); +} + +static int galaxybook_enable_acpi_notify(struct samsung_galaxybook *galaxybook) +{ + struct sawb buf = {}; + int err; + + err = galaxybook_enable_acpi_feature(galaxybook, GB_SASB_NOTIFICATIONS); + if (err) + return err; + + buf.safn = GB_SAFN; + buf.sasb = GB_SASB_NOTIFICATIONS; + buf.gunm = GB_GUNM_ACPI_NOTIFY_ENABLE; + buf.guds[0] = GB_GUDS_ACPI_NOTIFY_ENABLE; + + return galaxybook_acpi_method(galaxybook, GB_ACPI_METHOD_SETTINGS, + &buf, GB_SAWB_LEN_SETTINGS); +} + +static void galaxybook_acpi_remove_notify_handler(void *data) +{ + struct samsung_galaxybook *galaxybook = data; + + acpi_remove_notify_handler(galaxybook->acpi->handle, ACPI_ALL_NOTIFY, + galaxybook_acpi_notify); +} + +static void galaxybook_acpi_disable(void *data) +{ + struct samsung_galaxybook *galaxybook = data; + + acpi_execute_simple_method(galaxybook->acpi->handle, + GB_ACPI_METHOD_ENABLE, GB_ACPI_METHOD_ENABLE_OFF); +} + +static int galaxybook_acpi_init(struct samsung_galaxybook *galaxybook) +{ + acpi_status status; + int err; + + status = acpi_execute_simple_method(galaxybook->acpi->handle, GB_ACPI_METHOD_ENABLE, + GB_ACPI_METHOD_ENABLE_ON); + if (ACPI_FAILURE(status)) + return -EIO; + err = devm_add_action_or_reset(&galaxybook->platform->dev, + galaxybook_acpi_disable, galaxybook); + if (err) + return err; + + status = acpi_install_notify_handler(galaxybook->acpi->handle, ACPI_ALL_NOTIFY, + galaxybook_acpi_notify, galaxybook); + if (ACPI_FAILURE(status)) + return -EIO; + err = devm_add_action_or_reset(&galaxybook->platform->dev, + galaxybook_acpi_remove_notify_handler, galaxybook); + if (err) + return err; + + err = galaxybook_enable_acpi_notify(galaxybook); + if (err) + dev_dbg(&galaxybook->platform->dev, "failed to enable ACPI notifications; " + "some hotkeys will not be supported\n"); + + err = galaxybook_enable_acpi_feature(galaxybook, GB_SASB_POWER_MANAGEMENT); + if (err) + dev_dbg(&galaxybook->platform->dev, + "failed to initialize ACPI power management features; " + "many features of this driver will not be available\n"); + + return 0; +} + +/* + * Platform driver + */ + +static int galaxybook_probe(struct platform_device *pdev) +{ + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + struct samsung_galaxybook *galaxybook; + int err; + + if (!adev) + return -ENODEV; + + galaxybook = devm_kzalloc(&pdev->dev, sizeof(*galaxybook), GFP_KERNEL); + if (!galaxybook) + return -ENOMEM; + + galaxybook->platform = pdev; + galaxybook->acpi = adev; + + /* + * Features must be enabled and initialized in the following order to + * avoid failures seen on certain devices: + * - GB_SASB_POWER_MANAGEMENT (including performance mode) + * - GB_SASB_KBD_BACKLIGHT + * - GB_SASB_BLOCK_RECORDING (as part of fw_attrs init) + */ + + err = galaxybook_acpi_init(galaxybook); + if (err) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize ACPI device\n"); + + err = galaxybook_platform_profile_init(galaxybook); + if (!err) + galaxybook->has_performance_mode = true; + else if (err != GB_NOT_SUPPORTED) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize platform profile\n"); + + err = galaxybook_battery_threshold_init(galaxybook); + if (err) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize battery threshold\n"); + + err = galaxybook_kbd_backlight_init(galaxybook); + if (!err) + galaxybook->has_kbd_backlight = true; + else if (err != GB_NOT_SUPPORTED) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize kbd_backlight\n"); + + err = galaxybook_fw_attrs_init(galaxybook); + if (err) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize firmware-attributes\n"); + + err = galaxybook_i8042_filter_install(galaxybook); + if (err) + return dev_err_probe(&galaxybook->platform->dev, err, + "failed to initialize i8042_filter\n"); + + return 0; +} + +static const struct acpi_device_id galaxybook_device_ids[] = { + { "SAM0427" }, + { "SAM0428" }, + { "SAM0429" }, + { "SAM0430" }, + {} +}; +MODULE_DEVICE_TABLE(acpi, galaxybook_device_ids); + +static struct platform_driver galaxybook_platform_driver = { + .driver = { + .name = DRIVER_NAME, + .acpi_match_table = galaxybook_device_ids, + }, + .probe = galaxybook_probe, +}; +module_platform_driver(galaxybook_platform_driver); + +MODULE_AUTHOR("Joshua Grisham <josh@joshuagrisham.com>"); +MODULE_DESCRIPTION("Samsung Galaxy Book driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c index 323316ac6783..0fc275e461be 100644 --- a/drivers/platform/x86/think-lmi.c +++ b/drivers/platform/x86/think-lmi.c @@ -262,16 +262,11 @@ static int tlmi_simple_call(const char *guid, const char *arg) return 0; } -/* Extract output string from WMI return buffer */ -static int tlmi_extract_output_string(const struct acpi_buffer *output, - char **string) +/* Extract output string from WMI return value */ +static int tlmi_extract_output_string(union acpi_object *obj, char **string) { - const union acpi_object *obj; char *s; - obj = output->pointer; - if (!obj) - return -ENOMEM; if (obj->type != ACPI_TYPE_STRING || !obj->string.pointer) return -EIO; @@ -349,20 +344,18 @@ static int tlmi_opcode_setting(char *setting, const char *value) return ret; } -static int tlmi_setting(int item, char **value, const char *guid_string) +static int tlmi_setting(struct wmi_device *wdev, int item, char **value) { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_status status; + union acpi_object *obj; int ret; - status = wmi_query_block(guid_string, item, &output); - if (ACPI_FAILURE(status)) { - kfree(output.pointer); + obj = wmidev_block_query(wdev, item); + if (!obj) return -EIO; - } - ret = tlmi_extract_output_string(&output, value); - kfree(output.pointer); + ret = tlmi_extract_output_string(obj, value); + kfree(obj); + return ret; } @@ -370,19 +363,22 @@ static int tlmi_get_bios_selections(const char *item, char **value) { const struct acpi_buffer input = { strlen(item), (char *)item }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; acpi_status status; int ret; status = wmi_evaluate_method(LENOVO_GET_BIOS_SELECTIONS_GUID, 0, 0, &input, &output); - - if (ACPI_FAILURE(status)) { - kfree(output.pointer); + if (ACPI_FAILURE(status)) return -EIO; - } - ret = tlmi_extract_output_string(&output, value); - kfree(output.pointer); + obj = output.pointer; + if (!obj) + return -ENODATA; + + ret = tlmi_extract_output_string(obj, value); + kfree(obj); + return ret; } @@ -993,7 +989,7 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a char *item, *value; int ret; - ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID); + ret = tlmi_setting(setting->wdev, setting->index, &item); if (ret) return ret; @@ -1586,7 +1582,7 @@ static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type, return new_pwd; } -static int tlmi_analyze(void) +static int tlmi_analyze(struct wmi_device *wdev) { int i, ret; @@ -1623,7 +1619,7 @@ static int tlmi_analyze(void) char *item = NULL; tlmi_priv.setting[i] = NULL; - ret = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID); + ret = tlmi_setting(wdev, i, &item); if (ret) break; if (!item) @@ -1646,6 +1642,7 @@ static int tlmi_analyze(void) kfree(item); goto fail_clear_attr; } + setting->wdev = wdev; setting->index = i; strscpy(setting->display_name, item); /* If BIOS selections supported, load those */ @@ -1664,7 +1661,7 @@ static int tlmi_analyze(void) */ char *optitem, *optstart, *optend; - if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) { + if (!tlmi_setting(setting->wdev, setting->index, &optitem)) { optstart = strstr(optitem, "[Optional:"); if (optstart) { optstart += strlen("[Optional:"); @@ -1789,7 +1786,7 @@ static int tlmi_probe(struct wmi_device *wdev, const void *context) { int ret; - ret = tlmi_analyze(); + ret = tlmi_analyze(wdev); if (ret) return ret; diff --git a/drivers/platform/x86/think-lmi.h b/drivers/platform/x86/think-lmi.h index f267d8b46957..a80452482227 100644 --- a/drivers/platform/x86/think-lmi.h +++ b/drivers/platform/x86/think-lmi.h @@ -4,6 +4,7 @@ #define _THINK_LMI_H_ #include <linux/types.h> +#include <linux/wmi.h> #define TLMI_SETTINGS_COUNT 256 #define TLMI_SETTINGS_MAXLEN 512 @@ -87,6 +88,7 @@ struct tlmi_pwd_setting { /* Attribute setting details */ struct tlmi_attr_setting { struct kobject kobj; + struct wmi_device *wdev; int index; char display_name[TLMI_SETTINGS_MAXLEN]; char *possible_values; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 1cc91173e012..0384cf311878 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -39,7 +39,6 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/dmi.h> -#include <linux/fb.h> #include <linux/freezer.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> @@ -368,9 +367,6 @@ static struct { u32 beep_needs_two_args:1; u32 mixer_no_level_control:1; u32 battery_force_primary:1; - u32 input_device_registered:1; - u32 platform_drv_registered:1; - u32 sensors_pdrv_registered:1; u32 hotkey_poll_active:1; u32 has_adaptive_kbd:1; u32 kbd_lang:1; @@ -8513,7 +8509,7 @@ static void fan_watchdog_reset(void) if (fan_watchdog_maxinterval > 0 && tpacpi_lifecycle != TPACPI_LIFE_EXITING) mod_delayed_work(tpacpi_wq, &fan_watchdog_task, - msecs_to_jiffies(fan_watchdog_maxinterval * 1000)); + secs_to_jiffies(fan_watchdog_maxinterval)); else cancel_delayed_work(&fan_watchdog_task); } @@ -11817,36 +11813,18 @@ MODULE_PARM_DESC(profile_force, "Force profile mode. -1=off, 1=MMC, 2=PSC"); static void thinkpad_acpi_module_exit(void) { - struct ibm_struct *ibm, *itmp; - tpacpi_lifecycle = TPACPI_LIFE_EXITING; - if (tpacpi_hwmon) - hwmon_device_unregister(tpacpi_hwmon); - if (tp_features.sensors_pdrv_registered) + if (tpacpi_sensors_pdev) { platform_driver_unregister(&tpacpi_hwmon_pdriver); - if (tp_features.platform_drv_registered) - platform_driver_unregister(&tpacpi_pdriver); - - list_for_each_entry_safe_reverse(ibm, itmp, - &tpacpi_all_drivers, - all_drivers) { - ibm_exit(ibm); + platform_device_unregister(tpacpi_sensors_pdev); } - dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); - - if (tpacpi_inputdev) { - if (tp_features.input_device_registered) - input_unregister_device(tpacpi_inputdev); - else - input_free_device(tpacpi_inputdev); + if (tpacpi_pdev) { + platform_driver_unregister(&tpacpi_pdriver); + platform_device_unregister(tpacpi_pdev); } - if (tpacpi_sensors_pdev) - platform_device_unregister(tpacpi_sensors_pdev); - if (tpacpi_pdev) - platform_device_unregister(tpacpi_pdev); if (proc_dir) remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); if (tpacpi_wq) @@ -11858,11 +11836,76 @@ static void thinkpad_acpi_module_exit(void) kfree(thinkpad_id.nummodel_str); } +static void tpacpi_subdrivers_release(void *data) +{ + struct ibm_struct *ibm, *itmp; + + list_for_each_entry_safe_reverse(ibm, itmp, &tpacpi_all_drivers, all_drivers) + ibm_exit(ibm); + + dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); +} + +static int __init tpacpi_pdriver_probe(struct platform_device *pdev) +{ + int ret; + + ret = devm_mutex_init(&pdev->dev, &tpacpi_inputdev_send_mutex); + if (ret) + return ret; + + tpacpi_inputdev = devm_input_allocate_device(&pdev->dev); + if (!tpacpi_inputdev) + return -ENOMEM; + + tpacpi_inputdev->name = "ThinkPad Extra Buttons"; + tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; + tpacpi_inputdev->id.bustype = BUS_HOST; + tpacpi_inputdev->id.vendor = thinkpad_id.vendor; + tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; + tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; + tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; + + /* Init subdriver dependencies */ + tpacpi_detect_brightness_capabilities(); + + /* Init subdrivers */ + for (unsigned int i = 0; i < ARRAY_SIZE(ibms_init); i++) { + ret = ibm_init(&ibms_init[i]); + if (ret >= 0 && *ibms_init[i].param) + ret = ibms_init[i].data->write(ibms_init[i].param); + if (ret < 0) { + tpacpi_subdrivers_release(NULL); + return ret; + } + } + + ret = devm_add_action_or_reset(&pdev->dev, tpacpi_subdrivers_release, NULL); + if (ret) + return ret; + + ret = input_register_device(tpacpi_inputdev); + if (ret < 0) + pr_err("unable to register input device\n"); + + return ret; +} + +static int __init tpacpi_hwmon_pdriver_probe(struct platform_device *pdev) +{ + tpacpi_hwmon = devm_hwmon_device_register_with_groups( + &tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, tpacpi_hwmon_groups); + + if (IS_ERR(tpacpi_hwmon)) + pr_err("unable to register hwmon device\n"); + + return PTR_ERR_OR_ZERO(tpacpi_hwmon); +} static int __init thinkpad_acpi_module_init(void) { const struct dmi_system_id *dmi_id; - int ret, i; + int ret; acpi_object_type obj_type; tpacpi_lifecycle = TPACPI_LIFE_INIT; @@ -11922,93 +11965,29 @@ static int __init thinkpad_acpi_module_init(void) tp_features.quirks = dmi_id->driver_data; /* Device initialization */ - tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, PLATFORM_DEVID_NONE, - NULL, 0); + tpacpi_pdev = platform_create_bundle(&tpacpi_pdriver, tpacpi_pdriver_probe, + NULL, 0, NULL, 0); if (IS_ERR(tpacpi_pdev)) { ret = PTR_ERR(tpacpi_pdev); tpacpi_pdev = NULL; - pr_err("unable to register platform device\n"); + pr_err("unable to register platform device/driver bundle\n"); thinkpad_acpi_module_exit(); return ret; } - tpacpi_sensors_pdev = platform_device_register_simple( - TPACPI_HWMON_DRVR_NAME, - PLATFORM_DEVID_NONE, NULL, 0); + + tpacpi_sensors_pdev = platform_create_bundle(&tpacpi_hwmon_pdriver, + tpacpi_hwmon_pdriver_probe, + NULL, 0, NULL, 0); if (IS_ERR(tpacpi_sensors_pdev)) { ret = PTR_ERR(tpacpi_sensors_pdev); tpacpi_sensors_pdev = NULL; - pr_err("unable to register hwmon platform device\n"); + pr_err("unable to register hwmon platform device/driver bundle\n"); thinkpad_acpi_module_exit(); return ret; } - mutex_init(&tpacpi_inputdev_send_mutex); - tpacpi_inputdev = input_allocate_device(); - if (!tpacpi_inputdev) { - thinkpad_acpi_module_exit(); - return -ENOMEM; - } else { - /* Prepare input device, but don't register */ - tpacpi_inputdev->name = "ThinkPad Extra Buttons"; - tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; - tpacpi_inputdev->id.bustype = BUS_HOST; - tpacpi_inputdev->id.vendor = thinkpad_id.vendor; - tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; - tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; - tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; - } - - /* Init subdriver dependencies */ - tpacpi_detect_brightness_capabilities(); - - /* Init subdrivers */ - for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { - ret = ibm_init(&ibms_init[i]); - if (ret >= 0 && *ibms_init[i].param) - ret = ibms_init[i].data->write(ibms_init[i].param); - if (ret < 0) { - thinkpad_acpi_module_exit(); - return ret; - } - } - tpacpi_lifecycle = TPACPI_LIFE_RUNNING; - ret = platform_driver_register(&tpacpi_pdriver); - if (ret) { - pr_err("unable to register main platform driver\n"); - thinkpad_acpi_module_exit(); - return ret; - } - tp_features.platform_drv_registered = 1; - - ret = platform_driver_register(&tpacpi_hwmon_pdriver); - if (ret) { - pr_err("unable to register hwmon platform driver\n"); - thinkpad_acpi_module_exit(); - return ret; - } - tp_features.sensors_pdrv_registered = 1; - - tpacpi_hwmon = hwmon_device_register_with_groups( - &tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, tpacpi_hwmon_groups); - if (IS_ERR(tpacpi_hwmon)) { - ret = PTR_ERR(tpacpi_hwmon); - tpacpi_hwmon = NULL; - pr_err("unable to register hwmon device\n"); - thinkpad_acpi_module_exit(); - return ret; - } - - ret = input_register_device(tpacpi_inputdev); - if (ret < 0) { - pr_err("unable to register input device\n"); - thinkpad_acpi_module_exit(); - return ret; - } else { - tp_features.input_device_registered = 1; - } - return 0; } diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 646370bd6b03..e46453750d5f 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -123,24 +123,6 @@ static const void *find_guid_context(struct wmi_block *wblock, return NULL; } -static acpi_status wmi_method_enable(struct wmi_block *wblock, bool enable) -{ - struct guid_block *block; - char method[5]; - acpi_status status; - acpi_handle handle; - - block = &wblock->gblock; - handle = wblock->acpi_device->handle; - - snprintf(method, 5, "WE%02X", block->notify_id); - status = acpi_execute_simple_method(handle, method, enable); - if (status == AE_NOT_FOUND) - return AE_OK; - - return status; -} - #define WMI_ACPI_METHOD_NAME_SIZE 5 static inline void get_acpi_method_name(const struct wmi_block *wblock, @@ -184,6 +166,44 @@ static int wmidev_match_guid(struct device *dev, const void *data) static const struct bus_type wmi_bus_type; +static const struct device_type wmi_type_event; + +static const struct device_type wmi_type_method; + +static int wmi_device_enable(struct wmi_device *wdev, bool enable) +{ + struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev); + char method[WMI_ACPI_METHOD_NAME_SIZE]; + acpi_handle handle; + acpi_status status; + + if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE)) + return 0; + + if (wblock->dev.dev.type == &wmi_type_method) + return 0; + + if (wblock->dev.dev.type == &wmi_type_event) + snprintf(method, sizeof(method), "WE%02X", wblock->gblock.notify_id); + else + get_acpi_method_name(wblock, 'C', method); + + /* + * Not all WMI devices marked as expensive actually implement the + * necessary ACPI method. Ignore this missing ACPI method to match + * the behaviour of the Windows driver. + */ + status = acpi_get_handle(wblock->acpi_device->handle, method, &handle); + if (ACPI_FAILURE(status)) + return 0; + + status = acpi_execute_simple_method(handle, NULL, enable); + if (ACPI_FAILURE(status)) + return -EIO; + + return 0; +} + static struct wmi_device *wmi_find_device_by_guid(const char *guid_string) { struct device *dev; @@ -337,10 +357,8 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, { struct guid_block *block; acpi_handle handle; - acpi_status status, wc_status = AE_ERROR; struct acpi_object_list input; union acpi_object wq_params[1]; - char wc_method[WMI_ACPI_METHOD_NAME_SIZE]; char method[WMI_ACPI_METHOD_NAME_SIZE]; if (!out) @@ -364,40 +382,9 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, if (instance == 0 && test_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags)) input.count = 0; - /* - * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to - * enable collection. - */ - if (block->flags & ACPI_WMI_EXPENSIVE) { - get_acpi_method_name(wblock, 'C', wc_method); - - /* - * Some GUIDs break the specification by declaring themselves - * expensive, but have no corresponding WCxx method. So we - * should not fail if this happens. - */ - wc_status = acpi_execute_simple_method(handle, wc_method, 1); - } - get_acpi_method_name(wblock, 'Q', method); - status = acpi_evaluate_object(handle, method, &input, out); - - /* - * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if - * the WQxx method failed - we should disable collection anyway. - */ - if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { - /* - * Ignore whether this WCxx call succeeds or not since - * the previously executed WQxx method call might have - * succeeded, and returning the failing status code - * of this call would throw away the result of the WQxx - * call, potentially leaking memory. - */ - acpi_execute_simple_method(handle, wc_method, 0); - } - return status; + return acpi_evaluate_object(handle, method, &input, out); } /** @@ -421,9 +408,15 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance, if (IS_ERR(wdev)) return AE_ERROR; + if (wmi_device_enable(wdev, true) < 0) + dev_warn(&wdev->dev, "Failed to enable device\n"); + wblock = container_of(wdev, struct wmi_block, dev); status = __query_block(wblock, instance, out); + if (wmi_device_enable(wdev, false) < 0) + dev_warn(&wdev->dev, "Failed to disable device\n"); + wmi_device_put(wdev); return status; @@ -470,7 +463,14 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acp if (IS_ERR(wdev)) return AE_ERROR; + if (wmi_device_enable(wdev, true) < 0) + dev_warn(&wdev->dev, "Failed to enable device\n"); + status = wmidev_block_set(wdev, instance, in); + + if (wmi_device_enable(wdev, false) < 0) + dev_warn(&wdev->dev, "Failed to disable device\n"); + wmi_device_put(wdev); return status; @@ -551,7 +551,7 @@ acpi_status wmi_install_notify_handler(const char *guid, wblock->handler = handler; wblock->handler_data = data; - if (ACPI_FAILURE(wmi_method_enable(wblock, true))) + if (wmi_device_enable(wdev, true) < 0) dev_warn(&wblock->dev.dev, "Failed to enable device\n"); status = AE_OK; @@ -588,7 +588,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!wblock->handler) { status = AE_NULL_ENTRY; } else { - if (ACPI_FAILURE(wmi_method_enable(wblock, false))) + if (wmi_device_enable(wdev, false) < 0) dev_warn(&wblock->dev.dev, "Failed to disable device\n"); wblock->handler = NULL; @@ -821,11 +821,19 @@ static int wmi_dev_match(struct device *dev, const struct device_driver *driver) return 0; } +static void wmi_dev_disable(void *data) +{ + struct device *dev = data; + + if (wmi_device_enable(to_wmi_device(dev), false) < 0) + dev_warn(dev, "Failed to disable device\n"); +} + static int wmi_dev_probe(struct device *dev) { struct wmi_block *wblock = dev_to_wblock(dev); struct wmi_driver *wdriver = to_wmi_driver(dev->driver); - int ret = 0; + int ret; /* Some older WMI drivers will break if instantiated multiple times, * so they are blocked from probing WMI devices with a duplicated GUID. @@ -844,18 +852,22 @@ static int wmi_dev_probe(struct device *dev) return -ENODEV; } - if (ACPI_FAILURE(wmi_method_enable(wblock, true))) + if (wmi_device_enable(to_wmi_device(dev), true) < 0) dev_warn(dev, "failed to enable device -- probing anyway\n"); + /* + * We have to make sure that all devres-managed resources are released first because + * some might still want to access the underlying WMI device. + */ + ret = devm_add_action_or_reset(dev, wmi_dev_disable, dev); + if (ret < 0) + return ret; + if (wdriver->probe) { ret = wdriver->probe(to_wmi_device(dev), find_guid_context(wblock, wdriver)); - if (ret) { - if (ACPI_FAILURE(wmi_method_enable(wblock, false))) - dev_warn(dev, "Failed to disable device\n"); - + if (ret) return ret; - } } down_write(&wblock->notify_lock); @@ -876,9 +888,6 @@ static void wmi_dev_remove(struct device *dev) if (wdriver->remove) wdriver->remove(to_wmi_device(dev)); - - if (ACPI_FAILURE(wmi_method_enable(wblock, false))) - dev_warn(dev, "failed to disable device\n"); } static void wmi_dev_shutdown(struct device *dev) @@ -902,7 +911,11 @@ static void wmi_dev_shutdown(struct device *dev) if (wdriver->shutdown) wdriver->shutdown(to_wmi_device(dev)); - if (ACPI_FAILURE(wmi_method_enable(wblock, false))) + /* + * We still need to disable the WMI device here since devres-managed resources + * like wmi_dev_disable() will not be release during shutdown. + */ + if (wmi_device_enable(to_wmi_device(dev), false) < 0) dev_warn(dev, "Failed to disable device\n"); } } diff --git a/drivers/platform/x86/x86-android-tablets/Kconfig b/drivers/platform/x86/x86-android-tablets/Kconfig index a67bddc43007..193da15ee01c 100644 --- a/drivers/platform/x86/x86-android-tablets/Kconfig +++ b/drivers/platform/x86/x86-android-tablets/Kconfig @@ -10,6 +10,7 @@ config X86_ANDROID_TABLETS depends on ACPI && EFI && PCI select NEW_LEDS select LEDS_CLASS + select POWER_SUPPLY help X86 tablets which ship with Android as (part of) the factory image typically have various problems with their DSDTs. The factory kernels |