platform-drivers-x86 for v5.6-1
* Enable thermal policy for ASUS TUF FX705DY/FX505DY * Support left round button on ASUS N56VB * Support new Mellanox platforms of basic class VMOD0009 and VMOD0010 * Intel Comet Lake, Tiger Lake and Elkhart Lake support in the PMC driver * Big clean up to Intel PMC core, PMC IPC and SCU IPC drivers * Touchscreen support for the PiPO W11 tablet The following is an automated git shortlog grouped by driver: asus-nb-wmi: - Support left round button on N56VB asus-wmi: - Fix keyboard brightness cannot be set to 0 - Set throttle thermal policy to default - Support throttle thermal policy Documentation/ABI: - Add new attribute for mlxreg-io sysfs interfaces - Style changes - Add missed attribute for mlxreg-io sysfs interfaces - Fix documentation inconsistency for mlxreg-io sysfs interfaces GPD pocket fan: - Allow somewhat lower/higher temperature limits - Use default values when wrong modparams are given intel_atomisp2_pm: - Spelling fixes - Refactor timeout loop intel_mid_powerbtn: - Take a copy of ddata intel_pmc_core: - update Comet Lake platform driver - Fix spelling of MHz unit - Fix indentation in function definitions - Put more stuff under #ifdef DEBUG_FS - Respect error code of kstrtou32_from_user() - Add Intel Elkhart Lake support - Add Intel Tiger Lake support - Make debugfs entry for pch_ip_power_gating_status conditional - Create platform dependent bitmap structs - Remove unnecessary assignments - Clean up: Remove comma after the termination line intel_pmc_ipc: - Switch to use driver->dev_groups - Propagate error from kstrtoul() - Use octal permissions in sysfs attributes - Get rid of unnecessary includes - Drop ipc_data_readb() - Drop intel_pmc_gcr_read() and intel_pmc_gcr_write() - Make intel_pmc_ipc_raw_cmd() static - Make intel_pmc_ipc_simple_command() static - Make intel_pmc_gcr_update() static intel_scu_ipc: - Reformat kernel-doc comments of exported functions - Drop intel_scu_ipc_raw_command() - Drop intel_scu_ipc_io[read|write][8|16]() - Drop unused macros - Drop unused prototype intel_scu_ipc_fw_update() - Sleeping is fine when polling - Drop intel_scu_ipc_i2c_cntrl() - Remove Lincroft support - Add constants for register offsets - Fix interrupt support intel_scu_ipcutil: - Remove default y from Kconfig intel_telemetry_debugfs: - Respect error code of kstrtou32_from_user() intel_telemetry_pltdrv: - use devm_platform_ioremap_resource() mlx-platform: - Add support for next generation systems - Add support for new capability register - Add support for new system type - Set system mux configuration based on system type - Add more definitions for system attributes - Cosmetic changes platform/mellanox: - mlxreg-hotplug: Add support for new capability register - fix potential deadlock in the tmfifo driver tools/power/x86/intel-speed-select: - Update version - Change the order for clos disable - Fix result display for turbo-freq auto mode - Add support for core-power discovery - Allow additional core-power mailbox commands - Update MAINTAINERS for the intel uncore frequency control - Add support for Uncore frequency control touchscreen_dmi: - Fix indentation in several places - Add info for the PiPO W11 tablet -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEqaflIX74DDDzMJJtb7wzTHR8rCgFAl4uxRcACgkQb7wzTHR8 rCjV3xAArz8e4FmFRe77LF83BHduBYkMjnobDFqWa+BhUicapezU4121K/k1cSBi MRhYOK3+lZvMqFTbjFatgkCapjma34+6xMJztrT/drCgmxHzsLQgJsmJ3pXWqnYM t4CcPOjvjmZbNJT0NdKjeNyCwFGG6Lupf82fVfIXIshtaKE3xw51242+PJEI978i 2VL3Ck0NL1stgUkKf/ppHkqsjLb0s6IBtgWv052s/0SlHT7RlFAonsCBxIktVa5L divCtnWJKRhbalCPnKOJ1Q6/kpR/BSNq6OddcgaACKH9i0d5KwtdNDdQ66FkEidN 4rKK3gYMLRpgpLjApH91n7jWMQUaJawVN/3WuRfdnwQOcJ/PVY5vosv2yHKMy3yB mFLG0G2v3cXEmvRNEyeKBpSkOrAnsoylFt8zLN6/OP3cQ/jdrnq+UpurxRnBEGkm ZDbs5FYqjAPMyjL+/ldhndIdIqvusVgrl2V93BuAzN080UvkQ2FKjLnk0Dkc/xmZ XbXUAn+BCUpmABstLa7NJGruV3O9IdiSLHW5Cr0NZC74h4nHqDS57At7LkQbphkC Pt/+7tirpaEvSbgQZsVI0WfOwDjJf79FT4dYtCY1GkmSvmvF+OUgKicfEZsfuDan hLez0resoJkHLeJtcrF1lW3l3kyMaokBmkUhB1skOYlLUvcsOwg= =rMop -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v5.6-1' of git://git.infradead.org/linux-platform-drivers-x86 Pull x86 platform driver updates from Andy Shevchenko: - Enable thermal policy for ASUS TUF FX705DY/FX505DY - Support left round button on ASUS N56VB - Support new Mellanox platforms of basic class VMOD0009 and VMOD0010 - Intel Comet Lake, Tiger Lake and Elkhart Lake support in the PMC driver - Big clean-up to Intel PMC core, PMC IPC and SCU IPC drivers - Touchscreen support for the PiPO W11 tablet * tag 'platform-drivers-x86-v5.6-1' of git://git.infradead.org/linux-platform-drivers-x86: (64 commits) platform/x86: intel_pmc_ipc: Switch to use driver->dev_groups platform/x86: intel_pmc_ipc: Propagate error from kstrtoul() platform/x86: intel_pmc_ipc: Use octal permissions in sysfs attributes platform/x86: intel_pmc_ipc: Get rid of unnecessary includes platform/x86: intel_pmc_ipc: Drop ipc_data_readb() platform/x86: intel_pmc_ipc: Drop intel_pmc_gcr_read() and intel_pmc_gcr_write() platform/x86: intel_pmc_ipc: Make intel_pmc_ipc_raw_cmd() static platform/x86: intel_pmc_ipc: Make intel_pmc_ipc_simple_command() static platform/x86: intel_pmc_ipc: Make intel_pmc_gcr_update() static platform/x86: intel_scu_ipc: Reformat kernel-doc comments of exported functions platform/x86: intel_scu_ipc: Drop intel_scu_ipc_raw_command() platform/x86: intel_scu_ipc: Drop intel_scu_ipc_io[read|write][8|16]() platform/x86: intel_scu_ipc: Drop unused macros platform/x86: intel_scu_ipc: Drop unused prototype intel_scu_ipc_fw_update() platform/x86: intel_scu_ipc: Sleeping is fine when polling platform/x86: intel_scu_ipc: Drop intel_scu_ipc_i2c_cntrl() platform/x86: intel_scu_ipc: Remove Lincroft support platform/x86: intel_scu_ipc: Add constants for register offsets platform/x86: intel_scu_ipc: Fix interrupt support platform/x86: intel_scu_ipcutil: Remove default y from Kconfig ...
This commit is contained in:
commit
08c49dc135
@ -1,5 +1,4 @@
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/asic_health
|
||||
|
||||
Date: June 2018
|
||||
KernelVersion: 4.19
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -19,7 +18,6 @@ Description: These files show with which CPLD versions have been burned
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/fan_dir
|
||||
|
||||
Date: December 2018
|
||||
KernelVersion: 5.0
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -30,7 +28,6 @@ Description: This file shows the system fans direction:
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version
|
||||
|
||||
Date: November 2018
|
||||
KernelVersion: 5.0
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -40,7 +37,6 @@ Description: These files show with which CPLD versions have been burned
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
|
||||
|
||||
Date: November 2018
|
||||
KernelVersion: 5.0
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -108,7 +104,6 @@ What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_pwr_fail
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_comex
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_system
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_voltmon_upgrade_fail
|
||||
|
||||
Date: November 2018
|
||||
KernelVersion: 5.0
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -130,6 +125,12 @@ Description: These files show with which CPLD versions have been burned
|
||||
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_thermal
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_wd
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_asic
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_reload_bios
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_sff_wd
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_swb_wd
|
||||
Date: June 2019
|
||||
KernelVersion: 5.3
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
@ -143,9 +144,65 @@ Description: These files show the system reset cause, as following:
|
||||
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_thermal
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_comex_wd
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_from_asic
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_reload_bios
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_sff_wd
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_swb_wd
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/config1
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/config2
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: These files show system static topology identification
|
||||
like system's static I2C topology, number and type of FPGA
|
||||
devices within the system and so on.
|
||||
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_ac_pwr_fail
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_platform
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_soc
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/reset_sw_pwr_off
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: These files show the system reset causes, as following: reset
|
||||
due to AC power failure, reset invoked from software by
|
||||
assertion reset signal through CPLD. reset caused by signal
|
||||
asserted by SOC through ACPI register, reset invoked from
|
||||
software by assertion power off signal through CPLD.
|
||||
|
||||
The files are read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pcie_asic_reset_dis
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: This file allows to retain ASIC up during PCIe root complex
|
||||
reset, when attribute is set 1.
|
||||
|
||||
The file is read/write.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/vpd_wp
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: This file allows to overwrite system VPD hardware wrtie
|
||||
protection when attribute is set 1.
|
||||
|
||||
The file is read/write.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/voltreg_update_status
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: This file exposes the configuration update status of burnable
|
||||
voltage regulator devices. The status values are as following:
|
||||
0 - OK; 1 - CRC failure; 2 = I2C failure; 3 - in progress.
|
||||
|
||||
The file is read only.
|
||||
|
||||
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ufm_version
|
||||
Date: January 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: Vadim Pasternak <vadimpmellanox.com>
|
||||
Description: This file exposes the firmware version of burnable voltage
|
||||
regulator devices.
|
||||
|
||||
The file is read only.
|
||||
|
@ -46,3 +46,13 @@ Description:
|
||||
* 0 - normal,
|
||||
* 1 - overboost,
|
||||
* 2 - silent
|
||||
|
||||
What: /sys/devices/platform/<platform>/throttle_thermal_policy
|
||||
Date: Dec 2019
|
||||
KernelVersion: 5.6
|
||||
Contact: "Leonid Maksymchuk" <leonmaxx@gmail.com>
|
||||
Description:
|
||||
Throttle thermal policy mode:
|
||||
* 0 - default,
|
||||
* 1 - overboost,
|
||||
* 2 - silent
|
||||
|
@ -8573,6 +8573,12 @@ S: Maintained
|
||||
F: arch/x86/include/asm/intel_telemetry.h
|
||||
F: drivers/platform/x86/intel_telemetry*
|
||||
|
||||
INTEL UNCORE FREQUENCY CONTROL
|
||||
M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/intel-uncore-frequency.c
|
||||
|
||||
INTEL VIRTUAL BUTTON DRIVER
|
||||
M: AceLan Kao <acelan.kao@canonical.com>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
|
@ -31,30 +31,13 @@
|
||||
|
||||
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
|
||||
|
||||
int intel_pmc_ipc_simple_command(int cmd, int sub);
|
||||
int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
u32 *out, u32 outlen, u32 dptr, u32 sptr);
|
||||
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
u32 *out, u32 outlen);
|
||||
int intel_pmc_s0ix_counter_read(u64 *data);
|
||||
int intel_pmc_gcr_read(u32 offset, u32 *data);
|
||||
int intel_pmc_gcr_read64(u32 offset, u64 *data);
|
||||
int intel_pmc_gcr_write(u32 offset, u32 data);
|
||||
int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val);
|
||||
|
||||
#else
|
||||
|
||||
static inline int intel_pmc_ipc_simple_command(int cmd, int sub)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
u32 *out, u32 outlen, u32 dptr, u32 sptr)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||
u32 *out, u32 outlen)
|
||||
{
|
||||
@ -66,26 +49,11 @@ static inline int intel_pmc_s0ix_counter_read(u64 *data)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_read(u32 offset, u32 *data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_read64(u32 offset, u64 *data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_write(u32 offset, u32 data)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#endif /*CONFIG_INTEL_PMC_IPC*/
|
||||
|
||||
#endif
|
||||
|
@ -22,24 +22,12 @@
|
||||
/* Read single register */
|
||||
int intel_scu_ipc_ioread8(u16 addr, u8 *data);
|
||||
|
||||
/* Read two sequential registers */
|
||||
int intel_scu_ipc_ioread16(u16 addr, u16 *data);
|
||||
|
||||
/* Read four sequential registers */
|
||||
int intel_scu_ipc_ioread32(u16 addr, u32 *data);
|
||||
|
||||
/* Read a vector */
|
||||
int intel_scu_ipc_readv(u16 *addr, u8 *data, int len);
|
||||
|
||||
/* Write single register */
|
||||
int intel_scu_ipc_iowrite8(u16 addr, u8 data);
|
||||
|
||||
/* Write two sequential registers */
|
||||
int intel_scu_ipc_iowrite16(u16 addr, u16 data);
|
||||
|
||||
/* Write four sequential registers */
|
||||
int intel_scu_ipc_iowrite32(u16 addr, u32 data);
|
||||
|
||||
/* Write a vector */
|
||||
int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);
|
||||
|
||||
@ -50,14 +38,6 @@ int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
|
||||
int intel_scu_ipc_simple_command(int cmd, int sub);
|
||||
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
|
||||
u32 *out, int outlen);
|
||||
int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
|
||||
u32 *out, int outlen, u32 dptr, u32 sptr);
|
||||
|
||||
/* I2C control api */
|
||||
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
|
||||
|
||||
/* Update FW version */
|
||||
int intel_scu_ipc_fw_update(u8 *buffer, u32 length);
|
||||
|
||||
extern struct blocking_notifier_head intel_scu_notifier;
|
||||
|
||||
|
@ -40,13 +40,10 @@ struct telemetry_evtmap {
|
||||
struct telemetry_unit_config {
|
||||
struct telemetry_evtmap *telem_evts;
|
||||
void __iomem *regmap;
|
||||
u32 ssram_base_addr;
|
||||
u8 ssram_evts_used;
|
||||
u8 curr_period;
|
||||
u8 max_period;
|
||||
u8 min_period;
|
||||
u32 ssram_size;
|
||||
|
||||
};
|
||||
|
||||
struct telemetry_plt_config {
|
||||
|
@ -504,6 +504,20 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
item = pdata->items;
|
||||
|
||||
for (i = 0; i < pdata->counter; i++, item++) {
|
||||
if (item->capability) {
|
||||
/*
|
||||
* Read group capability register to get actual number
|
||||
* of interrupt capable components and set group mask
|
||||
* accordingly.
|
||||
*/
|
||||
ret = regmap_read(priv->regmap, item->capability,
|
||||
®val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
item->mask = GENMASK((regval & item->mask) - 1, 0);
|
||||
}
|
||||
|
||||
/* Clear group presense event. */
|
||||
ret = regmap_write(priv->regmap, item->reg +
|
||||
MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||
|
@ -997,7 +997,6 @@ config INTEL_SCU_IPC
|
||||
config INTEL_SCU_IPC_UTIL
|
||||
tristate "Intel SCU IPC utility driver"
|
||||
depends on INTEL_SCU_IPC
|
||||
default y
|
||||
---help---
|
||||
The IPC Util driver provides an interface with the SCU enabling
|
||||
low level access for debug work and updating the firmware. Say
|
||||
@ -1299,9 +1298,9 @@ config INTEL_ATOMISP2_PM
|
||||
depends on PCI && IOSF_MBI && PM
|
||||
help
|
||||
Power-management driver for Intel's Image Signal Processor found on
|
||||
Bay and Cherry Trail devices. This dummy driver's sole purpose is to
|
||||
turn the ISP off (put it in D3) to save power and to allow entering
|
||||
of S0ix modes.
|
||||
Bay Trail and Cherry Trail devices. This dummy driver's sole purpose
|
||||
is to turn the ISP off (put it in D3) to save power and to allow
|
||||
entering of S0ix modes.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called intel_atomisp2_pm.
|
||||
@ -1337,6 +1336,17 @@ config PCENGINES_APU2
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pcengines-apuv2.
|
||||
|
||||
config INTEL_UNCORE_FREQ_CONTROL
|
||||
tristate "Intel Uncore frequency control driver"
|
||||
depends on X86_64
|
||||
help
|
||||
This driver allows control of uncore frequency limits on
|
||||
supported server platforms.
|
||||
Uncore frequency controls RING/LLC (last-level cache) clocks.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called intel-uncore-frequency.
|
||||
|
||||
source "drivers/platform/x86/intel_speed_select_if/Kconfig"
|
||||
|
||||
config SYSTEM76_ACPI
|
||||
|
@ -105,3 +105,4 @@ obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o
|
||||
obj-$(CONFIG_PCENGINES_APU2) += pcengines-apuv2.o
|
||||
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += intel_speed_select_if/
|
||||
obj-$(CONFIG_SYSTEM76_ACPI) += system76_acpi.o
|
||||
obj-$(CONFIG_INTEL_UNCORE_FREQ_CONTROL) += intel-uncore-frequency.o
|
||||
|
@ -471,6 +471,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
|
||||
{ KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */
|
||||
{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
|
||||
{ KE_IGNORE, 0x6E, }, /* Low Battery notification */
|
||||
{ KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */
|
||||
{ KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
|
||||
{ KE_KEY, 0x7c, { KEY_MICMUTE } },
|
||||
{ KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
|
||||
|
@ -61,6 +61,7 @@ MODULE_LICENSE("GPL");
|
||||
#define NOTIFY_KBD_BRTDWN 0xc5
|
||||
#define NOTIFY_KBD_BRTTOGGLE 0xc7
|
||||
#define NOTIFY_KBD_FBM 0x99
|
||||
#define NOTIFY_KBD_TTP 0xae
|
||||
|
||||
#define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0)
|
||||
|
||||
@ -81,6 +82,10 @@ MODULE_LICENSE("GPL");
|
||||
#define ASUS_FAN_BOOST_MODE_SILENT_MASK 0x02
|
||||
#define ASUS_FAN_BOOST_MODES_MASK 0x03
|
||||
|
||||
#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT 0
|
||||
#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1
|
||||
#define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2
|
||||
|
||||
#define USB_INTEL_XUSB2PR 0xD0
|
||||
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
|
||||
|
||||
@ -198,6 +203,9 @@ struct asus_wmi {
|
||||
u8 fan_boost_mode_mask;
|
||||
u8 fan_boost_mode;
|
||||
|
||||
bool throttle_thermal_policy_available;
|
||||
u8 throttle_thermal_policy_mode;
|
||||
|
||||
// The RSOC controls the maximum charging percentage.
|
||||
bool battery_rsoc_available;
|
||||
|
||||
@ -1718,6 +1726,107 @@ static ssize_t fan_boost_mode_store(struct device *dev,
|
||||
// Fan boost mode: 0 - normal, 1 - overboost, 2 - silent
|
||||
static DEVICE_ATTR_RW(fan_boost_mode);
|
||||
|
||||
/* Throttle thermal policy ****************************************************/
|
||||
|
||||
static int throttle_thermal_policy_check_present(struct asus_wmi *asus)
|
||||
{
|
||||
u32 result;
|
||||
int err;
|
||||
|
||||
asus->throttle_thermal_policy_available = false;
|
||||
|
||||
err = asus_wmi_get_devstate(asus,
|
||||
ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
|
||||
&result);
|
||||
if (err) {
|
||||
if (err == -ENODEV)
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (result & ASUS_WMI_DSTS_PRESENCE_BIT)
|
||||
asus->throttle_thermal_policy_available = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int throttle_thermal_policy_write(struct asus_wmi *asus)
|
||||
{
|
||||
int err;
|
||||
u8 value;
|
||||
u32 retval;
|
||||
|
||||
value = asus->throttle_thermal_policy_mode;
|
||||
|
||||
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
|
||||
value, &retval);
|
||||
if (err) {
|
||||
pr_warn("Failed to set throttle thermal policy: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (retval != 1) {
|
||||
pr_warn("Failed to set throttle thermal policy (retval): 0x%x\n",
|
||||
retval);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int throttle_thermal_policy_set_default(struct asus_wmi *asus)
|
||||
{
|
||||
if (!asus->throttle_thermal_policy_available)
|
||||
return 0;
|
||||
|
||||
asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
|
||||
return throttle_thermal_policy_write(asus);
|
||||
}
|
||||
|
||||
static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)
|
||||
{
|
||||
u8 new_mode = asus->throttle_thermal_policy_mode + 1;
|
||||
|
||||
if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
|
||||
new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;
|
||||
|
||||
asus->throttle_thermal_policy_mode = new_mode;
|
||||
return throttle_thermal_policy_write(asus);
|
||||
}
|
||||
|
||||
static ssize_t throttle_thermal_policy_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
u8 mode = asus->throttle_thermal_policy_mode;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", mode);
|
||||
}
|
||||
|
||||
static ssize_t throttle_thermal_policy_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int result;
|
||||
u8 new_mode;
|
||||
struct asus_wmi *asus = dev_get_drvdata(dev);
|
||||
|
||||
result = kstrtou8(buf, 10, &new_mode);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT)
|
||||
return -EINVAL;
|
||||
|
||||
asus->throttle_thermal_policy_mode = new_mode;
|
||||
throttle_thermal_policy_write(asus);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent
|
||||
static DEVICE_ATTR_RW(throttle_thermal_policy);
|
||||
|
||||
/* Backlight ******************************************************************/
|
||||
|
||||
static int read_backlight_power(struct asus_wmi *asus)
|
||||
@ -1999,6 +2108,11 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
|
||||
return;
|
||||
}
|
||||
|
||||
if (asus->throttle_thermal_policy_available && code == NOTIFY_KBD_TTP) {
|
||||
throttle_thermal_policy_switch_next(asus);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_display_toggle(code) && asus->driver->quirks->no_display_toggle)
|
||||
return;
|
||||
|
||||
@ -2149,6 +2263,7 @@ static struct attribute *platform_attributes[] = {
|
||||
&dev_attr_lid_resume.attr,
|
||||
&dev_attr_als_enable.attr,
|
||||
&dev_attr_fan_boost_mode.attr,
|
||||
&dev_attr_throttle_thermal_policy.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -2172,6 +2287,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
|
||||
devid = ASUS_WMI_DEVID_ALS_ENABLE;
|
||||
else if (attr == &dev_attr_fan_boost_mode.attr)
|
||||
ok = asus->fan_boost_mode_available;
|
||||
else if (attr == &dev_attr_throttle_thermal_policy.attr)
|
||||
ok = asus->throttle_thermal_policy_available;
|
||||
|
||||
if (devid != -1)
|
||||
ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
|
||||
@ -2431,6 +2548,12 @@ static int asus_wmi_add(struct platform_device *pdev)
|
||||
if (err)
|
||||
goto fail_fan_boost_mode;
|
||||
|
||||
err = throttle_thermal_policy_check_present(asus);
|
||||
if (err)
|
||||
goto fail_throttle_thermal_policy;
|
||||
else
|
||||
throttle_thermal_policy_set_default(asus);
|
||||
|
||||
err = asus_wmi_sysfs_init(asus->platform_device);
|
||||
if (err)
|
||||
goto fail_sysfs;
|
||||
@ -2515,6 +2638,7 @@ fail_hwmon:
|
||||
fail_input:
|
||||
asus_wmi_sysfs_exit(asus->platform_device);
|
||||
fail_sysfs:
|
||||
fail_throttle_thermal_policy:
|
||||
fail_fan_boost_mode:
|
||||
fail_platform:
|
||||
kfree(asus);
|
||||
|
437
drivers/platform/x86/intel-uncore-frequency.c
Normal file
437
drivers/platform/x86/intel-uncore-frequency.c
Normal file
@ -0,0 +1,437 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Intel Uncore Frequency Setting
|
||||
* Copyright (c) 2019, Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Provide interface to set MSR 620 at a granularity of per die. On CPU online,
|
||||
* one control CPU is identified per die to read/write limit. This control CPU
|
||||
* is changed, if the CPU state is changed to offline. When the last CPU is
|
||||
* offline in a die then remove the sysfs object for that die.
|
||||
* The majority of actual code is related to sysfs create and read/write
|
||||
* attributes.
|
||||
*
|
||||
* Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
|
||||
#define MSR_UNCORE_RATIO_LIMIT 0x620
|
||||
#define UNCORE_FREQ_KHZ_MULTIPLIER 100000
|
||||
|
||||
/**
|
||||
* struct uncore_data - Encapsulate all uncore data
|
||||
* @stored_uncore_data: Last user changed MSR 620 value, which will be restored
|
||||
* on system resume.
|
||||
* @initial_min_freq_khz: Sampled minimum uncore frequency at driver init
|
||||
* @initial_max_freq_khz: Sampled maximum uncore frequency at driver init
|
||||
* @control_cpu: Designated CPU for a die to read/write
|
||||
* @valid: Mark the data valid/invalid
|
||||
*
|
||||
* This structure is used to encapsulate all data related to uncore sysfs
|
||||
* settings for a die/package.
|
||||
*/
|
||||
struct uncore_data {
|
||||
struct kobject kobj;
|
||||
u64 stored_uncore_data;
|
||||
u32 initial_min_freq_khz;
|
||||
u32 initial_max_freq_khz;
|
||||
int control_cpu;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
#define to_uncore_data(a) container_of(a, struct uncore_data, kobj)
|
||||
|
||||
/* Max instances for uncore data, one for each die */
|
||||
static int uncore_max_entries __read_mostly;
|
||||
/* Storage for uncore data for all instances */
|
||||
static struct uncore_data *uncore_instances;
|
||||
/* Root of the all uncore sysfs kobjs */
|
||||
struct kobject uncore_root_kobj;
|
||||
/* Stores the CPU mask of the target CPUs to use during uncore read/write */
|
||||
static cpumask_t uncore_cpu_mask;
|
||||
/* CPU online callback register instance */
|
||||
static enum cpuhp_state uncore_hp_state __read_mostly;
|
||||
/* Mutex to control all mutual exclusions */
|
||||
static DEFINE_MUTEX(uncore_lock);
|
||||
|
||||
struct uncore_attr {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct kobject *kobj,
|
||||
struct attribute *attr, char *buf);
|
||||
ssize_t (*store)(struct kobject *kobj,
|
||||
struct attribute *attr, const char *c, ssize_t count);
|
||||
};
|
||||
|
||||
#define define_one_uncore_ro(_name) \
|
||||
static struct uncore_attr _name = \
|
||||
__ATTR(_name, 0444, show_##_name, NULL)
|
||||
|
||||
#define define_one_uncore_rw(_name) \
|
||||
static struct uncore_attr _name = \
|
||||
__ATTR(_name, 0644, show_##_name, store_##_name)
|
||||
|
||||
#define show_uncore_data(member_name) \
|
||||
static ssize_t show_##member_name(struct kobject *kobj, \
|
||||
struct attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct uncore_data *data = to_uncore_data(kobj); \
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", \
|
||||
data->member_name); \
|
||||
} \
|
||||
define_one_uncore_ro(member_name)
|
||||
|
||||
show_uncore_data(initial_min_freq_khz);
|
||||
show_uncore_data(initial_max_freq_khz);
|
||||
|
||||
/* Common function to read MSR 0x620 and read min/max */
|
||||
static int uncore_read_ratio(struct uncore_data *data, unsigned int *min,
|
||||
unsigned int *max)
|
||||
{
|
||||
u64 cap;
|
||||
int ret;
|
||||
|
||||
ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*max = (cap & 0x7F) * UNCORE_FREQ_KHZ_MULTIPLIER;
|
||||
*min = ((cap & GENMASK(14, 8)) >> 8) * UNCORE_FREQ_KHZ_MULTIPLIER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Common function to set min/max ratios to be used by sysfs callbacks */
|
||||
static int uncore_write_ratio(struct uncore_data *data, unsigned int input,
|
||||
int set_max)
|
||||
{
|
||||
int ret;
|
||||
u64 cap;
|
||||
|
||||
mutex_lock(&uncore_lock);
|
||||
|
||||
input /= UNCORE_FREQ_KHZ_MULTIPLIER;
|
||||
if (!input || input > 0x7F) {
|
||||
ret = -EINVAL;
|
||||
goto finish_write;
|
||||
}
|
||||
|
||||
ret = rdmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, &cap);
|
||||
if (ret)
|
||||
goto finish_write;
|
||||
|
||||
if (set_max) {
|
||||
cap &= ~0x7F;
|
||||
cap |= input;
|
||||
} else {
|
||||
cap &= ~GENMASK(14, 8);
|
||||
cap |= (input << 8);
|
||||
}
|
||||
|
||||
ret = wrmsrl_on_cpu(data->control_cpu, MSR_UNCORE_RATIO_LIMIT, cap);
|
||||
if (ret)
|
||||
goto finish_write;
|
||||
|
||||
data->stored_uncore_data = cap;
|
||||
|
||||
finish_write:
|
||||
mutex_unlock(&uncore_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t store_min_max_freq_khz(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
const char *buf, ssize_t count,
|
||||
int min_max)
|
||||
{
|
||||
struct uncore_data *data = to_uncore_data(kobj);
|
||||
unsigned int input;
|
||||
|
||||
if (kstrtouint(buf, 10, &input))
|
||||
return -EINVAL;
|
||||
|
||||
uncore_write_ratio(data, input, min_max);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_min_max_freq_khz(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
char *buf, int min_max)
|
||||
{
|
||||
struct uncore_data *data = to_uncore_data(kobj);
|
||||
unsigned int min, max;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&uncore_lock);
|
||||
ret = uncore_read_ratio(data, &min, &max);
|
||||
mutex_unlock(&uncore_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (min_max)
|
||||
return sprintf(buf, "%u\n", max);
|
||||
|
||||
return sprintf(buf, "%u\n", min);
|
||||
}
|
||||
|
||||
#define store_uncore_min_max(name, min_max) \
|
||||
static ssize_t store_##name(struct kobject *kobj, \
|
||||
struct attribute *attr, \
|
||||
const char *buf, ssize_t count) \
|
||||
{ \
|
||||
\
|
||||
return store_min_max_freq_khz(kobj, attr, buf, count, \
|
||||
min_max); \
|
||||
}
|
||||
|
||||
#define show_uncore_min_max(name, min_max) \
|
||||
static ssize_t show_##name(struct kobject *kobj, \
|
||||
struct attribute *attr, char *buf) \
|
||||
{ \
|
||||
\
|
||||
return show_min_max_freq_khz(kobj, attr, buf, min_max); \
|
||||
}
|
||||
|
||||
store_uncore_min_max(min_freq_khz, 0);
|
||||
store_uncore_min_max(max_freq_khz, 1);
|
||||
|
||||
show_uncore_min_max(min_freq_khz, 0);
|
||||
show_uncore_min_max(max_freq_khz, 1);
|
||||
|
||||
define_one_uncore_rw(min_freq_khz);
|
||||
define_one_uncore_rw(max_freq_khz);
|
||||
|
||||
static struct attribute *uncore_attrs[] = {
|
||||
&initial_min_freq_khz.attr,
|
||||
&initial_max_freq_khz.attr,
|
||||
&max_freq_khz.attr,
|
||||
&min_freq_khz.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct kobj_type uncore_ktype = {
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
.default_attrs = uncore_attrs,
|
||||
};
|
||||
|
||||
static struct kobj_type uncore_root_ktype = {
|
||||
.sysfs_ops = &kobj_sysfs_ops,
|
||||
};
|
||||
|
||||
/* Caller provides protection */
|
||||
static struct uncore_data *uncore_get_instance(unsigned int cpu)
|
||||
{
|
||||
int id = topology_logical_die_id(cpu);
|
||||
|
||||
if (id >= 0 && id < uncore_max_entries)
|
||||
return &uncore_instances[id];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uncore_add_die_entry(int cpu)
|
||||
{
|
||||
struct uncore_data *data;
|
||||
|
||||
mutex_lock(&uncore_lock);
|
||||
data = uncore_get_instance(cpu);
|
||||
if (!data) {
|
||||
mutex_unlock(&uncore_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->valid) {
|
||||
/* control cpu changed */
|
||||
data->control_cpu = cpu;
|
||||
} else {
|
||||
char str[64];
|
||||
int ret;
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
sprintf(str, "package_%02d_die_%02d",
|
||||
topology_physical_package_id(cpu),
|
||||
topology_die_id(cpu));
|
||||
|
||||
uncore_read_ratio(data, &data->initial_min_freq_khz,
|
||||
&data->initial_max_freq_khz);
|
||||
|
||||
ret = kobject_init_and_add(&data->kobj, &uncore_ktype,
|
||||
&uncore_root_kobj, str);
|
||||
if (!ret) {
|
||||
data->control_cpu = cpu;
|
||||
data->valid = true;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&uncore_lock);
|
||||
}
|
||||
|
||||
/* Last CPU in this die is offline, so remove sysfs entries */
|
||||
static void uncore_remove_die_entry(int cpu)
|
||||
{
|
||||
struct uncore_data *data;
|
||||
|
||||
mutex_lock(&uncore_lock);
|
||||
data = uncore_get_instance(cpu);
|
||||
if (data) {
|
||||
kobject_put(&data->kobj);
|
||||
data->control_cpu = -1;
|
||||
data->valid = false;
|
||||
}
|
||||
mutex_unlock(&uncore_lock);
|
||||
}
|
||||
|
||||
static int uncore_event_cpu_online(unsigned int cpu)
|
||||
{
|
||||
int target;
|
||||
|
||||
/* Check if there is an online cpu in the package for uncore MSR */
|
||||
target = cpumask_any_and(&uncore_cpu_mask, topology_die_cpumask(cpu));
|
||||
if (target < nr_cpu_ids)
|
||||
return 0;
|
||||
|
||||
/* Use this CPU on this die as a control CPU */
|
||||
cpumask_set_cpu(cpu, &uncore_cpu_mask);
|
||||
uncore_add_die_entry(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uncore_event_cpu_offline(unsigned int cpu)
|
||||
{
|
||||
int target;
|
||||
|
||||
/* Check if existing cpu is used for uncore MSRs */
|
||||
if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
|
||||
return 0;
|
||||
|
||||
/* Find a new cpu to set uncore MSR */
|
||||
target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
|
||||
|
||||
if (target < nr_cpu_ids) {
|
||||
cpumask_set_cpu(target, &uncore_cpu_mask);
|
||||
uncore_add_die_entry(target);
|
||||
} else {
|
||||
uncore_remove_die_entry(cpu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uncore_pm_notify(struct notifier_block *nb, unsigned long mode,
|
||||
void *_unused)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
switch (mode) {
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_RESTORE:
|
||||
case PM_POST_SUSPEND:
|
||||
for_each_cpu(cpu, &uncore_cpu_mask) {
|
||||
struct uncore_data *data;
|
||||
int ret;
|
||||
|
||||
data = uncore_get_instance(cpu);
|
||||
if (!data || !data->valid || !data->stored_uncore_data)
|
||||
continue;
|
||||
|
||||
ret = wrmsrl_on_cpu(cpu, MSR_UNCORE_RATIO_LIMIT,
|
||||
data->stored_uncore_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block uncore_pm_nb = {
|
||||
.notifier_call = uncore_pm_notify,
|
||||
};
|
||||
|
||||
#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
|
||||
|
||||
static const struct x86_cpu_id intel_uncore_cpu_ids[] = {
|
||||
ICPU(INTEL_FAM6_BROADWELL_G),
|
||||
ICPU(INTEL_FAM6_BROADWELL_X),
|
||||
ICPU(INTEL_FAM6_BROADWELL_D),
|
||||
ICPU(INTEL_FAM6_SKYLAKE_X),
|
||||
ICPU(INTEL_FAM6_ICELAKE_X),
|
||||
ICPU(INTEL_FAM6_ICELAKE_D),
|
||||
{}
|
||||
};
|
||||
|
||||
static int __init intel_uncore_init(void)
|
||||
{
|
||||
const struct x86_cpu_id *id;
|
||||
int ret;
|
||||
|
||||
id = x86_match_cpu(intel_uncore_cpu_ids);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
uncore_max_entries = topology_max_packages() *
|
||||
topology_max_die_per_package();
|
||||
uncore_instances = kcalloc(uncore_max_entries,
|
||||
sizeof(*uncore_instances), GFP_KERNEL);
|
||||
if (!uncore_instances)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = kobject_init_and_add(&uncore_root_kobj, &uncore_root_ktype,
|
||||
&cpu_subsys.dev_root->kobj,
|
||||
"intel_uncore_frequency");
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
||||
"platform/x86/uncore-freq:online",
|
||||
uncore_event_cpu_online,
|
||||
uncore_event_cpu_offline);
|
||||
if (ret < 0)
|
||||
goto err_rem_kobj;
|
||||
|
||||
uncore_hp_state = ret;
|
||||
|
||||
ret = register_pm_notifier(&uncore_pm_nb);
|
||||
if (ret)
|
||||
goto err_rem_state;
|
||||
|
||||
return 0;
|
||||
|
||||
err_rem_state:
|
||||
cpuhp_remove_state(uncore_hp_state);
|
||||
err_rem_kobj:
|
||||
kobject_put(&uncore_root_kobj);
|
||||
err_free:
|
||||
kfree(uncore_instances);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(intel_uncore_init)
|
||||
|
||||
static void __exit intel_uncore_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
unregister_pm_notifier(&uncore_pm_nb);
|
||||
cpuhp_remove_state(uncore_hp_state);
|
||||
for (i = 0; i < uncore_max_entries; ++i) {
|
||||
if (uncore_instances[i].valid)
|
||||
kobject_put(&uncore_instances[i].kobj);
|
||||
}
|
||||
kobject_put(&uncore_root_kobj);
|
||||
kfree(uncore_instances);
|
||||
}
|
||||
module_exit(intel_uncore_exit)
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Intel Uncore Frequency Limits Driver");
|
@ -1,8 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Dummy driver for Intel's Image Signal Processor found on Bay and Cherry
|
||||
* Trail devices. The sole purpose of this driver is to allow the ISP to
|
||||
* be put in D3.
|
||||
* Dummy driver for Intel's Image Signal Processor found on Bay Trail
|
||||
* and Cherry Trail devices. The sole purpose of this driver is to allow
|
||||
* the ISP to be put in D3.
|
||||
*
|
||||
* Copyright (C) 2018 Hans de Goede <hdegoede@redhat.com>
|
||||
*
|
||||
@ -36,8 +36,7 @@
|
||||
static int isp_set_power(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
unsigned long timeout;
|
||||
u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON :
|
||||
ISPSSPM0_IUNIT_POWER_OFF;
|
||||
u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON : ISPSSPM0_IUNIT_POWER_OFF;
|
||||
|
||||
/* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */
|
||||
iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0,
|
||||
@ -45,29 +44,25 @@ static int isp_set_power(struct pci_dev *dev, bool enable)
|
||||
|
||||
/*
|
||||
* There should be no IUNIT access while power-down is
|
||||
* in progress HW sighting: 4567865
|
||||
* in progress. HW sighting: 4567865.
|
||||
* Wait up to 50 ms for the IUNIT to shut down.
|
||||
* And we do the same for power on.
|
||||
*/
|
||||
timeout = jiffies + msecs_to_jiffies(50);
|
||||
while (1) {
|
||||
do {
|
||||
u32 tmp;
|
||||
|
||||
/* Wait until ISPSSPM0 bit[25:24] shows the right value */
|
||||
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &tmp);
|
||||
tmp = (tmp & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
|
||||
if (tmp == val)
|
||||
break;
|
||||
return 0;
|
||||
|
||||
if (time_after(jiffies, timeout)) {
|
||||
dev_err(&dev->dev, "IUNIT power-%s timeout.\n",
|
||||
enable ? "on" : "off");
|
||||
return -EBUSY;
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
return 0;
|
||||
dev_err(&dev->dev, "IUNIT power-%s timeout.\n", enable ? "on" : "off");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
@ -146,9 +146,10 @@ static int mid_pb_probe(struct platform_device *pdev)
|
||||
|
||||
input_set_capability(input, EV_KEY, KEY_POWER);
|
||||
|
||||
ddata = (struct mid_pb_ddata *)id->driver_data;
|
||||
ddata = devm_kmemdup(&pdev->dev, (void *)id->driver_data,
|
||||
sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENODATA;
|
||||
return -ENOMEM;
|
||||
|
||||
ddata->dev = &pdev->dev;
|
||||
ddata->irq = irq;
|
||||
|
@ -49,7 +49,7 @@ static const struct pmc_bit_map spt_pll_map[] = {
|
||||
{"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1},
|
||||
{"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2},
|
||||
{"SATA PLL", SPT_PMC_BIT_MPHY_CMN_LANE3},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map spt_mphy_map[] = {
|
||||
@ -69,7 +69,7 @@ static const struct pmc_bit_map spt_mphy_map[] = {
|
||||
{"MPHY CORE LANE 13", SPT_PMC_BIT_MPHY_LANE13},
|
||||
{"MPHY CORE LANE 14", SPT_PMC_BIT_MPHY_LANE14},
|
||||
{"MPHY CORE LANE 15", SPT_PMC_BIT_MPHY_LANE15},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map spt_pfear_map[] = {
|
||||
@ -113,7 +113,12 @@ static const struct pmc_bit_map spt_pfear_map[] = {
|
||||
{"CSME_SMS1", SPT_PMC_BIT_CSME_SMS1},
|
||||
{"CSME_RTC", SPT_PMC_BIT_CSME_RTC},
|
||||
{"CSME_PSF", SPT_PMC_BIT_CSME_PSF},
|
||||
{},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ext_spt_pfear_map[] = {
|
||||
spt_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map spt_ltr_show_map[] = {
|
||||
@ -142,7 +147,7 @@ static const struct pmc_bit_map spt_ltr_show_map[] = {
|
||||
};
|
||||
|
||||
static const struct pmc_reg_map spt_reg_map = {
|
||||
.pfear_sts = spt_pfear_map,
|
||||
.pfear_sts = ext_spt_pfear_map,
|
||||
.mphy_sts = spt_mphy_map,
|
||||
.pll_sts = spt_pll_map,
|
||||
.ltr_show_sts = spt_ltr_show_map,
|
||||
@ -186,7 +191,10 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
|
||||
{"SDX", BIT(4)},
|
||||
{"SPE", BIT(5)},
|
||||
{"Fuse", BIT(6)},
|
||||
/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
|
||||
/*
|
||||
* Reserved for Cannon Lake but valid for Ice Lake, Comet Lake,
|
||||
* Tiger Lake and Elkhart Lake.
|
||||
*/
|
||||
{"SBR8", BIT(7)},
|
||||
|
||||
{"CSME_FSC", BIT(0)},
|
||||
@ -230,11 +238,22 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
|
||||
{"HDA_PGD4", BIT(2)},
|
||||
{"HDA_PGD5", BIT(3)},
|
||||
{"HDA_PGD6", BIT(4)},
|
||||
/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
|
||||
/*
|
||||
* Reserved for Cannon Lake but valid for Ice Lake, Comet Lake,
|
||||
* Tiger Lake and ELkhart Lake.
|
||||
*/
|
||||
{"PSF6", BIT(5)},
|
||||
{"PSF7", BIT(6)},
|
||||
{"PSF8", BIT(7)},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ext_cnp_pfear_map[] = {
|
||||
cnp_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map icl_pfear_map[] = {
|
||||
/* Ice Lake generation onwards only */
|
||||
{"RES_65", BIT(0)},
|
||||
{"RES_66", BIT(1)},
|
||||
@ -247,6 +266,30 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ext_icl_pfear_map[] = {
|
||||
cnp_pfear_map,
|
||||
icl_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map tgl_pfear_map[] = {
|
||||
/* Tiger Lake and Elkhart Lake generation onwards only */
|
||||
{"PSF9", BIT(0)},
|
||||
{"RES_66", BIT(1)},
|
||||
{"RES_67", BIT(2)},
|
||||
{"RES_68", BIT(3)},
|
||||
{"RES_69", BIT(4)},
|
||||
{"RES_70", BIT(5)},
|
||||
{"TBTLSX", BIT(6)},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map *ext_tgl_pfear_map[] = {
|
||||
cnp_pfear_map,
|
||||
tgl_pfear_map,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
|
||||
{"AUDIO_D3", BIT(0)},
|
||||
{"OTG_D3", BIT(1)},
|
||||
@ -300,7 +343,7 @@ static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
|
||||
cnp_slps0_dbg0_map,
|
||||
cnp_slps0_dbg1_map,
|
||||
cnp_slps0_dbg2_map,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct pmc_bit_map cnp_ltr_show_map[] = {
|
||||
@ -334,7 +377,7 @@ static const struct pmc_bit_map cnp_ltr_show_map[] = {
|
||||
};
|
||||
|
||||
static const struct pmc_reg_map cnp_reg_map = {
|
||||
.pfear_sts = cnp_pfear_map,
|
||||
.pfear_sts = ext_cnp_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slps0_dbg_maps = cnp_slps0_dbg_maps,
|
||||
.ltr_show_sts = cnp_ltr_show_map,
|
||||
@ -350,7 +393,7 @@ static const struct pmc_reg_map cnp_reg_map = {
|
||||
};
|
||||
|
||||
static const struct pmc_reg_map icl_reg_map = {
|
||||
.pfear_sts = cnp_pfear_map,
|
||||
.pfear_sts = ext_icl_pfear_map,
|
||||
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
|
||||
.slps0_dbg_maps = cnp_slps0_dbg_maps,
|
||||
.ltr_show_sts = cnp_ltr_show_map,
|
||||
@ -365,18 +408,29 @@ static const struct pmc_reg_map icl_reg_map = {
|
||||
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
|
||||
};
|
||||
|
||||
static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset)
|
||||
{
|
||||
return readb(pmcdev->regbase + offset);
|
||||
}
|
||||
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,
|
||||
.slps0_dbg_maps = cnp_slps0_dbg_maps,
|
||||
.ltr_show_sts = cnp_ltr_show_map,
|
||||
.msr_sts = msr_map,
|
||||
.slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
|
||||
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
|
||||
.regmap_length = CNP_PMC_MMIO_REG_LEN,
|
||||
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
|
||||
.ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES,
|
||||
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
|
||||
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
|
||||
.ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED,
|
||||
};
|
||||
|
||||
static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
|
||||
{
|
||||
return readl(pmcdev->regbase + reg_offset);
|
||||
}
|
||||
|
||||
static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int
|
||||
reg_offset, u32 val)
|
||||
static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset,
|
||||
u32 val)
|
||||
{
|
||||
writel(val, pmcdev->regbase + reg_offset);
|
||||
}
|
||||
@ -412,20 +466,25 @@ static int pmc_core_check_read_lock_bit(void)
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
static bool slps0_dbg_latch;
|
||||
|
||||
static void pmc_core_display_map(struct seq_file *s, int index,
|
||||
u8 pf_reg, const struct pmc_bit_map *pf_map)
|
||||
static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset)
|
||||
{
|
||||
return readb(pmcdev->regbase + offset);
|
||||
}
|
||||
|
||||
static void pmc_core_display_map(struct seq_file *s, int index, int idx, int ip,
|
||||
u8 pf_reg, const struct pmc_bit_map **pf_map)
|
||||
{
|
||||
seq_printf(s, "PCH IP: %-2d - %-32s\tState: %s\n",
|
||||
index, pf_map[index].name,
|
||||
pf_map[index].bit_mask & pf_reg ? "Off" : "On");
|
||||
ip, pf_map[idx][index].name,
|
||||
pf_map[idx][index].bit_mask & pf_reg ? "Off" : "On");
|
||||
}
|
||||
|
||||
static int pmc_core_ppfear_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct pmc_dev *pmcdev = s->private;
|
||||
const struct pmc_bit_map *map = pmcdev->map->pfear_sts;
|
||||
const struct pmc_bit_map **maps = pmcdev->map->pfear_sts;
|
||||
u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES];
|
||||
int index, iter;
|
||||
int index, iter, idx, ip = 0;
|
||||
|
||||
iter = pmcdev->map->ppfear0_offset;
|
||||
|
||||
@ -433,9 +492,12 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused)
|
||||
index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++)
|
||||
pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter);
|
||||
|
||||
for (index = 0; map[index].name &&
|
||||
index < pmcdev->map->ppfear_buckets * 8; index++)
|
||||
pmc_core_display_map(s, index, pf_regs[index / 8], map);
|
||||
for (idx = 0; maps[idx]; idx++) {
|
||||
for (index = 0; maps[idx][index].name &&
|
||||
index < pmcdev->map->ppfear_buckets * 8; ip++, index++)
|
||||
pmc_core_display_map(s, index, idx, ip,
|
||||
pf_regs[index / 8], maps);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -561,21 +623,22 @@ out_unlock:
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(pmc_core_pll);
|
||||
|
||||
static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
|
||||
*userbuf, size_t count, loff_t *ppos)
|
||||
static ssize_t pmc_core_ltr_ignore_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct pmc_dev *pmcdev = &pmc;
|
||||
const struct pmc_reg_map *map = pmcdev->map;
|
||||
u32 val, buf_size, fd;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
buf_size = count < 64 ? count : 64;
|
||||
mutex_lock(&pmcdev->lock);
|
||||
|
||||
if (kstrtou32_from_user(userbuf, buf_size, 10, &val)) {
|
||||
err = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
err = kstrtou32_from_user(userbuf, buf_size, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mutex_lock(&pmcdev->lock);
|
||||
|
||||
if (val > map->ltr_ignore_max) {
|
||||
err = -EINVAL;
|
||||
@ -767,8 +830,9 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
|
||||
debugfs_create_file("slp_s0_residency_usec", 0444, dir, pmcdev,
|
||||
&pmc_core_dev_state);
|
||||
|
||||
debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev,
|
||||
&pmc_core_ppfear_fops);
|
||||
if (pmcdev->map->pfear_sts)
|
||||
debugfs_create_file("pch_ip_power_gating_status", 0444, dir,
|
||||
pmcdev, &pmc_core_ppfear_fops);
|
||||
|
||||
debugfs_create_file("ltr_ignore", 0644, dir, pmcdev,
|
||||
&pmc_core_ltr_ignore_ops);
|
||||
@ -816,19 +880,22 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
|
||||
INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map),
|
||||
INTEL_CPU_FAM6(COMETLAKE, cnp_reg_map),
|
||||
INTEL_CPU_FAM6(COMETLAKE_L, cnp_reg_map),
|
||||
INTEL_CPU_FAM6(TIGERLAKE_L, tgl_reg_map),
|
||||
INTEL_CPU_FAM6(TIGERLAKE, tgl_reg_map),
|
||||
INTEL_CPU_FAM6(ATOM_TREMONT, tgl_reg_map),
|
||||
{}
|
||||
};
|
||||
|
||||
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), 0},
|
||||
{ 0, },
|
||||
{ PCI_VDEVICE(INTEL, SPT_PMC_PCI_DEVICE_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* This quirk can be used on those platforms where
|
||||
* the platform BIOS enforces 24Mhx Crystal to shutdown
|
||||
* the platform BIOS enforces 24Mhz crystal to shutdown
|
||||
* before PMC can assert SLP_S0#.
|
||||
*/
|
||||
static int quirk_xtal_ignore(const struct dmi_system_id *id)
|
||||
|
@ -186,6 +186,8 @@ enum ppfear_regs {
|
||||
#define ICL_NUM_IP_IGN_ALLOWED 20
|
||||
#define ICL_PMC_LTR_WIGIG 0x1BFC
|
||||
|
||||
#define TGL_NUM_IP_IGN_ALLOWED 22
|
||||
|
||||
struct pmc_bit_map {
|
||||
const char *name;
|
||||
u32 bit_mask;
|
||||
@ -213,7 +215,7 @@ struct pmc_bit_map {
|
||||
* captures them to have a common implementation.
|
||||
*/
|
||||
struct pmc_reg_map {
|
||||
const struct pmc_bit_map *pfear_sts;
|
||||
const struct pmc_bit_map **pfear_sts;
|
||||
const struct pmc_bit_map *mphy_sts;
|
||||
const struct pmc_bit_map *pll_sts;
|
||||
const struct pmc_bit_map **slps0_dbg_maps;
|
||||
|
@ -12,23 +12,13 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include <asm/intel_pmc_ipc.h>
|
||||
|
||||
@ -184,11 +174,6 @@ static inline void ipc_data_writel(u32 data, u32 offset)
|
||||
writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset);
|
||||
}
|
||||
|
||||
static inline u8 __maybe_unused ipc_data_readb(u32 offset)
|
||||
{
|
||||
return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
|
||||
}
|
||||
|
||||
static inline u32 ipc_data_readl(u32 offset)
|
||||
{
|
||||
return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
|
||||
@ -210,35 +195,6 @@ static inline int is_gcr_valid(u32 offset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_pmc_gcr_read() - Read a 32-bit PMC GCR register
|
||||
* @offset: offset of GCR register from GCR address base
|
||||
* @data: data pointer for storing the register output
|
||||
*
|
||||
* Reads the 32-bit PMC GCR register at given offset.
|
||||
*
|
||||
* Return: negative value on error or 0 on success.
|
||||
*/
|
||||
int intel_pmc_gcr_read(u32 offset, u32 *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock(&ipcdev.gcr_lock);
|
||||
|
||||
ret = is_gcr_valid(offset);
|
||||
if (ret < 0) {
|
||||
spin_unlock(&ipcdev.gcr_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*data = readl(ipcdev.gcr_mem_base + offset);
|
||||
|
||||
spin_unlock(&ipcdev.gcr_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_gcr_read);
|
||||
|
||||
/**
|
||||
* intel_pmc_gcr_read64() - Read a 64-bit PMC GCR register
|
||||
* @offset: offset of GCR register from GCR address base
|
||||
@ -268,36 +224,6 @@ int intel_pmc_gcr_read64(u32 offset, u64 *data)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_gcr_read64);
|
||||
|
||||
/**
|
||||
* intel_pmc_gcr_write() - Write PMC GCR register
|
||||
* @offset: offset of GCR register from GCR address base
|
||||
* @data: register update value
|
||||
*
|
||||
* Writes the PMC GCR register of given offset with given
|
||||
* value.
|
||||
*
|
||||
* Return: negative value on error or 0 on success.
|
||||
*/
|
||||
int intel_pmc_gcr_write(u32 offset, u32 data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock(&ipcdev.gcr_lock);
|
||||
|
||||
ret = is_gcr_valid(offset);
|
||||
if (ret < 0) {
|
||||
spin_unlock(&ipcdev.gcr_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
writel(data, ipcdev.gcr_mem_base + offset);
|
||||
|
||||
spin_unlock(&ipcdev.gcr_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_gcr_write);
|
||||
|
||||
/**
|
||||
* intel_pmc_gcr_update() - Update PMC GCR register bits
|
||||
* @offset: offset of GCR register from GCR address base
|
||||
@ -309,7 +235,7 @@ EXPORT_SYMBOL_GPL(intel_pmc_gcr_write);
|
||||
*
|
||||
* Return: negative value on error or 0 on success.
|
||||
*/
|
||||
int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
|
||||
static int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
u32 new_val;
|
||||
int ret = 0;
|
||||
@ -339,7 +265,6 @@ gcr_ipc_unlock:
|
||||
spin_unlock(&ipcdev.gcr_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);
|
||||
|
||||
static int update_no_reboot_bit(void *priv, bool set)
|
||||
{
|
||||
@ -405,7 +330,7 @@ static int intel_pmc_ipc_check_status(void)
|
||||
*
|
||||
* Return: an IPC error code or 0 on success.
|
||||
*/
|
||||
int intel_pmc_ipc_simple_command(int cmd, int sub)
|
||||
static int intel_pmc_ipc_simple_command(int cmd, int sub)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -420,7 +345,6 @@ int intel_pmc_ipc_simple_command(int cmd, int sub)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
|
||||
|
||||
/**
|
||||
* intel_pmc_ipc_raw_cmd() - IPC command with data and pointers
|
||||
@ -437,8 +361,8 @@ EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
|
||||
*
|
||||
* Return: an IPC error code or 0 on success.
|
||||
*/
|
||||
int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
|
||||
u32 outlen, u32 dptr, u32 sptr)
|
||||
static int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
|
||||
u32 outlen, u32 dptr, u32 sptr)
|
||||
{
|
||||
u32 wbuf[4] = { 0 };
|
||||
int ret;
|
||||
@ -470,7 +394,6 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd);
|
||||
|
||||
/**
|
||||
* intel_pmc_ipc_command() - IPC command with input/output data
|
||||
@ -579,6 +502,7 @@ static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev,
|
||||
}
|
||||
return (ssize_t)count;
|
||||
}
|
||||
static DEVICE_ATTR(simplecmd, 0200, NULL, intel_pmc_ipc_simple_cmd_store);
|
||||
|
||||
static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -588,8 +512,9 @@ static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev,
|
||||
int subcmd;
|
||||
int ret;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
ret = kstrtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val)
|
||||
subcmd = 1;
|
||||
@ -602,11 +527,7 @@ static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev,
|
||||
}
|
||||
return (ssize_t)count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(simplecmd, S_IWUSR,
|
||||
NULL, intel_pmc_ipc_simple_cmd_store);
|
||||
static DEVICE_ATTR(northpeak, S_IWUSR,
|
||||
NULL, intel_pmc_ipc_northpeak_store);
|
||||
static DEVICE_ATTR(northpeak, 0200, NULL, intel_pmc_ipc_northpeak_store);
|
||||
|
||||
static struct attribute *intel_ipc_attrs[] = {
|
||||
&dev_attr_northpeak.attr,
|
||||
@ -618,6 +539,11 @@ static const struct attribute_group intel_ipc_group = {
|
||||
.attrs = intel_ipc_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *intel_ipc_groups[] = {
|
||||
&intel_ipc_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct resource punit_res_array[] = {
|
||||
/* Punit BIOS */
|
||||
{
|
||||
@ -958,18 +884,10 @@ static int ipc_plat_probe(struct platform_device *pdev)
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
|
||||
ret);
|
||||
goto err_sys;
|
||||
}
|
||||
|
||||
ipcdev.has_gcr_regs = true;
|
||||
|
||||
return 0;
|
||||
err_sys:
|
||||
devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
|
||||
|
||||
err_irq:
|
||||
platform_device_unregister(ipcdev.tco_dev);
|
||||
platform_device_unregister(ipcdev.punit_dev);
|
||||
@ -980,7 +898,6 @@ err_irq:
|
||||
|
||||
static int ipc_plat_remove(struct platform_device *pdev)
|
||||
{
|
||||
sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
|
||||
devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
|
||||
platform_device_unregister(ipcdev.tco_dev);
|
||||
platform_device_unregister(ipcdev.punit_dev);
|
||||
@ -995,6 +912,7 @@ static struct platform_driver ipc_plat_driver = {
|
||||
.driver = {
|
||||
.name = "pmc-ipc-plat",
|
||||
.acpi_match_table = ACPI_PTR(ipc_acpi_ids),
|
||||
.dev_groups = intel_ipc_groups,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -26,11 +26,7 @@
|
||||
#include <asm/intel_scu_ipc.h>
|
||||
|
||||
/* IPC defines the following message types */
|
||||
#define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */
|
||||
#define IPCMSG_BATTERY 0xEF /* Coulomb Counter Accumulator */
|
||||
#define IPCMSG_FW_UPDATE 0xFE /* Firmware update */
|
||||
#define IPCMSG_PCNTRL 0xFF /* Power controller unit read/write */
|
||||
#define IPCMSG_FW_REVISION 0xF4 /* Get firmware revision */
|
||||
#define IPCMSG_PCNTRL 0xff /* Power controller unit read/write */
|
||||
|
||||
/* Command id associated with message IPCMSG_PCNTRL */
|
||||
#define IPC_CMD_PCNTRL_W 0 /* Register write */
|
||||
@ -58,56 +54,29 @@
|
||||
#define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */
|
||||
#define IPC_IOC 0x100 /* IPC command register IOC bit */
|
||||
|
||||
#define PCI_DEVICE_ID_LINCROFT 0x082a
|
||||
#define PCI_DEVICE_ID_PENWELL 0x080e
|
||||
#define PCI_DEVICE_ID_CLOVERVIEW 0x08ea
|
||||
#define PCI_DEVICE_ID_TANGIER 0x11a0
|
||||
|
||||
/* intel scu ipc driver data */
|
||||
struct intel_scu_ipc_pdata_t {
|
||||
u32 i2c_base;
|
||||
u32 i2c_len;
|
||||
u8 irq_mode;
|
||||
};
|
||||
|
||||
static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = {
|
||||
.i2c_base = 0xff12b000,
|
||||
.i2c_len = 0x10,
|
||||
.irq_mode = 0,
|
||||
};
|
||||
|
||||
/* Penwell and Cloverview */
|
||||
static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = {
|
||||
.i2c_base = 0xff12b000,
|
||||
.i2c_len = 0x10,
|
||||
.irq_mode = 1,
|
||||
};
|
||||
|
||||
static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
|
||||
.i2c_base = 0xff00d000,
|
||||
.i2c_len = 0x10,
|
||||
.irq_mode = 0,
|
||||
};
|
||||
|
||||
struct intel_scu_ipc_dev {
|
||||
struct device *dev;
|
||||
void __iomem *ipc_base;
|
||||
void __iomem *i2c_base;
|
||||
struct completion cmd_complete;
|
||||
u8 irq_mode;
|
||||
};
|
||||
|
||||
static struct intel_scu_ipc_dev ipcdev; /* Only one for now */
|
||||
|
||||
#define IPC_STATUS 0x04
|
||||
#define IPC_STATUS_IRQ BIT(2)
|
||||
#define IPC_STATUS_ERR BIT(1)
|
||||
#define IPC_STATUS_BUSY BIT(0)
|
||||
|
||||
/*
|
||||
* IPC Read Buffer (Read Only):
|
||||
* 16 byte buffer for receiving data from SCU, if IPC command
|
||||
* processing results in response data
|
||||
* IPC Write/Read Buffers:
|
||||
* 16 byte buffer for sending and receiving data to and from SCU.
|
||||
*/
|
||||
#define IPC_WRITE_BUFFER 0x80
|
||||
#define IPC_READ_BUFFER 0x90
|
||||
|
||||
#define IPC_I2C_CNTRL_ADDR 0
|
||||
#define I2C_DATA_ADDR 0x04
|
||||
/* Timeout in jiffies */
|
||||
#define IPC_TIMEOUT (3 * HZ)
|
||||
|
||||
static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
|
||||
|
||||
@ -120,11 +89,8 @@ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */
|
||||
*/
|
||||
static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
|
||||
{
|
||||
if (scu->irq_mode) {
|
||||
reinit_completion(&scu->cmd_complete);
|
||||
writel(cmd | IPC_IOC, scu->ipc_base);
|
||||
}
|
||||
writel(cmd, scu->ipc_base);
|
||||
reinit_completion(&scu->cmd_complete);
|
||||
writel(cmd | IPC_IOC, scu->ipc_base);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -135,7 +101,7 @@ static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
|
||||
*/
|
||||
static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset)
|
||||
{
|
||||
writel(data, scu->ipc_base + 0x80 + offset);
|
||||
writel(data, scu->ipc_base + IPC_WRITE_BUFFER + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -147,7 +113,7 @@ static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32
|
||||
*/
|
||||
static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu)
|
||||
{
|
||||
return __raw_readl(scu->ipc_base + 0x04);
|
||||
return __raw_readl(scu->ipc_base + IPC_STATUS);
|
||||
}
|
||||
|
||||
/* Read ipc byte data */
|
||||
@ -165,24 +131,20 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)
|
||||
/* Wait till scu status is busy */
|
||||
static inline int busy_loop(struct intel_scu_ipc_dev *scu)
|
||||
{
|
||||
u32 status = ipc_read_status(scu);
|
||||
u32 loop_count = 100000;
|
||||
unsigned long end = jiffies + msecs_to_jiffies(IPC_TIMEOUT);
|
||||
|
||||
do {
|
||||
u32 status;
|
||||
|
||||
/* break if scu doesn't reset busy bit after huge retry */
|
||||
while ((status & BIT(0)) && --loop_count) {
|
||||
udelay(1); /* scu processing time is in few u secods */
|
||||
status = ipc_read_status(scu);
|
||||
}
|
||||
if (!(status & IPC_STATUS_BUSY))
|
||||
return (status & IPC_STATUS_ERR) ? -EIO : 0;
|
||||
|
||||
if (status & BIT(0)) {
|
||||
dev_err(scu->dev, "IPC timed out");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
usleep_range(50, 100);
|
||||
} while (time_before(jiffies, end));
|
||||
|
||||
if (status & BIT(1))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
dev_err(scu->dev, "IPC timed out");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
|
||||
@ -190,13 +152,13 @@ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {
|
||||
if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) {
|
||||
dev_err(scu->dev, "IPC timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
status = ipc_read_status(scu);
|
||||
if (status & BIT(1))
|
||||
if (status & IPC_STATUS_ERR)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -260,14 +222,14 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_ioread8 - read a word via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: return pointer for read byte
|
||||
* intel_scu_ipc_ioread8 - read a word via the SCU
|
||||
* @addr: Register on SCU
|
||||
* @data: Return pointer for read byte
|
||||
*
|
||||
* Read a single register. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
* Read a single register. Returns %0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_ioread8(u16 addr, u8 *data)
|
||||
{
|
||||
@ -276,48 +238,14 @@ int intel_scu_ipc_ioread8(u16 addr, u8 *data)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_ioread8);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_ioread16 - read a word via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: return pointer for read word
|
||||
* intel_scu_ipc_iowrite8 - write a byte via the SCU
|
||||
* @addr: Register on SCU
|
||||
* @data: Byte to write
|
||||
*
|
||||
* Read a register pair. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
* Write a single register. Returns %0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_ioread16(u16 addr, u16 *data)
|
||||
{
|
||||
u16 x[2] = {addr, addr + 1};
|
||||
return pwr_reg_rdwr(x, (u8 *)data, 2, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R);
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_ioread16);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_ioread32 - read a dword via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: return pointer for read dword
|
||||
*
|
||||
* Read four registers. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_ioread32(u16 addr, u32 *data)
|
||||
{
|
||||
u16 x[4] = {addr, addr + 1, addr + 2, addr + 3};
|
||||
return pwr_reg_rdwr(x, (u8 *)data, 4, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_R);
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_ioread32);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_iowrite8 - write a byte via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: byte to write
|
||||
*
|
||||
* Write a single register. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_iowrite8(u16 addr, u8 data)
|
||||
{
|
||||
@ -326,51 +254,17 @@ int intel_scu_ipc_iowrite8(u16 addr, u8 data)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_iowrite8);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_iowrite16 - write a word via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: word to write
|
||||
* intel_scu_ipc_readvv - read a set of registers
|
||||
* @addr: Register list
|
||||
* @data: Bytes to return
|
||||
* @len: Length of array
|
||||
*
|
||||
* Write two registers. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
* Read registers. Returns %0 on success or an error code. All locking
|
||||
* between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_iowrite16(u16 addr, u16 data)
|
||||
{
|
||||
u16 x[2] = {addr, addr + 1};
|
||||
return pwr_reg_rdwr(x, (u8 *)&data, 2, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W);
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_iowrite16);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_iowrite32 - write a dword via the SCU
|
||||
* @addr: register on SCU
|
||||
* @data: dword to write
|
||||
* The largest array length permitted by the hardware is 5 items.
|
||||
*
|
||||
* Write four registers. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_iowrite32(u16 addr, u32 data)
|
||||
{
|
||||
u16 x[4] = {addr, addr + 1, addr + 2, addr + 3};
|
||||
return pwr_reg_rdwr(x, (u8 *)&data, 4, IPCMSG_PCNTRL, IPC_CMD_PCNTRL_W);
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_iowrite32);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_readvv - read a set of registers
|
||||
* @addr: register list
|
||||
* @data: bytes to return
|
||||
* @len: length of array
|
||||
*
|
||||
* Read registers. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
*
|
||||
* The largest array length permitted by the hardware is 5 items.
|
||||
*
|
||||
* This function may sleep.
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_readv(u16 *addr, u8 *data, int len)
|
||||
{
|
||||
@ -379,18 +273,17 @@ int intel_scu_ipc_readv(u16 *addr, u8 *data, int len)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_readv);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_writev - write a set of registers
|
||||
* @addr: register list
|
||||
* @data: bytes to write
|
||||
* @len: length of array
|
||||
* intel_scu_ipc_writev - write a set of registers
|
||||
* @addr: Register list
|
||||
* @data: Bytes to write
|
||||
* @len: Length of array
|
||||
*
|
||||
* Write registers. Returns 0 on success or an error code. All
|
||||
* locking between SCU accesses is handled for the caller.
|
||||
* Write registers. Returns %0 on success or an error code. All locking
|
||||
* between SCU accesses is handled for the caller.
|
||||
*
|
||||
* The largest array length permitted by the hardware is 5 items.
|
||||
*
|
||||
* This function may sleep.
|
||||
* The largest array length permitted by the hardware is 5 items.
|
||||
*
|
||||
* This function may sleep.
|
||||
*/
|
||||
int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)
|
||||
{
|
||||
@ -399,19 +292,18 @@ int intel_scu_ipc_writev(u16 *addr, u8 *data, int len)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_writev);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_update_register - r/m/w a register
|
||||
* @addr: register address
|
||||
* @bits: bits to update
|
||||
* @mask: mask of bits to update
|
||||
* intel_scu_ipc_update_register - r/m/w a register
|
||||
* @addr: Register address
|
||||
* @bits: Bits to update
|
||||
* @mask: Mask of bits to update
|
||||
*
|
||||
* Read-modify-write power control unit register. The first data argument
|
||||
* must be register value and second is mask value
|
||||
* mask is a bitmap that indicates which bits to update.
|
||||
* 0 = masked. Don't modify this bit, 1 = modify this bit.
|
||||
* returns 0 on success or an error code.
|
||||
* Read-modify-write power control unit register. The first data argument
|
||||
* must be register value and second is mask value mask is a bitmap that
|
||||
* indicates which bits to update. %0 = masked. Don't modify this bit, %1 =
|
||||
* modify this bit. returns %0 on success or an error code.
|
||||
*
|
||||
* This function may sleep. Locking between SCU accesses is handled
|
||||
* for the caller.
|
||||
* This function may sleep. Locking between SCU accesses is handled
|
||||
* for the caller.
|
||||
*/
|
||||
int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask)
|
||||
{
|
||||
@ -421,16 +313,16 @@ int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_update_register);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_simple_command - send a simple command
|
||||
* @cmd: command
|
||||
* @sub: sub type
|
||||
* intel_scu_ipc_simple_command - send a simple command
|
||||
* @cmd: Command
|
||||
* @sub: Sub type
|
||||
*
|
||||
* Issue a simple command to the SCU. Do not use this interface if
|
||||
* you must then access data as any data values may be overwritten
|
||||
* by another SCU access by the time this function returns.
|
||||
* Issue a simple command to the SCU. Do not use this interface if you must
|
||||
* then access data as any data values may be overwritten by another SCU
|
||||
* access by the time this function returns.
|
||||
*
|
||||
* This function may sleep. Locking for SCU accesses is handled for
|
||||
* the caller.
|
||||
* This function may sleep. Locking for SCU accesses is handled for the
|
||||
* caller.
|
||||
*/
|
||||
int intel_scu_ipc_simple_command(int cmd, int sub)
|
||||
{
|
||||
@ -450,16 +342,16 @@ int intel_scu_ipc_simple_command(int cmd, int sub)
|
||||
EXPORT_SYMBOL(intel_scu_ipc_simple_command);
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_command - command with data
|
||||
* @cmd: command
|
||||
* @sub: sub type
|
||||
* @in: input data
|
||||
* @inlen: input length in dwords
|
||||
* @out: output data
|
||||
* @outlein: output length in dwords
|
||||
* intel_scu_ipc_command - command with data
|
||||
* @cmd: Command
|
||||
* @sub: Sub type
|
||||
* @in: Input data
|
||||
* @inlen: Input length in dwords
|
||||
* @out: Output data
|
||||
* @outlen: Output length in dwords
|
||||
*
|
||||
* Issue a command to the SCU which involves data transfers. Do the
|
||||
* data copies under the lock but leave it for the caller to interpret
|
||||
* Issue a command to the SCU which involves data transfers. Do the
|
||||
* data copies under the lock but leave it for the caller to interpret.
|
||||
*/
|
||||
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
|
||||
u32 *out, int outlen)
|
||||
@ -489,117 +381,6 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_command);
|
||||
|
||||
#define IPC_SPTR 0x08
|
||||
#define IPC_DPTR 0x0C
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_raw_command() - IPC command with data and pointers
|
||||
* @cmd: IPC command code.
|
||||
* @sub: IPC command sub type.
|
||||
* @in: input data of this IPC command.
|
||||
* @inlen: input data length in dwords.
|
||||
* @out: output data of this IPC command.
|
||||
* @outlen: output data length in dwords.
|
||||
* @sptr: data writing to SPTR register.
|
||||
* @dptr: data writing to DPTR register.
|
||||
*
|
||||
* Send an IPC command to SCU with input/output data and source/dest pointers.
|
||||
*
|
||||
* Return: an IPC error code or 0 on success.
|
||||
*/
|
||||
int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
|
||||
u32 *out, int outlen, u32 dptr, u32 sptr)
|
||||
{
|
||||
struct intel_scu_ipc_dev *scu = &ipcdev;
|
||||
int inbuflen = DIV_ROUND_UP(inlen, 4);
|
||||
u32 inbuf[4];
|
||||
int i, err;
|
||||
|
||||
/* Up to 16 bytes */
|
||||
if (inbuflen > 4)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ipclock);
|
||||
if (scu->dev == NULL) {
|
||||
mutex_unlock(&ipclock);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
writel(dptr, scu->ipc_base + IPC_DPTR);
|
||||
writel(sptr, scu->ipc_base + IPC_SPTR);
|
||||
|
||||
/*
|
||||
* SRAM controller doesn't support 8-bit writes, it only
|
||||
* supports 32-bit writes, so we have to copy input data into
|
||||
* the temporary buffer, and SCU FW will use the inlen to
|
||||
* determine the actual input data length in the temporary
|
||||
* buffer.
|
||||
*/
|
||||
memcpy(inbuf, in, inlen);
|
||||
|
||||
for (i = 0; i < inbuflen; i++)
|
||||
ipc_data_writel(scu, inbuf[i], 4 * i);
|
||||
|
||||
ipc_command(scu, (inlen << 16) | (sub << 12) | cmd);
|
||||
err = intel_scu_ipc_check_status(scu);
|
||||
if (!err) {
|
||||
for (i = 0; i < outlen; i++)
|
||||
*out++ = ipc_data_readl(scu, 4 * i);
|
||||
}
|
||||
|
||||
mutex_unlock(&ipclock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_scu_ipc_raw_command);
|
||||
|
||||
/* I2C commands */
|
||||
#define IPC_I2C_WRITE 1 /* I2C Write command */
|
||||
#define IPC_I2C_READ 2 /* I2C Read command */
|
||||
|
||||
/**
|
||||
* intel_scu_ipc_i2c_cntrl - I2C read/write operations
|
||||
* @addr: I2C address + command bits
|
||||
* @data: data to read/write
|
||||
*
|
||||
* Perform an an I2C read/write operation via the SCU. All locking is
|
||||
* handled for the caller. This function may sleep.
|
||||
*
|
||||
* Returns an error code or 0 on success.
|
||||
*
|
||||
* This has to be in the IPC driver for the locking.
|
||||
*/
|
||||
int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
|
||||
{
|
||||
struct intel_scu_ipc_dev *scu = &ipcdev;
|
||||
u32 cmd = 0;
|
||||
|
||||
mutex_lock(&ipclock);
|
||||
if (scu->dev == NULL) {
|
||||
mutex_unlock(&ipclock);
|
||||
return -ENODEV;
|
||||
}
|
||||
cmd = (addr >> 24) & 0xFF;
|
||||
if (cmd == IPC_I2C_READ) {
|
||||
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
|
||||
/* Write not getting updated without delay */
|
||||
usleep_range(1000, 2000);
|
||||
*data = readl(scu->i2c_base + I2C_DATA_ADDR);
|
||||
} else if (cmd == IPC_I2C_WRITE) {
|
||||
writel(*data, scu->i2c_base + I2C_DATA_ADDR);
|
||||
usleep_range(1000, 2000);
|
||||
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
|
||||
} else {
|
||||
dev_err(scu->dev,
|
||||
"intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
|
||||
|
||||
mutex_unlock(&ipclock);
|
||||
return -EIO;
|
||||
}
|
||||
mutex_unlock(&ipclock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
|
||||
|
||||
/*
|
||||
* Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1
|
||||
* When ioc bit is set to 1, caller api must wait for interrupt handler called
|
||||
@ -610,9 +391,10 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);
|
||||
static irqreturn_t ioc(int irq, void *dev_id)
|
||||
{
|
||||
struct intel_scu_ipc_dev *scu = dev_id;
|
||||
int status = ipc_read_status(scu);
|
||||
|
||||
if (scu->irq_mode)
|
||||
complete(&scu->cmd_complete);
|
||||
writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS);
|
||||
complete(&scu->cmd_complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -629,17 +411,10 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct intel_scu_ipc_dev *scu = &ipcdev;
|
||||
struct intel_scu_ipc_pdata_t *pdata;
|
||||
|
||||
if (scu->dev) /* We support only one SCU */
|
||||
return -EBUSY;
|
||||
|
||||
pdata = (struct intel_scu_ipc_pdata_t *)id->driver_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
|
||||
scu->irq_mode = pdata->irq_mode;
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
@ -652,10 +427,6 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
||||
scu->ipc_base = pcim_iomap_table(pdev)[0];
|
||||
|
||||
scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);
|
||||
if (!scu->i2c_base)
|
||||
return -ENOMEM;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_scu_ipc",
|
||||
scu);
|
||||
if (err)
|
||||
@ -670,13 +441,10 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SCU_DEVICE(id, pdata) {PCI_VDEVICE(INTEL, id), (kernel_ulong_t)&pdata}
|
||||
|
||||
static const struct pci_device_id pci_ids[] = {
|
||||
SCU_DEVICE(PCI_DEVICE_ID_LINCROFT, intel_scu_ipc_lincroft_pdata),
|
||||
SCU_DEVICE(PCI_DEVICE_ID_PENWELL, intel_scu_ipc_penwell_pdata),
|
||||
SCU_DEVICE(PCI_DEVICE_ID_CLOVERVIEW, intel_scu_ipc_penwell_pdata),
|
||||
SCU_DEVICE(PCI_DEVICE_ID_TANGIER, intel_scu_ipc_tangier_pdata),
|
||||
{ PCI_VDEVICE(INTEL, 0x080e) },
|
||||
{ PCI_VDEVICE(INTEL, 0x08ea) },
|
||||
{ PCI_VDEVICE(INTEL, 0x11a0) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,8 @@ static const struct isst_valid_cmd_ranges isst_valid_cmds[] = {
|
||||
{0x7F, 0x00, 0x0B},
|
||||
{0x7F, 0x10, 0x12},
|
||||
{0x7F, 0x20, 0x23},
|
||||
{0x94, 0x03, 0x03},
|
||||
{0x95, 0x03, 0x03},
|
||||
};
|
||||
|
||||
static const struct isst_cmd_set_req_type isst_cmd_set_reqs[] = {
|
||||
@ -59,6 +61,7 @@ static const struct isst_cmd_set_req_type isst_cmd_set_reqs[] = {
|
||||
{0xD0, 0x03, 0x08},
|
||||
{0x7F, 0x02, 0x00},
|
||||
{0x7F, 0x08, 0x00},
|
||||
{0x95, 0x03, 0x03},
|
||||
};
|
||||
|
||||
struct isst_cmd {
|
||||
|
@ -686,13 +686,14 @@ static ssize_t telem_pss_trc_verb_write(struct file *file,
|
||||
u32 verbosity;
|
||||
int err;
|
||||
|
||||
if (kstrtou32_from_user(userbuf, count, 0, &verbosity))
|
||||
return -EFAULT;
|
||||
err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = telemetry_set_trace_verbosity(TELEM_PSS, verbosity);
|
||||
if (err) {
|
||||
pr_err("Changing PSS Trace Verbosity Failed. Error %d\n", err);
|
||||
count = err;
|
||||
return err;
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -733,13 +734,14 @@ static ssize_t telem_ioss_trc_verb_write(struct file *file,
|
||||
u32 verbosity;
|
||||
int err;
|
||||
|
||||
if (kstrtou32_from_user(userbuf, count, 0, &verbosity))
|
||||
return -EFAULT;
|
||||
err = kstrtou32_from_user(userbuf, count, 0, &verbosity);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = telemetry_set_trace_verbosity(TELEM_IOSS, verbosity);
|
||||
if (err) {
|
||||
pr_err("Changing IOSS Trace Verbosity Failed. Error %d\n", err);
|
||||
count = err;
|
||||
return err;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -1117,9 +1117,9 @@ static const struct telemetry_core_ops telm_pltops = {
|
||||
|
||||
static int telemetry_pltdrv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res0 = NULL, *res1 = NULL;
|
||||
const struct x86_cpu_id *id;
|
||||
int size, ret = -ENOMEM;
|
||||
void __iomem *mem;
|
||||
int ret;
|
||||
|
||||
id = x86_match_cpu(telemetry_cpu_ids);
|
||||
if (!id)
|
||||
@ -1127,50 +1127,17 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev)
|
||||
|
||||
telm_conf = (struct telemetry_plt_config *)id->driver_data;
|
||||
|
||||
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
size = resource_size(res0);
|
||||
if (!devm_request_mem_region(&pdev->dev, res0->start, size,
|
||||
pdev->name)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
telm_conf->pss_config.ssram_base_addr = res0->start;
|
||||
telm_conf->pss_config.ssram_size = size;
|
||||
mem = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mem))
|
||||
return PTR_ERR(mem);
|
||||
|
||||
res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!res1) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
size = resource_size(res1);
|
||||
if (!devm_request_mem_region(&pdev->dev, res1->start, size,
|
||||
pdev->name)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
telm_conf->pss_config.regmap = mem;
|
||||
|
||||
telm_conf->ioss_config.ssram_base_addr = res1->start;
|
||||
telm_conf->ioss_config.ssram_size = size;
|
||||
mem = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(mem))
|
||||
return PTR_ERR(mem);
|
||||
|
||||
telm_conf->pss_config.regmap = ioremap_nocache(
|
||||
telm_conf->pss_config.ssram_base_addr,
|
||||
telm_conf->pss_config.ssram_size);
|
||||
if (!telm_conf->pss_config.regmap) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
telm_conf->ioss_config.regmap = ioremap_nocache(
|
||||
telm_conf->ioss_config.ssram_base_addr,
|
||||
telm_conf->ioss_config.ssram_size);
|
||||
if (!telm_conf->ioss_config.regmap) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
telm_conf->ioss_config.regmap = mem;
|
||||
|
||||
mutex_init(&telm_conf->telem_lock);
|
||||
mutex_init(&telm_conf->telem_trace_lock);
|
||||
@ -1188,14 +1155,6 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (res0)
|
||||
release_mem_region(res0->start, resource_size(res0));
|
||||
if (res1)
|
||||
release_mem_region(res1->start, resource_size(res1));
|
||||
if (telm_conf->pss_config.regmap)
|
||||
iounmap(telm_conf->pss_config.regmap);
|
||||
if (telm_conf->ioss_config.regmap)
|
||||
iounmap(telm_conf->ioss_config.regmap);
|
||||
dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n");
|
||||
|
||||
return ret;
|
||||
@ -1204,9 +1163,6 @@ out:
|
||||
static int telemetry_pltdrv_remove(struct platform_device *pdev)
|
||||
{
|
||||
telemetry_clear_pltdata();
|
||||
iounmap(telm_conf->pss_config.regmap);
|
||||
iounmap(telm_conf->ioss_config.regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,8 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION 0x2a
|
||||
#define MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET 0x2b
|
||||
#define MLXPLAT_CPLD_LPC_REG_GP0_OFFSET 0x2e
|
||||
#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30
|
||||
#define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31
|
||||
#define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32
|
||||
@ -46,6 +48,8 @@
|
||||
#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_ASIC_HEALTH_OFFSET 0x50
|
||||
#define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51
|
||||
#define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52
|
||||
@ -68,6 +72,7 @@
|
||||
#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_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
|
||||
@ -85,9 +90,13 @@
|
||||
#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_CONFIG1_OFFSET 0xfb
|
||||
#define MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET 0xfc
|
||||
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
|
||||
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
|
||||
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
|
||||
#define MLXPLAT_CPLD_LPC_I2C_CH3_OFF 0xdc
|
||||
|
||||
#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
|
||||
#define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
|
||||
@ -96,6 +105,9 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
|
||||
MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
|
||||
MLXPLAT_CPLD_LPC_PIO_OFFSET)
|
||||
#define MLXPLAT_CPLD_LPC_REG3 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
|
||||
MLXPLAT_CPLD_LPC_I2C_CH3_OFF) | \
|
||||
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
|
||||
@ -112,17 +124,29 @@
|
||||
#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(5, 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_I2C_CAP_BIT 0x04
|
||||
#define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT)
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
@ -130,14 +154,16 @@
|
||||
/* Start channel numbers */
|
||||
#define MLXPLAT_CPLD_CH1 2
|
||||
#define MLXPLAT_CPLD_CH2 10
|
||||
#define MLXPLAT_CPLD_CH3 18
|
||||
|
||||
/* Number of LPC attached MUX platform devices */
|
||||
#define MLXPLAT_CPLD_LPC_MUX_DEVS 2
|
||||
#define MLXPLAT_CPLD_LPC_MUX_DEVS 3
|
||||
|
||||
/* 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_PSU_MSNXXXX_NR2 3
|
||||
#define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11
|
||||
#define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12
|
||||
#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13
|
||||
@ -187,8 +213,24 @@ static const struct resource mlxplat_lpc_resources[] = {
|
||||
IORESOURCE_IO),
|
||||
};
|
||||
|
||||
/* 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,
|
||||
@ -213,7 +255,7 @@ static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
|
||||
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_mux_data[] = {
|
||||
static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = {
|
||||
{
|
||||
.parent = 1,
|
||||
.base_nr = MLXPLAT_CPLD_CH1,
|
||||
@ -233,6 +275,40 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
|
||||
|
||||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 hotplug devices */
|
||||
static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
|
||||
{
|
||||
@ -276,6 +352,22 @@ static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
|
||||
},
|
||||
};
|
||||
|
||||
/* 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[] = {
|
||||
{
|
||||
@ -390,6 +482,45 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
|
||||
},
|
||||
};
|
||||
|
||||
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_psu),
|
||||
.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_pwr),
|
||||
.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_fan),
|
||||
.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,
|
||||
@ -400,6 +531,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
|
||||
.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",
|
||||
@ -723,6 +864,116 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
|
||||
.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_pwr[0],
|
||||
.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR2,
|
||||
},
|
||||
{
|
||||
.label = "pwr4",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
|
||||
.mask = BIT(3),
|
||||
.hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
|
||||
.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR2,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/* Platform led default data */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
|
||||
{
|
||||
@ -964,6 +1215,80 @@ static struct mlxreg_core_platform_data mlxplat_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 register access default */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
|
||||
{
|
||||
@ -1156,6 +1481,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
|
||||
.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,
|
||||
@ -1244,6 +1575,18 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.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,
|
||||
@ -1262,6 +1605,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.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,
|
||||
@ -1274,6 +1623,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.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 = "psu1_on",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
|
||||
@ -1317,6 +1672,43 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.bit = GENMASK(7, 0),
|
||||
.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 = "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 = "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 = {
|
||||
@ -1575,6 +1967,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
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_GP0_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
|
||||
@ -1582,6 +1975,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_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_ASIC_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
|
||||
@ -1621,6 +2015,8 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
|
||||
@ -1631,6 +2027,8 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
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_ASIC_HEALTH_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
|
||||
@ -1671,6 +2069,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
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_CONFIG1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1692,6 +2094,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
|
||||
@ -1700,6 +2104,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
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_ASIC_HEALTH_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
|
||||
@ -1734,6 +2140,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
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_CONFIG1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1751,6 +2161,19 @@ static const struct reg_default mlxplat_mlxcpld_regmap_ng[] = {
|
||||
{ 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 },
|
||||
};
|
||||
|
||||
struct mlxplat_mlxcpld_regmap_context {
|
||||
void __iomem *base;
|
||||
};
|
||||
@ -1803,6 +2226,34 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng = {
|
||||
.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 struct resource mlxplat_mlxcpld_resources[] = {
|
||||
[0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
|
||||
};
|
||||
@ -1821,7 +2272,10 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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]);
|
||||
@ -1834,13 +2288,16 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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);
|
||||
@ -1853,13 +2310,16 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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);
|
||||
@ -1872,13 +2332,16 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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);
|
||||
@ -1891,13 +2354,16 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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);
|
||||
@ -1914,7 +2380,57 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_ng;
|
||||
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
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_regmap_config = &mlxplat_mlxcpld_regmap_config_comex;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
|
||||
{
|
||||
@ -1953,6 +2469,18 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "VMOD0007"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = mlxplat_dmi_comex_matched,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "VMOD0009"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = mlxplat_dmi_ng400_matched,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = mlxplat_dmi_msn274x_matched,
|
||||
.matches = {
|
||||
@ -2043,7 +2571,7 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
|
||||
/* 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_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
|
||||
mlxplat_max_adap_num; i++) {
|
||||
search_adap = i2c_get_adapter(i);
|
||||
if (search_adap) {
|
||||
i2c_put_adapter(search_adap);
|
||||
@ -2057,12 +2585,12 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
|
||||
}
|
||||
|
||||
/* Return with error if free id for adapter is not found. */
|
||||
if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
|
||||
if (i == mlxplat_max_adap_num)
|
||||
return -ENODEV;
|
||||
|
||||
/* Shift adapter ids, since expected parent adapter is not free. */
|
||||
*nr = i;
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); 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;
|
||||
@ -2118,7 +2646,7 @@ static int __init mlxplat_init(void)
|
||||
if (nr < 0)
|
||||
goto fail_alloc;
|
||||
|
||||
nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
|
||||
nr = (nr == mlxplat_max_adap_num) ? -1 : nr;
|
||||
if (mlxplat_i2c)
|
||||
mlxplat_i2c->regmap = priv->regmap;
|
||||
priv->pdev_i2c = platform_device_register_resndata(
|
||||
@ -2131,7 +2659,7 @@ static int __init mlxplat_init(void)
|
||||
goto fail_alloc;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
|
||||
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,
|
||||
@ -2265,7 +2793,7 @@ static void __exit mlxplat_exit(void)
|
||||
platform_device_unregister(priv->pdev_led);
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
|
||||
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
|
||||
for (i = mlxplat_mux_num - 1; i >= 0 ; i--)
|
||||
platform_device_unregister(priv->pdev_mux[i]);
|
||||
|
||||
platform_device_unregister(priv->pdev_i2c);
|
||||
|
@ -219,8 +219,7 @@ static const struct property_entry digma_citi_e200_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1686-digma_citi_e200.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-digma_citi_e200.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -236,8 +235,7 @@ static const struct property_entry gp_electronic_t701_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-gp-electronic-t701.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-gp-electronic-t701.fw"),
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -382,8 +380,7 @@ static const struct property_entry onda_v80_plus_v3_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1698),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3676-onda-v80-plus-v3.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-v80-plus-v3.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -398,8 +395,7 @@ static const struct property_entry onda_v820w_32g_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-onda-v820w-32g.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-onda-v820w-32g.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -415,8 +411,7 @@ static const struct property_entry onda_v891w_v1_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3680-onda-v891w-v1.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-onda-v891w-v1.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -433,8 +428,7 @@ static const struct property_entry onda_v891w_v3_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1625),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1135),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3676-onda-v891w-v3.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-v891w-v3.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -450,8 +444,7 @@ static const struct property_entry pipo_w2s_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-pipo-w2s.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-pipo-w2s.fw"),
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -460,14 +453,29 @@ static const struct ts_dmi_data pipo_w2s_data = {
|
||||
.properties = pipo_w2s_props,
|
||||
};
|
||||
|
||||
static const struct property_entry pipo_w11_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1984),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1532),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-pipo-w11.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct ts_dmi_data pipo_w11_data = {
|
||||
.acpi_name = "MSSL1680:00",
|
||||
.properties = pipo_w11_props,
|
||||
};
|
||||
|
||||
static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3680-pov-mobii-wintab-p800w-v20.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -484,8 +492,7 @@ static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1794),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3692-pov-mobii-wintab-p800w.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-pov-mobii-wintab-p800w.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -502,8 +509,7 @@ static const struct property_entry pov_mobii_wintab_p1006w_v10_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1984),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1520),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3692-pov-mobii-wintab-p1006w-v10.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-pov-mobii-wintab-p1006w-v10.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -520,8 +526,7 @@ static const struct property_entry schneider_sct101ctm_props[] = {
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-schneider-sct101ctm.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-schneider-sct101ctm.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -551,8 +556,7 @@ static const struct property_entry teclast_x98plus2_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1686-teclast_x98plus2.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-teclast_x98plus2.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
{ }
|
||||
};
|
||||
@ -566,8 +570,7 @@ static const struct property_entry trekstor_primebook_c11_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1970),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1530),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-trekstor-primebook-c11.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-trekstor-primebook-c11.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -581,8 +584,7 @@ static const struct ts_dmi_data trekstor_primebook_c11_data = {
|
||||
static const struct property_entry trekstor_primebook_c13_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-trekstor-primebook-c13.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-trekstor-primebook-c13.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -596,8 +598,7 @@ static const struct ts_dmi_data trekstor_primebook_c13_data = {
|
||||
static const struct property_entry trekstor_primetab_t13b_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 2500),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1900),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1680-trekstor-primetab-t13b.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-trekstor-primetab-t13b.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
@ -613,8 +614,7 @@ static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
|
||||
PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl3670-surftab-twin-10-1-st10432-8.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-surftab-twin-10-1-st10432-8.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
{ }
|
||||
};
|
||||
@ -629,8 +629,7 @@ static const struct property_entry trekstor_surftab_wintron70_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
|
||||
PROPERTY_ENTRY_STRING("firmware-name",
|
||||
"gsl1686-surftab-wintron70-st70416-6.fw"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-surftab-wintron70-st70416-6.fw"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
{ }
|
||||
@ -909,6 +908,16 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Pipo W11 */
|
||||
.driver_data = (void *)&pipo_w11_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
|
||||
/* Above matches are too generic, add bios-ver match */
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "JS-BI-10.6-SF133GR300-GA55B-024-F"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
|
||||
.driver_data = (void *)&trekstor_surftab_wintron70_data,
|
||||
@ -1032,8 +1041,7 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
.driver_data = (void *)&trekstor_surftab_wintron70_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME,
|
||||
"SurfTab wintron 7.0 ST70416-6"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab wintron 7.0 ST70416-6"),
|
||||
/* Exact match, different versions need different fw */
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
|
||||
},
|
||||
@ -1065,7 +1073,7 @@ static void ts_dmi_add_props(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static int ts_dmi_notifier_call(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct i2c_client *client;
|
||||
|
@ -101,6 +101,7 @@ struct mlxreg_core_data {
|
||||
* @aggr_mask: group aggregation mask;
|
||||
* @reg: group interrupt status register;
|
||||
* @mask: group interrupt mask;
|
||||
* @capability: group capability register;
|
||||
* @cache: last status value for elements fro the same group;
|
||||
* @count: number of available elements in the group;
|
||||
* @ind: element's index inside the group;
|
||||
@ -112,6 +113,7 @@ struct mlxreg_core_item {
|
||||
u32 aggr_mask;
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
u32 capability;
|
||||
u32 cache;
|
||||
u8 count;
|
||||
u8 ind;
|
||||
|
@ -58,6 +58,7 @@
|
||||
#define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */
|
||||
#define ASUS_WMI_DEVID_LIGHTBAR 0x00050025
|
||||
#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018
|
||||
#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075
|
||||
|
||||
/* Misc */
|
||||
#define ASUS_WMI_DEVID_CAMERA 0x00060013
|
||||
|
@ -15,7 +15,7 @@ struct process_cmd_struct {
|
||||
int arg;
|
||||
};
|
||||
|
||||
static const char *version_str = "v1.1";
|
||||
static const char *version_str = "v1.2";
|
||||
static const int supported_api_ver = 1;
|
||||
static struct isst_if_platform_info isst_platform_info;
|
||||
static char *progname;
|
||||
@ -1384,14 +1384,10 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
|
||||
goto disp_result;
|
||||
}
|
||||
|
||||
if (auto_mode) {
|
||||
if (status) {
|
||||
ret = set_pbf_core_power(cpu);
|
||||
if (ret)
|
||||
goto disp_result;
|
||||
} else {
|
||||
isst_pm_qos_config(cpu, 0, 0);
|
||||
}
|
||||
if (auto_mode && status) {
|
||||
ret = set_pbf_core_power(cpu);
|
||||
if (ret)
|
||||
goto disp_result;
|
||||
}
|
||||
|
||||
ret = isst_set_pbf_fact_status(cpu, 1, status);
|
||||
@ -1408,6 +1404,9 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_mode && !status)
|
||||
isst_pm_qos_config(cpu, 0, 0);
|
||||
|
||||
disp_result:
|
||||
if (status)
|
||||
isst_display_result(cpu, outf, "base-freq", "enable",
|
||||
@ -1496,14 +1495,10 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
|
||||
int ret;
|
||||
int status = *(int *)arg4;
|
||||
|
||||
if (auto_mode) {
|
||||
if (status) {
|
||||
ret = isst_pm_qos_config(cpu, 1, 1);
|
||||
if (ret)
|
||||
goto disp_results;
|
||||
} else {
|
||||
isst_pm_qos_config(cpu, 0, 0);
|
||||
}
|
||||
if (auto_mode && status) {
|
||||
ret = isst_pm_qos_config(cpu, 1, 1);
|
||||
if (ret)
|
||||
goto disp_results;
|
||||
}
|
||||
|
||||
ret = isst_set_pbf_fact_status(cpu, 0, status);
|
||||
@ -1524,6 +1519,9 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
|
||||
ret = isst_set_trl(cpu, fact_trl);
|
||||
if (ret && auto_mode)
|
||||
isst_pm_qos_config(cpu, 0, 0);
|
||||
} else {
|
||||
if (auto_mode)
|
||||
isst_pm_qos_config(cpu, 0, 0);
|
||||
}
|
||||
|
||||
disp_results:
|
||||
@ -1638,7 +1636,7 @@ static void set_fact_enable(int arg)
|
||||
if (ret)
|
||||
goto error_disp;
|
||||
}
|
||||
isst_display_result(i, outf, "turbo-freq --auto", "enable", 0);
|
||||
isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -6,6 +6,44 @@
|
||||
|
||||
#include "isst.h"
|
||||
|
||||
int isst_write_pm_config(int cpu, int cp_state)
|
||||
{
|
||||
unsigned int req, resp;
|
||||
int ret;
|
||||
|
||||
if (cp_state)
|
||||
req = BIT(16);
|
||||
else
|
||||
req = 0;
|
||||
|
||||
ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
|
||||
&resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
|
||||
{
|
||||
unsigned int resp;
|
||||
int ret;
|
||||
|
||||
ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
|
||||
&resp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
|
||||
|
||||
*cp_state = resp & BIT(16);
|
||||
*cp_cap = resp & BIT(0) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
|
||||
{
|
||||
unsigned int resp;
|
||||
@ -36,6 +74,7 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
|
||||
int isst_get_ctdp_control(int cpu, int config_index,
|
||||
struct isst_pkg_ctdp_level_info *ctdp_level)
|
||||
{
|
||||
int cp_state, cp_cap;
|
||||
unsigned int resp;
|
||||
int ret;
|
||||
|
||||
@ -50,6 +89,15 @@ int isst_get_ctdp_control(int cpu, int config_index,
|
||||
ctdp_level->fact_enabled = !!(resp & BIT(16));
|
||||
ctdp_level->pbf_enabled = !!(resp & BIT(17));
|
||||
|
||||
ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
|
||||
if (ret) {
|
||||
debug_printf("cpu:%d pm_config is not supported \n", cpu);
|
||||
} else {
|
||||
debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
|
||||
ctdp_level->sst_cp_support = cp_cap;
|
||||
ctdp_level->sst_cp_enabled = cp_state;
|
||||
}
|
||||
|
||||
debug_printf(
|
||||
"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
|
||||
cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
|
||||
@ -779,6 +827,13 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
|
||||
debug_printf("Turbo-freq feature must be disabled first\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = isst_write_pm_config(cpu, 0);
|
||||
if (ret)
|
||||
perror("isst_write_pm_config\n");
|
||||
} else {
|
||||
ret = isst_write_pm_config(cpu, 1);
|
||||
if (ret)
|
||||
perror("isst_write_pm_config\n");
|
||||
}
|
||||
|
||||
ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
|
||||
|
@ -418,6 +418,17 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
|
||||
snprintf(value, sizeof(value), "unsupported");
|
||||
format_and_print(outf, base_level + 4, header, value);
|
||||
|
||||
snprintf(header, sizeof(header),
|
||||
"speed-select-core-power");
|
||||
if (ctdp_level->sst_cp_support) {
|
||||
if (ctdp_level->sst_cp_enabled)
|
||||
snprintf(value, sizeof(value), "enabled");
|
||||
else
|
||||
snprintf(value, sizeof(value), "disabled");
|
||||
} else
|
||||
snprintf(value, sizeof(value), "unsupported");
|
||||
format_and_print(outf, base_level + 4, header, value);
|
||||
|
||||
if (is_clx_n_platform()) {
|
||||
if (ctdp_level->pbf_support)
|
||||
_isst_pbf_display_information(cpu, outf,
|
||||
@ -634,13 +645,15 @@ void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
|
||||
char header[256];
|
||||
char value[256];
|
||||
|
||||
snprintf(header, sizeof(header), "package-%d",
|
||||
get_physical_package_id(cpu));
|
||||
format_and_print(outf, 1, header, NULL);
|
||||
snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
|
||||
format_and_print(outf, 2, header, NULL);
|
||||
snprintf(header, sizeof(header), "cpu-%d", cpu);
|
||||
format_and_print(outf, 3, header, NULL);
|
||||
if (cpu >= 0) {
|
||||
snprintf(header, sizeof(header), "package-%d",
|
||||
get_physical_package_id(cpu));
|
||||
format_and_print(outf, 1, header, NULL);
|
||||
snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
|
||||
format_and_print(outf, 2, header, NULL);
|
||||
snprintf(header, sizeof(header), "cpu-%d", cpu);
|
||||
format_and_print(outf, 3, header, NULL);
|
||||
}
|
||||
snprintf(header, sizeof(header), "%s", feature);
|
||||
format_and_print(outf, 4, header, NULL);
|
||||
snprintf(header, sizeof(header), "%s", cmd);
|
||||
|
@ -69,6 +69,10 @@
|
||||
#define PM_CLOS_OFFSET 0x08
|
||||
#define PQR_ASSOC_OFFSET 0x20
|
||||
|
||||
#define READ_PM_CONFIG 0x94
|
||||
#define WRITE_PM_CONFIG 0x95
|
||||
#define PM_FEATURE 0x03
|
||||
|
||||
#define DISP_FREQ_MULTIPLIER 100
|
||||
|
||||
struct isst_clos_config {
|
||||
@ -119,6 +123,8 @@ struct isst_pkg_ctdp_level_info {
|
||||
int pbf_support;
|
||||
int fact_enabled;
|
||||
int pbf_enabled;
|
||||
int sst_cp_support;
|
||||
int sst_cp_enabled;
|
||||
int tdp_ratio;
|
||||
int active;
|
||||
int tdp_control;
|
||||
|
Loading…
Reference in New Issue
Block a user