lkml.org 
[lkml]   [2019]   [Mar]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 11/14] soc: mediatek: Add subsys clock control for bus protection
    Date
    Add subsys CG control flow before/after the bus protect control
    due to bus protection need SMI bus relative CGs enabled to feedback
    its ack.

    Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
    ---
    drivers/soc/mediatek/mtk-scpsys.c | 72 ++++++++++++++++++++++++++++++-
    1 file changed, 70 insertions(+), 2 deletions(-)

    diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
    index 181bf7bce591..356ca2626b36 100644
    --- a/drivers/soc/mediatek/mtk-scpsys.c
    +++ b/drivers/soc/mediatek/mtk-scpsys.c
    @@ -108,6 +108,7 @@ static const char * const clk_names[] = {
    };

    #define MAX_CLKS 3
    +#define MAX_SUBSYS_CLKS 10

    /**
    * struct scp_domain_data - scp domain data for power on/off flow
    @@ -121,6 +122,8 @@ static const char * const clk_names[] = {
    * power domains.
    * @basic_clk_name: provide the same purpose with field "clk_id"
    * by declaring basic clock prefix name rather than clk_id.
    + * @subsys_clk_prefix: The prefix name of the clocks need to be enabled
    + * before releasing bus protection.
    * @caps: The flag for active wake-up action.
    * @bp_table: The mask table for multiple step bus protection.
    */
    @@ -133,6 +136,7 @@ struct scp_domain_data {
    u32 bus_prot_mask;
    enum clk_id clk_id[MAX_CLKS];
    const char *basic_clk_name[MAX_CLKS];
    + const char *subsys_clk_prefix;
    u8 caps;
    struct bus_prot bp_table[MAX_STEPS];
    };
    @@ -143,6 +147,7 @@ struct scp_domain {
    struct generic_pm_domain genpd;
    struct scp *scp;
    struct clk *clk[MAX_CLKS];
    + struct clk *subsys_clk[MAX_SUBSYS_CLKS];
    const struct scp_domain_data *data;
    struct regulator *supply;
    };
    @@ -361,16 +366,22 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
    val |= PWR_RST_B_BIT;
    writel(val, ctl_addr);

    - ret = scpsys_sram_enable(scpd, ctl_addr);
    + ret = scpsys_clk_enable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
    if (ret < 0)
    goto err_pwr_ack;

    + ret = scpsys_sram_enable(scpd, ctl_addr);
    + if (ret < 0)
    + goto err_sram;
    +
    ret = scpsys_bus_protect_disable(scpd);
    if (ret < 0)
    - goto err_pwr_ack;
    + goto err_sram;

    return 0;

    +err_sram:
    + scpsys_clk_disable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
    err_pwr_ack:
    scpsys_clk_disable(scpd->clk, MAX_CLKS);
    err_clk:
    @@ -397,6 +408,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
    if (ret < 0)
    goto out;

    + scpsys_clk_disable(scpd->subsys_clk, MAX_SUBSYS_CLKS);
    +
    /* subsys power off */
    val = readl(ctl_addr) | PWR_ISO_BIT;
    writel(val, ctl_addr);
    @@ -433,6 +446,48 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
    return ret;
    }

    +static int init_subsys_clks(struct platform_device *pdev,
    + const char *prefix, struct clk **clk)
    +{
    + struct device_node *node = pdev->dev.of_node;
    + u32 prefix_len, sub_clk_cnt = 0;
    + struct property *prop;
    + const char *clk_name;
    +
    + if (!node) {
    + dev_err(&pdev->dev, "Cannot find scpsys node: %ld\n",
    + PTR_ERR(node));
    + return PTR_ERR(node);
    + }
    +
    + prefix_len = strlen(prefix);
    +
    + of_property_for_each_string(node, "clock-names", prop, clk_name) {
    + if (!strncmp(clk_name, prefix, prefix_len) &&
    + (clk_name[prefix_len] == '-')) {
    + if (sub_clk_cnt >= MAX_SUBSYS_CLKS) {
    + dev_err(&pdev->dev,
    + "subsys clk out of range %d\n",
    + sub_clk_cnt);
    + return -ENOMEM;
    + }
    +
    + clk[sub_clk_cnt] = devm_clk_get(&pdev->dev,
    + clk_name);
    +
    + if (IS_ERR(clk)) {
    + dev_err(&pdev->dev,
    + "Subsys clk read fail %ld\n",
    + PTR_ERR(clk));
    + return PTR_ERR(clk);
    + }
    + sub_clk_cnt++;
    + }
    + }
    +
    + return sub_clk_cnt;
    +}
    +
    static void init_clks(struct platform_device *pdev, struct clk **clk)
    {
    int i;
    @@ -520,6 +575,7 @@ static struct scp *init_scp(struct platform_device *pdev,
    struct scp_domain *scpd = &scp->domains[i];
    struct generic_pm_domain *genpd = &scpd->genpd;
    const struct scp_domain_data *data = &scp_domain_data[i];
    + int clk_cnt;

    pd_data->domains[i] = genpd;
    scpd->scp = scp;
    @@ -546,6 +602,18 @@ static struct scp *init_scp(struct platform_device *pdev,
    data->basic_clk_name[j]);
    }

    + if (data->subsys_clk_prefix) {
    + clk_cnt = init_subsys_clks(pdev,
    + data->subsys_clk_prefix,
    + scpd->subsys_clk);
    + if (clk_cnt < 0) {
    + dev_err(&pdev->dev,
    + "%s: subsys clk unavailable\n",
    + data->name);
    + return ERR_PTR(clk_cnt);
    + }
    + }
    +
    genpd->name = data->name;
    genpd->power_off = scpsys_power_off;
    genpd->power_on = scpsys_power_on;
    --
    2.18.0
    \
     
     \ /
      Last update: 2019-03-19 09:03    [W:2.985 / U:0.584 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site