X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fclk%2Frenesas%2Fclk-rcar-gen3.c;h=15e38337567370cc72fb43a179e5decedf13770a;hb=cd93d625fd751d55c729c78b10f82109d56a5f1d;hp=76c6de2ab28dd8104035ed40fe98028a00812346;hpb=7c88556323447977fc248c52c525f15d62c8cd2e;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c index 76c6de2..15e3833 100644 --- a/drivers/clk/renesas/clk-rcar-gen3.c +++ b/drivers/clk/renesas/clk-rcar-gen3.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Renesas RCar Gen3 CPG MSSR driver * @@ -7,20 +8,21 @@ * r8a7796 Clock Pulse Generator / Module Standby and Software Reset * * Copyright (C) 2016 Glider bvba - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include +#include #include #include +#include #include #include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" #define CPG_RST_MODEMR 0x0060 @@ -34,47 +36,6 @@ #define CPG_RPC_POSTDIV_OFFSET 0 /* - * Module Standby and Software Reset register offets. - * - * If the registers exist, these are valid for SH-Mobile, R-Mobile, - * R-Car Gen2, R-Car Gen3, and RZ/G1. - * These are NOT valid for R-Car Gen1 and RZ/A1! - */ - -/* - * Module Stop Status Register offsets - */ - -static const u16 mstpsr[] = { - 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4, - 0x9A0, 0x9A4, 0x9A8, 0x9AC, -}; - -#define MSTPSR(i) mstpsr[i] - - -/* - * System Module Stop Control Register offsets - */ - -static const u16 smstpcr[] = { - 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C, - 0x990, 0x994, 0x998, 0x99C, -}; - -#define SMSTPCR(i) smstpcr[i] - - -/* Realtime Module Stop Control Register offsets */ -#define RMSTPCR(i) (smstpcr[i] - 0x20) - -/* Modem Module Stop Control Register offsets (r8a73a4) */ -#define MMSTPCR(i) (smstpcr[i] + 0x20) - -/* Software Reset Clearing Register offsets */ -#define SRSTCLR(i) (0x940 + (i) * 4) - -/* * SDn Clock */ #define CPG_SD_STP_HCK BIT(9) @@ -126,99 +87,46 @@ static const struct sd_div_table cpg_sd_div_table[] = { CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), }; -static bool gen3_clk_is_mod(struct clk *clk) -{ - return (clk->id >> 16) == CPG_MOD; -} - -static int gen3_clk_get_mod(struct clk *clk, const struct mssr_mod_clk **mssr) -{ - struct gen3_clk_priv *priv = dev_get_priv(clk->dev); - struct cpg_mssr_info *info = priv->info; - const unsigned long clkid = clk->id & 0xffff; - int i; - - if (!gen3_clk_is_mod(clk)) - return -EINVAL; - - for (i = 0; i < info->mod_clk_size; i++) { - if (info->mod_clk[i].id != - (info->mod_clk_base + MOD_CLK_PACK(clkid))) - continue; - - *mssr = &info->mod_clk[i]; - return 0; - } - - return -ENODEV; -} - -static int gen3_clk_get_core(struct clk *clk, const struct cpg_core_clk **core) -{ - struct gen3_clk_priv *priv = dev_get_priv(clk->dev); - struct cpg_mssr_info *info = priv->info; - const unsigned long clkid = clk->id & 0xffff; - int i; - - if (gen3_clk_is_mod(clk)) - return -EINVAL; - - for (i = 0; i < info->core_clk_size; i++) { - if (info->core_clk[i].id != clkid) - continue; - - *core = &info->core_clk[i]; - return 0; - } - - return -ENODEV; -} - -static int gen3_clk_get_parent(struct clk *clk, struct clk *parent) +static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk, + struct cpg_mssr_info *info, struct clk *parent) { const struct cpg_core_clk *core; - const struct mssr_mod_clk *mssr; int ret; - if (gen3_clk_is_mod(clk)) { - ret = gen3_clk_get_mod(clk, &mssr); + if (!renesas_clk_is_mod(clk)) { + ret = renesas_clk_get_core(clk, info, &core); if (ret) return ret; - parent->id = mssr->parent; - } else { - ret = gen3_clk_get_core(clk, &core); - if (ret) - return ret; - - if (core->type == CLK_TYPE_IN) - parent->id = ~0; /* Top-level clock */ - else - parent->id = core->parent; + if (core->type == CLK_TYPE_GEN3_MDSEL) { + parent->dev = clk->dev; + parent->id = core->parent >> (priv->sscg ? 16 : 0); + parent->id &= 0xffff; + return 0; + } } - parent->dev = clk->dev; - - return 0; + return renesas_clk_get_parent(clk, info, parent); } -static int gen3_clk_setup_sdif_div(struct clk *clk) +static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate) { struct gen3_clk_priv *priv = dev_get_priv(clk->dev); + struct cpg_mssr_info *info = priv->info; const struct cpg_core_clk *core; struct clk parent; int ret; - ret = gen3_clk_get_parent(clk, &parent); + ret = gen3_clk_get_parent(priv, clk, info, &parent); if (ret) { printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); return ret; } - if (gen3_clk_is_mod(&parent)) + if (renesas_clk_is_mod(&parent)) return 0; - ret = gen3_clk_get_core(&parent, &core); + ret = renesas_clk_get_core(&parent, info, &core); if (ret) return ret; @@ -227,50 +135,26 @@ static int gen3_clk_setup_sdif_div(struct clk *clk) debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset); - writel(1, priv->base + core->offset); + writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset); return 0; } -static int gen3_clk_endisable(struct clk *clk, bool enable) +static int gen3_clk_enable(struct clk *clk) { struct gen3_clk_priv *priv = dev_get_priv(clk->dev); - const unsigned long clkid = clk->id & 0xffff; - const unsigned int reg = clkid / 100; - const unsigned int bit = clkid % 100; - const u32 bitmask = BIT(bit); - int ret; - - if (!gen3_clk_is_mod(clk)) - return -EINVAL; - - debug("%s[%i] MSTP %lu=%02u/%02u %s\n", __func__, __LINE__, - clkid, reg, bit, enable ? "ON" : "OFF"); - - if (enable) { - ret = gen3_clk_setup_sdif_div(clk); - if (ret) - return ret; - clrbits_le32(priv->base + SMSTPCR(reg), bitmask); - return wait_for_bit("MSTP", priv->base + MSTPSR(reg), - bitmask, 0, 100, 0); - } else { - setbits_le32(priv->base + SMSTPCR(reg), bitmask); - return 0; - } -} -static int gen3_clk_enable(struct clk *clk) -{ - return gen3_clk_endisable(clk, true); + return renesas_clk_endisable(clk, priv->base, true); } static int gen3_clk_disable(struct clk *clk) { - return gen3_clk_endisable(clk, false); + struct gen3_clk_priv *priv = dev_get_priv(clk->dev); + + return renesas_clk_endisable(clk, priv->base, false); } -static ulong gen3_clk_get_rate(struct clk *clk) +static u64 gen3_clk_get_rate64(struct clk *clk) { struct gen3_clk_priv *priv = dev_get_priv(clk->dev); struct cpg_mssr_info *info = priv->info; @@ -278,25 +162,26 @@ static ulong gen3_clk_get_rate(struct clk *clk) const struct cpg_core_clk *core; const struct rcar_gen3_cpg_pll_config *pll_config = priv->cpg_pll_config; - u32 value, mult, prediv, postdiv, rate = 0; + u32 value, mult, div, prediv, postdiv; + u64 rate = 0; int i, ret; debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id); - ret = gen3_clk_get_parent(clk, &parent); + ret = gen3_clk_get_parent(priv, clk, info, &parent); if (ret) { printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); return ret; } - if (gen3_clk_is_mod(clk)) { - rate = gen3_clk_get_rate(&parent); - debug("%s[%i] MOD clk: parent=%lu => rate=%u\n", + if (renesas_clk_is_mod(clk)) { + rate = gen3_clk_get_rate64(&parent); + debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n", __func__, __LINE__, parent.id, rate); return rate; } - ret = gen3_clk_get_core(clk, &core); + ret = renesas_clk_get_core(clk, info, &core); if (ret) return ret; @@ -304,14 +189,14 @@ static ulong gen3_clk_get_rate(struct clk *clk) case CLK_TYPE_IN: if (core->id == info->clk_extal_id) { rate = clk_get_rate(&priv->clk_extal); - debug("%s[%i] EXTAL clk: rate=%u\n", + debug("%s[%i] EXTAL clk: rate=%llu\n", __func__, __LINE__, rate); return rate; } if (core->id == info->clk_extalr_id) { rate = clk_get_rate(&priv->clk_extalr); - debug("%s[%i] EXTALR clk: rate=%u\n", + debug("%s[%i] EXTALR clk: rate=%llu\n", __func__, __LINE__, rate); return rate; } @@ -319,8 +204,8 @@ static ulong gen3_clk_get_rate(struct clk *clk) return -EINVAL; case CLK_TYPE_GEN3_MAIN: - rate = gen3_clk_get_rate(&parent) / pll_config->extal_div; - debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) / pll_config->extal_div; + debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%llu\n", __func__, __LINE__, core->parent, pll_config->extal_div, rate); return rate; @@ -328,49 +213,61 @@ static ulong gen3_clk_get_rate(struct clk *clk) case CLK_TYPE_GEN3_PLL0: value = readl(priv->base + CPG_PLL0CR); mult = (((value >> 24) & 0x7f) + 1) * 2; - rate = gen3_clk_get_rate(&parent) * mult; - debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) * mult; + debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%llu\n", __func__, __LINE__, core->parent, mult, rate); return rate; case CLK_TYPE_GEN3_PLL1: - rate = gen3_clk_get_rate(&parent) * pll_config->pll1_mult; - debug("%s[%i] PLL1 clk: parent=%i mul=%i => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) * pll_config->pll1_mult; + rate /= pll_config->pll1_div; + debug("%s[%i] PLL1 clk: parent=%i mul=%i div=%i => rate=%llu\n", __func__, __LINE__, - core->parent, pll_config->pll1_mult, rate); + core->parent, pll_config->pll1_mult, + pll_config->pll1_div, rate); return rate; case CLK_TYPE_GEN3_PLL2: value = readl(priv->base + CPG_PLL2CR); mult = (((value >> 24) & 0x7f) + 1) * 2; - rate = gen3_clk_get_rate(&parent) * mult; - debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) * mult; + debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%llu\n", __func__, __LINE__, core->parent, mult, rate); return rate; case CLK_TYPE_GEN3_PLL3: - rate = gen3_clk_get_rate(&parent) * pll_config->pll3_mult; - debug("%s[%i] PLL3 clk: parent=%i mul=%i => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) * pll_config->pll3_mult; + rate /= pll_config->pll3_div; + debug("%s[%i] PLL3 clk: parent=%i mul=%i div=%i => rate=%llu\n", __func__, __LINE__, - core->parent, pll_config->pll3_mult, rate); + core->parent, pll_config->pll3_mult, + pll_config->pll3_div, rate); return rate; case CLK_TYPE_GEN3_PLL4: value = readl(priv->base + CPG_PLL4CR); mult = (((value >> 24) & 0x7f) + 1) * 2; - rate = gen3_clk_get_rate(&parent) * mult; - debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%u\n", + rate = gen3_clk_get_rate64(&parent) * mult; + debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%llu\n", __func__, __LINE__, core->parent, mult, rate); return rate; case CLK_TYPE_FF: - case CLK_TYPE_GEN3_PE: /* FIXME */ - rate = (gen3_clk_get_rate(&parent) * core->mult) / core->div; - debug("%s[%i] FIXED clk: parent=%i div=%i mul=%i => rate=%u\n", + rate = (gen3_clk_get_rate64(&parent) * core->mult) / core->div; + debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%llu\n", __func__, __LINE__, core->parent, core->mult, core->div, rate); return rate; + case CLK_TYPE_GEN3_MDSEL: + div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff; + rate = gen3_clk_get_rate64(&parent) / div; + debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n", + __func__, __LINE__, + (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff, + div, rate); + return rate; + case CLK_TYPE_GEN3_SD: /* FIXME */ value = readl(priv->base + core->offset); value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK; @@ -379,9 +276,9 @@ static ulong gen3_clk_get_rate(struct clk *clk) if (cpg_sd_div_table[i].val != value) continue; - rate = gen3_clk_get_rate(&parent) / + rate = gen3_clk_get_rate64(&parent) / cpg_sd_div_table[i].div; - debug("%s[%i] SD clk: parent=%i div=%i => rate=%u\n", + debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n", __func__, __LINE__, core->parent, cpg_sd_div_table[i].div, rate); @@ -391,7 +288,7 @@ static ulong gen3_clk_get_rate(struct clk *clk) return -EINVAL; case CLK_TYPE_GEN3_RPC: - rate = gen3_clk_get_rate(&parent); + rate = gen3_clk_get_rate64(&parent); value = readl(priv->base + core->offset); @@ -408,7 +305,7 @@ static ulong gen3_clk_get_rate(struct clk *clk) CPG_RPC_POSTDIV_MASK; rate /= postdiv + 1; - debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%u\n", + debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n", __func__, __LINE__, core->parent, prediv, postdiv, rate); @@ -421,9 +318,16 @@ static ulong gen3_clk_get_rate(struct clk *clk) return -ENOENT; } +static ulong gen3_clk_get_rate(struct clk *clk) +{ + return gen3_clk_get_rate64(clk); +} + static ulong gen3_clk_set_rate(struct clk *clk, ulong rate) { - return gen3_clk_get_rate(clk); + /* Force correct SD-IF divider configuration if applicable */ + gen3_clk_setup_sdif_div(clk, rate); + return gen3_clk_get_rate64(clk); } static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) @@ -475,6 +379,8 @@ int gen3_clk_probe(struct udevice *dev) if (!priv->cpg_pll_config->extal_div) return -EINVAL; + priv->sscg = !(cpg_mode & BIT(12)); + ret = clk_get_by_name(dev, "extal", &priv->clk_extal); if (ret < 0) return ret; @@ -491,20 +397,6 @@ int gen3_clk_probe(struct udevice *dev) int gen3_clk_remove(struct udevice *dev) { struct gen3_clk_priv *priv = dev_get_priv(dev); - struct cpg_mssr_info *info = priv->info; - unsigned int i; - - /* Stop TMU0 */ - clrbits_le32(TMU_BASE + TSTR0, TSTR0_STR0); - - /* Stop module clock */ - for (i = 0; i < info->mstp_table_size; i++) { - clrsetbits_le32(priv->base + SMSTPCR(i), - info->mstp_table[i].dis, - info->mstp_table[i].en); - clrsetbits_le32(priv->base + RMSTPCR(i), - info->mstp_table[i].dis, 0x0); - } - return 0; + return renesas_clk_remove(priv->base, priv->info); }