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