Implement the sysreset get_status() ops and return same value as the
existing get_reset_cause() helper used for DISPLAY_CPUINFO. Only include
the ops in U-Boot proper to avoid increasing code size for xPL builds.

Signed-off-by: Jonas Karlman <[email protected]>
---
 drivers/sysreset/sysreset_rockchip.c | 52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/sysreset/sysreset_rockchip.c 
b/drivers/sysreset/sysreset_rockchip.c
index 27ba4ee0667c..4b10d6bb762e 100644
--- a/drivers/sysreset/sysreset_rockchip.c
+++ b/drivers/sysreset/sysreset_rockchip.c
@@ -11,8 +11,19 @@
 #include <asm/arch-rockchip/clock.h>
 #include <asm/arch-rockchip/hardware.h>
 
+enum {
+       GLB_POR_RST,
+       FST_GLB_RST_ST          = BIT(0),
+       SND_GLB_RST_ST          = BIT(1),
+       FST_GLB_TSADC_RST_ST    = BIT(2),
+       SND_GLB_TSADC_RST_ST    = BIT(3),
+       FST_GLB_WDT_RST_ST      = BIT(4),
+       SND_GLB_WDT_RST_ST      = BIT(5),
+};
+
 struct sysreset_reg {
        unsigned long cru_base;
+       unsigned int glb_rst_st;
        unsigned int glb_srst_fst;
        unsigned int glb_srst_snd;
 };
@@ -38,8 +49,48 @@ static int rockchip_sysreset_request(struct udevice *dev, 
enum sysreset_t type)
        return -EINPROGRESS;
 }
 
+static const char __maybe_unused *rockchip_sysreset_get_cause(u32 data)
+{
+       if (data == GLB_POR_RST)
+               return "POR";
+       else if (data & (FST_GLB_RST_ST | SND_GLB_RST_ST))
+               return "RST";
+       else if (data & (FST_GLB_TSADC_RST_ST | SND_GLB_TSADC_RST_ST))
+               return "THERMAL";
+       else if (data & (FST_GLB_WDT_RST_ST | SND_GLB_WDT_RST_ST))
+               return "WDOG";
+       else
+               return NULL;
+}
+
+static int __maybe_unused rockchip_sysreset_get_status(struct udevice *dev,
+                                                      char *buf, int size)
+{
+       struct sysreset_reg *priv = dev_get_priv(dev);
+       const char *cause;
+       u32 data;
+
+       if (!buf || size <= 0)
+               return -EINVAL;
+
+       if (!priv->cru_base || !priv->glb_rst_st)
+               return -ENOSYS;
+
+       data = readl(priv->cru_base + priv->glb_rst_st);
+       cause = rockchip_sysreset_get_cause(data);
+       if (!cause)
+               return -ENODATA;
+
+       strlcpy(buf, cause, size);
+
+       return 0;
+}
+
 static struct sysreset_ops rockchip_sysreset = {
        .request        = rockchip_sysreset_request,
+#if !IS_ENABLED(CONFIG_XPL_BUILD)
+       .get_status     = rockchip_sysreset_get_status,
+#endif
 };
 
 U_BOOT_DRIVER(sysreset_rockchip) = {
@@ -68,6 +119,7 @@ int rockchip_sysreset_bind(struct udevice *pdev,
                return -ENOMEM;
 
        priv->cru_base = cru_base;
+       priv->glb_rst_st = glb_rst_st;
        priv->glb_srst_fst = glb_srst_fst;
        priv->glb_srst_snd = glb_srst_snd;
        dev_set_priv(sysreset_dev, priv);
-- 
2.54.0

Reply via email to