]> git.sur5r.net Git - u-boot/commitdiff
Merge git://git.denx.de/u-boot-rockchip
authorTom Rini <trini@konsulko.com>
Tue, 9 Jan 2018 18:28:51 +0000 (13:28 -0500)
committerTom Rini <trini@konsulko.com>
Tue, 9 Jan 2018 18:28:51 +0000 (13:28 -0500)
12 files changed:
arch/arm/include/asm/arch-rockchip/clock.h
drivers/clk/rockchip/clk_rk3036.c
drivers/clk/rockchip/clk_rk3188.c
drivers/clk/rockchip/clk_rk322x.c
drivers/clk/rockchip/clk_rk3288.c
drivers/clk/rockchip/clk_rk3328.c
drivers/clk/rockchip/clk_rk3368.c
drivers/clk/rockchip/clk_rk3399.c
drivers/clk/rockchip/clk_rv1108.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-rockchip.c [new file with mode: 0644]

index 736b2603fdadea83a42e193874c73c4c0ae26049..52641116f33af4f2fc6053bc7aa30a71f059b99e 100644 (file)
@@ -85,4 +85,14 @@ void rk3288_clk_configure_cpu(struct rk3288_cru *cru, struct rk3288_grf *grf);
 
 int rockchip_get_clk(struct udevice **devp);
 
+/*
+ * rockchip_reset_bind() - Bind soft reset device as child of clock device
+ *
+ * @pdev: clock udevice
+ * @reg_offset: the first offset in cru for softreset registers
+ * @reg_number: the reg numbers of softreset registers
+ * @return 0 success, or error value
+ */
+int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number);
+
 #endif
index 280ebb9ba2e6a0e13844c471ba7fe78b1a0612f3..510a00a3aaf32f0a33f54335c2d6bda87f4eb505 100644 (file)
@@ -347,6 +347,13 @@ static int rk3036_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3036_cru, cru_softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 9);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
index fca6899d8b6ec6164a71bb4ab9dafc789a46cd0f..6451c95a320cc2f88f29dd75c0075cd21fd35a91 100644 (file)
@@ -590,6 +590,13 @@ static int rk3188_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3188_cru, cru_softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 9);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
index ff52b5522903ea026c779cbc93e4faf9e1234366..c8a241355a2288b15ccaf90118e67ac0d1eb01a5 100644 (file)
@@ -402,6 +402,13 @@ static int rk322x_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk322x_cru, cru_softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 9);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
index ac53239363c7478bc0d7f86f26f17983437b21ff..b64c1071c1ff2584ca5c0a60a003729f8e36c958 100644 (file)
@@ -876,6 +876,13 @@ static int rk3288_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3288_cru, cru_softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 12);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
index 4d522a781647492d4810dda9034b673138c86828..fa0c777044b397877ce6331d57576d94cb183667 100644 (file)
@@ -614,6 +614,13 @@ static int rk3328_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3328_cru, softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 12);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return ret;
 }
 
index bfeef39d2a263f51518e67b9e73de94bed623859..a8319917bb5585a4ac605df6d01940706684ad20 100644 (file)
@@ -543,6 +543,13 @@ static int rk3368_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3368_cru, softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 15);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return ret;
 }
 
index 2e85ac7df2ce2980841b5b9a2439e78a289b89f7..2f4c4e343cf96d1a877b792adcd90c15dc324c25 100644 (file)
@@ -1046,6 +1046,13 @@ static int rk3399_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3399_cru, softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 21);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
@@ -1221,6 +1228,19 @@ static int rk3399_pmuclk_ofdata_to_platdata(struct udevice *dev)
        return 0;
 }
 
+static int rk3399_pmuclk_bind(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       int ret;
+
+       ret = offsetof(struct rk3399_pmucru, pmucru_softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 2);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+       return 0;
+}
+
 static const struct udevice_id rk3399_pmuclk_ids[] = {
        { .compatible = "rockchip,rk3399-pmucru" },
        { }
@@ -1234,6 +1254,7 @@ U_BOOT_DRIVER(rockchip_rk3399_pmuclk) = {
        .ofdata_to_platdata = rk3399_pmuclk_ofdata_to_platdata,
        .ops            = &rk3399_pmuclk_ops,
        .probe          = rk3399_pmuclk_probe,
+       .bind           = rk3399_pmuclk_bind,
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
        .platdata_auto_alloc_size = sizeof(struct rk3399_pmuclk_plat),
 #endif
index a1195486a9aafe0c1f9a18a9923a614e81870de4..224c81355ee4ad563c18f44753596057c0b59db7 100644 (file)
@@ -240,6 +240,13 @@ static int rv1108_clk_bind(struct udevice *dev)
                sys_child->priv = priv;
        }
 
+#if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
+       ret = offsetof(struct rk3368_cru, softrst_con[0]);
+       ret = rockchip_reset_bind(dev, ret, 13);
+       if (ret)
+               debug("Warning: software reset driver bind faile\n");
+#endif
+
        return 0;
 }
 
index ce46e2752c256873ddbf29bc0d47ff2605becdd2..3964b9eb6e18b208c689e731e23edb42c96b4b22 100644 (file)
@@ -74,4 +74,13 @@ config AST2500_RESET
          resets that are supported by watchdog. The main limitation though
          is that some reset signals, like I2C or MISC reset multiple devices.
 
+config RESET_ROCKCHIP
+       bool "Reset controller driver for Rockchip SoCs"
+       depends on DM_RESET && ARCH_ROCKCHIP && CLK
+       default y
+       help
+         Support for reset controller on rockchip SoC. The main limitation
+         though is that some reset signals, like I2C or MISC reset multiple
+         devices.
+
 endmenu
index 252cefeed5b0cda84f0c5d519d43400ed816d5c3..7d7e080c78469067a00e24812299f3595522505a 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
 obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
+obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
diff --git a/drivers/reset/reset-rockchip.c b/drivers/reset/reset-rockchip.c
new file mode 100644 (file)
index 0000000..01047a2
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <linux/io.h>
+#include <asm/arch/hardware.h>
+#include <dm/lists.h>
+/*
+ * Each reg has 16 bits reset signal for devices
+ * Note: Not including rk2818 and older SoCs
+ */
+#define ROCKCHIP_RESET_NUM_IN_REG      16
+
+struct rockchip_reset_priv {
+       void __iomem *base;
+       /* Rockchip reset reg locate at cru controller */
+       u32 reset_reg_offset;
+       /* Rockchip reset reg number */
+       u32 reset_reg_num;
+};
+
+static int rockchip_reset_request(struct reset_ctl *reset_ctl)
+{
+       struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+
+       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);
+
+       if (reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG >= priv->reset_reg_num)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int rockchip_reset_free(struct reset_ctl *reset_ctl)
+{
+       debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+             reset_ctl->dev, reset_ctl->id);
+
+       return 0;
+}
+
+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;
+
+       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));
+
+       rk_setreg(priv->base + (bank * 4), BIT(offset));
+
+       return 0;
+}
+
+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;
+
+       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));
+
+       rk_clrreg(priv->base + (bank * 4), BIT(offset));
+
+       return 0;
+}
+
+struct reset_ops rockchip_reset_ops = {
+       .request = rockchip_reset_request,
+       .free = rockchip_reset_free,
+       .rst_assert = rockchip_reset_assert,
+       .rst_deassert = rockchip_reset_deassert,
+};
+
+static int rockchip_reset_probe(struct udevice *dev)
+{
+       struct rockchip_reset_priv *priv = dev_get_priv(dev);
+       fdt_addr_t addr;
+       fdt_size_t size;
+
+       addr = dev_read_addr_size(dev, "reg", &size);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       if ((priv->reset_reg_offset == 0) && (priv->reset_reg_num == 0))
+               return -EINVAL;
+
+       addr += priv->reset_reg_offset;
+       priv->base = ioremap(addr, size);
+
+       debug("%s(base=%p) (reg_offset=%x, reg_num=%d)\n", __func__,
+             priv->base, priv->reset_reg_offset, priv->reset_reg_num);
+
+       return 0;
+}
+
+int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number)
+{
+       struct udevice *rst_dev;
+       struct rockchip_reset_priv *priv;
+       int ret;
+
+        ret = device_bind_driver_to_node(pdev, "rockchip_reset", "reset",
+                                         dev_ofnode(pdev), &rst_dev);
+       if (ret) {
+               debug("Warning: No rockchip reset driver: ret=%d\n", ret);
+               return ret;
+       }
+       priv = malloc(sizeof(struct rockchip_reset_priv));
+       priv->reset_reg_offset = reg_offset;
+       priv->reset_reg_num = reg_number;
+       rst_dev->priv = priv;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(rockchip_reset) = {
+       .name = "rockchip_reset",
+       .id = UCLASS_RESET,
+       .probe = rockchip_reset_probe,
+       .ops = &rockchip_reset_ops,
+       .priv_auto_alloc_size = sizeof(struct rockchip_reset_priv),
+};