stm32-vrefbuf.c (7641B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) STMicroelectronics 2017 4 * 5 * Author: Fabrice Gasnier <fabrice.gasnier@st.com> 6 */ 7 8#include <linux/bitfield.h> 9#include <linux/clk.h> 10#include <linux/io.h> 11#include <linux/iopoll.h> 12#include <linux/module.h> 13#include <linux/of_device.h> 14#include <linux/platform_device.h> 15#include <linux/regulator/driver.h> 16#include <linux/regulator/of_regulator.h> 17#include <linux/pm_runtime.h> 18 19/* STM32 VREFBUF registers */ 20#define STM32_VREFBUF_CSR 0x00 21 22/* STM32 VREFBUF CSR bitfields */ 23#define STM32_VRS GENMASK(6, 4) 24#define STM32_VRR BIT(3) 25#define STM32_HIZ BIT(1) 26#define STM32_ENVR BIT(0) 27 28#define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10 29 30struct stm32_vrefbuf { 31 void __iomem *base; 32 struct clk *clk; 33 struct device *dev; 34}; 35 36static const unsigned int stm32_vrefbuf_voltages[] = { 37 /* Matches resp. VRS = 000b, 001b, 010b, 011b */ 38 2500000, 2048000, 1800000, 1500000, 39}; 40 41static int stm32_vrefbuf_enable(struct regulator_dev *rdev) 42{ 43 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 44 u32 val; 45 int ret; 46 47 ret = pm_runtime_resume_and_get(priv->dev); 48 if (ret < 0) 49 return ret; 50 51 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 52 val = (val & ~STM32_HIZ) | STM32_ENVR; 53 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 54 55 /* 56 * Vrefbuf startup time depends on external capacitor: wait here for 57 * VRR to be set. That means output has reached expected value. 58 * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as 59 * arbitrary timeout. 60 */ 61 ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val, 62 val & STM32_VRR, 650, 10000); 63 if (ret) { 64 dev_err(&rdev->dev, "stm32 vrefbuf timed out!\n"); 65 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 66 val = (val & ~STM32_ENVR) | STM32_HIZ; 67 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 68 } 69 70 pm_runtime_mark_last_busy(priv->dev); 71 pm_runtime_put_autosuspend(priv->dev); 72 73 return ret; 74} 75 76static int stm32_vrefbuf_disable(struct regulator_dev *rdev) 77{ 78 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 79 u32 val; 80 int ret; 81 82 ret = pm_runtime_resume_and_get(priv->dev); 83 if (ret < 0) 84 return ret; 85 86 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 87 val &= ~STM32_ENVR; 88 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 89 90 pm_runtime_mark_last_busy(priv->dev); 91 pm_runtime_put_autosuspend(priv->dev); 92 93 return 0; 94} 95 96static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev) 97{ 98 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 99 int ret; 100 101 ret = pm_runtime_resume_and_get(priv->dev); 102 if (ret < 0) 103 return ret; 104 105 ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR; 106 107 pm_runtime_mark_last_busy(priv->dev); 108 pm_runtime_put_autosuspend(priv->dev); 109 110 return ret; 111} 112 113static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev, 114 unsigned sel) 115{ 116 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 117 u32 val; 118 int ret; 119 120 ret = pm_runtime_resume_and_get(priv->dev); 121 if (ret < 0) 122 return ret; 123 124 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 125 val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel); 126 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 127 128 pm_runtime_mark_last_busy(priv->dev); 129 pm_runtime_put_autosuspend(priv->dev); 130 131 return 0; 132} 133 134static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev) 135{ 136 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 137 u32 val; 138 int ret; 139 140 ret = pm_runtime_resume_and_get(priv->dev); 141 if (ret < 0) 142 return ret; 143 144 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 145 ret = FIELD_GET(STM32_VRS, val); 146 147 pm_runtime_mark_last_busy(priv->dev); 148 pm_runtime_put_autosuspend(priv->dev); 149 150 return ret; 151} 152 153static const struct regulator_ops stm32_vrefbuf_volt_ops = { 154 .enable = stm32_vrefbuf_enable, 155 .disable = stm32_vrefbuf_disable, 156 .is_enabled = stm32_vrefbuf_is_enabled, 157 .get_voltage_sel = stm32_vrefbuf_get_voltage_sel, 158 .set_voltage_sel = stm32_vrefbuf_set_voltage_sel, 159 .list_voltage = regulator_list_voltage_table, 160}; 161 162static const struct regulator_desc stm32_vrefbuf_regu = { 163 .name = "vref", 164 .supply_name = "vdda", 165 .volt_table = stm32_vrefbuf_voltages, 166 .n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages), 167 .ops = &stm32_vrefbuf_volt_ops, 168 .off_on_delay = 1000, 169 .type = REGULATOR_VOLTAGE, 170 .owner = THIS_MODULE, 171}; 172 173static int stm32_vrefbuf_probe(struct platform_device *pdev) 174{ 175 struct stm32_vrefbuf *priv; 176 struct regulator_config config = { }; 177 struct regulator_dev *rdev; 178 int ret; 179 180 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 181 if (!priv) 182 return -ENOMEM; 183 priv->dev = &pdev->dev; 184 185 priv->base = devm_platform_ioremap_resource(pdev, 0); 186 if (IS_ERR(priv->base)) 187 return PTR_ERR(priv->base); 188 189 priv->clk = devm_clk_get(&pdev->dev, NULL); 190 if (IS_ERR(priv->clk)) 191 return PTR_ERR(priv->clk); 192 193 pm_runtime_get_noresume(&pdev->dev); 194 pm_runtime_set_active(&pdev->dev); 195 pm_runtime_set_autosuspend_delay(&pdev->dev, 196 STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS); 197 pm_runtime_use_autosuspend(&pdev->dev); 198 pm_runtime_enable(&pdev->dev); 199 200 ret = clk_prepare_enable(priv->clk); 201 if (ret) { 202 dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret); 203 goto err_pm_stop; 204 } 205 206 config.dev = &pdev->dev; 207 config.driver_data = priv; 208 config.of_node = pdev->dev.of_node; 209 config.init_data = of_get_regulator_init_data(&pdev->dev, 210 pdev->dev.of_node, 211 &stm32_vrefbuf_regu); 212 213 rdev = regulator_register(&stm32_vrefbuf_regu, &config); 214 if (IS_ERR(rdev)) { 215 ret = PTR_ERR(rdev); 216 dev_err(&pdev->dev, "register failed with error %d\n", ret); 217 goto err_clk_dis; 218 } 219 platform_set_drvdata(pdev, rdev); 220 221 pm_runtime_mark_last_busy(&pdev->dev); 222 pm_runtime_put_autosuspend(&pdev->dev); 223 224 return 0; 225 226err_clk_dis: 227 clk_disable_unprepare(priv->clk); 228err_pm_stop: 229 pm_runtime_disable(&pdev->dev); 230 pm_runtime_set_suspended(&pdev->dev); 231 pm_runtime_put_noidle(&pdev->dev); 232 233 return ret; 234} 235 236static int stm32_vrefbuf_remove(struct platform_device *pdev) 237{ 238 struct regulator_dev *rdev = platform_get_drvdata(pdev); 239 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 240 241 pm_runtime_get_sync(&pdev->dev); 242 regulator_unregister(rdev); 243 clk_disable_unprepare(priv->clk); 244 pm_runtime_disable(&pdev->dev); 245 pm_runtime_set_suspended(&pdev->dev); 246 pm_runtime_put_noidle(&pdev->dev); 247 248 return 0; 249}; 250 251static int __maybe_unused stm32_vrefbuf_runtime_suspend(struct device *dev) 252{ 253 struct regulator_dev *rdev = dev_get_drvdata(dev); 254 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 255 256 clk_disable_unprepare(priv->clk); 257 258 return 0; 259} 260 261static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev) 262{ 263 struct regulator_dev *rdev = dev_get_drvdata(dev); 264 struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev); 265 266 return clk_prepare_enable(priv->clk); 267} 268 269static const struct dev_pm_ops stm32_vrefbuf_pm_ops = { 270 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 271 pm_runtime_force_resume) 272 SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend, 273 stm32_vrefbuf_runtime_resume, 274 NULL) 275}; 276 277static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = { 278 { .compatible = "st,stm32-vrefbuf", }, 279 {}, 280}; 281MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match); 282 283static struct platform_driver stm32_vrefbuf_driver = { 284 .probe = stm32_vrefbuf_probe, 285 .remove = stm32_vrefbuf_remove, 286 .driver = { 287 .name = "stm32-vrefbuf", 288 .of_match_table = of_match_ptr(stm32_vrefbuf_of_match), 289 .pm = &stm32_vrefbuf_pm_ops, 290 }, 291}; 292module_platform_driver(stm32_vrefbuf_driver); 293 294MODULE_LICENSE("GPL v2"); 295MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); 296MODULE_DESCRIPTION("STMicroelectronics STM32 VREFBUF driver"); 297MODULE_ALIAS("platform:stm32-vrefbuf");