mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
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:
commit
a97bf0c6aa
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
11
MAINTAINERS
11
MAINTAINERS
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
236
drivers/reset/reset-rzv2h-usb2phy.c
Normal file
236
drivers/reset/reset-rzv2h-usb2phy.c
Normal 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");
|
||||
135
drivers/reset/reset-th1520.c
Normal file
135
drivers/reset/reset-th1520.c
Normal 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");
|
||||
16
include/dt-bindings/reset/thead,th1520-reset.h
Normal file
16
include/dt-bindings/reset/thead,th1520-reset.h
Normal 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 */
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user