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 ...
This commit is contained in:
@ -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);
|
||||
|
||||
return i2c_new_device(adapter, info);
|
||||
client = i2c_new_device(adapter, info);
|
||||
if (!client)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
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,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)
|
||||
{
|
||||
struct acpi_resource_i2c_serialbus *sb;
|
||||
u32 *addr = data;
|
||||
|
||||
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
|
||||
struct acpi_resource_i2c_serialbus *sb;
|
||||
|
||||
sb = &ares->data.i2c_serial_bus;
|
||||
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
|
||||
if (*addr)
|
||||
*addr |= (sb->slave_address << 16);
|
||||
else
|
||||
*addr = sb->slave_address;
|
||||
}
|
||||
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 */
|
||||
|
||||
@ -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]) {
|
||||
dev_err(dev, "Error creating i2c-client, idx %d\n", i);
|
||||
ret = -ENODEV;
|
||||
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);
|
||||
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;
|
||||
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,
|
||||
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 @@ out_unregister_fusb302:
|
||||
i2c_unregister_device(data->fusb302);
|
||||
|
||||
out_unregister_max17047:
|
||||
if (data->max17047)
|
||||
i2c_unregister_device(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,8 +230,7 @@ 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);
|
||||
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;
|
||||
debugfs_remove_recursive(ips->debug_root);
|
||||
}
|
||||
|
||||
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 @@ out_unlock:
|
||||
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 @@ out_unlock:
|
||||
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,18 +136,46 @@ enum ppfear_regs {
|
||||
#define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3)
|
||||
|
||||
/* 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_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 */
|
||||
#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_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 {
|
||||
const char *name;
|
||||
u32 bit_mask;
|
||||
@ -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;
|
||||
|
||||
@ -1,34 +1,9 @@
|
||||
// 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;
|
||||
@ -8710,40 +8713,18 @@ static const struct attribute_group fan_attr_group = {
|
||||
.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_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
|
||||
|
||||
Reference in New Issue
Block a user