Browse Source

Merge tag 'reset-for-4.9' of git://git.pengutronix.de/git/pza/linux into next/drivers

Merge "Reset controller changes for v4.9" from Philipp Zabel:

- add reset controller driver Kconfig options,
  allow building drivers with COMPILE_TEST
- add reset controller driver for UniPhier SoCs
- add reset controller driver for STM32 MCUs
- simplify SoCFPGA reset controller driver a bit

* tag 'reset-for-4.9' of git://git.pengutronix.de/git/pza/linux:
  reset: hi6220: allow to compile test driver on other architectures
  reset: zynq: add driver Kconfig option
  reset: sunxi: add driver Kconfig option
  reset: stm32: add driver Kconfig option
  reset: socfpga: add driver Kconfig option
  reset: pistachio: add driver Kconfig option
  reset: meson: add driver Kconfig option
  reset: lpc18xx: add driver Kconfig option
  reset: berlin: add driver Kconfig option
  reset: ath79: add driver Kconfig option
  reset: ath79: add missing include
  reset: warn on invalid input to reset_control_reset/assert/deassert/status
  reset: uniphier: add reset controller driver for UniPhier SoCs
  ARM: dts: stm32f429: add missing #reset-cells of rcc
  drivers: reset: Add STM32 reset driver
  dt-bindings: Document the STM32 reset bindings
  dt-bindings: mfd: Add STM32F4 RCC numeric constants into DT include file
  reset: socfpga: no need to store modrst_offset
Arnd Bergmann 9 years ago
parent
commit
7d3ef43f1f

+ 35 - 7
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

@@ -1,16 +1,16 @@
 STMicroelectronics STM32 Reset and Clock Controller
 STMicroelectronics STM32 Reset and Clock Controller
 ===================================================
 ===================================================
 
 
-The RCC IP is both a reset and a clock controller. This documentation only
-describes the clock part.
+The RCC IP is both a reset and a clock controller.
 
 
-Please also refer to clock-bindings.txt in this directory for common clock
-controller binding usage.
+Please refer to clock-bindings.txt for common clock controller binding usage.
+Please also refer to reset.txt for common reset controller binding usage.
 
 
 Required properties:
 Required properties:
 - compatible: Should be "st,stm32f42xx-rcc"
 - compatible: Should be "st,stm32f42xx-rcc"
 - reg: should be register base and length as documented in the
 - reg: should be register base and length as documented in the
   datasheet
   datasheet
+- #reset-cells: 1, see below
 - #clock-cells: 2, device nodes should specify the clock in their "clocks"
 - #clock-cells: 2, device nodes should specify the clock in their "clocks"
   property, containing a phandle to the clock device node, an index selecting
   property, containing a phandle to the clock device node, an index selecting
   between gated clocks and other clocks and an index specifying the clock to
   between gated clocks and other clocks and an index specifying the clock to
@@ -19,6 +19,7 @@ Required properties:
 Example:
 Example:
 
 
 	rcc: rcc@40023800 {
 	rcc: rcc@40023800 {
+		#reset-cells = <1>;
 		#clock-cells = <2>
 		#clock-cells = <2>
 		compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
 		compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
 		reg = <0x40023800 0x400>;
 		reg = <0x40023800 0x400>;
@@ -35,16 +36,23 @@ from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30).
 It is calculated as: index = register_offset / 4 * 32 + bit_offset.
 It is calculated as: index = register_offset / 4 * 32 + bit_offset.
 Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31).
 Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31).
 
 
+To simplify the usage and to share bit definition with the reset and clock
+drivers of the RCC IP, macros are available to generate the index in
+human-readble format.
+
+For STM32F4 series, the macro are available here:
+ - include/dt-bindings/mfd/stm32f4-rcc.h
+
 Example:
 Example:
 
 
 	/* Gated clock, AHB1 bit 0 (GPIOA) */
 	/* Gated clock, AHB1 bit 0 (GPIOA) */
 	... {
 	... {
-		clocks = <&rcc 0 0>
+		clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>
 	};
 	};
 
 
 	/* Gated clock, AHB2 bit 4 (CRYP) */
 	/* Gated clock, AHB2 bit 4 (CRYP) */
 	... {
 	... {
-		clocks = <&rcc 0 36>
+		clocks = <&rcc 0 STM32F4_AHB2_CLOCK(CRYP)>
 	};
 	};
 
 
 Specifying other clocks
 Specifying other clocks
@@ -61,5 +69,25 @@ Example:
 
 
 	/* Misc clock, FCLK */
 	/* Misc clock, FCLK */
 	... {
 	... {
-		clocks = <&rcc 1 1>
+		clocks = <&rcc 1 STM32F4_APB1_CLOCK(TIM2)>
+	};
+
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+The index is the bit number within the RCC registers bank, starting from RCC
+base address.
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register.
+For example, for CRC reset:
+  crc = AHB1RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x10 / 4 * 32 + 12 = 140
+
+example:
+
+	timer2 {
+		resets	= <&rcc STM32F4_APB1_RESET(TIM2)>;
 	};
 	};

+ 6 - 0
Documentation/devicetree/bindings/reset/st,stm32-rcc.txt

@@ -0,0 +1,6 @@
+STMicroelectronics STM32 Peripheral Reset Controller
+====================================================
+
+The RCC IP is both a reset and a clock controller.
+
+Please see Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

+ 93 - 0
Documentation/devicetree/bindings/reset/uniphier-reset.txt

@@ -0,0 +1,93 @@
+UniPhier reset controller
+
+
+System reset
+------------
+
+Required properties:
+- compatible: should be one of the following:
+    "socionext,uniphier-sld3-reset" - for PH1-sLD3 SoC.
+    "socionext,uniphier-ld4-reset"  - for PH1-LD4 SoC.
+    "socionext,uniphier-pro4-reset" - for PH1-Pro4 SoC.
+    "socionext,uniphier-sld8-reset" - for PH1-sLD8 SoC.
+    "socionext,uniphier-pro5-reset" - for PH1-Pro5 SoC.
+    "socionext,uniphier-pxs2-reset" - for ProXstream2/PH1-LD6b SoC.
+    "socionext,uniphier-ld11-reset" - for PH1-LD11 SoC.
+    "socionext,uniphier-ld20-reset" - for PH1-LD20 SoC.
+- #reset-cells: should be 1.
+
+Example:
+
+	sysctrl@61840000 {
+		compatible = "socionext,uniphier-ld20-sysctrl",
+			     "simple-mfd", "syscon";
+		reg = <0x61840000 0x4000>;
+
+		reset {
+			compatible = "socionext,uniphier-ld20-reset";
+			#reset-cells = <1>;
+		};
+
+		other nodes ...
+	};
+
+
+Media I/O (MIO) reset
+---------------------
+
+Required properties:
+- compatible: should be one of the following:
+    "socionext,uniphier-sld3-mio-reset" - for PH1-sLD3 SoC.
+    "socionext,uniphier-ld4-mio-reset"  - for PH1-LD4 SoC.
+    "socionext,uniphier-pro4-mio-reset" - for PH1-Pro4 SoC.
+    "socionext,uniphier-sld8-mio-reset" - for PH1-sLD8 SoC.
+    "socionext,uniphier-pro5-mio-reset" - for PH1-Pro5 SoC.
+    "socionext,uniphier-pxs2-mio-reset" - for ProXstream2/PH1-LD6b SoC.
+    "socionext,uniphier-ld11-mio-reset" - for PH1-LD11 SoC.
+    "socionext,uniphier-ld20-mio-reset" - for PH1-LD20 SoC.
+- #reset-cells: should be 1.
+
+Example:
+
+	mioctrl@59810000 {
+		compatible = "socionext,uniphier-ld20-mioctrl",
+			     "simple-mfd", "syscon";
+		reg = <0x59810000 0x800>;
+
+		reset {
+			compatible = "socionext,uniphier-ld20-mio-reset";
+			#reset-cells = <1>;
+		};
+
+		other nodes ...
+	};
+
+
+Peripheral reset
+----------------
+
+Required properties:
+- compatible: should be one of the following:
+    "socionext,uniphier-ld4-peri-reset"  - for PH1-LD4 SoC.
+    "socionext,uniphier-pro4-peri-reset" - for PH1-Pro4 SoC.
+    "socionext,uniphier-sld8-peri-reset" - for PH1-sLD8 SoC.
+    "socionext,uniphier-pro5-peri-reset" - for PH1-Pro5 SoC.
+    "socionext,uniphier-pxs2-peri-reset" - for ProXstream2/PH1-LD6b SoC.
+    "socionext,uniphier-ld11-peri-reset" - for PH1-LD11 SoC.
+    "socionext,uniphier-ld20-peri-reset" - for PH1-LD20 SoC.
+- #reset-cells: should be 1.
+
+Example:
+
+	perictrl@59820000 {
+		compatible = "socionext,uniphier-ld20-perictrl",
+			     "simple-mfd", "syscon";
+		reg = <0x59820000 0x200>;
+
+		reset {
+			compatible = "socionext,uniphier-ld20-peri-reset";
+			#reset-cells = <1>;
+		};
+
+		other nodes ...
+	};

+ 1 - 0
MAINTAINERS

@@ -1840,6 +1840,7 @@ F:	arch/arm64/boot/dts/socionext/
 F:	drivers/bus/uniphier-system-bus.c
 F:	drivers/bus/uniphier-system-bus.c
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/pinctrl/uniphier/
 F:	drivers/pinctrl/uniphier/
+F:	drivers/reset/reset-uniphier.c
 F:	drivers/tty/serial/8250/8250_uniphier.c
 F:	drivers/tty/serial/8250/8250_uniphier.c
 N:	uniphier
 N:	uniphier
 
 

+ 1 - 0
arch/arm/boot/dts/stm32f429.dtsi

@@ -326,6 +326,7 @@
 		};
 		};
 
 
 		rcc: rcc@40023810 {
 		rcc: rcc@40023810 {
+			#reset-cells = <1>;
 			#clock-cells = <2>;
 			#clock-cells = <2>;
 			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
 			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
 			reg = <0x40023800 0x400>;
 			reg = <0x40023800 0x400>;

+ 65 - 0
drivers/reset/Kconfig

@@ -14,9 +14,58 @@ menuconfig RESET_CONTROLLER
 
 
 if RESET_CONTROLLER
 if RESET_CONTROLLER
 
 
+config RESET_ATH79
+	bool "AR71xx Reset Driver" if COMPILE_TEST
+	default ATH79
+	help
+	  This enables the ATH79 reset controller driver that supports the
+	  AR71xx SoC reset controller.
+
+config RESET_BERLIN
+	bool "Berlin Reset Driver" if COMPILE_TEST
+	default ARCH_BERLIN
+	help
+	  This enables the reset controller driver for Marvell Berlin SoCs.
+
+config RESET_LPC18XX
+	bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
+	default ARCH_LPC18XX
+	help
+	  This enables the reset controller driver for NXP LPC18xx/43xx SoCs.
+
+config RESET_MESON
+	bool "Meson Reset Driver" if COMPILE_TEST
+	default ARCH_MESON
+	help
+	  This enables the reset driver for Amlogic Meson SoCs.
+
 config RESET_OXNAS
 config RESET_OXNAS
 	bool
 	bool
 
 
+config RESET_PISTACHIO
+	bool "Pistachio Reset Driver" if COMPILE_TEST
+	default MACH_PISTACHIO
+	help
+	  This enables the reset driver for ImgTec Pistachio SoCs.
+
+config RESET_SOCFPGA
+	bool "SoCFPGA Reset Driver" if COMPILE_TEST
+	default ARCH_SOCFPGA
+	help
+	  This enables the reset controller driver for Altera SoCFPGAs.
+
+config RESET_STM32
+	bool "STM32 Reset Driver" if COMPILE_TEST
+	default ARCH_STM32
+	help
+	  This enables the RCC reset controller driver for STM32 MCUs.
+
+config RESET_SUNXI
+	bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
+	default ARCH_SUNXI
+	help
+	  This enables the reset driver for Allwinner SoCs.
+
 config TI_SYSCON_RESET
 config TI_SYSCON_RESET
 	tristate "TI SYSCON Reset Driver"
 	tristate "TI SYSCON Reset Driver"
 	depends on HAS_IOMEM
 	depends on HAS_IOMEM
@@ -27,6 +76,22 @@ config TI_SYSCON_RESET
 	  you wish to use the reset framework for such memory-mapped devices,
 	  you wish to use the reset framework for such memory-mapped devices,
 	  say Y here. Otherwise, say N.
 	  say Y here. Otherwise, say N.
 
 
+config RESET_UNIPHIER
+	tristate "Reset controller driver for UniPhier SoCs"
+	depends on ARCH_UNIPHIER || COMPILE_TEST
+	depends on OF && MFD_SYSCON
+	default ARCH_UNIPHIER
+	help
+	  Support for reset controllers on UniPhier SoCs.
+	  Say Y if you want to control reset signals provided by System Control
+	  block, Media I/O block, Peripheral Block.
+
+config RESET_ZYNQ
+	bool "ZYNQ Reset Driver" if COMPILE_TEST
+	default ARCH_ZYNQ
+	help
+	  This enables the reset controller driver for Xilinx Zynq SoCs.
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
 
 

+ 11 - 9
drivers/reset/Makefile

@@ -1,13 +1,15 @@
 obj-y += core.o
 obj-y += core.o
-obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
-obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
-obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
-obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
-obj-$(CONFIG_ARCH_MESON) += reset-meson.o
-obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
+obj-y += hisilicon/
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_STI) += sti/
-obj-$(CONFIG_ARCH_HISI) += hisilicon/
-obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
-obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
+obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
+obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_STM32) += reset-stm32.o
+obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
 obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
+obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o

+ 11 - 1
drivers/reset/core.c

@@ -138,7 +138,8 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register);
  */
  */
 int reset_control_reset(struct reset_control *rstc)
 int reset_control_reset(struct reset_control *rstc)
 {
 {
-	if (WARN_ON(rstc->shared))
+	if (WARN_ON(IS_ERR_OR_NULL(rstc)) ||
+	    WARN_ON(rstc->shared))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (rstc->rcdev->ops->reset)
 	if (rstc->rcdev->ops->reset)
@@ -161,6 +162,9 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
  */
  */
 int reset_control_assert(struct reset_control *rstc)
 int reset_control_assert(struct reset_control *rstc)
 {
 {
+	if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+		return -EINVAL;
+
 	if (!rstc->rcdev->ops->assert)
 	if (!rstc->rcdev->ops->assert)
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
@@ -184,6 +188,9 @@ EXPORT_SYMBOL_GPL(reset_control_assert);
  */
  */
 int reset_control_deassert(struct reset_control *rstc)
 int reset_control_deassert(struct reset_control *rstc)
 {
 {
+	if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+		return -EINVAL;
+
 	if (!rstc->rcdev->ops->deassert)
 	if (!rstc->rcdev->ops->deassert)
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 
@@ -204,6 +211,9 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
  */
  */
 int reset_control_status(struct reset_control *rstc)
 int reset_control_status(struct reset_control *rstc)
 {
 {
+	if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+		return -EINVAL;
+
 	if (rstc->rcdev->ops->status)
 	if (rstc->rcdev->ops->status)
 		return rstc->rcdev->ops->status(rstc->rcdev, rstc->id);
 		return rstc->rcdev->ops->status(rstc->rcdev, rstc->id);
 
 

+ 2 - 1
drivers/reset/hisilicon/Kconfig

@@ -1,5 +1,6 @@
 config COMMON_RESET_HI6220
 config COMMON_RESET_HI6220
 	tristate "Hi6220 Reset Driver"
 	tristate "Hi6220 Reset Driver"
-	depends on (ARCH_HISI && RESET_CONTROLLER)
+	depends on ARCH_HISI || COMPILE_TEST
+	default ARCH_HISI
 	help
 	help
 	  Build the Hisilicon Hi6220 reset driver.
 	  Build the Hisilicon Hi6220 reset driver.

+ 1 - 0
drivers/reset/reset-ath79.c

@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  */
  */
 
 
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/reset-controller.h>

+ 9 - 10
drivers/reset/reset-socfpga.c

@@ -28,7 +28,6 @@
 struct socfpga_reset_data {
 struct socfpga_reset_data {
 	spinlock_t			lock;
 	spinlock_t			lock;
 	void __iomem			*membase;
 	void __iomem			*membase;
-	u32				modrst_offset;
 	struct reset_controller_dev	rcdev;
 	struct reset_controller_dev	rcdev;
 };
 };
 
 
@@ -45,9 +44,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
 
 
 	spin_lock_irqsave(&data->lock, flags);
 	spin_lock_irqsave(&data->lock, flags);
 
 
-	reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
-	writel(reg | BIT(offset), data->membase + data->modrst_offset +
-				 (bank * NR_BANKS));
+	reg = readl(data->membase + (bank * NR_BANKS));
+	writel(reg | BIT(offset), data->membase + (bank * NR_BANKS));
 	spin_unlock_irqrestore(&data->lock, flags);
 	spin_unlock_irqrestore(&data->lock, flags);
 
 
 	return 0;
 	return 0;
@@ -67,9 +65,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
 
 
 	spin_lock_irqsave(&data->lock, flags);
 	spin_lock_irqsave(&data->lock, flags);
 
 
-	reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
-	writel(reg & ~BIT(offset), data->membase + data->modrst_offset +
-				  (bank * NR_BANKS));
+	reg = readl(data->membase + (bank * NR_BANKS));
+	writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS));
 
 
 	spin_unlock_irqrestore(&data->lock, flags);
 	spin_unlock_irqrestore(&data->lock, flags);
 
 
@@ -85,7 +82,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
 	int offset = id % BITS_PER_LONG;
 	int offset = id % BITS_PER_LONG;
 	u32 reg;
 	u32 reg;
 
 
-	reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
+	reg = readl(data->membase + (bank * NR_BANKS));
 
 
 	return !(reg & BIT(offset));
 	return !(reg & BIT(offset));
 }
 }
@@ -102,6 +99,7 @@ static int socfpga_reset_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct device_node *np = dev->of_node;
+	u32 modrst_offset;
 
 
 	/*
 	/*
 	 * The binding was mainlined without the required property.
 	 * The binding was mainlined without the required property.
@@ -122,10 +120,11 @@ static int socfpga_reset_probe(struct platform_device *pdev)
 	if (IS_ERR(data->membase))
 	if (IS_ERR(data->membase))
 		return PTR_ERR(data->membase);
 		return PTR_ERR(data->membase);
 
 
-	if (of_property_read_u32(np, "altr,modrst-offset", &data->modrst_offset)) {
+	if (of_property_read_u32(np, "altr,modrst-offset", &modrst_offset)) {
 		dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n");
 		dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n");
-		data->modrst_offset = 0x10;
+		modrst_offset = 0x10;
 	}
 	}
+	data->membase += modrst_offset;
 
 
 	spin_lock_init(&data->lock);
 	spin_lock_init(&data->lock);
 
 

+ 108 - 0
drivers/reset/reset-stm32.c

@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ *
+ * Heavily based on sunxi driver from Maxime Ripard.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+struct stm32_reset_data {
+	spinlock_t			lock;
+	void __iomem			*membase;
+	struct reset_controller_dev	rcdev;
+};
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct stm32_reset_data *data = container_of(rcdev,
+						     struct stm32_reset_data,
+						     rcdev);
+	int bank = id / BITS_PER_LONG;
+	int offset = id % BITS_PER_LONG;
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	reg = readl(data->membase + (bank * 4));
+	writel(reg | BIT(offset), data->membase + (bank * 4));
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	return 0;
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct stm32_reset_data *data = container_of(rcdev,
+						     struct stm32_reset_data,
+						     rcdev);
+	int bank = id / BITS_PER_LONG;
+	int offset = id % BITS_PER_LONG;
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	reg = readl(data->membase + (bank * 4));
+	writel(reg & ~BIT(offset), data->membase + (bank * 4));
+
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	return 0;
+}
+
+static const struct reset_control_ops stm32_reset_ops = {
+	.assert		= stm32_reset_assert,
+	.deassert	= stm32_reset_deassert,
+};
+
+static const struct of_device_id stm32_reset_dt_ids[] = {
+	 { .compatible = "st,stm32-rcc", },
+	 { /* sentinel */ },
+};
+
+static int stm32_reset_probe(struct platform_device *pdev)
+{
+	struct stm32_reset_data *data;
+	struct resource *res;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->membase))
+		return PTR_ERR(data->membase);
+
+	spin_lock_init(&data->lock);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = resource_size(res) * 8;
+	data->rcdev.ops = &stm32_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static struct platform_driver stm32_reset_driver = {
+	.probe	= stm32_reset_probe,
+	.driver = {
+		.name		= "stm32-rcc-reset",
+		.of_match_table	= stm32_reset_dt_ids,
+	},
+};
+builtin_platform_driver(stm32_reset_driver);

+ 440 - 0
drivers/reset/reset-uniphier.c

@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+struct uniphier_reset_data {
+	unsigned int id;
+	unsigned int reg;
+	unsigned int bit;
+	unsigned int flags;
+#define UNIPHIER_RESET_ACTIVE_LOW		BIT(0)
+};
+
+#define UNIPHIER_RESET_ID_END		(unsigned int)(-1)
+
+#define UNIPHIER_RESET_END				\
+	{ .id = UNIPHIER_RESET_ID_END }
+
+#define UNIPHIER_RESET(_id, _reg, _bit)			\
+	{						\
+		.id = (_id),				\
+		.reg = (_reg),				\
+		.bit = (_bit),				\
+	}
+
+#define UNIPHIER_RESETX(_id, _reg, _bit)		\
+	{						\
+		.id = (_id),				\
+		.reg = (_reg),				\
+		.bit = (_bit),				\
+		.flags = UNIPHIER_RESET_ACTIVE_LOW,	\
+	}
+
+/* System reset data */
+#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id)		\
+	UNIPHIER_RESETX((id), 0x2000, 10)
+
+#define UNIPHIER_LD11_SYS_RESET_STDMAC(id)		\
+	UNIPHIER_RESETX((id), 0x200c, 8)
+
+#define UNIPHIER_PRO4_SYS_RESET_GIO(id)			\
+	UNIPHIER_RESETX((id), 0x2000, 6)
+
+#define UNIPHIER_LD20_SYS_RESET_GIO(id)			\
+	UNIPHIER_RESETX((id), 0x200c, 5)
+
+#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch)		\
+	UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
+
+const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
+	UNIPHIER_SLD3_SYS_RESET_STDMAC(8),	/* Ether, HSC, MIO */
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
+	UNIPHIER_SLD3_SYS_RESET_STDMAC(8),	/* HSC, MIO, RLE */
+	UNIPHIER_PRO4_SYS_RESET_GIO(12),	/* Ether, SATA, USB3 */
+	UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
+	UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
+	UNIPHIER_SLD3_SYS_RESET_STDMAC(8),	/* HSC */
+	UNIPHIER_PRO4_SYS_RESET_GIO(12),	/* PCIe, USB3 */
+	UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
+	UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
+	UNIPHIER_SLD3_SYS_RESET_STDMAC(8),	/* HSC, RLE */
+	UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
+	UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
+	UNIPHIER_RESETX(16, 0x2014, 4),		/* USB30-PHY0 */
+	UNIPHIER_RESETX(17, 0x2014, 0),		/* USB30-PHY1 */
+	UNIPHIER_RESETX(18, 0x2014, 2),		/* USB30-PHY2 */
+	UNIPHIER_RESETX(20, 0x2014, 5),		/* USB31-PHY0 */
+	UNIPHIER_RESETX(21, 0x2014, 1),		/* USB31-PHY1 */
+	UNIPHIER_RESETX(28, 0x2014, 12),	/* SATA */
+	UNIPHIER_RESET(29, 0x2014, 8),		/* SATA-PHY (active high) */
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
+	UNIPHIER_LD11_SYS_RESET_STDMAC(8),	/* HSC, MIO */
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
+	UNIPHIER_LD11_SYS_RESET_STDMAC(8),	/* HSC */
+	UNIPHIER_LD20_SYS_RESET_GIO(12),	/* PCIe, USB3 */
+	UNIPHIER_RESETX(16, 0x200c, 12),	/* USB30-PHY0 */
+	UNIPHIER_RESETX(17, 0x200c, 13),	/* USB30-PHY1 */
+	UNIPHIER_RESETX(18, 0x200c, 14),	/* USB30-PHY2 */
+	UNIPHIER_RESETX(19, 0x200c, 15),	/* USB30-PHY3 */
+	UNIPHIER_RESET_END,
+};
+
+/* Media I/O reset data */
+#define UNIPHIER_MIO_RESET_SD(id, ch)			\
+	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
+
+#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch)		\
+	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26)
+
+#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch)	\
+	UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0)
+
+#define UNIPHIER_MIO_RESET_USB2(id, ch)			\
+	UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0)
+
+#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch)		\
+	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24)
+
+#define UNIPHIER_MIO_RESET_DMAC(id)			\
+	UNIPHIER_RESETX((id), 0x110, 17)
+
+const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
+	UNIPHIER_MIO_RESET_SD(0, 0),
+	UNIPHIER_MIO_RESET_SD(1, 1),
+	UNIPHIER_MIO_RESET_SD(2, 2),
+	UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0),
+	UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1),
+	UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2),
+	UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
+	UNIPHIER_MIO_RESET_DMAC(7),
+	UNIPHIER_MIO_RESET_USB2(8, 0),
+	UNIPHIER_MIO_RESET_USB2(9, 1),
+	UNIPHIER_MIO_RESET_USB2(10, 2),
+	UNIPHIER_MIO_RESET_USB2(11, 3),
+	UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
+	UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
+	UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
+	UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_pro5_mio_reset_data[] = {
+	UNIPHIER_MIO_RESET_SD(0, 0),
+	UNIPHIER_MIO_RESET_SD(1, 1),
+	UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
+	UNIPHIER_RESET_END,
+};
+
+/* Peripheral reset data */
+#define UNIPHIER_PERI_RESET_UART(id, ch)		\
+	UNIPHIER_RESETX((id), 0x114, 19 + (ch))
+
+#define UNIPHIER_PERI_RESET_I2C(id, ch)			\
+	UNIPHIER_RESETX((id), 0x114, 5 + (ch))
+
+#define UNIPHIER_PERI_RESET_FI2C(id, ch)		\
+	UNIPHIER_RESETX((id), 0x114, 24 + (ch))
+
+const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
+	UNIPHIER_PERI_RESET_UART(0, 0),
+	UNIPHIER_PERI_RESET_UART(1, 1),
+	UNIPHIER_PERI_RESET_UART(2, 2),
+	UNIPHIER_PERI_RESET_UART(3, 3),
+	UNIPHIER_PERI_RESET_I2C(4, 0),
+	UNIPHIER_PERI_RESET_I2C(5, 1),
+	UNIPHIER_PERI_RESET_I2C(6, 2),
+	UNIPHIER_PERI_RESET_I2C(7, 3),
+	UNIPHIER_PERI_RESET_I2C(8, 4),
+	UNIPHIER_RESET_END,
+};
+
+const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
+	UNIPHIER_PERI_RESET_UART(0, 0),
+	UNIPHIER_PERI_RESET_UART(1, 1),
+	UNIPHIER_PERI_RESET_UART(2, 2),
+	UNIPHIER_PERI_RESET_UART(3, 3),
+	UNIPHIER_PERI_RESET_FI2C(4, 0),
+	UNIPHIER_PERI_RESET_FI2C(5, 1),
+	UNIPHIER_PERI_RESET_FI2C(6, 2),
+	UNIPHIER_PERI_RESET_FI2C(7, 3),
+	UNIPHIER_PERI_RESET_FI2C(8, 4),
+	UNIPHIER_PERI_RESET_FI2C(9, 5),
+	UNIPHIER_PERI_RESET_FI2C(10, 6),
+	UNIPHIER_RESET_END,
+};
+
+/* core implementaton */
+struct uniphier_reset_priv {
+	struct reset_controller_dev rcdev;
+	struct device *dev;
+	struct regmap *regmap;
+	const struct uniphier_reset_data *data;
+};
+
+#define to_uniphier_reset_priv(_rcdev) \
+			container_of(_rcdev, struct uniphier_reset_priv, rcdev)
+
+static int uniphier_reset_update(struct reset_controller_dev *rcdev,
+				 unsigned long id, int assert)
+{
+	struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
+	const struct uniphier_reset_data *p;
+
+	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
+		unsigned int mask, val;
+
+		if (p->id != id)
+			continue;
+
+		mask = BIT(p->bit);
+
+		if (assert)
+			val = mask;
+		else
+			val = ~mask;
+
+		if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
+			val = ~val;
+
+		return regmap_write_bits(priv->regmap, p->reg, mask, val);
+	}
+
+	dev_err(priv->dev, "reset_id=%lu was not handled\n", id);
+	return -EINVAL;
+}
+
+static int uniphier_reset_assert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	return uniphier_reset_update(rcdev, id, 1);
+}
+
+static int uniphier_reset_deassert(struct reset_controller_dev *rcdev,
+				   unsigned long id)
+{
+	return uniphier_reset_update(rcdev, id, 0);
+}
+
+static int uniphier_reset_status(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
+	const struct uniphier_reset_data *p;
+
+	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
+		unsigned int val;
+		int ret, asserted;
+
+		if (p->id != id)
+			continue;
+
+		ret = regmap_read(priv->regmap, p->reg, &val);
+		if (ret)
+			return ret;
+
+		asserted = !!(val & BIT(p->bit));
+
+		if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
+			asserted = !asserted;
+
+		return asserted;
+	}
+
+	dev_err(priv->dev, "reset_id=%lu was not found\n", id);
+	return -EINVAL;
+}
+
+static const struct reset_control_ops uniphier_reset_ops = {
+	.assert = uniphier_reset_assert,
+	.deassert = uniphier_reset_deassert,
+	.status = uniphier_reset_status,
+};
+
+static int uniphier_reset_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct uniphier_reset_priv *priv;
+	const struct uniphier_reset_data *p, *data;
+	struct regmap *regmap;
+	struct device_node *parent;
+	unsigned int nr_resets = 0;
+
+	data = of_device_get_match_data(dev);
+	if (WARN_ON(!data))
+		return -EINVAL;
+
+	parent = of_get_parent(dev->of_node); /* parent should be syscon node */
+	regmap = syscon_node_to_regmap(parent);
+	of_node_put(parent);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to get regmap (error %ld)\n",
+			PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	for (p = data; p->id != UNIPHIER_RESET_ID_END; p++)
+		nr_resets = max(nr_resets, p->id + 1);
+
+	priv->rcdev.ops = &uniphier_reset_ops;
+	priv->rcdev.owner = dev->driver->owner;
+	priv->rcdev.of_node = dev->of_node;
+	priv->rcdev.nr_resets = nr_resets;
+	priv->dev = dev;
+	priv->regmap = regmap;
+	priv->data = data;
+
+	return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
+}
+
+static const struct of_device_id uniphier_reset_match[] = {
+	/* System reset */
+	{
+		.compatible = "socionext,uniphier-sld3-reset",
+		.data = uniphier_sld3_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld4-reset",
+		.data = uniphier_sld3_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-reset",
+		.data = uniphier_pro4_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-reset",
+		.data = uniphier_sld3_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-reset",
+		.data = uniphier_pro5_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-reset",
+		.data = uniphier_pxs2_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-reset",
+		.data = uniphier_ld11_sys_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-reset",
+		.data = uniphier_ld20_sys_reset_data,
+	},
+	/* Media I/O reset */
+	{
+		.compatible = "socionext,uniphier-sld3-mio-reset",
+		.data = uniphier_sld3_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld4-mio-reset",
+		.data = uniphier_sld3_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-mio-reset",
+		.data = uniphier_sld3_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-mio-reset",
+		.data = uniphier_sld3_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-mio-reset",
+		.data = uniphier_pro5_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-mio-reset",
+		.data = uniphier_pro5_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-mio-reset",
+		.data = uniphier_sld3_mio_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-mio-reset",
+		.data = uniphier_pro5_mio_reset_data,
+	},
+	/* Peripheral reset */
+	{
+		.compatible = "socionext,uniphier-ld4-peri-reset",
+		.data = uniphier_ld4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-peri-reset",
+		.data = uniphier_pro4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-peri-reset",
+		.data = uniphier_ld4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-peri-reset",
+		.data = uniphier_pro4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-peri-reset",
+		.data = uniphier_pro4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-peri-reset",
+		.data = uniphier_pro4_peri_reset_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-peri-reset",
+		.data = uniphier_pro4_peri_reset_data,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_reset_match);
+
+static struct platform_driver uniphier_reset_driver = {
+	.probe = uniphier_reset_probe,
+	.driver = {
+		.name = "uniphier-reset",
+		.of_match_table = uniphier_reset_match,
+	},
+};
+module_platform_driver(uniphier_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier Reset Controller Driver");
+MODULE_LICENSE("GPL");

+ 98 - 0
include/dt-bindings/mfd/stm32f4-rcc.h

@@ -0,0 +1,98 @@
+/*
+ * This header provides constants for the STM32F4 RCC IP
+ */
+
+#ifndef _DT_BINDINGS_MFD_STM32F4_RCC_H
+#define _DT_BINDINGS_MFD_STM32F4_RCC_H
+
+/* AHB1 */
+#define STM32F4_RCC_AHB1_GPIOA	0
+#define STM32F4_RCC_AHB1_GPIOB	1
+#define STM32F4_RCC_AHB1_GPIOC	2
+#define STM32F4_RCC_AHB1_GPIOD	3
+#define STM32F4_RCC_AHB1_GPIOE	4
+#define STM32F4_RCC_AHB1_GPIOF	5
+#define STM32F4_RCC_AHB1_GPIOG	6
+#define STM32F4_RCC_AHB1_GPIOH	7
+#define STM32F4_RCC_AHB1_GPIOI	8
+#define STM32F4_RCC_AHB1_GPIOJ	9
+#define STM32F4_RCC_AHB1_GPIOK	10
+#define STM32F4_RCC_AHB1_CRC	12
+#define STM32F4_RCC_AHB1_DMA1	21
+#define STM32F4_RCC_AHB1_DMA2	22
+#define STM32F4_RCC_AHB1_DMA2D	23
+#define STM32F4_RCC_AHB1_ETHMAC	25
+#define STM32F4_RCC_AHB1_OTGHS	29
+
+#define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8))
+#define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit + (0x30 * 8))
+
+
+/* AHB2 */
+#define STM32F4_RCC_AHB2_DCMI	0
+#define STM32F4_RCC_AHB2_CRYP	4
+#define STM32F4_RCC_AHB2_HASH	5
+#define STM32F4_RCC_AHB2_RNG	6
+#define STM32F4_RCC_AHB2_OTGFS	7
+
+#define STM32F4_AHB2_RESET(bit)	(STM32F4_RCC_AHB2_##bit + (0x14 * 8))
+#define STM32F4_AHB2_CLOCK(bit)	(STM32F4_RCC_AHB2_##bit + (0x34 * 8))
+
+/* AHB3 */
+#define STM32F4_RCC_AHB3_FMC	0
+
+#define STM32F4_AHB3_RESET(bit)	(STM32F4_RCC_AHB3_##bit + (0x18 * 8))
+#define STM32F4_AHB3_CLOCK(bit)	(STM32F4_RCC_AHB3_##bit + (0x38 * 8))
+
+/* APB1 */
+#define STM32F4_RCC_APB1_TIM2	0
+#define STM32F4_RCC_APB1_TIM3	1
+#define STM32F4_RCC_APB1_TIM4	2
+#define STM32F4_RCC_APB1_TIM5	3
+#define STM32F4_RCC_APB1_TIM6	4
+#define STM32F4_RCC_APB1_TIM7	5
+#define STM32F4_RCC_APB1_TIM12	6
+#define STM32F4_RCC_APB1_TIM13	7
+#define STM32F4_RCC_APB1_TIM14	8
+#define STM32F4_RCC_APB1_WWDG	11
+#define STM32F4_RCC_APB1_SPI2	14
+#define STM32F4_RCC_APB1_SPI3	15
+#define STM32F4_RCC_APB1_UART2	17
+#define STM32F4_RCC_APB1_UART3	18
+#define STM32F4_RCC_APB1_UART4	19
+#define STM32F4_RCC_APB1_UART5	20
+#define STM32F4_RCC_APB1_I2C1	21
+#define STM32F4_RCC_APB1_I2C2	22
+#define STM32F4_RCC_APB1_I2C3	23
+#define STM32F4_RCC_APB1_CAN1	25
+#define STM32F4_RCC_APB1_CAN2	26
+#define STM32F4_RCC_APB1_PWR	28
+#define STM32F4_RCC_APB1_DAC	29
+#define STM32F4_RCC_APB1_UART7	30
+#define STM32F4_RCC_APB1_UART8	31
+
+#define STM32F4_APB1_RESET(bit)	(STM32F4_RCC_APB1_##bit + (0x20 * 8))
+#define STM32F4_APB1_CLOCK(bit)	(STM32F4_RCC_APB1_##bit + (0x40 * 8))
+
+/* APB2 */
+#define STM32F4_RCC_APB2_TIM1	0
+#define STM32F4_RCC_APB2_TIM8	1
+#define STM32F4_RCC_APB2_USART1	4
+#define STM32F4_RCC_APB2_USART6	5
+#define STM32F4_RCC_APB2_ADC	8
+#define STM32F4_RCC_APB2_SDIO	11
+#define STM32F4_RCC_APB2_SPI1	12
+#define STM32F4_RCC_APB2_SPI4	13
+#define STM32F4_RCC_APB2_SYSCFG	14
+#define STM32F4_RCC_APB2_TIM9	16
+#define STM32F4_RCC_APB2_TIM10	17
+#define STM32F4_RCC_APB2_TIM11	18
+#define STM32F4_RCC_APB2_SPI5	20
+#define STM32F4_RCC_APB2_SPI6	21
+#define STM32F4_RCC_APB2_SAI1	22
+#define STM32F4_RCC_APB2_LTDC	26
+
+#define STM32F4_APB2_RESET(bit)	(STM32F4_RCC_APB2_##bit + (0x24 * 8))
+#define STM32F4_APB2_CLOCK(bit)	(STM32F4_RCC_APB2_##bit + (0x44 * 8))
+
+#endif /* _DT_BINDINGS_MFD_STM32F4_RCC_H */