summaryrefslogtreecommitdiffstats
path: root/drivers/reset
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2019-07-10 22:11:09 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-07-15 08:41:44 +0200
commit7de1395b21d5d4186a802fb02f1250e2e890919b (patch)
tree9d1ca206f9df95aff4f4d7621544450a5e0f78f1 /drivers/reset
parentc73f083b3089cd62f5e7cdc61c3c82278360e52f (diff)
downloadbarebox-7de1395b21d5d4186a802fb02f1250e2e890919b.tar.gz
barebox-7de1395b21d5d4186a802fb02f1250e2e890919b.tar.xz
reset: add reset controller driver for STM32 RCC
On the STM32MP, reset of the I2C, SPI and USB IPs occurs over the RCC. This driver adds support for the controller, so it may be reused by other drivers. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/Kconfig5
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-stm32.c109
3 files changed, 115 insertions, 0 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index caf1dc9acb..048f2081f8 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -21,4 +21,9 @@ config RESET_IMX7
help
This enables the reset controller driver for i.MX7 SoCs.
+config RESET_STM32
+ bool "STM32 Reset Driver"
+ help
+ This enables the reset controller driver for STM32MP and STM32 MCUs.
+
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 0b55caa204..8460c4b154 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_RESET_CONTROLLER) += core.o
obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
+obj-$(CONFIG_RESET_STM32) += reset-stm32.o
diff --git a/drivers/reset/reset-stm32.c b/drivers/reset/reset-stm32.c
new file mode 100644
index 0000000000..5689dfd488
--- /dev/null
+++ b/drivers/reset/reset-stm32.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019, Ahmad Fatoum, Pengutronix
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/err.h>
+#include <linux/reset-controller.h>
+#include <asm/io.h>
+
+#define RCC_CL 0x4
+
+struct stm32_reset {
+ void __iomem *base;
+ struct reset_controller_dev rcdev;
+ void (*reset)(void __iomem *reg, unsigned offset, bool assert);
+};
+
+static struct stm32_reset *to_stm32_reset(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct stm32_reset, rcdev);
+}
+
+static void stm32mp_reset(void __iomem *reg, unsigned offset, bool assert)
+{
+ if (!assert)
+ reg += RCC_CL;
+
+ writel(BIT(offset), reg);
+}
+
+static void stm32mcu_reset(void __iomem *reg, unsigned offset, bool assert)
+{
+ if (assert)
+ setbits_le32(reg, BIT(offset));
+ else
+ clrbits_le32(reg, BIT(offset));
+}
+
+static void stm32_reset(struct stm32_reset *priv, unsigned long id, bool assert)
+{
+ int bank = (id / BITS_PER_LONG) * 4;
+ int offset = id % BITS_PER_LONG;
+
+ priv->reset(priv->base + bank, offset, assert);
+}
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ stm32_reset(to_stm32_reset(rcdev), id, true);
+ return 0;
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ stm32_reset(to_stm32_reset(rcdev), id, false);
+ return 0;
+}
+
+static const struct reset_control_ops stm32_reset_ops = {
+ .assert = stm32_reset_assert,
+ .deassert = stm32_reset_deassert,
+};
+
+static int stm32_reset_probe(struct device_d *dev)
+{
+ struct stm32_reset *priv;
+ struct resource *iores;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+ ret = dev_get_drvdata(dev, (const void **)&priv->reset);
+ if (ret)
+ return ret;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ priv->base = IOMEM(iores->start);
+ priv->rcdev.nr_resets = (iores->end - iores->start) * BITS_PER_BYTE;
+ priv->rcdev.ops = &stm32_reset_ops;
+ priv->rcdev.of_node = dev->device_node;
+
+ return reset_controller_register(&priv->rcdev);
+}
+
+static const struct of_device_id stm32_rcc_reset_dt_ids[] = {
+ { .compatible = "st,stm32mp1-rcc", .data = stm32mp_reset },
+ { .compatible = "st,stm32-rcc", .data = stm32mcu_reset },
+ { /* sentinel */ },
+};
+
+static struct driver_d stm32_rcc_reset_driver = {
+ .name = "stm32_rcc_reset",
+ .probe = stm32_reset_probe,
+ .of_compatible = DRV_OF_COMPAT(stm32_rcc_reset_dt_ids),
+};
+
+static int stm32_rcc_reset_init(void)
+{
+ return platform_driver_register(&stm32_rcc_reset_driver);
+}
+postcore_initcall(stm32_rcc_reset_init);