brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · 2d56707 Raw
261 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * This file is part of STM32 DAC driver4 *5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved6 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.7 *8 */9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/mod_devicetable.h>13#include <linux/module.h>14#include <linux/of_platform.h>15#include <linux/platform_device.h>16#include <linux/pm_runtime.h>17#include <linux/property.h>18#include <linux/regulator/consumer.h>19#include <linux/reset.h>20 21#include "stm32-dac-core.h"22 23/**24 * struct stm32_dac_priv - stm32 DAC core private data25 * @pclk:		peripheral clock common for all DACs26 * @vref:		regulator reference27 * @common:		Common data for all DAC instances28 */29struct stm32_dac_priv {30	struct clk *pclk;31	struct regulator *vref;32	struct stm32_dac_common common;33};34 35/**36 * struct stm32_dac_cfg - DAC configuration37 * @has_hfsel: DAC has high frequency control38 */39struct stm32_dac_cfg {40	bool has_hfsel;41};42 43static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com)44{45	return container_of(com, struct stm32_dac_priv, common);46}47 48static const struct regmap_config stm32_dac_regmap_cfg = {49	.reg_bits = 32,50	.val_bits = 32,51	.reg_stride = sizeof(u32),52	.max_register = 0x3fc,53};54 55static int stm32_dac_core_hw_start(struct device *dev)56{57	struct stm32_dac_common *common = dev_get_drvdata(dev);58	struct stm32_dac_priv *priv = to_stm32_dac_priv(common);59	int ret;60 61	ret = regulator_enable(priv->vref);62	if (ret < 0) {63		dev_err(dev, "vref enable failed: %d\n", ret);64		return ret;65	}66 67	ret = clk_prepare_enable(priv->pclk);68	if (ret < 0) {69		dev_err(dev, "pclk enable failed: %d\n", ret);70		goto err_regulator_disable;71	}72 73	return 0;74 75err_regulator_disable:76	regulator_disable(priv->vref);77 78	return ret;79}80 81static void stm32_dac_core_hw_stop(struct device *dev)82{83	struct stm32_dac_common *common = dev_get_drvdata(dev);84	struct stm32_dac_priv *priv = to_stm32_dac_priv(common);85 86	clk_disable_unprepare(priv->pclk);87	regulator_disable(priv->vref);88}89 90static int stm32_dac_probe(struct platform_device *pdev)91{92	struct device *dev = &pdev->dev;93	const struct stm32_dac_cfg *cfg;94	struct stm32_dac_priv *priv;95	struct regmap *regmap;96	void __iomem *mmio;97	struct reset_control *rst;98	int ret;99 100	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);101	if (!priv)102		return -ENOMEM;103	platform_set_drvdata(pdev, &priv->common);104 105	cfg = device_get_match_data(dev);106 107	mmio = devm_platform_ioremap_resource(pdev, 0);108	if (IS_ERR(mmio))109		return PTR_ERR(mmio);110 111	regmap = devm_regmap_init_mmio_clk(dev, "pclk", mmio,112					   &stm32_dac_regmap_cfg);113	if (IS_ERR(regmap))114		return PTR_ERR(regmap);115	priv->common.regmap = regmap;116 117	priv->pclk = devm_clk_get(dev, "pclk");118	if (IS_ERR(priv->pclk))119		return dev_err_probe(dev, PTR_ERR(priv->pclk), "pclk get failed\n");120 121	priv->vref = devm_regulator_get(dev, "vref");122	if (IS_ERR(priv->vref))123		return dev_err_probe(dev, PTR_ERR(priv->vref), "vref get failed\n");124 125	pm_runtime_get_noresume(dev);126	pm_runtime_set_active(dev);127	pm_runtime_enable(dev);128 129	ret = stm32_dac_core_hw_start(dev);130	if (ret)131		goto err_pm_stop;132 133	ret = regulator_get_voltage(priv->vref);134	if (ret < 0) {135		dev_err(dev, "vref get voltage failed, %d\n", ret);136		goto err_hw_stop;137	}138	priv->common.vref_mv = ret / 1000;139	dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv);140 141	rst = devm_reset_control_get_optional_exclusive(dev, NULL);142	if (rst) {143		if (IS_ERR(rst)) {144			ret = dev_err_probe(dev, PTR_ERR(rst), "reset get failed\n");145			goto err_hw_stop;146		}147 148		reset_control_assert(rst);149		udelay(2);150		reset_control_deassert(rst);151	}152 153	if (cfg && cfg->has_hfsel) {154		/* When clock speed is higher than 80MHz, set HFSEL */155		priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL);156		ret = regmap_update_bits(regmap, STM32_DAC_CR,157					 STM32H7_DAC_CR_HFSEL,158					 priv->common.hfsel ?159					 STM32H7_DAC_CR_HFSEL : 0);160		if (ret)161			goto err_hw_stop;162	}163 164 165	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, dev);166	if (ret < 0) {167		dev_err(dev, "failed to populate DT children\n");168		goto err_hw_stop;169	}170 171	pm_runtime_put(dev);172 173	return 0;174 175err_hw_stop:176	stm32_dac_core_hw_stop(dev);177err_pm_stop:178	pm_runtime_disable(dev);179	pm_runtime_set_suspended(dev);180	pm_runtime_put_noidle(dev);181 182	return ret;183}184 185static void stm32_dac_remove(struct platform_device *pdev)186{187	pm_runtime_get_sync(&pdev->dev);188	of_platform_depopulate(&pdev->dev);189	stm32_dac_core_hw_stop(&pdev->dev);190	pm_runtime_disable(&pdev->dev);191	pm_runtime_set_suspended(&pdev->dev);192	pm_runtime_put_noidle(&pdev->dev);193}194 195static int stm32_dac_core_resume(struct device *dev)196{197	struct stm32_dac_common *common = dev_get_drvdata(dev);198	struct stm32_dac_priv *priv = to_stm32_dac_priv(common);199	int ret;200 201	if (priv->common.hfsel) {202		/* restore hfsel (maybe lost under low power state) */203		ret = regmap_set_bits(priv->common.regmap, STM32_DAC_CR,204				      STM32H7_DAC_CR_HFSEL);205		if (ret)206			return ret;207	}208 209	return pm_runtime_force_resume(dev);210}211 212static int stm32_dac_core_runtime_suspend(struct device *dev)213{214	stm32_dac_core_hw_stop(dev);215 216	return 0;217}218 219static int stm32_dac_core_runtime_resume(struct device *dev)220{221	return stm32_dac_core_hw_start(dev);222}223 224static const struct dev_pm_ops stm32_dac_core_pm_ops = {225	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, stm32_dac_core_resume)226	RUNTIME_PM_OPS(stm32_dac_core_runtime_suspend,227		       stm32_dac_core_runtime_resume,228		       NULL)229};230 231static const struct stm32_dac_cfg stm32h7_dac_cfg = {232	.has_hfsel = true,233};234 235static const struct of_device_id stm32_dac_of_match[] = {236	{237		.compatible = "st,stm32f4-dac-core",238	}, {239		.compatible = "st,stm32h7-dac-core",240		.data = (void *)&stm32h7_dac_cfg,241	},242	{},243};244MODULE_DEVICE_TABLE(of, stm32_dac_of_match);245 246static struct platform_driver stm32_dac_driver = {247	.probe = stm32_dac_probe,248	.remove_new = stm32_dac_remove,249	.driver = {250		.name = "stm32-dac-core",251		.of_match_table = stm32_dac_of_match,252		.pm = pm_ptr(&stm32_dac_core_pm_ops),253	},254};255module_platform_driver(stm32_dac_driver);256 257MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");258MODULE_DESCRIPTION("STMicroelectronics STM32 DAC core driver");259MODULE_LICENSE("GPL v2");260MODULE_ALIAS("platform:stm32-dac-core");261