Linux clock drivers for rockchip SoCs have to convenience functions that weren't ported: rockchip_register_restart_notifier() rockchip_register_softrst() They control system and peripheral reset, respectively. Port both. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- Hello Sascha, I ported these over for rk3399, but I see, you might need them too, so sending these out early. Ported from v5.13. --- drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk.c | 26 ++++++++ drivers/clk/rockchip/clk.h | 17 +++++ drivers/clk/rockchip/softrst.c | 110 +++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 drivers/clk/rockchip/softrst.c diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 4c387b3a890e..a2461d16c10d 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y += clk-cpu.o clk-pll.o clk.o clk-muxgrf.o clk-mmc-phase.o clk-inverter.o +obj-$(CONFIG_RESET_CONTROLLER) += softrst.o obj-$(CONFIG_ARCH_RK3188) += clk-rk3188.o obj-$(CONFIG_ARCH_RK3288) += clk-rk3288.o obj-$(CONFIG_ARCH_RK3568) += clk-rk3568.o diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index dd542c2e2060..613b168b4d96 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -21,6 +21,7 @@ #include <mfd/syscon.h> #include <linux/spinlock.h> #include <linux/rational.h> +#include <restart.h> #include "clk.h" /* @@ -545,3 +546,28 @@ void rockchip_clk_protect_critical(const char *const clocks[], } } EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical); + +static void rockchip_restart(struct restart_handler *this) +{ + struct rockchip_clk_provider *ctx = + container_of(this, struct rockchip_clk_provider, restart_handler); + + writel(0xfdb9, ctx->reg_base + ctx->reg_restart); + mdelay(1000); +} + +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg) +{ + int ret; + + ctx->restart_handler.name = "rockchip-pmu", + ctx->restart_handler.restart = rockchip_restart, + ctx->restart_handler.priority = RESTART_DEFAULT_PRIORITY, + + ret = restart_handler_register(&ctx->restart_handler); + if (ret) + pr_err("%s: cannot register restart handler, %d\n", + __func__, ret); +} +EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index c17da6e66386..2616277bb049 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -19,6 +19,7 @@ #include <io.h> #include <linux/clk.h> +#include <restart.h> struct clk; #define writel_relaxed writel @@ -268,6 +269,8 @@ struct rockchip_clk_provider { struct clk_onecell_data clk_data; struct device_node *cru_node; struct regmap *grf; + struct restart_handler restart_handler; + unsigned int reg_restart; spinlock_t lock; }; @@ -806,6 +809,20 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, const struct rockchip_cpuclk_rate_table *rates, int nrates); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg); + +#ifdef CONFIG_RESET_CONTROLLER +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags); +#else +static inline void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ +} +#endif #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c new file mode 100644 index 000000000000..e3f3937ca019 --- /dev/null +++ b/drivers/clk/rockchip/softrst.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@xxxxxxxxx> + */ + +#include <common.h> +#include <io.h> +#include <linux/bitops.h> +#include <linux/reset-controller.h> +#include <linux/spinlock.h> +#include "clk.h" + +struct rockchip_softrst { + struct reset_controller_dev rcdev; + void __iomem *reg_base; + int num_regs; + int num_per_reg; + u8 flags; + spinlock_t lock; +}; + +static int rockchip_softrst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank = id / softrst->num_per_reg; + int offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel(BIT(offset) | (BIT(offset) << 16), + softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg | BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank = id / softrst->num_per_reg; + int offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel((BIT(offset) << 16), softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static const struct reset_control_ops rockchip_softrst_ops = { + .assert = rockchip_softrst_assert, + .deassert = rockchip_softrst_deassert, +}; + +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ + struct rockchip_softrst *softrst; + int ret; + + softrst = kzalloc(sizeof(*softrst), GFP_KERNEL); + if (!softrst) + return; + + spin_lock_init(&softrst->lock); + + softrst->reg_base = base; + softrst->flags = flags; + softrst->num_regs = num_regs; + softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 + : 32; + + softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg; + softrst->rcdev.ops = &rockchip_softrst_ops; + softrst->rcdev.of_node = np; + ret = reset_controller_register(&softrst->rcdev); + if (ret) { + pr_err("%s: could not register reset controller, %d\n", + __func__, ret); + kfree(softrst); + } +}; +EXPORT_SYMBOL_GPL(rockchip_register_softrst); -- 2.29.2 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox