Merge "regulator: cpr-regulator: Add support for Voltage Sensors"
This commit is contained in:
commit
f8dd376dbe
|
@ -0,0 +1,136 @@
|
|||
Voltage Sensors
|
||||
|
||||
Voltage Sensors are hardware blocks that sense the voltage at
|
||||
a particular point in hardware. The device is capable of issuing
|
||||
interrupts when a programmed min or max threshold is crossed.
|
||||
|
||||
Required Properties
|
||||
- compatible:
|
||||
Must be 'qcom,msm-vsens'
|
||||
|
||||
- reg:
|
||||
specifies the address and size of the Voltage Sensor block
|
||||
|
||||
- reg-names:
|
||||
"base" to identify the physical address base of the
|
||||
Voltage Sensor block.
|
||||
|
||||
- label:
|
||||
String indicating this vsens instance.
|
||||
|
||||
- qcom,vsens-cpus:
|
||||
Array of CPU phandles which correspond to the cores which are
|
||||
supplied power by the rail monitored by this vsens device.
|
||||
|
||||
- qcom,vsens-cal-id:
|
||||
The VSENS rail id to index into the SMEM data which points to
|
||||
the calibarated voltage and vsens-codes. This value is determined
|
||||
based on the number of voltage-sensors supported on a target.
|
||||
|
||||
Optional Properties
|
||||
- interrupts:
|
||||
IRQ lines used by Voltage Sensors
|
||||
|
||||
- interrupt-names:
|
||||
Descriptive names for IRQs used by Voltage Sensors.
|
||||
"max": maximum threshold crossed IRQ
|
||||
"min": minium threshold crossed IRQ
|
||||
|
||||
- qcom,temperature-pct:
|
||||
The percentage shift in voltage values over operational
|
||||
temperature range. This value is used to lower the floor
|
||||
and raise a ceiling voltage to account for temperature
|
||||
shifts. If not specified a default value of 15% is used.
|
||||
|
||||
- qcom,min-operational-floor-uv:
|
||||
The min floor voltage below which the voltage sensor
|
||||
is not operational and must be disabled. If this
|
||||
is not specified the voltage sensor is assumed to be
|
||||
operational for all voltage ranges.
|
||||
|
||||
- clocks:
|
||||
Array of clock tuples in which each tuple consists of a
|
||||
phandle to a clock device and a clock ID number.
|
||||
|
||||
- clock-names:
|
||||
The name of the voltage-sensor clock. The supported
|
||||
clock-name is 'vsens-clk'.
|
||||
|
||||
- qcom,corner-clock-rate:
|
||||
The clock rate (HZ) of the voltage sensor clock
|
||||
for each corner. The number of entries should match
|
||||
the 'qcom,num-corners'.
|
||||
|
||||
- qcom,calib-clock-rate:
|
||||
The clock rate (HZ) at which the VSENS calibration
|
||||
is done.
|
||||
|
||||
- qcom,num-corners:
|
||||
The number of corners supported by the voltage sensor.
|
||||
Its determined by the number of operating frequencies of
|
||||
the vsens-clk.
|
||||
|
||||
Sub Node required regulators
|
||||
- qcom,vsens-voltage:
|
||||
A node to indicate the voltage range monitored by the sensor.
|
||||
|
||||
- qcom,vsens-corner:
|
||||
A node to indicate the current corner of the voltage sensor.
|
||||
|
||||
Sub-nodes required properties for 'qcom,vsens-voltage' regulator
|
||||
|
||||
- regulator-name: A string used to describe the regulator
|
||||
- regulator-min-microvolt: Minimum voltage level expected to be
|
||||
monitored by the voltage sensor for
|
||||
a rail.
|
||||
- regulator-max-microvolt: Maximum voltage level expected to be
|
||||
monitored by the voltage sensor for
|
||||
a rail.
|
||||
|
||||
Sub-nodes required properties for 'qcom,vsens-corner' regulator
|
||||
|
||||
- regulator-name: A string used to describe the regulator
|
||||
- regulator-min-microvolt: The lowest corner supported by the voltage
|
||||
sensor. Its value is 1.
|
||||
- regulator-max-microvolt: The max corner supported by the voltage sensor.
|
||||
Its value is equal to 'qcom,num-corners'.
|
||||
|
||||
Any property defined as part of the core regulator binding, defined in
|
||||
regulator.txt, can also be used.
|
||||
|
||||
Example:
|
||||
vsens_apc0: vsens@b1d6000 {
|
||||
compatible = "qcom,msm-vsens";
|
||||
reg = <0xb1d6000 0xc>;
|
||||
reg-names = "base";
|
||||
interrupts = <0 265 0>,
|
||||
<0 266 0>;
|
||||
interrupt-names = "max",
|
||||
"min";
|
||||
label = "vsens-acpu0";
|
||||
|
||||
qcom,vsens-cal-id = <3>;
|
||||
qcom,vsens-cpus = <&CPU0 &CPU1 &CPU2 &CPU3>;
|
||||
|
||||
clock-names = "vsens_clk";
|
||||
clocks = <&clock_gcc clk_gcc_aps_0_clk>;
|
||||
|
||||
qcom,num-corners = <2>;
|
||||
qcom,corner-clock-rate =
|
||||
<300000000 540000000>;
|
||||
qcom,calib-clock-rate = <540000000>;
|
||||
qcom,min-operational-floor-uv = <500000>;
|
||||
qcom,temperature-pct = <20>;
|
||||
|
||||
vsens_apc0_voltage:qcom,vsens-voltage {
|
||||
regulator-name = "msm-vsens-apc0-voltage";
|
||||
regulator-min-microvolt = <700000>;
|
||||
regulator-max-microvolt = <1165000>;
|
||||
};
|
||||
|
||||
vsens_apc0_corner:qcom,vsens-corner {
|
||||
regulator-name = "msm-vsens-apc0-corner";
|
||||
regulator-min-microvolt = <1>;
|
||||
regulator-max-microvolt = <2>;
|
||||
};
|
||||
};
|
|
@ -649,6 +649,12 @@ Optional properties:
|
|||
the RPM corner to the corresponding APC virtual
|
||||
corner. This property must be defined if
|
||||
'rpm-apc-supply' is present.
|
||||
- qcom,vsens-corner-map: Array of integers which define the mapping of the VSENS corner to the
|
||||
corresponding APC fuse corner. The qcom,vsens-corner-map and
|
||||
vdd-vsense-corner-supply properties must both be specified for a given
|
||||
cpr-regulator device or neither must be specified.
|
||||
- vdd-vsens-corner-supply: Regulator to specify the current operating fuse corner to the Voltage Sensor.
|
||||
- vdd-vsens-voltage-supply: Regulator to specify the corner floor/ceiling voltages to the Voltage Sensor.
|
||||
|
||||
Example:
|
||||
apc_vreg_corner: regulator@f9018000 {
|
||||
|
@ -722,6 +728,10 @@ Example:
|
|||
qcom,cpr-clamp-timer-interval = <1>;
|
||||
qcom,cpr-apc-volt-step = <5000>;
|
||||
|
||||
qcom,vsens-corner-map = <1 2 2>;
|
||||
vdd-vsens-corner-supply = <&vsens_apc0_corner>;
|
||||
vdd-vsens-voltage-supply = <&vsens_apc0_voltage>;
|
||||
|
||||
rpm-apc-supply = <&rpm_apc_vreg>;
|
||||
qcom,rpm-apc-corner-map = <4 4 5 5 7 7 7 7 7 7 7 7>;
|
||||
|
||||
|
|
|
@ -534,6 +534,7 @@ CONFIG_MSM_OCMEM=y
|
|||
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
|
||||
CONFIG_MSM_BOOT_STATS=y
|
||||
CONFIG_MSM_SCM=y
|
||||
CONFIG_MSM_VSENS=y
|
||||
CONFIG_MEM_SHARE_QMI_SERVICE=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
|
|
|
@ -551,6 +551,7 @@ CONFIG_MSM_OCMEM_NONSECURE=y
|
|||
CONFIG_MSM_BOOT_STATS=y
|
||||
CONFIG_MSM_SCM=y
|
||||
CONFIG_MSM_XPU_ERR_FATAL=y
|
||||
CONFIG_MSM_VSENS=y
|
||||
CONFIG_MEM_SHARE_QMI_SERVICE=y
|
||||
CONFIG_MSM_TZ_LOG=y
|
||||
CONFIG_EXT2_FS=y
|
||||
|
|
|
@ -279,6 +279,13 @@ struct cpr_regulator {
|
|||
int *save_ctl;
|
||||
int *save_irq;
|
||||
|
||||
int *vsens_corner_map;
|
||||
/* vsens status */
|
||||
bool vsens_enabled;
|
||||
/* vsens regulators */
|
||||
struct regulator *vdd_vsens_corner;
|
||||
struct regulator *vdd_vsens_voltage;
|
||||
|
||||
/* Config parameters */
|
||||
bool enable;
|
||||
u32 ref_clk_khz;
|
||||
|
@ -703,12 +710,20 @@ static int cpr_scale_voltage(struct cpr_regulator *cpr_vreg, int corner,
|
|||
{
|
||||
int rc = 0, vdd_mx_vmin = 0;
|
||||
int mem_acc_corner = cpr_vreg->mem_acc_corner_map[corner];
|
||||
int apc_corner;
|
||||
int fuse_corner = cpr_vreg->corner_map[corner];
|
||||
int apc_corner, vsens_corner;
|
||||
|
||||
/* Determine the vdd_mx voltage */
|
||||
if (dir != NO_CHANGE && cpr_vreg->vdd_mx != NULL)
|
||||
vdd_mx_vmin = cpr_mx_get(cpr_vreg, corner, new_apc_volt);
|
||||
|
||||
|
||||
if (cpr_vreg->vdd_vsens_voltage && cpr_vreg->vsens_enabled) {
|
||||
rc = regulator_disable(cpr_vreg->vdd_vsens_voltage);
|
||||
if (!rc)
|
||||
cpr_vreg->vsens_enabled = false;
|
||||
}
|
||||
|
||||
if (dir == DOWN) {
|
||||
if (!rc && cpr_vreg->mem_acc_vreg)
|
||||
rc = regulator_set_voltage(cpr_vreg->mem_acc_vreg,
|
||||
|
@ -750,6 +765,22 @@ static int cpr_scale_voltage(struct cpr_regulator *cpr_vreg, int corner,
|
|||
rc = cpr_mx_set(cpr_vreg, corner, vdd_mx_vmin);
|
||||
}
|
||||
|
||||
if (!rc && cpr_vreg->vdd_vsens_corner) {
|
||||
vsens_corner = cpr_vreg->vsens_corner_map[fuse_corner];
|
||||
rc = regulator_set_voltage(cpr_vreg->vdd_vsens_corner,
|
||||
vsens_corner, vsens_corner);
|
||||
}
|
||||
if (!rc && cpr_vreg->vdd_vsens_voltage) {
|
||||
rc = regulator_set_voltage(cpr_vreg->vdd_vsens_voltage,
|
||||
cpr_vreg->floor_volt[corner],
|
||||
cpr_vreg->ceiling_volt[corner]);
|
||||
if (!rc && !cpr_vreg->vsens_enabled) {
|
||||
rc = regulator_enable(cpr_vreg->vdd_vsens_voltage);
|
||||
if (!rc)
|
||||
cpr_vreg->vsens_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4208,6 +4239,70 @@ static int cpr_rpm_apc_init(struct platform_device *pdev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cpr_vsens_init(struct platform_device *pdev,
|
||||
struct cpr_regulator *cpr_vreg)
|
||||
{
|
||||
int rc = 0, len = 0;
|
||||
struct device_node *of_node = pdev->dev.of_node;
|
||||
|
||||
if (of_find_property(of_node, "vdd-vsens-voltage-supply", NULL)) {
|
||||
cpr_vreg->vdd_vsens_voltage = devm_regulator_get(&pdev->dev,
|
||||
"vdd-vsens-voltage");
|
||||
if (IS_ERR_OR_NULL(cpr_vreg->vdd_vsens_voltage)) {
|
||||
rc = PTR_ERR(cpr_vreg->vdd_vsens_voltage);
|
||||
cpr_vreg->vdd_vsens_voltage = NULL;
|
||||
if (rc == -EPROBE_DEFER)
|
||||
return rc;
|
||||
/* device not found */
|
||||
cpr_debug(cpr_vreg, "regulator_get: vdd-vsens-voltage: rc=%d\n",
|
||||
rc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_find_property(of_node, "vdd-vsens-corner-supply", NULL)) {
|
||||
cpr_vreg->vdd_vsens_corner = devm_regulator_get(&pdev->dev,
|
||||
"vdd-vsens-corner");
|
||||
if (IS_ERR_OR_NULL(cpr_vreg->vdd_vsens_corner)) {
|
||||
rc = PTR_ERR(cpr_vreg->vdd_vsens_corner);
|
||||
cpr_vreg->vdd_vsens_corner = NULL;
|
||||
if (rc == -EPROBE_DEFER)
|
||||
return rc;
|
||||
/* device not found */
|
||||
cpr_debug(cpr_vreg, "regulator_get: vdd-vsens-corner: rc=%d\n",
|
||||
rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!of_find_property(of_node, "qcom,vsens-corner-map", &len)) {
|
||||
cpr_err(cpr_vreg, "qcom,vsens-corner-map missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len != cpr_vreg->num_fuse_corners * sizeof(u32)) {
|
||||
cpr_err(cpr_vreg, "qcom,vsens-corner-map length=%d is invalid: required:%d\n",
|
||||
len, cpr_vreg->num_fuse_corners);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpr_vreg->vsens_corner_map = devm_kcalloc(&pdev->dev,
|
||||
(cpr_vreg->num_fuse_corners + 1),
|
||||
sizeof(*cpr_vreg->vsens_corner_map), GFP_KERNEL);
|
||||
if (!cpr_vreg->vsens_corner_map)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = of_property_read_u32_array(of_node,
|
||||
"qcom,vsens-corner-map",
|
||||
&cpr_vreg->vsens_corner_map[1],
|
||||
cpr_vreg->num_fuse_corners);
|
||||
if (rc)
|
||||
cpr_err(cpr_vreg, "read qcom,vsens-corner-map failed, rc = %d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cpr_init_cpr(struct platform_device *pdev,
|
||||
struct cpr_regulator *cpr_vreg)
|
||||
{
|
||||
|
@ -5024,6 +5119,13 @@ static int cpr_regulator_probe(struct platform_device *pdev)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
rc = cpr_vsens_init(pdev, cpr_vreg);
|
||||
if (rc) {
|
||||
cpr_err(cpr_vreg, "Initialize vsens configuration failed rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cpr_apc_init(pdev, cpr_vreg);
|
||||
if (rc) {
|
||||
if (rc != -EPROBE_DEFER)
|
||||
|
|
|
@ -686,6 +686,17 @@ config TRACER_PKT
|
|||
processor communication protocols. The profiling information
|
||||
can be logged into the tracer packet itself.
|
||||
|
||||
config MSM_VSENS
|
||||
bool "Voltage Sensor Monitoring"
|
||||
help
|
||||
Enable support for Voltage Sensing Block available on certain MSM
|
||||
chipsets. Voltage Sensing Block monitors the voltage at certain points
|
||||
in the chip and makes recent readings available via FIFO registers.
|
||||
It can also be configured to trigger an interrupt when a min or max threshold is
|
||||
crossed.
|
||||
|
||||
Say yes to support these devices.
|
||||
|
||||
source "drivers/soc/qcom/memshare/Kconfig"
|
||||
|
||||
endif # ARCH_MSM
|
||||
|
|
|
@ -91,3 +91,4 @@ obj-$(CONFIG_QCOM_EARLY_RANDOM) += early_random.o
|
|||
obj-$(CONFIG_MSM_PACMAN) += msm_pacman.o
|
||||
obj-$(CONFIG_MSM_TEST_PACMAN) += msm_test_pacman.o
|
||||
obj-$(CONFIG_TRACER_PKT) += tracer_pkt.o
|
||||
obj-$(CONFIG_MSM_VSENS) += vsens.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue