|
@@ -645,7 +645,9 @@ static int rpm_reg_set(struct qcom_rpm_reg *vreg,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
|
|
|
|
|
|
+static int rpm_reg_of_parse_freq(struct device *dev,
|
|
|
|
+ struct device_node *node,
|
|
|
|
+ struct qcom_rpm_reg *vreg)
|
|
{
|
|
{
|
|
static const int freq_table[] = {
|
|
static const int freq_table[] = {
|
|
19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
|
|
19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
|
|
@@ -659,7 +661,7 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
|
|
int i;
|
|
int i;
|
|
|
|
|
|
key = "qcom,switch-mode-frequency";
|
|
key = "qcom,switch-mode-frequency";
|
|
- ret = of_property_read_u32(dev->of_node, key, &freq);
|
|
|
|
|
|
+ ret = of_property_read_u32(node, key, &freq);
|
|
if (ret) {
|
|
if (ret) {
|
|
dev_err(dev, "regulator requires %s property\n", key);
|
|
dev_err(dev, "regulator requires %s property\n", key);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -676,84 +678,40 @@ static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
-static int rpm_reg_probe(struct platform_device *pdev)
|
|
|
|
|
|
+static int rpm_reg_of_parse(struct device_node *node,
|
|
|
|
+ const struct regulator_desc *desc,
|
|
|
|
+ struct regulator_config *config)
|
|
{
|
|
{
|
|
- struct regulator_init_data *initdata;
|
|
|
|
- const struct qcom_rpm_reg *template;
|
|
|
|
- const struct of_device_id *match;
|
|
|
|
- struct regulator_config config = { };
|
|
|
|
- struct regulator_dev *rdev;
|
|
|
|
- struct qcom_rpm_reg *vreg;
|
|
|
|
|
|
+ struct qcom_rpm_reg *vreg = config->driver_data;
|
|
|
|
+ struct device *dev = config->dev;
|
|
const char *key;
|
|
const char *key;
|
|
u32 force_mode;
|
|
u32 force_mode;
|
|
bool pwm;
|
|
bool pwm;
|
|
u32 val;
|
|
u32 val;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- match = of_match_device(rpm_of_match, &pdev->dev);
|
|
|
|
- template = match->data;
|
|
|
|
-
|
|
|
|
- vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
|
|
|
|
- if (!vreg) {
|
|
|
|
- dev_err(&pdev->dev, "failed to allocate vreg\n");
|
|
|
|
- return -ENOMEM;
|
|
|
|
- }
|
|
|
|
- memcpy(vreg, template, sizeof(*vreg));
|
|
|
|
- mutex_init(&vreg->lock);
|
|
|
|
- vreg->dev = &pdev->dev;
|
|
|
|
- vreg->desc.id = -1;
|
|
|
|
- vreg->desc.owner = THIS_MODULE;
|
|
|
|
- vreg->desc.type = REGULATOR_VOLTAGE;
|
|
|
|
- vreg->desc.name = pdev->dev.of_node->name;
|
|
|
|
- vreg->desc.supply_name = "vin";
|
|
|
|
-
|
|
|
|
- vreg->rpm = dev_get_drvdata(pdev->dev.parent);
|
|
|
|
- if (!vreg->rpm) {
|
|
|
|
- dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
|
|
|
|
- &vreg->desc);
|
|
|
|
- if (!initdata)
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
- key = "reg";
|
|
|
|
- ret = of_property_read_u32(pdev->dev.of_node, key, &val);
|
|
|
|
- if (ret) {
|
|
|
|
- dev_err(&pdev->dev, "failed to read %s\n", key);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
- vreg->resource = val;
|
|
|
|
-
|
|
|
|
- if ((vreg->parts->uV.mask || vreg->parts->mV.mask) &&
|
|
|
|
- (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) {
|
|
|
|
- dev_err(&pdev->dev, "no voltage specified for regulator\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
key = "bias-pull-down";
|
|
key = "bias-pull-down";
|
|
- if (of_property_read_bool(pdev->dev.of_node, key)) {
|
|
|
|
|
|
+ if (of_property_read_bool(node, key)) {
|
|
ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
|
|
ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
|
|
if (ret) {
|
|
if (ret) {
|
|
- dev_err(&pdev->dev, "%s is invalid", key);
|
|
|
|
|
|
+ dev_err(dev, "%s is invalid", key);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (vreg->parts->freq.mask) {
|
|
if (vreg->parts->freq.mask) {
|
|
- ret = rpm_reg_of_parse_freq(&pdev->dev, vreg);
|
|
|
|
|
|
+ ret = rpm_reg_of_parse_freq(dev, node, vreg);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
if (vreg->parts->pm.mask) {
|
|
if (vreg->parts->pm.mask) {
|
|
key = "qcom,power-mode-hysteretic";
|
|
key = "qcom,power-mode-hysteretic";
|
|
- pwm = !of_property_read_bool(pdev->dev.of_node, key);
|
|
|
|
|
|
+ pwm = !of_property_read_bool(node, key);
|
|
|
|
|
|
ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
|
|
ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
|
|
if (ret) {
|
|
if (ret) {
|
|
- dev_err(&pdev->dev, "failed to set power mode\n");
|
|
|
|
|
|
+ dev_err(dev, "failed to set power mode\n");
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -762,11 +720,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
|
force_mode = -1;
|
|
force_mode = -1;
|
|
|
|
|
|
key = "qcom,force-mode";
|
|
key = "qcom,force-mode";
|
|
- ret = of_property_read_u32(pdev->dev.of_node, key, &val);
|
|
|
|
|
|
+ ret = of_property_read_u32(node, key, &val);
|
|
if (ret == -EINVAL) {
|
|
if (ret == -EINVAL) {
|
|
val = QCOM_RPM_FORCE_MODE_NONE;
|
|
val = QCOM_RPM_FORCE_MODE_NONE;
|
|
} else if (ret < 0) {
|
|
} else if (ret < 0) {
|
|
- dev_err(&pdev->dev, "failed to read %s\n", key);
|
|
|
|
|
|
+ dev_err(dev, "failed to read %s\n", key);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -801,21 +759,84 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
|
}
|
|
}
|
|
|
|
|
|
if (force_mode == -1) {
|
|
if (force_mode == -1) {
|
|
- dev_err(&pdev->dev, "invalid force mode\n");
|
|
|
|
|
|
+ dev_err(dev, "invalid force mode\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
|
|
ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
|
|
if (ret) {
|
|
if (ret) {
|
|
- dev_err(&pdev->dev, "failed to set force mode\n");
|
|
|
|
|
|
+ dev_err(dev, "failed to set force mode\n");
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int rpm_reg_probe(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ struct regulator_init_data *initdata;
|
|
|
|
+ const struct qcom_rpm_reg *template;
|
|
|
|
+ const struct of_device_id *match;
|
|
|
|
+ struct regulator_config config = { };
|
|
|
|
+ struct regulator_dev *rdev;
|
|
|
|
+ struct qcom_rpm_reg *vreg;
|
|
|
|
+ const char *key;
|
|
|
|
+ u32 val;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ match = of_match_device(rpm_of_match, &pdev->dev);
|
|
|
|
+ template = match->data;
|
|
|
|
+
|
|
|
|
+ vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
|
|
|
|
+ if (!vreg) {
|
|
|
|
+ dev_err(&pdev->dev, "failed to allocate vreg\n");
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ memcpy(vreg, template, sizeof(*vreg));
|
|
|
|
+ mutex_init(&vreg->lock);
|
|
|
|
+ vreg->dev = &pdev->dev;
|
|
|
|
+ vreg->desc.id = -1;
|
|
|
|
+ vreg->desc.owner = THIS_MODULE;
|
|
|
|
+ vreg->desc.type = REGULATOR_VOLTAGE;
|
|
|
|
+ vreg->desc.name = pdev->dev.of_node->name;
|
|
|
|
+ vreg->desc.supply_name = "vin";
|
|
|
|
+
|
|
|
|
+ vreg->rpm = dev_get_drvdata(pdev->dev.parent);
|
|
|
|
+ if (!vreg->rpm) {
|
|
|
|
+ dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
|
|
|
|
+ &vreg->desc);
|
|
|
|
+ if (!initdata)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ key = "reg";
|
|
|
|
+ ret = of_property_read_u32(pdev->dev.of_node, key, &val);
|
|
|
|
+ if (ret) {
|
|
|
|
+ dev_err(&pdev->dev, "failed to read %s\n", key);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ vreg->resource = val;
|
|
|
|
+
|
|
|
|
+ if ((vreg->parts->uV.mask || vreg->parts->mV.mask) &&
|
|
|
|
+ (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) {
|
|
|
|
+ dev_err(&pdev->dev, "no voltage specified for regulator\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
config.dev = &pdev->dev;
|
|
config.dev = &pdev->dev;
|
|
config.init_data = initdata;
|
|
config.init_data = initdata;
|
|
config.driver_data = vreg;
|
|
config.driver_data = vreg;
|
|
config.of_node = pdev->dev.of_node;
|
|
config.of_node = pdev->dev.of_node;
|
|
|
|
+
|
|
|
|
+ ret = rpm_reg_of_parse(pdev->dev.of_node, &vreg->desc, &config);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
|
|
rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
|
|
if (IS_ERR(rdev)) {
|
|
if (IS_ERR(rdev)) {
|
|
dev_err(&pdev->dev, "can't register regulator\n");
|
|
dev_err(&pdev->dev, "can't register regulator\n");
|