Merge branches 'clk-doc', 'clk-renesas', 'clk-at91', 'clk-cleanup' and 'clk-debugfs...
authorStephen Boyd <sboyd@kernel.org>
Wed, 12 Jan 2022 02:30:10 +0000 (18:30 -0800)
committerStephen Boyd <sboyd@kernel.org>
Wed, 12 Jan 2022 02:30:10 +0000 (18:30 -0800)
* clk-doc:
  clk: Gemini: fix struct name in kernel-doc
  clk: zynq: pll: Fix kernel-doc warnings
  clk: imx: pllv1: fix kernel-doc notation for struct clk_pllv1

* clk-renesas: (31 commits)
  clk: renesas: r9a07g044: Add GPU clock and reset entries
  clk: renesas: r9a07g044: Add mux and divider for G clock
  clk: renesas: r9a07g044: Rename CLK_PLL3_DIV4 macro
  clk: renesas: cpg-mssr: Add support for R-Car S4-8
  clk: renesas: rcar-gen4: Introduce R-Car Gen4 CPG driver
  dt-bindings: clock: Add r8a779f0 CPG Core Clock Definitions
  dt-bindings: power: Add r8a779f0 SYSC power domain definitions
  clk: renesas: r9a07g044: Add TSU clock and reset entry
  mmc: renesas_sdhi: Simplify an expression
  mmc: renesas_sdhi: Use devm_clk_get_optional() to obtain CD clock
  dt-bindings: clock: renesas,cpg-mssr: Document r8a779f0
  clk: renesas: cpg-mssr: propagate return value of_genpd_add_provider_simple()
  clk: renesas: cpg-mssr: Check return value of pm_genpd_init()
  clk: renesas: rzg2l: propagate return value of_genpd_add_provider_simple()
  clk: renesas: rzg2l: Check return value of pm_genpd_init()
  clk: renesas: r9a07g044: Add RSPI clock and reset entries
  clk: renesas: r9a07g044: Change core clock "I" from DEF_FIXED->DEF_DIV
  clk: renesas: rzg2l: Add CPG_PL1_DDIV macro
  mmc: renesas_sdhi: Parse DT for SDnH
  mmc: renesas_sdhi: Use dev_err_probe when getting clock fails
  ...

* clk-at91:
  clk: lan966x: Extend lan966x clock driver for clock gating support
  dt-bindings: clock: lan966x: Extend includes with clock gates
  dt-bindings: clock: lan966x: Extend for clock gate support
  clk: gate: Add devm_clk_hw_register_gate()
  clk: lan966x: Add lan966x SoC clock driver
  dt-bindings: clock: lan966x: Add LAN966X Clock Controller
  dt-bindings: clock: lan966x: Add binding includes for lan966x SoC clock IDs

* clk-cleanup:
  clk: stm32mp1: remove redundant assignment to pointer data
  clk: __clk_core_init() never takes NULL
  clk: clk_core_get() can also return NULL
  clk/ti/adpll: Make const pointer error a static const array

* clk-debugfs:
  clk: Enable/Disable runtime PM for clk_summary
  clk: Emit a stern warning with writable debugfs enabled
  clk: Add write operation for clk_parent debugfs node

37 files changed:
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml
drivers/clk/clk-gemini.c
drivers/clk/clk-stm32mp1.c
drivers/clk/clk.c
drivers/clk/imx/clk-pllv1.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/r8a774a1-cpg-mssr.c
drivers/clk/renesas/r8a774b1-cpg-mssr.c
drivers/clk/renesas/r8a774c0-cpg-mssr.c
drivers/clk/renesas/r8a774e1-cpg-mssr.c
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/r8a77965-cpg-mssr.c
drivers/clk/renesas/r8a77980-cpg-mssr.c
drivers/clk/renesas/r8a77990-cpg-mssr.c
drivers/clk/renesas/r8a77995-cpg-mssr.c
drivers/clk/renesas/r8a779a0-cpg-mssr.c
drivers/clk/renesas/r8a779f0-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r9a07g044-cpg.c
drivers/clk/renesas/rcar-cpg-lib.c
drivers/clk/renesas/rcar-cpg-lib.h
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/rcar-gen4-cpg.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen4-cpg.h [new file with mode: 0644]
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/renesas/rzg2l-cpg.c
drivers/clk/renesas/rzg2l-cpg.h
drivers/clk/ti/adpll.c
drivers/clk/zynq/pll.c
drivers/mmc/host/renesas_sdhi.h
drivers/mmc/host/renesas_sdhi_core.c
drivers/mmc/host/renesas_sdhi_internal_dmac.c
include/dt-bindings/clock/r8a779f0-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/power/r8a779f0-sysc.h [new file with mode: 0644]

index 9b414fb..e0b8621 100644 (file)
@@ -48,6 +48,7 @@ properties:
       - renesas,r8a77990-cpg-mssr # R-Car E3
       - renesas,r8a77995-cpg-mssr # R-Car D3
       - renesas,r8a779a0-cpg-mssr # R-Car V3U
+      - renesas,r8a779f0-cpg-mssr # R-Car S4-8
 
   reg:
     maxItems: 1
index b51069e..a23fa6d 100644 (file)
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(gemini_clk_lock);
 #define PCI_DLL_TAP_SEL_MASK           0x1f
 
 /**
- * struct gemini_data_data - Gemini gated clocks
+ * struct gemini_gate_data - Gemini gated clocks
  * @bit_idx: the bit used to gate this clock in the clock register
  * @name: the clock name
  * @parent_name: the name of the parent clock
index 4bd1fe7..863274a 100644 (file)
@@ -2253,8 +2253,6 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base,
        const struct stm32_rcc_match_data *data = match->data;
        struct stm32_reset_data *reset_data = NULL;
 
-       data = match->data;
-
        reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
        if (!reset_data)
                return -ENOMEM;
index f467d63..c3c4849 100644 (file)
@@ -424,19 +424,20 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
 
        if (entry->hw) {
                parent = entry->hw->core;
-               /*
-                * We have a direct reference but it isn't registered yet?
-                * Orphan it and let clk_reparent() update the orphan status
-                * when the parent is registered.
-                */
-               if (!parent)
-                       parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
                if (PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
+       /*
+        * We have a direct reference but it isn't registered yet?
+        * Orphan it and let clk_reparent() update the orphan status
+        * when the parent is registered.
+        */
+       if (!parent)
+               parent = ERR_PTR(-EPROBE_DEFER);
+
        /* Only cache it if it's not an error */
        if (!IS_ERR(parent))
                entry->core = parent;
@@ -2965,7 +2966,9 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 {
        struct clk_core *child;
 
+       clk_pm_runtime_get(c);
        clk_summary_show_one(s, c, level);
+       clk_pm_runtime_put(c);
 
        hlist_for_each_entry(child, &c->children, child_node)
                clk_summary_show_subtree(s, child, level + 1);
@@ -3217,6 +3220,42 @@ static int current_parent_show(struct seq_file *s, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(current_parent);
 
+#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
+static ssize_t current_parent_write(struct file *file, const char __user *ubuf,
+                                   size_t count, loff_t *ppos)
+{
+       struct seq_file *s = file->private_data;
+       struct clk_core *core = s->private;
+       struct clk_core *parent;
+       u8 idx;
+       int err;
+
+       err = kstrtou8_from_user(ubuf, count, 0, &idx);
+       if (err < 0)
+               return err;
+
+       parent = clk_core_get_parent_by_index(core, idx);
+       if (!parent)
+               return -ENOENT;
+
+       clk_prepare_lock();
+       err = clk_core_set_parent_nolock(core, parent);
+       clk_prepare_unlock();
+       if (err)
+               return err;
+
+       return count;
+}
+
+static const struct file_operations current_parent_rw_fops = {
+       .open           = current_parent_open,
+       .write          = current_parent_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
 static int clk_duty_cycle_show(struct seq_file *s, void *data)
 {
        struct clk_core *core = s->private;
@@ -3282,8 +3321,12 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 #ifdef CLOCK_ALLOW_WRITE_DEBUGFS
        debugfs_create_file("clk_prepare_enable", 0644, root, core,
                            &clk_prepare_enable_fops);
-#endif
 
+       if (core->num_parents > 1)
+               debugfs_create_file("clk_parent", 0644, root, core,
+                                   &current_parent_rw_fops);
+       else
+#endif
        if (core->num_parents > 0)
                debugfs_create_file("clk_parent", 0444, root, core,
                                    &current_parent_fops);
@@ -3343,6 +3386,24 @@ static int __init clk_debug_init(void)
 {
        struct clk_core *core;
 
+#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
+       pr_warn("\n");
+       pr_warn("********************************************************************\n");
+       pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE           **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("**  WRITEABLE clk DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("** This means that this kernel is built to expose clk operations  **\n");
+       pr_warn("** such as parent or rate setting, enabling, disabling, etc.      **\n");
+       pr_warn("** to userspace, which may compromise security on your system.    **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("** If you see this message and you are not debugging the          **\n");
+       pr_warn("** kernel, report this immediately to your vendor!                **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE           **\n");
+       pr_warn("********************************************************************\n");
+#endif
+
        rootdir = debugfs_create_dir("clk", NULL);
 
        debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
@@ -3413,9 +3474,6 @@ static int __clk_core_init(struct clk_core *core)
        unsigned long rate;
        int phase;
 
-       if (!core)
-               return -EINVAL;
-
        clk_prepare_lock();
 
        ret = clk_pm_runtime_get(core);
index 36ffb05..93ee81b 100644 (file)
@@ -8,20 +8,19 @@
 
 #include "clk.h"
 
+#define MFN_BITS       (10)
+#define MFN_SIGN       (BIT(MFN_BITS - 1))
+#define MFN_MASK       (MFN_SIGN - 1)
+
 /**
- * pll v1
+ * struct clk_pllv1 - IMX PLLv1 clock descriptor
  *
- * @clk_hw     clock source
- * @parent     the parent clock name
- * @base       base address of pll registers
+ * @hw:                clock source
+ * @base:      base address of pll registers
+ * @type:      type of IMX_PLLV1
  *
  * PLL clock version 1, found on i.MX1/21/25/27/31/35
  */
-
-#define MFN_BITS       (10)
-#define MFN_SIGN       (BIT(MFN_BITS - 1))
-#define MFN_MASK       (MFN_SIGN - 1)
-
 struct clk_pllv1 {
        struct clk_hw   hw;
        void __iomem    *base;
index 6d02807..be6e6ae 100644 (file)
@@ -31,6 +31,7 @@ config CLK_RENESAS
        select CLK_R8A77990 if ARCH_R8A77990
        select CLK_R8A77995 if ARCH_R8A77995
        select CLK_R8A779A0 if ARCH_R8A779A0
+       select CLK_R8A779F0 if ARCH_R8A779F0
        select CLK_R9A06G032 if ARCH_R9A06G032
        select CLK_R9A07G044 if ARCH_R9A07G044
        select CLK_SH73A0 if ARCH_SH73A0
@@ -149,8 +150,11 @@ config CLK_R8A77995
 
 config CLK_R8A779A0
        bool "R-Car V3U clock support" if COMPILE_TEST
-       select CLK_RCAR_CPG_LIB
-       select CLK_RENESAS_CPG_MSSR
+       select CLK_RCAR_GEN4_CPG
+
+config CLK_R8A779F0
+       bool "R-Car S4-8 clock support" if COMPILE_TEST
+       select CLK_RCAR_GEN4_CPG
 
 config CLK_R9A06G032
        bool "RZ/N1D clock support" if COMPILE_TEST
@@ -178,6 +182,11 @@ config CLK_RCAR_GEN3_CPG
        select CLK_RCAR_CPG_LIB
        select CLK_RENESAS_CPG_MSSR
 
+config CLK_RCAR_GEN4_CPG
+       bool "R-Car Gen4 clock support" if COMPILE_TEST
+       select CLK_RCAR_CPG_LIB
+       select CLK_RENESAS_CPG_MSSR
+
 config CLK_RCAR_USB2_CLOCK_SEL
        bool "Renesas R-Car USB2 clock selector support"
        depends on ARCH_RENESAS || COMPILE_TEST
index 7d01870..8b34db1 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_CLK_R8A77980)            += r8a77980-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77990)             += r8a77990-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77995)             += r8a77995-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A779A0)             += r8a779a0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779F0)             += r8a779f0-cpg-mssr.o
 obj-$(CONFIG_CLK_R9A06G032)            += r9a06g032-clocks.o
 obj-$(CONFIG_CLK_R9A07G044)            += r9a07g044-cpg.o
 obj-$(CONFIG_CLK_SH73A0)               += clk-sh73a0.o
@@ -36,6 +37,7 @@ obj-$(CONFIG_CLK_SH73A0)              += clk-sh73a0.o
 obj-$(CONFIG_CLK_RCAR_CPG_LIB)         += rcar-cpg-lib.o
 obj-$(CONFIG_CLK_RCAR_GEN2_CPG)                += rcar-gen2-cpg.o
 obj-$(CONFIG_CLK_RCAR_GEN3_CPG)                += rcar-gen3-cpg.o
+obj-$(CONFIG_CLK_RCAR_GEN4_CPG)                += rcar-gen4-cpg.o
 obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL)  += rcar-usb2-clock-sel.o
 obj-$(CONFIG_CLK_RZG2L)                        += rzg2l-cpg.o
 
index 39b185d..95dd56b 100644 (file)
@@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774A1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774A1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774A1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774A1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774A1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774A1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774A1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774A1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774A1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774A1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774A1_CLK_SD0,   R8A774A1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774A1_CLK_SD1,   R8A774A1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774A1_CLK_SD2,   R8A774A1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774A1_CLK_SD3,   R8A774A1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774A1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A774A1_CLK_CP,    CLK_EXTAL,      2, 1),
index af602d8..56061b9 100644 (file)
@@ -97,10 +97,14 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774B1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774B1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774B1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774B1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774B1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774B1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774B1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774B1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774B1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774B1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774B1_CLK_SD0,   R8A774B1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774B1_CLK_SD1,   R8A774B1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774B1_CLK_SD2,   R8A774B1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774B1_CLK_SD3,   R8A774B1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774B1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A774B1_CLK_CP,    CLK_EXTAL,      2, 1),
index 5b938eb..b5eb5dc 100644 (file)
@@ -108,9 +108,12 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
        DEF_FIXED("s3d2",      R8A774C0_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",      R8A774C0_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",     R8A774C0_CLK_SD0,   CLK_SDSRC,     0x0074),
-       DEF_GEN3_SD("sd1",     R8A774C0_CLK_SD1,   CLK_SDSRC,     0x0078),
-       DEF_GEN3_SD("sd3",     R8A774C0_CLK_SD3,   CLK_SDSRC,     0x026c),
+       DEF_GEN3_SDH("sd0h",   R8A774C0_CLK_SD0H, CLK_SDSRC,         0x0074),
+       DEF_GEN3_SDH("sd1h",   R8A774C0_CLK_SD1H, CLK_SDSRC,         0x0078),
+       DEF_GEN3_SDH("sd3h",   R8A774C0_CLK_SD3H, CLK_SDSRC,         0x026c),
+       DEF_GEN3_SD("sd0",     R8A774C0_CLK_SD0,  R8A774C0_CLK_SD0H, 0x0074),
+       DEF_GEN3_SD("sd1",     R8A774C0_CLK_SD1,  R8A774C0_CLK_SD1H, 0x0078),
+       DEF_GEN3_SD("sd3",     R8A774C0_CLK_SD3,  R8A774C0_CLK_SD3H, 0x026c),
 
        DEF_FIXED("cl",        R8A774C0_CLK_CL,    CLK_PLL1,      48, 1),
        DEF_FIXED("cp",        R8A774C0_CLK_CP,    CLK_EXTAL,      2, 1),
index 40c7146..2950f0d 100644 (file)
@@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774E1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774E1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774E1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774E1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774E1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774E1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774E1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774E1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774E1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774E1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774E1_CLK_SD0,   R8A774E1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774E1_CLK_SD1,   R8A774E1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774E1_CLK_SD2,   R8A774E1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774E1_CLK_SD3,   R8A774E1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774E1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A774E1_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index d6b1d01..991a443 100644 (file)
@@ -104,10 +104,14 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
        DEF_FIXED("s3d2",       R8A7795_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7795_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A7795_CLK_SD0H,  CLK_SDSRC,        0x074),
+       DEF_GEN3_SDH("sd1h",    R8A7795_CLK_SD1H,  CLK_SDSRC,        0x078),
+       DEF_GEN3_SDH("sd2h",    R8A7795_CLK_SD2H,  CLK_SDSRC,        0x268),
+       DEF_GEN3_SDH("sd3h",    R8A7795_CLK_SD3H,  CLK_SDSRC,        0x26c),
+       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   R8A7795_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   R8A7795_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   R8A7795_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   R8A7795_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A7795_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A7795_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index 9c22977..7950313 100644 (file)
@@ -106,10 +106,14 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A7796_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7796_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A7796_CLK_SD0H,  CLK_SDSRC,        0x074),
+       DEF_GEN3_SDH("sd1h",    R8A7796_CLK_SD1H,  CLK_SDSRC,        0x078),
+       DEF_GEN3_SDH("sd2h",    R8A7796_CLK_SD2H,  CLK_SDSRC,        0x268),
+       DEF_GEN3_SDH("sd3h",    R8A7796_CLK_SD3H,  CLK_SDSRC,        0x26c),
+       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   R8A7796_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   R8A7796_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   R8A7796_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   R8A7796_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A7796_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index 7eee45a..d687c29 100644 (file)
@@ -101,10 +101,14 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A77965_CLK_S3D2,      CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A77965_CLK_S3D4,      CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A77965_CLK_SD0,       CLK_SDSRC,      0x074),
-       DEF_GEN3_SD("sd1",      R8A77965_CLK_SD1,       CLK_SDSRC,      0x078),
-       DEF_GEN3_SD("sd2",      R8A77965_CLK_SD2,       CLK_SDSRC,      0x268),
-       DEF_GEN3_SD("sd3",      R8A77965_CLK_SD3,       CLK_SDSRC,      0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A77965_CLK_SD0H,      CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A77965_CLK_SD1H,      CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A77965_CLK_SD2H,      CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A77965_CLK_SD3H,      CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A77965_CLK_SD0,       R8A77965_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A77965_CLK_SD1,       R8A77965_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A77965_CLK_SD2,       R8A77965_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A77965_CLK_SD3,       R8A77965_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A77965_CLK_CL,        CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A77965_CLK_CR,        CLK_PLL1_DIV4,  2, 1),
index 9fe3722..f3cd64d 100644 (file)
@@ -96,7 +96,8 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A77980_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A77980_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A77980_CLK_SD0,   CLK_SDSRC,    0x0074),
+       DEF_GEN3_SDH("sd0h",    R8A77980_CLK_SD0H,  CLK_SDSRC,         0x0074),
+       DEF_GEN3_SD("sd0",      R8A77980_CLK_SD0,   R8A77980_CLK_SD0H, 0x0074),
 
        DEF_FIXED("cl",         R8A77980_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A77980_CLK_CP,    CLK_EXTAL,      2, 1),
index a582f2e..faf60f7 100644 (file)
@@ -100,9 +100,12 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
        DEF_FIXED("s3d2",      R8A77990_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",      R8A77990_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",     R8A77990_CLK_SD0,   CLK_SDSRC,     0x0074),
-       DEF_GEN3_SD("sd1",     R8A77990_CLK_SD1,   CLK_SDSRC,     0x0078),
-       DEF_GEN3_SD("sd3",     R8A77990_CLK_SD3,   CLK_SDSRC,     0x026c),
+       DEF_GEN3_SDH("sd0h",   R8A77990_CLK_SD0H,  CLK_SDSRC,         0x0074),
+       DEF_GEN3_SDH("sd1h",   R8A77990_CLK_SD1H,  CLK_SDSRC,         0x0078),
+       DEF_GEN3_SDH("sd3h",   R8A77990_CLK_SD3H,  CLK_SDSRC,         0x026c),
+       DEF_GEN3_SD("sd0",     R8A77990_CLK_SD0,   R8A77990_CLK_SD0H, 0x0074),
+       DEF_GEN3_SD("sd1",     R8A77990_CLK_SD1,   R8A77990_CLK_SD1H, 0x0078),
+       DEF_GEN3_SD("sd3",     R8A77990_CLK_SD3,   R8A77990_CLK_SD3H, 0x026c),
 
        DEF_FIXED("cl",        R8A77990_CLK_CL,    CLK_PLL1,      48, 1),
        DEF_FIXED("cr",        R8A77990_CLK_CR,    CLK_PLL1D2,     2, 1),
index 81c0bc1..7713cfd 100644 (file)
@@ -103,7 +103,8 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
        DEF_GEN3_PE("s3d2c",   R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
        DEF_GEN3_PE("s3d4c",   R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
 
-       DEF_GEN3_SD("sd0",     R8A77995_CLK_SD0,   CLK_SDSRC,     0x268),
+       DEF_GEN3_SDH("sd0h",   R8A77995_CLK_SD0H, CLK_SDSRC,         0x268),
+       DEF_GEN3_SD("sd0",     R8A77995_CLK_SD0,  R8A77995_CLK_SD0H, 0x268),
 
        DEF_DIV6P1("canfd",    R8A77995_CLK_CANFD, CLK_PLL0D3,    0x244),
        DEF_DIV6P1("mso",      R8A77995_CLK_MSO,   CLK_PLL1D2,    0x014),
index fbd7454..1c09d4e 100644 (file)
  * Copyright (C) 2015 Renesas Electronics Corp.
  */
 
-#include <linux/bug.h>
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/init.h>
-#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/pm.h>
-#include <linux/slab.h>
 #include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
 
-#include "rcar-cpg-lib.h"
 #include "renesas-cpg-mssr.h"
-
-enum rcar_r8a779a0_clk_types {
-       CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM,
-       CLK_TYPE_R8A779A0_PLL1,
-       CLK_TYPE_R8A779A0_PLL2X_3X,     /* PLL[23][01] */
-       CLK_TYPE_R8A779A0_PLL5,
-       CLK_TYPE_R8A779A0_Z,
-       CLK_TYPE_R8A779A0_SD,
-       CLK_TYPE_R8A779A0_MDSEL,        /* Select parent/divider using mode pin */
-       CLK_TYPE_R8A779A0_OSC,  /* OSC EXTAL predivider and fixed divider */
-       CLK_TYPE_R8A779A0_RPCSRC,
-       CLK_TYPE_R8A779A0_RPC,
-       CLK_TYPE_R8A779A0_RPCD2,
-};
-
-struct rcar_r8a779a0_cpg_pll_config {
-       u8 extal_div;
-       u8 pll1_mult;
-       u8 pll1_div;
-       u8 pll5_mult;
-       u8 pll5_div;
-       u8 osc_prediv;
-};
+#include "rcar-gen4-cpg.h"
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
@@ -85,33 +58,18 @@ enum clk_ids {
 };
 
 #define DEF_PLL(_name, _id, _offset)   \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL2X_3X, CLK_MAIN, \
                 .offset = _offset)
 
-#define DEF_Z(_name, _id, _parent, _div, _offset)      \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_Z, _parent, .div = _div, \
-                .offset = _offset)
-
-#define DEF_SD(_name, _id, _parent, _offset)   \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
-
-#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL,   \
-                (_parent0) << 16 | (_parent1),         \
-                .div = (_div0) << 16 | (_div1), .offset = _md)
-
-#define DEF_OSC(_name, _id, _parent, _div)             \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div)
-
 static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        /* External Clock Inputs */
        DEF_INPUT("extal",  CLK_EXTAL),
        DEF_INPUT("extalr", CLK_EXTALR),
 
        /* Internal Core Clocks */
-       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_R8A779A0_MAIN, CLK_EXTAL),
-       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_R8A779A0_PLL1, CLK_MAIN),
-       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_R8A779A0_PLL5, CLK_MAIN),
+       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_GEN4_PLL5, CLK_MAIN),
        DEF_PLL(".pll20", CLK_PLL20,    0x0834),
        DEF_PLL(".pll21", CLK_PLL21,    0x0838),
        DEF_PLL(".pll30", CLK_PLL30,    0x083c),
@@ -128,14 +86,14 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        DEF_FIXED(".s3",                CLK_S3,         CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED(".sdsrc",             CLK_SDSRC,      CLK_PLL5_DIV4,  1, 1),
        DEF_RATE(".oco",                CLK_OCO,        32768),
-       DEF_BASE(".rpcsrc",      CLK_RPCSRC,       CLK_TYPE_R8A779A0_RPCSRC, CLK_PLL5),
-       DEF_BASE("rpc",          R8A779A0_CLK_RPC, CLK_TYPE_R8A779A0_RPC, CLK_RPCSRC),
-       DEF_BASE("rpcd2",        R8A779A0_CLK_RPCD2, CLK_TYPE_R8A779A0_RPCD2,
+       DEF_BASE(".rpcsrc",      CLK_RPCSRC,       CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+       DEF_BASE("rpc",          R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+       DEF_BASE("rpcd2",        R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2,
                 R8A779A0_CLK_RPC),
 
        /* Core Clock Outputs */
-       DEF_Z("z0",             R8A779A0_CLK_Z0,        CLK_PLL20,      2, 0),
-       DEF_Z("z1",             R8A779A0_CLK_Z1,        CLK_PLL21,      2, 8),
+       DEF_GEN4_Z("z0",        R8A779A0_CLK_Z0,        CLK_TYPE_GEN4_Z,        CLK_PLL20,      2, 0),
+       DEF_GEN4_Z("z1",        R8A779A0_CLK_Z1,        CLK_TYPE_GEN4_Z,        CLK_PLL21,      2, 8),
        DEF_FIXED("zx",         R8A779A0_CLK_ZX,        CLK_PLL20_DIV2, 2, 1),
        DEF_FIXED("s1d1",       R8A779A0_CLK_S1D1,      CLK_S1,         1, 1),
        DEF_FIXED("s1d2",       R8A779A0_CLK_S1D2,      CLK_S1,         2, 1),
@@ -159,15 +117,16 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        DEF_FIXED("cp",         R8A779A0_CLK_CP,        CLK_EXTAL,      2, 1),
        DEF_FIXED("cl16mck",    R8A779A0_CLK_CL16MCK,   CLK_PLL1_DIV2,  64, 1),
 
-       DEF_SD("sd0",           R8A779A0_CLK_SD0,       CLK_SDSRC,      0x870),
+       DEF_GEN4_SDH("sdh0",    R8A779A0_CLK_SD0H,      CLK_SDSRC,         0x870),
+       DEF_GEN4_SD("sd0",      R8A779A0_CLK_SD0,       R8A779A0_CLK_SD0H, 0x870),
 
        DEF_DIV6P1("mso",       R8A779A0_CLK_MSO,       CLK_PLL5_DIV4,  0x87c),
        DEF_DIV6P1("canfd",     R8A779A0_CLK_CANFD,     CLK_PLL5_DIV4,  0x878),
        DEF_DIV6P1("csi0",      R8A779A0_CLK_CSI0,      CLK_PLL5_DIV4,  0x880),
        DEF_DIV6P1("dsi",       R8A779A0_CLK_DSI,       CLK_PLL5_DIV4,  0x884),
 
-       DEF_OSC("osc",          R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
-       DEF_MDSEL("r",          R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+       DEF_GEN4_OSC("osc",     R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
+       DEF_GEN4_MDSEL("r",     R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
 };
 
 static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
@@ -271,256 +230,6 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
        DEF_MOD("vspx3",        1031,   R8A779A0_CLK_S1D1),
 };
 
-static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
-static unsigned int cpg_clk_extalr __initdata;
-static u32 cpg_mode __initdata;
-
-/*
- * Z0 Clock & Z1 Clock
- */
-#define CPG_FRQCRB                     0x00000804
-#define CPG_FRQCRB_KICK                        BIT(31)
-#define CPG_FRQCRC                     0x00000808
-
-struct cpg_z_clk {
-       struct clk_hw hw;
-       void __iomem *reg;
-       void __iomem *kick_reg;
-       unsigned long max_rate;         /* Maximum rate for normal mode */
-       unsigned int fixed_div;
-       u32 mask;
-};
-
-#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
-
-static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
-                                          unsigned long parent_rate)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int mult;
-       u32 val;
-
-       val = readl(zclk->reg) & zclk->mask;
-       mult = 32 - (val >> __ffs(zclk->mask));
-
-       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
-                                    32 * zclk->fixed_div);
-}
-
-static int cpg_z_clk_determine_rate(struct clk_hw *hw,
-                                   struct clk_rate_request *req)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int min_mult, max_mult, mult;
-       unsigned long rate, prate;
-
-       rate = min(req->rate, req->max_rate);
-       if (rate <= zclk->max_rate) {
-               /* Set parent rate to initial value for normal modes */
-               prate = zclk->max_rate;
-       } else {
-               /* Set increased parent rate for boost modes */
-               prate = rate;
-       }
-       req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
-                                                 prate * zclk->fixed_div);
-
-       prate = req->best_parent_rate / zclk->fixed_div;
-       min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
-       max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
-       if (max_mult < min_mult)
-               return -EINVAL;
-
-       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
-       mult = clamp(mult, min_mult, max_mult);
-
-       req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
-       return 0;
-}
-
-static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long parent_rate)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int mult;
-       unsigned int i;
-
-       mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
-                                      parent_rate);
-       mult = clamp(mult, 1U, 32U);
-
-       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
-               return -EBUSY;
-
-       cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
-
-       /*
-        * Set KICK bit in FRQCRB to update hardware setting and wait for
-        * clock change completion.
-        */
-       cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
-
-       /*
-        * Note: There is no HW information about the worst case latency.
-        *
-        * Using experimental measurements, it seems that no more than
-        * ~10 iterations are needed, independently of the CPU rate.
-        * Since this value might be dependent on external xtal rate, pll1
-        * rate or even the other emulation clocks rate, use 1000 as a
-        * "super" safe value.
-        */
-       for (i = 1000; i; i--) {
-               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
-                       return 0;
-
-               cpu_relax();
-       }
-
-       return -ETIMEDOUT;
-}
-
-static const struct clk_ops cpg_z_clk_ops = {
-       .recalc_rate = cpg_z_clk_recalc_rate,
-       .determine_rate = cpg_z_clk_determine_rate,
-       .set_rate = cpg_z_clk_set_rate,
-};
-
-static struct clk * __init cpg_z_clk_register(const char *name,
-                                             const char *parent_name,
-                                             void __iomem *reg,
-                                             unsigned int div,
-                                             unsigned int offset)
-{
-       struct clk_init_data init = {};
-       struct cpg_z_clk *zclk;
-       struct clk *clk;
-
-       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
-       if (!zclk)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = name;
-       init.ops = &cpg_z_clk_ops;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       zclk->reg = reg + CPG_FRQCRC;
-       zclk->kick_reg = reg + CPG_FRQCRB;
-       zclk->hw.init = &init;
-       zclk->mask = GENMASK(offset + 4, offset);
-       zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
-
-       clk = clk_register(NULL, &zclk->hw);
-       if (IS_ERR(clk)) {
-               kfree(zclk);
-               return clk;
-       }
-
-       zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
-                        zclk->fixed_div;
-       return clk;
-}
-
-/*
- * RPC Clocks
- */
-#define CPG_RPCCKCR 0x874
-
-static const struct clk_div_table cpg_rpcsrc_div_table[] = {
-       { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
-};
-
-static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
-       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
-       struct clk **clks, void __iomem *base,
-       struct raw_notifier_head *notifiers)
-{
-       const struct clk *parent;
-       unsigned int mult = 1;
-       unsigned int div = 1;
-       u32 value;
-
-       parent = clks[core->parent & 0xffff];   /* some types use high bits */
-       if (IS_ERR(parent))
-               return ERR_CAST(parent);
-
-       switch (core->type) {
-       case CLK_TYPE_R8A779A0_MAIN:
-               div = cpg_pll_config->extal_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL1:
-               mult = cpg_pll_config->pll1_mult;
-               div = cpg_pll_config->pll1_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL2X_3X:
-               value = readl(base + core->offset);
-               mult = (((value >> 24) & 0x7f) + 1) * 2;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL5:
-               mult = cpg_pll_config->pll5_mult;
-               div = cpg_pll_config->pll5_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_Z:
-               return cpg_z_clk_register(core->name, __clk_get_name(parent),
-                                         base, core->div, core->offset);
-
-       case CLK_TYPE_R8A779A0_SD:
-               return cpg_sd_clk_register(core->name, base, core->offset,
-                                          __clk_get_name(parent), notifiers,
-                                          false);
-               break;
-
-       case CLK_TYPE_R8A779A0_MDSEL:
-               /*
-                * Clock selectable between two parents and two fixed dividers
-                * using a mode pin
-                */
-               if (cpg_mode & BIT(core->offset)) {
-                       div = core->div & 0xffff;
-               } else {
-                       parent = clks[core->parent >> 16];
-                       if (IS_ERR(parent))
-                               return ERR_CAST(parent);
-                       div = core->div >> 16;
-               }
-               mult = 1;
-               break;
-
-       case CLK_TYPE_R8A779A0_OSC:
-               /*
-                * Clock combining OSC EXTAL predivider and a fixed divider
-                */
-               div = cpg_pll_config->osc_prediv * core->div;
-               break;
-
-       case CLK_TYPE_R8A779A0_RPCSRC:
-               return clk_register_divider_table(NULL, core->name,
-                                                 __clk_get_name(parent), 0,
-                                                 base + CPG_RPCCKCR, 3, 2, 0,
-                                                 cpg_rpcsrc_div_table,
-                                                 &cpg_lock);
-
-       case CLK_TYPE_R8A779A0_RPC:
-               return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
-                                           __clk_get_name(parent), notifiers);
-
-       case CLK_TYPE_R8A779A0_RPCD2:
-               return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
-                                             __clk_get_name(parent));
-
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
-       return clk_register_fixed_factor(NULL, core->name,
-                                        __clk_get_name(parent), 0, mult, div);
-}
-
 static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
        MOD_CLK_ID(907),        /* RWDT */
 };
@@ -539,17 +248,19 @@ static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
  */
 #define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
                                         (((md) & BIT(13)) >> 13))
-
-static const struct rcar_r8a779a0_cpg_pll_config cpg_pll_configs[4] = {
-       /* EXTAL div    PLL1 mult/div   PLL5 mult/div   OSC prediv */
-       { 1,            128,    1,      192,    1,      16,     },
-       { 1,            106,    1,      160,    1,      19,     },
-       { 0,            0,      0,      0,      0,      0,      },
-       { 2,            128,    1,      192,    1,      32,     },
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+       /* EXTAL div    PLL1 mult/div   PLL2 mult/div   PLL3 mult/div   PLL5 mult/div   PLL6 mult/div   OSC prediv */
+       { 1,            128,    1,      0,      0,      0,      0,      192,    1,      0,      0,      16,     },
+       { 1,            106,    1,      0,      0,      0,      0,      160,    1,      0,      0,      19,     },
+       { 0,            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      },
+       { 2,            128,    1,      0,      0,      0,      0,      192,    1,      0,      0,      32,     },
 };
 
+
 static int __init r8a779a0_cpg_mssr_init(struct device *dev)
 {
+       const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
        int error;
 
        error = rcar_rst_read_mode_pins(&cpg_mode);
@@ -557,10 +268,8 @@ static int __init r8a779a0_cpg_mssr_init(struct device *dev)
                return error;
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
-       cpg_clk_extalr = CLK_EXTALR;
-       spin_lock_init(&cpg_lock);
 
-       return 0;
+       return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
 }
 
 const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
@@ -581,7 +290,7 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
 
        /* Callbacks */
        .init = r8a779a0_cpg_mssr_init,
-       .cpg_clk_register = rcar_r8a779a0_cpg_clk_register,
+       .cpg_clk_register = rcar_gen4_cpg_clk_register,
 
-       .reg_layout = CLK_REG_LAYOUT_RCAR_V3U,
+       .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
 };
diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
new file mode 100644 (file)
index 0000000..e6ec02c
--- /dev/null
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779f0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on r8a779a0-cpg-mssr.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A779F0_CLK_R,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_EXTALR,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL1,
+       CLK_PLL2,
+       CLK_PLL3,
+       CLK_PLL5,
+       CLK_PLL6,
+       CLK_PLL1_DIV2,
+       CLK_PLL2_DIV2,
+       CLK_PLL3_DIV2,
+       CLK_PLL5_DIV2,
+       CLK_PLL5_DIV4,
+       CLK_PLL6_DIV2,
+       CLK_S0,
+       CLK_SDSRC,
+       CLK_RPCSRC,
+       CLK_OCO,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("extalr",     CLK_EXTALR),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+       DEF_BASE(".pll2", CLK_PLL2,     CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+       DEF_BASE(".pll3", CLK_PLL3,     CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+       DEF_BASE(".pll6", CLK_PLL6,     CLK_TYPE_GEN4_PLL6, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,  CLK_PLL1,       2, 1),
+       DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2,  CLK_PLL2,       2, 1),
+       DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2,  CLK_PLL3,       2, 1),
+       DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2,  CLK_PLL5,       2, 1),
+       DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4,  CLK_PLL5_DIV2,  2, 1),
+       DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2,  CLK_PLL6,       2, 1),
+       DEF_FIXED(".s0",        CLK_S0,         CLK_PLL1_DIV2,  2, 1),
+       DEF_BASE(".sdsrc",      CLK_SDSRC,      CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+       DEF_RATE(".oco",        CLK_OCO,        32768),
+
+       DEF_BASE(".rpcsrc",     CLK_RPCSRC,             CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+       DEF_BASE(".rpc",        R8A779F0_CLK_RPC,       CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A779F0_CLK_RPCD2,     CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC),
+
+       /* Core Clock Outputs */
+       DEF_FIXED("s0d2",       R8A779F0_CLK_S0D2,      CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A779F0_CLK_S0D3,      CLK_S0,         3, 1),
+       DEF_FIXED("s0d4",       R8A779F0_CLK_S0D4,      CLK_S0,         4, 1),
+       DEF_FIXED("cl16m",      R8A779F0_CLK_CL16M,     CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_mm",    R8A779F0_CLK_S0D2_MM,   CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_mm",    R8A779F0_CLK_S0D3_MM,   CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_mm",    R8A779F0_CLK_S0D4_MM,   CLK_S0,         4, 1),
+       DEF_FIXED("cl16m_mm",   R8A779F0_CLK_CL16M_MM,  CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_rt",    R8A779F0_CLK_S0D2_RT,   CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_rt",    R8A779F0_CLK_S0D3_RT,   CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_rt",    R8A779F0_CLK_S0D4_RT,   CLK_S0,         4, 1),
+       DEF_FIXED("s0d6_rt",    R8A779F0_CLK_S0D6_RT,   CLK_S0,         6, 1),
+       DEF_FIXED("cl16m_rt",   R8A779F0_CLK_CL16M_RT,  CLK_S0,         48, 1),
+       DEF_FIXED("s0d3_per",   R8A779F0_CLK_S0D3_PER,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d6_per",   R8A779F0_CLK_S0D6_PER,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d12_per",  R8A779F0_CLK_S0D12_PER, CLK_S0,         12, 1),
+       DEF_FIXED("s0d24_per",  R8A779F0_CLK_S0D24_PER, CLK_S0,         24, 1),
+       DEF_FIXED("cl16m_per",  R8A779F0_CLK_CL16M_PER, CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_hsc",   R8A779F0_CLK_S0D2_HSC,  CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_hsc",   R8A779F0_CLK_S0D3_HSC,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_hsc",   R8A779F0_CLK_S0D4_HSC,  CLK_S0,         4, 1),
+       DEF_FIXED("s0d6_hsc",   R8A779F0_CLK_S0D6_HSC,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d12_hsc",  R8A779F0_CLK_S0D12_HSC, CLK_S0,         12, 1),
+       DEF_FIXED("cl16m_hsc",  R8A779F0_CLK_CL16M_HSC, CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_cc",    R8A779F0_CLK_S0D2_CC,   CLK_S0,         2, 1),
+       DEF_FIXED("rsw2",       R8A779F0_CLK_RSW2,      CLK_PLL5,       2, 1),
+       DEF_FIXED("cbfusa",     R8A779F0_CLK_CBFUSA,    CLK_EXTAL,      2, 1),
+       DEF_FIXED("cpex",       R8A779F0_CLK_CPEX,      CLK_EXTAL,      2, 1),
+
+       DEF_GEN4_SD("sd0",      R8A779F0_CLK_SD0,       CLK_SDSRC,      0x870),
+       DEF_DIV6P1("mso",       R8A779F0_CLK_MSO,       CLK_PLL5_DIV4,  0x87c),
+
+       DEF_GEN4_OSC("osc",     R8A779F0_CLK_OSC,       CLK_EXTAL,      8),
+       DEF_GEN4_MDSEL("r",     R8A779F0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
+       DEF_MOD("scif0",        702,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif1",        703,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif3",        704,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif4",        705,    R8A779F0_CLK_S0D12_PER),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ *   MD         EXTAL          PLL1    PLL2    PLL3    PLL5    PLL6    OSC
+ * 14 13 (MHz)
+ * ----------------------------------------------------------------
+ * 0  0         16    / 1      x200    x150    x200    x200    x134    /15
+ * 0  1         20    / 1      x160    x120    x160    x160    x106    /19
+ * 1  0         Prohibited setting
+ * 1  1         40    / 2      x160    x120    x160    x160    x106    /38
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
+                                        (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+       /* EXTAL div    PLL1 mult/div   PLL2 mult/div   PLL3 mult/div   PLL5 mult/div   PLL6 mult/div   OSC prediv */
+       { 1,            200,    1,      150,    1,      200,    1,      200,    1,      134,    1,      15,     },
+       { 1,            160,    1,      120,    1,      160,    1,      160,    1,      106,    1,      19,     },
+       { 0,            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      },
+       { 2,            160,    1,      120,    1,      160,    1,      160,    1,      106,    1,      38,     },
+};
+
+static int __init r8a779f0_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+       if (!cpg_pll_config->extal_div) {
+               dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+               return -EINVAL;
+       }
+
+       return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779f0_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a779f0_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a779f0_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a779f0_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a779f0_mod_clks),
+       .num_hw_mod_clks = 28 * 32,
+
+       /* Callbacks */
+       .init = r8a779f0_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+       .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
index 47c1626..79042bf 100644 (file)
@@ -26,15 +26,15 @@ enum clk_ids {
        CLK_PLL1,
        CLK_PLL2,
        CLK_PLL2_DIV2,
-       CLK_PLL2_DIV16,
-       CLK_PLL2_DIV20,
+       CLK_PLL2_DIV2_8,
+       CLK_PLL2_DIV2_10,
        CLK_PLL3,
        CLK_PLL3_400,
        CLK_PLL3_533,
        CLK_PLL3_DIV2,
+       CLK_PLL3_DIV2_2,
        CLK_PLL3_DIV2_4,
        CLK_PLL3_DIV2_4_2,
-       CLK_PLL3_DIV4,
        CLK_SEL_PLL3_3,
        CLK_DIV_PLL3_C,
        CLK_PLL4,
@@ -50,12 +50,21 @@ enum clk_ids {
        CLK_PLL2_SDHI_266,
        CLK_SD0_DIV4,
        CLK_SD1_DIV4,
+       CLK_SEL_GPU2,
 
        /* Module Clocks */
        MOD_CLK_BASE,
 };
 
 /* Divider tables */
+static const struct clk_div_table dtable_1_8[] = {
+       {0, 1},
+       {1, 2},
+       {2, 4},
+       {3, 8},
+       {0, 0},
+};
+
 static const struct clk_div_table dtable_1_32[] = {
        {0, 1},
        {1, 2},
@@ -69,6 +78,7 @@ static const struct clk_div_table dtable_1_32[] = {
 static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
 static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
 static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
 
 static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
        /* External Clock Inputs */
@@ -94,13 +104,13 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
        DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
        DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
 
-       DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16),
-       DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20),
+       DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+       DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10),
 
        DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+       DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2),
        DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
        DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
-       DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4),
        DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3,
                sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY),
        DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3,
@@ -108,13 +118,16 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
 
        DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
        DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
+       DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2,
+               sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY),
 
        /* Core output clk */
-       DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1),
-       DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A,
+       DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8,
+               CLK_DIVIDER_HIWORD_MASK),
+       DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A,
                dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
        DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2),
-       DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1),
+       DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1),
        DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4,
                DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
        DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
@@ -132,6 +145,8 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
                   sel_shdi, ARRAY_SIZE(sel_shdi)),
        DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
        DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+       DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8,
+               CLK_DIVIDER_HIWORD_MASK),
 };
 
 static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
@@ -145,6 +160,24 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x52c, 0),
        DEF_MOD("dmac_pclk",    R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
                                0x52c, 1),
+       DEF_MOD("ostm0_pclk",   R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0,
+                               0x534, 0),
+       DEF_MOD("ostm1_clk",    R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0,
+                               0x534, 1),
+       DEF_MOD("ostm2_pclk",   R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
+                               0x534, 2),
+       DEF_MOD("wdt0_pclk",    R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0,
+                               0x548, 0),
+       DEF_MOD("wdt0_clk",     R9A07G044_WDT0_CLK, R9A07G044_OSCCLK,
+                               0x548, 1),
+       DEF_MOD("wdt1_pclk",    R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0,
+                               0x548, 2),
+       DEF_MOD("wdt1_clk",     R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
+                               0x548, 3),
+       DEF_MOD("wdt2_pclk",    R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0,
+                               0x548, 4),
+       DEF_MOD("wdt2_clk",     R9A07G044_WDT2_CLK, R9A07G044_OSCCLK,
+                               0x548, 5),
        DEF_MOD("spi_clk2",     R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
                                0x550, 0),
        DEF_MOD("spi_clk",      R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
@@ -165,6 +198,12 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x554, 6),
        DEF_MOD("sdhi1_aclk",   R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
                                0x554, 7),
+       DEF_MOD("gpu_clk",      R9A07G044_GPU_CLK, R9A07G044_CLK_G,
+                               0x558, 0),
+       DEF_MOD("gpu_axi_clk",  R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1,
+                               0x558, 1),
+       DEF_MOD("gpu_ace_clk",  R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1,
+                               0x558, 2),
        DEF_MOD("ssi0_pclk",    R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
                                0x570, 0),
        DEF_MOD("ssi0_sfr",     R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
@@ -217,6 +256,14 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x584, 4),
        DEF_MOD("sci0",         R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
                                0x588, 0),
+       DEF_MOD("sci1",         R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0,
+                               0x588, 1),
+       DEF_MOD("rspi0",        R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0,
+                               0x590, 0),
+       DEF_MOD("rspi1",        R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0,
+                               0x590, 1),
+       DEF_MOD("rspi2",        R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0,
+                               0x590, 2),
        DEF_MOD("canfd",        R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
                                0x594, 0),
        DEF_MOD("gpio",         R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
@@ -225,6 +272,8 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x5a8, 0),
        DEF_MOD("adc_pclk",     R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
                                0x5a8, 1),
+       DEF_MOD("tsu_pclk",     R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU,
+                               0x5ac, 0),
 };
 
 static struct rzg2l_reset r9a07g044_resets[] = {
@@ -233,9 +282,18 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
        DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
        DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
+       DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0),
+       DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1),
+       DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2),
+       DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0),
+       DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
+       DEF_RST(R9A07G044_WDT2_PRESETN, 0x848, 2),
        DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
        DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
        DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
+       DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0),
+       DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1),
+       DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2),
        DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
        DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
        DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
@@ -256,6 +314,10 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3),
        DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4),
        DEF_RST(R9A07G044_SCI0_RST, 0x888, 0),
+       DEF_RST(R9A07G044_SCI1_RST, 0x888, 1),
+       DEF_RST(R9A07G044_RSPI0_RST, 0x890, 0),
+       DEF_RST(R9A07G044_RSPI1_RST, 0x890, 1),
+       DEF_RST(R9A07G044_RSPI2_RST, 0x890, 2),
        DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0),
        DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1),
        DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0),
@@ -263,6 +325,7 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2),
        DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0),
        DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1),
+       DEF_RST(R9A07G044_TSU_PRESETN, 0x8ac, 0),
 };
 
 static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
index e93f001..e2e0447 100644 (file)
@@ -65,206 +65,49 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
 /*
  * SDn Clock
  */
-#define CPG_SD_STP_HCK         BIT(9)
-#define CPG_SD_STP_CK          BIT(8)
-
-#define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
-#define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
-
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
-{ \
-       .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
-              ((sd_srcfc) << 2) | \
-              ((sd_fc) << 0), \
-       .div = (sd_div), \
-}
 
-struct sd_div_table {
-       u32 val;
-       unsigned int div;
-};
+#define SDnSRCFC_SHIFT 2
+#define STPnHCK        BIT(9 - SDnSRCFC_SHIFT)
 
-struct sd_clock {
-       struct clk_hw hw;
-       const struct sd_div_table *div_table;
-       struct cpg_simple_notifier csn;
-       unsigned int div_num;
-       unsigned int cur_div_idx;
-};
-
-/* SDn divider
- *           sd_srcfc   sd_fc   div
- * stp_hck   (div)      (div)     = sd_srcfc x sd_fc
- *---------------------------------------------------------
- *  0         0 (1)      1 (4)      4 : SDR104 / HS200 / HS400 (8 TAP)
- *  0         1 (2)      1 (4)      8 : SDR50
- *  1         2 (4)      1 (4)     16 : HS / SDR25
- *  1         3 (8)      1 (4)     32 : NS / SDR12
- *  1         4 (16)     1 (4)     64
- *  0         0 (1)      0 (2)      2
- *  0         1 (2)      0 (2)      4 : SDR104 / HS200 / HS400 (4 TAP)
- *  1         2 (4)      0 (2)      8
- *  1         3 (8)      0 (2)     16
- *  1         4 (16)     0 (2)     32
- *
- *  NOTE: There is a quirk option to ignore the first row of the dividers
- *  table when searching for suitable settings. This is because HS400 on
- *  early ES versions of H3 and M3-W requires a specific setting to work.
- */
-static const struct sd_div_table cpg_sd_div_table[] = {
-/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  sd_srcfc,   sd_fc,  sd_div) */
-       CPG_SD_DIV_TABLE_DATA(0,        0,          1,        4),
-       CPG_SD_DIV_TABLE_DATA(0,        1,          1,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        2,          1,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        3,          1,       32),
-       CPG_SD_DIV_TABLE_DATA(1,        4,          1,       64),
-       CPG_SD_DIV_TABLE_DATA(0,        0,          0,        2),
-       CPG_SD_DIV_TABLE_DATA(0,        1,          0,        4),
-       CPG_SD_DIV_TABLE_DATA(1,        2,          0,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        3,          0,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        4,          0,       32),
+static const struct clk_div_table cpg_sdh_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
+       { STPnHCK | 4, 16 }, { 0, 0 },
 };
 
-#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
-
-static int cpg_sd_clock_enable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
-                      clock->div_table[clock->cur_div_idx].val &
-                      CPG_SD_STP_MASK);
-
-       return 0;
-}
-
-static void cpg_sd_clock_disable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
-}
-
-static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
+struct clk * __init cpg_sdh_clk_register(const char *name,
+       void __iomem *sdnckcr, const char *parent_name,
+       struct raw_notifier_head *notifiers)
 {
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
-}
+       struct cpg_simple_notifier *csn;
+       struct clk *clk;
 
-static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
+       csn = kzalloc(sizeof(*csn), GFP_KERNEL);
+       if (!csn)
+               return ERR_PTR(-ENOMEM);
 
-       return DIV_ROUND_CLOSEST(parent_rate,
-                                clock->div_table[clock->cur_div_idx].div);
-}
+       csn->reg = sdnckcr;
 
-static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
-                                      struct clk_rate_request *req)
-{
-       unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned long calc_rate, diff;
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++) {
-               calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
-                                             clock->div_table[i].div);
-               if (calc_rate < req->min_rate || calc_rate > req->max_rate)
-                       continue;
-
-               diff = calc_rate > req->rate ? calc_rate - req->rate
-                                            : req->rate - calc_rate;
-               if (diff < diff_min) {
-                       best_rate = calc_rate;
-                       diff_min = diff;
-               }
+       clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+                                        SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
+                                        &cpg_lock);
+       if (IS_ERR(clk)) {
+               kfree(csn);
+               return clk;
        }
 
-       if (best_rate == ULONG_MAX)
-               return -EINVAL;
-
-       req->rate = best_rate;
-       return 0;
-}
-
-static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++)
-               if (rate == DIV_ROUND_CLOSEST(parent_rate,
-                                             clock->div_table[i].div))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       clock->cur_div_idx = i;
-
-       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
-                      clock->div_table[i].val &
-                      (CPG_SD_STP_MASK | CPG_SD_FC_MASK));
-
-       return 0;
+       cpg_simple_notifier_register(notifiers, csn);
+       return clk;
 }
 
-static const struct clk_ops cpg_sd_clock_ops = {
-       .enable = cpg_sd_clock_enable,
-       .disable = cpg_sd_clock_disable,
-       .is_enabled = cpg_sd_clock_is_enabled,
-       .recalc_rate = cpg_sd_clock_recalc_rate,
-       .determine_rate = cpg_sd_clock_determine_rate,
-       .set_rate = cpg_sd_clock_set_rate,
+static const struct clk_div_table cpg_sd_div_table[] = {
+       { 0, 2 }, { 1, 4 }, { 0, 0 },
 };
 
 struct clk * __init cpg_sd_clk_register(const char *name,
-       void __iomem *base, unsigned int offset, const char *parent_name,
-       struct raw_notifier_head *notifiers, bool skip_first)
+       void __iomem *sdnckcr, const char *parent_name)
 {
-       struct clk_init_data init = {};
-       struct sd_clock *clock;
-       struct clk *clk;
-       u32 val;
-
-       clock = kzalloc(sizeof(*clock), GFP_KERNEL);
-       if (!clock)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = name;
-       init.ops = &cpg_sd_clock_ops;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       clock->csn.reg = base + offset;
-       clock->hw.init = &init;
-       clock->div_table = cpg_sd_div_table;
-       clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
-
-       if (skip_first) {
-               clock->div_table++;
-               clock->div_num--;
-       }
-
-       val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
-       val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
-       writel(val, clock->csn.reg);
-
-       clk = clk_register(NULL, &clock->hw);
-       if (IS_ERR(clk))
-               goto free_clock;
-
-       cpg_simple_notifier_register(notifiers, &clock->csn);
-       return clk;
-
-free_clock:
-       kfree(clock);
-       return clk;
+       return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+                                         0, 2, 0, cpg_sd_div_table, &cpg_lock);
 }
 
 struct rpc_clock {
index 35c0217..94627df 100644 (file)
@@ -26,9 +26,12 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
 
 void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set);
 
+struct clk * __init cpg_sdh_clk_register(const char *name,
+       void __iomem *sdnckcr, const char *parent_name,
+       struct raw_notifier_head *notifiers);
+
 struct clk * __init cpg_sd_clk_register(const char *name,
-       void __iomem *base, unsigned int offset, const char *parent_name,
-       struct raw_notifier_head *notifiers, bool skip_first);
+       void __iomem *sdnckcr, const char *parent_name);
 
 struct clk * __init cpg_rpc_clk_register(const char *name,
        void __iomem *rpcckcr, const char *parent_name,
index 741f6e7..e668f23 100644 (file)
@@ -312,29 +312,20 @@ static u32 cpg_quirks __initdata;
 
 #define PLL_ERRATA     BIT(0)          /* Missing PLL0/2/4 post-divider */
 #define RCKCR_CKSEL    BIT(1)          /* Manual RCLK parent selection */
-#define SD_SKIP_FIRST  BIT(2)          /* Skip first clock in SD table */
 
 
 static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
        {
                .soc_id = "r8a7795", .revision = "ES1.0",
-               .data = (void *)(PLL_ERRATA | RCKCR_CKSEL | SD_SKIP_FIRST),
+               .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
        },
        {
                .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
-       },
-       {
-               .soc_id = "r8a7795", .revision = "ES2.0",
-               .data = (void *)SD_SKIP_FIRST,
+               .data = (void *)(RCKCR_CKSEL),
        },
        {
                .soc_id = "r8a7796", .revision = "ES1.0",
-               .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
-       },
-       {
-               .soc_id = "r8a7796", .revision = "ES1.1",
-               .data = (void *)SD_SKIP_FIRST,
+               .data = (void *)(RCKCR_CKSEL),
        },
        { /* sentinel */ }
 };
@@ -401,10 +392,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                        mult *= 2;
                break;
 
+       case CLK_TYPE_GEN3_SDH:
+               return cpg_sdh_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent), notifiers);
+
        case CLK_TYPE_GEN3_SD:
-               return cpg_sd_clk_register(core->name, base, core->offset,
-                                          __clk_get_name(parent), notifiers,
-                                          cpg_quirks & SD_SKIP_FIRST);
+               return cpg_sd_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent));
 
        case CLK_TYPE_GEN3_R:
                if (cpg_quirks & RCKCR_CKSEL) {
index 3d949c4..2bc0afa 100644 (file)
@@ -17,6 +17,7 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_PLL2,
        CLK_TYPE_GEN3_PLL3,
        CLK_TYPE_GEN3_PLL4,
+       CLK_TYPE_GEN3_SDH,
        CLK_TYPE_GEN3_SD,
        CLK_TYPE_GEN3_R,
        CLK_TYPE_GEN3_MDSEL,    /* Select parent/divider using mode pin */
@@ -32,6 +33,9 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_SOC_BASE,
 };
 
+#define DEF_GEN3_SDH(_name, _id, _parent, _offset)     \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN3_SDH, _parent, .offset = _offset)
+
 #define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
        DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
 
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c
new file mode 100644 (file)
index 0000000..54ebf4b
--- /dev/null
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on rcar-gen3-cpg.c
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+#include "rcar-cpg-lib.h"
+
+static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initconst;
+static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+
+/*
+ * Z0 Clock & Z1 Clock
+ */
+#define CPG_FRQCRB                     0x00000804
+#define CPG_FRQCRB_KICK                        BIT(31)
+#define CPG_FRQCRC                     0x00000808
+
+struct cpg_z_clk {
+       struct clk_hw hw;
+       void __iomem *reg;
+       void __iomem *kick_reg;
+       unsigned long max_rate;         /* Maximum rate for normal mode */
+       unsigned int fixed_div;
+       u32 mask;
+};
+
+#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       u32 val;
+
+       val = readl(zclk->reg) & zclk->mask;
+       mult = 32 - (val >> __ffs(zclk->mask));
+
+       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
+                                    32 * zclk->fixed_div);
+}
+
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+                                   struct clk_rate_request *req)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int min_mult, max_mult, mult;
+       unsigned long rate, prate;
+
+       rate = min(req->rate, req->max_rate);
+       if (rate <= zclk->max_rate) {
+               /* Set parent rate to initial value for normal modes */
+               prate = zclk->max_rate;
+       } else {
+               /* Set increased parent rate for boost modes */
+               prate = rate;
+       }
+       req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+                                                 prate * zclk->fixed_div);
+
+       prate = req->best_parent_rate / zclk->fixed_div;
+       min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
+       max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
+       if (max_mult < min_mult)
+               return -EINVAL;
+
+       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
+       mult = clamp(mult, min_mult, max_mult);
+
+       req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
+       return 0;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       unsigned int i;
+
+       mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
+                                      parent_rate);
+       mult = clamp(mult, 1U, 32U);
+
+       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+               return -EBUSY;
+
+       cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
+
+       /*
+        * Set KICK bit in FRQCRB to update hardware setting and wait for
+        * clock change completion.
+        */
+       cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
+
+       /*
+        * Note: There is no HW information about the worst case latency.
+        *
+        * Using experimental measurements, it seems that no more than
+        * ~10 iterations are needed, independently of the CPU rate.
+        * Since this value might be dependent on external xtal rate, pll1
+        * rate or even the other emulation clocks rate, use 1000 as a
+        * "super" safe value.
+        */
+       for (i = 1000; i; i--) {
+               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+       .recalc_rate = cpg_z_clk_recalc_rate,
+       .determine_rate = cpg_z_clk_determine_rate,
+       .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+                                             const char *parent_name,
+                                             void __iomem *reg,
+                                             unsigned int div,
+                                             unsigned int offset)
+{
+       struct clk_init_data init = {};
+       struct cpg_z_clk *zclk;
+       struct clk *clk;
+
+       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+       if (!zclk)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &cpg_z_clk_ops;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       zclk->reg = reg + CPG_FRQCRC;
+       zclk->kick_reg = reg + CPG_FRQCRB;
+       zclk->hw.init = &init;
+       zclk->mask = GENMASK(offset + 4, offset);
+       zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
+
+       clk = clk_register(NULL, &zclk->hw);
+       if (IS_ERR(clk)) {
+               kfree(zclk);
+               return clk;
+       }
+
+       zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
+                        zclk->fixed_div;
+       return clk;
+}
+
+/*
+ * RPC Clocks
+ */
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+       { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
+struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev,
+       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+       struct clk **clks, void __iomem *base,
+       struct raw_notifier_head *notifiers)
+{
+       const struct clk *parent;
+       unsigned int mult = 1;
+       unsigned int div = 1;
+       u32 value;
+
+       parent = clks[core->parent & 0xffff];   /* some types use high bits */
+       if (IS_ERR(parent))
+               return ERR_CAST(parent);
+
+       switch (core->type) {
+       case CLK_TYPE_GEN4_MAIN:
+               div = cpg_pll_config->extal_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL1:
+               mult = cpg_pll_config->pll1_mult;
+               div = cpg_pll_config->pll1_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL2:
+               mult = cpg_pll_config->pll2_mult;
+               div = cpg_pll_config->pll2_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL3:
+               mult = cpg_pll_config->pll3_mult;
+               div = cpg_pll_config->pll3_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL5:
+               mult = cpg_pll_config->pll5_mult;
+               div = cpg_pll_config->pll5_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL6:
+               mult = cpg_pll_config->pll6_mult;
+               div = cpg_pll_config->pll6_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL2X_3X:
+               value = readl(base + core->offset);
+               mult = (((value >> 24) & 0x7f) + 1) * 2;
+               break;
+
+       case CLK_TYPE_GEN4_Z:
+               return cpg_z_clk_register(core->name, __clk_get_name(parent),
+                                         base, core->div, core->offset);
+
+       case CLK_TYPE_GEN4_SDSRC:
+               div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 4;
+               break;
+
+       case CLK_TYPE_GEN4_SDH:
+               return cpg_sdh_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent), notifiers);
+
+       case CLK_TYPE_GEN4_SD:
+               return cpg_sd_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent));
+
+       case CLK_TYPE_GEN4_MDSEL:
+               /*
+                * Clock selectable between two parents and two fixed dividers
+                * using a mode pin
+                */
+               if (cpg_mode & BIT(core->offset)) {
+                       div = core->div & 0xffff;
+               } else {
+                       parent = clks[core->parent >> 16];
+                       if (IS_ERR(parent))
+                               return ERR_CAST(parent);
+                       div = core->div >> 16;
+               }
+               mult = 1;
+               break;
+
+       case CLK_TYPE_GEN4_OSC:
+               /*
+                * Clock combining OSC EXTAL predivider and a fixed divider
+                */
+               div = cpg_pll_config->osc_prediv * core->div;
+               break;
+
+       case CLK_TYPE_GEN4_RPCSRC:
+               return clk_register_divider_table(NULL, core->name,
+                                                 __clk_get_name(parent), 0,
+                                                 base + CPG_RPCCKCR, 3, 2, 0,
+                                                 cpg_rpcsrc_div_table,
+                                                 &cpg_lock);
+
+       case CLK_TYPE_GEN4_RPC:
+               return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
+                                           __clk_get_name(parent), notifiers);
+
+       case CLK_TYPE_GEN4_RPCD2:
+               return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
+                                             __clk_get_name(parent));
+
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       return clk_register_fixed_factor(NULL, core->name,
+                                        __clk_get_name(parent), 0, mult, div);
+}
+
+int __init rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+                             unsigned int clk_extalr, u32 mode)
+{
+       cpg_pll_config = config;
+       cpg_clk_extalr = clk_extalr;
+       cpg_mode = mode;
+
+       spin_lock_init(&cpg_lock);
+
+       return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.h b/drivers/clk/renesas/rcar-gen4-cpg.h
new file mode 100644 (file)
index 0000000..afc8c02
--- /dev/null
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN4_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN4_CPG_H__
+
+enum rcar_gen4_clk_types {
+       CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM,
+       CLK_TYPE_GEN4_PLL1,
+       CLK_TYPE_GEN4_PLL2,
+       CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */
+       CLK_TYPE_GEN4_PLL3,
+       CLK_TYPE_GEN4_PLL5,
+       CLK_TYPE_GEN4_PLL6,
+       CLK_TYPE_GEN4_SDSRC,
+       CLK_TYPE_GEN4_SDH,
+       CLK_TYPE_GEN4_SD,
+       CLK_TYPE_GEN4_MDSEL,    /* Select parent/divider using mode pin */
+       CLK_TYPE_GEN4_Z,
+       CLK_TYPE_GEN4_OSC,      /* OSC EXTAL predivider and fixed divider */
+       CLK_TYPE_GEN4_RPCSRC,
+       CLK_TYPE_GEN4_RPC,
+       CLK_TYPE_GEN4_RPCD2,
+
+       /* SoC specific definitions start here */
+       CLK_TYPE_GEN4_SOC_BASE,
+};
+
+#define DEF_GEN4_SDH(_name, _id, _parent, _offset)     \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_SDH, _parent, .offset = _offset)
+
+#define DEF_GEN4_SD(_name, _id, _parent, _offset)      \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_SD, _parent, .offset = _offset)
+
+#define DEF_GEN4_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_MDSEL,       \
+                (_parent0) << 16 | (_parent1),         \
+                .div = (_div0) << 16 | (_div1), .offset = _md)
+
+#define DEF_GEN4_OSC(_name, _id, _parent, _div)                \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_OSC, _parent, .div = _div)
+
+#define DEF_GEN4_Z(_name, _id, _type, _parent, _div, _offset)  \
+       DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
+
+struct rcar_gen4_cpg_pll_config {
+       u8 extal_div;
+       u8 pll1_mult;
+       u8 pll1_div;
+       u8 pll2_mult;
+       u8 pll2_div;
+       u8 pll3_mult;
+       u8 pll3_div;
+       u8 pll5_mult;
+       u8 pll5_div;
+       u8 pll6_mult;
+       u8 pll6_div;
+       u8 osc_prediv;
+};
+
+#define CPG_RPCCKCR    0x874
+#define SD0CKCR1       0x8a4
+
+struct clk *rcar_gen4_cpg_clk_register(struct device *dev,
+       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+       struct clk **clks, void __iomem *base,
+       struct raw_notifier_head *notifiers);
+int rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+                      unsigned int clk_extalr, u32 mode);
+
+#endif
index 21f762a..5d2c3ed 100644 (file)
@@ -57,9 +57,11 @@ static const u16 mstpsr[] = {
        0x9A0, 0x9A4, 0x9A8, 0x9AC,
 };
 
-static const u16 mstpsr_for_v3u[] = {
+static const u16 mstpsr_for_gen4[] = {
        0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
-       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
+       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
+       0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
+       0x2E60, 0x2E64, 0x2E68, 0x2E6C,
 };
 
 /*
@@ -71,9 +73,11 @@ static const u16 smstpcr[] = {
        0x990, 0x994, 0x998, 0x99C,
 };
 
-static const u16 mstpcr_for_v3u[] = {
+static const u16 mstpcr_for_gen4[] = {
        0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
-       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
+       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
+       0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
+       0x2D60, 0x2D64, 0x2D68, 0x2D6C,
 };
 
 /*
@@ -95,9 +99,11 @@ static const u16 srcr[] = {
        0x920, 0x924, 0x928, 0x92C,
 };
 
-static const u16 srcr_for_v3u[] = {
+static const u16 srcr_for_gen4[] = {
        0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
-       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
+       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
+       0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
+       0x2C60, 0x2C64, 0x2C68, 0x2C6C,
 };
 
 /*
@@ -109,9 +115,11 @@ static const u16 srstclr[] = {
        0x960, 0x964, 0x968, 0x96C,
 };
 
-static const u16 srstclr_for_v3u[] = {
+static const u16 srstclr_for_gen4[] = {
        0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
-       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
+       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
+       0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
+       0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC,
 };
 
 /**
@@ -158,7 +166,7 @@ struct cpg_mssr_priv {
        struct {
                u32 mask;
                u32 val;
-       } smstpcr_saved[ARRAY_SIZE(mstpsr_for_v3u)];
+       } smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
 
        struct clk *clks[];
 };
@@ -552,6 +560,11 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
                pm_clk_destroy(dev);
 }
 
+static void cpg_mssr_genpd_remove(void *data)
+{
+       pm_genpd_remove(data);
+}
+
 static int __init cpg_mssr_add_clk_domain(struct device *dev,
                                          const unsigned int *core_pm_clks,
                                          unsigned int num_core_pm_clks)
@@ -560,6 +573,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
        struct generic_pm_domain *genpd;
        struct cpg_mssr_clk_domain *pd;
        size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
+       int ret;
 
        pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
        if (!pd)
@@ -574,11 +588,17 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
                       GENPD_FLAG_ACTIVE_WAKEUP;
        genpd->attach_dev = cpg_mssr_attach_dev;
        genpd->detach_dev = cpg_mssr_detach_dev;
-       pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(dev, cpg_mssr_genpd_remove, genpd);
+       if (ret)
+               return ret;
+
        cpg_mssr_clk_domain = pd;
 
-       of_genpd_add_provider_simple(np, genpd);
-       return 0;
+       return of_genpd_add_provider_simple(np, genpd);
 }
 
 #ifdef CONFIG_RESET_CONTROLLER
@@ -827,6 +847,12 @@ static const struct of_device_id cpg_mssr_match[] = {
                .compatible = "renesas,r8a779a0-cpg-mssr",
                .data = &r8a779a0_cpg_mssr_info,
        },
+#endif
+#ifdef CONFIG_CLK_R8A779F0
+       {
+               .compatible = "renesas,r8a779f0-cpg-mssr",
+               .data = &r8a779f0_cpg_mssr_info,
+       },
 #endif
        { /* sentinel */ }
 };
@@ -970,11 +996,11 @@ static int __init cpg_mssr_common_init(struct device *dev,
                priv->reset_clear_regs = srstclr;
        } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
                priv->control_regs = stbcr;
-       } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
-               priv->status_regs = mstpsr_for_v3u;
-               priv->control_regs = mstpcr_for_v3u;
-               priv->reset_regs = srcr_for_v3u;
-               priv->reset_clear_regs = srstclr_for_v3u;
+       } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
+               priv->status_regs = mstpsr_for_gen4;
+               priv->control_regs = mstpcr_for_gen4;
+               priv->reset_regs = srcr_for_gen4;
+               priv->reset_clear_regs = srstclr_for_gen4;
        } else {
                error = -EINVAL;
                goto out_err;
index 6b2a0ad..16810dd 100644 (file)
@@ -88,7 +88,7 @@ struct device_node;
 enum clk_reg_layout {
        CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
        CLK_REG_LAYOUT_RZ_A,
-       CLK_REG_LAYOUT_RCAR_V3U,
+       CLK_REG_LAYOUT_RCAR_GEN4,
 };
 
     /**
@@ -178,6 +178,7 @@ extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77990_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779f0_cpg_mssr_info;
 
 void __init cpg_mssr_early_init(struct device_node *np,
                                const struct cpg_mssr_info *info);
index 4021f6c..edd0abe 100644 (file)
@@ -74,6 +74,7 @@ struct sd_hw_data {
  * @clks: Array containing all Core and Module Clocks
  * @num_core_clks: Number of Core Clocks in clks[]
  * @num_mod_clks: Number of Module Clocks in clks[]
+ * @num_resets: Number of Module Resets in info->resets[]
  * @last_dt_core_clk: ID of the last Core Clock exported to DT
  * @notifiers: Notifier chain to save/restore clock state for system resume
  * @info: Pointer to platform data
@@ -850,10 +851,16 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device
                pm_clk_destroy(dev);
 }
 
+static void rzg2l_cpg_genpd_remove(void *data)
+{
+       pm_genpd_remove(data);
+}
+
 static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
 {
        struct device_node *np = dev->of_node;
        struct generic_pm_domain *genpd;
+       int ret;
 
        genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL);
        if (!genpd)
@@ -864,10 +871,15 @@ static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
                       GENPD_FLAG_ACTIVE_WAKEUP;
        genpd->attach_dev = rzg2l_cpg_attach_dev;
        genpd->detach_dev = rzg2l_cpg_detach_dev;
-       pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       if (ret)
+               return ret;
 
-       of_genpd_add_provider_simple(np, genpd);
-       return 0;
+       ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd);
+       if (ret)
+               return ret;
+
+       return of_genpd_add_provider_simple(np, genpd);
 }
 
 static int __init rzg2l_cpg_probe(struct platform_device *pdev)
index 7fb6b40..5729d10 100644 (file)
@@ -9,11 +9,14 @@
 #ifndef __RENESAS_RZG2L_CPG_H__
 #define __RENESAS_RZG2L_CPG_H__
 
+#define CPG_PL1_DDIV           (0x200)
 #define CPG_PL2_DDIV           (0x204)
 #define CPG_PL3A_DDIV          (0x208)
+#define CPG_PL6_DDIV           (0x210)
 #define CPG_PL2SDHI_DSEL       (0x218)
 #define CPG_CLKSTATUS          (0x280)
 #define CPG_PL3_SSEL           (0x408)
+#define CPG_PL6_SSEL           (0x414)
 #define CPG_PL6_ETH_SSEL       (0x418)
 
 #define CPG_CLKSTATUS_SELSDHI0_STS     BIT(28)
 
 #define DDIV_PACK(offset, bitpos, size) \
                (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+#define DIVPL1A                DDIV_PACK(CPG_PL1_DDIV, 0, 2)
 #define DIVPL2A                DDIV_PACK(CPG_PL2_DDIV, 0, 3)
 #define DIVPL3A                DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
 #define DIVPL3B                DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
 #define DIVPL3C                DDIV_PACK(CPG_PL3A_DDIV, 8, 3)
+#define DIVGPU         DDIV_PACK(CPG_PL6_DDIV, 0, 2)
 
 #define SEL_PLL_PACK(offset, bitpos, size) \
                (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
 
 #define SEL_PLL3_3     SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
 #define SEL_PLL6_2     SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
+#define SEL_GPU2       SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
 
 #define SEL_SDHI0      DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
 #define SEL_SDHI1      DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
@@ -168,6 +174,9 @@ struct rzg2l_reset {
  * @num_mod_clks: Number of entries in mod_clks[]
  * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
  *
+ * @resets: Array of Module Reset definitions
+ * @num_resets: Number of entries in resets[]
+ *
  * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
  *                 should not be disabled without a knowledgeable driver
  * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
index b341cd9..962502c 100644 (file)
@@ -807,7 +807,7 @@ static int ti_adpll_init_registers(struct ti_adpll_data *d)
 
 static int ti_adpll_init_inputs(struct ti_adpll_data *d)
 {
-       const char *error = "need at least %i inputs";
+       static const char error[] = "need at least %i inputs";
        struct clk *clock;
        int nr_inputs;
 
index 54f4184..e5f8fb7 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/io.h>
 
 /**
- * struct zynq_pll
+ * struct zynq_pll - pll clock
  * @hw:                Handle between common and hardware-specific interfaces
  * @pll_ctrl:  PLL control register
  * @pll_status:        PLL status register
@@ -46,7 +46,7 @@ struct zynq_pll {
  * @hw:                Handle between common and hardware-specific interfaces
  * @rate:      Desired clock frequency
  * @prate:     Clock frequency of parent clock
- * Returns frequency closest to @rate the hardware can generate.
+ * Return:     frequency closest to @rate the hardware can generate.
  */
 static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                unsigned long *prate)
@@ -66,7 +66,7 @@ static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  * zynq_pll_recalc_rate() - Recalculate clock frequency
  * @hw:                        Handle between common and hardware-specific interfaces
  * @parent_rate:       Clock frequency of parent clock
- * Returns current clock frequency.
+ * Return:             current clock frequency.
  */
 static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
@@ -87,7 +87,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
 /**
  * zynq_pll_is_enabled - Check if a clock is enabled
  * @hw:                Handle between common and hardware-specific interfaces
- * Returns 1 if the clock is enabled, 0 otherwise.
+ * Return:     1 if the clock is enabled, 0 otherwise.
  *
  * Not sure this is a good idea, but since disabled means bypassed for
  * this clock implementation we say we are always enabled.
@@ -110,7 +110,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw)
 /**
  * zynq_pll_enable - Enable clock
  * @hw:                Handle between common and hardware-specific interfaces
- * Returns 0 on success
+ * Return: 0 on success
  */
 static int zynq_pll_enable(struct clk_hw *hw)
 {
@@ -179,7 +179,7 @@ static const struct clk_ops zynq_pll_ops = {
  * @pll_status:        Pointer to PLL status register
  * @lock_index:        Bit index to this PLL's lock status bit in @pll_status
  * @lock:      Register lock
- * Returns handle to the registered clock.
+ * Return:     handle to the registered clock.
  */
 struct clk *clk_register_zynq_pll(const char *name, const char *parent,
                void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
index 0c45e82..66d308e 100644 (file)
@@ -18,6 +18,8 @@ struct renesas_sdhi_scc {
        u32 tap_hs400_4tap;     /* sampling clock position for HS400 (4 TAP) */
 };
 
+#define SDHI_FLAG_NEED_CLKH_FALLBACK   BIT(0)
+
 struct renesas_sdhi_of_data {
        unsigned long tmio_flags;
        u32           tmio_ocr_mask;
@@ -31,6 +33,7 @@ struct renesas_sdhi_of_data {
        int taps_num;
        unsigned int max_blk_count;
        unsigned short max_segs;
+       unsigned long sdhi_flags;
 };
 
 #define SDHI_CALIB_TABLE_MAX 32
@@ -57,6 +60,7 @@ struct tmio_mmc_dma {
 
 struct renesas_sdhi {
        struct clk *clk;
+       struct clk *clkh;
        struct clk *clk_cd;
        struct tmio_mmc_data mmc_data;
        struct tmio_mmc_dma dma_priv;
index a4407f3..415911e 100644 (file)
@@ -127,10 +127,12 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
 }
 
 static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
-                                           unsigned int new_clock)
+                                           unsigned int wanted_clock)
 {
        struct renesas_sdhi *priv = host_to_priv(host);
+       struct clk *ref_clk = priv->clk;
        unsigned int freq, diff, best_freq = 0, diff_min = ~0;
+       unsigned int new_clock, clkh_shift = 0;
        int i;
 
        /*
@@ -141,6 +143,16 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
        if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2) || mmc_doing_tune(host->mmc))
                return clk_get_rate(priv->clk);
 
+       if (priv->clkh) {
+               bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
+               bool need_slow_clkh = (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
+                                     (host->mmc->ios.timing == MMC_TIMING_MMC_HS400);
+               clkh_shift = use_4tap && need_slow_clkh ? 1 : 2;
+               ref_clk = priv->clkh;
+       }
+
+       new_clock = wanted_clock << clkh_shift;
+
        /*
         * We want the bus clock to be as close as possible to, but no
         * greater than, new_clock.  As we can divide by 1 << i for
@@ -148,11 +160,10 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
         * possible, but no greater than, new_clock << i.
         */
        for (i = min(9, ilog2(UINT_MAX / new_clock)); i >= 0; i--) {
-               freq = clk_round_rate(priv->clk, new_clock << i);
+               freq = clk_round_rate(ref_clk, new_clock << i);
                if (freq > (new_clock << i)) {
                        /* Too fast; look for a slightly slower option */
-                       freq = clk_round_rate(priv->clk,
-                                             (new_clock << i) / 4 * 3);
+                       freq = clk_round_rate(ref_clk, (new_clock << i) / 4 * 3);
                        if (freq > (new_clock << i))
                                continue;
                }
@@ -164,7 +175,10 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
                }
        }
 
-       clk_set_rate(priv->clk, best_freq);
+       clk_set_rate(ref_clk, best_freq);
+
+       if (priv->clkh)
+               clk_set_rate(priv->clk, best_freq >> clkh_shift);
 
        return clk_get_rate(priv->clk);
 }
@@ -904,11 +918,12 @@ int renesas_sdhi_probe(struct platform_device *pdev,
        dma_priv = &priv->dma_priv;
 
        priv->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(priv->clk)) {
-               ret = PTR_ERR(priv->clk);
-               dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(priv->clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "cannot get clock");
+
+       priv->clkh = devm_clk_get_optional(&pdev->dev, "clkh");
+       if (IS_ERR(priv->clkh))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clkh), "cannot get clkh");
 
        /*
         * Some controllers provide a 2nd clock just to run the internal card
@@ -921,9 +936,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
         * to the card detect circuit. That leaves us with if separate clocks
         * are presented, we must treat them both as virtually 1 clock.
         */
-       priv->clk_cd = devm_clk_get(&pdev->dev, "cd");
+       priv->clk_cd = devm_clk_get_optional(&pdev->dev, "cd");
        if (IS_ERR(priv->clk_cd))
-               priv->clk_cd = NULL;
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk_cd), "cannot get cd clock");
 
        priv->pinctrl = devm_pinctrl_get(&pdev->dev);
        if (!IS_ERR(priv->pinctrl)) {
@@ -947,6 +962,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
                mmc_data->max_segs = of_data->max_segs;
                dma_priv->dma_buswidth = of_data->dma_buswidth;
                host->bus_shift = of_data->bus_shift;
+               /* Fallback for old DTs */
+               if (!priv->clkh && of_data->sdhi_flags & SDHI_FLAG_NEED_CLKH_FALLBACK)
+                       priv->clkh = clk_get_parent(clk_get_parent(priv->clk));
+
        }
 
        host->write16_hook      = renesas_sdhi_write16_hook;
@@ -1044,7 +1063,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
             host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR |
                                 MMC_CAP2_HS400_1_8V))) {
                const struct renesas_sdhi_scc *taps = of_data->taps;
-               bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
+               bool use_4tap = quirks && quirks->hs400_4taps;
                bool hit = false;
 
                for (i = 0; i < of_data->taps_num; i++) {
index 7660f7e..9d2c600 100644 (file)
@@ -125,6 +125,22 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
        /* DMAC can handle 32bit blk count but only 1 segment */
        .max_blk_count  = UINT_MAX / TMIO_MAX_BLK_SIZE,
        .max_segs       = 1,
+       .sdhi_flags     = SDHI_FLAG_NEED_CLKH_FALLBACK,
+};
+
+static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_fallback = {
+       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
+                         TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+                         MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY,
+       .capabilities2  = MMC_CAP2_NO_WRITE_PROTECT | MMC_CAP2_MERGE_CAPABLE,
+       .bus_shift      = 2,
+       .scc_offset     = 0x1000,
+       .taps           = rcar_gen3_scc_taps,
+       .taps_num       = ARRAY_SIZE(rcar_gen3_scc_taps),
+       /* DMAC can handle 32bit blk count but only 1 segment */
+       .max_blk_count  = UINT_MAX / TMIO_MAX_BLK_SIZE,
+       .max_segs       = 1,
 };
 
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
@@ -214,6 +230,10 @@ static const struct renesas_sdhi_of_data_with_quirks of_r8a77965_compatible = {
        .quirks = &sdhi_quirks_r8a77965,
 };
 
+static const struct renesas_sdhi_of_data_with_quirks of_r8a77970_compatible = {
+       .of_data = &of_data_rcar_gen3_no_fallback,
+};
+
 static const struct renesas_sdhi_of_data_with_quirks of_r8a77980_compatible = {
        .of_data = &of_data_rcar_gen3,
        .quirks = &sdhi_quirks_nohs400,
@@ -235,6 +255,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
        { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },
        { .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
        { .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
+       { .compatible = "renesas,sdhi-r8a77970", .data = &of_r8a77970_compatible, },
        { .compatible = "renesas,sdhi-r8a77980", .data = &of_r8a77980_compatible, },
        { .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, },
        { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, },
diff --git a/include/dt-bindings/clock/r8a779f0-cpg-mssr.h b/include/dt-bindings/clock/r8a779f0-cpg-mssr.h
new file mode 100644 (file)
index 0000000..f2ae1c6
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: (GPL-2.0 or MIT) */
+/*
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a779f0 CPG Core Clocks */
+
+#define R8A779F0_CLK_ZX                        0
+#define R8A779F0_CLK_ZS                        1
+#define R8A779F0_CLK_ZT                        2
+#define R8A779F0_CLK_ZTR               3
+#define R8A779F0_CLK_S0D2              4
+#define R8A779F0_CLK_S0D3              5
+#define R8A779F0_CLK_S0D4              6
+#define R8A779F0_CLK_S0D2_MM           7
+#define R8A779F0_CLK_S0D3_MM           8
+#define R8A779F0_CLK_S0D4_MM           9
+#define R8A779F0_CLK_S0D2_RT           10
+#define R8A779F0_CLK_S0D3_RT           11
+#define R8A779F0_CLK_S0D4_RT           12
+#define R8A779F0_CLK_S0D6_RT           13
+#define R8A779F0_CLK_S0D3_PER          14
+#define R8A779F0_CLK_S0D6_PER          15
+#define R8A779F0_CLK_S0D12_PER         16
+#define R8A779F0_CLK_S0D24_PER         17
+#define R8A779F0_CLK_S0D2_HSC          18
+#define R8A779F0_CLK_S0D3_HSC          19
+#define R8A779F0_CLK_S0D4_HSC          20
+#define R8A779F0_CLK_S0D6_HSC          21
+#define R8A779F0_CLK_S0D12_HSC         22
+#define R8A779F0_CLK_S0D2_CC           23
+#define R8A779F0_CLK_CL                        24
+#define R8A779F0_CLK_CL16M             25
+#define R8A779F0_CLK_CL16M_MM          26
+#define R8A779F0_CLK_CL16M_RT          27
+#define R8A779F0_CLK_CL16M_PER         28
+#define R8A779F0_CLK_CL16M_HSC         29
+#define R8A779F0_CLK_Z0                        30
+#define R8A779F0_CLK_Z1                        31
+#define R8A779F0_CLK_ZB3               32
+#define R8A779F0_CLK_ZB3D2             33
+#define R8A779F0_CLK_ZB3D4             34
+#define R8A779F0_CLK_SD0H              35
+#define R8A779F0_CLK_SD0               36
+#define R8A779F0_CLK_RPC               37
+#define R8A779F0_CLK_RPCD2             38
+#define R8A779F0_CLK_MSO               39
+#define R8A779F0_CLK_SASYNCRT          40
+#define R8A779F0_CLK_SASYNCPERD1       41
+#define R8A779F0_CLK_SASYNCPERD2       42
+#define R8A779F0_CLK_SASYNCPERD4       43
+#define R8A779F0_CLK_DBGSOC_HSC                44
+#define R8A779F0_CLK_RSW2              45
+#define R8A779F0_CLK_OSC               46
+#define R8A779F0_CLK_ZR                        47
+#define R8A779F0_CLK_CPEX              48
+#define R8A779F0_CLK_CBFUSA            49
+#define R8A779F0_CLK_R                 50
+
+#endif /* __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/power/r8a779f0-sysc.h b/include/dt-bindings/power/r8a779f0-sysc.h
new file mode 100644 (file)
index 0000000..0ec8ad7
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: (GPL-2.0 or MIT) */
+/*
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A779F0_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A779F0_SYSC_H__
+
+/*
+ * These power domain indices match the Power Domain Register Numbers (PDR)
+ */
+
+#define R8A779F0_PD_A1E0D0C0           0
+#define R8A779F0_PD_A1E0D0C1           1
+#define R8A779F0_PD_A1E0D1C0           2
+#define R8A779F0_PD_A1E0D1C1           3
+#define R8A779F0_PD_A1E1D0C0           4
+#define R8A779F0_PD_A1E1D0C1           5
+#define R8A779F0_PD_A1E1D1C0           6
+#define R8A779F0_PD_A1E1D1C1           7
+#define R8A779F0_PD_A2E0D0             16
+#define R8A779F0_PD_A2E0D1             17
+#define R8A779F0_PD_A2E1D0             18
+#define R8A779F0_PD_A2E1D1             19
+#define R8A779F0_PD_A3E0               20
+#define R8A779F0_PD_A3E1               21
+
+/* Always-on power area */
+#define R8A779F0_PD_ALWAYS_ON          64
+
+#endif /* __DT_BINDINGS_POWER_R8A779A0_SYSC_H__*/