summaryrefslogtreecommitdiff
path: root/drivers/mfd/stm32-timers.c
diff options
context:
space:
mode:
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>2017-01-20 10:15:03 +0100
committerLee Jones <lee.jones@linaro.org>2017-01-23 12:03:57 +0000
commitd0f949e220fdf5ed1033e9f6e80749b05f2e7b70 (patch)
tree5b443357a8208a29a75d073ff680d0c671e15607 /drivers/mfd/stm32-timers.c
parent8f9359c6c6a00b43273480a5cf5b0f240aa3b648 (diff)
mfd: Add STM32 Timers driver
This hardware block could at used at same time for PWM generation and IIO timers. PWM and IIO timer configuration are mixed in the same registers so we need a multi fonction driver to be able to share those registers. version 7: - rebase on v4.10-rc2 version 6: - rename files to stm32-timers - rename functions to stm32_timers_xxx version 5: - fix Lee comments about detect function - add missing dependency on REGMAP_MMIO version 4: - add a function to detect Auto Reload Register (ARR) size - rename the structure shared with other drivers version 2: - rename driver "stm32-gptimer" to be align with SoC documentation - only keep one compatible - use of_platform_populate() instead of devm_mfd_add_devices() Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/stm32-timers.c')
-rw-r--r--drivers/mfd/stm32-timers.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
new file mode 100644
index 000000000000..41bd9017f3d0
--- /dev/null
+++ b/drivers/mfd/stm32-timers.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) STMicroelectronics 2016
+ *
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/mfd/stm32-timers.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+
+static const struct regmap_config stm32_timers_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = sizeof(u32),
+ .max_register = 0x400,
+};
+
+static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
+{
+ /*
+ * Only the available bits will be written so when readback
+ * we get the maximum value of auto reload register
+ */
+ regmap_write(ddata->regmap, TIM_ARR, ~0L);
+ regmap_read(ddata->regmap, TIM_ARR, &ddata->max_arr);
+ regmap_write(ddata->regmap, TIM_ARR, 0x0);
+}
+
+static int stm32_timers_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct stm32_timers *ddata;
+ struct resource *res;
+ void __iomem *mmio;
+
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(mmio))
+ return PTR_ERR(mmio);
+
+ ddata->regmap = devm_regmap_init_mmio_clk(dev, "int", mmio,
+ &stm32_timers_regmap_cfg);
+ if (IS_ERR(ddata->regmap))
+ return PTR_ERR(ddata->regmap);
+
+ ddata->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ddata->clk))
+ return PTR_ERR(ddata->clk);
+
+ stm32_timers_get_arr_size(ddata);
+
+ platform_set_drvdata(pdev, ddata);
+
+ return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
+
+static const struct of_device_id stm32_timers_of_match[] = {
+ { .compatible = "st,stm32-timers", },
+ { /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
+
+static struct platform_driver stm32_timers_driver = {
+ .probe = stm32_timers_probe,
+ .driver = {
+ .name = "stm32-timers",
+ .of_match_table = stm32_timers_of_match,
+ },
+};
+module_platform_driver(stm32_timers_driver);
+
+MODULE_DESCRIPTION("STMicroelectronics STM32 Timers");
+MODULE_LICENSE("GPL v2");