Merge "regulator: cpr-regulator: Add support for Voltage Sensors"

This commit is contained in:
Linux Build Service Account 2015-08-16 16:19:46 -07:00 committed by Gerrit - the friendly Code Review server
commit f8dd376dbe
8 changed files with 1585 additions and 1 deletions

View File

@ -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>;
};
};

View File

@ -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>;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

1322
drivers/soc/qcom/vsens.c Normal file

File diff suppressed because it is too large Load Diff