diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2019-07-10 22:11:09 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-07-15 08:41:44 +0200 |
commit | 7de1395b21d5d4186a802fb02f1250e2e890919b (patch) | |
tree | 9d1ca206f9df95aff4f4d7621544450a5e0f78f1 /drivers/reset | |
parent | c73f083b3089cd62f5e7cdc61c3c82278360e52f (diff) | |
download | barebox-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/Kconfig | 5 | ||||
-rw-r--r-- | drivers/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/reset/reset-stm32.c | 109 |
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); |