reset: rockchip: implement rk3588 lookup table
The current DT bindings for the rk3588 clock use a different ID than the
one that is supposed to be written to the hardware registers.
Thus, we cannot use directly the id provided in the phandle, but rather
use a lookup table to correctly setup the hardware.
This approach has been implemented already in Linux, by commit :
f1c506d152ff ("clk: rockchip: add clock controller for the RK3588")
Hence, implement a similar approach using the lookup table, and adapt
the existing reset driver to work with SoCs using lookup table.
The file rst-rk3588.c has been copied as much as possible from Linux.
Adapt the clk rk3588 driver as well to bind the reset driver with the
lookup table.
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
diff --git a/drivers/reset/reset-rockchip.c b/drivers/reset/reset-rockchip.c
index 732ac34..2ebe338 100644
--- a/drivers/reset/reset-rockchip.c
+++ b/drivers/reset/reset-rockchip.c
@@ -21,6 +21,7 @@
struct rockchip_reset_priv {
void __iomem *base;
+ const int *lut;
/* Rockchip reset reg locate at cru controller */
u32 reset_reg_offset;
/* Rockchip reset reg number */
@@ -30,11 +31,15 @@
static int rockchip_reset_request(struct reset_ctl *reset_ctl)
{
struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+ unsigned long id = reset_ctl->id;
+
+ if (priv->lut)
+ id = priv->lut[id];
debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_num=%d)\n", __func__,
- reset_ctl, reset_ctl->dev, reset_ctl->id, priv->reset_reg_num);
+ reset_ctl, reset_ctl->dev, id, priv->reset_reg_num);
- if (reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num)
+ if (id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num)
return -EINVAL;
return 0;
@@ -43,12 +48,17 @@
static int rockchip_reset_assert(struct reset_ctl *reset_ctl)
{
struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
- int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG;
- int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG;
+ unsigned long id = reset_ctl->id;
+ int bank, offset;
+
+ if (priv->lut)
+ id = priv->lut[id];
+
+ bank = id / ROCKCHIP_RESET_NUM_IN_REG;
+ offset = id % ROCKCHIP_RESET_NUM_IN_REG;
debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__,
- reset_ctl, reset_ctl->dev, reset_ctl->id,
- priv->base + (bank * 4));
+ reset_ctl, reset_ctl->dev, id, priv->base + (bank * 4));
rk_setreg(priv->base + (bank * 4), BIT(offset));
@@ -58,12 +68,17 @@
static int rockchip_reset_deassert(struct reset_ctl *reset_ctl)
{
struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
- int bank = reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG;
- int offset = reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG;
+ unsigned long id = reset_ctl->id;
+ int bank, offset;
+
+ if (priv->lut)
+ id = priv->lut[id];
+
+ bank = id / ROCKCHIP_RESET_NUM_IN_REG;
+ offset = id % ROCKCHIP_RESET_NUM_IN_REG;
debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__,
- reset_ctl, reset_ctl->dev, reset_ctl->id,
- priv->base + (bank * 4));
+ reset_ctl, reset_ctl->dev, id, priv->base + (bank * 4));
rk_clrreg(priv->base + (bank * 4), BIT(offset));
@@ -98,7 +113,10 @@
return 0;
}
-int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number)
+int rockchip_reset_bind_lut(struct udevice *pdev,
+ const int *lookup_table,
+ u32 reg_offset,
+ u32 reg_number)
{
struct udevice *rst_dev;
struct rockchip_reset_priv *priv;
@@ -113,11 +131,17 @@
priv = malloc(sizeof(struct rockchip_reset_priv));
priv->reset_reg_offset = reg_offset;
priv->reset_reg_num = reg_number;
+ priv->lut = lookup_table;
dev_set_priv(rst_dev, priv);
return 0;
}
+int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number)
+{
+ return rockchip_reset_bind_lut(pdev, NULL, reg_offset, reg_number);
+}
+
U_BOOT_DRIVER(rockchip_reset) = {
.name = "rockchip_reset",
.id = UCLASS_RESET,