Merge "msm: krait-regulator: use phase management for v2"

This commit is contained in:
Linux Build Service Account
2013-03-05 17:50:48 -08:00
committed by Gerrit - the friendly Code Review server
5 changed files with 209 additions and 130 deletions
@@ -1,5 +1,20 @@
Krait Voltage regulators
The cpus are powered using a single supply powered by PMIC ganged regulators operating in
different phases. Individual kraits further can draw power from the single supply via
a LDO or a head switch (BHS). The first level node represents the PMIC ganged regulator
and its properties and encompasses second level nodes that represent the individual
krait LDO/BHS control regulator.
[First Level Nodes]
Required properties:
- compatible: Must be "qcom,krait-pdn"
Optional properties:
- qcom,use-phase-switching indicates whether the driver should add/shed phases on the PMIC
ganged regulator as cpus are hotplugged.
[Second Level Nodes]
Required properties:
- compatible: Must be "qcom,krait-regulator"
- reg: Specifies the address and size for this regulator device,
@@ -27,19 +42,26 @@ Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.
Example:
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait0";
reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <745000>;
qcom,ldo-default-voltage = <745000>;
qcom,ldo-threshold-voltage = <750000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = 0;
};
krait_pdn: krait-pdn {
compatible = "qcom,krait-pdn";
qcom,use-phase-switching;
#address-cells = <1>;
#size-cells = <1>;
ranges;
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait0";
reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <0>;
};
};
+66 -59
View File
@@ -423,68 +423,75 @@
};
/ {
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait0";
reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <0>;
};
krait_pdn: krait-pdn {
compatible = "qcom,krait-pdn";
#address-cells = <1>;
#size-cells = <1>;
ranges;
krait1_vreg: regulator@f9098000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait1";
reg = <0xf9098000 0x1000>, /* APCS_ALIAS1_KPSS_ACS */
<0xf909a800 0x1000>; /* APCS_ALIAS1_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <1>;
};
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait0";
reg = <0xf9088000 0x1000>, /* APCS_ALIAS0_KPSS_ACS */
<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <0>;
};
krait2_vreg: regulator@f90a8000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait2";
reg = <0xf90a8000 0x1000>, /* APCS_ALIAS2_KPSS_ACS */
<0xf90aa800 0x1000>; /* APCS_ALIAS2_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <2>;
};
krait1_vreg: regulator@f9098000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait1";
reg = <0xf9098000 0x1000>, /* APCS_ALIAS1_KPSS_ACS */
<0xf909a800 0x1000>; /* APCS_ALIAS1_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <1>;
};
krait3_vreg: regulator@f90b8000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait3";
reg = <0xf90b8000 0x1000>, /* APCS_ALIAS3_KPSS_ACS */
<0xf90ba800 0x1000>; /* APCS_ALIAS3_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <3>;
krait2_vreg: regulator@f90a8000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait2";
reg = <0xf90a8000 0x1000>, /* APCS_ALIAS2_KPSS_ACS */
<0xf90aa800 0x1000>; /* APCS_ALIAS2_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <2>;
};
krait3_vreg: regulator@f90b8000 {
compatible = "qcom,krait-regulator";
regulator-name = "krait3";
reg = <0xf90b8000 0x1000>, /* APCS_ALIAS3_KPSS_ACS */
<0xf90ba800 0x1000>; /* APCS_ALIAS3_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
qcom,ldo-threshold-voltage = <850000>;
qcom,ldo-delta-voltage = <50000>;
qcom,cpu-num = <3>;
};
};
spi_eth_vreg: spi_eth_phy_vreg {
+4
View File
@@ -111,3 +111,7 @@
<2024000 1212000>,
<2132000 1279000>;
};
&krait_pdn {
qcom,use-phase-switching;
};
+100 -55
View File
@@ -155,6 +155,7 @@ struct pmic_gang_vreg {
bool pfm_mode;
int pmic_min_uV_for_retention;
bool retention_enabled;
bool use_phase_switching;
};
static struct pmic_gang_vreg *the_gang;
@@ -390,13 +391,17 @@ static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
return 0;
}
static int set_pmic_gang_phases(int phase_count)
static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
{
/*
* TODO : spm writes for phase control,
* pmic phase control is not working yet
*/
return 0;
pr_debug("programming phase_count = %d\n", phase_count);
if (pvreg->use_phase_switching)
/*
* note the PMIC sets the phase count to one more than
* the value in the register - hence subtract 1 from it
*/
return msm_spm_apcs_set_phase(phase_count - 1);
else
return 0;
}
static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
@@ -547,14 +552,19 @@ static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
int load_uA)
{
struct pmic_gang_vreg *pvreg = from->pvreg;
int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE) - 1;
int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE);
int rc = 0;
if (phase_count < 0)
phase_count = 0;
if (phase_count <= 0)
phase_count = 1;
/* Increase phases if it is less than the number of cpus online */
if (phase_count < num_online_cpus()) {
phase_count = num_online_cpus();
}
if (phase_count != pvreg->pmic_phase_count) {
rc = set_pmic_gang_phases(phase_count);
rc = set_pmic_gang_phases(pvreg, phase_count);
if (rc < 0) {
dev_err(&from->rdev->dev,
"%s failed set phase %d rc = %d\n",
@@ -577,32 +587,6 @@ static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
return rc;
}
static int __devinit pvreg_init(struct platform_device *pdev)
{
struct pmic_gang_vreg *pvreg;
pvreg = devm_kzalloc(&pdev->dev,
sizeof(struct pmic_gang_vreg), GFP_KERNEL);
if (!pvreg) {
pr_err("kzalloc failed.\n");
return -ENOMEM;
}
pvreg->name = "pmic_gang";
pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
pvreg->pmic_phase_count = 1;
pvreg->retention_enabled = true;
pvreg->pmic_min_uV_for_retention = INT_MAX;
mutex_init(&pvreg->krait_power_vregs_lock);
INIT_LIST_HEAD(&pvreg->krait_power_vregs);
the_gang = pvreg;
pr_debug("name=%s inited\n", pvreg->name);
return 0;
}
static int krait_power_get_voltage(struct regulator_dev *rdev)
{
struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -925,24 +909,6 @@ static int __devinit krait_power_probe(struct platform_device *pdev)
int ldo_delta_uV;
int cpu_num;
/* Initialize the pmic gang if it hasn't been initialized already */
if (the_gang == NULL) {
rc = pvreg_init(pdev);
if (rc < 0) {
dev_err(&pdev->dev,
"failed to init pmic gang rc = %d\n", rc);
return rc;
}
/* global initializtion */
glb_init(pdev);
}
if (dent == NULL) {
dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
debugfs_create_file("retention_uV",
0644, dent, the_gang, &retention_fops);
}
if (pdev->dev.of_node) {
/* Get init_data from device tree. */
init_data = of_get_regulator_init_data(&pdev->dev,
@@ -1139,14 +1105,93 @@ static struct platform_driver krait_power_driver = {
},
};
static struct of_device_id krait_pdn_match_table[] = {
{ .compatible = "qcom,krait-pdn", },
{}
};
static int __devinit krait_pdn_probe(struct platform_device *pdev)
{
int rc;
bool use_phase_switching = false;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct pmic_gang_vreg *pvreg;
if (!dev->of_node) {
dev_err(dev, "device tree information missing\n");
return -ENODEV;
}
use_phase_switching = of_property_read_bool(node,
"qcom,use-phase-switching");
pvreg = devm_kzalloc(&pdev->dev,
sizeof(struct pmic_gang_vreg), GFP_KERNEL);
if (!pvreg) {
pr_err("kzalloc failed.\n");
return 0;
}
pvreg->name = "pmic_gang";
pvreg->pmic_vmax_uV = PMIC_VOLTAGE_MIN;
pvreg->pmic_phase_count = -EINVAL;
pvreg->retention_enabled = true;
pvreg->pmic_min_uV_for_retention = INT_MAX;
pvreg->use_phase_switching = use_phase_switching;
mutex_init(&pvreg->krait_power_vregs_lock);
INIT_LIST_HEAD(&pvreg->krait_power_vregs);
the_gang = pvreg;
pr_debug("name=%s inited\n", pvreg->name);
/* global initializtion */
glb_init(pdev);
rc = of_platform_populate(node, NULL, NULL, dev);
if (rc) {
dev_err(dev, "failed to add child nodes, rc=%d\n", rc);
return rc;
}
dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
debugfs_create_file("retention_uV",
0644, dent, the_gang, &retention_fops);
return 0;
}
static int __devexit krait_pdn_remove(struct platform_device *pdev)
{
the_gang = NULL;
debugfs_remove_recursive(dent);
return 0;
}
static struct platform_driver krait_pdn_driver = {
.probe = krait_pdn_probe,
.remove = __devexit_p(krait_pdn_remove),
.driver = {
.name = KRAIT_PDN_DRIVER_NAME,
.of_match_table = krait_pdn_match_table,
.owner = THIS_MODULE,
},
};
int __init krait_power_init(void)
{
return platform_driver_register(&krait_power_driver);
int rc = platform_driver_register(&krait_power_driver);
if (rc) {
pr_err("failed to add %s driver rc = %d\n",
KRAIT_REGULATOR_DRIVER_NAME, rc);
return rc;
}
return platform_driver_register(&krait_pdn_driver);
}
static void __exit krait_power_exit(void)
{
platform_driver_unregister(&krait_power_driver);
platform_driver_unregister(&krait_pdn_driver);
}
module_exit(krait_power_exit);
+2 -1
View File
@@ -13,7 +13,8 @@
#ifndef __KRAIT_REGULATOR_H__
#define __KRAIT_REGULATOR_H__
#define KRAIT_REGULATOR_DRIVER_NAME "krait-power-regulator"
#define KRAIT_REGULATOR_DRIVER_NAME "krait-power-regulator"
#define KRAIT_PDN_DRIVER_NAME "krait-pdn"
/**
* krait_power_init - driver initialization function