PMU: Power Domain Controller Driver for JH7110 SOC
authorWalker Chen <walker.chen@starfivetech.com>
Fri, 1 Jul 2022 01:49:32 +0000 (09:49 +0800)
committerWalker Chen <walker.chen@starfivetech.com>
Fri, 1 Jul 2022 02:44:20 +0000 (10:44 +0800)
Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
arch/riscv/boot/dts/starfive/jh7110.dtsi
arch/riscv/configs/starfive_jh7110_defconfig
drivers/crypto/starfive/jh7110/jh7110-sec.c [changed mode: 0644->0755]
drivers/i2c/busses/i2c-designware-platdrv.c [changed mode: 0644->0755]
drivers/soc/starfive/Kconfig [changed mode: 0644->0755]
drivers/soc/starfive/jh7110_pmu.c [changed mode: 0644->0755]
include/dt-bindings/power/jh7110-power.h [new file with mode: 0755]
include/soc/starfive/jh7110_pmu.h [deleted file]
sound/soc/dwc/i2srx-master.c

index dcbe71c..5fae7e1 100755 (executable)
@@ -10,6 +10,7 @@
 #include <dt-bindings/clock/starfive-jh7110-clkgen.h>
 #include <dt-bindings/clock/starfive-jh7110-vout.h>
 #include <dt-bindings/clock/starfive-jh7110-isp.h>
+#include <dt-bindings/power/jh7110-power.h>
 
 / {
        compatible = "starfive,jh7110";
                        resets = <&rstgen RSTN_U0_DOM_VOUT_TOP_SRC>;
                        reset-names = "vout_src";
                        #clock-cells = <1>;
+                       power-domains = <&pwrc JH7110_PD_VOUT>;
                        status = "okay";
                };
 
                                 <&rstgen RSTN_U0_NOC_BUS_ISP_AXI_N>;
                        reset-names = "rst_isp_top_n", "rst_isp_top_axi",
                                      "rst_isp_noc_bus_n";
+                       power-domains = <&pwrc JH7110_PD_ISP>;
                        status = "okay";
                };
 
                        status = "okay";
                };
 
-               pmu: pmu@17030000 {
+               pwrc: power-controller@17030000 {
                        compatible = "starfive,jh7110-pmu";
                        reg = <0x0 0x17030000 0x0 0x10000>;
                        interrupts = <111>;
+                       #power-domain-cells = <1>;
                        status = "okay";
                };
 
                                "rst_m31dphy_hw", "rst_m31dphy_b09_always_on",
                                "rst_isp_top_n", "rst_isp_top_axi";
                        interrupts = <92 87>;
-                       starfive,aon-syscon = <&aon_syscon 0x00>;
+                       power-domains = <&pwrc JH7110_PD_ISP>;
                        status = "disabled";
                };
 
                        reg = <0x0 0x100a0000 0x0 0x1000>;
                        clocks = <&clkgen JH7110_SPDIF_CLK_APB>,
                                 <&clkgen JH7110_SPDIF_CLK_CORE>,
-                                <&clkgen JH7110_APB0>,
-                                <&clkgen JH7110_AUDIO_ROOT>,
-                                <&clkgen JH7110_MCLK_INNER>;
-                       clock-names = "spdif-apb", "spdif-core", "apb0",
-                                     "audroot", "mclk_inner";
+                                <&clkgen JH7110_MCLK>;
+                       clock-names = "spdif-apb", "spdif-core", "audioclk";
                        resets = <&rstgen RSTN_U0_CDNS_SPDIF_APB>;
                        reset-names = "rst_apb";
                        interrupts = <84>;
                                        "rst_noc_cpu","rst_noc_axicfg0","rst_noc_apb",
                                        "rst_noc_gpu","rst_noc_vdec","rst_jtag2apb",
                                        "rst_noc_disp","rst_noc_isp","rst_noc_stg","rst_noc_ddrc";
+                       power-domains = <&pwrc JH7110_PD_VOUT>;
                };
 
                encoder: display-encoder {
index e495931..66252c4 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_SOC_STARFIVE=y
 CONFIG_SOC_STARFIVE_JH7110=y
 CONFIG_SMP=y
 CONFIG_HZ_100=y
+CONFIG_PM=y
 # CONFIG_SECCOMP is not set
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -205,6 +206,7 @@ CONFIG_SND_STARFIVE_SPDIF=y
 CONFIG_SND_STARFIVE_SPDIF_PCM=y
 CONFIG_SND_STARFIVE_PWMDAC=y
 CONFIG_SND_STARFIVE_PDM=y
+CONFIG_SND_STARFIVE_TDM=y
 CONFIG_SND_SOC_SPDIF=y
 CONFIG_SND_SOC_WM8960=y
 CONFIG_SND_SIMPLE_CARD=y
@@ -241,6 +243,7 @@ CONFIG_RPMSG_CHAR=y
 CONFIG_RPMSG_VIRTIO=y
 CONFIG_SIFIVE_L2_FLUSH_START=0x40000000
 CONFIG_SIFIVE_L2_FLUSH_SIZE=0x400000000
+CONFIG_STARFIVE_PMU=y
 CONFIG_PWM=y
 CONFIG_PWM_STARFIVE_PTC=y
 CONFIG_PHY_M31_DPHY_RX0=y
old mode 100644 (file)
new mode 100755 (executable)
index b55e743..004e41d
@@ -384,7 +384,8 @@ static int jh7110_cryp_runtime_suspend(struct device *dev)
 {
        struct jh7110_sec_dev *sdev = dev_get_drvdata(dev);
 
-       clk_disable_unprepare(sdev->clk);
+       clk_disable_unprepare(sdev->sec_ahb);
+       clk_disable_unprepare(sdev->sec_hclk);
 
        return 0;
 }
@@ -394,9 +395,15 @@ static int jh7110_cryp_runtime_resume(struct device *dev)
        struct jh7110_sec_dev *sdev = dev_get_drvdata(dev);
        int ret;
 
-       ret = clk_prepare_enable(sdev->clk);
+       ret = clk_prepare_enable(sdev->sec_ahb);
+       if (ret) {
+               dev_err(sdev->dev, "Failed to prepare_enable sec_ahb clock\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(sdev->sec_hclk);
        if (ret) {
-               dev_err(sdev->dev, "Failed to prepare_enable clock\n");
+               dev_err(sdev->dev, "Failed to prepare_enable sec_hclk clock\n");
                return ret;
        }
 
old mode 100644 (file)
new mode 100755 (executable)
index d9c5ad1..dd65935
@@ -392,6 +392,7 @@ static void dw_i2c_plat_complete(struct device *dev)
 #endif
 
 #ifdef CONFIG_PM
+/*
 static int dw_i2c_plat_suspend(struct device *dev)
 {
        struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
@@ -426,8 +427,10 @@ static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
        SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
        SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
 };
+*/
 
-#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
+//#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
+#define DW_I2C_DEV_PMOPS NULL
 #else
 #define DW_I2C_DEV_PMOPS NULL
 #endif
old mode 100644 (file)
new mode 100755 (executable)
index d4b0454..5692254
@@ -2,8 +2,8 @@
 
 config STARFIVE_PMU
        bool "Support PMU for StarFive Soc"
-       depends on SOC_STARFIVE || COMPILE_TEST
-       default SOC_STARFIVE_JH7110
+       depends on PM && (SOC_STARFIVE || COMPILE_TEST)
+       select PM_GENERIC_DOMAINS
        help
-         Support PMU for StarFive Soc.
+         Say y here to enable power domain support.
 
old mode 100644 (file)
new mode 100755 (executable)
index 3731a2f..74f09b7
@@ -1,33 +1,24 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * PMU driver for the StarFive JH7110 SoC
+ * JH7110 Power Domain Controller Driver
  *
- * Copyright (C) 2022 samin <samin.guo@starfivetech.com>
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
  */
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
+
+#include <dt-bindings/power/jh7110-power.h>
 #include <linux/io.h>
-#include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
-#include <soc/starfive/jh7110_pmu.h>
+#include <linux/interrupt.h>
+#include <linux/pm_domain.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 /* register define */
 #define HW_EVENT_TURN_ON_MASK          0x04
 #define HW_EVENT_TURN_OFF_MASK         0x08
 #define SW_TURN_ON_POWER_MODE          0x0C
 #define SW_TURN_OFF_POWER_MODE         0x10
-#define THE_SHOLD_SEQ_TIMEOUT          0x14
-#define POWER_DOMAIN_CASCADE_0         0x18
-#define POWER_DOMAIN_CASCADE_1         0x1C
-#define POWER_DOMAIN_CASCADE_2         0x20
-#define POWER_DOMAIN_CASCADE_3         0x24
-#define POWER_DOMAIN_CASCADE_4         0x28
-#define POWER_DOMAIN_CASCADE_5         0x2C
-#define POWER_DOMAIN_CASCADE_6         0x30
-#define POWER_DOMAIN_CASCADE_7         0x34
-#define POWER_DOMAIN_CASCADE_8         0x38
-#define POWER_DOMAIN_CASCADE_9         0x3C
-#define POWER_DOMAIN_CASCADE_10                0x40
 #define SW_ENCOURAGE                   0x44
 #define PMU_INT_MASK                   0x48
 #define PCH_BYPASS                     0x4C
 #define LP_TIMEOUT                     0x58
 #define HW_TURN_ON_MODE                        0x5C
 #define CURR_POWER_MODE                        0x80
-#define CURR_SEQ_STATE                 0x84
 #define PMU_EVENT_STATUS               0x88
 #define PMU_INT_STATUS                 0x8C
-#define HW_EVENT_RECORD                        0x90
-#define HW_EVENT_TYPE_RECORD           0x94
-#define PCH_PACTIVE_STATUS             0x98
+
+/* sw encourage cfg */
+#define SW_MODE_ENCOURAGE_EN_LO                0x05
+#define SW_MODE_ENCOURAGE_EN_HI                0x50
+#define SW_MODE_ENCOURAGE_DIS_LO       0x0A
+#define SW_MODE_ENCOURAGE_DIS_HI       0xA0
+#define SW_MODE_ENCOURAGE_ON           0xFF
 
 /* pmu int status */
 #define PMU_INT_SEQ_DONE               BIT(0)
 #define PMU_INT_SW_FAIL                        GENMASK(3, 2)
 #define PMU_INT_HW_FAIL                        GENMASK(5, 4)
 #define PMU_INT_PCH_FAIL               GENMASK(8, 6)
-#define PMU_INT_FAIL_MASK              (PMU_INT_SW_FAIL|\
-                                       PMU_INT_HW_FAIL |\
+#define PMU_INT_FAIL_MASK              (PMU_INT_SW_FAIL | \
+                                       PMU_INT_HW_FAIL | \
                                        PMU_INT_PCH_FAIL)
-#define PMU_INT_ALL_MASK               (PMU_INT_SEQ_DONE|\
-                                       PMU_INT_HW_REQ  |\
+#define PMU_INT_ALL_MASK               (PMU_INT_SEQ_DONE | \
+                                       PMU_INT_HW_REQ \
                                        PMU_INT_FAIL_MASK)
 
-/* sw encourage cfg */
-#define SW_MODE_ENCOURAGE_EN_LO                0x05
-#define SW_MODE_ENCOURAGE_EN_HI                0x50
-#define SW_MODE_ENCOURAGE_DIS_LO       0x0A
-#define SW_MODE_ENCOURAGE_DIS_HI       0xA0
-#define SW_MODE_ENCOURAGE_ON           0xFF
-
-u32 power_domain_cascade[] = {
-       GENMASK(4, 0),
-       GENMASK(9, 5),
-       GENMASK(14, 10),
-       GENMASK(19, 15),
-       GENMASK(24, 20),
-       GENMASK(29, 25)
+struct jh7110_power_dev {
+       struct generic_pm_domain genpd;
+       struct jh7110_pmu *power;
+       uint32_t mask;
 };
 
-static void __iomem *pmu_base;
-
-struct starfive_pmu {
-       struct device   *dev;
+struct jh7110_pmu {
+       void __iomem *base;
        spinlock_t lock;
        int irq;
+       struct device *pdev;
+       struct jh7110_power_dev *dev;
+       struct genpd_onecell_data genpd_data;
+       struct generic_pm_domain **genpd;
 };
 
-static inline u32 pmu_readl(u32 offset)
-{
-       return readl(pmu_base + offset);
-}
-
-static inline void pmu_writel(u32 val, u32 offset)
-{
-       writel(val, pmu_base + offset);
-}
-
-static bool pmu_get_current_power_mode(u32 domain)
-{
-       return pmu_readl(CURR_POWER_MODE) & domain;
-}
+struct jh7110_pmu_data {
+       const char * const name;
+       uint8_t bit;
+       unsigned int flags;
+};
 
-static void starfive_pmu_int_enable(u32 mask, bool enable)
+static int jh7110_pmu_get_state(struct jh7110_power_dev *pmd, bool *is_on)
 {
-       u32 val = pmu_readl(PMU_INT_MASK);
+       struct jh7110_pmu *pmu = pmd->power;
 
-       if (enable)
-               val &= ~mask;
-       else
-               val |= mask;
-
-       pmu_writel(val, PMU_INT_MASK);
-}
-/*
- * mask the hw_evnet
- */
-static void starfive_pmu_hw_event_turn_on_mask(u32 hw_event, bool mask)
-{
-       u32 val = pmu_readl(HW_EVENT_TURN_ON_MASK);
+       if (!pmd->mask) {
+               *is_on = false;
+               return -EINVAL;
+       }
 
-       if (mask)
-               val |= hw_event;
-       else
-               val &= ~hw_event;
+       *is_on = __raw_readl(pmu->base + CURR_POWER_MODE) & pmd->mask;
 
-       pmu_writel(val, HW_EVENT_TURN_ON_MASK);
+       return 0;
 }
 
-void starfive_pmu_hw_event_turn_off_mask(u32 mask)
+static int jh7110_pmu_set_state(struct jh7110_power_dev *pmd, bool on)
 {
-       pmu_writel(mask, HW_EVENT_TURN_OFF_MASK);
-}
-EXPORT_SYMBOL(starfive_pmu_hw_event_turn_off_mask);
+       struct jh7110_pmu *pmu = pmd->power;
+       unsigned long flags;
+       uint32_t val;
+       uint32_t mode;
+       uint32_t encourage_lo;
+       uint32_t encourage_hi;
+       bool is_on;
+       int ret;
 
-void starfive_power_domain_set(u32 domain, bool enable)
-{
-       u32 val, mode;
-       u32 encourage_lo, encourage_hi;
+       if (!pmd->mask)
+               return -EINVAL;
+       ret = jh7110_pmu_get_state(pmd, &is_on);
+       if (ret)
+               dev_info(pmu->pdev, "unable to get current state for %s\n",
+                               pmd->genpd.name);
+       if (is_on == on) {
+               dev_info(pmu->pdev, "pm domain is already %sable status.\n",
+                               on ? "en" : "dis");
+               return 0;
+       }
 
-       if (!(pmu_get_current_power_mode(domain) ^ enable))
-               return;
+       spin_lock_irqsave(&pmu->lock, flags);
 
-       if (enable) {
+       if (on) {
                mode = SW_TURN_ON_POWER_MODE;
                encourage_lo = SW_MODE_ENCOURAGE_EN_LO;
                encourage_hi = SW_MODE_ENCOURAGE_EN_HI;
@@ -145,187 +121,226 @@ void starfive_power_domain_set(u32 domain, bool enable)
                encourage_hi = SW_MODE_ENCOURAGE_DIS_HI;
        }
 
-       pr_debug("[pmu]domain: %#x %sable\n", domain, enable ? "en" : "dis");
-       val = pmu_readl(mode);
-       val |= domain;
-       pmu_writel(val, mode);
+       val = __raw_readl(pmu->base + mode);
+       val |= pmd->mask;
+       __raw_writel(val, pmu->base + mode);
 
        /* write SW_ENCOURAGE to make the configuration take effect */
-       pmu_writel(SW_MODE_ENCOURAGE_ON, SW_ENCOURAGE);
-       pmu_writel(encourage_lo, SW_ENCOURAGE);
-       pmu_writel(encourage_hi, SW_ENCOURAGE);
+       __raw_writel(SW_MODE_ENCOURAGE_ON, pmu->base + SW_ENCOURAGE);
+       __raw_writel(encourage_lo, pmu->base + SW_ENCOURAGE);
+       __raw_writel(encourage_hi, pmu->base + SW_ENCOURAGE);
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       return 0;
 }
-EXPORT_SYMBOL(starfive_power_domain_set);
 
-void starfive_power_domain_set_by_hwevent(u32 domain, u32 event, bool enable)
+static int jh7110_pmu_on(struct generic_pm_domain *genpd)
 {
-       u32 val;
+       struct jh7110_power_dev *pmd = container_of(genpd,
+               struct jh7110_power_dev, genpd);
+
+       return jh7110_pmu_set_state(pmd, true);
+}
+
+static int jh7110_pmu_off(struct generic_pm_domain *genpd)
+{
+       struct jh7110_power_dev *pmd = container_of(genpd,
+               struct jh7110_power_dev, genpd);
+
+       return jh7110_pmu_set_state(pmd, false);
+}
 
-       val = pmu_readl(HW_TURN_ON_MODE);
+static void starfive_pmu_int_enable(struct jh7110_pmu *pmu, u32 mask, bool enable)
+{
+       u32 val = __raw_readl(pmu->base + PMU_INT_MASK);
 
        if (enable)
-               val |= domain;
+               val &= ~mask;
        else
-               val &= ~domain;
-
-       pmu_writel(val, HW_TURN_ON_MODE);
+               val |= mask;
 
-       starfive_pmu_hw_event_turn_on_mask(event, enable);
+       __raw_writel(val, pmu->base + PMU_INT_MASK);
 }
-EXPORT_SYMBOL(starfive_power_domain_set_by_hwevent);
 
 static irqreturn_t starfive_pmu_interrupt(int irq, void *data)
 {
-       struct starfive_pmu *pmu = data;
+       struct jh7110_pmu *pmu = data;
        unsigned long flags;
        u32 val;
 
        spin_lock_irqsave(&pmu->lock, flags);
-       val = pmu_readl(PMU_INT_STATUS);
+       val = __raw_readl(pmu->base + PMU_INT_STATUS);
 
        if (val & PMU_INT_SEQ_DONE)
-               dev_dbg(pmu->dev, "sequence done.\n");
+               dev_dbg(pmu->pdev, "sequence done.\n");
        if (val & PMU_INT_HW_REQ)
-               dev_dbg(pmu->dev, "hardware encourage requestion.\n");
+               dev_dbg(pmu->pdev, "hardware encourage requestion.\n");
        if (val & PMU_INT_SW_FAIL)
-               dev_err(pmu->dev, "software encourage fail.\n");
+               dev_err(pmu->pdev, "software encourage fail.\n");
        if (val & PMU_INT_HW_FAIL)
-               dev_err(pmu->dev, "hardware encourage fail.\n");
+               dev_err(pmu->pdev, "hardware encourage fail.\n");
        if (val & PMU_INT_PCH_FAIL)
-               dev_err(pmu->dev, "p-channel fail event.\n");
+               dev_err(pmu->pdev, "p-channel fail event.\n");
 
        /* clear interrupts */
-       pmu_writel(val, PMU_INT_STATUS);
-       pmu_writel(val, PMU_EVENT_STATUS);
+       __raw_writel(val, pmu->base + PMU_INT_STATUS);
+       __raw_writel(val, pmu->base + PMU_EVENT_STATUS);
 
        spin_unlock_irqrestore(&pmu->lock, flags);
 
        return IRQ_HANDLED;
 }
 
-static int starfive_pmu_pad_order_get(u32 domain, bool on_off)
+static int jh7110_pmu_probe(struct platform_device *pdev)
 {
-       unsigned int group;
-       u32 val, offset;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct resource *res;
+       const struct jh7110_pmu_data *entry, *table;
+       struct jh7110_pmu *pmu;
+       unsigned int i;
+       uint8_t max_bit = 0;
+       int ret;
 
-       group = domain / 3;
-       offset = (domain % 3) << 1;
+       pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
+       if (!pmu)
+               return -ENOMEM;
 
-       val = pmu_readl(POWER_DOMAIN_CASCADE_0 + group * 4);
-       if (on_off)
-               val &= power_domain_cascade[offset + 1];
-       else
-               val &= power_domain_cascade[offset];
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pmu->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmu->base))
+               return PTR_ERR(pmu->base);
 
-       return val;
-}
+       /* initialize pmu interrupt  */
+       pmu->irq = platform_get_irq(pdev, 0);
+       if (pmu->irq < 0)
+               return pmu->irq;
 
-static void starfive_pmu_pad_order_set(u32 domain, bool on_off, u32 order)
-{
-       unsigned int group;
-       u32 val, offset;
+       ret = devm_request_irq(dev, pmu->irq, starfive_pmu_interrupt,
+                              0, pdev->name, pmu);
+       if (ret)
+               dev_err(dev, "request irq failed.\n");
 
-       group = domain / 3;
-       offset = (domain % 3) << 1;
+       table = of_device_get_match_data(dev);
+       if (!table)
+               return -EINVAL;
 
-       val = pmu_readl(POWER_DOMAIN_CASCADE_0 + group * 4);
-       if (on_off)
-               val |= (order << __ffs(power_domain_cascade[offset + 1]));
-       else
-               val |= (order << __ffs(power_domain_cascade[offset]));
+       pmu->pdev = dev;
+       pmu->genpd_data.num_domains = 0;
+       i = 0;
+       for (entry = table; entry->name; entry++) {
+               max_bit = max(max_bit, entry->bit);
+               i++;
+       }
 
-       pmu_writel(val, POWER_DOMAIN_CASCADE_0 + group * 4);
-}
+       if (!i)
+               return -ENODEV;
 
-int starfive_power_domain_order_on_get(u32 domain)
-{
-       return starfive_pmu_pad_order_get(domain, true);
-}
-EXPORT_SYMBOL(starfive_power_domain_order_on_get);
+       pmu->genpd_data.num_domains = max_bit + 1;
 
-int starfive_power_domain_order_off_get(u32 domain)
-{
-       return starfive_pmu_pad_order_get(domain, false);
-}
-EXPORT_SYMBOL(starfive_power_domain_order_off_get);
+       pmu->dev = devm_kcalloc(dev, pmu->genpd_data.num_domains,
+                                 sizeof(struct jh7110_power_dev),
+                                 GFP_KERNEL);
+       if (!pmu->dev)
+               return -ENOMEM;
 
-void starfive_power_domain_order_on_set(u32 domain, u32 order)
-{
-       starfive_pmu_pad_order_set(domain, true, order);
-}
-EXPORT_SYMBOL(starfive_power_domain_order_on_set);
+       pmu->genpd = devm_kcalloc(dev, pmu->genpd_data.num_domains,
+                                   sizeof(struct generic_pm_domain *),
+                                   GFP_KERNEL);
+       if (!pmu->genpd)
+               return -ENOMEM;
 
-void starfive_power_domain_order_off_set(u32 domain, u32 order)
-{
-       starfive_pmu_pad_order_set(domain, false, order);
-}
-EXPORT_SYMBOL(starfive_power_domain_order_off_set);
+       pmu->genpd_data.domains = pmu->genpd;
 
-static int starfive_pmu_probe(struct platform_device *pdev)
-{
-       struct starfive_pmu *pmu;
-       struct device *dev = &pdev->dev;
-       int ret;
+       i = 0;
+       for (entry = table; entry->name; entry++) {
+               struct jh7110_power_dev *pmd = &pmu->dev[i];
+               bool is_on;
 
-       pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
-       if (!pmu)
-               return -ENOMEM;
+               pmd->power = pmu;
+               pmd->mask = BIT(entry->bit);
+               pmd->genpd.name = entry->name;
+               pmd->genpd.flags = entry->flags;
 
-       pmu->dev = dev;
-       dev->driver_data = pmu;
+               ret = jh7110_pmu_get_state(pmd, &is_on);
+               if (ret)
+                       dev_warn(dev, "unable to get current state for %s\n",
+                                pmd->genpd.name);
 
-       pmu_base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pmu_base))
-               return PTR_ERR(pmu_base);
+               pmd->genpd.power_on = jh7110_pmu_on;
+               pmd->genpd.power_off = jh7110_pmu_off;
 
-       pmu->irq = platform_get_irq(pdev, 0);
-       if (pmu->irq < 0)
-               return pmu->irq;
+               pm_genpd_init(&pmd->genpd, NULL, !is_on);
+               pmu->genpd[entry->bit] = &pmd->genpd;
 
-       ret = devm_request_irq(dev, pmu->irq, starfive_pmu_interrupt,
-                              0, pdev->name, pmu);
-       if (ret)
-               dev_err(dev, "request irq failed.\n");
+               i++;
+       }
 
        spin_lock_init(&pmu->lock);
-       starfive_pmu_int_enable(PMU_INT_ALL_MASK & ~PMU_INT_PCH_FAIL, true);
+       starfive_pmu_int_enable(pmu, PMU_INT_ALL_MASK & ~PMU_INT_PCH_FAIL, true);
 
-       return ret;
-}
+       ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+       if (ret) {
+               dev_err(dev, "failed to register genpd driver: %d\n", ret);
+               return ret;
+       }
 
-static int starfive_pmu_remove(struct platform_device *dev)
-{
-       starfive_pmu_int_enable(PMU_INT_ALL_MASK, false);
+       dev_info(dev, "registered %u power domains\n", i);
 
        return 0;
 }
 
-static const struct of_device_id starfive_pmu_dt_ids[] = {
-       { .compatible = "starfive,jh7110-pmu" },
-       { /* sentinel */ }
-};
-
-static struct platform_driver starfive_pmu_driver = {
-       .probe          = starfive_pmu_probe,
-       .remove         = starfive_pmu_remove,
-       .driver         = {
-               .name   = "starfive-pmu",
-               .of_match_table = starfive_pmu_dt_ids,
+static const struct jh7110_pmu_data jh7110_power_domains[] = {
+       {
+               .name = "SYSTOP",
+               .bit = JH7110_PD_SYSTOP,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "CPU",
+               .bit = JH7110_PD_CPU,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "GPUA",
+               .bit = JH7110_PD_GPUA,
+       }, {
+               .name = "VDEC",
+               .bit = JH7110_PD_VDEC,
+       }, {
+               .name = "VOUT",
+               .bit = JH7110_PD_VOUT,
+       }, {
+               .name = "ISP",
+               .bit = JH7110_PD_ISP,
+       }, {
+               .name = "VENC",
+               .bit = JH7110_PD_VENC,
+       }, {
+               .name = "GPUB",
+               .bit = JH7110_PD_GPUB,
+       }, {
+               /* sentinel */
        },
 };
 
-static int __init starfive_pmu_init(void)
-{
-       return platform_driver_register(&starfive_pmu_driver);
-}
+static const struct of_device_id jh7110_pmu_of_match[] = {
+       {
+               .compatible = "starfive,jh7110-pmu",
+               .data = &jh7110_power_domains,
+       }, {
+               /* sentinel */
+       }
+};
 
-static void __exit starfive_pmu_exit(void)
-{
-       platform_driver_unregister(&starfive_pmu_driver);
-}
-subsys_initcall(starfive_pmu_init);
-module_exit(starfive_pmu_exit);
+static struct platform_driver jh7110_pmu_driver = {
+       .driver = {
+               .name = "jh7110-pmu",
+               .of_match_table = jh7110_pmu_of_match,
+       },
+       .probe  = jh7110_pmu_probe,
+};
+builtin_platform_driver(jh7110_pmu_driver);
 
-MODULE_AUTHOR("samin <samin.guo@starfivetech.com>");
-MODULE_DESCRIPTION("StarFive JH7110 PMU Device Driver");
-MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
+MODULE_DESCRIPTION("Starfive JH7110 Power Domain Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/power/jh7110-power.h b/include/dt-bindings/power/jh7110-power.h
new file mode 100755 (executable)
index 0000000..97528f5
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0) */
+/*
+ * Copyright (c) 2022 Starfive, Inc.
+ * Author: Walker Chen <walker.chen@starfivetech.com>
+ */
+#ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__
+#define __DT_BINDINGS_POWER_JH7110_POWER_H__
+
+#define JH7110_PD_SYSTOP       0
+#define JH7110_PD_CPU          1
+#define JH7110_PD_GPUA         2
+#define JH7110_PD_VDEC         3
+#define JH7110_PD_VOUT         4
+#define JH7110_PD_ISP          5
+#define JH7110_PD_VENC         6
+#define JH7110_PD_GPUB         7
+
+#endif
diff --git a/include/soc/starfive/jh7110_pmu.h b/include/soc/starfive/jh7110_pmu.h
deleted file mode 100644 (file)
index d408057..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Reset driver for the StarFive JH7110 SoC
- *
- * Copyright (C) 2022 samin <samin.guo@starfivetech.com>
- */
-
-#ifndef __SOC_STARFIVE_JH7110_PMU_H__
-#define __SOC_STARFIVE_JH7110_PMU_H__
-
-#include <linux/bits.h>
-#include <linux/types.h>
-
-/* SW/HW Power domain id  */
-enum PMU_POWER_DOMAIN {
-       POWER_DOMAIN_SYSTOP     = BIT(0),
-       POWER_DOMAIN_CPU        = BIT(1),
-       POWER_DOMAIN_GPUA       = BIT(2),
-       POWER_DOMAIN_VDEC       = BIT(3),
-       POWER_DOMAIN_JPU        = POWER_DOMAIN_VDEC,
-       POWER_DOMAIN_VOUT       = BIT(4),
-       POWER_DOMAIN_ISP        = BIT(5),
-       POWER_DOMAIN_VENC       = BIT(6),
-       POWER_DOMAIN_GPUB       = BIT(7),
-       POWER_DOMAIN_ALL        = GENMASK(7, 0),
-};
-
-enum PMU_HARD_EVENT {
-       PMU_HW_EVENT_RTC        = BIT(0),
-       PMU_HW_EVENT_GMAC       = BIT(1),
-       PMU_HW_EVENT_RFU        = BIT(2),
-       PMU_HW_EVENT_RGPIO0     = BIT(3),
-       PMU_HW_EVENT_RGPIO1     = BIT(4),
-       PMU_HW_EVENT_RGPIO2     = BIT(5),
-       PMU_HW_EVENT_RGPIO3     = BIT(6),
-       PMU_HW_EVENT_GPU        = BIT(7),
-       PMU_HW_EVENT_ALL        = GENMASK(7, 0),
-};
-
-/*
- * @func: starfive_power_domain_set
- * @dec: power domain turn-on/off by software
- * @domain: power domain id
- *     POWER_DOMAIN_SYSTOP:
- *     POWER_DOMAIN_CPU
- *     POWER_DOMAIN_GPUA
- *     POWER_DOMAIN_VDEC
- *     POWER_DOMAIN_VOUT
- *     POWER_DOMAIN_ISP
- *     POWER_DOMAIN_VENC
- *     POWER_DOMAIN_GPUB
- * @enable: 1:enable 0:disable
- */
-void starfive_power_domain_set(u32 domain, bool enable);
-
-/*
- * @func: starfive_pmu_hw_encourage
- * @dec: power domain turn-on/off by HW envent(interrupt)
- * @domain: power domain id
- * @event: Hardware trigger event. PMU_HARD_EVENT:
-       PMU_HW_EVENT_RTC,
-       PMU_HW_EVENT_GMAC,
-       PMU_HW_EVENT_RFU,
-       PMU_HW_EVENT_RGPIO0,
-       PMU_HW_EVENT_RGPIO1,
-       PMU_HW_EVENT_RGPIO2,
-       PMU_HW_EVENT_RGPIO3,
-       PMU_HW_EVENT_GPU,
- * @enable: 1:enable 0:disable
- *
- * @for example:
- *     starfive_power_domain_set_by_hwevent(POWER_DOMAIN_VDEC, RTC_EVENT, 0);
- *
- *     Means that when the RTC alarm is interrupted, the hardware
- *     is triggered to close the power domain of VDEC.
- */
-void starfive_power_domain_set_by_hwevent(u32 domain, u32 event, bool enable);
-
-/*
- * @func: starfive_power_domain_order_on_get
- * @dec: PMU power domian power on order get.
- * @domian: powerff domain id
- */
-int starfive_power_domain_order_on_get(u32 domain);
-
-/*
- * @func: starfive_power_domain_order_off_get
- * @dec: PMU power domian power off order get.
- * @domian: power domain id
- */
-int starfive_power_domain_order_off_get(u32 domain);
-
-/*
- * @func: starfive_power_domain_order_on_set
- * @dec: PMU power domian power on order set.
- * @domian: powerff domain id
- * @order: the poweron order of domain
- */
-void starfive_power_domain_order_on_set(u32 domain, u32 order);
-
-/*
- * @func: starfive_power_domain_order_off_set
- * @dec: PMU power domian power off order set.
- * @domian: power domain id
- * @order: the poweroff order of domain
- */
-void starfive_power_domain_order_off_set(u32 domain, u32 order);
-
-void starfive_pmu_hw_event_turn_off_mask(u32 mask);
-
-#endif /* __SOC_STARFIVE_JH7110_PMU_H__ */
index e11dcbf..eeb991e 100644 (file)
@@ -382,33 +382,40 @@ static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
 #ifdef CONFIG_PM
 static int dw_i2s_runtime_suspend(struct device *dev)
 {
+/*
        struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
 
        if (dw_dev->capability & DW_I2S_MASTER)
                clk_disable(dw_dev->clk);
+*/
        return 0;
 }
 
 static int dw_i2s_runtime_resume(struct device *dev)
 {
+/*
        struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
 
        if (dw_dev->capability & DW_I2S_MASTER)
                clk_enable(dw_dev->clk);
+*/
        return 0;
 }
 
 static int dw_i2s_suspend(struct snd_soc_component *component)
 {
+/*
        struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component);
 
        if (dev->capability & DW_I2S_MASTER)
                clk_disable(dev->clk);
+*/
        return 0;
 }
 
 static int dw_i2s_resume(struct snd_soc_component *component)
 {
+/*
        struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component);
        struct snd_soc_dai *dai;
        int stream;
@@ -421,6 +428,7 @@ static int dw_i2s_resume(struct snd_soc_component *component)
                        if (snd_soc_dai_stream_active(dai, stream))
                                dw_i2s_config(dev, stream);
        }
+*/
 
        return 0;
 }