summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2026-04-02 23:15:26 +0200
committerArnd Bergmann <arnd@arndb.de>2026-04-02 23:15:27 +0200
commitfbf57f25f032bfccbf74eb1898646c9fbd862d2f (patch)
tree493e6d3697077c14ef526959716f944022d36e86
parent62513d2213a6af4640342a8959638cbf2a740c13 (diff)
parentd373605cd514837d8a6de3d00c786d4bae6dbaf8 (diff)
Merge tag 'reset-for-v7.1' of https://git.pengutronix.de/git/pza/linux into soc/drivers
Reset controller updates for v7.1 * Rework the reset core to support firmware nodes, add more fine grained locking, and use guard() helpers. * Change the reset-gpio driver to use firmware nodes. * Add support for the Cix Sky1 SoC reset controller. * Add support for the RZ/G3E SoC to the reset-rzv2h-usb2phy driver and convert it to regmap. Prepare registering a VBUS mux controller. * Replace use of the deprecated register_restart_handler() function in the ath79, intel-gw, lpc18xx, ma35d1, npcm, and sunplus reset drivers. * Combine two allocations into one in the sti/reset-syscfg driver. * Fix the reset-rzg2l-usbphy-ctrl MODULE_AUTHOR email. * Fix the reset_control_rearm() kerneldoc comment. The last commit is a merge of reset-fixes-for-v7.0-2 into reset/next, to solve a merge conflict between commits a9b95ce36de4 ("reset: gpio: add a devlink between reset-gpio and its consumer") and fbffb8c7c7bb ("reset: gpio: fix double free in reset_add_gpio_aux_device() error path"). * tag 'reset-for-v7.1' of https://git.pengutronix.de/git/pza/linux: (35 commits) reset: rzv2h-usb2phy: Add support for VBUS mux controller registration reset: rzv2h-usb2phy: Convert to regmap API dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/G3E USB2PHY reset dt-bindings: reset: renesas,rzv2h-usb2phy: Add '#mux-state-cells' property reset: core: Drop unnecessary double quote reset: rzv2h-usb2phy: Keep PHY clock enabled for entire device lifetime reset: spacemit: k3: Decouple composite reset lines reset: gpio: fix double free in reset_add_gpio_aux_device() error path reset: rzg2l-usbphy-ctrl: Fix malformed MODULE_AUTHOR string reset: sti: kzalloc + kcalloc to kzalloc reset: don't overwrite fwnode_reset_n_cells reset: core: Fix indentation reset: add Sky1 soc reset support dt-bindings: soc: cix: document the syscon on Sky1 SoC reset: gpio: make the driver fwnode-agnostic reset: convert reset core to using firmware nodes reset: convert the core API to using firmware nodes reset: convert of_reset_control_get_count() to using firmware nodes reset: protect struct reset_control with its own mutex reset: protect struct reset_controller_dev with its own mutex ... Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml9
-rw-r--r--Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml42
-rw-r--r--Documentation/driver-api/reset.rst1
-rw-r--r--drivers/reset/Kconfig9
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/core.c506
-rw-r--r--drivers/reset/reset-ath79.c12
-rw-r--r--drivers/reset/reset-gpio.c27
-rw-r--r--drivers/reset/reset-intel-gw.c11
-rw-r--r--drivers/reset/reset-lpc18xx.c12
-rw-r--r--drivers/reset/reset-ma35d1.c11
-rw-r--r--drivers/reset/reset-npcm.c12
-rw-r--r--drivers/reset/reset-rzg2l-usbphy-ctrl.c5
-rw-r--r--drivers/reset/reset-rzv2h-usb2phy.c197
-rw-r--r--drivers/reset/reset-sky1.c367
-rw-r--r--drivers/reset/reset-sunplus.c12
-rw-r--r--drivers/reset/spacemit/reset-spacemit-k3.c60
-rw-r--r--drivers/reset/sti/reset-syscfg.c9
-rw-r--r--include/dt-bindings/reset/cix,sky1-s5-system-control.h163
-rw-r--r--include/dt-bindings/reset/cix,sky1-system-control.h41
-rw-r--r--include/dt-bindings/reset/spacemit,k3-resets.h48
-rw-r--r--include/linux/reset-controller.h21
-rw-r--r--include/linux/reset.h43
23 files changed, 1217 insertions, 402 deletions
diff --git a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml
index c1b800a10b53..66650ef8f772 100644
--- a/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml
@@ -17,7 +17,9 @@ properties:
compatible:
oneOf:
- items:
- - const: renesas,r9a09g056-usb2phy-reset # RZ/V2N
+ - enum:
+ - renesas,r9a09g047-usb2phy-reset # RZ/G3E
+ - renesas,r9a09g056-usb2phy-reset # RZ/V2N
- const: renesas,r9a09g057-usb2phy-reset
- const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
@@ -37,6 +39,9 @@ properties:
'#reset-cells':
const: 0
+ '#mux-state-cells':
+ const: 1
+
required:
- compatible
- reg
@@ -44,6 +49,7 @@ required:
- resets
- power-domains
- '#reset-cells'
+ - '#mux-state-cells'
additionalProperties: false
@@ -58,4 +64,5 @@ examples:
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
+ #mux-state-cells = <1>;
};
diff --git a/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml b/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml
new file mode 100644
index 000000000000..a01a515222c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/cix/cix,sky1-system-control.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cix Sky1 SoC system control register region
+
+maintainers:
+ - Gary Yang <gary.yang@cixtech.com>
+
+description:
+ An wide assortment of registers of the system controller on Sky1 SoC,
+ including resets, usb, wakeup sources and so on.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - cix,sky1-system-control
+ - cix,sky1-s5-system-control
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+ '#reset-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ syscon@4160000 {
+ compatible = "cix,sky1-system-control", "syscon";
+ reg = <0x4160000 0x100>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/driver-api/reset.rst b/Documentation/driver-api/reset.rst
index f773100daaa4..7a6571849664 100644
--- a/Documentation/driver-api/reset.rst
+++ b/Documentation/driver-api/reset.rst
@@ -198,7 +198,6 @@ query the reset line status using reset_control_status().
reset_control_rearm
reset_control_put
of_reset_control_get_count
- of_reset_control_array_get
devm_reset_control_array_get
reset_control_get_count
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 7ce151f6a7e4..2fda1d9622f4 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -257,6 +257,8 @@ config RESET_RZG2L_USBPHY_CTRL
config RESET_RZV2H_USB2PHY
tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver"
depends on ARCH_RENESAS || COMPILE_TEST
+ select AUXILIARY_BUS
+ select REGMAP_MMIO
help
Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC
(and similar SoCs).
@@ -291,6 +293,13 @@ config RESET_SIMPLE
- SiFive FU740 SoCs
- Sophgo SoCs
+config RESET_SKY1
+ bool "Cix Sky1 reset controller"
+ depends on ARCH_CIX || COMPILE_TEST
+ select REGMAP_MMIO
+ help
+ This enables the reset controller for Cix Sky1.
+
config RESET_SOCFPGA
bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
default ARM && ARCH_INTEL_SOCFPGA
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index fc0cc99f8514..d1b8c66e5086 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
obj-$(CONFIG_RESET_RZV2H_USB2PHY) += reset-rzv2h-usb2phy.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
+obj-$(CONFIG_RESET_SKY1) += reset-sky1.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index fceec45c8afc..38e189d04d09 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/export.h>
+#include <linux/fwnode.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
@@ -20,9 +21,11 @@
#include <linux/kref.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/property.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
+#include <linux/srcu.h>
static DEFINE_MUTEX(reset_list_mutex);
static LIST_HEAD(reset_controller_list);
@@ -36,6 +39,7 @@ static DEFINE_IDA(reset_gpio_ida);
* struct reset_control - a reset control
* @rcdev: a pointer to the reset controller device
* this reset control belongs to
+ * @srcu: protects the rcdev pointer from removal during consumer access
* @list: list entry for the rcdev's reset controller list
* @id: ID of the reset controller in the reset
* controller device
@@ -47,9 +51,11 @@ static DEFINE_IDA(reset_gpio_ida);
* @triggered_count: Number of times this reset line has been reset. Currently
* only used for shared resets, which means that the value
* will be either 0 or 1.
+ * @lock: serializes the internals of reset_control_acquire()
*/
struct reset_control {
- struct reset_controller_dev *rcdev;
+ struct reset_controller_dev __rcu *rcdev;
+ struct srcu_struct srcu;
struct list_head list;
unsigned int id;
struct kref refcnt;
@@ -58,6 +64,7 @@ struct reset_control {
bool array;
atomic_t deassert_count;
atomic_t triggered_count;
+ struct mutex lock;
};
/**
@@ -74,14 +81,16 @@ struct reset_control_array {
/**
* struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
- * @of_args: phandle to the reset controller with all the args like GPIO number
+ * @ref_args: Reference to the reset controller with all the args like GPIO number
* @swnode: Software node containing the reference to the GPIO provider
* @list: list entry for the reset_gpio_lookup_list
+ * @adev: Auxiliary device representing the reset controller
*/
struct reset_gpio_lookup {
- struct of_phandle_args of_args;
+ struct fwnode_reference_args ref_args;
struct fwnode_handle *swnode;
struct list_head list;
+ struct auxiliary_device adev;
};
static const char *rcdev_name(struct reset_controller_dev *rcdev)
@@ -89,27 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
if (rcdev->dev)
return dev_name(rcdev->dev);
- if (rcdev->of_node)
- return rcdev->of_node->full_name;
-
- if (rcdev->of_args)
- return rcdev->of_args->np->full_name;
+ if (rcdev->fwnode)
+ return fwnode_get_name(rcdev->fwnode);
return NULL;
}
/**
- * of_reset_simple_xlate - translate reset_spec to the reset line number
+ * fwnode_reset_simple_xlate - translate reset_spec to the reset line number
* @rcdev: a pointer to the reset controller device
- * @reset_spec: reset line specifier as found in the device tree
+ * @reset_spec: reset line specifier as found in firmware
*
- * This static translation function is used by default if of_xlate in
- * :c:type:`reset_controller_dev` is not set. It is useful for all reset
- * controllers with 1:1 mapping, where reset lines can be indexed by number
- * without gaps.
+ * This static translation function is used by default if neither fwnode_xlate
+ * not of_xlate in :c:type:`reset_controller_dev` is not set. It is useful for
+ * all reset controllers with 1:1 mapping, where reset lines can be indexed by
+ * number without gaps.
*/
-static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
- const struct of_phandle_args *reset_spec)
+static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev,
+ const struct fwnode_reference_args *reset_spec)
{
if (reset_spec->args[0] >= rcdev->nr_resets)
return -EINVAL;
@@ -123,33 +129,71 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
*/
int reset_controller_register(struct reset_controller_dev *rcdev)
{
- if (rcdev->of_node && rcdev->of_args)
+ if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate))
return -EINVAL;
- if (!rcdev->of_xlate) {
- rcdev->of_reset_n_cells = 1;
- rcdev->of_xlate = of_reset_simple_xlate;
+ if (rcdev->of_node && !rcdev->fwnode)
+ rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
+
+ if (!rcdev->fwnode) {
+ rcdev->fwnode = dev_fwnode(rcdev->dev);
+ if (!rcdev->fwnode)
+ return -EINVAL;
+ }
+
+ if (rcdev->of_xlate)
+ rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
+
+ if (!rcdev->fwnode_xlate && !rcdev->of_xlate) {
+ rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
+ rcdev->fwnode_reset_n_cells = 1;
}
INIT_LIST_HEAD(&rcdev->reset_control_head);
+ mutex_init(&rcdev->lock);
+
+ guard(mutex)(&reset_list_mutex);
- mutex_lock(&reset_list_mutex);
list_add(&rcdev->list, &reset_controller_list);
- mutex_unlock(&reset_list_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(reset_controller_register);
+static void reset_controller_remove(struct reset_controller_dev *rcdev,
+ struct reset_control *rstc)
+{
+ lockdep_assert_held(&rcdev->lock);
+
+ list_del(&rstc->list);
+ module_put(rcdev->owner);
+ put_device(rcdev->dev);
+}
+
/**
* reset_controller_unregister - unregister a reset controller device
* @rcdev: a pointer to the reset controller device
*/
void reset_controller_unregister(struct reset_controller_dev *rcdev)
{
- mutex_lock(&reset_list_mutex);
- list_del(&rcdev->list);
- mutex_unlock(&reset_list_mutex);
+ struct reset_control *rstc, *pos;
+
+ scoped_guard(mutex, &reset_list_mutex)
+ list_del(&rcdev->list);
+
+ scoped_guard(mutex, &rcdev->lock) {
+ /*
+ * Numb but don't free the remaining reset control handles that are
+ * still held by consumers.
+ */
+ list_for_each_entry_safe(rstc, pos, &rcdev->reset_control_head, list) {
+ rcu_assign_pointer(rstc->rcdev, NULL);
+ synchronize_srcu(&rstc->srcu);
+ reset_controller_remove(rcdev, rstc);
+ }
+ }
+
+ mutex_destroy(&rcdev->lock);
}
EXPORT_SYMBOL_GPL(reset_controller_unregister);
@@ -326,6 +370,7 @@ static inline bool reset_control_is_array(struct reset_control *rstc)
*/
int reset_control_reset(struct reset_control *rstc)
{
+ struct reset_controller_dev *rcdev;
int ret;
if (!rstc)
@@ -337,7 +382,13 @@ int reset_control_reset(struct reset_control *rstc)
if (reset_control_is_array(rstc))
return reset_control_array_reset(rstc_to_array(rstc));
- if (!rstc->rcdev->ops->reset)
+ guard(srcu)(&rstc->srcu);
+
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ return -ENODEV;
+
+ if (!rcdev->ops->reset)
return -ENOTSUPP;
if (rstc->shared) {
@@ -351,7 +402,7 @@ int reset_control_reset(struct reset_control *rstc)
return -EPERM;
}
- ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
+ ret = rcdev->ops->reset(rcdev, rstc->id);
if (rstc->shared && ret)
atomic_dec(&rstc->triggered_count);
@@ -384,7 +435,7 @@ int reset_control_bulk_reset(int num_rstcs,
EXPORT_SYMBOL_GPL(reset_control_bulk_reset);
/**
- * reset_control_rearm - allow shared reset line to be re-triggered"
+ * reset_control_rearm - allow shared reset line to be re-triggered
* @rstc: reset controller
*
* On a shared reset line the actual reset pulse is only triggered once for the
@@ -441,6 +492,8 @@ EXPORT_SYMBOL_GPL(reset_control_rearm);
*/
int reset_control_assert(struct reset_control *rstc)
{
+ struct reset_controller_dev *rcdev;
+
if (!rstc)
return 0;
@@ -450,6 +503,12 @@ int reset_control_assert(struct reset_control *rstc)
if (reset_control_is_array(rstc))
return reset_control_array_assert(rstc_to_array(rstc));
+ guard(srcu)(&rstc->srcu);
+
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ return -ENODEV;
+
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
return -EINVAL;
@@ -464,7 +523,7 @@ int reset_control_assert(struct reset_control *rstc)
* Shared reset controls allow the reset line to be in any state
* after this call, so doing nothing is a valid option.
*/
- if (!rstc->rcdev->ops->assert)
+ if (!rcdev->ops->assert)
return 0;
} else {
/*
@@ -472,17 +531,17 @@ int reset_control_assert(struct reset_control *rstc)
* is no way to guarantee that the reset line is asserted after
* this call.
*/
- if (!rstc->rcdev->ops->assert)
+ if (!rcdev->ops->assert)
return -ENOTSUPP;
if (!rstc->acquired) {
WARN(1, "reset %s (ID: %u) is not acquired\n",
- rcdev_name(rstc->rcdev), rstc->id);
+ rcdev_name(rcdev), rstc->id);
return -EPERM;
}
}
- return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
+ return rcdev->ops->assert(rcdev, rstc->id);
}
EXPORT_SYMBOL_GPL(reset_control_assert);
@@ -529,6 +588,8 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_assert);
*/
int reset_control_deassert(struct reset_control *rstc)
{
+ struct reset_controller_dev *rcdev;
+
if (!rstc)
return 0;
@@ -538,6 +599,12 @@ int reset_control_deassert(struct reset_control *rstc)
if (reset_control_is_array(rstc))
return reset_control_array_deassert(rstc_to_array(rstc));
+ guard(srcu)(&rstc->srcu);
+
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ return -ENODEV;
+
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
return -EINVAL;
@@ -547,7 +614,7 @@ int reset_control_deassert(struct reset_control *rstc)
} else {
if (!rstc->acquired) {
WARN(1, "reset %s (ID: %u) is not acquired\n",
- rcdev_name(rstc->rcdev), rstc->id);
+ rcdev_name(rcdev), rstc->id);
return -EPERM;
}
}
@@ -559,10 +626,10 @@ int reset_control_deassert(struct reset_control *rstc)
* case, the reset controller driver should implement .deassert() and
* return -ENOTSUPP.
*/
- if (!rstc->rcdev->ops->deassert)
+ if (!rcdev->ops->deassert)
return 0;
- return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
+ return rcdev->ops->deassert(rcdev, rstc->id);
}
EXPORT_SYMBOL_GPL(reset_control_deassert);
@@ -604,14 +671,22 @@ EXPORT_SYMBOL_GPL(reset_control_bulk_deassert);
*/
int reset_control_status(struct reset_control *rstc)
{
+ struct reset_controller_dev *rcdev;
+
if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc))
return -EINVAL;
- if (rstc->rcdev->ops->status)
- return rstc->rcdev->ops->status(rstc->rcdev, rstc->id);
+ guard(srcu)(&rstc->srcu);
+
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ return -ENODEV;
+
+ if (rcdev->ops->status)
+ return rcdev->ops->status(rcdev, rstc->id);
return -ENOTSUPP;
}
@@ -639,6 +714,7 @@ EXPORT_SYMBOL_GPL(reset_control_status);
*/
int reset_control_acquire(struct reset_control *rstc)
{
+ struct reset_controller_dev *rcdev;
struct reset_control *rc;
if (!rstc)
@@ -650,25 +726,28 @@ int reset_control_acquire(struct reset_control *rstc)
if (reset_control_is_array(rstc))
return reset_control_array_acquire(rstc_to_array(rstc));
- mutex_lock(&reset_list_mutex);
+ guard(mutex)(&rstc->lock);
- if (rstc->acquired) {
- mutex_unlock(&reset_list_mutex);
+ if (rstc->acquired)
return 0;
- }
- list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) {
- if (rstc != rc && rstc->id == rc->id) {
- if (rc->acquired) {
- mutex_unlock(&reset_list_mutex);
- return -EBUSY;
+ guard(srcu)(&rstc->srcu);
+
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ return -ENODEV;
+
+ scoped_guard(mutex, &rcdev->lock) {
+ list_for_each_entry(rc, &rcdev->reset_control_head, list) {
+ if (rstc != rc && rstc->id == rc->id) {
+ if (rc->acquired)
+ return -EBUSY;
}
}
}
rstc->acquired = true;
- mutex_unlock(&reset_list_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(reset_control_acquire);
@@ -752,8 +831,9 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev,
bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED;
bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED;
struct reset_control *rstc;
+ int ret;
- lockdep_assert_held(&reset_list_mutex);
+ lockdep_assert_held(&rcdev->lock);
/* Expect callers to filter out OPTIONAL and DEASSERTED bits */
if (WARN_ON(flags & ~(RESET_CONTROL_FLAGS_BIT_SHARED |
@@ -782,15 +862,23 @@ __reset_control_get_internal(struct reset_controller_dev *rcdev,
if (!rstc)
return ERR_PTR(-ENOMEM);
+ ret = init_srcu_struct(&rstc->srcu);
+ if (ret) {
+ kfree(rstc);
+ return ERR_PTR(ret);
+ }
+
if (!try_module_get(rcdev->owner)) {
+ cleanup_srcu_struct(&rstc->srcu);
kfree(rstc);
return ERR_PTR(-ENODEV);
}
- rstc->rcdev = rcdev;
+ rcu_assign_pointer(rstc->rcdev, rcdev);
list_add(&rstc->list, &rcdev->reset_control_head);
rstc->id = index;
kref_init(&rstc->refcnt);
+ mutex_init(&rstc->lock);
rstc->acquired = acquired;
rstc->shared = shared;
get_device(rcdev->dev);
@@ -802,77 +890,133 @@ static void __reset_control_release(struct kref *kref)
{
struct reset_control *rstc = container_of(kref, struct reset_control,
refcnt);
+ struct reset_controller_dev *rcdev;
- lockdep_assert_held(&reset_list_mutex);
+ lockdep_assert_held(&rstc->srcu);
- module_put(rstc->rcdev->owner);
+ rcdev = rcu_replace_pointer(rstc->rcdev, NULL, true);
+ if (rcdev) {
+ lockdep_assert_held(&rcdev->lock);
+ reset_controller_remove(rcdev, rstc);
+ }
- list_del(&rstc->list);
- put_device(rstc->rcdev->dev);
- kfree(rstc);
+ mutex_destroy(&rstc->lock);
}
-static void __reset_control_put_internal(struct reset_control *rstc)
+static void reset_control_put_internal(struct reset_control *rstc)
{
- lockdep_assert_held(&reset_list_mutex);
+ struct reset_controller_dev *rcdev;
+ int ret = 0;
if (IS_ERR_OR_NULL(rstc))
return;
- kref_put(&rstc->refcnt, __reset_control_release);
+ scoped_guard(srcu, &rstc->srcu) {
+ rcdev = srcu_dereference(rstc->rcdev, &rstc->srcu);
+ if (!rcdev)
+ /* Already released. */
+ return;
+
+ guard(mutex)(&rcdev->lock);
+ ret = kref_put(&rstc->refcnt, __reset_control_release);
+ }
+
+ if (ret) {
+ synchronize_srcu(&rstc->srcu);
+ cleanup_srcu_struct(&rstc->srcu);
+ kfree(rstc);
+ }
}
static void reset_gpio_aux_device_release(struct device *dev)
{
- struct auxiliary_device *adev = to_auxiliary_dev(dev);
-
- kfree(adev);
+ WARN(1, "reset-gpio device %s should never have been removed", dev_name(dev));
}
-static int reset_add_gpio_aux_device(struct device *parent,
- struct fwnode_handle *swnode,
- int id, void *pdata)
+static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
+ struct device *parent)
{
- struct auxiliary_device *adev;
- int ret;
+ struct auxiliary_device *adev = &rgpio_dev->adev;
+ int ret, id;
- adev = kzalloc_obj(*adev);
- if (!adev)
+ id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
+ if (id < 0)
return -ENOMEM;
adev->id = id;
adev->name = "gpio";
adev->dev.parent = parent;
- adev->dev.platform_data = pdata;
+ adev->dev.platform_data = &rgpio_dev->ref_args;
adev->dev.release = reset_gpio_aux_device_release;
- device_set_node(&adev->dev, swnode);
+ device_set_node(&adev->dev, rgpio_dev->swnode);
ret = auxiliary_device_init(adev);
if (ret) {
- kfree(adev);
+ ida_free(&reset_gpio_ida, id);
return ret;
}
ret = __auxiliary_device_add(adev, "reset");
if (ret) {
auxiliary_device_uninit(adev);
- kfree(adev);
+ ida_free(&reset_gpio_ida, id);
return ret;
}
- return ret;
+ return 0;
+}
+
+static void reset_gpio_add_devlink(struct fwnode_handle *fwnode,
+ struct reset_gpio_lookup *rgpio_dev)
+{
+ struct device *consumer;
+
+ /*
+ * We must use get_dev_from_fwnode() and not ref_find_device_by_node()
+ * because the latter only considers the platform bus while we want to
+ * get consumers of any kind that can be associated with firmware
+ * nodes: auxiliary, soundwire, etc.
+ */
+ consumer = get_dev_from_fwnode(fwnode);
+ if (consumer) {
+ if (!device_link_add(consumer, &rgpio_dev->adev.dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER))
+ pr_warn("Failed to create a device link between reset-gpio and its consumer");
+
+ put_device(consumer);
+ }
+ /*
+ * else { }
+ *
+ * TODO: If ever there's a case where we need to support shared
+ * reset-gpios retrieved from a device node for which there's no
+ * device present yet, this is where we'd set up a notifier waiting
+ * for the device to appear in the system. This would be a lot of code
+ * that would go unused for now so let's cross that bridge when and if
+ * we get there.
+ */
+}
+
+/* TODO: move it out into drivers/base/ */
+static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left,
+ const struct fwnode_reference_args *right)
+{
+ return left->fwnode == right->fwnode && left->nargs == right->nargs &&
+ !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs);
}
/*
- * @args: phandle to the GPIO provider with all the args like GPIO number
+ * @np: OF-node associated with the consumer
+ * @args: Reference to the GPIO provider with all the args like GPIO number
*/
-static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
+static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode,
+ const struct fwnode_reference_args *args)
{
struct property_entry properties[3] = { };
- unsigned int offset, of_flags, lflags;
+ unsigned int offset, flags, lflags;
struct reset_gpio_lookup *rgpio_dev;
struct device *parent;
- int id, ret, prop = 0;
+ int ret, prop = 0;
/*
* Currently only #gpio-cells=2 is supported with the meaning of:
@@ -880,7 +1024,7 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
* args[1]: GPIO flags
* TODO: Handle other cases.
*/
- if (args->args_count != 2)
+ if (args->nargs != 2)
return -ENOENT;
/*
@@ -891,7 +1035,7 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
lockdep_assert_not_held(&reset_list_mutex);
offset = args->args[0];
- of_flags = args->args[1];
+ flags = args->args[1];
/*
* Later we map GPIO flags between OF and Linux, however not all
@@ -901,90 +1045,89 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
* FIXME: Find a better way of translating OF flags to GPIO lookup
* flags.
*/
- if (of_flags > GPIO_ACTIVE_LOW) {
+ if (flags > GPIO_ACTIVE_LOW) {
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
- of_flags, offset);
+ flags, offset);
return -EINVAL;
}
struct gpio_device *gdev __free(gpio_device_put) =
- gpio_device_find_by_fwnode(of_fwnode_handle(args->np));
+ gpio_device_find_by_fwnode(args->fwnode);
if (!gdev)
return -EPROBE_DEFER;
guard(mutex)(&reset_gpio_lookup_mutex);
list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
- if (args->np == rgpio_dev->of_args.np) {
- if (of_phandle_args_equal(args, &rgpio_dev->of_args))
- return 0; /* Already on the list, done */
+ if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) {
+ /*
+ * Already on the list, create the device link
+ * and stop here.
+ */
+ reset_gpio_add_devlink(fwnode, rgpio_dev);
+ return 0;
}
}
- lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
+ lflags = GPIO_PERSISTENT | (flags & GPIO_ACTIVE_LOW);
parent = gpio_device_to_device(gdev);
properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio");
properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
- id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
- if (id < 0)
- return id;
-
/* Not freed on success, because it is persisent subsystem data. */
rgpio_dev = kzalloc_obj(*rgpio_dev);
- if (!rgpio_dev) {
- ret = -ENOMEM;
- goto err_ida_free;
- }
+ if (!rgpio_dev)
+ return -ENOMEM;
- rgpio_dev->of_args = *args;
+ rgpio_dev->ref_args = *args;
/*
- * We keep the device_node reference, but of_args.np is put at the end
- * of __of_reset_control_get(), so get it one more time.
+ * We keep the fwnode_handle reference, but ref_args.fwnode is put at
+ * the end of __fwnode_reset_control_get(), so get it one more time.
* Hold reference as long as rgpio_dev memory is valid.
*/
- of_node_get(rgpio_dev->of_args.np);
+ fwnode_handle_get(rgpio_dev->ref_args.fwnode);
rgpio_dev->swnode = fwnode_create_software_node(properties, NULL);
if (IS_ERR(rgpio_dev->swnode)) {
ret = PTR_ERR(rgpio_dev->swnode);
- goto err_put_of_node;
+ goto err_put_fwnode;
}
- ret = reset_add_gpio_aux_device(parent, rgpio_dev->swnode, id,
- &rgpio_dev->of_args);
+ ret = reset_create_gpio_aux_device(rgpio_dev, parent);
if (ret)
goto err_del_swnode;
+ reset_gpio_add_devlink(fwnode, rgpio_dev);
list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
return 0;
err_del_swnode:
fwnode_remove_software_node(rgpio_dev->swnode);
-err_put_of_node:
- of_node_put(rgpio_dev->of_args.np);
+err_put_fwnode:
+ fwnode_handle_put(rgpio_dev->ref_args.fwnode);
kfree(rgpio_dev);
-err_ida_free:
- ida_free(&reset_gpio_ida, id);
return ret;
}
-static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
- bool gpio_fallback)
+static struct reset_controller_dev *
+__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback)
{
+ struct fwnode_reference_args *rc_args;
struct reset_controller_dev *rcdev;
lockdep_assert_held(&reset_list_mutex);
list_for_each_entry(rcdev, &reset_controller_list, list) {
- if (gpio_fallback) {
- if (rcdev->of_args && of_phandle_args_equal(args,
- rcdev->of_args))
+ if (gpio_fallback && rcdev->dev &&
+ device_is_compatible(rcdev->dev, "reset-gpio")) {
+ rc_args = dev_get_platdata(rcdev->dev);
+
+ if (fwnode_reference_args_equal(args, rc_args))
return rcdev;
} else {
- if (args->np == rcdev->of_node)
+ if (args->fwnode == rcdev->fwnode)
return rcdev;
}
}
@@ -993,31 +1136,31 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a
}
struct reset_control *
-__of_reset_control_get(struct device_node *node, const char *id, int index,
- enum reset_control_flags flags)
+__fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int index,
+ enum reset_control_flags flags)
{
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
bool gpio_fallback = false;
- struct reset_control *rstc;
+ struct reset_control *rstc = ERR_PTR(-EINVAL);
struct reset_controller_dev *rcdev;
- struct of_phandle_args args;
- int rstc_id;
+ struct fwnode_reference_args args;
+ struct of_phandle_args of_args;
+ int rstc_id = -EINVAL;
int ret;
- if (!node)
+ if (!fwnode)
return ERR_PTR(-EINVAL);
if (id) {
- index = of_property_match_string(node,
- "reset-names", id);
+ index = fwnode_property_match_string(fwnode, "reset-names", id);
if (index == -EILSEQ)
return ERR_PTR(index);
if (index < 0)
return optional ? NULL : ERR_PTR(-ENOENT);
}
- ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
- index, &args);
+ ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells",
+ 0, index, &args);
if (ret == -EINVAL)
return ERR_PTR(ret);
if (ret) {
@@ -1028,51 +1171,65 @@ __of_reset_control_get(struct device_node *node, const char *id, int index,
* There can be only one reset-gpio for regular devices, so
* don't bother with the "reset-gpios" phandle index.
*/
- ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
- 0, &args);
+ ret = fwnode_property_get_reference_args(fwnode, "reset-gpios",
+ "#gpio-cells", 0, 0, &args);
if (ret)
return optional ? NULL : ERR_PTR(ret);
gpio_fallback = true;
- ret = __reset_add_reset_gpio_device(&args);
+ ret = __reset_add_reset_gpio_device(fwnode, &args);
if (ret) {
- rstc = ERR_PTR(ret);
- goto out_put;
+ fwnode_handle_put(args.fwnode);
+ return ERR_PTR(ret);
}
}
- mutex_lock(&reset_list_mutex);
+ guard(mutex)(&reset_list_mutex);
+
rcdev = __reset_find_rcdev(&args, gpio_fallback);
if (!rcdev) {
rstc = ERR_PTR(-EPROBE_DEFER);
- goto out_unlock;
+ goto out_put;
}
- if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
+ if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
rstc = ERR_PTR(-EINVAL);
- goto out_unlock;
+ goto out_put;
}
- rstc_id = rcdev->of_xlate(rcdev, &args);
+ if (rcdev->of_xlate && is_of_node(fwnode)) {
+ ret = of_parse_phandle_with_args(to_of_node(fwnode),
+ gpio_fallback ? "reset-gpios" : "resets",
+ gpio_fallback ? "#gpio-cells" : "#reset-cells",
+ gpio_fallback ? 0 : index,
+ &of_args);
+ if (ret) {
+ rstc = ERR_PTR(ret);
+ goto out_put;
+ }
+
+ rstc_id = rcdev->of_xlate(rcdev, &of_args);
+ of_node_put(of_args.np);
+ } else if (rcdev->fwnode_xlate) {
+ rstc_id = rcdev->fwnode_xlate(rcdev, &args);
+ }
if (rstc_id < 0) {
rstc = ERR_PTR(rstc_id);
- goto out_unlock;
+ goto out_put;
}
flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
- /* reset_list_mutex also protects the rcdev's reset_control list */
- rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
+ scoped_guard(mutex, &rcdev->lock)
+ rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
-out_unlock:
- mutex_unlock(&reset_list_mutex);
out_put:
- of_node_put(args.np);
+ fwnode_handle_put(args.fwnode);
return rstc;
}
-EXPORT_SYMBOL_GPL(__of_reset_control_get);
+EXPORT_SYMBOL_GPL(__fwnode_reset_control_get);
struct reset_control *__reset_control_get(struct device *dev, const char *id,
int index, enum reset_control_flags flags)
@@ -1080,12 +1237,13 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
bool shared = flags & RESET_CONTROL_FLAGS_BIT_SHARED;
bool acquired = flags & RESET_CONTROL_FLAGS_BIT_ACQUIRED;
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
if (WARN_ON(shared && acquired))
return ERR_PTR(-EINVAL);
- if (dev->of_node)
- return __of_reset_control_get(dev->of_node, id, index, flags);
+ if (fwnode)
+ return __fwnode_reset_control_get(fwnode, id, index, flags);
return optional ? NULL : ERR_PTR(-ENOENT);
}
@@ -1108,10 +1266,9 @@ int __reset_control_bulk_get(struct device *dev, int num_rstcs,
return 0;
err:
- mutex_lock(&reset_list_mutex);
while (i--)
- __reset_control_put_internal(rstcs[i].rstc);
- mutex_unlock(&reset_list_mutex);
+ reset_control_put_internal(rstcs[i].rstc);
+
return ret;
}
EXPORT_SYMBOL_GPL(__reset_control_bulk_get);
@@ -1120,10 +1277,8 @@ static void reset_control_array_put(struct reset_control_array *resets)
{
int i;
- mutex_lock(&reset_list_mutex);
for (i = 0; i < resets->num_rstcs; i++)
- __reset_control_put_internal(resets->rstc[i]);
- mutex_unlock(&reset_list_mutex);
+ reset_control_put_internal(resets->rstc[i]);
kfree(resets);
}
@@ -1141,9 +1296,7 @@ void reset_control_put(struct reset_control *rstc)
return;
}
- mutex_lock(&reset_list_mutex);
- __reset_control_put_internal(rstc);
- mutex_unlock(&reset_list_mutex);
+ reset_control_put_internal(rstc);
}
EXPORT_SYMBOL_GPL(reset_control_put);
@@ -1154,10 +1307,8 @@ EXPORT_SYMBOL_GPL(reset_control_put);
*/
void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
{
- mutex_lock(&reset_list_mutex);
while (num_rstcs--)
- __reset_control_put_internal(rstcs[num_rstcs].rstc);
- mutex_unlock(&reset_list_mutex);
+ reset_control_put_internal(rstcs[num_rstcs].rstc);
}
EXPORT_SYMBOL_GPL(reset_control_bulk_put);
@@ -1318,21 +1469,35 @@ EXPORT_SYMBOL_GPL(__device_reset);
*/
/**
- * of_reset_control_get_count - Count number of resets available with a device
+ * fwnode_reset_control_get_count - Count number of resets available with a device
*
- * @node: device node that contains 'resets'.
+ * @fwnode: firmware node that contains 'resets'.
*
* Returns positive reset count on success, or error number on failure and
* on count being zero.
*/
-static int of_reset_control_get_count(struct device_node *node)
+static int fwnode_reset_control_get_count(struct fwnode_handle *fwnode)
{
- int count;
+ struct fwnode_reference_args args;
+ int count = 0, ret;
- if (!node)
+ if (!fwnode)
return -EINVAL;
- count = of_count_phandle_with_args(node, "resets", "#reset-cells");
+ for (;;) {
+ ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells",
+ 0, count, &args);
+ if (ret) {
+ if (ret == -ENOENT)
+ break;
+
+ return ret;
+ }
+
+ fwnode_handle_put(args.fwnode);
+ count++;
+ }
+
if (count == 0)
count = -ENOENT;
@@ -1340,23 +1505,24 @@ static int of_reset_control_get_count(struct device_node *node)
}
/**
- * of_reset_control_array_get - Get a list of reset controls using
- * device node.
+ * fwnode_reset_control_array_get - Get a list of reset controls using
+ * a firmware node.
*
- * @np: device node for the device that requests the reset controls array
+ * @fwnode: firmware node for the device that requests the reset controls array
* @flags: whether reset controls are shared, optional, acquired
*
* Returns pointer to allocated reset_control on success or error on failure
*/
struct reset_control *
-of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags)
+fwnode_reset_control_array_get(struct fwnode_handle *fwnode,
+ enum reset_control_flags flags)
{
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
struct reset_control_array *resets;
struct reset_control *rstc;
int num, i;
- num = of_reset_control_get_count(np);
+ num = fwnode_reset_control_get_count(fwnode);
if (num < 0)
return optional ? NULL : ERR_PTR(num);
@@ -1366,7 +1532,7 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag
resets->num_rstcs = num;
for (i = 0; i < num; i++) {
- rstc = __of_reset_control_get(np, NULL, i, flags);
+ rstc = __fwnode_reset_control_get(fwnode, NULL, i, flags);
if (IS_ERR(rstc))
goto err_rst;
resets->rstc[i] = rstc;
@@ -1376,16 +1542,14 @@ of_reset_control_array_get(struct device_node *np, enum reset_control_flags flag
return &resets->base;
err_rst:
- mutex_lock(&reset_list_mutex);
while (--i >= 0)
- __reset_control_put_internal(resets->rstc[i]);
- mutex_unlock(&reset_list_mutex);
+ reset_control_put_internal(resets->rstc[i]);
kfree(resets);
return rstc;
}
-EXPORT_SYMBOL_GPL(of_reset_control_array_get);
+EXPORT_SYMBOL_GPL(fwnode_reset_control_array_get);
/**
* devm_reset_control_array_get - Resource managed reset control array get
@@ -1409,7 +1573,7 @@ devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags)
if (!ptr)
return ERR_PTR(-ENOMEM);
- rstc = of_reset_control_array_get(dev->of_node, flags);
+ rstc = fwnode_reset_control_array_get(dev_fwnode(dev), flags);
if (IS_ERR_OR_NULL(rstc)) {
devres_free(ptr);
return rstc;
@@ -1432,8 +1596,10 @@ EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
*/
int reset_control_get_count(struct device *dev)
{
- if (dev->of_node)
- return of_reset_control_get_count(dev->of_node);
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+
+ if (fwnode)
+ return fwnode_reset_control_get_count(fwnode);
return -ENOENT;
}
diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
index b5d620132052..4c4e69eb32bb 100644
--- a/drivers/reset/reset-ath79.c
+++ b/drivers/reset/reset-ath79.c
@@ -15,7 +15,6 @@
struct ath79_reset {
struct reset_controller_dev rcdev;
- struct notifier_block restart_nb;
void __iomem *base;
spinlock_t lock;
};
@@ -72,11 +71,9 @@ static const struct reset_control_ops ath79_reset_ops = {
.status = ath79_reset_status,
};
-static int ath79_reset_restart_handler(struct notifier_block *nb,
- unsigned long action, void *data)
+static int ath79_reset_restart_handler(struct sys_off_data *data)
{
- struct ath79_reset *ath79_reset =
- container_of(nb, struct ath79_reset, restart_nb);
+ struct ath79_reset *ath79_reset = data->cb_data;
ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET);
@@ -108,10 +105,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
if (err)
return err;
- ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler;
- ath79_reset->restart_nb.priority = 128;
-
- err = register_restart_handler(&ath79_reset->restart_nb);
+ err = devm_register_restart_handler(&pdev->dev, ath79_reset_restart_handler, ath79_reset);
if (err)
dev_warn(&pdev->dev, "Failed to register restart handler\n");
diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c
index 0a1610d9e78a..26aa2c3a2e68 100644
--- a/drivers/reset/reset-gpio.c
+++ b/drivers/reset/reset-gpio.c
@@ -4,7 +4,7 @@
#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/reset-controller.h>
struct reset_gpio_priv {
@@ -46,34 +46,22 @@ static const struct reset_control_ops reset_gpio_ops = {
.status = reset_gpio_status,
};
-static int reset_gpio_of_xlate(struct reset_controller_dev *rcdev,
- const struct of_phandle_args *reset_spec)
+static int reset_gpio_fwnode_xlate(struct reset_controller_dev *rcdev,
+ const struct fwnode_reference_args *reset_spec)
{
return reset_spec->args[0];
}
-static void reset_gpio_of_node_put(void *data)
-{
- of_node_put(data);
-}
-
static int reset_gpio_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct device *dev = &adev->dev;
- struct of_phandle_args *platdata = dev_get_platdata(dev);
struct reset_gpio_priv *priv;
- int ret;
-
- if (!platdata)
- return -EINVAL;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- auxiliary_set_drvdata(adev, &priv->rc);
-
priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(priv->reset))
return dev_err_probe(dev, PTR_ERR(priv->reset),
@@ -82,15 +70,10 @@ static int reset_gpio_probe(struct auxiliary_device *adev,
priv->rc.ops = &reset_gpio_ops;
priv->rc.owner = THIS_MODULE;
priv->rc.dev = dev;
- priv->rc.of_args = platdata;
- ret = devm_add_action_or_reset(dev, reset_gpio_of_node_put,
- priv->rc.of_node);
- if (ret)
- return ret;
/* Cells to match GPIO specifier, but it's not really used */
- priv->rc.of_reset_n_cells = 2;
- priv->rc.of_xlate = reset_gpio_of_xlate;
+ priv->rc.fwnode_reset_n_cells = 2;
+ priv->rc.fwnode_xlate = reset_gpio_fwnode_xlate;
priv->rc.nr_resets = 1;
return devm_reset_controller_register(dev, &priv->rc);
diff --git a/drivers/reset/reset-intel-gw.c b/drivers/reset/reset-intel-gw.c
index a5ce3350cb5e..0db64cc8a282 100644
--- a/drivers/reset/reset-intel-gw.c
+++ b/drivers/reset/reset-intel-gw.c
@@ -28,7 +28,6 @@ struct intel_reset_soc {
struct intel_reset_data {
struct reset_controller_dev rcdev;
- struct notifier_block restart_nb;
const struct intel_reset_soc *soc_data;
struct regmap *regmap;
struct device *dev;
@@ -153,12 +152,10 @@ static int intel_reset_xlate(struct reset_controller_dev *rcdev,
return id;
}
-static int intel_reset_restart_handler(struct notifier_block *nb,
- unsigned long action, void *data)
+static int intel_reset_restart_handler(struct sys_off_data *data)
{
- struct intel_reset_data *reset_data;
+ struct intel_reset_data *reset_data = data->cb_data;
- reset_data = container_of(nb, struct intel_reset_data, restart_nb);
intel_assert_device(&reset_data->rcdev, reset_data->reboot_id);
return NOTIFY_DONE;
@@ -215,9 +212,7 @@ static int intel_reset_probe(struct platform_device *pdev)
if (data->soc_data->legacy)
data->reboot_id |= FIELD_PREP(STAT_BIT_OFFSET_MASK, rb_id[2]);
- data->restart_nb.notifier_call = intel_reset_restart_handler;
- data->restart_nb.priority = 128;
- register_restart_handler(&data->restart_nb);
+ devm_register_restart_handler(&pdev->dev, intel_reset_restart_handler, data);
return 0;
}
diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
index e42b2f24a93d..8ac9f237e1ce 100644
--- a/drivers/reset/reset-lpc18xx.c
+++ b/drivers/reset/reset-lpc18xx.c
@@ -31,7 +31,6 @@
struct lpc18xx_rgu_data {
struct reset_controller_dev rcdev;
- struct notifier_block restart_nb;
struct clk *clk_delay;
struct clk *clk_reg;
void __iomem *base;
@@ -41,11 +40,9 @@ struct lpc18xx_rgu_data {
#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
-static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
- void *cmd)
+static int lpc18xx_rgu_restart(struct sys_off_data *data)
{
- struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
- restart_nb);
+ struct lpc18xx_rgu_data *rc = data->cb_data;
writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
mdelay(2000);
@@ -178,9 +175,8 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(&pdev->dev, ret, "unable to register device\n");
- rc->restart_nb.priority = 192,
- rc->restart_nb.notifier_call = lpc18xx_rgu_restart,
- ret = register_restart_handler(&rc->restart_nb);
+ ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192,
+ lpc18xx_rgu_restart, rc);
if (ret)
dev_warn(&pdev->dev, "failed to register restart handler\n");
diff --git a/drivers/reset/reset-ma35d1.c b/drivers/reset/reset-ma35d1.c
index 54e53863c98a..4ee901f00132 100644
--- a/drivers/reset/reset-ma35d1.c
+++ b/drivers/reset/reset-ma35d1.c
@@ -19,7 +19,6 @@
struct ma35d1_reset_data {
struct reset_controller_dev rcdev;
- struct notifier_block restart_handler;
void __iomem *base;
/* protect registers against concurrent read-modify-write */
spinlock_t lock;
@@ -125,10 +124,9 @@ static const struct {
[MA35D1_RESET_SSPCC] = {0x2C, 31}
};
-static int ma35d1_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd)
+static int ma35d1_restart_handler(struct sys_off_data *sys_off_data)
{
- struct ma35d1_reset_data *data =
- container_of(this, struct ma35d1_reset_data, restart_handler);
+ struct ma35d1_reset_data *data = sys_off_data->cb_data;
u32 id = MA35D1_RESET_CHIP;
writel_relaxed(BIT(ma35d1_reset_map[id].bit),
@@ -213,11 +211,10 @@ static int ma35d1_reset_probe(struct platform_device *pdev)
reset_data->rcdev.nr_resets = MA35D1_RESET_COUNT;
reset_data->rcdev.ops = &ma35d1_reset_ops;
reset_data->rcdev.of_node = dev->of_node;
- reset_data->restart_handler.notifier_call = ma35d1_restart_handler;
- reset_data->restart_handler.priority = 192;
spin_lock_init(&reset_data->lock);
- err = register_restart_handler(&reset_data->restart_handler);
+ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 192,
+ ma35d1_restart_handler, reset_data);
if (err)
dev_warn(&pdev->dev, "failed to register restart handler\n");
diff --git a/drivers/reset/reset-npcm.c b/drivers/reset/reset-npcm.c
index 4070a4b6663f..a762d0215e76 100644
--- a/drivers/reset/reset-npcm.c
+++ b/drivers/reset/reset-npcm.c
@@ -89,7 +89,6 @@ static const struct npcm_reset_info npxm8xx_reset_info[] = {
struct npcm_rc_data {
struct reset_controller_dev rcdev;
- struct notifier_block restart_nb;
const struct npcm_reset_info *info;
struct regmap *gcr_regmap;
u32 sw_reset_number;
@@ -100,11 +99,9 @@ struct npcm_rc_data {
#define to_rc_data(p) container_of(p, struct npcm_rc_data, rcdev)
-static int npcm_rc_restart(struct notifier_block *nb, unsigned long mode,
- void *cmd)
+static int npcm_rc_restart(struct sys_off_data *data)
{
- struct npcm_rc_data *rc = container_of(nb, struct npcm_rc_data,
- restart_nb);
+ struct npcm_rc_data *rc = data->cb_data;
writel(NPCM_SWRST << rc->sw_reset_number, rc->base + NPCM_SWRSTR);
mdelay(1000);
@@ -472,9 +469,8 @@ static int npcm_rc_probe(struct platform_device *pdev)
if (!of_property_read_u32(pdev->dev.of_node, "nuvoton,sw-reset-number",
&rc->sw_reset_number)) {
if (rc->sw_reset_number && rc->sw_reset_number < 5) {
- rc->restart_nb.priority = 192;
- rc->restart_nb.notifier_call = npcm_rc_restart;
- ret = register_restart_handler(&rc->restart_nb);
+ ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, 192,
+ npcm_rc_restart, rc);
if (ret) {
dev_warn(&pdev->dev, "failed to register restart handler\n");
return ret;
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
index 32bc268c9149..fd75d9601a3b 100644
--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
@@ -136,6 +136,9 @@ static int rzg2l_usbphy_ctrl_set_pwrrdy(struct regmap_field *pwrrdy,
{
u32 val = power_on ? 0 : 1;
+ if (!pwrrdy)
+ return 0;
+
/* The initialization path guarantees that the mask is 1 bit long. */
return regmap_field_update_bits(pwrrdy, 1, val);
}
@@ -347,4 +350,4 @@ module_platform_driver(rzg2l_usbphy_ctrl_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Renesas RZ/G2L USBPHY Control");
-MODULE_AUTHOR("biju.das.jz@bp.renesas.com>");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
diff --git a/drivers/reset/reset-rzv2h-usb2phy.c b/drivers/reset/reset-rzv2h-usb2phy.c
index ae643575b067..d96042e28cd5 100644
--- a/drivers/reset/reset-rzv2h-usb2phy.c
+++ b/drivers/reset/reset-rzv2h-usb2phy.c
@@ -5,42 +5,39 @@
* Copyright (C) 2025 Renesas Electronics Corporation
*/
-#include <linux/cleanup.h>
+#include <linux/auxiliary_bus.h>
#include <linux/delay.h>
+#include <linux/idr.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
-struct rzv2h_usb2phy_regval {
- u16 reg;
- u16 val;
-};
+static DEFINE_IDA(auxiliary_ids);
struct rzv2h_usb2phy_reset_of_data {
- const struct rzv2h_usb2phy_regval *init_vals;
- unsigned int init_val_count;
+ const struct reg_sequence *init_seq;
+ unsigned int init_nseq;
+
+ const struct reg_sequence *assert_seq;
+ unsigned int assert_nseq;
+
+ const struct reg_sequence *deassert_seq;
+ unsigned int deassert_nseq;
u16 reset_reg;
- u16 reset_assert_val;
- u16 reset_deassert_val;
u16 reset_status_bits;
- u16 reset_release_val;
-
- u16 reset2_reg;
- u16 reset2_acquire_val;
- u16 reset2_release_val;
};
struct rzv2h_usb2phy_reset_priv {
const struct rzv2h_usb2phy_reset_of_data *data;
- void __iomem *base;
+ struct regmap *regmap;
struct device *dev;
struct reset_controller_dev rcdev;
- spinlock_t lock; /* protects register accesses */
};
static inline struct rzv2h_usb2phy_reset_priv
@@ -49,81 +46,31 @@ static inline struct rzv2h_usb2phy_reset_priv
return container_of(rcdev, struct rzv2h_usb2phy_reset_priv, rcdev);
}
-/* This function must be called only after pm_runtime_resume_and_get() has been called */
-static void rzv2h_usbphy_assert_helper(struct rzv2h_usb2phy_reset_priv *priv)
-{
- const struct rzv2h_usb2phy_reset_of_data *data = priv->data;
-
- scoped_guard(spinlock, &priv->lock) {
- writel(data->reset2_acquire_val, priv->base + data->reset2_reg);
- writel(data->reset_assert_val, priv->base + data->reset_reg);
- }
-
- usleep_range(11, 20);
-}
-
static int rzv2h_usbphy_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
- struct device *dev = priv->dev;
- int ret;
-
- ret = pm_runtime_resume_and_get(dev);
- if (ret) {
- dev_err(dev, "pm_runtime_resume_and_get failed\n");
- return ret;
- }
-
- rzv2h_usbphy_assert_helper(priv);
- pm_runtime_put(dev);
-
- return 0;
+ return regmap_multi_reg_write(priv->regmap, priv->data->assert_seq,
+ priv->data->assert_nseq);
}
static int rzv2h_usbphy_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
- const struct rzv2h_usb2phy_reset_of_data *data = priv->data;
- struct device *dev = priv->dev;
- int ret;
-
- ret = pm_runtime_resume_and_get(dev);
- if (ret) {
- dev_err(dev, "pm_runtime_resume_and_get failed\n");
- return ret;
- }
- scoped_guard(spinlock, &priv->lock) {
- writel(data->reset_deassert_val, priv->base + data->reset_reg);
- writel(data->reset2_release_val, priv->base + data->reset2_reg);
- writel(data->reset_release_val, priv->base + data->reset_reg);
- }
-
- pm_runtime_put(dev);
-
- return 0;
+ return regmap_multi_reg_write(priv->regmap, priv->data->deassert_seq,
+ priv->data->deassert_nseq);
}
static int rzv2h_usbphy_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_usb2phy_reset_priv *priv = rzv2h_usbphy_rcdev_to_priv(rcdev);
- struct device *dev = priv->dev;
- int ret;
u32 reg;
- ret = pm_runtime_resume_and_get(dev);
- if (ret) {
- dev_err(dev, "pm_runtime_resume_and_get failed\n");
- return ret;
- }
-
- reg = readl(priv->base + priv->data->reset_reg);
-
- pm_runtime_put(dev);
+ regmap_read(priv->regmap, priv->data->reset_reg, &reg);
return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits;
}
@@ -141,12 +88,52 @@ static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev,
return 0;
}
+static void rzv2h_usb2phy_reset_ida_free(void *data)
+{
+ struct auxiliary_device *adev = data;
+
+ ida_free(&auxiliary_ids, adev->id);
+}
+
+static int rzv2h_usb2phy_reset_mux_register(struct device *dev,
+ const char *mux_name)
+{
+ struct auxiliary_device *adev;
+ int id;
+
+ id = ida_alloc(&auxiliary_ids, GFP_KERNEL);
+ if (id < 0)
+ return id;
+
+ adev = __devm_auxiliary_device_create(dev, dev->driver->name,
+ mux_name, NULL, id);
+ if (!adev) {
+ ida_free(&auxiliary_ids, id);
+ return -ENOMEM;
+ }
+
+ return devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_ida_free, adev);
+}
+
+static const struct regmap_config rzv2h_usb2phy_reset_regconf = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .can_sleep = true,
+};
+
+static void rzv2h_usb2phy_reset_pm_runtime_put(void *data)
+{
+ pm_runtime_put(data);
+}
+
static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
{
const struct rzv2h_usb2phy_reset_of_data *data;
struct rzv2h_usb2phy_reset_priv *priv;
struct device *dev = &pdev->dev;
struct reset_control *rstc;
+ void __iomem *base;
int error;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -156,17 +143,19 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
data = of_device_get_match_data(dev);
priv->data = data;
priv->dev = dev;
- priv->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap = devm_regmap_init_mmio(dev, base, &rzv2h_usb2phy_reset_regconf);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
rstc = devm_reset_control_get_shared_deasserted(dev, NULL);
if (IS_ERR(rstc))
return dev_err_probe(dev, PTR_ERR(rstc),
"failed to get deasserted reset\n");
- spin_lock_init(&priv->lock);
-
error = devm_pm_runtime_enable(dev);
if (error)
return dev_err_probe(dev, error, "Failed to enable pm_runtime\n");
@@ -175,13 +164,14 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
if (error)
return dev_err_probe(dev, error, "pm_runtime_resume_and_get failed\n");
- for (unsigned int i = 0; i < data->init_val_count; i++)
- writel(data->init_vals[i].val, priv->base + data->init_vals[i].reg);
-
- /* keep usb2phy in asserted state */
- rzv2h_usbphy_assert_helper(priv);
+ error = devm_add_action_or_reset(dev, rzv2h_usb2phy_reset_pm_runtime_put,
+ dev);
+ if (error)
+ return dev_err_probe(dev, error, "unable to register cleanup action\n");
- pm_runtime_put(dev);
+ error = regmap_multi_reg_write(priv->regmap, data->init_seq, data->init_nseq);
+ if (error)
+ return dev_err_probe(dev, error, "failed to initialize PHY registers\n");
priv->rcdev.ops = &rzv2h_usbphy_reset_ops;
priv->rcdev.of_reset_n_cells = 0;
@@ -190,30 +180,47 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
priv->rcdev.of_node = dev->of_node;
priv->rcdev.dev = dev;
- return devm_reset_controller_register(dev, &priv->rcdev);
+ error = devm_reset_controller_register(dev, &priv->rcdev);
+ if (error)
+ return dev_err_probe(dev, error, "could not register reset controller\n");
+
+ error = rzv2h_usb2phy_reset_mux_register(dev, "vbenctl");
+ if (error)
+ return dev_err_probe(dev, error, "could not register aux mux\n");
+
+ return 0;
}
/*
* initialization values required to prepare the PHY to receive
* assert and deassert requests.
*/
-static const struct rzv2h_usb2phy_regval rzv2h_init_vals[] = {
- { .reg = 0xc10, .val = 0x67c },
- { .reg = 0xc14, .val = 0x1f },
- { .reg = 0x600, .val = 0x909 },
+static const struct reg_sequence rzv2h_init_seq[] = {
+ { .reg = 0xc10, .def = 0x67c },
+ { .reg = 0xc14, .def = 0x01f },
+ { .reg = 0x600, .def = 0x909 },
+};
+
+static const struct reg_sequence rzv2h_assert_seq[] = {
+ { .reg = 0xb04, .def = 0x303 },
+ { .reg = 0x000, .def = 0x206, .delay_us = 11 },
+};
+
+static const struct reg_sequence rzv2h_deassert_seq[] = {
+ { .reg = 0x000, .def = 0x200 },
+ { .reg = 0xb04, .def = 0x003 },
+ { .reg = 0x000, .def = 0x000 },
};
static const struct rzv2h_usb2phy_reset_of_data rzv2h_reset_of_data = {
- .init_vals = rzv2h_init_vals,
- .init_val_count = ARRAY_SIZE(rzv2h_init_vals),
+ .init_seq = rzv2h_init_seq,
+ .init_nseq = ARRAY_SIZE(rzv2h_init_seq),
+ .assert_seq = rzv2h_assert_seq,
+ .assert_nseq = ARRAY_SIZE(rzv2h_assert_seq),
+ .deassert_seq = rzv2h_deassert_seq,
+ .deassert_nseq = ARRAY_SIZE(rzv2h_deassert_seq),
.reset_reg = 0,
- .reset_assert_val = 0x206,
.reset_status_bits = BIT(2),
- .reset_deassert_val = 0x200,
- .reset_release_val = 0x0,
- .reset2_reg = 0xb04,
- .reset2_acquire_val = 0x303,
- .reset2_release_val = 0x3,
};
static const struct of_device_id rzv2h_usb2phy_reset_of_match[] = {
diff --git a/drivers/reset/reset-sky1.c b/drivers/reset/reset-sky1.c
new file mode 100644
index 000000000000..78e80a533c39
--- /dev/null
+++ b/drivers/reset/reset-sky1.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *
+ * CIX System Reset Controller (SRC) driver
+ *
+ * Author: Jerry Zhu <jerry.zhu@cixtech.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/reset/cix,sky1-system-control.h>
+#include <dt-bindings/reset/cix,sky1-s5-system-control.h>
+
+#define SKY1_RESET_SLEEP_MIN_US 50
+#define SKY1_RESET_SLEEP_MAX_US 100
+
+struct sky1_src_signal {
+ unsigned int offset;
+ unsigned int bit;
+};
+
+struct sky1_src_variant {
+ const struct sky1_src_signal *signals;
+ unsigned int signals_num;
+};
+
+struct sky1_src {
+ struct reset_controller_dev rcdev;
+ const struct sky1_src_signal *signals;
+ struct regmap *regmap;
+};
+
+enum {
+ CSU_PM_RESET = 0x304,
+ SENSORFUSION_RESET = 0x308,
+ SENSORFUSION_NOC_RESET = 0x30c,
+ RESET_GROUP0_S0_DOMAIN_0 = 0x400,
+ RESET_GROUP0_S0_DOMAIN_1 = 0x404,
+ RESET_GROUP1_USB_PHYS = 0x408,
+ RESET_GROUP1_USB_CONTROLLERS = 0x40c,
+ RESET_GROUP0_RCSU = 0x800,
+ RESET_GROUP1_RCSU = 0x804,
+};
+
+static const struct sky1_src_signal sky1_src_signals[] = {
+ /* reset group1 for s0 domain modules */
+ [SKY1_CSU_PM_RESET_N] = { CSU_PM_RESET, BIT(0) },
+ [SKY1_SENSORFUSION_RESET_N] = { SENSORFUSION_RESET, BIT(0) },
+ [SKY1_SENSORFUSION_NOC_RESET_N] = { SENSORFUSION_NOC_RESET, BIT(0) },
+ [SKY1_DDRC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(0) },
+ [SKY1_GIC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(1) },
+ [SKY1_CI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(2) },
+ [SKY1_SYS_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(3) },
+ [SKY1_MM_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(4) },
+ [SKY1_PCIE_NI700_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(5) },
+ [SKY1_GPU_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(6) },
+ [SKY1_NPUTOP_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(7) },
+ [SKY1_NPUCORE0_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(8) },
+ [SKY1_NPUCORE1_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(9) },
+ [SKY1_NPUCORE2_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(10) },
+ [SKY1_VPU_RESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(11) },
+ [SKY1_ISP_SRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(12) },
+ [SKY1_ISP_ARESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(13) },
+ [SKY1_ISP_HRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(14) },
+ [SKY1_ISP_GDCRESET_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(15) },
+ [SKY1_DPU_RESET0_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(16) },
+ [SKY1_DPU_RESET1_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(17) },
+ [SKY1_DPU_RESET2_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(18) },
+ [SKY1_DPU_RESET3_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(19) },
+ [SKY1_DPU_RESET4_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(20) },
+ [SKY1_DP_RESET0_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(21) },
+ [SKY1_DP_RESET1_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(22) },
+ [SKY1_DP_RESET2_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(23) },
+ [SKY1_DP_RESET3_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(24) },
+ [SKY1_DP_RESET4_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(25) },
+ [SKY1_DP_PHY_RST_N] = { RESET_GROUP0_S0_DOMAIN_0, BIT(26) },
+
+ /* reset group1 for s0 domain modules */
+ [SKY1_AUDIO_HIFI5_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(0) },
+ [SKY1_AUDIO_HIFI5_NOC_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(1) },
+ [SKY1_CSIDPHY_PRST0_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(2) },
+ [SKY1_CSIDPHY_CMNRST0_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(3) },
+ [SKY1_CSI0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(4) },
+ [SKY1_CSIDPHY_PRST1_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(5) },
+ [SKY1_CSIDPHY_CMNRST1_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(6) },
+ [SKY1_CSI1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(7) },
+ [SKY1_CSI2_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(8) },
+ [SKY1_CSI3_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(9) },
+ [SKY1_CSIBRDGE0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(10) },
+ [SKY1_CSIBRDGE1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(11) },
+ [SKY1_CSIBRDGE2_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(12) },
+ [SKY1_CSIBRDGE3_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(13) },
+ [SKY1_GMAC0_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(14) },
+ [SKY1_GMAC1_RST_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(15) },
+ [SKY1_PCIE0_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(16) },
+ [SKY1_PCIE1_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(17) },
+ [SKY1_PCIE2_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(18) },
+ [SKY1_PCIE3_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(19) },
+ [SKY1_PCIE4_RESET_N] = { RESET_GROUP0_S0_DOMAIN_1, BIT(20) },
+
+ /* reset group1 for usb phys */
+ [SKY1_USB_DP_PHY0_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(0) },
+ [SKY1_USB_DP_PHY1_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(1) },
+ [SKY1_USB_DP_PHY2_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(2) },
+ [SKY1_USB_DP_PHY3_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(3) },
+ [SKY1_USB_DP_PHY0_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(4) },
+ [SKY1_USB_DP_PHY1_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(5) },
+ [SKY1_USB_DP_PHY2_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(6) },
+ [SKY1_USB_DP_PHY3_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(7) },
+ [SKY1_USBPHY_SS_PST_N] = { RESET_GROUP1_USB_PHYS, BIT(8) },
+ [SKY1_USBPHY_SS_RST_N] = { RESET_GROUP1_USB_PHYS, BIT(9) },
+ [SKY1_USBPHY_HS0_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(10) },
+ [SKY1_USBPHY_HS1_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(11) },
+ [SKY1_USBPHY_HS2_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(12) },
+ [SKY1_USBPHY_HS3_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(13) },
+ [SKY1_USBPHY_HS4_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(14) },
+ [SKY1_USBPHY_HS5_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(15) },
+ [SKY1_USBPHY_HS6_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(16) },
+ [SKY1_USBPHY_HS7_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(17) },
+ [SKY1_USBPHY_HS8_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(18) },
+ [SKY1_USBPHY_HS9_PRST_N] = { RESET_GROUP1_USB_PHYS, BIT(19) },
+
+ /* reset group1 for usb controllers */
+ [SKY1_USBC_SS0_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(0) },
+ [SKY1_USBC_SS1_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(1) },
+ [SKY1_USBC_SS2_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(2) },
+ [SKY1_USBC_SS3_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(3) },
+ [SKY1_USBC_SS4_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(4) },
+ [SKY1_USBC_SS5_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(5) },
+ [SKY1_USBC_SS0_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(6) },
+ [SKY1_USBC_SS1_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(7) },
+ [SKY1_USBC_SS2_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(8) },
+ [SKY1_USBC_SS3_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(9) },
+ [SKY1_USBC_SS4_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(10) },
+ [SKY1_USBC_SS5_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(11) },
+ [SKY1_USBC_HS0_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(12) },
+ [SKY1_USBC_HS1_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(13) },
+ [SKY1_USBC_HS2_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(14) },
+ [SKY1_USBC_HS3_PRST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(15) },
+ [SKY1_USBC_HS0_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(16) },
+ [SKY1_USBC_HS1_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(17) },
+ [SKY1_USBC_HS2_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(18) },
+ [SKY1_USBC_HS3_RST_N] = { RESET_GROUP1_USB_CONTROLLERS, BIT(19) },
+
+ /* reset group0 for rcsu */
+ [SKY1_AUDIO_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(0) },
+ [SKY1_CI700_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(1) },
+ [SKY1_CSI_RCSU0_RESET_N] = { RESET_GROUP0_RCSU, BIT(2) },
+ [SKY1_CSI_RCSU1_RESET_N] = { RESET_GROUP0_RCSU, BIT(3) },
+ [SKY1_CSU_PM_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(4) },
+ [SKY1_DDR_BROADCAST_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(5) },
+ [SKY1_DDR_CTRL_RCSU_0_RESET_N] = { RESET_GROUP0_RCSU, BIT(6) },
+ [SKY1_DDR_CTRL_RCSU_1_RESET_N] = { RESET_GROUP0_RCSU, BIT(7) },
+ [SKY1_DDR_CTRL_RCSU_2_RESET_N] = { RESET_GROUP0_RCSU, BIT(8) },
+ [SKY1_DDR_CTRL_RCSU_3_RESET_N] = { RESET_GROUP0_RCSU, BIT(9) },
+ [SKY1_DDR_TZC400_RCSU_0_RESET_N] = { RESET_GROUP0_RCSU, BIT(10) },
+ [SKY1_DDR_TZC400_RCSU_1_RESET_N] = { RESET_GROUP0_RCSU, BIT(11) },
+ [SKY1_DDR_TZC400_RCSU_2_RESET_N] = { RESET_GROUP0_RCSU, BIT(12) },
+ [SKY1_DDR_TZC400_RCSU_3_RESET_N] = { RESET_GROUP0_RCSU, BIT(13) },
+ [SKY1_DP0_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(14) },
+ [SKY1_DP1_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(15) },
+ [SKY1_DP2_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(16) },
+ [SKY1_DP3_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(17) },
+ [SKY1_DP4_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(18) },
+ [SKY1_DPU0_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(19) },
+ [SKY1_DPU1_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(20) },
+ [SKY1_DPU2_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(21) },
+ [SKY1_DPU3_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(22) },
+ [SKY1_DPU4_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(23) },
+ [SKY1_DSU_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(24) },
+ [SKY1_FCH_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(25) },
+ [SKY1_GICD_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(26) },
+ [SKY1_GMAC_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(27) },
+ [SKY1_GPU_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(28) },
+ [SKY1_ISP_RCSU0_RESET_N] = { RESET_GROUP0_RCSU, BIT(29) },
+ [SKY1_ISP_RCSU1_RESET_N] = { RESET_GROUP0_RCSU, BIT(30) },
+ [SKY1_NI700_MMHUB_RCSU_RESET_N] = { RESET_GROUP0_RCSU, BIT(31) },
+
+ /* reset group1 for rcsu */
+ [SKY1_NPU_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(0) },
+ [SKY1_NI700_PCIE_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(1) },
+ [SKY1_PCIE_X421_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(2) },
+ [SKY1_PCIE_X8_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(3) },
+ [SKY1_SF_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(4) },
+ [SKY1_RCSU_SMMU_MMHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(5) },
+ [SKY1_RCSU_SMMU_PCIEHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(6) },
+ [SKY1_RCSU_SYSHUB_RESET_N] = { RESET_GROUP1_RCSU, BIT(7) },
+ [SKY1_NI700_SMN_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(8) },
+ [SKY1_NI700_SYSHUB_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(9) },
+ [SKY1_RCSU_USB2_HOST0_RESET_N] = { RESET_GROUP1_RCSU, BIT(10) },
+ [SKY1_RCSU_USB2_HOST1_RESET_N] = { RESET_GROUP1_RCSU, BIT(11) },
+ [SKY1_RCSU_USB2_HOST2_RESET_N] = { RESET_GROUP1_RCSU, BIT(12) },
+ [SKY1_RCSU_USB2_HOST3_RESET_N] = { RESET_GROUP1_RCSU, BIT(13) },
+ [SKY1_RCSU_USB3_TYPEA_DRD_RESET_N] = { RESET_GROUP1_RCSU, BIT(14) },
+ [SKY1_RCSU_USB3_TYPEC_DRD_RESET_N] = { RESET_GROUP1_RCSU, BIT(15) },
+ [SKY1_RCSU_USB3_TYPEC_HOST0_RESET_N] = { RESET_GROUP1_RCSU, BIT(16) },
+ [SKY1_RCSU_USB3_TYPEC_HOST1_RESET_N] = { RESET_GROUP1_RCSU, BIT(17) },
+ [SKY1_RCSU_USB3_TYPEC_HOST2_RESET_N] = { RESET_GROUP1_RCSU, BIT(18) },
+ [SKY1_VPU_RCSU_RESET_N] = { RESET_GROUP1_RCSU, BIT(19) },
+};
+
+static const struct sky1_src_variant variant_sky1 = {
+ .signals = sky1_src_signals,
+ .signals_num = ARRAY_SIZE(sky1_src_signals),
+};
+
+enum {
+ FCH_SW_RST_FUNC = 0x8,
+ FCH_SW_RST_BUS = 0xc,
+ FCH_SW_XSPI = 0x10,
+};
+
+static const struct sky1_src_signal sky1_src_fch_signals[] = {
+ /* resets for fch_sw_rst_func */
+ [SW_I3C0_RST_FUNC_G_N] = { FCH_SW_RST_FUNC, BIT(0) },
+ [SW_I3C0_RST_FUNC_I_N] = { FCH_SW_RST_FUNC, BIT(1) },
+ [SW_I3C1_RST_FUNC_G_N] = { FCH_SW_RST_FUNC, BIT(2) },
+ [SW_I3C1_RST_FUNC_I_N] = { FCH_SW_RST_FUNC, BIT(3) },
+ [SW_UART0_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(4) },
+ [SW_UART1_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(5) },
+ [SW_UART2_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(6) },
+ [SW_UART3_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(7) },
+ [SW_TIMER_RST_FUNC_N] = { FCH_SW_RST_FUNC, BIT(20) },
+
+ /* resets for fch_sw_rst_bus */
+ [SW_I3C0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(0) },
+ [SW_I3C1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(1) },
+ [SW_DMA_RST_AXI_N] = { FCH_SW_RST_BUS, BIT(2) },
+ [SW_UART0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(4) },
+ [SW_UART1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(5) },
+ [SW_UART2_RST_APB_N] = { FCH_SW_RST_BUS, BIT(6) },
+ [SW_UART3_RST_APB_N] = { FCH_SW_RST_BUS, BIT(7) },
+ [SW_SPI0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(8) },
+ [SW_SPI1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(9) },
+ [SW_I2C0_RST_APB_N] = { FCH_SW_RST_BUS, BIT(12) },
+ [SW_I2C1_RST_APB_N] = { FCH_SW_RST_BUS, BIT(13) },
+ [SW_I2C2_RST_APB_N] = { FCH_SW_RST_BUS, BIT(14) },
+ [SW_I2C3_RST_APB_N] = { FCH_SW_RST_BUS, BIT(15) },
+ [SW_I2C4_RST_APB_N] = { FCH_SW_RST_BUS, BIT(16) },
+ [SW_I2C5_RST_APB_N] = { FCH_SW_RST_BUS, BIT(17) },
+ [SW_I2C6_RST_APB_N] = { FCH_SW_RST_BUS, BIT(18) },
+ [SW_I2C7_RST_APB_N] = { FCH_SW_RST_BUS, BIT(19) },
+ [SW_GPIO_RST_APB_N] = { FCH_SW_RST_BUS, BIT(21) },
+
+ /* resets for fch_sw_xspi */
+ [SW_XSPI_REG_RST_N] = { FCH_SW_XSPI, BIT(0) },
+ [SW_XSPI_SYS_RST_N] = { FCH_SW_XSPI, BIT(1) },
+};
+
+static const struct sky1_src_variant variant_sky1_fch = {
+ .signals = sky1_src_fch_signals,
+ .signals_num = ARRAY_SIZE(sky1_src_fch_signals),
+};
+
+static struct sky1_src *to_sky1_src(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct sky1_src, rcdev);
+}
+
+static int sky1_reset_set(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct sky1_src *sky1src = to_sky1_src(rcdev);
+ const struct sky1_src_signal *signal = &sky1src->signals[id];
+ unsigned int value = assert ? 0 : signal->bit;
+
+ return regmap_update_bits(sky1src->regmap,
+ signal->offset, signal->bit, value);
+}
+
+static int sky1_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ sky1_reset_set(rcdev, id, true);
+ usleep_range(SKY1_RESET_SLEEP_MIN_US,
+ SKY1_RESET_SLEEP_MAX_US);
+ return 0;
+}
+
+static int sky1_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ sky1_reset_set(rcdev, id, false);
+ usleep_range(SKY1_RESET_SLEEP_MIN_US,
+ SKY1_RESET_SLEEP_MAX_US);
+ return 0;
+}
+
+static int sky1_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ sky1_reset_assert(rcdev, id);
+ sky1_reset_deassert(rcdev, id);
+ return 0;
+}
+
+static int sky1_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ unsigned int value = 0;
+ struct sky1_src *sky1src = to_sky1_src(rcdev);
+ const struct sky1_src_signal *signal = &sky1src->signals[id];
+
+ regmap_read(sky1src->regmap, signal->offset, &value);
+ return !(value & signal->bit);
+}
+
+static const struct reset_control_ops sky1_src_ops = {
+ .reset = sky1_reset,
+ .assert = sky1_reset_assert,
+ .deassert = sky1_reset_deassert,
+ .status = sky1_reset_status
+};
+
+static int sky1_reset_probe(struct platform_device *pdev)
+{
+ struct sky1_src *sky1src;
+ struct device *dev = &pdev->dev;
+ const struct sky1_src_variant *variant;
+
+ sky1src = devm_kzalloc(dev, sizeof(*sky1src), GFP_KERNEL);
+ if (!sky1src)
+ return -ENOMEM;
+
+ variant = of_device_get_match_data(dev);
+
+ sky1src->regmap = device_node_to_regmap(dev->of_node);
+ if (IS_ERR(sky1src->regmap)) {
+ return dev_err_probe(dev, PTR_ERR(sky1src->regmap),
+ "Unable to get sky1-src regmap");
+ }
+
+ sky1src->signals = variant->signals;
+ sky1src->rcdev.owner = THIS_MODULE;
+ sky1src->rcdev.nr_resets = variant->signals_num;
+ sky1src->rcdev.ops = &sky1_src_ops;
+ sky1src->rcdev.of_node = dev->of_node;
+ sky1src->rcdev.dev = dev;
+
+ return devm_reset_controller_register(dev, &sky1src->rcdev);
+}
+
+static const struct of_device_id sky1_sysreg_of_match[] = {
+ { .compatible = "cix,sky1-system-control", .data = &variant_sky1_fch},
+ { .compatible = "cix,sky1-s5-system-control", .data = &variant_sky1},
+ {},
+};
+MODULE_DEVICE_TABLE(of, sky1_sysreg_of_match);
+
+static struct platform_driver sky1_reset_driver = {
+ .probe = sky1_reset_probe,
+ .driver = {
+ .name = "cix,sky1-rst",
+ .of_match_table = sky1_sysreg_of_match,
+ },
+};
+module_platform_driver(sky1_reset_driver)
+
+MODULE_AUTHOR("Jerry Zhu <jerry.zhu@cixtech.com>");
+MODULE_DESCRIPTION("Cix Sky1 reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-sunplus.c b/drivers/reset/reset-sunplus.c
index df58decab64d..58b087433759 100644
--- a/drivers/reset/reset-sunplus.c
+++ b/drivers/reset/reset-sunplus.c
@@ -100,7 +100,6 @@ static const u32 sp_resets[] = {
struct sp_reset {
struct reset_controller_dev rcdev;
- struct notifier_block notifier;
void __iomem *base;
};
@@ -154,10 +153,9 @@ static const struct reset_control_ops sp_reset_ops = {
.status = sp_reset_status,
};
-static int sp_restart(struct notifier_block *nb, unsigned long mode,
- void *cmd)
+static int sp_restart(struct sys_off_data *data)
{
- struct sp_reset *reset = container_of(nb, struct sp_reset, notifier);
+ struct sp_reset *reset = data->cb_data;
sp_reset_assert(&reset->rcdev, 0);
sp_reset_deassert(&reset->rcdev, 0);
@@ -189,10 +187,8 @@ static int sp_reset_probe(struct platform_device *pdev)
if (ret)
return ret;
- reset->notifier.notifier_call = sp_restart;
- reset->notifier.priority = 192;
-
- return register_restart_handler(&reset->notifier);
+ return devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
+ 192, sp_restart, reset);
}
static const struct of_device_id sp_reset_dt_ids[] = {
diff --git a/drivers/reset/spacemit/reset-spacemit-k3.c b/drivers/reset/spacemit/reset-spacemit-k3.c
index e9e32e4c1ba5..9841f5e057b2 100644
--- a/drivers/reset/spacemit/reset-spacemit-k3.c
+++ b/drivers/reset/spacemit/reset-spacemit-k3.c
@@ -112,16 +112,21 @@ static const struct ccu_reset_data k3_apmu_resets[] = {
[RESET_APMU_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)),
[RESET_APMU_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)),
[RESET_APMU_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)),
- [RESET_APMU_USB2] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0,
- BIT(1)|BIT(2)|BIT(3)),
- [RESET_APMU_USB3_PORTA] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0,
- BIT(5)|BIT(6)|BIT(7)),
- [RESET_APMU_USB3_PORTB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0,
- BIT(9)|BIT(10)|BIT(11)),
- [RESET_APMU_USB3_PORTC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0,
- BIT(13)|BIT(14)|BIT(15)),
- [RESET_APMU_USB3_PORTD] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0,
- BIT(17)|BIT(18)|BIT(19)),
+ [RESET_APMU_USB2_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_APMU_USB2_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_APMU_USB2_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_APMU_USB3_A_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(5)),
+ [RESET_APMU_USB3_A_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(6)),
+ [RESET_APMU_USB3_A_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(7)),
+ [RESET_APMU_USB3_B_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_APMU_USB3_B_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)),
+ [RESET_APMU_USB3_B_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)),
+ [RESET_APMU_USB3_C_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(13)),
+ [RESET_APMU_USB3_C_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(14)),
+ [RESET_APMU_USB3_C_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(15)),
+ [RESET_APMU_USB3_D_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(17)),
+ [RESET_APMU_USB3_D_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(18)),
+ [RESET_APMU_USB3_D_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(19)),
[RESET_APMU_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)),
[RESET_APMU_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)),
[RESET_APMU_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)),
@@ -151,10 +156,12 @@ static const struct ccu_reset_data k3_apmu_resets[] = {
[RESET_APMU_CPU7_SW] = RESET_DATA(APMU_PMU_CC2_AP, BIT(26), 0),
[RESET_APMU_C1_MPSUB_SW] = RESET_DATA(APMU_PMU_CC2_AP, BIT(28), 0),
[RESET_APMU_MPSUB_DBG] = RESET_DATA(APMU_PMU_CC2_AP, BIT(29), 0),
- [RESET_APMU_UCIE] = RESET_DATA(APMU_UCIE_CTRL,
- BIT(1) | BIT(2) | BIT(3), 0),
- [RESET_APMU_RCPU] = RESET_DATA(APMU_RCPU_CLK_RES_CTRL, 0,
- BIT(3) | BIT(2) | BIT(0)),
+ [RESET_APMU_UCIE_IP] = RESET_DATA(APMU_UCIE_CTRL, BIT(1), 0),
+ [RESET_APMU_UCIE_HOT] = RESET_DATA(APMU_UCIE_CTRL, BIT(2), 0),
+ [RESET_APMU_UCIE_MON] = RESET_DATA(APMU_UCIE_CTRL, BIT(3), 0),
+ [RESET_APMU_RCPU_AUDIO_SYS] = RESET_DATA(APMU_RCPU_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_APMU_RCPU_MCU_CORE] = RESET_DATA(APMU_RCPU_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_APMU_RCPU_AUDIO_APMU] = RESET_DATA(APMU_RCPU_CLK_RES_CTRL, 0, BIT(3)),
[RESET_APMU_DSI4LN2_ESCCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL3, 0, BIT(3)),
[RESET_APMU_DSI4LN2_LCD_SW] = RESET_DATA(APMU_LCD_CLK_RES_CTRL3, 0, BIT(4)),
[RESET_APMU_DSI4LN2_LCD_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL4, 0, BIT(9)),
@@ -164,16 +171,21 @@ static const struct ccu_reset_data k3_apmu_resets[] = {
[RESET_APMU_UFS_ACLK] = RESET_DATA(APMU_UFS_CLK_RES_CTRL, 0, BIT(0)),
[RESET_APMU_EDP0] = RESET_DATA(APMU_LCD_EDP_CTRL, 0, BIT(0)),
[RESET_APMU_EDP1] = RESET_DATA(APMU_LCD_EDP_CTRL, 0, BIT(16)),
- [RESET_APMU_PCIE_PORTA] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_A, 0,
- BIT(5) | BIT(4) | BIT(3)),
- [RESET_APMU_PCIE_PORTB] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_B, 0,
- BIT(5) | BIT(4) | BIT(3)),
- [RESET_APMU_PCIE_PORTC] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_C, 0,
- BIT(5) | BIT(4) | BIT(3)),
- [RESET_APMU_PCIE_PORTD] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_D, 0,
- BIT(5) | BIT(4) | BIT(3)),
- [RESET_APMU_PCIE_PORTE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_E, 0,
- BIT(5) | BIT(4) | BIT(3)),
+ [RESET_APMU_PCIE_A_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_A, 0, BIT(3)),
+ [RESET_APMU_PCIE_A_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_A, 0, BIT(4)),
+ [RESET_APMU_PCIE_A_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_A, 0, BIT(5)),
+ [RESET_APMU_PCIE_B_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_B, 0, BIT(3)),
+ [RESET_APMU_PCIE_B_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_B, 0, BIT(4)),
+ [RESET_APMU_PCIE_B_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_B, 0, BIT(5)),
+ [RESET_APMU_PCIE_C_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_C, 0, BIT(3)),
+ [RESET_APMU_PCIE_C_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_C, 0, BIT(4)),
+ [RESET_APMU_PCIE_C_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_C, 0, BIT(5)),
+ [RESET_APMU_PCIE_D_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_D, 0, BIT(3)),
+ [RESET_APMU_PCIE_D_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_D, 0, BIT(4)),
+ [RESET_APMU_PCIE_D_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_D, 0, BIT(5)),
+ [RESET_APMU_PCIE_E_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_E, 0, BIT(3)),
+ [RESET_APMU_PCIE_E_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_E, 0, BIT(4)),
+ [RESET_APMU_PCIE_E_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_E, 0, BIT(5)),
[RESET_APMU_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)),
[RESET_APMU_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)),
[RESET_APMU_EMAC2] = RESET_DATA(APMU_EMAC2_CLK_RES_CTRL, 0, BIT(1)),
diff --git a/drivers/reset/sti/reset-syscfg.c b/drivers/reset/sti/reset-syscfg.c
index 2324060b747c..38f78d78fa4f 100644
--- a/drivers/reset/sti/reset-syscfg.c
+++ b/drivers/reset/sti/reset-syscfg.c
@@ -41,7 +41,7 @@ struct syscfg_reset_channel {
struct syscfg_reset_controller {
struct reset_controller_dev rst;
bool active_low;
- struct syscfg_reset_channel *channels;
+ struct syscfg_reset_channel channels[];
};
#define to_syscfg_reset_controller(_rst) \
@@ -135,15 +135,10 @@ static int syscfg_reset_controller_register(struct device *dev,
struct syscfg_reset_controller *rc;
int i, err;
- rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL);
+ rc = devm_kzalloc(dev, struct_size(rc, channels, data->nr_channels), GFP_KERNEL);
if (!rc)
return -ENOMEM;
- rc->channels = devm_kcalloc(dev, data->nr_channels,
- sizeof(*rc->channels), GFP_KERNEL);
- if (!rc->channels)
- return -ENOMEM;
-
rc->rst.ops = &syscfg_reset_ops;
rc->rst.of_node = dev->of_node;
rc->rst.nr_resets = data->nr_channels;
diff --git a/include/dt-bindings/reset/cix,sky1-s5-system-control.h b/include/dt-bindings/reset/cix,sky1-s5-system-control.h
new file mode 100644
index 000000000000..808bbcbe0c98
--- /dev/null
+++ b/include/dt-bindings/reset/cix,sky1-s5-system-control.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/* Author: Jerry Zhu <jerry.zhu@cixtech.com> */
+#ifndef DT_BINDING_RESET_CIX_SKY1_S5_SYSTEM_CONTROL_H
+#define DT_BINDING_RESET_CIX_SKY1_S5_SYSTEM_CONTROL_H
+
+/* reset for csu_pm */
+#define SKY1_CSU_PM_RESET_N 0
+#define SKY1_SENSORFUSION_RESET_N 1
+#define SKY1_SENSORFUSION_NOC_RESET_N 2
+
+/* reset group0 for s0 domain modules */
+#define SKY1_DDRC_RESET_N 3
+#define SKY1_GIC_RESET_N 4
+#define SKY1_CI700_RESET_N 5
+#define SKY1_SYS_NI700_RESET_N 6
+#define SKY1_MM_NI700_RESET_N 7
+#define SKY1_PCIE_NI700_RESET_N 8
+#define SKY1_GPU_RESET_N 9
+#define SKY1_NPUTOP_RESET_N 10
+#define SKY1_NPUCORE0_RESET_N 11
+#define SKY1_NPUCORE1_RESET_N 12
+#define SKY1_NPUCORE2_RESET_N 13
+#define SKY1_VPU_RESET_N 14
+#define SKY1_ISP_SRESET_N 15
+#define SKY1_ISP_ARESET_N 16
+#define SKY1_ISP_HRESET_N 17
+#define SKY1_ISP_GDCRESET_N 18
+#define SKY1_DPU_RESET0_N 19
+#define SKY1_DPU_RESET1_N 20
+#define SKY1_DPU_RESET2_N 21
+#define SKY1_DPU_RESET3_N 22
+#define SKY1_DPU_RESET4_N 23
+#define SKY1_DP_RESET0_N 24
+#define SKY1_DP_RESET1_N 25
+#define SKY1_DP_RESET2_N 26
+#define SKY1_DP_RESET3_N 27
+#define SKY1_DP_RESET4_N 28
+#define SKY1_DP_PHY_RST_N 29
+
+/* reset group1 for s0 domain modules */
+#define SKY1_AUDIO_HIFI5_RESET_N 30
+#define SKY1_AUDIO_HIFI5_NOC_RESET_N 31
+#define SKY1_CSIDPHY_PRST0_N 32
+#define SKY1_CSIDPHY_CMNRST0_N 33
+#define SKY1_CSI0_RST_N 34
+#define SKY1_CSIDPHY_PRST1_N 35
+#define SKY1_CSIDPHY_CMNRST1_N 36
+#define SKY1_CSI1_RST_N 37
+#define SKY1_CSI2_RST_N 38
+#define SKY1_CSI3_RST_N 39
+#define SKY1_CSIBRDGE0_RST_N 40
+#define SKY1_CSIBRDGE1_RST_N 41
+#define SKY1_CSIBRDGE2_RST_N 42
+#define SKY1_CSIBRDGE3_RST_N 43
+#define SKY1_GMAC0_RST_N 44
+#define SKY1_GMAC1_RST_N 45
+#define SKY1_PCIE0_RESET_N 46
+#define SKY1_PCIE1_RESET_N 47
+#define SKY1_PCIE2_RESET_N 48
+#define SKY1_PCIE3_RESET_N 49
+#define SKY1_PCIE4_RESET_N 50
+
+/* reset group1 for usb phys */
+#define SKY1_USB_DP_PHY0_PRST_N 51
+#define SKY1_USB_DP_PHY1_PRST_N 52
+#define SKY1_USB_DP_PHY2_PRST_N 53
+#define SKY1_USB_DP_PHY3_PRST_N 54
+#define SKY1_USB_DP_PHY0_RST_N 55
+#define SKY1_USB_DP_PHY1_RST_N 56
+#define SKY1_USB_DP_PHY2_RST_N 57
+#define SKY1_USB_DP_PHY3_RST_N 58
+#define SKY1_USBPHY_SS_PST_N 59
+#define SKY1_USBPHY_SS_RST_N 60
+#define SKY1_USBPHY_HS0_PRST_N 61
+#define SKY1_USBPHY_HS1_PRST_N 62
+#define SKY1_USBPHY_HS2_PRST_N 63
+#define SKY1_USBPHY_HS3_PRST_N 64
+#define SKY1_USBPHY_HS4_PRST_N 65
+#define SKY1_USBPHY_HS5_PRST_N 66
+#define SKY1_USBPHY_HS6_PRST_N 67
+#define SKY1_USBPHY_HS7_PRST_N 68
+#define SKY1_USBPHY_HS8_PRST_N 69
+#define SKY1_USBPHY_HS9_PRST_N 70
+
+/* reset group1 for usb controllers */
+#define SKY1_USBC_SS0_PRST_N 71
+#define SKY1_USBC_SS1_PRST_N 72
+#define SKY1_USBC_SS2_PRST_N 73
+#define SKY1_USBC_SS3_PRST_N 74
+#define SKY1_USBC_SS4_PRST_N 75
+#define SKY1_USBC_SS5_PRST_N 76
+#define SKY1_USBC_SS0_RST_N 77
+#define SKY1_USBC_SS1_RST_N 78
+#define SKY1_USBC_SS2_RST_N 79
+#define SKY1_USBC_SS3_RST_N 80
+#define SKY1_USBC_SS4_RST_N 81
+#define SKY1_USBC_SS5_RST_N 82
+#define SKY1_USBC_HS0_PRST_N 83
+#define SKY1_USBC_HS1_PRST_N 84
+#define SKY1_USBC_HS2_PRST_N 85
+#define SKY1_USBC_HS3_PRST_N 86
+#define SKY1_USBC_HS0_RST_N 87
+#define SKY1_USBC_HS1_RST_N 88
+#define SKY1_USBC_HS2_RST_N 89
+#define SKY1_USBC_HS3_RST_N 90
+
+/* reset group0 for rcsu */
+#define SKY1_AUDIO_RCSU_RESET_N 91
+#define SKY1_CI700_RCSU_RESET_N 92
+#define SKY1_CSI_RCSU0_RESET_N 93
+#define SKY1_CSI_RCSU1_RESET_N 94
+#define SKY1_CSU_PM_RCSU_RESET_N 95
+#define SKY1_DDR_BROADCAST_RCSU_RESET_N 96
+#define SKY1_DDR_CTRL_RCSU_0_RESET_N 97
+#define SKY1_DDR_CTRL_RCSU_1_RESET_N 98
+#define SKY1_DDR_CTRL_RCSU_2_RESET_N 99
+#define SKY1_DDR_CTRL_RCSU_3_RESET_N 100
+#define SKY1_DDR_TZC400_RCSU_0_RESET_N 101
+#define SKY1_DDR_TZC400_RCSU_1_RESET_N 102
+#define SKY1_DDR_TZC400_RCSU_2_RESET_N 103
+#define SKY1_DDR_TZC400_RCSU_3_RESET_N 104
+#define SKY1_DP0_RCSU_RESET_N 105
+#define SKY1_DP1_RCSU_RESET_N 106
+#define SKY1_DP2_RCSU_RESET_N 107
+#define SKY1_DP3_RCSU_RESET_N 108
+#define SKY1_DP4_RCSU_RESET_N 109
+#define SKY1_DPU0_RCSU_RESET_N 110
+#define SKY1_DPU1_RCSU_RESET_N 111
+#define SKY1_DPU2_RCSU_RESET_N 112
+#define SKY1_DPU3_RCSU_RESET_N 113
+#define SKY1_DPU4_RCSU_RESET_N 114
+#define SKY1_DSU_RCSU_RESET_N 115
+#define SKY1_FCH_RCSU_RESET_N 116
+#define SKY1_GICD_RCSU_RESET_N 117
+#define SKY1_GMAC_RCSU_RESET_N 118
+#define SKY1_GPU_RCSU_RESET_N 119
+#define SKY1_ISP_RCSU0_RESET_N 120
+#define SKY1_ISP_RCSU1_RESET_N 121
+#define SKY1_NI700_MMHUB_RCSU_RESET_N 122
+
+/* reset group1 for rcsu */
+#define SKY1_NPU_RCSU_RESET_N 123
+#define SKY1_NI700_PCIE_RCSU_RESET_N 124
+#define SKY1_PCIE_X421_RCSU_RESET_N 125
+#define SKY1_PCIE_X8_RCSU_RESET_N 126
+#define SKY1_SF_RCSU_RESET_N 127
+#define SKY1_RCSU_SMMU_MMHUB_RESET_N 128
+#define SKY1_RCSU_SMMU_PCIEHUB_RESET_N 129
+#define SKY1_RCSU_SYSHUB_RESET_N 130
+#define SKY1_NI700_SMN_RCSU_RESET_N 131
+#define SKY1_NI700_SYSHUB_RCSU_RESET_N 132
+#define SKY1_RCSU_USB2_HOST0_RESET_N 133
+#define SKY1_RCSU_USB2_HOST1_RESET_N 134
+#define SKY1_RCSU_USB2_HOST2_RESET_N 135
+#define SKY1_RCSU_USB2_HOST3_RESET_N 136
+#define SKY1_RCSU_USB3_TYPEA_DRD_RESET_N 137
+#define SKY1_RCSU_USB3_TYPEC_DRD_RESET_N 138
+#define SKY1_RCSU_USB3_TYPEC_HOST0_RESET_N 139
+#define SKY1_RCSU_USB3_TYPEC_HOST1_RESET_N 140
+#define SKY1_RCSU_USB3_TYPEC_HOST2_RESET_N 141
+#define SKY1_VPU_RCSU_RESET_N 142
+
+#endif
diff --git a/include/dt-bindings/reset/cix,sky1-system-control.h b/include/dt-bindings/reset/cix,sky1-system-control.h
new file mode 100644
index 000000000000..7a16fc4ef3b5
--- /dev/null
+++ b/include/dt-bindings/reset/cix,sky1-system-control.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/* Author: Jerry Zhu <jerry.zhu@cixtech.com> */
+#ifndef DT_BINDING_RESET_CIX_SKY1_SYSTEM_CONTROL_H
+#define DT_BINDING_RESET_CIX_SKY1_SYSTEM_CONTROL_H
+
+/* func reset for sky1 fch */
+#define SW_I3C0_RST_FUNC_G_N 0
+#define SW_I3C0_RST_FUNC_I_N 1
+#define SW_I3C1_RST_FUNC_G_N 2
+#define SW_I3C1_RST_FUNC_I_N 3
+#define SW_UART0_RST_FUNC_N 4
+#define SW_UART1_RST_FUNC_N 5
+#define SW_UART2_RST_FUNC_N 6
+#define SW_UART3_RST_FUNC_N 7
+#define SW_TIMER_RST_FUNC_N 8
+
+/* apb reset for sky1 fch */
+#define SW_I3C0_RST_APB_N 9
+#define SW_I3C1_RST_APB_N 10
+#define SW_DMA_RST_AXI_N 11
+#define SW_UART0_RST_APB_N 12
+#define SW_UART1_RST_APB_N 13
+#define SW_UART2_RST_APB_N 14
+#define SW_UART3_RST_APB_N 15
+#define SW_SPI0_RST_APB_N 16
+#define SW_SPI1_RST_APB_N 17
+#define SW_I2C0_RST_APB_N 18
+#define SW_I2C1_RST_APB_N 19
+#define SW_I2C2_RST_APB_N 20
+#define SW_I2C3_RST_APB_N 21
+#define SW_I2C4_RST_APB_N 22
+#define SW_I2C5_RST_APB_N 23
+#define SW_I2C6_RST_APB_N 24
+#define SW_I2C7_RST_APB_N 25
+#define SW_GPIO_RST_APB_N 26
+
+/* fch rst for xspi */
+#define SW_XSPI_REG_RST_N 27
+#define SW_XSPI_SYS_RST_N 28
+
+#endif
diff --git a/include/dt-bindings/reset/spacemit,k3-resets.h b/include/dt-bindings/reset/spacemit,k3-resets.h
index 79ac1c22b7b5..dc1ef009ba79 100644
--- a/include/dt-bindings/reset/spacemit,k3-resets.h
+++ b/include/dt-bindings/reset/spacemit,k3-resets.h
@@ -97,11 +97,11 @@
#define RESET_APMU_SDH0 13
#define RESET_APMU_SDH1 14
#define RESET_APMU_SDH2 15
-#define RESET_APMU_USB2 16
-#define RESET_APMU_USB3_PORTA 17
-#define RESET_APMU_USB3_PORTB 18
-#define RESET_APMU_USB3_PORTC 19
-#define RESET_APMU_USB3_PORTD 20
+#define RESET_APMU_USB2_AHB 16
+#define RESET_APMU_USB2_VCC 17
+#define RESET_APMU_USB2_PHY 18
+#define RESET_APMU_USB3_A_AHB 19
+#define RESET_APMU_USB3_A_VCC 20
#define RESET_APMU_QSPI 21
#define RESET_APMU_QSPI_BUS 22
#define RESET_APMU_DMA 23
@@ -132,8 +132,8 @@
#define RESET_APMU_CPU7_SW 48
#define RESET_APMU_C1_MPSUB_SW 49
#define RESET_APMU_MPSUB_DBG 50
-#define RESET_APMU_UCIE 51
-#define RESET_APMU_RCPU 52
+#define RESET_APMU_USB3_A_PHY 51 /* USB3 A */
+#define RESET_APMU_USB3_B_AHB 52
#define RESET_APMU_DSI4LN2_ESCCLK 53
#define RESET_APMU_DSI4LN2_LCD_SW 54
#define RESET_APMU_DSI4LN2_LCD_MCLK 55
@@ -143,16 +143,40 @@
#define RESET_APMU_UFS_ACLK 59
#define RESET_APMU_EDP0 60
#define RESET_APMU_EDP1 61
-#define RESET_APMU_PCIE_PORTA 62
-#define RESET_APMU_PCIE_PORTB 63
-#define RESET_APMU_PCIE_PORTC 64
-#define RESET_APMU_PCIE_PORTD 65
-#define RESET_APMU_PCIE_PORTE 66
+#define RESET_APMU_USB3_B_VCC 62 /* USB3 B */
+#define RESET_APMU_USB3_B_PHY 63
+#define RESET_APMU_USB3_C_AHB 64
+#define RESET_APMU_USB3_C_VCC 65
+#define RESET_APMU_USB3_C_PHY 66
#define RESET_APMU_EMAC0 67
#define RESET_APMU_EMAC1 68
#define RESET_APMU_EMAC2 69
#define RESET_APMU_ESPI_MCLK 70
#define RESET_APMU_ESPI_SCLK 71
+#define RESET_APMU_USB3_D_AHB 72 /* USB3 D */
+#define RESET_APMU_USB3_D_VCC 73
+#define RESET_APMU_USB3_D_PHY 74
+#define RESET_APMU_UCIE_IP 75
+#define RESET_APMU_UCIE_HOT 76
+#define RESET_APMU_UCIE_MON 77
+#define RESET_APMU_RCPU_AUDIO_SYS 78
+#define RESET_APMU_RCPU_MCU_CORE 79
+#define RESET_APMU_RCPU_AUDIO_APMU 80
+#define RESET_APMU_PCIE_A_DBI 81
+#define RESET_APMU_PCIE_A_SLAVE 82
+#define RESET_APMU_PCIE_A_MASTER 83
+#define RESET_APMU_PCIE_B_DBI 84
+#define RESET_APMU_PCIE_B_SLAVE 85
+#define RESET_APMU_PCIE_B_MASTER 86
+#define RESET_APMU_PCIE_C_DBI 87
+#define RESET_APMU_PCIE_C_SLAVE 88
+#define RESET_APMU_PCIE_C_MASTER 89
+#define RESET_APMU_PCIE_D_DBI 90
+#define RESET_APMU_PCIE_D_SLAVE 91
+#define RESET_APMU_PCIE_D_MASTER 92
+#define RESET_APMU_PCIE_E_DBI 93
+#define RESET_APMU_PCIE_E_SLAVE 94
+#define RESET_APMU_PCIE_E_MASTER 95
/* DCIU resets*/
#define RESET_DCIU_HDMA 0
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
index 46514cb1b9e0..52a5a4e81f18 100644
--- a/include/linux/reset-controller.h
+++ b/include/linux/reset-controller.h
@@ -3,7 +3,10 @@
#define _LINUX_RESET_CONTROLLER_H_
#include <linux/list.h>
+#include <linux/mutex.h>
+struct fwnode_handle;
+struct fwnode_reference_args;
struct reset_controller_dev;
/**
@@ -35,14 +38,16 @@ struct of_phandle_args;
* @reset_control_head: head of internal list of requested reset controls
* @dev: corresponding driver model device struct
* @of_node: corresponding device tree node as phandle target
- * @of_args: for reset-gpios controllers: corresponding phandle args with
- * of_node and GPIO number complementing of_node; either this or
- * of_node should be present
* @of_reset_n_cells: number of cells in reset line specifiers
* @of_xlate: translation function to translate from specifier as found in the
- * device tree to id as given to the reset control ops, defaults
- * to :c:func:`of_reset_simple_xlate`.
+ * device tree to id as given to the reset control ops
+ * @fwnode: firmware node associated with this device
+ * @fwnode_reset_n_cells: number of cells in reset line specifiers
+ * @fwnode_xlate: translation function to translate from firmware specifier to
+ * id as given to the reset control ops, defaults to
+ * :c:func:`fwnode_reset_simple_xlate`
* @nr_resets: number of reset controls in this reset controller device
+ * @lock: protects the reset control list from concurrent access
*/
struct reset_controller_dev {
const struct reset_control_ops *ops;
@@ -51,11 +56,15 @@ struct reset_controller_dev {
struct list_head reset_control_head;
struct device *dev;
struct device_node *of_node;
- const struct of_phandle_args *of_args;
int of_reset_n_cells;
int (*of_xlate)(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec);
+ struct fwnode_handle *fwnode;
+ int fwnode_reset_n_cells;
+ int (*fwnode_xlate)(struct reset_controller_dev *rcdev,
+ const struct fwnode_reference_args *reset_spec);
unsigned int nr_resets;
+ struct mutex lock;
};
#if IS_ENABLED(CONFIG_RESET_CONTROLLER)
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 44f9e3415f92..9c391cf0c822 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -5,10 +5,12 @@
#include <linux/bits.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/of.h>
#include <linux/types.h>
struct device;
struct device_node;
+struct fwnode_handle;
struct reset_control;
/**
@@ -84,7 +86,7 @@ int reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *r
int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs);
void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs);
-struct reset_control *__of_reset_control_get(struct device_node *node,
+struct reset_control *__fwnode_reset_control_get(struct fwnode_handle *fwnode,
const char *id, int index, enum reset_control_flags flags);
struct reset_control *__reset_control_get(struct device *dev, const char *id,
int index, enum reset_control_flags flags);
@@ -103,7 +105,8 @@ int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
struct reset_control *devm_reset_control_array_get(struct device *dev,
enum reset_control_flags flags);
-struct reset_control *of_reset_control_array_get(struct device_node *np, enum reset_control_flags);
+struct reset_control *fwnode_reset_control_array_get(struct fwnode_handle *fwnode,
+ enum reset_control_flags);
int reset_control_get_count(struct device *dev);
@@ -152,8 +155,8 @@ static inline int __device_reset(struct device *dev, bool optional)
return optional ? 0 : -ENOTSUPP;
}
-static inline struct reset_control *__of_reset_control_get(
- struct device_node *node,
+static inline struct reset_control *__fwnode_reset_control_get(
+ struct fwnode_handle *fwnode,
const char *id, int index, enum reset_control_flags flags)
{
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
@@ -242,7 +245,7 @@ devm_reset_control_array_get(struct device *dev, enum reset_control_flags flags)
}
static inline struct reset_control *
-of_reset_control_array_get(struct device_node *np, enum reset_control_flags flags)
+fwnode_reset_control_array_get(struct fwnode_handle *fwnode, enum reset_control_flags flags)
{
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
@@ -500,7 +503,8 @@ reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs,
static inline struct reset_control *of_reset_control_get_exclusive(
struct device_node *node, const char *id)
{
- return __of_reset_control_get(node, id, 0, RESET_CONTROL_EXCLUSIVE);
+ return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0,
+ RESET_CONTROL_EXCLUSIVE);
}
/**
@@ -520,7 +524,8 @@ static inline struct reset_control *of_reset_control_get_exclusive(
static inline struct reset_control *of_reset_control_get_optional_exclusive(
struct device_node *node, const char *id)
{
- return __of_reset_control_get(node, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
+ return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0,
+ RESET_CONTROL_OPTIONAL_EXCLUSIVE);
}
/**
@@ -545,7 +550,8 @@ static inline struct reset_control *of_reset_control_get_optional_exclusive(
static inline struct reset_control *of_reset_control_get_shared(
struct device_node *node, const char *id)
{
- return __of_reset_control_get(node, id, 0, RESET_CONTROL_SHARED);
+ return __fwnode_reset_control_get(of_fwnode_handle(node), id, 0,
+ RESET_CONTROL_SHARED);
}
/**
@@ -562,7 +568,8 @@ static inline struct reset_control *of_reset_control_get_shared(
static inline struct reset_control *of_reset_control_get_exclusive_by_index(
struct device_node *node, int index)
{
- return __of_reset_control_get(node, NULL, index, RESET_CONTROL_EXCLUSIVE);
+ return __fwnode_reset_control_get(of_fwnode_handle(node), NULL, index,
+ RESET_CONTROL_EXCLUSIVE);
}
/**
@@ -590,7 +597,8 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
static inline struct reset_control *of_reset_control_get_shared_by_index(
struct device_node *node, int index)
{
- return __of_reset_control_get(node, NULL, index, RESET_CONTROL_SHARED);
+ return __fwnode_reset_control_get(of_fwnode_handle(node), NULL, index,
+ RESET_CONTROL_SHARED);
}
/**
@@ -1032,30 +1040,35 @@ devm_reset_control_array_get_optional_shared(struct device *dev)
static inline struct reset_control *
of_reset_control_array_get_exclusive(struct device_node *node)
{
- return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE);
+ return fwnode_reset_control_array_get(of_fwnode_handle(node),
+ RESET_CONTROL_EXCLUSIVE);
}
static inline struct reset_control *
of_reset_control_array_get_exclusive_released(struct device_node *node)
{
- return of_reset_control_array_get(node, RESET_CONTROL_EXCLUSIVE_RELEASED);
+ return fwnode_reset_control_array_get(of_fwnode_handle(node),
+ RESET_CONTROL_EXCLUSIVE_RELEASED);
}
static inline struct reset_control *
of_reset_control_array_get_shared(struct device_node *node)
{
- return of_reset_control_array_get(node, RESET_CONTROL_SHARED);
+ return fwnode_reset_control_array_get(of_fwnode_handle(node),
+ RESET_CONTROL_SHARED);
}
static inline struct reset_control *
of_reset_control_array_get_optional_exclusive(struct device_node *node)
{
- return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
+ return fwnode_reset_control_array_get(of_fwnode_handle(node),
+ RESET_CONTROL_OPTIONAL_EXCLUSIVE);
}
static inline struct reset_control *
of_reset_control_array_get_optional_shared(struct device_node *node)
{
- return of_reset_control_array_get(node, RESET_CONTROL_OPTIONAL_SHARED);
+ return fwnode_reset_control_array_get(of_fwnode_handle(node),
+ RESET_CONTROL_OPTIONAL_SHARED);
}
#endif