Re: [PATCH 1/2] reset: add simple reset controller support

2022-01-31 Thread Sascha Hauer
On Mon, Jan 31, 2022 at 08:53:37AM +0100, Ahmad Fatoum wrote:
> Incoming STM32 MCU support will leverage this driver, so port it over
> from Linux v5.16.
> 
> Signed-off-by: Ahmad Fatoum 
> ---
>  drivers/reset/Kconfig  |  17 +++
>  drivers/reset/Makefile |   1 +
>  drivers/reset/reset-simple.c   | 189 +
>  include/linux/reset/reset-simple.h |  45 +++
>  4 files changed, 252 insertions(+)
>  create mode 100644 drivers/reset/reset-simple.c
>  create mode 100644 include/linux/reset/reset-simple.h

Applied, thanks

Sascha


-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


[PATCH 1/2] reset: add simple reset controller support

2022-01-30 Thread Ahmad Fatoum
Incoming STM32 MCU support will leverage this driver, so port it over
from Linux v5.16.

Signed-off-by: Ahmad Fatoum 
---
 drivers/reset/Kconfig  |  17 +++
 drivers/reset/Makefile |   1 +
 drivers/reset/reset-simple.c   | 189 +
 include/linux/reset/reset-simple.h |  45 +++
 4 files changed, 252 insertions(+)
 create mode 100644 drivers/reset/reset-simple.c
 create mode 100644 include/linux/reset/reset-simple.h

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 6c70c1026998..82c85162533d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -15,6 +15,23 @@ menuconfig RESET_CONTROLLER
 
 if RESET_CONTROLLER
 
+config RESET_SIMPLE
+   bool "Simple Reset Controller Driver" if COMPILE_TEST
+   help
+ This enables a simple reset controller driver for reset lines that
+ that can be asserted and deasserted by toggling bits in a contiguous,
+ exclusive register space.
+
+ Currently this driver supports:
+  - Altera 64-Bit SoCFPGAs
+  - ASPEED BMC SoCs
+  - Bitmain BM1880 SoC
+  - Realtek SoCs
+  - RCC reset controller in STM32 MCUs
+  - Allwinner SoCs
+  - SiFive FU740 SoCs
+
+
 config RESET_IMX7
bool "i.MX7 Reset Driver"
default ARCH_IMX7
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index d884a83aa3f7..b4270411fdaf 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_RESET_SIMPLE) += reset-simple.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-simple.c b/drivers/reset/reset-simple.c
new file mode 100644
index ..082956d94dae
--- /dev/null
+++ b/drivers/reset/reset-simple.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Simple Reset Controller Driver
+ *
+ * Copyright (C) 2017 Pengutronix, Philipp Zabel 
+ *
+ * Based on Allwinner SoCs Reset Controller driver
+ *
+ * Copyright 2013 Maxime Ripard
+ *
+ * Maxime Ripard 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static inline struct reset_simple_data *
+to_reset_simple_data(struct reset_controller_dev *rcdev)
+{
+   return container_of(rcdev, struct reset_simple_data, rcdev);
+}
+
+static int reset_simple_update(struct reset_controller_dev *rcdev,
+  unsigned long id, bool assert)
+{
+   struct reset_simple_data *data = to_reset_simple_data(rcdev);
+   int reg_width = sizeof(u32);
+   int bank = id / (reg_width * BITS_PER_BYTE);
+   int offset = id % (reg_width * BITS_PER_BYTE);
+   u32 reg;
+
+   reg = readl(data->membase + (bank * reg_width));
+   if (assert ^ data->active_low)
+   reg |= BIT(offset);
+   else
+   reg &= ~BIT(offset);
+   writel(reg, data->membase + (bank * reg_width));
+
+   return 0;
+}
+
+static int reset_simple_assert(struct reset_controller_dev *rcdev,
+  unsigned long id)
+{
+   return reset_simple_update(rcdev, id, true);
+}
+
+static int reset_simple_deassert(struct reset_controller_dev *rcdev,
+unsigned long id)
+{
+   return reset_simple_update(rcdev, id, false);
+}
+
+static int reset_simple_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+   struct reset_simple_data *data = to_reset_simple_data(rcdev);
+   int ret;
+
+   if (!data->reset_us)
+   return -ENOTSUPP;
+
+   ret = reset_simple_assert(rcdev, id);
+   if (ret)
+   return ret;
+
+   udelay(data->reset_us);
+
+   return reset_simple_deassert(rcdev, id);
+}
+
+static int __maybe_unused reset_simple_status(struct reset_controller_dev 
*rcdev,
+ unsigned long id)
+{
+   struct reset_simple_data *data = to_reset_simple_data(rcdev);
+   int reg_width = sizeof(u32);
+   int bank = id / (reg_width * BITS_PER_BYTE);
+   int offset = id % (reg_width * BITS_PER_BYTE);
+   u32 reg;
+
+   reg = readl(data->membase + (bank * reg_width));
+
+   return !(reg & BIT(offset)) ^ !data->status_active_low;
+}
+
+const struct reset_control_ops reset_simple_ops = {
+   .assert = reset_simple_assert,
+   .deassert   = reset_simple_deassert,
+   .reset  = reset_simple_reset,
+};
+EXPORT_SYMBOL_GPL(reset_simple_ops);
+
+/**
+ * struct reset_simple_devdata - simple reset controller properties
+ * @reg_offset: offset between base address and first reset register.
+ * @nr_resets: number of resets. If not set, default to resource size in bits.
+ * @active_low: if true, bits are cleared to assert the reset.