Reset controller updates for v6.16

* Add T-HEAD TH1520 and Renesas RZ/V2H(P) USB2PHY reset controller
   drivers.
 * Add devm_reset_control_array_get_exclusive_released() variant to allow
   using the acquire/release hand-off mechanism for exclusive reset
   controls bundled into reset control arrays.
 * Add Sophgo SG2044 reset controller to device tree bindings.
 -----BEGIN PGP SIGNATURE-----
 
 iI0EABYIADUWIQRRO6F6WdpH1R0vGibVhaclGDdiwAUCaCL/7xcccC56YWJlbEBw
 ZW5ndXRyb25peC5kZQAKCRDVhaclGDdiwJd2AP9X3ZZicbRqxdKmcQFOp8Z6SAGI
 MJJqENBDHn6hnpIdAgEAjx8mRRjLY7JTgcf03sOsGHypV1Ay46uGDNoQM9eRkgw=
 =5611
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmguB28ACgkQmmx57+YA
 GNmqKxAAitU9jR468IK6CiijcwskOlAKHuMK9xrdcTL7sGNTtSEj7fCRCTLZNr+/
 xoGYDzV3aVbhWHonN00Wg32lrApCsrr/NqG1B5XCSOJKokaGPl/lb4mooxOvLUSJ
 8U9pxTdh6z4cmM8ofq0MgbQc2FHZIy+F6JszHaLFIuBXs3fkT44w5ZydbvzR4wON
 QN/+ypuWC/sVF3RG1Vg9xKRXoyTLxFV6eVysVLn1V6CrCTlKqsxglN5MePirk+yA
 kE6WcfoQxRYEj6NFGBxeIVaSmOv0CyuR5yWBM1ryy62CVF9LTWS6/nk+Vpomb56h
 /tKDvxZRJdPJ0ddzdsQnlLG/wLRwcFeFQqHuOXuljmMBaanZphNxfyahgD1QfWIn
 EM4KLbsJUzC/WUVKr7B5pn6w5yutNjqZlfUIatM8evhmvrMmcb9DoU5HHyskpQ7M
 2I3ZK23uArFv62//e10z4uVgssO97IHFlxWQMCXKeXouIkkhPhILFQZlN9j3pr0T
 UlCbd6Qn/hwtsNV6bcoBDIDA0AsEQI5B2a/lutGXZ1Ebd+EirFnEdukSyfSpViDY
 kP1sajgZ2tyNMxkTATK0DFbu624o+Hzyh6Am5Y1iSHGa215KVLgcPBUyvNMfh1tZ
 H6o/ZHgLFOQBDEwnW2U1GHgwTEIvUtxAtYPF86F8rfvno3XL2vg=
 =ZnDG
 -----END PGP SIGNATURE-----

Merge tag 'reset-for-v6.16' of git://git.pengutronix.de/pza/linux into soc/drivers

Reset controller updates for v6.16

* Add T-HEAD TH1520 and Renesas RZ/V2H(P) USB2PHY reset controller
  drivers.
* Add devm_reset_control_array_get_exclusive_released() variant to allow
  using the acquire/release hand-off mechanism for exclusive reset
  controls bundled into reset control arrays.
* Add Sophgo SG2044 reset controller to device tree bindings.

* tag 'reset-for-v6.16' of git://git.pengutronix.de/pza/linux:
  dt-bindings: reset: sophgo: Add SG2044 bindings.
  MAINTAINERS: Add entry for Renesas RZ/V2H(P) USB2PHY Port Reset driver
  reset: Add USB2PHY port reset driver for Renesas RZ/V2H(P)
  dt-bindings: reset: Document RZ/V2H(P) USB2PHY reset
  reset: Add devm_reset_control_array_get_exclusive_released()
  reset: thead: Add TH1520 reset controller driver
  dt-bindings: reset: Add T-HEAD TH1520 SoC Reset Controller

Link: https://lore.kernel.org/r/20250513092516.3331585-1-p.zabel@pengutronix.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2025-05-21 19:03:42 +02:00
commit a97bf0c6aa
10 changed files with 529 additions and 1 deletions

View File

@ -0,0 +1,56 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/renesas,rzv2h-usb2phy-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/V2H(P) USB2PHY Port reset Control
maintainers:
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
description:
The RZ/V2H(P) USB2PHY Control mainly controls Port reset and power down of the
USB2.0 PHY.
properties:
compatible:
const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
reg:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
power-domains:
maxItems: 1
'#reset-cells':
const: 0
required:
- compatible
- reg
- clocks
- resets
- power-domains
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/renesas,r9a09g057-cpg.h>
reset-controller@15830000 {
compatible = "renesas,r9a09g057-usb2phy-reset";
reg = <0x15830000 0x10000>;
clocks = <&cpg CPG_MOD 0xb6>;
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
};

View File

@ -11,7 +11,12 @@ maintainers:
properties:
compatible:
const: sophgo,sg2042-reset
oneOf:
- items:
- enum:
- sophgo,sg2044-reset
- const: sophgo,sg2042-reset
- const: sophgo,sg2042-reset
reg:
maxItems: 1

View File

@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/thead,th1520-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: T-HEAD TH1520 SoC Reset Controller
description:
The T-HEAD TH1520 reset controller is a hardware block that asserts/deasserts
resets for SoC subsystems.
maintainers:
- Michal Wilczynski <m.wilczynski@samsung.com>
properties:
compatible:
enum:
- thead,th1520-reset
reg:
maxItems: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- "#reset-cells"
additionalProperties: false
examples:
- |
soc {
#address-cells = <2>;
#size-cells = <2>;
rst: reset-controller@ffef528000 {
compatible = "thead,th1520-reset";
reg = <0xff 0xef528000 0x0 0x1000>;
#reset-cells = <1>;
};
};

View File

@ -20673,6 +20673,14 @@ S: Maintained
F: Documentation/devicetree/bindings/usb/renesas,rzn1-usbf.yaml
F: drivers/usb/gadget/udc/renesas_usbf.c
RENESAS RZ/V2H(P) USB2PHY PORT RESET DRIVER
M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
L: linux-renesas-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/reset/renesas,rzv2h-usb2phy-reset.yaml
F: drivers/reset/reset-rzv2h-usb2phy.c
RENESAS RZ/V2M I2C DRIVER
M: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
L: linux-i2c@vger.kernel.org
@ -20885,6 +20893,7 @@ F: Documentation/devicetree/bindings/firmware/thead,th1520-aon.yaml
F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml
F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml
F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml
F: Documentation/devicetree/bindings/reset/thead,th1520-reset.yaml
F: arch/riscv/boot/dts/thead/
F: drivers/clk/thead/clk-th1520-ap.c
F: drivers/firmware/thead,th1520-aon.c
@ -20892,8 +20901,10 @@ F: drivers/mailbox/mailbox-th1520.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
F: drivers/pinctrl/pinctrl-th1520.c
F: drivers/pmdomain/thead/
F: drivers/reset/reset-th1520.c
F: include/dt-bindings/clock/thead,th1520-clk-ap.h
F: include/dt-bindings/power/thead,th1520-power.h
F: include/dt-bindings/reset/thead,th1520-reset.h
F: include/linux/firmware/thead/thead,th1520-aon.h
RNBD BLOCK DRIVERS

View File

@ -225,6 +225,13 @@ config RESET_RZG2L_USBPHY_CTRL
Support for USBPHY Control found on RZ/G2L family. It mainly
controls reset and power down of the USB/PHY.
config RESET_RZV2H_USB2PHY
tristate "Renesas RZ/V2H(P) (and similar SoCs) USB2PHY Reset driver"
depends on ARCH_RENESAS || COMPILE_TEST
help
Support for USB2PHY Port reset Control found on the RZ/V2H(P) SoC
(and similar SoCs).
config RESET_SCMI
tristate "Reset driver controlled via ARM SCMI interface"
depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
@ -279,6 +286,16 @@ config RESET_SUNXI
help
This enables the reset driver for Allwinner SoCs.
config RESET_TH1520
tristate "T-HEAD 1520 reset controller"
depends on ARCH_THEAD || COMPILE_TEST
select REGMAP_MMIO
help
This driver provides support for the T-HEAD TH1520 SoC reset controller,
which manages hardware reset lines for SoC components such as the GPU.
Enable this option if you need to control hardware resets on TH1520-based
systems.
config RESET_TI_SCI
tristate "TI System Control Interface (TI-SCI) reset driver"
depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n)

View File

@ -31,11 +31,13 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
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_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o

View File

@ -0,0 +1,236 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/V2H(P) USB2PHY Port reset control driver
*
* Copyright (C) 2025 Renesas Electronics Corporation
*/
#include <linux/cleanup.h>
#include <linux/delay.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/reset.h>
#include <linux/reset-controller.h>
struct rzv2h_usb2phy_regval {
u16 reg;
u16 val;
};
struct rzv2h_usb2phy_reset_of_data {
const struct rzv2h_usb2phy_regval *init_vals;
unsigned int init_val_count;
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 device *dev;
struct reset_controller_dev rcdev;
spinlock_t lock; /* protects register accesses */
};
static inline struct rzv2h_usb2phy_reset_priv
*rzv2h_usbphy_rcdev_to_priv(struct reset_controller_dev *rcdev)
{
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;
}
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;
}
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);
return (reg & priv->data->reset_status_bits) == priv->data->reset_status_bits;
}
static const struct reset_control_ops rzv2h_usbphy_reset_ops = {
.assert = rzv2h_usbphy_reset_assert,
.deassert = rzv2h_usbphy_reset_deassert,
.status = rzv2h_usbphy_reset_status,
};
static int rzv2h_usb2phy_reset_of_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
/* No special handling needed, we have only one reset line per device */
return 0;
}
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;
int error;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
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);
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");
error = pm_runtime_resume_and_get(dev);
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);
pm_runtime_put(dev);
priv->rcdev.ops = &rzv2h_usbphy_reset_ops;
priv->rcdev.of_reset_n_cells = 0;
priv->rcdev.nr_resets = 1;
priv->rcdev.of_xlate = rzv2h_usb2phy_reset_of_xlate;
priv->rcdev.of_node = dev->of_node;
priv->rcdev.dev = dev;
return devm_reset_controller_register(dev, &priv->rcdev);
}
/*
* 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 rzv2h_usb2phy_reset_of_data rzv2h_reset_of_data = {
.init_vals = rzv2h_init_vals,
.init_val_count = ARRAY_SIZE(rzv2h_init_vals),
.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[] = {
{ .compatible = "renesas,r9a09g057-usb2phy-reset", .data = &rzv2h_reset_of_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, rzv2h_usb2phy_reset_of_match);
static struct platform_driver rzv2h_usb2phy_reset_driver = {
.driver = {
.name = "rzv2h_usb2phy_reset",
.of_match_table = rzv2h_usb2phy_reset_of_match,
},
.probe = rzv2h_usb2phy_reset_probe,
};
module_platform_driver(rzv2h_usb2phy_reset_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
MODULE_DESCRIPTION("Renesas RZ/V2H(P) USB2PHY Control");

View File

@ -0,0 +1,135 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd.
* Author: Michal Wilczynski <m.wilczynski@samsung.com>
*/
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/regmap.h>
#include <dt-bindings/reset/thead,th1520-reset.h>
/* register offset in VOSYS_REGMAP */
#define TH1520_GPU_RST_CFG 0x0
#define TH1520_GPU_RST_CFG_MASK GENMASK(1, 0)
/* register values */
#define TH1520_GPU_SW_GPU_RST BIT(0)
#define TH1520_GPU_SW_CLKGEN_RST BIT(1)
struct th1520_reset_priv {
struct reset_controller_dev rcdev;
struct regmap *map;
};
struct th1520_reset_map {
u32 bit;
u32 reg;
};
static const struct th1520_reset_map th1520_resets[] = {
[TH1520_RESET_ID_GPU] = {
.bit = TH1520_GPU_SW_GPU_RST,
.reg = TH1520_GPU_RST_CFG,
},
[TH1520_RESET_ID_GPU_CLKGEN] = {
.bit = TH1520_GPU_SW_CLKGEN_RST,
.reg = TH1520_GPU_RST_CFG,
}
};
static inline struct th1520_reset_priv *
to_th1520_reset(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct th1520_reset_priv, rcdev);
}
static int th1520_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
const struct th1520_reset_map *reset;
reset = &th1520_resets[id];
return regmap_update_bits(priv->map, reset->reg, reset->bit, 0);
}
static int th1520_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
const struct th1520_reset_map *reset;
reset = &th1520_resets[id];
return regmap_update_bits(priv->map, reset->reg, reset->bit,
reset->bit);
}
static const struct reset_control_ops th1520_reset_ops = {
.assert = th1520_reset_assert,
.deassert = th1520_reset_deassert,
};
static const struct regmap_config th1520_reset_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
};
static int th1520_reset_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct th1520_reset_priv *priv;
void __iomem *base;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
priv->map = devm_regmap_init_mmio(dev, base,
&th1520_reset_regmap_config);
if (IS_ERR(priv->map))
return PTR_ERR(priv->map);
/* Initialize GPU resets to asserted state */
ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG,
TH1520_GPU_RST_CFG_MASK, 0);
if (ret)
return ret;
priv->rcdev.owner = THIS_MODULE;
priv->rcdev.nr_resets = ARRAY_SIZE(th1520_resets);
priv->rcdev.ops = &th1520_reset_ops;
priv->rcdev.of_node = dev->of_node;
return devm_reset_controller_register(dev, &priv->rcdev);
}
static const struct of_device_id th1520_reset_match[] = {
{ .compatible = "thead,th1520-reset" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, th1520_reset_match);
static struct platform_driver th1520_reset_driver = {
.driver = {
.name = "th1520-reset",
.of_match_table = th1520_reset_match,
},
.probe = th1520_reset_probe,
};
module_platform_driver(th1520_reset_driver);
MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd.
* Author: Michal Wilczynski <m.wilczynski@samsung.com>
*/
#ifndef _DT_BINDINGS_TH1520_RESET_H
#define _DT_BINDINGS_TH1520_RESET_H
#define TH1520_RESET_ID_GPU 0
#define TH1520_RESET_ID_GPU_CLKGEN 1
#define TH1520_RESET_ID_NPU 2
#define TH1520_RESET_ID_WDT0 3
#define TH1520_RESET_ID_WDT1 4
#endif /* _DT_BINDINGS_TH1520_RESET_H */

View File

@ -1004,6 +1004,12 @@ devm_reset_control_array_get_exclusive(struct device *dev)
return devm_reset_control_array_get(dev, RESET_CONTROL_EXCLUSIVE);
}
static inline struct reset_control *
devm_reset_control_array_get_exclusive_released(struct device *dev)
{
return devm_reset_control_array_get(dev, RESET_CONTROL_EXCLUSIVE_RELEASED);
}
static inline struct reset_control *
devm_reset_control_array_get_shared(struct device *dev)
{