13
13
* GNU General Public License for more details.
14
14
*/
15
15
16
- #include <linux/module .h>
16
+ #include <linux/export .h>
17
17
#include <linux/acpi.h>
18
18
#include <linux/regmap.h>
19
19
#include <acpi/acpi_lpat.h>
20
20
#include "intel_pmic.h"
21
21
22
22
#define PMIC_POWER_OPREGION_ID 0x8d
23
23
#define PMIC_THERMAL_OPREGION_ID 0x8c
24
+ #define PMIC_REGS_OPREGION_ID 0x8f
25
+
26
+ struct intel_pmic_regs_handler_ctx {
27
+ unsigned int val ;
28
+ u16 addr ;
29
+ };
24
30
25
31
struct intel_pmic_opregion {
26
32
struct mutex lock ;
27
33
struct acpi_lpat_conversion_table * lpat_table ;
28
34
struct regmap * regmap ;
29
35
struct intel_pmic_opregion_data * data ;
36
+ struct intel_pmic_regs_handler_ctx ctx ;
30
37
};
31
38
32
39
static int pmic_get_reg_bit (int address , struct pmic_table * table ,
@@ -131,7 +138,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
131
138
}
132
139
133
140
static int pmic_thermal_pen (struct intel_pmic_opregion * opregion , int reg ,
134
- u32 function , u64 * value )
141
+ int bit , u32 function , u64 * value )
135
142
{
136
143
struct intel_pmic_opregion_data * d = opregion -> data ;
137
144
struct regmap * regmap = opregion -> regmap ;
@@ -140,12 +147,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
140
147
return - ENXIO ;
141
148
142
149
if (function == ACPI_READ )
143
- return d -> get_policy (regmap , reg , value );
150
+ return d -> get_policy (regmap , reg , bit , value );
144
151
145
152
if (* value != 0 && * value != 1 )
146
153
return - EINVAL ;
147
154
148
- return d -> update_policy (regmap , reg , * value );
155
+ return d -> update_policy (regmap , reg , bit , * value );
149
156
}
150
157
151
158
static bool pmic_thermal_is_temp (int address )
@@ -170,13 +177,13 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
170
177
{
171
178
struct intel_pmic_opregion * opregion = region_context ;
172
179
struct intel_pmic_opregion_data * d = opregion -> data ;
173
- int reg , result ;
180
+ int reg , bit , result ;
174
181
175
182
if (bits != 32 || !value64 )
176
183
return AE_BAD_PARAMETER ;
177
184
178
185
result = pmic_get_reg_bit (address , d -> thermal_table ,
179
- d -> thermal_table_count , & reg , NULL );
186
+ d -> thermal_table_count , & reg , & bit );
180
187
if (result == - ENOENT )
181
188
return AE_BAD_PARAMETER ;
182
189
@@ -187,7 +194,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
187
194
else if (pmic_thermal_is_aux (address ))
188
195
result = pmic_thermal_aux (opregion , reg , function , value64 );
189
196
else if (pmic_thermal_is_pen (address ))
190
- result = pmic_thermal_pen (opregion , reg , function , value64 );
197
+ result = pmic_thermal_pen (opregion , reg , bit ,
198
+ function , value64 );
191
199
else
192
200
result = - EINVAL ;
193
201
@@ -203,6 +211,48 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
203
211
return AE_OK ;
204
212
}
205
213
214
+ static acpi_status intel_pmic_regs_handler (u32 function ,
215
+ acpi_physical_address address , u32 bits , u64 * value64 ,
216
+ void * handler_context , void * region_context )
217
+ {
218
+ struct intel_pmic_opregion * opregion = region_context ;
219
+ int result = 0 ;
220
+
221
+ switch (address ) {
222
+ case 0 :
223
+ return AE_OK ;
224
+ case 1 :
225
+ opregion -> ctx .addr |= (* value64 & 0xff ) << 8 ;
226
+ return AE_OK ;
227
+ case 2 :
228
+ opregion -> ctx .addr |= * value64 & 0xff ;
229
+ return AE_OK ;
230
+ case 3 :
231
+ opregion -> ctx .val = * value64 & 0xff ;
232
+ return AE_OK ;
233
+ case 4 :
234
+ if (* value64 ) {
235
+ result = regmap_write (opregion -> regmap , opregion -> ctx .addr ,
236
+ opregion -> ctx .val );
237
+ } else {
238
+ result = regmap_read (opregion -> regmap , opregion -> ctx .addr ,
239
+ & opregion -> ctx .val );
240
+ if (result == 0 )
241
+ * value64 = opregion -> ctx .val ;
242
+ }
243
+ memset (& opregion -> ctx , 0x00 , sizeof (opregion -> ctx ));
244
+ }
245
+
246
+ if (result < 0 ) {
247
+ if (result == - EINVAL )
248
+ return AE_BAD_PARAMETER ;
249
+ else
250
+ return AE_ERROR ;
251
+ }
252
+
253
+ return AE_OK ;
254
+ }
255
+
206
256
int intel_pmic_install_opregion_handler (struct device * dev , acpi_handle handle ,
207
257
struct regmap * regmap ,
208
258
struct intel_pmic_opregion_data * d )
@@ -242,16 +292,30 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
242
292
acpi_remove_address_space_handler (handle , PMIC_POWER_OPREGION_ID ,
243
293
intel_pmic_power_handler );
244
294
ret = - ENODEV ;
245
- goto out_error ;
295
+ goto out_remove_power_handler ;
296
+ }
297
+
298
+ status = acpi_install_address_space_handler (handle ,
299
+ PMIC_REGS_OPREGION_ID , intel_pmic_regs_handler , NULL ,
300
+ opregion );
301
+ if (ACPI_FAILURE (status )) {
302
+ ret = - ENODEV ;
303
+ goto out_remove_thermal_handler ;
246
304
}
247
305
248
306
opregion -> data = d ;
249
307
return 0 ;
250
308
309
+ out_remove_thermal_handler :
310
+ acpi_remove_address_space_handler (handle , PMIC_THERMAL_OPREGION_ID ,
311
+ intel_pmic_thermal_handler );
312
+
313
+ out_remove_power_handler :
314
+ acpi_remove_address_space_handler (handle , PMIC_POWER_OPREGION_ID ,
315
+ intel_pmic_power_handler );
316
+
251
317
out_error :
252
318
acpi_lpat_free_conversion_table (opregion -> lpat_table );
253
319
return ret ;
254
320
}
255
321
EXPORT_SYMBOL_GPL (intel_pmic_install_opregion_handler );
256
-
257
- MODULE_LICENSE ("GPL" );
0 commit comments