Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.2-rc2 192 lines 4.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * This file is part of STM32 DAC driver 4 * 5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>. 7 * 8 */ 9 10#include <linux/clk.h> 11#include <linux/delay.h> 12#include <linux/module.h> 13#include <linux/of_platform.h> 14#include <linux/regulator/consumer.h> 15#include <linux/reset.h> 16 17#include "stm32-dac-core.h" 18 19/** 20 * struct stm32_dac_priv - stm32 DAC core private data 21 * @pclk: peripheral clock common for all DACs 22 * @rst: peripheral reset control 23 * @vref: regulator reference 24 * @common: Common data for all DAC instances 25 */ 26struct stm32_dac_priv { 27 struct clk *pclk; 28 struct reset_control *rst; 29 struct regulator *vref; 30 struct stm32_dac_common common; 31}; 32 33/** 34 * struct stm32_dac_cfg - DAC configuration 35 * @has_hfsel: DAC has high frequency control 36 */ 37struct stm32_dac_cfg { 38 bool has_hfsel; 39}; 40 41static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com) 42{ 43 return container_of(com, struct stm32_dac_priv, common); 44} 45 46static const struct regmap_config stm32_dac_regmap_cfg = { 47 .reg_bits = 32, 48 .val_bits = 32, 49 .reg_stride = sizeof(u32), 50 .max_register = 0x3fc, 51}; 52 53static int stm32_dac_probe(struct platform_device *pdev) 54{ 55 struct device *dev = &pdev->dev; 56 const struct stm32_dac_cfg *cfg; 57 struct stm32_dac_priv *priv; 58 struct regmap *regmap; 59 struct resource *res; 60 void __iomem *mmio; 61 int ret; 62 63 if (!dev->of_node) 64 return -ENODEV; 65 66 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 67 if (!priv) 68 return -ENOMEM; 69 cfg = (const struct stm32_dac_cfg *) 70 of_match_device(dev->driver->of_match_table, dev)->data; 71 72 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 73 mmio = devm_ioremap_resource(dev, res); 74 if (IS_ERR(mmio)) 75 return PTR_ERR(mmio); 76 77 regmap = devm_regmap_init_mmio(dev, mmio, &stm32_dac_regmap_cfg); 78 if (IS_ERR(regmap)) 79 return PTR_ERR(regmap); 80 priv->common.regmap = regmap; 81 82 priv->vref = devm_regulator_get(dev, "vref"); 83 if (IS_ERR(priv->vref)) { 84 ret = PTR_ERR(priv->vref); 85 dev_err(dev, "vref get failed, %d\n", ret); 86 return ret; 87 } 88 89 ret = regulator_enable(priv->vref); 90 if (ret < 0) { 91 dev_err(dev, "vref enable failed\n"); 92 return ret; 93 } 94 95 ret = regulator_get_voltage(priv->vref); 96 if (ret < 0) { 97 dev_err(dev, "vref get voltage failed, %d\n", ret); 98 goto err_vref; 99 } 100 priv->common.vref_mv = ret / 1000; 101 dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); 102 103 priv->pclk = devm_clk_get(dev, "pclk"); 104 if (IS_ERR(priv->pclk)) { 105 ret = PTR_ERR(priv->pclk); 106 dev_err(dev, "pclk get failed\n"); 107 goto err_vref; 108 } 109 110 ret = clk_prepare_enable(priv->pclk); 111 if (ret < 0) { 112 dev_err(dev, "pclk enable failed\n"); 113 goto err_vref; 114 } 115 116 priv->rst = devm_reset_control_get_exclusive(dev, NULL); 117 if (!IS_ERR(priv->rst)) { 118 reset_control_assert(priv->rst); 119 udelay(2); 120 reset_control_deassert(priv->rst); 121 } 122 123 if (cfg && cfg->has_hfsel) { 124 /* When clock speed is higher than 80MHz, set HFSEL */ 125 priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL); 126 ret = regmap_update_bits(regmap, STM32_DAC_CR, 127 STM32H7_DAC_CR_HFSEL, 128 priv->common.hfsel ? 129 STM32H7_DAC_CR_HFSEL : 0); 130 if (ret) 131 goto err_pclk; 132 } 133 134 platform_set_drvdata(pdev, &priv->common); 135 136 ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev); 137 if (ret < 0) { 138 dev_err(dev, "failed to populate DT children\n"); 139 goto err_pclk; 140 } 141 142 return 0; 143 144err_pclk: 145 clk_disable_unprepare(priv->pclk); 146err_vref: 147 regulator_disable(priv->vref); 148 149 return ret; 150} 151 152static int stm32_dac_remove(struct platform_device *pdev) 153{ 154 struct stm32_dac_common *common = platform_get_drvdata(pdev); 155 struct stm32_dac_priv *priv = to_stm32_dac_priv(common); 156 157 of_platform_depopulate(&pdev->dev); 158 clk_disable_unprepare(priv->pclk); 159 regulator_disable(priv->vref); 160 161 return 0; 162} 163 164static const struct stm32_dac_cfg stm32h7_dac_cfg = { 165 .has_hfsel = true, 166}; 167 168static const struct of_device_id stm32_dac_of_match[] = { 169 { 170 .compatible = "st,stm32f4-dac-core", 171 }, { 172 .compatible = "st,stm32h7-dac-core", 173 .data = (void *)&stm32h7_dac_cfg, 174 }, 175 {}, 176}; 177MODULE_DEVICE_TABLE(of, stm32_dac_of_match); 178 179static struct platform_driver stm32_dac_driver = { 180 .probe = stm32_dac_probe, 181 .remove = stm32_dac_remove, 182 .driver = { 183 .name = "stm32-dac-core", 184 .of_match_table = stm32_dac_of_match, 185 }, 186}; 187module_platform_driver(stm32_dac_driver); 188 189MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); 190MODULE_DESCRIPTION("STMicroelectronics STM32 DAC core driver"); 191MODULE_LICENSE("GPL v2"); 192MODULE_ALIAS("platform:stm32-dac-core");