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

iio: adc: Add support for STM32 ADC core

Add core driver for STMicroelectronics STM32 ADC (Analog to Digital
Converter). STM32 ADC can be composed of up to 3 ADCs with shared
resources like clock prescaler, common interrupt line and analog
reference voltage.
This core driver basically manages shared resources.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Fabrice Gasnier and committed by
Jonathan Cameron
1add6988 841fcea4

+368
+12
drivers/iio/adc/Kconfig
··· 441 441 To compile this driver as a module, choose M here: the 442 442 module will be called rockchip_saradc. 443 443 444 + config STM32_ADC_CORE 445 + tristate "STMicroelectronics STM32 adc core" 446 + depends on ARCH_STM32 || COMPILE_TEST 447 + depends on OF 448 + depends on REGULATOR 449 + help 450 + Select this option to enable the core driver for STMicroelectronics 451 + STM32 analog-to-digital converter (ADC). 452 + 453 + This driver can also be built as a module. If so, the module 454 + will be called stm32-adc-core. 455 + 444 456 config STX104 445 457 tristate "Apex Embedded Systems STX104 driver" 446 458 depends on X86 && ISA_BUS_API
+1
drivers/iio/adc/Makefile
··· 43 43 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o 44 44 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o 45 45 obj-$(CONFIG_STX104) += stx104.o 46 + obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o 46 47 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 47 48 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 48 49 obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
+303
drivers/iio/adc/stm32-adc-core.c
··· 1 + /* 2 + * This file is part of STM32 ADC driver 3 + * 4 + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved 5 + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>. 6 + * 7 + * Inspired from: fsl-imx25-tsadc 8 + * 9 + * License type: GPLv2 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License version 2 as published by 13 + * the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, but 16 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 + * or FITNESS FOR A PARTICULAR PURPOSE. 18 + * See the GNU General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License along with 21 + * this program. If not, see <http://www.gnu.org/licenses/>. 22 + */ 23 + 24 + #include <linux/clk.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/irqchip/chained_irq.h> 27 + #include <linux/irqdesc.h> 28 + #include <linux/irqdomain.h> 29 + #include <linux/module.h> 30 + #include <linux/of_device.h> 31 + #include <linux/regulator/consumer.h> 32 + #include <linux/slab.h> 33 + 34 + #include "stm32-adc-core.h" 35 + 36 + /* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */ 37 + #define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) 38 + #define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) 39 + 40 + /* STM32F4_ADC_CSR - bit fields */ 41 + #define STM32F4_EOC3 BIT(17) 42 + #define STM32F4_EOC2 BIT(9) 43 + #define STM32F4_EOC1 BIT(1) 44 + 45 + /* STM32F4_ADC_CCR - bit fields */ 46 + #define STM32F4_ADC_ADCPRE_SHIFT 16 47 + #define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16) 48 + 49 + /* STM32 F4 maximum analog clock rate (from datasheet) */ 50 + #define STM32F4_ADC_MAX_CLK_RATE 36000000 51 + 52 + /** 53 + * struct stm32_adc_priv - stm32 ADC core private data 54 + * @irq: irq for ADC block 55 + * @domain: irq domain reference 56 + * @aclk: clock reference for the analog circuitry 57 + * @vref: regulator reference 58 + * @common: common data for all ADC instances 59 + */ 60 + struct stm32_adc_priv { 61 + int irq; 62 + struct irq_domain *domain; 63 + struct clk *aclk; 64 + struct regulator *vref; 65 + struct stm32_adc_common common; 66 + }; 67 + 68 + static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) 69 + { 70 + return container_of(com, struct stm32_adc_priv, common); 71 + } 72 + 73 + /* STM32F4 ADC internal common clock prescaler division ratios */ 74 + static int stm32f4_pclk_div[] = {2, 4, 6, 8}; 75 + 76 + /** 77 + * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler 78 + * @priv: stm32 ADC core private data 79 + * Select clock prescaler used for analog conversions, before using ADC. 80 + */ 81 + static int stm32f4_adc_clk_sel(struct platform_device *pdev, 82 + struct stm32_adc_priv *priv) 83 + { 84 + unsigned long rate; 85 + u32 val; 86 + int i; 87 + 88 + rate = clk_get_rate(priv->aclk); 89 + for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { 90 + if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE) 91 + break; 92 + } 93 + if (i >= ARRAY_SIZE(stm32f4_pclk_div)) 94 + return -EINVAL; 95 + 96 + val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR); 97 + val &= ~STM32F4_ADC_ADCPRE_MASK; 98 + val |= i << STM32F4_ADC_ADCPRE_SHIFT; 99 + writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR); 100 + 101 + dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n", 102 + rate / (stm32f4_pclk_div[i] * 1000)); 103 + 104 + return 0; 105 + } 106 + 107 + /* ADC common interrupt for all instances */ 108 + static void stm32_adc_irq_handler(struct irq_desc *desc) 109 + { 110 + struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc); 111 + struct irq_chip *chip = irq_desc_get_chip(desc); 112 + u32 status; 113 + 114 + chained_irq_enter(chip, desc); 115 + status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR); 116 + 117 + if (status & STM32F4_EOC1) 118 + generic_handle_irq(irq_find_mapping(priv->domain, 0)); 119 + 120 + if (status & STM32F4_EOC2) 121 + generic_handle_irq(irq_find_mapping(priv->domain, 1)); 122 + 123 + if (status & STM32F4_EOC3) 124 + generic_handle_irq(irq_find_mapping(priv->domain, 2)); 125 + 126 + chained_irq_exit(chip, desc); 127 + }; 128 + 129 + static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq, 130 + irq_hw_number_t hwirq) 131 + { 132 + irq_set_chip_data(irq, d->host_data); 133 + irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq); 134 + 135 + return 0; 136 + } 137 + 138 + static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq) 139 + { 140 + irq_set_chip_and_handler(irq, NULL, NULL); 141 + irq_set_chip_data(irq, NULL); 142 + } 143 + 144 + static const struct irq_domain_ops stm32_adc_domain_ops = { 145 + .map = stm32_adc_domain_map, 146 + .unmap = stm32_adc_domain_unmap, 147 + .xlate = irq_domain_xlate_onecell, 148 + }; 149 + 150 + static int stm32_adc_irq_probe(struct platform_device *pdev, 151 + struct stm32_adc_priv *priv) 152 + { 153 + struct device_node *np = pdev->dev.of_node; 154 + 155 + priv->irq = platform_get_irq(pdev, 0); 156 + if (priv->irq < 0) { 157 + dev_err(&pdev->dev, "failed to get irq\n"); 158 + return priv->irq; 159 + } 160 + 161 + priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0, 162 + &stm32_adc_domain_ops, 163 + priv); 164 + if (!priv->domain) { 165 + dev_err(&pdev->dev, "Failed to add irq domain\n"); 166 + return -ENOMEM; 167 + } 168 + 169 + irq_set_chained_handler(priv->irq, stm32_adc_irq_handler); 170 + irq_set_handler_data(priv->irq, priv); 171 + 172 + return 0; 173 + } 174 + 175 + static void stm32_adc_irq_remove(struct platform_device *pdev, 176 + struct stm32_adc_priv *priv) 177 + { 178 + int hwirq; 179 + 180 + for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++) 181 + irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq)); 182 + irq_domain_remove(priv->domain); 183 + irq_set_chained_handler(priv->irq, NULL); 184 + } 185 + 186 + static int stm32_adc_probe(struct platform_device *pdev) 187 + { 188 + struct stm32_adc_priv *priv; 189 + struct device_node *np = pdev->dev.of_node; 190 + struct resource *res; 191 + int ret; 192 + 193 + if (!pdev->dev.of_node) 194 + return -ENODEV; 195 + 196 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 197 + if (!priv) 198 + return -ENOMEM; 199 + 200 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 201 + priv->common.base = devm_ioremap_resource(&pdev->dev, res); 202 + if (IS_ERR(priv->common.base)) 203 + return PTR_ERR(priv->common.base); 204 + 205 + priv->vref = devm_regulator_get(&pdev->dev, "vref"); 206 + if (IS_ERR(priv->vref)) { 207 + ret = PTR_ERR(priv->vref); 208 + dev_err(&pdev->dev, "vref get failed, %d\n", ret); 209 + return ret; 210 + } 211 + 212 + ret = regulator_enable(priv->vref); 213 + if (ret < 0) { 214 + dev_err(&pdev->dev, "vref enable failed\n"); 215 + return ret; 216 + } 217 + 218 + ret = regulator_get_voltage(priv->vref); 219 + if (ret < 0) { 220 + dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret); 221 + goto err_regulator_disable; 222 + } 223 + priv->common.vref_mv = ret / 1000; 224 + dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv); 225 + 226 + priv->aclk = devm_clk_get(&pdev->dev, "adc"); 227 + if (IS_ERR(priv->aclk)) { 228 + ret = PTR_ERR(priv->aclk); 229 + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); 230 + goto err_regulator_disable; 231 + } 232 + 233 + ret = clk_prepare_enable(priv->aclk); 234 + if (ret < 0) { 235 + dev_err(&pdev->dev, "adc clk enable failed\n"); 236 + goto err_regulator_disable; 237 + } 238 + 239 + ret = stm32f4_adc_clk_sel(pdev, priv); 240 + if (ret < 0) { 241 + dev_err(&pdev->dev, "adc clk selection failed\n"); 242 + goto err_clk_disable; 243 + } 244 + 245 + ret = stm32_adc_irq_probe(pdev, priv); 246 + if (ret < 0) 247 + goto err_clk_disable; 248 + 249 + platform_set_drvdata(pdev, &priv->common); 250 + 251 + ret = of_platform_populate(np, NULL, NULL, &pdev->dev); 252 + if (ret < 0) { 253 + dev_err(&pdev->dev, "failed to populate DT children\n"); 254 + goto err_irq_remove; 255 + } 256 + 257 + return 0; 258 + 259 + err_irq_remove: 260 + stm32_adc_irq_remove(pdev, priv); 261 + 262 + err_clk_disable: 263 + clk_disable_unprepare(priv->aclk); 264 + 265 + err_regulator_disable: 266 + regulator_disable(priv->vref); 267 + 268 + return ret; 269 + } 270 + 271 + static int stm32_adc_remove(struct platform_device *pdev) 272 + { 273 + struct stm32_adc_common *common = platform_get_drvdata(pdev); 274 + struct stm32_adc_priv *priv = to_stm32_adc_priv(common); 275 + 276 + of_platform_depopulate(&pdev->dev); 277 + stm32_adc_irq_remove(pdev, priv); 278 + clk_disable_unprepare(priv->aclk); 279 + regulator_disable(priv->vref); 280 + 281 + return 0; 282 + } 283 + 284 + static const struct of_device_id stm32_adc_of_match[] = { 285 + { .compatible = "st,stm32f4-adc-core" }, 286 + {}, 287 + }; 288 + MODULE_DEVICE_TABLE(of, stm32_adc_of_match); 289 + 290 + static struct platform_driver stm32_adc_driver = { 291 + .probe = stm32_adc_probe, 292 + .remove = stm32_adc_remove, 293 + .driver = { 294 + .name = "stm32-adc-core", 295 + .of_match_table = stm32_adc_of_match, 296 + }, 297 + }; 298 + module_platform_driver(stm32_adc_driver); 299 + 300 + MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); 301 + MODULE_DESCRIPTION("STMicroelectronics STM32 ADC core driver"); 302 + MODULE_LICENSE("GPL v2"); 303 + MODULE_ALIAS("platform:stm32-adc-core");
+52
drivers/iio/adc/stm32-adc-core.h
··· 1 + /* 2 + * This file is part of STM32 ADC driver 3 + * 4 + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved 5 + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>. 6 + * 7 + * License type: GPLv2 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License version 2 as published by 11 + * the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, but 14 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 + * or FITNESS FOR A PARTICULAR PURPOSE. 16 + * See the GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License along with 19 + * this program. If not, see <http://www.gnu.org/licenses/>. 20 + */ 21 + 22 + #ifndef __STM32_ADC_H 23 + #define __STM32_ADC_H 24 + 25 + /* 26 + * STM32 - ADC global register map 27 + * ________________________________________________________ 28 + * | Offset | Register | 29 + * -------------------------------------------------------- 30 + * | 0x000 | Master ADC1 | 31 + * -------------------------------------------------------- 32 + * | 0x100 | Slave ADC2 | 33 + * -------------------------------------------------------- 34 + * | 0x200 | Slave ADC3 | 35 + * -------------------------------------------------------- 36 + * | 0x300 | Master & Slave common regs | 37 + * -------------------------------------------------------- 38 + */ 39 + #define STM32_ADC_MAX_ADCS 3 40 + #define STM32_ADCX_COMN_OFFSET 0x300 41 + 42 + /** 43 + * struct stm32_adc_common - stm32 ADC driver common data (for all instances) 44 + * @base: control registers base cpu addr 45 + * @vref_mv: vref voltage (mv) 46 + */ 47 + struct stm32_adc_common { 48 + void __iomem *base; 49 + int vref_mv; 50 + }; 51 + 52 + #endif