Commit c76cd634 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v4.21-1' of git://git.infradead.org/linux-platform-drivers-x86

Pull x86 platform driver updates from Andy Shevchenko:

 - The USB Power Delivery discrete components now can be enumerated by
   i2c-multi-instantiate driver via several resources under single ACPI
   device node (ACPI ID is INT3515).

 - Touchscreen support is added for the Mediacom Flexbook Edge 11.

 - Mellanox driver got fixed due to updates in their firmware.

 - The power management stub driver for AtomISP v2 is fixed in order to
   support Intel Baytrail SoCs where same quirk is needed for S0ix to
   work.

 - Special key handling has been fixed for Favorites hotkey on Thinkpad,
   and Screen LOCK on ASUS.

 - Ideapad Yoga 2 13 has no HW rfkill switch, thus, driver has been
   updated to support this.

 - Few cleanups related to debugfs have been made in Intel IPS and Intel
   PMC drivers. Besides that Intel PMC has been extended to show more
   detailed information about Latency Tolerance

* tag 'platform-drivers-x86-v4.21-1' of git://git.infradead.org/linux-platform-drivers-x86: (41 commits)
  platform/x86: mlx-platform: Convert to use SPDX identifier
  Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces
  platform/x86: mlx-platform: Allow mlxreg-io driver activation for new systems
  platform/x86: mlx-platform: Fix LED configuration
  platform/x86: mlx-platform: Fix tachometer registers
  platform/x86: mlx-platform: Rename new systems product names
  platform/x86: mlx-platform: Add definitions for new registers
  platform/x86: intel_telemetry: convert to DEFINE_SHOW_ATTRIBUTE
  platform/x86: intel_pmc_core: convert to DEFINE_SHOW_ATTRIBUTE
  platform/x86: thinkpad_acpi: Cleanup quirks macros
  platform/x86: touchscreen_dmi: Add info for the Mediacom Flexbook Edge 11
  platform/x86: Fix config space access for intel_atomisp2_pm
  platform/x86: Add the VLV ISP PCI ID to atomisp2_pm
  platform/x86: intel_ips: Convert to use DEFINE_SHOW_ATTRIBUTE macro
  platform/x86: intel_ips: Remove never happen condition
  platform/x86: intel_ips: NULL check before some freeing functions is not needed
  platform/x86: intel_ips: remove unnecessary checks in ips_debugfs_init
  iio: inv_mpu6050: Use i2c_acpi_get_i2c_resource() helper
  ACPI / scan: Create platform device for INT3515 ACPI nodes
  platform/x86: i2c-multi-instantiate: Allow to have same slaves
  ...
parents 8fe28cb5 fb7255a9
...@@ -12,7 +12,6 @@ Description: This file shows ASIC health status. The possible values are: ...@@ -12,7 +12,6 @@ Description: This file shows ASIC health status. The possible values are:
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
cpld1_version cpld1_version
cpld2_version cpld2_version
Date: June 2018 Date: June 2018
KernelVersion: 4.19 KernelVersion: 4.19
Contact: Vadim Pasternak <vadimpmellanox.com> Contact: Vadim Pasternak <vadimpmellanox.com>
...@@ -21,6 +20,28 @@ Description: These files show with which CPLD versions have been burned ...@@ -21,6 +20,28 @@ Description: These files show with which CPLD versions have been burned
The files are read only. The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
cpld3_version
Date: November 2018
KernelVersion: 4.21
Contact: Vadim Pasternak <vadimpmellanox.com>
Description: These files show with which CPLD versions have been burned
on LED board.
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
jtag_enable
Date: November 2018
KernelVersion: 4.21
Contact: Vadim Pasternak <vadimpmellanox.com>
Description: These files enable and disable the access to the JTAG domain.
By default access to the JTAG domain is disabled.
The file is read/write.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/select_iio What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/select_iio
Date: June 2018 Date: June 2018
KernelVersion: 4.19 KernelVersion: 4.19
...@@ -76,3 +97,21 @@ Description: These files show the system reset cause, as following: power ...@@ -76,3 +97,21 @@ Description: These files show the system reset cause, as following: power
reset cause. reset cause.
The files are read only. The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
reset_comex_pwr_fail
reset_from_comex
reset_system
reset_voltmon_upgrade_fail
Date: November 2018
KernelVersion: 4.21
Contact: Vadim Pasternak <vadimpmellanox.com>
Description: These files show the system reset cause, as following: ComEx
power fail, reset from ComEx, system platform reset, reset
due to voltage monitor devices upgrade failure,
Value 1 in file means this is reset cause, 0 - otherwise.
Only one bit could be 1 at the same time, representing only
the last reset cause.
The files are read only.
...@@ -1541,6 +1541,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) ...@@ -1541,6 +1541,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
static const struct acpi_device_id i2c_multi_instantiate_ids[] = { static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
{"BSG1160", }, {"BSG1160", },
{"INT33FE", }, {"INT33FE", },
{"INT3515", },
{} {}
}; };
......
...@@ -45,6 +45,33 @@ struct i2c_acpi_lookup { ...@@ -45,6 +45,33 @@ struct i2c_acpi_lookup {
u32 min_speed; u32 min_speed;
}; };
/**
* i2c_acpi_get_i2c_resource - Gets I2cSerialBus resource if type matches
* @ares: ACPI resource
* @i2c: Pointer to I2cSerialBus resource will be returned here
*
* Checks if the given ACPI resource is of type I2cSerialBus.
* In this case, returns a pointer to it to the caller.
*
* Returns true if resource type is of I2cSerialBus, otherwise false.
*/
bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c)
{
struct acpi_resource_i2c_serialbus *sb;
if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
return false;
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
return false;
*i2c = sb;
return true;
}
EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource);
static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
{ {
struct i2c_acpi_lookup *lookup = data; struct i2c_acpi_lookup *lookup = data;
...@@ -52,11 +79,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) ...@@ -52,11 +79,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
struct acpi_resource_i2c_serialbus *sb; struct acpi_resource_i2c_serialbus *sb;
acpi_status status; acpi_status status;
if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb))
return 1;
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
return 1; return 1;
if (lookup->index != -1 && lookup->n++ != lookup->index) if (lookup->index != -1 && lookup->n++ != lookup->index)
...@@ -65,7 +88,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) ...@@ -65,7 +88,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
status = acpi_get_handle(lookup->device_handle, status = acpi_get_handle(lookup->device_handle,
sb->resource_source.string_ptr, sb->resource_source.string_ptr,
&lookup->adapter_handle); &lookup->adapter_handle);
if (!ACPI_SUCCESS(status)) if (ACPI_FAILURE(status))
return 1; return 1;
info->addr = sb->slave_address; info->addr = sb->slave_address;
...@@ -386,20 +409,22 @@ struct notifier_block i2c_acpi_notifier = { ...@@ -386,20 +409,22 @@ struct notifier_block i2c_acpi_notifier = {
* *
* Also see i2c_new_device, which this function calls to create the i2c-client. * Also see i2c_new_device, which this function calls to create the i2c-client.
* *
* Returns a pointer to the new i2c-client, or NULL if the adapter is not found. * Returns a pointer to the new i2c-client, or error pointer in case of failure.
* Specifically, -EPROBE_DEFER is returned if the adapter is not found.
*/ */
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_acpi_lookup lookup; struct i2c_acpi_lookup lookup;
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
struct i2c_client *client;
struct acpi_device *adev; struct acpi_device *adev;
LIST_HEAD(resource_list); LIST_HEAD(resource_list);
int ret; int ret;
adev = ACPI_COMPANION(dev); adev = ACPI_COMPANION(dev);
if (!adev) if (!adev)
return NULL; return ERR_PTR(-EINVAL);
memset(&lookup, 0, sizeof(lookup)); memset(&lookup, 0, sizeof(lookup));
lookup.info = info; lookup.info = info;
...@@ -408,16 +433,23 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, ...@@ -408,16 +433,23 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
ret = acpi_dev_get_resources(adev, &resource_list, ret = acpi_dev_get_resources(adev, &resource_list,
i2c_acpi_fill_info, &lookup); i2c_acpi_fill_info, &lookup);
if (ret < 0)
return ERR_PTR(ret);
acpi_dev_free_resource_list(&resource_list); acpi_dev_free_resource_list(&resource_list);
if (ret < 0 || !info->addr) if (!info->addr)
return NULL; return ERR_PTR(-EADDRNOTAVAIL);
adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle); adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
if (!adapter) if (!adapter)
return NULL; return ERR_PTR(-EPROBE_DEFER);
client = i2c_new_device(adapter, info);
if (!client)
return ERR_PTR(-ENODEV);
return i2c_new_device(adapter, info); return client;
} }
EXPORT_SYMBOL_GPL(i2c_acpi_new_device); EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
...@@ -525,13 +557,7 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command, ...@@ -525,13 +557,7 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command,
goto err; goto err;
} }
if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
ret = AE_BAD_PARAMETER;
goto err;
}
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
ret = AE_BAD_PARAMETER; ret = AE_BAD_PARAMETER;
goto err; goto err;
} }
......
...@@ -91,18 +91,14 @@ static int asus_acpi_get_sensor_info(struct acpi_device *adev, ...@@ -91,18 +91,14 @@ static int asus_acpi_get_sensor_info(struct acpi_device *adev,
static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data) static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data)
{ {
struct acpi_resource_i2c_serialbus *sb;
u32 *addr = data; u32 *addr = data;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { if (i2c_acpi_get_i2c_resource(ares, &sb)) {
struct acpi_resource_i2c_serialbus *sb; if (*addr)
*addr |= (sb->slave_address << 16);
sb = &ares->data.i2c_serial_bus; else
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { *addr = sb->slave_address;
if (*addr)
*addr |= (sb->slave_address << 16);
else
*addr = sb->slave_address;
}
} }
/* Tell the ACPI core that we already copied this address */ /* Tell the ACPI core that we already copied this address */
......
...@@ -442,8 +442,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { ...@@ -442,8 +442,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0x32, { KEY_MUTE } }, { KE_KEY, 0x32, { KEY_MUTE } },
{ KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */ { KE_KEY, 0x35, { KEY_SCREENLOCK } },
{ KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
{ KE_KEY, 0x41, { KEY_NEXTSONG } }, { KE_KEY, 0x41, { KEY_NEXTSONG } },
{ KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
......
...@@ -2131,7 +2131,8 @@ static int asus_wmi_add(struct platform_device *pdev) ...@@ -2131,7 +2131,8 @@ static int asus_wmi_add(struct platform_device *pdev)
err = asus_wmi_backlight_init(asus); err = asus_wmi_backlight_init(asus);
if (err && err != -ENODEV) if (err && err != -ENODEV)
goto fail_backlight; goto fail_backlight;
} } else
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
status = wmi_install_notify_handler(asus->driver->event_guid, status = wmi_install_notify_handler(asus->driver->event_guid,
asus_wmi_notify, asus); asus_wmi_notify, asus);
......
...@@ -1565,8 +1565,10 @@ static ssize_t kbd_led_timeout_store(struct device *dev, ...@@ -1565,8 +1565,10 @@ static ssize_t kbd_led_timeout_store(struct device *dev,
switch (unit) { switch (unit) {
case KBD_TIMEOUT_DAYS: case KBD_TIMEOUT_DAYS:
value *= 24; value *= 24;
/* fall through */
case KBD_TIMEOUT_HOURS: case KBD_TIMEOUT_HOURS:
value *= 60; value *= 60;
/* fall through */
case KBD_TIMEOUT_MINUTES: case KBD_TIMEOUT_MINUTES:
value *= 60; value *= 60;
unit = KBD_TIMEOUT_SECONDS; unit = KBD_TIMEOUT_SECONDS;
......
...@@ -7,15 +7,23 @@ ...@@ -7,15 +7,23 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h>
#define IRQ_RESOURCE_TYPE GENMASK(1, 0)
#define IRQ_RESOURCE_NONE 0
#define IRQ_RESOURCE_GPIO 1
#define IRQ_RESOURCE_APIC 2
struct i2c_inst_data { struct i2c_inst_data {
const char *type; const char *type;
int gpio_irq_idx; unsigned int flags;
int irq_idx;
}; };
struct i2c_multi_inst_data { struct i2c_multi_inst_data {
...@@ -23,6 +31,31 @@ struct i2c_multi_inst_data { ...@@ -23,6 +31,31 @@ struct i2c_multi_inst_data {
struct i2c_client *clients[0]; struct i2c_client *clients[0];
}; };
static int i2c_multi_inst_count(struct acpi_resource *ares, void *data)
{
struct acpi_resource_i2c_serialbus *sb;
int *count = data;
if (i2c_acpi_get_i2c_resource(ares, &sb))
*count = *count + 1;
return 1;
}
static int i2c_multi_inst_count_resources(struct acpi_device *adev)
{
LIST_HEAD(r);
int count = 0;
int ret;
ret = acpi_dev_get_resources(adev, &r, i2c_multi_inst_count, &count);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&r);
return count;
}
static int i2c_multi_inst_probe(struct platform_device *pdev) static int i2c_multi_inst_probe(struct platform_device *pdev)
{ {
struct i2c_multi_inst_data *multi; struct i2c_multi_inst_data *multi;
...@@ -44,40 +77,59 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) ...@@ -44,40 +77,59 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
adev = ACPI_COMPANION(dev); adev = ACPI_COMPANION(dev);
/* Count number of clients to instantiate */ /* Count number of clients to instantiate */
for (i = 0; inst_data[i].type; i++) {} ret = i2c_multi_inst_count_resources(adev);
if (ret < 0)
return ret;
multi = devm_kmalloc(dev, multi = devm_kmalloc(dev,
offsetof(struct i2c_multi_inst_data, clients[i]), offsetof(struct i2c_multi_inst_data, clients[ret]),
GFP_KERNEL); GFP_KERNEL);
if (!multi) if (!multi)
return -ENOMEM; return -ENOMEM;
multi->num_clients = i; multi->num_clients = ret;
for (i = 0; i < multi->num_clients; i++) { for (i = 0; i < multi->num_clients && inst_data[i].type; i++) {
memset(&board_info, 0, sizeof(board_info)); memset(&board_info, 0, sizeof(board_info));
strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE); strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE);
snprintf(name, sizeof(name), "%s-%s", match->id, snprintf(name, sizeof(name), "%s-%s.%d", match->id,
inst_data[i].type); inst_data[i].type, i);
board_info.dev_name = name; board_info.dev_name = name;
board_info.irq = 0; switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) {
if (inst_data[i].gpio_irq_idx != -1) { case IRQ_RESOURCE_GPIO:
ret = acpi_dev_gpio_irq_get(adev, ret = acpi_dev_gpio_irq_get(adev, inst_data[i].irq_idx);
inst_data[i].gpio_irq_idx);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Error requesting irq at index %d: %d\n", dev_err(dev, "Error requesting irq at index %d: %d\n",
inst_data[i].gpio_irq_idx, ret); inst_data[i].irq_idx, ret);
goto error; goto error;
} }
board_info.irq = ret; board_info.irq = ret;
break;
case IRQ_RESOURCE_APIC:
ret = platform_get_irq(pdev, inst_data[i].irq_idx);
if (ret < 0) {
dev_dbg(dev, "Error requesting irq at index %d: %d\n",
inst_data[i].irq_idx, ret);
}
board_info.irq = ret;
break;
default:
board_info.irq = 0;
break;
} }
multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info); multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info);
if (!multi->clients[i]) { if (IS_ERR(multi->clients[i])) {
dev_err(dev, "Error creating i2c-client, idx %d\n", i); ret = PTR_ERR(multi->clients[i]);
ret = -ENODEV; if (ret != -EPROBE_DEFER)
dev_err(dev, "Error creating i2c-client, idx %d\n", i);
goto error; goto error;
} }
} }
if (i < multi->num_clients) {
dev_err(dev, "Error finding driver, idx %d\n", i);
ret = -ENODEV;
goto error;
}
platform_set_drvdata(pdev, multi); platform_set_drvdata(pdev, multi);
return 0; return 0;
...@@ -101,9 +153,17 @@ static int i2c_multi_inst_remove(struct platform_device *pdev) ...@@ -101,9 +153,17 @@ static int i2c_multi_inst_remove(struct platform_device *pdev)
} }
static const struct i2c_inst_data bsg1160_data[] = { static const struct i2c_inst_data bsg1160_data[] = {
{ "bmc150_accel", 0 }, { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
{ "bmc150_magn", -1 }, { "bmc150_magn" },
{ "bmg160", -1 }, { "bmg160" },
{}
};
static const struct i2c_inst_data int3515_data[] = {
{ "tps6598x", IRQ_RESOURCE_APIC, 0 },
{ "tps6598x", IRQ_RESOURCE_APIC, 1 },
{ "tps6598x", IRQ_RESOURCE_APIC, 2 },
{ "tps6598x", IRQ_RESOURCE_APIC, 3 },
{} {}
}; };
...@@ -113,6 +173,7 @@ static const struct i2c_inst_data bsg1160_data[] = { ...@@ -113,6 +173,7 @@ static const struct i2c_inst_data bsg1160_data[] = {
*/ */
static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = { static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
{ "BSG1160", (unsigned long)bsg1160_data }, { "BSG1160", (unsigned long)bsg1160_data },
{ "INT3515", (unsigned long)int3515_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids); MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
......
...@@ -1188,6 +1188,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { ...@@ -1188,6 +1188,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_BOARD_NAME, "Yoga2"), DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
}, },
}, },
{
.ident = "Lenovo Yoga 2 13",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Yoga 2 13"),
},
},
{ {
.ident = "Lenovo Yoga 3 1170 / 1470", .ident = "Lenovo Yoga 3 1170 / 1470",
.matches = { .matches = {
......
...@@ -33,46 +33,45 @@ ...@@ -33,46 +33,45 @@
#define ISPSSPM0_IUNIT_POWER_ON 0x0 #define ISPSSPM0_IUNIT_POWER_ON 0x0
#define ISPSSPM0_IUNIT_POWER_OFF 0x3 #define ISPSSPM0_IUNIT_POWER_OFF 0x3
static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id) static int isp_set_power(struct pci_dev *dev, bool enable)
{ {
unsigned long timeout; unsigned long timeout;
u32 val; u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON :
ISPSSPM0_IUNIT_POWER_OFF;
pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, 0);
/*
* MRFLD IUNIT DPHY is located in an always-power-on island
* MRFLD HW design need all CSI ports are disabled before
* powering down the IUNIT.
*/
pci_read_config_dword(dev, PCI_CSI_CONTROL, &val);
val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
pci_write_config_dword(dev, PCI_CSI_CONTROL, val);
/* Write 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */ /* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */
iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0,
ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK); val, ISPSSPM0_ISPSSC_MASK);
/* /*
* There should be no IUNIT access while power-down is * 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. * 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); timeout = jiffies + msecs_to_jiffies(50);
while (1) { while (1) {
/* Wait until ISPSSPM0 bit[25:24] shows 0x3 */ u32 tmp;
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val);
val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET; /* Wait until ISPSSPM0 bit[25:24] shows the right value */
if (val == ISPSSPM0_IUNIT_POWER_OFF) iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &tmp);
tmp = (tmp & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
if (tmp == val)
break; break;
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
dev_err(&dev->dev, "IUNIT power-off timeout.\n"); dev_err(&dev->dev, "IUNIT power-%s timeout.\n",
enable ? "on" : "off");
return -EBUSY; return -EBUSY;
} }
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
return 0;
}
static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
pm_runtime_allow(&dev->dev); pm_runtime_allow(&dev->dev);
pm_runtime_put_sync_suspend(&dev->dev); pm_runtime_put_sync_suspend(&dev->dev);
...@@ -87,11 +86,40 @@ static void isp_remove(struct pci_dev *dev) ...@@ -87,11 +86,40 @@ static void isp_remove(struct pci_dev *dev)
static int isp_pci_suspend(struct device *dev) static int isp_pci_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
u32 val;
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, 0);
/*
* MRFLD IUNIT DPHY is located in an always-power-on island
* MRFLD HW design need all CSI ports are disabled before
* powering down the IUNIT.
*/
pci_read_config_dword(pdev, PCI_CSI_CONTROL, &val);
val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
pci_write_config_dword(pdev, PCI_CSI_CONTROL, val);
/*
* We lose config space access when punit power gates
* the ISP. Can't use pci_set_power_state() because
* pmcsr won't actually change when we write to it.
*/
pci_save_state(pdev);
pdev->current_state = PCI_D3cold;
isp_set_power(pdev, false);
return 0; return 0;
} }
static int isp_pci_resume(struct device *dev) static int isp_pci_resume(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
isp_set_power(pdev, true);
pdev->current_state = PCI_D0;
pci_restore_state(pdev);
return 0; return 0;
} }
...@@ -99,6 +127,7 @@ static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend, ...@@ -99,6 +127,7 @@ static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend,
isp_pci_resume, NULL); isp_pci_resume, NULL);
static const struct pci_device_id isp_id_table[] = { static const struct pci_device_id isp_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x0f38), },
{ PCI_VDEVICE(INTEL, 0x22b8), }, { PCI_VDEVICE(INTEL, 0x22b8), },
{ 0, } { 0, }
}; };
......
...@@ -168,8 +168,8 @@ static int cht_int33fe_probe(struct platform_device *pdev) ...@@ -168,8 +168,8 @@ static int cht_int33fe_probe(struct platform_device *pdev)
board_info.dev_name = "max17047"; board_info.dev_name = "max17047";
board_info.properties = max17047_props; board_info.properties = max17047_props;
data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
if (!data->max17047) if (IS_ERR(data->max17047))
return -EPROBE_DEFER; /* Wait for i2c-adapter to load */ return PTR_ERR(data->max17047);
} }
data->connections[0].endpoint[0] = "port0"; data->connections[0].endpoint[0] = "port0";
...@@ -194,16 +194,20 @@ static int cht_int33fe_probe(struct platform_device *pdev) ...@@ -194,16 +194,20 @@ static int cht_int33fe_probe(struct platform_device *pdev)
board_info.irq = fusb302_irq; board_info.irq = fusb302_irq;
data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info);
if (!data->fusb302) if (IS_ERR(data->fusb302)) {
ret = PTR_ERR(data->fusb302);
goto out_unregister_max17047; goto out_unregister_max17047;
}
memset(&board_info, 0, sizeof(board_info)); memset(&board_info, 0, sizeof(board_info));
board_info.dev_name = "pi3usb30532"; board_info.dev_name = "pi3usb30532";
strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE);
data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info);
if (!data->pi3usb30532) if (IS_ERR(data->pi3usb30532)) {
ret = PTR_ERR(data->pi3usb30532);
goto out_unregister_fusb302; goto out_unregister_fusb302;
}
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
...@@ -213,12 +217,11 @@ static int cht_int33fe_probe(struct platform_device *pdev) ...@@ -213,12 +217,11 @@ static int cht_int33fe_probe(struct platform_device *pdev)
i2c_unregister_device(data->fusb302); i2c_unregister_device(data->fusb302);
out_unregister_max17047: out_unregister_max17047:
if (data->max17047) i2c_unregister_device(data->max17047);
i2c_unregister_device(data->max17047);
device_connections_remove(data->connections); device_connections_remove(data->connections);
return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ return ret;
} }
static int cht_int33fe_remove(struct platform_device *pdev) static int cht_int33fe_remove(struct platform_device *pdev)
...@@ -227,8 +230,7 @@ static int cht_int33fe_remove(struct platform_device *pdev) ...@@ -227,8 +230,7 @@ static int cht_int33fe_remove(struct platform_device *pdev)
i2c_unregister_device(data->pi3usb30532); i2c_unregister_device(data->pi3usb30532);
i2c_unregister_device(data->fusb302); i2c_unregister_device(data->fusb302);
if (data->max17047) i2c_unregister_device(data->max17047);
i2c_unregister_device(data->max17047);
device_connections_remove(data->connections); device_connections_remove(data->connections);
......
...@@ -1210,13 +1210,7 @@ static void ips_debugfs_cleanup(struct ips_driver *ips) { return; } ...@@ -1210,13 +1210,7 @@ static void ips_debugfs_cleanup(struct ips_driver *ips) { return; }
/* Expose current state and limits in debugfs if possible */ /* Expose current state and limits in debugfs if possible */
struct ips_debugfs_node { static int cpu_temp_show(struct seq_file *m, void *data)
struct ips_driver *ips;
char *name;
int (*show)(struct seq_file *m, void *data);
};
static int show_cpu_temp(struct seq_file *m, void *data)
{ {
struct ips_driver *ips = m->private; struct ips_driver *ips = m->private;
...@@ -1225,8 +1219,9 @@ static int show_cpu_temp(struct seq_file *m, void *data) ...@@ -1225,8 +1219,9 @@ static int show_cpu_temp(struct seq_file *m, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(cpu_temp);
static int show_cpu_power(struct seq_file *m, void *data) static int cpu_power_show(struct seq_file *m, void *data)
{ {
struct ips_driver *ips = m->private; struct ips_driver *ips = m->private;
...@@ -1234,8 +1229,9 @@ static int show_cpu_power(struct seq_file *m, void *data) ...@@ -1234,8 +1229,9 @@ static int show_cpu_power(struct seq_file *m, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(cpu_power);
static int show_cpu_clamp(struct seq_file *m, void *data) static int cpu_clamp_show(struct seq_file *m, void *data)
{ {
u64 turbo_override; u64 turbo_override;
int tdp, tdc; int tdp, tdc;
...@@ -1255,8 +1251,9 @@ static int show_cpu_clamp(struct seq_file *m, void *data) ...@@ -1255,8 +1251,9 @@ static int show_cpu_clamp(struct seq_file *m, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(cpu_clamp);
static int show_mch_temp(struct seq_file *m, void *data) static int mch_temp_show(struct seq_file *m, void *data)
{ {
struct ips_driver *ips = m->private; struct ips_driver *ips = m->private;
...@@ -1265,8 +1262,9 @@ static int show_mch_temp(struct seq_file *m, void *data) ...@@ -1265,8 +1262,9 @@ static int show_mch_temp(struct seq_file *m, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(mch_temp);
static int show_mch_power(struct seq_file *m, void *data) static int mch_power_show(struct seq_file *m, void *data)
{ {
struct ips_driver *ips = m->private; struct ips_driver *ips = m->private;
...@@ -1274,68 +1272,22 @@ static int show_mch_power(struct seq_file *m, void *data) ...@@ -1274,68 +1272,22 @@ static int show_mch_power(struct seq_file *m, void *data)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(mch_power);
static struct ips_debugfs_node ips_debug_files[] = {
{ NULL, "cpu_temp", show_cpu_temp },
{ NULL, "cpu_power", show_cpu_power },
{ NULL, "cpu_clamp", show_cpu_clamp },
{ NULL, "mch_temp", show_mch_temp },
{ NULL, "mch_power", show_mch_power },
};
static int ips_debugfs_open(struct inode *inode, struct file *file)
{
struct ips_debugfs_node *node = inode->i_private;
return single_open(file, node->show, node->ips);
}
static const struct file_operations ips_debugfs_ops = {
.owner = THIS_MODULE,
.open = ips_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void ips_debugfs_cleanup(struct ips_driver *ips) static void ips_debugfs_cleanup(struct ips_driver *ips)
{ {
if (ips->debug_root) debugfs_remove_recursive(ips->debug_root);
debugfs_remove_recursive(ips->debug_root);
return;
} }
static void ips_debugfs_init(struct ips_driver *ips) static void ips_debugfs_init(struct ips_driver *ips)
{ {
int i;
ips->debug_root = debugfs_create_dir("ips", NULL); ips->debug_root = debugfs_create_dir("ips", NULL);
if (!ips->debug_root) {
dev_err(ips->dev, "failed to create debugfs entries: %ld\n",
PTR_ERR(ips->debug_root));
return;
}
for (i = 0; i < ARRAY_SIZE(ips_debug_files); i++) { debugfs_create_file("cpu_temp", 0444, ips->debug_root, ips, &cpu_temp_fops);
struct dentry *ent; debugfs_create_file("cpu_power", 0444, ips->debug_root, ips, &cpu_power_fops);
struct ips_debugfs_node *node = &ips_debug_files[i]; debugfs_create_file("cpu_clamp", 0444, ips->debug_root, ips, &cpu_clamp_fops);
debugfs_create_file("mch_temp", 0444, ips->debug_root, ips, &mch_temp_fops);
node->ips = ips; debugfs_create_file("mch_power", 0444, ips->debug_root, ips, &mch_power_fops);
ent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
ips->debug_root, node,
&ips_debugfs_ops);
if (!ent) {
dev_err(ips->dev, "failed to create debug file: %ld\n",
PTR_ERR(ent));
goto err_cleanup;
}
}
return;
err_cleanup:
ips_debugfs_cleanup(ips);
return;
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
...@@ -1646,9 +1598,6 @@ static void ips_remove(struct pci_dev *dev) ...@@ -1646,9 +1598,6 @@ static void ips_remove(struct pci_dev *dev)
struct ips_driver *ips = pci_get_drvdata(dev); struct ips_driver *ips = pci_get_drvdata(dev);
u64 turbo_override; u64 turbo_override;
if (!ips)
return;
ips_debugfs_cleanup(ips); ips_debugfs_cleanup(ips);
/* Release i915 driver */ /* Release i915 driver */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -101,10 +102,35 @@ static const struct pmc_bit_map spt_pfear_map[] = { ...@@ -101,10 +102,35 @@ static const struct pmc_bit_map spt_pfear_map[] = {
{}, {},
}; };
static const struct pmc_bit_map spt_ltr_show_map[] = {
{"SOUTHPORT_A", SPT_PMC_LTR_SPA},
{"SOUTHPORT_B", SPT_PMC_LTR_SPB},
{"SATA", SPT_PMC_LTR_SATA},
{"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE},
{"XHCI", SPT_PMC_LTR_XHCI},
{"ME", SPT_PMC_LTR_ME},
/* EVA is Enterprise Value Add, doesn't really exist on PCH */
{"EVA", SPT_PMC_LTR_EVA},
{"SOUTHPORT_C", SPT_PMC_LTR_SPC},
{"HD_AUDIO", SPT_PMC_LTR_AZ},
{"LPSS", SPT_PMC_LTR_LPSS},
{"SOUTHPORT_D", SPT_PMC_LTR_SPD},
{"SOUTHPORT_E", SPT_PMC_LTR_SPE},
{"CAMERA", SPT_PMC_LTR_CAM},
{"ESPI", SPT_PMC_LTR_ESPI},
{"SCC", SPT_PMC_LTR_SCC},
{"ISH", SPT_PMC_LTR_ISH},
/* Below two cannot be used for LTR_IGNORE */
{"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT},
{"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT},
{}
};
static const struct pmc_reg_map spt_reg_map = { static const struct pmc_reg_map spt_reg_map = {
.pfear_sts = spt_pfear_map, .pfear_sts = spt_pfear_map,
.mphy_sts = spt_mphy_map, .mphy_sts = spt_mphy_map,
.pll_sts = spt_pll_map, .pll_sts = spt_pll_map,
.ltr_show_sts = spt_ltr_show_map,
.slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET,
.ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET,
.regmap_length = SPT_PMC_MMIO_REG_LEN, .regmap_length = SPT_PMC_MMIO_REG_LEN,
...@@ -112,6 +138,7 @@ static const struct pmc_reg_map spt_reg_map = { ...@@ -112,6 +138,7 @@ static const struct pmc_reg_map spt_reg_map = {
.ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED,
}; };
/* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */ /* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */
...@@ -243,10 +270,38 @@ static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { ...@@ -243,10 +270,38 @@ static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
NULL, NULL,
}; };
static const struct pmc_bit_map cnp_ltr_show_map[] = {
{"SOUTHPORT_A", CNP_PMC_LTR_SPA},
{"SOUTHPORT_B", CNP_PMC_LTR_SPB},
{"SATA", CNP_PMC_LTR_SATA},
{"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE},
{"XHCI", CNP_PMC_LTR_XHCI},
{"ME", CNP_PMC_LTR_ME},
/* EVA is Enterprise Value Add, doesn't really exist on PCH */
{"EVA", CNP_PMC_LTR_EVA},
{"SOUTHPORT_C", CNP_PMC_LTR_SPC},
{"HD_AUDIO", CNP_PMC_LTR_AZ},
{"CNV", CNP_PMC_LTR_CNV},
{"LPSS", CNP_PMC_LTR_LPSS},
{"SOUTHPORT_D", CNP_PMC_LTR_SPD},
{"SOUTHPORT_E", CNP_PMC_LTR_SPE},
{"CAMERA", CNP_PMC_LTR_CAM},
{"ESPI", CNP_PMC_LTR_ESPI},
{"SCC", CNP_PMC_LTR_SCC},
{"ISH", CNP_PMC_LTR_ISH},
{"UFSX2", CNP_PMC_LTR_UFSX2},
{"EMMC", CNP_PMC_LTR_EMMC},
/* Below two cannot be used for LTR_IGNORE */
{"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT},
{"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT},
{}
};
static const struct pmc_reg_map cnp_reg_map = { static const struct pmc_reg_map cnp_reg_map = {
.pfear_sts = cnp_pfear_map, .pfear_sts = cnp_pfear_map,
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
.slps0_dbg_maps = cnp_slps0_dbg_maps, .slps0_dbg_maps = cnp_slps0_dbg_maps,
.ltr_show_sts = cnp_ltr_show_map,
.slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.regmap_length = CNP_PMC_MMIO_REG_LEN, .regmap_length = CNP_PMC_MMIO_REG_LEN,
...@@ -254,6 +309,7 @@ static const struct pmc_reg_map cnp_reg_map = { ...@@ -254,6 +309,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED,
}; };
static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset)
...@@ -311,7 +367,7 @@ static void pmc_core_display_map(struct seq_file *s, int index, ...@@ -311,7 +367,7 @@ static void pmc_core_display_map(struct seq_file *s, int index,
pf_map[index].bit_mask & pf_reg ? "Off" : "On"); pf_map[index].bit_mask & pf_reg ? "Off" : "On");
} }
static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused) static int pmc_core_ppfear_show(struct seq_file *s, void *unused)
{ {
struct pmc_dev *pmcdev = s->private; struct pmc_dev *pmcdev = s->private;
const struct pmc_bit_map *map = pmcdev->map->pfear_sts; const struct pmc_bit_map *map = pmcdev->map->pfear_sts;
...@@ -329,18 +385,7 @@ static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused) ...@@ -329,18 +385,7 @@ static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear);
static int pmc_core_ppfear_sts_open(struct inode *inode, struct file *file)
{
return single_open(file, pmc_core_ppfear_sts_show, inode->i_private);
}
static const struct file_operations pmc_core_ppfear_ops = {
.open = pmc_core_ppfear_sts_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* This function should return link status, 0 means ready */ /* This function should return link status, 0 means ready */
static int pmc_core_mtpmc_link_status(void) static int pmc_core_mtpmc_link_status(void)
...@@ -372,7 +417,7 @@ static int pmc_core_send_msg(u32 *addr_xram) ...@@ -372,7 +417,7 @@ static int pmc_core_send_msg(u32 *addr_xram)
return 0; return 0;
} }
static int pmc_core_mphy_pg_sts_show(struct seq_file *s, void *unused) static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused)
{ {
struct pmc_dev *pmcdev = s->private; struct pmc_dev *pmcdev = s->private;
const struct pmc_bit_map *map = pmcdev->map->mphy_sts; const struct pmc_bit_map *map = pmcdev->map->mphy_sts;
...@@ -424,18 +469,7 @@ static int pmc_core_mphy_pg_sts_show(struct seq_file *s, void *unused) ...@@ -424,18 +469,7 @@ static int pmc_core_mphy_pg_sts_show(struct seq_file *s, void *unused)
mutex_unlock(&pmcdev->lock); mutex_unlock(&pmcdev->lock);
return err; return err;
} }
DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg);
static int pmc_core_mphy_pg_sts_open(struct inode *inode, struct file *file)
{
return single_open(file, pmc_core_mphy_pg_sts_show, inode->i_private);
}
static const struct file_operations pmc_core_mphy_pg_ops = {
.open = pmc_core_mphy_pg_sts_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int pmc_core_pll_show(struct seq_file *s, void *unused) static int pmc_core_pll_show(struct seq_file *s, void *unused)
{ {
...@@ -471,18 +505,7 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused) ...@@ -471,18 +505,7 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused)
mutex_unlock(&pmcdev->lock); mutex_unlock(&pmcdev->lock);
return err; return err;
} }
DEFINE_SHOW_ATTRIBUTE(pmc_core_pll);
static int pmc_core_pll_open(struct inode *inode, struct file *file)
{
return single_open(file, pmc_core_pll_show, inode->i_private);
}
static const struct file_operations pmc_core_pll_ops = {
.open = pmc_core_pll_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
*userbuf, size_t count, loff_t *ppos) *userbuf, size_t count, loff_t *ppos)
...@@ -500,7 +523,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user ...@@ -500,7 +523,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
goto out_unlock; goto out_unlock;
} }
if (val > NUM_IP_IGN_ALLOWED) { if (val > map->ltr_ignore_max) {
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
} }
...@@ -583,6 +606,77 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) ...@@ -583,6 +606,77 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)
} }
DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg);
static u32 convert_ltr_scale(u32 val)
{
/*
* As per PCIE specification supporting document
* ECN_LatencyTolnReporting_14Aug08.pdf the Latency
* Tolerance Reporting data payload is encoded in a
* 3 bit scale and 10 bit value fields. Values are
* multiplied by the indicated scale to yield an absolute time
* value, expressible in a range from 1 nanosecond to
* 2^25*(2^10-1) = 34,326,183,936 nanoseconds.
*
* scale encoding is as follows:
*
* ----------------------------------------------
* |scale factor | Multiplier (ns) |
* ----------------------------------------------
* | 0 | 1 |
* | 1 | 32 |
* | 2 | 1024 |
* | 3 | 32768 |
* | 4 | 1048576 |
* | 5 | 33554432 |
* | 6 | Invalid |
* | 7 | Invalid |
* ----------------------------------------------
*/
if (val > 5) {
pr_warn("Invalid LTR scale factor.\n");
return 0;
}
return 1U << (5 * val);
}
static int pmc_core_ltr_show(struct seq_file *s, void *unused)
{
struct pmc_dev *pmcdev = s->private;
const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts;
u64 decoded_snoop_ltr, decoded_non_snoop_ltr;
u32 ltr_raw_data, scale, val;
u16 snoop_ltr, nonsnoop_ltr;
int index;
for (index = 0; map[index].name ; index++) {
decoded_snoop_ltr = decoded_non_snoop_ltr = 0;
ltr_raw_data = pmc_core_reg_read(pmcdev,
map[index].bit_mask);
snoop_ltr = ltr_raw_data & ~MTPMC_MASK;
nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK;
if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) {
scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr);
val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr);
decoded_non_snoop_ltr = val * convert_ltr_scale(scale);
}
if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) {
scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr);
val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr);
decoded_snoop_ltr = val * convert_ltr_scale(scale);
}
seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n",
map[index].name, ltr_raw_data,
decoded_non_snoop_ltr,
decoded_snoop_ltr);
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr);
static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
{ {
debugfs_remove_recursive(pmcdev->dbgfs_dir); debugfs_remove_recursive(pmcdev->dbgfs_dir);
...@@ -602,19 +696,21 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) ...@@ -602,19 +696,21 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
&pmc_core_dev_state); &pmc_core_dev_state);
debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev, debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev,
&pmc_core_ppfear_ops); &pmc_core_ppfear_fops);
debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, debugfs_create_file("ltr_ignore", 0644, dir, pmcdev,
&pmc_core_ltr_ignore_ops); &pmc_core_ltr_ignore_ops);
debugfs_create_file("ltr_show", 0644, dir, pmcdev, &pmc_core_ltr_fops);
if (pmcdev->map->pll_sts) if (pmcdev->map->pll_sts)
debugfs_create_file("pll_status", 0444, dir, pmcdev, debugfs_create_file("pll_status", 0444, dir, pmcdev,
&pmc_core_pll_ops); &pmc_core_pll_fops);
if (pmcdev->map->mphy_sts) if (pmcdev->map->mphy_sts)
debugfs_create_file("mphy_core_lanes_power_gating_status", debugfs_create_file("mphy_core_lanes_power_gating_status",
0444, dir, pmcdev, 0444, dir, pmcdev,
&pmc_core_mphy_pg_ops); &pmc_core_mphy_pg_fops);
if (pmcdev->map->slps0_dbg_maps) { if (pmcdev->map->slps0_dbg_maps) {
debugfs_create_file("slp_s0_debug_status", 0444, debugfs_create_file("slp_s0_debug_status", 0444,
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#ifndef PMC_CORE_H #ifndef PMC_CORE_H
#define PMC_CORE_H #define PMC_CORE_H
#include <linux/bits.h>
#define PMC_BASE_ADDR_DEFAULT 0xFE000000 #define PMC_BASE_ADDR_DEFAULT 0xFE000000
/* Sunrise Point Power Management Controller PCI Device ID */ /* Sunrise Point Power Management Controller PCI Device ID */
...@@ -35,7 +37,26 @@ ...@@ -35,7 +37,26 @@
#define SPT_PMC_READ_DISABLE_BIT 0x16 #define SPT_PMC_READ_DISABLE_BIT 0x16
#define SPT_PMC_MSG_FULL_STS_BIT 0x18 #define SPT_PMC_MSG_FULL_STS_BIT 0x18
#define NUM_RETRIES 100 #define NUM_RETRIES 100
#define NUM_IP_IGN_ALLOWED 17 #define SPT_NUM_IP_IGN_ALLOWED 17
#define SPT_PMC_LTR_CUR_PLT 0x350
#define SPT_PMC_LTR_CUR_ASLT 0x354
#define SPT_PMC_LTR_SPA 0x360
#define SPT_PMC_LTR_SPB 0x364
#define SPT_PMC_LTR_SATA 0x368
#define SPT_PMC_LTR_GBE 0x36C
#define SPT_PMC_LTR_XHCI 0x370
#define SPT_PMC_LTR_ME 0x378
#define SPT_PMC_LTR_EVA 0x37C
#define SPT_PMC_LTR_SPC 0x380
#define SPT_PMC_LTR_AZ 0x384
#define SPT_PMC_LTR_LPSS 0x38C
#define SPT_PMC_LTR_CAM 0x390
#define SPT_PMC_LTR_SPD 0x394
#define SPT_PMC_LTR_SPE 0x398
#define SPT_PMC_LTR_ESPI 0x39C
#define SPT_PMC_LTR_SCC 0x3A0
#define SPT_PMC_LTR_ISH 0x3A4
/* Sunrise Point: PGD PFET Enable Ack Status Registers */ /* Sunrise Point: PGD PFET Enable Ack Status Registers */
enum ppfear_regs { enum ppfear_regs {
...@@ -115,18 +136,46 @@ enum ppfear_regs { ...@@ -115,18 +136,46 @@ enum ppfear_regs {
#define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3) #define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3)
/* Cannonlake Power Management Controller register offsets */ /* Cannonlake Power Management Controller register offsets */
#define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C
#define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C
#define CNP_PMC_PM_CFG_OFFSET 0x1818
#define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4
#define CNP_PMC_PM_CFG_OFFSET 0x1818
#define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C
#define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C
/* Cannonlake: PGD PFET Enable Ack Status Register(s) start */ /* Cannonlake: PGD PFET Enable Ack Status Register(s) start */
#define CNP_PMC_HOST_PPFEAR0A 0x1D90 #define CNP_PMC_HOST_PPFEAR0A 0x1D90
#define CNP_PMC_MMIO_REG_LEN 0x2000
#define CNP_PPFEAR_NUM_ENTRIES 8
#define CNP_PMC_READ_DISABLE_BIT 22
#define CNP_PMC_LATCH_SLPS0_EVENTS BIT(31) #define CNP_PMC_LATCH_SLPS0_EVENTS BIT(31)
#define CNP_PMC_MMIO_REG_LEN 0x2000
#define CNP_PPFEAR_NUM_ENTRIES 8
#define CNP_PMC_READ_DISABLE_BIT 22
#define CNP_NUM_IP_IGN_ALLOWED 19
#define CNP_PMC_LTR_CUR_PLT 0x1B50
#define CNP_PMC_LTR_CUR_ASLT 0x1B54
#define CNP_PMC_LTR_SPA 0x1B60
#define CNP_PMC_LTR_SPB 0x1B64
#define CNP_PMC_LTR_SATA 0x1B68
#define CNP_PMC_LTR_GBE 0x1B6C
#define CNP_PMC_LTR_XHCI 0x1B70
#define CNP_PMC_LTR_ME 0x1B78
#define CNP_PMC_LTR_EVA 0x1B7C
#define CNP_PMC_LTR_SPC 0x1B80
#define CNP_PMC_LTR_AZ 0x1B84
#define CNP_PMC_LTR_LPSS 0x1B8C
#define CNP_PMC_LTR_CAM 0x1B90
#define CNP_PMC_LTR_SPD 0x1B94
#define CNP_PMC_LTR_SPE 0x1B98
#define CNP_PMC_LTR_ESPI 0x1B9C
#define CNP_PMC_LTR_SCC 0x1BA0
#define CNP_PMC_LTR_ISH 0x1BA4
#define CNP_PMC_LTR_CNV 0x1BF0
#define CNP_PMC_LTR_EMMC 0x1BF4
#define CNP_PMC_LTR_UFSX2 0x1BF8
#define LTR_DECODED_VAL GENMASK(9, 0)
#define LTR_DECODED_SCALE GENMASK(12, 10)
#define LTR_REQ_SNOOP BIT(15)
#define LTR_REQ_NONSNOOP BIT(31)
struct pmc_bit_map { struct pmc_bit_map {
const char *name; const char *name;
u32 bit_mask; u32 bit_mask;
...@@ -139,6 +188,7 @@ struct pmc_bit_map { ...@@ -139,6 +188,7 @@ struct pmc_bit_map {
* @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit * @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit
* @pll_sts: Maps name of PLL to corresponding bit status * @pll_sts: Maps name of PLL to corresponding bit status
* @slps0_dbg_maps: Array of SLP_S0_DBG* registers containing debug info * @slps0_dbg_maps: Array of SLP_S0_DBG* registers containing debug info
* @ltr_show_sts: Maps PCH IP Names to their MMIO register offsets
* @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency * @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency
* @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit
* @regmap_length: Length of memory to map from PWRMBASE address to access * @regmap_length: Length of memory to map from PWRMBASE address to access
...@@ -157,6 +207,7 @@ struct pmc_reg_map { ...@@ -157,6 +207,7 @@ struct pmc_reg_map {
const struct pmc_bit_map *mphy_sts; const struct pmc_bit_map *mphy_sts;
const struct pmc_bit_map *pll_sts; const struct pmc_bit_map *pll_sts;
const struct pmc_bit_map **slps0_dbg_maps; const struct pmc_bit_map **slps0_dbg_maps;
const struct pmc_bit_map *ltr_show_sts;
const u32 slp_s0_offset; const u32 slp_s0_offset;
const u32 ltr_ignore_offset; const u32 ltr_ignore_offset;
const int regmap_length; const int regmap_length;
...@@ -165,6 +216,7 @@ struct pmc_reg_map { ...@@ -165,6 +216,7 @@ struct pmc_reg_map {
const u32 pm_cfg_offset; const u32 pm_cfg_offset;
const int pm_read_disable_bit; const int pm_read_disable_bit;
const u32 slps0_dbg_offset; const u32 slps0_dbg_offset;
const u32 ltr_ignore_max;
}; };
/** /**
......
...@@ -466,17 +466,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) ...@@ -466,17 +466,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int telem_pss_state_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(telem_pss_states);
{
return single_open(file, telem_pss_states_show, inode->i_private);
}
static const struct file_operations telem_pss_ops = {
.open = telem_pss_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int telem_ioss_states_show(struct seq_file *s, void *unused) static int telem_ioss_states_show(struct seq_file *s, void *unused)
{ {
...@@ -505,17 +495,7 @@ static int telem_ioss_states_show(struct seq_file *s, void *unused) ...@@ -505,17 +495,7 @@ static int telem_ioss_states_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int telem_ioss_state_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);
{
return single_open(file, telem_ioss_states_show, inode->i_private);
}
static const struct file_operations telem_ioss_ops = {
.open = telem_ioss_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int telem_soc_states_show(struct seq_file *s, void *unused) static int telem_soc_states_show(struct seq_file *s, void *unused)
{ {
...@@ -664,17 +644,7 @@ static int telem_soc_states_show(struct seq_file *s, void *unused) ...@@ -664,17 +644,7 @@ static int telem_soc_states_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int telem_soc_state_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(telem_soc_states);
{
return single_open(file, telem_soc_states_show, inode->i_private);
}
static const struct file_operations telem_socstate_ops = {
.open = telem_soc_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int telem_s0ix_res_get(void *data, u64 *val) static int telem_s0ix_res_get(void *data, u64 *val)
{ {
...@@ -960,7 +930,7 @@ static int __init telemetry_debugfs_init(void) ...@@ -960,7 +930,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO, f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, NULL, debugfs_conf->telemetry_dbg_dir, NULL,
&telem_pss_ops); &telem_pss_states_fops);
if (!f) { if (!f) {
pr_err("pss_sample_info debugfs register failed\n"); pr_err("pss_sample_info debugfs register failed\n");
goto out; goto out;
...@@ -968,7 +938,7 @@ static int __init telemetry_debugfs_init(void) ...@@ -968,7 +938,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, f = debugfs_create_file("ioss_info", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, NULL, debugfs_conf->telemetry_dbg_dir, NULL,
&telem_ioss_ops); &telem_ioss_states_fops);
if (!f) { if (!f) {
pr_err("ioss_sample_info debugfs register failed\n"); pr_err("ioss_sample_info debugfs register failed\n");
goto out; goto out;
...@@ -976,7 +946,7 @@ static int __init telemetry_debugfs_init(void) ...@@ -976,7 +946,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("soc_states", S_IFREG | S_IRUGO, f = debugfs_create_file("soc_states", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, debugfs_conf->telemetry_dbg_dir,
NULL, &telem_socstate_ops); NULL, &telem_soc_states_fops);
if (!f) { if (!f) {
pr_err("ioss_sample_info debugfs register failed\n"); pr_err("ioss_sample_info debugfs register failed\n");
goto out; goto out;
......
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/* /*
* Copyright (c) 2016 Mellanox Technologies. All rights reserved. * Mellanox platform driver
* Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
* *
* Redistribution and use in source and binary forms, with or without * Copyright (C) 2016-2018 Mellanox Technologies
* modification, are permitted provided that the following conditions are met: * Copyright (C) 2016-2018 Vadim Pasternak <vadimp@mellanox.com>
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <linux/device.h> #include <linux/device.h>
...@@ -49,7 +24,10 @@ ...@@ -49,7 +24,10 @@
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00
#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
...@@ -83,12 +61,12 @@ ...@@ -83,12 +61,12 @@
#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 #define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7
#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 #define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8
#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 #define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9
#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea #define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xeb
#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb #define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xec
#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec #define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xed
#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed #define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee
#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee #define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef
#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef #define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
...@@ -1101,6 +1079,118 @@ static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { ...@@ -1101,6 +1079,118 @@ static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = {
.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data),
}; };
/* Platform register access for next generation systems families data */
static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
{
.label = "cpld1_version",
.reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
.bit = GENMASK(7, 0),
.mode = 0444,
},
{
.label = "cpld2_version",
.reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
.bit = GENMASK(7, 0),
.mode = 0444,
},
{
.label = "cpld3_version",
.reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET,
.bit = GENMASK(7, 0),
.mode = 0444,
},
{
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
.mode = 0444,
},
{
.label = "reset_short_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(1),
.mode = 0444,
},
{
.label = "reset_aux_pwr_or_ref",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(2),
.mode = 0444,
},
{
.label = "reset_from_comex",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(4),
.mode = 0444,
},
{
.label = "reset_asic_thermal",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(7),
.mode = 0444,
},
{
.label = "reset_comex_pwr_fail",
.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(3),
.mode = 0444,
},
{
.label = "reset_voltmon_upgrade_fail",
.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
.mode = 0444,
},
{
.label = "reset_system",
.reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(1),
.mode = 0444,
},
{
.label = "psu1_on",
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
.mode = 0200,
},
{
.label = "psu2_on",
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(1),
.mode = 0200,
},
{
.label = "pwr_cycle",
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(2),
.mode = 0200,
},
{
.label = "pwr_down",
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(3),
.mode = 0200,
},
{
.label = "jtag_enable",
.reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(4),
.mode = 0644,
},
{
.label = "asic_health",
.reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
.mask = MLXPLAT_CPLD_ASIC_MASK,
.bit = 1,
.mode = 0444,
},
};
static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = {
.data = mlxplat_mlxcpld_default_ng_regs_io_data,
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data),
};
/* Platform FAN default */ /* Platform FAN default */
static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
{ {
...@@ -1208,7 +1298,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) ...@@ -1208,7 +1298,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
switch (reg) { switch (reg) {
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
...@@ -1258,7 +1351,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) ...@@ -1258,7 +1351,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) { switch (reg) {
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
...@@ -1421,7 +1517,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) ...@@ -1421,7 +1517,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_ng_led_data; mlxplat_led = &mlxplat_msn21xx_led_data;
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
return 1; return 1;
...@@ -1439,7 +1535,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) ...@@ -1439,7 +1535,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
mlxplat_hotplug->deferred_nr = mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_msn21xx_led_data; mlxplat_led = &mlxplat_default_ng_led_data;
mlxplat_regs_io = &mlxplat_default_ng_regs_io_data;
mlxplat_fan = &mlxplat_default_fan_data; mlxplat_fan = &mlxplat_default_fan_data;
return 1; return 1;
...@@ -1499,21 +1596,21 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { ...@@ -1499,21 +1596,21 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
.callback = mlxplat_dmi_qmb7xx_matched, .callback = mlxplat_dmi_qmb7xx_matched,
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"), DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"),
}, },
}, },
{ {
.callback = mlxplat_dmi_qmb7xx_matched, .callback = mlxplat_dmi_qmb7xx_matched,
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "SN37"), DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"),
}, },
}, },
{ {
.callback = mlxplat_dmi_qmb7xx_matched, .callback = mlxplat_dmi_qmb7xx_matched,
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "SN34"), DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"),
}, },
}, },
{ {
......
...@@ -478,6 +478,12 @@ do { \ ...@@ -478,6 +478,12 @@ do { \
.ec = TPACPI_MATCH_ANY, \ .ec = TPACPI_MATCH_ANY, \
.quirks = (__quirk) } .quirks = (__quirk) }
#define TPACPI_QEC_IBM(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_IBM, \
.bios = TPACPI_MATCH_ANY, \
.ec = TPID(__id1, __id2), \
.quirks = (__quirk) }
#define TPACPI_QEC_LNV(__id1, __id2, __quirk) \ #define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \ { .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPACPI_MATCH_ANY, \ .bios = TPACPI_MATCH_ANY, \
...@@ -3457,7 +3463,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) ...@@ -3457,7 +3463,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
KEY_UNKNOWN, KEY_UNKNOWN,
KEY_FAVORITES, /* Favorite app, 0x311 */ KEY_BOOKMARKS, /* Favorite app, 0x311 */
KEY_RESERVED, /* Clipping tool */ KEY_RESERVED, /* Clipping tool */
KEY_CALC, /* Calculator (above numpad, P52) */ KEY_CALC, /* Calculator (above numpad, P52) */
KEY_BLUETOOTH, /* Bluetooth */ KEY_BLUETOOTH, /* Bluetooth */
...@@ -5973,9 +5979,6 @@ static const struct tpacpi_quirk led_useful_qtable[] __initconst = { ...@@ -5973,9 +5979,6 @@ static const struct tpacpi_quirk led_useful_qtable[] __initconst = {
}, },
}; };
#undef TPACPI_LEDQ_IBM
#undef TPACPI_LEDQ_LNV
static enum led_access_mode __init led_init_detect_mode(void) static enum led_access_mode __init led_init_detect_mode(void)
{ {
acpi_status status; acpi_status status;
...@@ -8710,40 +8713,18 @@ static const struct attribute_group fan_attr_group = { ...@@ -8710,40 +8713,18 @@ static const struct attribute_group fan_attr_group = {
.attrs = fan_attributes, .attrs = fan_attributes,
}; };
#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */ #define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */
#define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */ #define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */
#define TPACPI_FAN_QI(__id1, __id2, __quirks) \
{ .vendor = PCI_VENDOR_ID_IBM, \
.bios = TPACPI_MATCH_ANY, \
.ec = TPID(__id1, __id2), \
.quirks = __quirks }
#define TPACPI_FAN_QL(__id1, __id2, __quirks) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPACPI_MATCH_ANY, \
.ec = TPID(__id1, __id2), \
.quirks = __quirks }
#define TPACPI_FAN_QB(__id1, __id2, __quirks) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPID(__id1, __id2), \
.ec = TPACPI_MATCH_ANY, \
.quirks = __quirks }
static const struct tpacpi_quirk fan_quirk_table[] __initconst = { static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1), TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1), TPACPI_QEC_IBM('7', '8', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1), TPACPI_QEC_IBM('7', '6', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1), TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN), TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN), TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
}; };
#undef TPACPI_FAN_QL
#undef TPACPI_FAN_QI
#undef TPACPI_FAN_QB
static int __init fan_init(struct ibm_init_struct *iibm) static int __init fan_init(struct ibm_init_struct *iibm)
{ {
int rc; int rc;
......
...@@ -614,6 +614,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -614,6 +614,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
}, },
}, },
{
/* Mediacom Flexbook Edge 11 (same hw as TS Primebook C11) */
.driver_data = (void *)&trekstor_primebook_c11_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
DMI_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
},
},
{ {
/* Onda oBook 20 Plus */ /* Onda oBook 20 Plus */
.driver_data = (void *)&onda_obook_20_plus_data, .driver_data = (void *)&onda_obook_20_plus_data,
......
...@@ -501,19 +501,19 @@ static int tps6598x_remove(struct i2c_client *client) ...@@ -501,19 +501,19 @@ static int tps6598x_remove(struct i2c_client *client)
return 0; return 0;
} }
static const struct acpi_device_id tps6598x_acpi_match[] = { static const struct i2c_device_id tps6598x_id[] = {
{ "INT3515", 0 }, { "tps6598x" },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, tps6598x_acpi_match); MODULE_DEVICE_TABLE(i2c, tps6598x_id);
static struct i2c_driver tps6598x_i2c_driver = { static struct i2c_driver tps6598x_i2c_driver = {
.driver = { .driver = {
.name = "tps6598x", .name = "tps6598x",
.acpi_match_table = tps6598x_acpi_match,
}, },
.probe_new = tps6598x_probe, .probe_new = tps6598x_probe,
.remove = tps6598x_remove, .remove = tps6598x_remove,
.id_table = tps6598x_id,
}; };
module_i2c_driver(tps6598x_i2c_driver); module_i2c_driver(tps6598x_i2c_driver);
......
...@@ -1054,6 +1054,17 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) ...@@ -1054,6 +1054,17 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
} }
#endif #endif
#if defined(CONFIG_ACPI) && IS_ENABLED(CONFIG_I2C)
bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c);
#else
static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
struct acpi_resource_i2c_serialbus **i2c)
{
return false;
}
#endif
/* Device properties */ /* Device properties */
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment