mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "clk: qcom: gdsc-regulator: Remove polling logic when disabling GDSC HW CTL"
This commit is contained in:
commit
0c4596a68b
1 changed files with 157 additions and 158 deletions
|
|
@ -500,17 +500,11 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
|||
/*
|
||||
* There may be a race with internal HW trigger signal,
|
||||
* that will result in GDSC going through a power down and
|
||||
* up cycle. If we poll too early, status bit will
|
||||
* indicate 'on' before the GDSC can finish the power cycle.
|
||||
* Account for this case by waiting 1us before polling.
|
||||
* up cycle. Account for this case by waiting 1us before
|
||||
* proceeding.
|
||||
*/
|
||||
gdsc_mb(sc);
|
||||
udelay(1);
|
||||
|
||||
ret = poll_gdsc_status(sc, ENABLED);
|
||||
if (ret)
|
||||
dev_err(&rdev->dev, "%s set_mode timed out: 0x%x\n",
|
||||
sc->rdesc.name, regval);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
|
@ -542,129 +536,144 @@ static const struct regmap_config gdsc_regmap_config = {
|
|||
.fast_io = true,
|
||||
};
|
||||
|
||||
static int gdsc_probe(struct platform_device *pdev)
|
||||
static int gdsc_parse_dt_data(struct gdsc *sc, struct device *dev,
|
||||
struct regulator_init_data **init_data)
|
||||
{
|
||||
static atomic_t gdsc_count = ATOMIC_INIT(-1);
|
||||
struct regulator_config reg_config = {};
|
||||
struct regulator_init_data *init_data;
|
||||
struct resource *res;
|
||||
struct gdsc *sc;
|
||||
uint32_t regval, clk_dis_wait_val = 0;
|
||||
bool support_hw_trigger;
|
||||
int i, ret;
|
||||
u32 timeout;
|
||||
int ret;
|
||||
|
||||
sc = devm_kzalloc(&pdev->dev, sizeof(struct gdsc), GFP_KERNEL);
|
||||
if (sc == NULL)
|
||||
*init_data = of_get_regulator_init_data(dev, dev->of_node, &sc->rdesc);
|
||||
if (*init_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
|
||||
&sc->rdesc);
|
||||
if (init_data == NULL)
|
||||
return -ENOMEM;
|
||||
if (of_get_property(dev->of_node, "parent-supply", NULL))
|
||||
(*init_data)->supply_regulator = "parent";
|
||||
|
||||
if (of_get_property(pdev->dev.of_node, "parent-supply", NULL))
|
||||
init_data->supply_regulator = "parent";
|
||||
|
||||
ret = of_property_read_string(pdev->dev.of_node, "regulator-name",
|
||||
&sc->rdesc.name);
|
||||
ret = of_property_read_string(dev->of_node, "regulator-name",
|
||||
&sc->rdesc.name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "Failed to get resources\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->gdscr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (sc->gdscr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sc->regmap = devm_regmap_init_mmio(&pdev->dev, sc->gdscr,
|
||||
&gdsc_regmap_config);
|
||||
if (!sc->regmap) {
|
||||
dev_err(&pdev->dev, "Couldn't get regmap\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "domain-addr", NULL)) {
|
||||
sc->domain_addr = syscon_regmap_lookup_by_phandle
|
||||
(pdev->dev.of_node, "domain-addr");
|
||||
if (of_find_property(dev->of_node, "domain-addr", NULL)) {
|
||||
sc->domain_addr = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"domain-addr");
|
||||
if (IS_ERR(sc->domain_addr))
|
||||
return -ENODEV;
|
||||
return PTR_ERR(sc->domain_addr);
|
||||
}
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "sw-reset", NULL)) {
|
||||
sc->sw_reset = syscon_regmap_lookup_by_phandle
|
||||
(pdev->dev.of_node, "sw-reset");
|
||||
if (of_find_property(dev->of_node, "sw-reset", NULL)) {
|
||||
sc->sw_reset = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"sw-reset");
|
||||
if (IS_ERR(sc->sw_reset))
|
||||
return -ENODEV;
|
||||
return PTR_ERR(sc->sw_reset);
|
||||
}
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "hw-ctrl-addr", NULL)) {
|
||||
sc->hw_ctrl = syscon_regmap_lookup_by_phandle(
|
||||
pdev->dev.of_node, "hw-ctrl-addr");
|
||||
if (of_find_property(dev->of_node, "hw-ctrl-addr", NULL)) {
|
||||
sc->hw_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"hw-ctrl-addr");
|
||||
if (IS_ERR(sc->hw_ctrl))
|
||||
return -ENODEV;
|
||||
return PTR_ERR(sc->hw_ctrl);
|
||||
}
|
||||
|
||||
sc->gds_timeout = TIMEOUT_US;
|
||||
of_property_read_u32(dev->of_node, "qcom,gds-timeout",
|
||||
&sc->gds_timeout);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "qcom,gds-timeout",
|
||||
&timeout);
|
||||
if (!ret)
|
||||
sc->gds_timeout = timeout;
|
||||
|
||||
sc->clock_count = of_property_count_strings(pdev->dev.of_node,
|
||||
"clock-names");
|
||||
sc->clock_count = of_property_count_strings(dev->of_node,
|
||||
"clock-names");
|
||||
if (sc->clock_count == -EINVAL) {
|
||||
sc->clock_count = 0;
|
||||
} else if (sc->clock_count < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get clock names\n");
|
||||
dev_err(dev, "Failed to get clock names, ret=%d\n",
|
||||
sc->clock_count);
|
||||
return sc->clock_count;
|
||||
}
|
||||
|
||||
sc->root_en = of_property_read_bool(dev->of_node,
|
||||
"qcom,enable-root-clk");
|
||||
sc->force_root_en = of_property_read_bool(dev->of_node,
|
||||
"qcom,force-enable-root-clk");
|
||||
sc->reset_aon = of_property_read_bool(dev->of_node,
|
||||
"qcom,reset-aon-logic");
|
||||
sc->no_status_check_on_disable = of_property_read_bool(dev->of_node,
|
||||
"qcom,no-status-check-on-disable");
|
||||
sc->retain_ff_enable = of_property_read_bool(dev->of_node,
|
||||
"qcom,retain-regs");
|
||||
|
||||
sc->toggle_logic = !of_property_read_bool(dev->of_node,
|
||||
"qcom,skip-logic-collapse");
|
||||
if (!sc->toggle_logic) {
|
||||
sc->reset_count = of_property_count_strings(dev->of_node,
|
||||
"reset-names");
|
||||
if (sc->reset_count == -EINVAL) {
|
||||
sc->reset_count = 0;
|
||||
} else if (sc->reset_count < 0) {
|
||||
dev_err(dev, "Failed to get reset clock names\n");
|
||||
return sc->reset_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_find_property(dev->of_node, "qcom,support-hw-trigger", NULL)) {
|
||||
(*init_data)->constraints.valid_ops_mask |=
|
||||
REGULATOR_CHANGE_MODE;
|
||||
(*init_data)->constraints.valid_modes_mask |=
|
||||
REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdsc_get_resources(struct gdsc *sc, struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
int ret, i;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(dev, "Failed to get address resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->clocks = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct clk *) * sc->clock_count, GFP_KERNEL);
|
||||
if (!sc->clocks)
|
||||
sc->gdscr = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (sc->gdscr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sc->root_clk_idx = -1;
|
||||
sc->regmap = devm_regmap_init_mmio(dev, sc->gdscr, &gdsc_regmap_config);
|
||||
if (!sc->regmap) {
|
||||
dev_err(dev, "Couldn't get regmap\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->root_en = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,enable-root-clk");
|
||||
|
||||
sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,force-enable-root-clk");
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "vdd_parent-supply", NULL)) {
|
||||
sc->parent_regulator = devm_regulator_get(&pdev->dev,
|
||||
"vdd_parent");
|
||||
if (of_find_property(dev->of_node, "vdd_parent-supply", NULL)) {
|
||||
sc->parent_regulator = devm_regulator_get(dev, "vdd_parent");
|
||||
if (IS_ERR(sc->parent_regulator)) {
|
||||
ret = PTR_ERR(sc->parent_regulator);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev,
|
||||
"Unable to get vdd_parent regulator, err: %d\n",
|
||||
dev_err(dev, "Unable to get vdd_parent regulator, ret=%d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
sc->clocks = devm_kcalloc(dev, sc->clock_count, sizeof(*sc->clocks),
|
||||
GFP_KERNEL);
|
||||
if (sc->clock_count && !sc->clocks)
|
||||
return -ENOMEM;
|
||||
|
||||
sc->root_clk_idx = -1;
|
||||
for (i = 0; i < sc->clock_count; i++) {
|
||||
const char *clock_name;
|
||||
|
||||
of_property_read_string_index(pdev->dev.of_node, "clock-names",
|
||||
i, &clock_name);
|
||||
of_property_read_string_index(dev->of_node, "clock-names", i,
|
||||
&clock_name);
|
||||
|
||||
sc->clocks[i] = devm_clk_get(&pdev->dev, clock_name);
|
||||
sc->clocks[i] = devm_clk_get(dev, clock_name);
|
||||
if (IS_ERR(sc->clocks[i])) {
|
||||
int rc = PTR_ERR(sc->clocks[i]);
|
||||
|
||||
if (rc != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to get %s\n",
|
||||
clock_name);
|
||||
return rc;
|
||||
ret = PTR_ERR(sc->clocks[i]);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get %s, ret=%d\n",
|
||||
clock_name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!strcmp(clock_name, "core_root_clk"))
|
||||
|
|
@ -672,18 +681,57 @@ static int gdsc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if ((sc->root_en || sc->force_root_en) && (sc->root_clk_idx == -1)) {
|
||||
dev_err(&pdev->dev, "Failed to get root clock name\n");
|
||||
dev_err(dev, "Failed to get root clock name\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->reset_aon = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,reset-aon-logic");
|
||||
if (!sc->toggle_logic) {
|
||||
sc->reset_clocks = devm_kcalloc(&pdev->dev, sc->reset_count,
|
||||
sizeof(*sc->reset_clocks),
|
||||
GFP_KERNEL);
|
||||
if (sc->reset_count && !sc->reset_clocks)
|
||||
return -ENOMEM;
|
||||
|
||||
sc->rdesc.id = atomic_inc_return(&gdsc_count);
|
||||
sc->rdesc.ops = &gdsc_ops;
|
||||
sc->rdesc.type = REGULATOR_VOLTAGE;
|
||||
sc->rdesc.owner = THIS_MODULE;
|
||||
platform_set_drvdata(pdev, sc);
|
||||
for (i = 0; i < sc->reset_count; i++) {
|
||||
const char *reset_name;
|
||||
|
||||
of_property_read_string_index(pdev->dev.of_node,
|
||||
"reset-names", i, &reset_name);
|
||||
sc->reset_clocks[i] = devm_reset_control_get(&pdev->dev,
|
||||
reset_name);
|
||||
if (IS_ERR(sc->reset_clocks[i])) {
|
||||
ret = PTR_ERR(sc->reset_clocks[i]);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to get %s, ret=%d\n",
|
||||
reset_name, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdsc_probe(struct platform_device *pdev)
|
||||
{
|
||||
static atomic_t gdsc_count = ATOMIC_INIT(-1);
|
||||
struct regulator_config reg_config = {};
|
||||
struct regulator_init_data *init_data = NULL;
|
||||
struct gdsc *sc;
|
||||
uint32_t regval, clk_dis_wait_val = 0;
|
||||
int ret;
|
||||
|
||||
sc = devm_kzalloc(&pdev->dev, sizeof(*sc), GFP_KERNEL);
|
||||
if (sc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = gdsc_parse_dt_data(sc, &pdev->dev, &init_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gdsc_get_resources(sc, pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Disable HW trigger: collapse/restore occur based on registers writes.
|
||||
|
|
@ -703,54 +751,7 @@ static int gdsc_probe(struct platform_device *pdev)
|
|||
|
||||
regmap_write(sc->regmap, REG_OFFSET, regval);
|
||||
|
||||
sc->no_status_check_on_disable =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,no-status-check-on-disable");
|
||||
sc->retain_ff_enable = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,retain-regs");
|
||||
sc->toggle_logic = !of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,skip-logic-collapse");
|
||||
support_hw_trigger = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,support-hw-trigger");
|
||||
if (support_hw_trigger) {
|
||||
init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
|
||||
init_data->constraints.valid_modes_mask |=
|
||||
REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
|
||||
}
|
||||
|
||||
if (!sc->toggle_logic) {
|
||||
sc->reset_count = of_property_count_strings(pdev->dev.of_node,
|
||||
"reset-names");
|
||||
if (sc->reset_count == -EINVAL) {
|
||||
sc->reset_count = 0;
|
||||
} else if (sc->reset_count < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get reset clock names\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->reset_clocks = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct reset_control *) * sc->reset_count,
|
||||
GFP_KERNEL);
|
||||
if (!sc->reset_clocks)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < sc->reset_count; i++) {
|
||||
const char *reset_name;
|
||||
|
||||
of_property_read_string_index(pdev->dev.of_node,
|
||||
"reset-names", i, &reset_name);
|
||||
sc->reset_clocks[i] = devm_reset_control_get(&pdev->dev,
|
||||
reset_name);
|
||||
if (IS_ERR(sc->reset_clocks[i])) {
|
||||
int rc = PTR_ERR(sc->reset_clocks[i]);
|
||||
|
||||
if (rc != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to get %s\n",
|
||||
reset_name);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
regval &= ~SW_COLLAPSE_MASK;
|
||||
regmap_write(sc->regmap, REG_OFFSET, regval);
|
||||
|
||||
|
|
@ -762,27 +763,26 @@ static int gdsc_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
sc->rdesc.id = atomic_inc_return(&gdsc_count);
|
||||
sc->rdesc.ops = &gdsc_ops;
|
||||
sc->rdesc.type = REGULATOR_VOLTAGE;
|
||||
sc->rdesc.owner = THIS_MODULE;
|
||||
|
||||
reg_config.dev = &pdev->dev;
|
||||
reg_config.init_data = init_data;
|
||||
reg_config.driver_data = sc;
|
||||
reg_config.of_node = pdev->dev.of_node;
|
||||
reg_config.regmap = sc->regmap;
|
||||
|
||||
sc->rdev = regulator_register(&sc->rdesc, ®_config);
|
||||
sc->rdev = devm_regulator_register(&pdev->dev, &sc->rdesc, ®_config);
|
||||
if (IS_ERR(sc->rdev)) {
|
||||
dev_err(&pdev->dev, "regulator_register(\"%s\") failed.\n",
|
||||
sc->rdesc.name);
|
||||
return PTR_ERR(sc->rdev);
|
||||
ret = PTR_ERR(sc->rdev);
|
||||
dev_err(&pdev->dev, "regulator_register(\"%s\") failed, ret=%d\n",
|
||||
sc->rdesc.name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdsc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gdsc *sc = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(sc->rdev);
|
||||
platform_set_drvdata(pdev, sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -794,7 +794,6 @@ static const struct of_device_id gdsc_match_table[] = {
|
|||
|
||||
static struct platform_driver gdsc_driver = {
|
||||
.probe = gdsc_probe,
|
||||
.remove = gdsc_remove,
|
||||
.driver = {
|
||||
.name = "gdsc",
|
||||
.of_match_table = gdsc_match_table,
|
||||
|
|
|
|||
Loading…
Reference in a new issue