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:
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
cpld1_version
cpld2_version
Date: June 2018
KernelVersion: 4.19
Contact: Vadim Pasternak <vadimpmellanox.com>
......@@ -21,6 +20,28 @@ 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*/
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
Date: June 2018
KernelVersion: 4.19
......@@ -76,3 +97,21 @@ Description: These files show the system reset cause, as following: power
reset cause.
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)
static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
{"BSG1160", },
{"INT33FE", },
{"INT3515", },
{}
};
......
......@@ -45,6 +45,33 @@ struct i2c_acpi_lookup {
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)
{
struct i2c_acpi_lookup *lookup = data;
......@@ -52,11 +79,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
struct acpi_resource_i2c_serialbus *sb;
acpi_status status;
if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
return 1;
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb))
return 1;
if (lookup->index != -1 && lookup->n++ != lookup->index)
......@@ -65,7 +88,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
status = acpi_get_handle(lookup->device_handle,
sb->resource_source.string_ptr,
&lookup->adapter_handle);
if (!ACPI_SUCCESS(status))
if (ACPI_FAILURE(status))
return 1;
info->addr = sb->slave_address;
......@@ -386,20 +409,22 @@ struct notifier_block i2c_acpi_notifier = {
*
* 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_board_info *info)
{
struct i2c_acpi_lookup lookup;
struct i2c_adapter *adapter;
struct i2c_client *client;
struct acpi_device *adev;
LIST_HEAD(resource_list);
int ret;
adev = ACPI_COMPANION(dev);
if (!adev)
return NULL;
return ERR_PTR(-EINVAL);
memset(&lookup, 0, sizeof(lookup));
lookup.info = info;
......@@ -408,16 +433,23 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
ret = acpi_dev_get_resources(adev, &resource_list,
i2c_acpi_fill_info, &lookup);
if (ret < 0)
return ERR_PTR(ret);
acpi_dev_free_resource_list(&resource_list);
if (ret < 0 || !info->addr)
return NULL;
if (!info->addr)
return ERR_PTR(-EADDRNOTAVAIL);
adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
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);
......@@ -525,13 +557,7 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command,
goto err;
}
if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
ret = AE_BAD_PARAMETER;
goto err;
}
sb = &ares->data.i2c_serial_bus;
if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {
ret = AE_BAD_PARAMETER;
goto err;
}
......
......@@ -91,19 +91,15 @@ static int asus_acpi_get_sensor_info(struct acpi_device *adev,
static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data)
{
u32 *addr = data;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
struct acpi_resource_i2c_serialbus *sb;
u32 *addr = data;
sb = &ares->data.i2c_serial_bus;
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
if (i2c_acpi_get_i2c_resource(ares, &sb)) {
if (*addr)
*addr |= (sb->slave_address << 16);
else
*addr = sb->slave_address;
}
}
/* Tell the ACPI core that we already copied this address */
return 1;
......
......@@ -442,8 +442,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0x32, { KEY_MUTE } },
{ KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
{ KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
{ KE_KEY, 0x35, { KEY_SCREENLOCK } },
{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
{ KE_KEY, 0x41, { KEY_NEXTSONG } },
{ KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
......
......@@ -2131,7 +2131,8 @@ static int asus_wmi_add(struct platform_device *pdev)
err = asus_wmi_backlight_init(asus);
if (err && err != -ENODEV)
goto fail_backlight;
}
} else
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
status = wmi_install_notify_handler(asus->driver->event_guid,
asus_wmi_notify, asus);
......
......@@ -1565,8 +1565,10 @@ static ssize_t kbd_led_timeout_store(struct device *dev,
switch (unit) {
case KBD_TIMEOUT_DAYS:
value *= 24;
/* fall through */
case KBD_TIMEOUT_HOURS:
value *= 60;
/* fall through */
case KBD_TIMEOUT_MINUTES:
value *= 60;
unit = KBD_TIMEOUT_SECONDS;
......
......@@ -7,15 +7,23 @@
*/
#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.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 {
const char *type;
int gpio_irq_idx;
unsigned int flags;
int irq_idx;
};
struct i2c_multi_inst_data {
......@@ -23,6 +31,31 @@ struct i2c_multi_inst_data {
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)
{
struct i2c_multi_inst_data *multi;
......@@ -44,40 +77,59 @@ static int i2c_multi_inst_probe(struct platform_device *pdev)
adev = ACPI_COMPANION(dev);
/* 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,
offsetof(struct i2c_multi_inst_data, clients[i]),
offsetof(struct i2c_multi_inst_data, clients[ret]),
GFP_KERNEL);
if (!multi)
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));
strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE);
snprintf(name, sizeof(name), "%s-%s", match->id,
inst_data[i].type);
snprintf(name, sizeof(name), "%s-%s.%d", match->id,
inst_data[i].type, i);
board_info.dev_name = name;
board_info.irq = 0;
if (inst_data[i].gpio_irq_idx != -1) {
ret = acpi_dev_gpio_irq_get(adev,
inst_data[i].gpio_irq_idx);
switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) {
case IRQ_RESOURCE_GPIO:
ret = acpi_dev_gpio_irq_get(adev, inst_data[i].irq_idx);
if (ret < 0) {
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;
}
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);
if (!multi->clients[i]) {
if (IS_ERR(multi->clients[i])) {
ret = PTR_ERR(multi->clients[i]);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Error creating i2c-client, idx %d\n", i);
ret = -ENODEV;
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);
return 0;
......@@ -101,9 +153,17 @@ static int i2c_multi_inst_remove(struct platform_device *pdev)
}
static const struct i2c_inst_data bsg1160_data[] = {
{ "bmc150_accel", 0 },
{ "bmc150_magn", -1 },
{ "bmg160", -1 },
{ "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
{ "bmc150_magn" },
{ "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[] = {
*/
static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
{ "BSG1160", (unsigned long)bsg1160_data },
{ "INT3515", (unsigned long)int3515_data },
{ }
};
MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
......
......@@ -1188,6 +1188,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
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",
.matches = {
......
......@@ -33,46 +33,45 @@
#define ISPSSPM0_IUNIT_POWER_ON 0x0
#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;
u32 val;
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);
u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON :
ISPSSPM0_IUNIT_POWER_OFF;
/* 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,
ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK);
val, ISPSSPM0_ISPSSC_MASK);
/*
* There should be no IUNIT access while power-down is
* 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) {
/* Wait until ISPSSPM0 bit[25:24] shows 0x3 */
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val);
val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
if (val == ISPSSPM0_IUNIT_POWER_OFF)
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;
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;
}
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_put_sync_suspend(&dev->dev);
......@@ -87,11 +86,40 @@ static void isp_remove(struct pci_dev *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;
}
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;
}
......@@ -99,6 +127,7 @@ static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend,
isp_pci_resume, NULL);
static const struct pci_device_id isp_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x0f38), },
{ PCI_VDEVICE(INTEL, 0x22b8), },
{ 0, }
};
......
......@@ -168,8 +168,8 @@ static int cht_int33fe_probe(struct platform_device *pdev)
board_info.dev_name = "max17047";
board_info.properties = max17047_props;
data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
if (!data->max17047)
return -EPROBE_DEFER; /* Wait for i2c-adapter to load */
if (IS_ERR(data->max17047))
return PTR_ERR(data->max17047);
}
data->connections[0].endpoint[0] = "port0";
......@@ -194,16 +194,20 @@ static int cht_int33fe_probe(struct platform_device *pdev)
board_info.irq = fusb302_irq;
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;
}
memset(&board_info, 0, sizeof(board_info));
board_info.dev_name = "pi3usb30532";
strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE);
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;
}
platform_set_drvdata(pdev, data);
......@@ -213,12 +217,11 @@ static int cht_int33fe_probe(struct platform_device *pdev)
i2c_unregister_device(data->fusb302);
out_unregister_max17047:
if (data->max17047)
i2c_unregister_device(data->max17047);
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)
......@@ -227,7 +230,6 @@ static int cht_int33fe_remove(struct platform_device *pdev)
i2c_unregister_device(data->pi3usb30532);
i2c_unregister_device(data->fusb302);
if (data->max17047)
i2c_unregister_device(data->max17047);
device_connections_remove(data->connections);
......
......@@ -1210,13 +1210,7 @@ static void ips_debugfs_cleanup(struct ips_driver *ips) { return; }
/* Expose current state and limits in debugfs if possible */
struct ips_debugfs_node {
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)
static int cpu_temp_show(struct seq_file *m, void *data)
{
struct ips_driver *ips = m->private;
......@@ -1225,8 +1219,9 @@ static int show_cpu_temp(struct seq_file *m, void *data)
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;
......@@ -1234,8 +1229,9 @@ static int show_cpu_power(struct seq_file *m, void *data)
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;
int tdp, tdc;
......@@ -1255,8 +1251,9 @@ static int show_cpu_clamp(struct seq_file *m, void *data)
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;
......@@ -1265,8 +1262,9 @@ static int show_mch_temp(struct seq_file *m, void *data)
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;
......@@ -1274,68 +1272,22 @@ static int show_mch_power(struct seq_file *m, void *data)
return 0;
}
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,
};
DEFINE_SHOW_ATTRIBUTE(mch_power);
static void ips_debugfs_cleanup(struct ips_driver *ips)
{
if (ips->debug_root)
debugfs_remove_recursive(ips->debug_root);
return;
}
static void ips_debugfs_init(struct ips_driver *ips)
{
int i;
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++) {
struct dentry *ent;
struct ips_debugfs_node *node = &ips_debug_files[i];
node->ips = ips;
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;
debugfs_create_file("cpu_temp", 0444, ips->debug_root, ips, &cpu_temp_fops);
debugfs_create_file("cpu_power", 0444, ips->debug_root, ips, &cpu_power_fops);
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);
debugfs_create_file("mch_power", 0444, ips->debug_root, ips, &mch_power_fops);
}
#endif /* CONFIG_DEBUG_FS */
......@@ -1646,9 +1598,6 @@ static void ips_remove(struct pci_dev *dev)
struct ips_driver *ips = pci_get_drvdata(dev);
u64 turbo_override;
if (!ips)
return;
ips_debugfs_cleanup(ips);
/* Release i915 driver */
......
......@@ -12,6 +12,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/io.h>
......@@ -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 = {
.pfear_sts = spt_pfear_map,
.mphy_sts = spt_mphy_map,
.pll_sts = spt_pll_map,
.ltr_show_sts = spt_ltr_show_map,
.slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET,
.ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET,
.regmap_length = SPT_PMC_MMIO_REG_LEN,
......@@ -112,6 +138,7 @@ static const struct pmc_reg_map spt_reg_map = {
.ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET,
.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 */
......@@ -243,10 +270,38 @@ static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
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 = {
.pfear_sts = 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,
.slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.regmap_length = CNP_PMC_MMIO_REG_LEN,
......@@ -254,6 +309,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES,
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.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)
......@@ -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");
}
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;
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)
return 0;
}
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,
};
DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear);
/* This function should return link status, 0 means ready */
static int pmc_core_mtpmc_link_status(void)
......@@ -372,7 +417,7 @@ static int pmc_core_send_msg(u32 *addr_xram)
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;
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)
mutex_unlock(&pmcdev->lock);
return err;
}
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,
};
DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg);
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);
return err;
}
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,
};
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)
......@@ -500,7 +523,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user
goto out_unlock;
}
if (val > NUM_IP_IGN_ALLOWED) {
if (val > map->ltr_ignore_max) {
err = -EINVAL;
goto out_unlock;
}
......@@ -583,6 +606,77 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)
}
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)
{
debugfs_remove_recursive(pmcdev->dbgfs_dir);
......@@ -602,19 +696,21 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
&pmc_core_dev_state);
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,
&pmc_core_ltr_ignore_ops);
debugfs_create_file("ltr_show", 0644, dir, pmcdev, &pmc_core_ltr_fops);
if (pmcdev->map->pll_sts)
debugfs_create_file("pll_status", 0444, dir, pmcdev,
&pmc_core_pll_ops);
&pmc_core_pll_fops);
if (pmcdev->map->mphy_sts)
debugfs_create_file("mphy_core_lanes_power_gating_status",
0444, dir, pmcdev,
&pmc_core_mphy_pg_ops);
&pmc_core_mphy_pg_fops);
if (pmcdev->map->slps0_dbg_maps) {
debugfs_create_file("slp_s0_debug_status", 0444,
......
......@@ -12,6 +12,8 @@
#ifndef PMC_CORE_H
#define PMC_CORE_H
#include <linux/bits.h>
#define PMC_BASE_ADDR_DEFAULT 0xFE000000
/* Sunrise Point Power Management Controller PCI Device ID */
......@@ -35,7 +37,26 @@
#define SPT_PMC_READ_DISABLE_BIT 0x16
#define SPT_PMC_MSG_FULL_STS_BIT 0x18
#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 */
enum ppfear_regs {
......@@ -115,17 +136,45 @@ enum ppfear_regs {
#define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3)
/* Cannonlake Power Management Controller register offsets */
#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
#define CNP_PMC_PM_CFG_OFFSET 0x1818
#define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4
/* Cannonlake: PGD PFET Enable Ack Status Register(s) start */
#define CNP_PMC_HOST_PPFEAR0A 0x1D90
#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_PMC_LATCH_SLPS0_EVENTS BIT(31)
#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 {
const char *name;
......@@ -139,6 +188,7 @@ struct pmc_bit_map {
* @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit
* @pll_sts: Maps name of PLL to corresponding bit status
* @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
* @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit
* @regmap_length: Length of memory to map from PWRMBASE address to access
......@@ -157,6 +207,7 @@ struct pmc_reg_map {
const struct pmc_bit_map *mphy_sts;
const struct pmc_bit_map *pll_sts;
const struct pmc_bit_map **slps0_dbg_maps;
const struct pmc_bit_map *ltr_show_sts;
const u32 slp_s0_offset;
const u32 ltr_ignore_offset;
const int regmap_length;
......@@ -165,6 +216,7 @@ struct pmc_reg_map {
const u32 pm_cfg_offset;
const int pm_read_disable_bit;
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)
return 0;
}
static int telem_pss_state_open(struct inode *inode, struct file *file)
{
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,
};
DEFINE_SHOW_ATTRIBUTE(telem_pss_states);
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;
}
static int telem_ioss_state_open(struct inode *inode, struct file *file)
{
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,
};
DEFINE_SHOW_ATTRIBUTE(telem_ioss_states);
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;
}
static int telem_soc_state_open(struct inode *inode, struct file *file)
{
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,
};
DEFINE_SHOW_ATTRIBUTE(telem_soc_states);
static int telem_s0ix_res_get(void *data, u64 *val)
{
......@@ -960,7 +930,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, NULL,
&telem_pss_ops);
&telem_pss_states_fops);
if (!f) {
pr_err("pss_sample_info debugfs register failed\n");
goto out;
......@@ -968,7 +938,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("ioss_info", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir, NULL,
&telem_ioss_ops);
&telem_ioss_states_fops);
if (!f) {
pr_err("ioss_sample_info debugfs register failed\n");
goto out;
......@@ -976,7 +946,7 @@ static int __init telemetry_debugfs_init(void)
f = debugfs_create_file("soc_states", S_IFREG | S_IRUGO,
debugfs_conf->telemetry_dbg_dir,
NULL, &telem_socstate_ops);
NULL, &telem_soc_states_fops);
if (!f) {
pr_err("ioss_sample_info debugfs register failed\n");
goto out;
......
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/*
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
* Mellanox platform driver
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 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.
* Copyright (C) 2016-2018 Mellanox Technologies
* Copyright (C) 2016-2018 Vadim Pasternak <vadimp@mellanox.com>
*/
#include <linux/device.h>
......@@ -49,7 +24,10 @@
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00
#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
......@@ -83,12 +61,12 @@
#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7
#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8
#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9
#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea
#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb
#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec
#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed
#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee
#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef
#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xeb
#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xec
#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xed
#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee
#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef
#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
......@@ -1101,6 +1079,118 @@ static struct mlxreg_core_platform_data mlxplat_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 */
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)
switch (reg) {
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
......@@ -1258,7 +1351,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) {
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
......@@ -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->deferred_nr =
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;
return 1;
......@@ -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->deferred_nr =
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;
return 1;
......@@ -1499,21 +1596,21 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"),
DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"),
},
},
{
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "SN37"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"),
},
},
{
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"),
},
},
{
......
......@@ -478,6 +478,12 @@ do { \
.ec = TPACPI_MATCH_ANY, \
.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) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPACPI_MATCH_ANY, \
......@@ -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_FAVORITES, /* Favorite app, 0x311 */
KEY_BOOKMARKS, /* Favorite app, 0x311 */
KEY_RESERVED, /* Clipping tool */
KEY_CALC, /* Calculator (above numpad, P52) */
KEY_BLUETOOTH, /* Bluetooth */
......@@ -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)
{
acpi_status status;
......@@ -8713,37 +8716,15 @@ static const struct attribute_group fan_attr_group = {
#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */
#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 = {
TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN),
TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN),
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
TPACPI_QEC_IBM('7', '8', TPACPI_FAN_Q1),
TPACPI_QEC_IBM('7', '6', TPACPI_FAN_Q1),
TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
TPACPI_QEC_LNV('7', 'M', 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)
{
int rc;
......
......@@ -614,6 +614,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
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 */
.driver_data = (void *)&onda_obook_20_plus_data,
......
......@@ -501,19 +501,19 @@ static int tps6598x_remove(struct i2c_client *client)
return 0;
}
static const struct acpi_device_id tps6598x_acpi_match[] = {
{ "INT3515", 0 },
static const struct i2c_device_id tps6598x_id[] = {
{ "tps6598x" },
{ }
};
MODULE_DEVICE_TABLE(acpi, tps6598x_acpi_match);
MODULE_DEVICE_TABLE(i2c, tps6598x_id);
static struct i2c_driver tps6598x_i2c_driver = {
.driver = {
.name = "tps6598x",
.acpi_match_table = tps6598x_acpi_match,
},
.probe_new = tps6598x_probe,
.remove = tps6598x_remove,
.id_table = tps6598x_id,
};
module_i2c_driver(tps6598x_i2c_driver);
......
......@@ -1054,6 +1054,17 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
}
#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 */
#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