Skip to content

Commit

Permalink
Merge branch 'acpi-pmic'
Browse files Browse the repository at this point in the history
* acpi-pmic:
  ACPI / PMIC: remove modular references from non-modular code
  ACPI / PMIC: intel: initialize result to 0
  ACPI / PMIC: intel: add REGS operation region support
  ACPI / PMIC: Add opregion driver for Intel BXT WhiskeyCove PMIC
  ACPI / PMIC: modify the pen function signature to take bit field

Conflicts:
	drivers/acpi/Makefile
  • Loading branch information
Rafael J. Wysocki committed Jul 25, 2016
2 parents 6149dff + 6d3ef8d commit 273b5a4
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 19 deletions.
6 changes: 6 additions & 0 deletions drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,12 @@ config XPOWER_PMIC_OPREGION
help
This config adds ACPI operation region support for XPower AXP288 PMIC.

config BXT_WC_PMIC_OPREGION
bool "ACPI operation region support for BXT WhiskeyCove PMIC"
depends on INTEL_SOC_PMIC
help
This config adds ACPI operation region support for BXT WhiskeyCove PMIC.

endif

config ACPI_CONFIGFS
Expand Down
2 changes: 2 additions & 0 deletions drivers/acpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ obj-$(CONFIG_ACPI_EXTLOG) += acpi_extlog.o
obj-$(CONFIG_PMIC_OPREGION) += pmic/intel_pmic.o
obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o

obj-$(CONFIG_ACPI_CONFIGFS) += acpi_configfs.o

video-objs += acpi_video.o video_detect.o
84 changes: 74 additions & 10 deletions drivers/acpi/pmic/intel_pmic.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,27 @@
* GNU General Public License for more details.
*/

#include <linux/module.h>
#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <acpi/acpi_lpat.h>
#include "intel_pmic.h"

#define PMIC_POWER_OPREGION_ID 0x8d
#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 mutex lock;
struct acpi_lpat_conversion_table *lpat_table;
struct regmap *regmap;
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,
Expand Down Expand Up @@ -131,7 +138,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
}

static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
u32 function, u64 *value)
int bit, u32 function, u64 *value)
{
struct intel_pmic_opregion_data *d = opregion->data;
struct regmap *regmap = opregion->regmap;
Expand All @@ -140,12 +147,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
return -ENXIO;

if (function == ACPI_READ)
return d->get_policy(regmap, reg, value);
return d->get_policy(regmap, reg, bit, value);

if (*value != 0 && *value != 1)
return -EINVAL;

return d->update_policy(regmap, reg, *value);
return d->update_policy(regmap, reg, bit, *value);
}

static bool pmic_thermal_is_temp(int address)
Expand All @@ -170,13 +177,13 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
{
struct intel_pmic_opregion *opregion = region_context;
struct intel_pmic_opregion_data *d = opregion->data;
int reg, result;
int reg, bit, result;

if (bits != 32 || !value64)
return AE_BAD_PARAMETER;

result = pmic_get_reg_bit(address, d->thermal_table,
d->thermal_table_count, &reg, NULL);
d->thermal_table_count, &reg, &bit);
if (result == -ENOENT)
return AE_BAD_PARAMETER;

Expand All @@ -187,7 +194,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
else if (pmic_thermal_is_aux(address))
result = pmic_thermal_aux(opregion, reg, function, value64);
else if (pmic_thermal_is_pen(address))
result = pmic_thermal_pen(opregion, reg, function, value64);
result = pmic_thermal_pen(opregion, reg, bit,
function, value64);
else
result = -EINVAL;

Expand All @@ -203,6 +211,48 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
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 = 0;

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,
struct regmap *regmap,
struct intel_pmic_opregion_data *d)
Expand Down Expand Up @@ -242,16 +292,30 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID,
intel_pmic_power_handler);
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;
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:
acpi_lpat_free_conversion_table(opregion->lpat_table);
return ret;
}
EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);

MODULE_LICENSE("GPL");
4 changes: 2 additions & 2 deletions drivers/acpi/pmic/intel_pmic.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct intel_pmic_opregion_data {
int (*update_power)(struct regmap *r, int reg, int bit, bool on);
int (*get_raw_temp)(struct regmap *r, int reg);
int (*update_aux)(struct regmap *r, int reg, int raw_temp);
int (*get_policy)(struct regmap *r, int reg, u64 *value);
int (*update_policy)(struct regmap *r, int reg, int enable);
int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value);
int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
struct pmic_table *power_table;
int power_table_count;
struct pmic_table *thermal_table;
Expand Down
Loading

0 comments on commit 273b5a4

Please sign in to comment.