From cc0594c4b0ef280dd7bdceab1a7c940d356f494d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2020 07:51:56 +0200 Subject: ACPI / PMIC: Add i2c address for thermal control On Asus T101HA, we keep receiving those error messages: i915 0000:00:02.0: [drm] *ERROR* mipi_exec_pmic failed, error: -95 intel_soc_pmic_exec_mipi_pmic_seq_element: Not implemented intel_soc_pmic_exec_mipi_pmic_seq_element: i2c-addr: 0x5e reg-addr 0x4b value 0x59 mask 0xff Because the opregion is missing the I2C address. Suggested-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans de Goede Reviewed-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pmic/intel_pmic_chtdc_ti.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c index 7ccd7d9660bc..a5101b07611a 100644 --- a/drivers/acpi/pmic/intel_pmic_chtdc_ti.c +++ b/drivers/acpi/pmic/intel_pmic_chtdc_ti.c @@ -102,6 +102,7 @@ static struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = { .power_table_count = ARRAY_SIZE(chtdc_ti_power_table), .thermal_table = chtdc_ti_thermal_table, .thermal_table_count = ARRAY_SIZE(chtdc_ti_thermal_table), + .pmic_i2c_address = 0x5e, }; static int chtdc_ti_pmic_opregion_probe(struct platform_device *pdev) -- cgit v1.2.3 From 7f17b4a121d0d50eca22cb1edebf0a157f3e43bf Mon Sep 17 00:00:00 2001 From: James Morse Date: Fri, 1 May 2020 17:45:42 +0100 Subject: ACPI: APEI: Kick the memory_failure() queue for synchronous errors memory_failure() offlines or repairs pages of memory that have been discovered to be corrupt. These may be detected by an external component, (e.g. the memory controller), and notified via an IRQ. In this case the work is queued as not all of memory_failure()s work can happen in IRQ context. If the error was detected as a result of user-space accessing a corrupt memory location the CPU may take an abort instead. On arm64 this is a 'synchronous external abort', and on a firmware first system it is replayed using NOTIFY_SEA. This notification has NMI like properties, (it can interrupt IRQ-masked code), so the memory_failure() work is queued. If we return to user-space before the queued memory_failure() work is processed, we will take the fault again. This loop may cause platform firmware to exceed some threshold and reboot when Linux could have recovered from this error. For NMIlike notifications keep track of whether memory_failure() work was queued, and make task_work pending to flush out the queue. To save memory allocations, the task_work is allocated as part of the ghes_estatus_node, and free()ing it back to the pool is deferred. Signed-off-by: James Morse Tested-by: Tyler Baicar Signed-off-by: Rafael J. Wysocki --- drivers/acpi/apei/ghes.c | 67 ++++++++++++++++++++++++++++++++++++++++-------- include/acpi/ghes.h | 3 +++ 2 files changed, 59 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 24c9642e8fc7..5abca09455ad 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -414,23 +415,46 @@ static void ghes_clear_estatus(struct ghes *ghes, ghes_ack_error(ghes->generic_v2); } -static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) +/* + * Called as task_work before returning to user-space. + * Ensure any queued work has been done before we return to the context that + * triggered the notification. + */ +static void ghes_kick_task_work(struct callback_head *head) +{ + struct acpi_hest_generic_status *estatus; + struct ghes_estatus_node *estatus_node; + u32 node_len; + + estatus_node = container_of(head, struct ghes_estatus_node, task_work); + if (IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) + memory_failure_queue_kick(estatus_node->task_work_cpu); + + estatus = GHES_ESTATUS_FROM_NODE(estatus_node); + node_len = GHES_ESTATUS_NODE_LEN(cper_estatus_len(estatus)); + gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len); +} + +static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, + int sev) { -#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE unsigned long pfn; int flags = -1; int sec_sev = ghes_severity(gdata->error_severity); struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); + if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) + return false; + if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) - return; + return false; pfn = mem_err->physical_addr >> PAGE_SHIFT; if (!pfn_valid(pfn)) { pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid address in generic error data: %#llx\n", mem_err->physical_addr); - return; + return false; } /* iff following two events can be handled properly by now */ @@ -440,9 +464,12 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) flags = 0; - if (flags != -1) + if (flags != -1) { memory_failure_queue(pfn, flags); -#endif + return true; + } + + return false; } /* @@ -490,7 +517,7 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata) #endif } -static void ghes_do_proc(struct ghes *ghes, +static bool ghes_do_proc(struct ghes *ghes, const struct acpi_hest_generic_status *estatus) { int sev, sec_sev; @@ -498,6 +525,7 @@ static void ghes_do_proc(struct ghes *ghes, guid_t *sec_type; const guid_t *fru_id = &guid_null; char *fru_text = ""; + bool queued = false; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { @@ -515,7 +543,7 @@ static void ghes_do_proc(struct ghes *ghes, ghes_edac_report_mem_error(sev, mem_err); arch_apei_report_mem_error(sev, mem_err); - ghes_handle_memory_failure(gdata, sev); + queued = ghes_handle_memory_failure(gdata, sev); } else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { ghes_handle_aer(gdata); @@ -532,6 +560,8 @@ static void ghes_do_proc(struct ghes *ghes, gdata->error_data_length); } } + + return queued; } static void __ghes_print_estatus(const char *pfx, @@ -827,7 +857,9 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; struct acpi_hest_generic_status *estatus; + bool task_work_pending; u32 len, node_len; + int ret; llnode = llist_del_all(&ghes_estatus_llist); /* @@ -842,14 +874,26 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) estatus = GHES_ESTATUS_FROM_NODE(estatus_node); len = cper_estatus_len(estatus); node_len = GHES_ESTATUS_NODE_LEN(len); - ghes_do_proc(estatus_node->ghes, estatus); + task_work_pending = ghes_do_proc(estatus_node->ghes, estatus); if (!ghes_estatus_cached(estatus)) { generic = estatus_node->generic; if (ghes_print_estatus(NULL, generic, estatus)) ghes_estatus_cache_add(generic, estatus); } - gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, - node_len); + + if (task_work_pending && current->mm != &init_mm) { + estatus_node->task_work.func = ghes_kick_task_work; + estatus_node->task_work_cpu = smp_processor_id(); + ret = task_work_add(current, &estatus_node->task_work, + true); + if (ret) + estatus_node->task_work.func = NULL; + } + + if (!estatus_node->task_work.func) + gen_pool_free(ghes_estatus_pool, + (unsigned long)estatus_node, node_len); + llnode = next; } } @@ -909,6 +953,7 @@ static int ghes_in_nmi_queue_one_entry(struct ghes *ghes, estatus_node->ghes = ghes; estatus_node->generic = ghes->generic; + estatus_node->task_work.func = NULL; estatus = GHES_ESTATUS_FROM_NODE(estatus_node); if (__ghes_read_estatus(estatus, buf_paddr, fixmap_idx, len)) { diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index e3f1cddb4ac8..517a5231cc1b 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -33,6 +33,9 @@ struct ghes_estatus_node { struct llist_node llnode; struct acpi_hest_generic *generic; struct ghes *ghes; + + int task_work_cpu; + struct callback_head task_work; }; struct ghes_estatus_cache { -- cgit v1.2.3 From c41c36e900a337b4132b12ccabc97f5578248b44 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Fri, 22 May 2020 14:22:28 +0200 Subject: ACPI: video: Use native backlight on Acer TravelMate 5735Z MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, changing the brightness of the internal display of the Acer TravelMate 5735Z does not work. Pressing the function keys or changing the slider, GNOME Shell 3.36.2 displays the OSD (five steps), but the brightness does not change. The Acer TravelMate 5735Z shipped with Windows 7 and as such does not trigger our "win8 ready" heuristic for preferring the native backlight interface. Still ACPI backlight control doesn't work on this model, where as the native (intel_video) backlight interface does work by adding `acpi_backlight=native` or `acpi_backlight=none` to Linux’ command line. So, add a quirk to force using native backlight control on this model. Link: https://bugzilla.kernel.org/show_bug.cgi?id=207835 Reviewed-by: Hans de Goede Signed-off-by: Paul Menzel Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video_detect.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b4994e50608d..2499d7e3c710 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -361,6 +361,16 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "JV50"), }, }, + { + /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */ + .callback = video_detect_force_native, + .ident = "Acer TravelMate 5735Z", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5735Z"), + DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"), + }, + }, /* * Desktops which falsely report a backlight and which our heuristics -- cgit v1.2.3 From 668ce99e4ed4c07bb14465f80492bc6cf76ed3c9 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Thu, 21 May 2020 13:30:15 -0700 Subject: ACPI: DPTF: Additional sysfs attributes for power participant driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two additional attributes to the existing power participant driver: rest_of_platform_power_mw: (RO) Shows the rest of worst case platform power in mW outside of S0C. This will help in power distribution to SoC and rest of the system. For example on a test system, this value is 2.5W with a 15W TDP SoC. Based on the adapter rating (adapter_rating_mw), user space software can decide on proper power allocation to SoC to improve short term performance via powercap/RAPL interface. prochot_confirm: (WO) Confirm EC about a prochot notification. Also userspace is notified via sysfs_notify(), whenever power source or rest of the platform power is changed. So user space can use poll() system call on those attributes. The ACPI methods used in this patch are as follows: PROP This object evaluates to the rest of worst case platform power in mW. Bits: 23:0 Worst case rest of platform power in mW. PBOK PBOK is a method designed to provide a mechanism for OSPM to change power setting before EC can de-assert a PROCHOT from a device. The EC may receive several PROCHOTs, so it has a sequence number attached to PSRC (read via existing attribute "platform_power_source"). Once OSPM takes action for a PSRC change notification, it can call PBOK method to confirm with the sequence number. Bits: 3:0 Power Delivery State Change Sequence number 30 Reserved 31 0 – Not OK to de-assert PROCHOT 1 – OK to de-assert PROCHOT PSRC (Platform Power Source): Not new in this patch but for documentation for new bits This object evaluates to an integer that represents the system power source as well as the power delivery state change sequence number. Bits: 3:0 The current power source as an integer for AC, DC, USB, Wireless. 0 = DC, 1 = AC, 2 = USB, 3 = Wireless Charging 7:4 Power Delivery State Change Sequence Number. Default value is 0 Notifications: 0x81: (Power State Change) Used to notify when the power source has changed. 0x84: (PROP change) Used to notify when the platform rest of power has changed. Signed-off-by: Srinivas Pandruvada [ rjw: Subject, minor ABI documentation edit ] Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-platform-dptf | 24 ++++++++-- drivers/acpi/dptf/dptf_power.c | 69 ++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/ABI/testing/sysfs-platform-dptf b/Documentation/ABI/testing/sysfs-platform-dptf index 325dc0667dbb..4f14d5b83bef 100644 --- a/Documentation/ABI/testing/sysfs-platform-dptf +++ b/Documentation/ABI/testing/sysfs-platform-dptf @@ -27,10 +27,12 @@ KernelVersion: v4.10 Contact: linux-acpi@vger.kernel.org Description: (RO) Display the platform power source - 0x00 = DC - 0x01 = AC - 0x02 = USB - 0x03 = Wireless Charger + bits[3:0] Current power source + 0x00 = DC + 0x01 = AC + 0x02 = USB + 0x03 = Wireless Charger + bits[7:4] Power source sequence number What: /sys/bus/platform/devices/INT3407:00/dptf_power/battery_steady_power Date: Jul, 2016 @@ -38,3 +40,17 @@ KernelVersion: v4.10 Contact: linux-acpi@vger.kernel.org Description: (RO) The maximum sustained power for battery in milliwatts. + +What: /sys/bus/platform/devices/INT3407:00/dptf_power/rest_of_platform_power_mw +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) Shows the rest (outside of SoC) of worst-case platform power. + +What: /sys/bus/platform/devices/INT3407:00/dptf_power/prochot_confirm +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (WO) Confirm embedded controller about a prochot notification. diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index e4e8b75d39f0..abe99039af74 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -16,6 +16,7 @@ * ARTG : Adapter rating * CTYP : Charger type * PBSS : Battery steady power + * PROP : Rest of worst case platform Power */ #define DPTF_POWER_SHOW(name, object) \ static ssize_t name##_show(struct device *dev,\ @@ -39,12 +40,34 @@ DPTF_POWER_SHOW(platform_power_source, PSRC) DPTF_POWER_SHOW(adapter_rating_mw, ARTG) DPTF_POWER_SHOW(battery_steady_power_mw, PBSS) DPTF_POWER_SHOW(charger_type, CTYP) +DPTF_POWER_SHOW(rest_of_platform_power_mw, PROP) static DEVICE_ATTR_RO(max_platform_power_mw); static DEVICE_ATTR_RO(platform_power_source); static DEVICE_ATTR_RO(adapter_rating_mw); static DEVICE_ATTR_RO(battery_steady_power_mw); static DEVICE_ATTR_RO(charger_type); +static DEVICE_ATTR_RO(rest_of_platform_power_mw); + +static ssize_t prochot_confirm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi_dev = dev_get_drvdata(dev); + acpi_status status; + int seq_no; + + if (kstrtouint(buf, 0, &seq_no) < 0) + return -EINVAL; + + status = acpi_execute_simple_method(acpi_dev->handle, "PBOK", seq_no); + if (ACPI_SUCCESS(status)) + return count; + + return -EINVAL; +} + +static DEVICE_ATTR_WO(prochot_confirm); static struct attribute *dptf_power_attrs[] = { &dev_attr_max_platform_power_mw.attr, @@ -52,6 +75,8 @@ static struct attribute *dptf_power_attrs[] = { &dev_attr_adapter_rating_mw.attr, &dev_attr_battery_steady_power_mw.attr, &dev_attr_charger_type.attr, + &dev_attr_rest_of_platform_power_mw.attr, + &dev_attr_prochot_confirm.attr, NULL }; @@ -60,6 +85,33 @@ static const struct attribute_group dptf_power_attribute_group = { .name = "dptf_power" }; +#define POWER_STATE_CHANGED 0x81 +#define POWER_PROP_CHANGE_EVENT 0x84 + +static void dptf_power_notify(acpi_handle handle, u32 event, void *data) +{ + struct platform_device *pdev = data; + char *attr; + + switch (event) { + case POWER_STATE_CHANGED: + attr = "platform_power_source"; + break; + case POWER_PROP_CHANGE_EVENT: + attr = "rest_of_platform_power_mw"; + break; + default: + dev_err(&pdev->dev, "Unsupported event [0x%x]\n", event); + return; + } + + /* + * Notify that an attribute is changed, so that user space can read + * again. + */ + sysfs_notify(&pdev->dev.kobj, "dptf_power", attr); +} + static int dptf_power_add(struct platform_device *pdev) { struct acpi_device *acpi_dev; @@ -78,10 +130,21 @@ static int dptf_power_add(struct platform_device *pdev) if (ptype != 0x11) return -ENODEV; + result = acpi_install_notify_handler(acpi_dev->handle, + ACPI_DEVICE_NOTIFY, + dptf_power_notify, + (void *)pdev); + if (result) + return result; + result = sysfs_create_group(&pdev->dev.kobj, &dptf_power_attribute_group); - if (result) + if (result) { + acpi_remove_notify_handler(acpi_dev->handle, + ACPI_DEVICE_NOTIFY, + dptf_power_notify); return result; + } platform_set_drvdata(pdev, acpi_dev); @@ -90,7 +153,11 @@ static int dptf_power_add(struct platform_device *pdev) static int dptf_power_remove(struct platform_device *pdev) { + struct acpi_device *acpi_dev = platform_get_drvdata(pdev); + acpi_remove_notify_handler(acpi_dev->handle, + ACPI_DEVICE_NOTIFY, + dptf_power_notify); sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); return 0; -- cgit v1.2.3 From 7b52b200cf5bdd04f3ee22121960bd6f4ec5efa1 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 22 May 2020 14:45:09 -0700 Subject: ACPI: DPTF: Add battery participant driver This driver adds support for Dynamic Platform and Thermal Framework battery participant device support. These attributes are presented via sysfs interface under the platform device for the battery participant: $ls /sys/bus/platform/devices/INT3532:00/dptf_battery current_discharge_capbility_ma max_platform_power_mw no_load_voltage_mv high_freq_impedance_mohm max_steady_state_power_mw Refer to the documentation at Documentation/ABI/testing/sysfs-platform-dptf for details. Here the implementation reuses existing dptf-power.c as the motivation and processing is same. It also shares one ACPI method. Here this change is using participant type, "PTYP" method to identify and do different processing. By using participant type, create/delete either "dptf_power" or "dptf_battery" attribute group and send notifications. The particpant type for for the battery participant is 0x0C. ACPI methods description: PMAX (Intel(R) Dynamic Tuning Platform Max Power Supplied by Battery): This object evaluates to the maximum platform power that can be supported by the battery in milli watts. PBSS (Intel(R) Dynamic Tuning Power Battery Steady State): This object returns the max sustained power for battery in milli watts. RBHF (Intel(R) Dynamic Tuning High Frequency Impedance): This object returns high frequency impedance value that can be obtained from battery fuel gauge. VBNL (Intel(R) Dynamic Tuning No-Load Voltage) This object returns battery instantaneous no-load voltage that can be obtained from battery fuel gauge in milli volts CMPP (Intel(R) Dynamic Tuning Current Discharge Capability) This object returns battery discharge current capability obtained from battery fuel gauge milli amps. Notifications: 0x80: PMAX change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the PMAX has changed by 250mw. 0x83: PBSS change. Used to notify Intel(R) Dynamic Tuning Battery participant driver when the power source has changed. 0x85: RBHF change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the RBHF has changed over a threshold by 5mOhm. 0x86: Battery Capability change. Used to notify Intel(R)Dynamic Tuning Battery participant driver when the battery capability has changed. Signed-off-by: Srinivas Pandruvada [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-platform-dptf | 38 +++++++++++++ drivers/acpi/dptf/dptf_power.c | 82 +++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/ABI/testing/sysfs-platform-dptf b/Documentation/ABI/testing/sysfs-platform-dptf index 4f14d5b83bef..eeed81ca6949 100644 --- a/Documentation/ABI/testing/sysfs-platform-dptf +++ b/Documentation/ABI/testing/sysfs-platform-dptf @@ -54,3 +54,41 @@ KernelVersion: v5.8 Contact: linux-acpi@vger.kernel.org Description: (WO) Confirm embedded controller about a prochot notification. + +What: /sys/bus/platform/devices/INT3532:00/dptf_battery/max_platform_power_mw +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) The maximum platform power that can be supported by the battery in milli watts. + +What: /sys/bus/platform/devices/INT3532:00/dptf_battery/max_steady_state_power_mw +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) The maximum sustained power for battery in milli watts. + +What: /sys/bus/platform/devices/INT3532:00/dptf_battery/high_freq_impedance_mohm +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) The high frequency impedance value that can be obtained from battery + fuel gauge in milli Ohms. + +What: /sys/bus/platform/devices/INT3532:00/dptf_battery/no_load_voltage_mv +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) The no-load voltage that can be obtained from battery fuel gauge in + milli volts. + +What: /sys/bus/platform/devices/INT3532:00/dptf_battery/current_discharge_capbility_ma +Date: June, 2020 +KernelVersion: v5.8 +Contact: linux-acpi@vger.kernel.org +Description: + (RO) The battery discharge current capability obtained from battery fuel gauge in + milli Amps. diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index abe99039af74..5fab7e350db8 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -10,13 +10,19 @@ #include /* - * Presentation of attributes which are defined for INT3407. They are: + * Presentation of attributes which are defined for INT3407 and INT3532. + * They are: * PMAX : Maximum platform powe * PSRC : Platform power source * ARTG : Adapter rating * CTYP : Charger type * PBSS : Battery steady power * PROP : Rest of worst case platform Power + * PBSS : Power Battery Steady State + * PBSS : Power Battery Steady State + * RBHF : High Frequency Impedance + * VBNL : Instantaneous No-Load Voltage + * CMPP : Current Discharge Capability */ #define DPTF_POWER_SHOW(name, object) \ static ssize_t name##_show(struct device *dev,\ @@ -41,6 +47,10 @@ DPTF_POWER_SHOW(adapter_rating_mw, ARTG) DPTF_POWER_SHOW(battery_steady_power_mw, PBSS) DPTF_POWER_SHOW(charger_type, CTYP) DPTF_POWER_SHOW(rest_of_platform_power_mw, PROP) +DPTF_POWER_SHOW(max_steady_state_power_mw, PBSS) +DPTF_POWER_SHOW(high_freq_impedance_mohm, RBHF) +DPTF_POWER_SHOW(no_load_voltage_mv, VBNL) +DPTF_POWER_SHOW(current_discharge_capbility_ma, CMPP); static DEVICE_ATTR_RO(max_platform_power_mw); static DEVICE_ATTR_RO(platform_power_source); @@ -48,6 +58,10 @@ static DEVICE_ATTR_RO(adapter_rating_mw); static DEVICE_ATTR_RO(battery_steady_power_mw); static DEVICE_ATTR_RO(charger_type); static DEVICE_ATTR_RO(rest_of_platform_power_mw); +static DEVICE_ATTR_RO(max_steady_state_power_mw); +static DEVICE_ATTR_RO(high_freq_impedance_mohm); +static DEVICE_ATTR_RO(no_load_voltage_mv); +static DEVICE_ATTR_RO(current_discharge_capbility_ma); static ssize_t prochot_confirm_store(struct device *dev, struct device_attribute *attr, @@ -85,8 +99,38 @@ static const struct attribute_group dptf_power_attribute_group = { .name = "dptf_power" }; +static struct attribute *dptf_battery_attrs[] = { + &dev_attr_max_platform_power_mw.attr, + &dev_attr_max_steady_state_power_mw.attr, + &dev_attr_high_freq_impedance_mohm.attr, + &dev_attr_no_load_voltage_mv.attr, + &dev_attr_current_discharge_capbility_ma.attr, + NULL +}; + +static const struct attribute_group dptf_battery_attribute_group = { + .attrs = dptf_battery_attrs, + .name = "dptf_battery" +}; + +#define MAX_POWER_CHANGED 0x80 #define POWER_STATE_CHANGED 0x81 +#define STEADY_STATE_POWER_CHANGED 0x83 #define POWER_PROP_CHANGE_EVENT 0x84 +#define IMPEDANCED_CHNGED 0x85 +#define VOLTAGE_CURRENT_CHANGED 0x86 + +static long long dptf_participant_type(acpi_handle handle) +{ + unsigned long long ptype; + acpi_status status; + + status = acpi_evaluate_integer(handle, "PTYP", NULL, &ptype); + if (ACPI_FAILURE(status)) + return -ENODEV; + + return ptype; +} static void dptf_power_notify(acpi_handle handle, u32 event, void *data) { @@ -100,6 +144,15 @@ static void dptf_power_notify(acpi_handle handle, u32 event, void *data) case POWER_PROP_CHANGE_EVENT: attr = "rest_of_platform_power_mw"; break; + case MAX_POWER_CHANGED: + attr = "max_platform_power_mw"; + break; + case STEADY_STATE_POWER_CHANGED: + attr = "max_steady_state_power_mw"; + break; + case VOLTAGE_CURRENT_CHANGED: + attr = "no_load_voltage_mv"; + break; default: dev_err(&pdev->dev, "Unsupported event [0x%x]\n", event); return; @@ -109,13 +162,16 @@ static void dptf_power_notify(acpi_handle handle, u32 event, void *data) * Notify that an attribute is changed, so that user space can read * again. */ - sysfs_notify(&pdev->dev.kobj, "dptf_power", attr); + if (dptf_participant_type(handle) == 0x0CULL) + sysfs_notify(&pdev->dev.kobj, "dptf_battery", attr); + else + sysfs_notify(&pdev->dev.kobj, "dptf_power", attr); } static int dptf_power_add(struct platform_device *pdev) { + const struct attribute_group *attr_group; struct acpi_device *acpi_dev; - acpi_status status; unsigned long long ptype; int result; @@ -123,11 +179,12 @@ static int dptf_power_add(struct platform_device *pdev) if (!acpi_dev) return -ENODEV; - status = acpi_evaluate_integer(acpi_dev->handle, "PTYP", NULL, &ptype); - if (ACPI_FAILURE(status)) - return -ENODEV; - - if (ptype != 0x11) + ptype = dptf_participant_type(acpi_dev->handle); + if (ptype == 0x11) + attr_group = &dptf_power_attribute_group; + else if (ptype == 0x0C) + attr_group = &dptf_battery_attribute_group; + else return -ENODEV; result = acpi_install_notify_handler(acpi_dev->handle, @@ -138,7 +195,7 @@ static int dptf_power_add(struct platform_device *pdev) return result; result = sysfs_create_group(&pdev->dev.kobj, - &dptf_power_attribute_group); + attr_group); if (result) { acpi_remove_notify_handler(acpi_dev->handle, ACPI_DEVICE_NOTIFY, @@ -158,13 +215,18 @@ static int dptf_power_remove(struct platform_device *pdev) acpi_remove_notify_handler(acpi_dev->handle, ACPI_DEVICE_NOTIFY, dptf_power_notify); - sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); + + if (dptf_participant_type(acpi_dev->handle) == 0x0CULL) + sysfs_remove_group(&pdev->dev.kobj, &dptf_battery_attribute_group); + else + sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); return 0; } static const struct acpi_device_id int3407_device_ids[] = { {"INT3407", 0}, + {"INT3532", 0}, {"INTC1047", 0}, {"", 0}, }; -- cgit v1.2.3