From 8c65c1948348acc6738d0609a59d852f23fd2fa9 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 16 Aug 2021 11:06:15 +0800 Subject: [PATCH] soc: rockchip: io-domain: rv1126 use separated notify RV1126 set 3.3V before regulator disable. Do a fix to rockchip io-domain, follow this orders: * system running state -> io-domain vsel to 3.3V (actually is done by event-disable) -> regulator_enable -> vsel change according to regulator voltage * system running state -> regulator_disable -> io-domain vsel to 3.3V The bug only instance on RV1126, and tested on RV1126 EVB DDR3 V10. Change-Id: Ic9d6b05d07b050c392e415786cf6390cc1c5aa9e Signed-off-by: Jianqun Xu --- drivers/soc/rockchip/io-domain.c | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c index 5b3770589d67..c609004dd8d9 100644 --- a/drivers/soc/rockchip/io-domain.c +++ b/drivers/soc/rockchip/io-domain.c @@ -610,6 +610,55 @@ static const struct of_device_id rockchip_iodomain_match[] = { }; MODULE_DEVICE_TABLE(of, rockchip_iodomain_match); +static int rv1126_iodomain_notify(struct notifier_block *nb, + unsigned long event, + void *data) +{ + struct rockchip_iodomain_supply *supply = + container_of(nb, struct rockchip_iodomain_supply, nb); + int uV; + int ret; + + if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) { + struct pre_voltage_change_data *pvc_data = data; + + uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV); + } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE | + REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) { + uV = (unsigned long)data; + } else if (event & REGULATOR_EVENT_DISABLE) { + uV = MAX_VOLTAGE_3_3; + } else if (event & REGULATOR_EVENT_ENABLE) { + if (!data) + return NOTIFY_BAD; + + uV = (unsigned long)data; + } else { + return NOTIFY_OK; + } + + if (uV <= 0) { + dev_err(supply->iod->dev, "Voltage invalid: %d\n", uV); + return NOTIFY_BAD; + } + + dev_dbg(supply->iod->dev, "Setting to %d\n", uV); + + if (uV > MAX_VOLTAGE_3_3) { + dev_err(supply->iod->dev, "Voltage too high: %d\n", uV); + + if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) + return NOTIFY_BAD; + } + + ret = supply->iod->write(supply, uV); + if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) + return NOTIFY_BAD; + + dev_dbg(supply->iod->dev, "Setting to %d done\n", uV); + return NOTIFY_OK; +} + static int rockchip_iodomain_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -695,6 +744,8 @@ static int rockchip_iodomain_probe(struct platform_device *pdev) supply->iod = iod; supply->reg = reg; supply->nb.notifier_call = rockchip_iodomain_notify; + if (IS_ENABLED(CONFIG_CPU_RV1126)) + supply->nb.notifier_call = rv1126_iodomain_notify; ret = iod->write(supply, uV); if (ret) {