diff options
author | Eugen Hristev <eugen.hristev@collabora.com> | 2023-05-15 13:55:04 +0300 |
---|---|---|
committer | Kever Yang <kever.yang@rock-chips.com> | 2023-05-17 17:36:18 +0800 |
commit | bb52f1c604d09b0c378addfa5c75c82efc219b03 (patch) | |
tree | af0eb7040455d593aecce1fd8ce250afa45d868b /drivers/reset/reset-rockchip.c | |
parent | 6891bdf711126425f33890ba23fb02ba84b9b698 (diff) |
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>
Diffstat (limited to 'drivers/reset/reset-rockchip.c')
-rw-r--r-- | drivers/reset/reset-rockchip.c | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/reset/reset-rockchip.c b/drivers/reset/reset-rockchip.c index 732ac343b2b..2ebe3382f70 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 @@ struct rockchip_reset_priv { 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_request(struct reset_ctl *reset_ctl) 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_assert(struct reset_ctl *reset_ctl) 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 @@ static int rockchip_reset_probe(struct udevice *dev) 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 @@ int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number) 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, |