From 69a034d29725b7805e1bd7ec8b9b124f32bd5bcb Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 16 Aug 2021 11:06:15 +0800 Subject: [PATCH] power/avs: 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/power/avs/rockchip-io-domain.c | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/drivers/power/avs/rockchip-io-domain.c b/drivers/power/avs/rockchip-io-domain.c index d13514dc4647..9b9bcd5b7208 100644 --- a/drivers/power/avs/rockchip-io-domain.c +++ b/drivers/power/avs/rockchip-io-domain.c @@ -743,6 +743,55 @@ static void rockchip_iodomain_dump(const struct platform_device *pdev, } } +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; @@ -831,6 +880,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) {