.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * dptf_power: DPTF platform power driver |
---|
3 | 4 | * Copyright (c) 2016, Intel Corporation. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | | - * |
---|
14 | 5 | */ |
---|
15 | 6 | |
---|
16 | 7 | #include <linux/kernel.h> |
---|
.. | .. |
---|
19 | 10 | #include <linux/platform_device.h> |
---|
20 | 11 | |
---|
21 | 12 | /* |
---|
22 | | - * Presentation of attributes which are defined for INT3407. They are: |
---|
| 13 | + * Presentation of attributes which are defined for INT3407 and INT3532. |
---|
| 14 | + * They are: |
---|
23 | 15 | * PMAX : Maximum platform powe |
---|
24 | 16 | * PSRC : Platform power source |
---|
25 | 17 | * ARTG : Adapter rating |
---|
26 | 18 | * CTYP : Charger type |
---|
27 | 19 | * PBSS : Battery steady power |
---|
| 20 | + * PROP : Rest of worst case platform Power |
---|
| 21 | + * PBSS : Power Battery Steady State |
---|
| 22 | + * PBSS : Power Battery Steady State |
---|
| 23 | + * RBHF : High Frequency Impedance |
---|
| 24 | + * VBNL : Instantaneous No-Load Voltage |
---|
| 25 | + * CMPP : Current Discharge Capability |
---|
28 | 26 | */ |
---|
29 | 27 | #define DPTF_POWER_SHOW(name, object) \ |
---|
30 | 28 | static ssize_t name##_show(struct device *dev,\ |
---|
31 | 29 | struct device_attribute *attr,\ |
---|
32 | 30 | char *buf)\ |
---|
33 | 31 | {\ |
---|
34 | | - struct platform_device *pdev = to_platform_device(dev);\ |
---|
35 | | - struct acpi_device *acpi_dev = platform_get_drvdata(pdev);\ |
---|
| 32 | + struct acpi_device *acpi_dev = dev_get_drvdata(dev);\ |
---|
36 | 33 | unsigned long long val;\ |
---|
37 | 34 | acpi_status status;\ |
---|
38 | 35 | \ |
---|
.. | .. |
---|
49 | 46 | DPTF_POWER_SHOW(adapter_rating_mw, ARTG) |
---|
50 | 47 | DPTF_POWER_SHOW(battery_steady_power_mw, PBSS) |
---|
51 | 48 | DPTF_POWER_SHOW(charger_type, CTYP) |
---|
| 49 | +DPTF_POWER_SHOW(rest_of_platform_power_mw, PROP) |
---|
| 50 | +DPTF_POWER_SHOW(max_steady_state_power_mw, PBSS) |
---|
| 51 | +DPTF_POWER_SHOW(high_freq_impedance_mohm, RBHF) |
---|
| 52 | +DPTF_POWER_SHOW(no_load_voltage_mv, VBNL) |
---|
| 53 | +DPTF_POWER_SHOW(current_discharge_capbility_ma, CMPP); |
---|
52 | 54 | |
---|
53 | 55 | static DEVICE_ATTR_RO(max_platform_power_mw); |
---|
54 | 56 | static DEVICE_ATTR_RO(platform_power_source); |
---|
55 | 57 | static DEVICE_ATTR_RO(adapter_rating_mw); |
---|
56 | 58 | static DEVICE_ATTR_RO(battery_steady_power_mw); |
---|
57 | 59 | static DEVICE_ATTR_RO(charger_type); |
---|
| 60 | +static DEVICE_ATTR_RO(rest_of_platform_power_mw); |
---|
| 61 | +static DEVICE_ATTR_RO(max_steady_state_power_mw); |
---|
| 62 | +static DEVICE_ATTR_RO(high_freq_impedance_mohm); |
---|
| 63 | +static DEVICE_ATTR_RO(no_load_voltage_mv); |
---|
| 64 | +static DEVICE_ATTR_RO(current_discharge_capbility_ma); |
---|
| 65 | + |
---|
| 66 | +static ssize_t prochot_confirm_store(struct device *dev, |
---|
| 67 | + struct device_attribute *attr, |
---|
| 68 | + const char *buf, size_t count) |
---|
| 69 | +{ |
---|
| 70 | + struct acpi_device *acpi_dev = dev_get_drvdata(dev); |
---|
| 71 | + acpi_status status; |
---|
| 72 | + int seq_no; |
---|
| 73 | + |
---|
| 74 | + if (kstrtouint(buf, 0, &seq_no) < 0) |
---|
| 75 | + return -EINVAL; |
---|
| 76 | + |
---|
| 77 | + status = acpi_execute_simple_method(acpi_dev->handle, "PBOK", seq_no); |
---|
| 78 | + if (ACPI_SUCCESS(status)) |
---|
| 79 | + return count; |
---|
| 80 | + |
---|
| 81 | + return -EINVAL; |
---|
| 82 | +} |
---|
| 83 | + |
---|
| 84 | +static DEVICE_ATTR_WO(prochot_confirm); |
---|
58 | 85 | |
---|
59 | 86 | static struct attribute *dptf_power_attrs[] = { |
---|
60 | 87 | &dev_attr_max_platform_power_mw.attr, |
---|
.. | .. |
---|
62 | 89 | &dev_attr_adapter_rating_mw.attr, |
---|
63 | 90 | &dev_attr_battery_steady_power_mw.attr, |
---|
64 | 91 | &dev_attr_charger_type.attr, |
---|
| 92 | + &dev_attr_rest_of_platform_power_mw.attr, |
---|
| 93 | + &dev_attr_prochot_confirm.attr, |
---|
65 | 94 | NULL |
---|
66 | 95 | }; |
---|
67 | 96 | |
---|
.. | .. |
---|
70 | 99 | .name = "dptf_power" |
---|
71 | 100 | }; |
---|
72 | 101 | |
---|
| 102 | +static struct attribute *dptf_battery_attrs[] = { |
---|
| 103 | + &dev_attr_max_platform_power_mw.attr, |
---|
| 104 | + &dev_attr_max_steady_state_power_mw.attr, |
---|
| 105 | + &dev_attr_high_freq_impedance_mohm.attr, |
---|
| 106 | + &dev_attr_no_load_voltage_mv.attr, |
---|
| 107 | + &dev_attr_current_discharge_capbility_ma.attr, |
---|
| 108 | + NULL |
---|
| 109 | +}; |
---|
| 110 | + |
---|
| 111 | +static const struct attribute_group dptf_battery_attribute_group = { |
---|
| 112 | + .attrs = dptf_battery_attrs, |
---|
| 113 | + .name = "dptf_battery" |
---|
| 114 | +}; |
---|
| 115 | + |
---|
| 116 | +#define MAX_POWER_CHANGED 0x80 |
---|
| 117 | +#define POWER_STATE_CHANGED 0x81 |
---|
| 118 | +#define STEADY_STATE_POWER_CHANGED 0x83 |
---|
| 119 | +#define POWER_PROP_CHANGE_EVENT 0x84 |
---|
| 120 | +#define IMPEDANCED_CHNGED 0x85 |
---|
| 121 | +#define VOLTAGE_CURRENT_CHANGED 0x86 |
---|
| 122 | + |
---|
| 123 | +static long long dptf_participant_type(acpi_handle handle) |
---|
| 124 | +{ |
---|
| 125 | + unsigned long long ptype; |
---|
| 126 | + acpi_status status; |
---|
| 127 | + |
---|
| 128 | + status = acpi_evaluate_integer(handle, "PTYP", NULL, &ptype); |
---|
| 129 | + if (ACPI_FAILURE(status)) |
---|
| 130 | + return -ENODEV; |
---|
| 131 | + |
---|
| 132 | + return ptype; |
---|
| 133 | +} |
---|
| 134 | + |
---|
| 135 | +static void dptf_power_notify(acpi_handle handle, u32 event, void *data) |
---|
| 136 | +{ |
---|
| 137 | + struct platform_device *pdev = data; |
---|
| 138 | + char *attr; |
---|
| 139 | + |
---|
| 140 | + switch (event) { |
---|
| 141 | + case POWER_STATE_CHANGED: |
---|
| 142 | + attr = "platform_power_source"; |
---|
| 143 | + break; |
---|
| 144 | + case POWER_PROP_CHANGE_EVENT: |
---|
| 145 | + attr = "rest_of_platform_power_mw"; |
---|
| 146 | + break; |
---|
| 147 | + case MAX_POWER_CHANGED: |
---|
| 148 | + attr = "max_platform_power_mw"; |
---|
| 149 | + break; |
---|
| 150 | + case STEADY_STATE_POWER_CHANGED: |
---|
| 151 | + attr = "max_steady_state_power_mw"; |
---|
| 152 | + break; |
---|
| 153 | + case VOLTAGE_CURRENT_CHANGED: |
---|
| 154 | + attr = "no_load_voltage_mv"; |
---|
| 155 | + break; |
---|
| 156 | + default: |
---|
| 157 | + dev_err(&pdev->dev, "Unsupported event [0x%x]\n", event); |
---|
| 158 | + return; |
---|
| 159 | + } |
---|
| 160 | + |
---|
| 161 | + /* |
---|
| 162 | + * Notify that an attribute is changed, so that user space can read |
---|
| 163 | + * again. |
---|
| 164 | + */ |
---|
| 165 | + if (dptf_participant_type(handle) == 0x0CULL) |
---|
| 166 | + sysfs_notify(&pdev->dev.kobj, "dptf_battery", attr); |
---|
| 167 | + else |
---|
| 168 | + sysfs_notify(&pdev->dev.kobj, "dptf_power", attr); |
---|
| 169 | +} |
---|
| 170 | + |
---|
73 | 171 | static int dptf_power_add(struct platform_device *pdev) |
---|
74 | 172 | { |
---|
| 173 | + const struct attribute_group *attr_group; |
---|
75 | 174 | struct acpi_device *acpi_dev; |
---|
76 | | - acpi_status status; |
---|
77 | 175 | unsigned long long ptype; |
---|
78 | 176 | int result; |
---|
79 | 177 | |
---|
.. | .. |
---|
81 | 179 | if (!acpi_dev) |
---|
82 | 180 | return -ENODEV; |
---|
83 | 181 | |
---|
84 | | - status = acpi_evaluate_integer(acpi_dev->handle, "PTYP", NULL, &ptype); |
---|
85 | | - if (ACPI_FAILURE(status)) |
---|
| 182 | + ptype = dptf_participant_type(acpi_dev->handle); |
---|
| 183 | + if (ptype == 0x11) |
---|
| 184 | + attr_group = &dptf_power_attribute_group; |
---|
| 185 | + else if (ptype == 0x0C) |
---|
| 186 | + attr_group = &dptf_battery_attribute_group; |
---|
| 187 | + else |
---|
86 | 188 | return -ENODEV; |
---|
87 | 189 | |
---|
88 | | - if (ptype != 0x11) |
---|
89 | | - return -ENODEV; |
---|
90 | | - |
---|
91 | | - result = sysfs_create_group(&pdev->dev.kobj, |
---|
92 | | - &dptf_power_attribute_group); |
---|
| 190 | + result = acpi_install_notify_handler(acpi_dev->handle, |
---|
| 191 | + ACPI_DEVICE_NOTIFY, |
---|
| 192 | + dptf_power_notify, |
---|
| 193 | + (void *)pdev); |
---|
93 | 194 | if (result) |
---|
94 | 195 | return result; |
---|
| 196 | + |
---|
| 197 | + result = sysfs_create_group(&pdev->dev.kobj, |
---|
| 198 | + attr_group); |
---|
| 199 | + if (result) { |
---|
| 200 | + acpi_remove_notify_handler(acpi_dev->handle, |
---|
| 201 | + ACPI_DEVICE_NOTIFY, |
---|
| 202 | + dptf_power_notify); |
---|
| 203 | + return result; |
---|
| 204 | + } |
---|
95 | 205 | |
---|
96 | 206 | platform_set_drvdata(pdev, acpi_dev); |
---|
97 | 207 | |
---|
.. | .. |
---|
100 | 210 | |
---|
101 | 211 | static int dptf_power_remove(struct platform_device *pdev) |
---|
102 | 212 | { |
---|
| 213 | + struct acpi_device *acpi_dev = platform_get_drvdata(pdev); |
---|
103 | 214 | |
---|
104 | | - sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); |
---|
| 215 | + acpi_remove_notify_handler(acpi_dev->handle, |
---|
| 216 | + ACPI_DEVICE_NOTIFY, |
---|
| 217 | + dptf_power_notify); |
---|
| 218 | + |
---|
| 219 | + if (dptf_participant_type(acpi_dev->handle) == 0x0CULL) |
---|
| 220 | + sysfs_remove_group(&pdev->dev.kobj, &dptf_battery_attribute_group); |
---|
| 221 | + else |
---|
| 222 | + sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); |
---|
105 | 223 | |
---|
106 | 224 | return 0; |
---|
107 | 225 | } |
---|
108 | 226 | |
---|
109 | 227 | static const struct acpi_device_id int3407_device_ids[] = { |
---|
110 | 228 | {"INT3407", 0}, |
---|
| 229 | + {"INT3532", 0}, |
---|
| 230 | + {"INTC1047", 0}, |
---|
| 231 | + {"INTC1050", 0}, |
---|
| 232 | + {"INTC1060", 0}, |
---|
| 233 | + {"INTC1061", 0}, |
---|
111 | 234 | {"", 0}, |
---|
112 | 235 | }; |
---|
113 | 236 | MODULE_DEVICE_TABLE(acpi, int3407_device_ids); |
---|
.. | .. |
---|
116 | 239 | .probe = dptf_power_add, |
---|
117 | 240 | .remove = dptf_power_remove, |
---|
118 | 241 | .driver = { |
---|
119 | | - .name = "DPTF Platform Power", |
---|
| 242 | + .name = "dptf_power", |
---|
120 | 243 | .acpi_match_table = int3407_device_ids, |
---|
121 | 244 | }, |
---|
122 | 245 | }; |
---|