ACPI / PMIC: intel: add REGS operation region support
At least some of the Broxtons have a third custom OpRegion named REGS. This adds handling for it. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
9b928c78bb
commit
0afa877a56
@ -21,12 +21,19 @@
|
|||||||
|
|
||||||
#define PMIC_POWER_OPREGION_ID 0x8d
|
#define PMIC_POWER_OPREGION_ID 0x8d
|
||||||
#define PMIC_THERMAL_OPREGION_ID 0x8c
|
#define PMIC_THERMAL_OPREGION_ID 0x8c
|
||||||
|
#define PMIC_REGS_OPREGION_ID 0x8f
|
||||||
|
|
||||||
|
struct intel_pmic_regs_handler_ctx {
|
||||||
|
unsigned int val;
|
||||||
|
u16 addr;
|
||||||
|
};
|
||||||
|
|
||||||
struct intel_pmic_opregion {
|
struct intel_pmic_opregion {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct acpi_lpat_conversion_table *lpat_table;
|
struct acpi_lpat_conversion_table *lpat_table;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct intel_pmic_opregion_data *data;
|
struct intel_pmic_opregion_data *data;
|
||||||
|
struct intel_pmic_regs_handler_ctx ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pmic_get_reg_bit(int address, struct pmic_table *table,
|
static int pmic_get_reg_bit(int address, struct pmic_table *table,
|
||||||
@ -204,6 +211,48 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
|
|||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static acpi_status intel_pmic_regs_handler(u32 function,
|
||||||
|
acpi_physical_address address, u32 bits, u64 *value64,
|
||||||
|
void *handler_context, void *region_context)
|
||||||
|
{
|
||||||
|
struct intel_pmic_opregion *opregion = region_context;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
switch (address) {
|
||||||
|
case 0:
|
||||||
|
return AE_OK;
|
||||||
|
case 1:
|
||||||
|
opregion->ctx.addr |= (*value64 & 0xff) << 8;
|
||||||
|
return AE_OK;
|
||||||
|
case 2:
|
||||||
|
opregion->ctx.addr |= *value64 & 0xff;
|
||||||
|
return AE_OK;
|
||||||
|
case 3:
|
||||||
|
opregion->ctx.val = *value64 & 0xff;
|
||||||
|
return AE_OK;
|
||||||
|
case 4:
|
||||||
|
if (*value64) {
|
||||||
|
result = regmap_write(opregion->regmap, opregion->ctx.addr,
|
||||||
|
opregion->ctx.val);
|
||||||
|
} else {
|
||||||
|
result = regmap_read(opregion->regmap, opregion->ctx.addr,
|
||||||
|
&opregion->ctx.val);
|
||||||
|
if (result == 0)
|
||||||
|
*value64 = opregion->ctx.val;
|
||||||
|
}
|
||||||
|
memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
if (result == -EINVAL)
|
||||||
|
return AE_BAD_PARAMETER;
|
||||||
|
else
|
||||||
|
return AE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
|
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
|
||||||
struct regmap *regmap,
|
struct regmap *regmap,
|
||||||
struct intel_pmic_opregion_data *d)
|
struct intel_pmic_opregion_data *d)
|
||||||
@ -243,12 +292,28 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
|
|||||||
acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
|
acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
|
||||||
intel_pmic_power_handler);
|
intel_pmic_power_handler);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out_error;
|
goto out_remove_power_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = acpi_install_address_space_handler(handle,
|
||||||
|
PMIC_REGS_OPREGION_ID, intel_pmic_regs_handler, NULL,
|
||||||
|
opregion);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out_remove_thermal_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
opregion->data = d;
|
opregion->data = d;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_remove_thermal_handler:
|
||||||
|
acpi_remove_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID,
|
||||||
|
intel_pmic_thermal_handler);
|
||||||
|
|
||||||
|
out_remove_power_handler:
|
||||||
|
acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
|
||||||
|
intel_pmic_power_handler);
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
acpi_lpat_free_conversion_table(opregion->lpat_table);
|
acpi_lpat_free_conversion_table(opregion->lpat_table);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user