Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * intel_pmic.c - Intel PMIC operation region driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2014 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/mfd/intel_soc_pmic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <acpi/acpi_lpat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "intel_pmic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define PMIC_POWER_OPREGION_ID		0x8d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define PMIC_THERMAL_OPREGION_ID	0x8c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define PMIC_REGS_OPREGION_ID		0x8f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) struct intel_pmic_regs_handler_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	u16 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) struct intel_pmic_opregion {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct acpi_lpat_conversion_table *lpat_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct intel_pmic_opregion_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct intel_pmic_regs_handler_ctx ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static struct intel_pmic_opregion *intel_pmic_opregion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static int pmic_get_reg_bit(int address, struct pmic_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 			    int count, int *reg, int *bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		if (table[i].address == address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			*reg = table[i].reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			if (bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 				*bit = table[i].bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static acpi_status intel_pmic_power_handler(u32 function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		acpi_physical_address address, u32 bits, u64 *value64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		void *handler_context, void *region_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct intel_pmic_opregion *opregion = region_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct regmap *regmap = opregion->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	struct intel_pmic_opregion_data *d = opregion->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	int reg, bit, result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	if (bits != 32 || !value64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (function == ACPI_WRITE && !(*value64 == 0 || *value64 == 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	result = pmic_get_reg_bit(address, d->power_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				  d->power_table_count, &reg, &bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (result == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	mutex_lock(&opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	result = function == ACPI_READ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		d->get_power(regmap, reg, bit, value64) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		d->update_power(regmap, reg, bit, *value64 == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	mutex_unlock(&opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	return result ? AE_ERROR : AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) static int pmic_read_temp(struct intel_pmic_opregion *opregion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			  int reg, u64 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	int raw_temp, temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (!opregion->data->get_raw_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	raw_temp = opregion->data->get_raw_temp(opregion->regmap, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (raw_temp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		return raw_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (!opregion->lpat_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		*value = raw_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (temp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	*value = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int pmic_thermal_temp(struct intel_pmic_opregion *opregion, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			     u32 function, u64 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	return function == ACPI_READ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		pmic_read_temp(opregion, reg, value) : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			    u32 function, u64 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	int raw_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (function == ACPI_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		return pmic_read_temp(opregion, reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (!opregion->data->update_aux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (opregion->lpat_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		raw_temp = acpi_lpat_temp_to_raw(opregion->lpat_table, *value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		if (raw_temp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			return raw_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		raw_temp = *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return opregion->data->update_aux(opregion->regmap, reg, raw_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			    int bit, u32 function, u64 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	struct intel_pmic_opregion_data *d = opregion->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	struct regmap *regmap = opregion->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (!d->get_policy || !d->update_policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (function == ACPI_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		return d->get_policy(regmap, reg, bit, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (*value != 0 && *value != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return d->update_policy(regmap, reg, bit, *value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static bool pmic_thermal_is_temp(int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	return (address <= 0x3c) && !(address % 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static bool pmic_thermal_is_aux(int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	return (address >= 4 && address <= 0x40 && !((address - 4) % 12)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	       (address >= 8 && address <= 0x44 && !((address - 8) % 12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static bool pmic_thermal_is_pen(int address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	return address >= 0x48 && address <= 0x5c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static acpi_status intel_pmic_thermal_handler(u32 function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		acpi_physical_address address, u32 bits, u64 *value64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		void *handler_context, void *region_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	struct intel_pmic_opregion *opregion = region_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	struct intel_pmic_opregion_data *d = opregion->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	int reg, bit, result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (bits != 32 || !value64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	result = pmic_get_reg_bit(address, d->thermal_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 				  d->thermal_table_count, &reg, &bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (result == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	mutex_lock(&opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	if (pmic_thermal_is_temp(address))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		result = pmic_thermal_temp(opregion, reg, function, value64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	else if (pmic_thermal_is_aux(address))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		result = pmic_thermal_aux(opregion, reg, function, value64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	else if (pmic_thermal_is_pen(address))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		result = pmic_thermal_pen(opregion, reg, bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 						function, value64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	mutex_unlock(&opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		if (result == -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static acpi_status intel_pmic_regs_handler(u32 function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		acpi_physical_address address, u32 bits, u64 *value64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		void *handler_context, void *region_context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct intel_pmic_opregion *opregion = region_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	int result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	if (function == ACPI_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		switch (address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			opregion->ctx.addr |= (*value64 & 0xff) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 			return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			opregion->ctx.addr |= *value64 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			opregion->ctx.val = *value64 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			if (*value64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				result = regmap_write(opregion->regmap, opregion->ctx.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 						      opregion->ctx.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 				result = regmap_read(opregion->regmap, opregion->ctx.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 						     &opregion->ctx.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			opregion->ctx.addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (function == ACPI_READ && address == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		*value64 = opregion->ctx.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		if (result == -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			return AE_BAD_PARAMETER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 					struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 					struct intel_pmic_opregion_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	struct intel_pmic_opregion *opregion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (!dev || !regmap || !d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (!handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	opregion = devm_kzalloc(dev, sizeof(*opregion), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (!opregion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	mutex_init(&opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	opregion->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	opregion->lpat_table = acpi_lpat_get_conversion_table(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	if (d->power_table_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		status = acpi_install_address_space_handler(handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 						    PMIC_POWER_OPREGION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 						    intel_pmic_power_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 						    NULL, opregion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if (d->thermal_table_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		status = acpi_install_address_space_handler(handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 						    PMIC_THERMAL_OPREGION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 						    intel_pmic_thermal_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 						    NULL, opregion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		goto out_remove_power_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	status = acpi_install_address_space_handler(handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			PMIC_REGS_OPREGION_ID, intel_pmic_regs_handler, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			opregion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		goto out_remove_thermal_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	opregion->data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	intel_pmic_opregion = opregion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) out_remove_thermal_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (d->thermal_table_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		acpi_remove_address_space_handler(handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 						  PMIC_THERMAL_OPREGION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 						  intel_pmic_thermal_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) out_remove_power_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (d->power_table_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		acpi_remove_address_space_handler(handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 						  PMIC_POWER_OPREGION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 						  intel_pmic_power_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	acpi_lpat_free_conversion_table(opregion->lpat_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  * intel_soc_pmic_exec_mipi_pmic_seq_element - Execute PMIC MIPI sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  * @i2c_address:  I2C client address for the PMIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * @reg_address:  PMIC register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * @value:        New value for the register bits to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * @mask:         Mask indicating which register bits to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * DSI LCD panels describe an initialization sequence in the i915 VBT (Video
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * BIOS Tables) using so called MIPI sequences. One possible element in these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  * sequences is a PMIC specific element of 15 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * This function executes these PMIC specific elements sending the embedded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  * commands to the PMIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  * Return 0 on success, < 0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 					      u32 value, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	struct intel_pmic_opregion_data *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	if (!intel_pmic_opregion) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		pr_warn("%s: No PMIC registered\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	d = intel_pmic_opregion->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	mutex_lock(&intel_pmic_opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	if (d->exec_mipi_pmic_seq_element) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 						    i2c_address, reg_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 						    value, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	} else if (d->pmic_i2c_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		if (i2c_address == d->pmic_i2c_address) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			ret = regmap_update_bits(intel_pmic_opregion->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 						 reg_address, mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			       __func__, i2c_address, reg_address, value, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		pr_warn("%s: Not implemented\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		pr_warn("%s: i2c-addr: 0x%x reg-addr 0x%x value 0x%x mask 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			__func__, i2c_address, reg_address, value, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	mutex_unlock(&intel_pmic_opregion->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EXPORT_SYMBOL_GPL(intel_soc_pmic_exec_mipi_pmic_seq_element);