]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge branches 'clk-debugfs-danger', 'clk-basic-hw', 'clk-renesas', 'clk-amlogic...
authorStephen Boyd <sboyd@kernel.org>
Fri, 31 Jan 2020 21:12:14 +0000 (13:12 -0800)
committerStephen Boyd <sboyd@kernel.org>
Fri, 31 Jan 2020 21:12:14 +0000 (13:12 -0800)
 - Support dangerous debugfs actions on clks with dead code
 - Convert gpio, fixed-factor, mux, gate, divider basic clks to hw based APIs

* clk-debugfs-danger:
  clk: Add support for setting clk_rate via debugfs

* clk-basic-hw:
  clk: divider: Add support for specifying parents via DT/pointers
  clk: gate: Add support for specifying parents via DT/pointers
  clk: mux: Add support for specifying parents via DT/pointers
  clk: asm9260: Use parent accuracy in fixed rate clk
  clk: fixed-rate: Document that accuracy isn't a rate
  clk: fixed-rate: Add clk flags for parent accuracy
  clk: fixed-rate: Add support for specifying parents via DT/pointers
  clk: fixed-rate: Document accuracy member
  clk: fixed-rate: Move to_clk_fixed_rate() to C file
  clk: fixed-rate: Remove clk_register_fixed_rate_with_accuracy()
  clk: fixed-rate: Convert to clk_hw based APIs
  clk: gpio: Use DT way of specifying parents

* clk-renesas:
  clk: renesas: Prepare for split of R-Car H3 config symbol
  dt-bindings: clock: renesas: cpg-mssr: Fix r8a774b1 typo
  clk: renesas: r7s9210: Add SPIBSC clock
  clk: renesas: rcar-gen3: Allow changing the RPC[D2] clocks
  clk: renesas: Remove use of ARCH_R8A7796
  clk: renesas: rcar-gen2: Change multipliers and dividers to u8

* clk-amlogic:
  clk: clarify that clk_set_rate() does updates from top to bottom
  clk: meson: meson8b: make the CCF use the glitch-free mali mux
  clk: meson: pll: Fix by 0 division in __pll_params_to_rate()
  clk: meson: g12a: fix missing uart2 in regmap table
  clk: meson: meson8b: use of_clk_hw_register to register the clocks
  clk: meson: meson8b: don't register the XTAL clock when provided via OF
  clk: meson: meson8b: change references to the XTAL clock to use [fw_]name
  clk: meson: meson8b: use clk_hw_set_parent in the CPU clock notifier
  clk: meson: add a driver for the Meson8/8b/8m2 DDR clock controller
  dt-bindings: clock: meson8b: add the clock inputs
  dt-bindings: clock: add the Amlogic Meson8 DDR clock controller binding

* clk-allwinner:
  clk: sunxi: a23/a33: Export the MIPI PLL
  clk: sunxi: a31: Export the MIPI PLL
  clk: sunxi-ng: a64: export CLK_CPUX clock for DVFS
  clk: sunxi-ng: add mux and pll notifiers for A64 CPU clock
  clk: sunxi-ng: r40: Export MBUS clock
  clk: sunxi: use of_device_get_match_data

34 files changed:
Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
drivers/clk/clk-asm9260.c
drivers/clk/clk-divider.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-gate.c
drivers/clk/clk-gpio.c
drivers/clk/clk-mux.c
drivers/clk/clk.c
drivers/clk/meson/Makefile
drivers/clk/meson/clk-pll.c
drivers/clk/meson/g12a.c
drivers/clk/meson/meson8-ddr.c [new file with mode: 0644]
drivers/clk/meson/meson8b.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/r7s9210-cpg-mssr.c
drivers/clk/renesas/rcar-gen2-cpg.h
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.h
drivers/clk/sunxi-ng/ccu-sun6i-a31.h
drivers/clk/sunxi-ng/ccu-sun8i-a23-a33.h
drivers/clk/sunxi-ng/ccu-sun8i-r40.h
drivers/clk/sunxi/clk-sun6i-apb0-gates.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
include/dt-bindings/clock/meson8-ddr-clkc.h [new file with mode: 0644]
include/dt-bindings/clock/sun50i-a64-ccu.h
include/dt-bindings/clock/sun6i-a31-ccu.h
include/dt-bindings/clock/sun8i-a23-a33-ccu.h
include/dt-bindings/clock/sun8i-r40-ccu.h
include/linux/clk-provider.h
include/linux/clk.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
new file mode 100644 (file)
index 0000000..4b8669f
--- /dev/null
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,meson8-ddr-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic DDR Clock Controller Device Tree Bindings
+
+maintainers:
+  - Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,meson8-ddr-clkc
+      - amlogic,meson8b-ddr-clkc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: xtal
+
+  "#clock-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    ddr_clkc: clock-controller@400 {
+      compatible = "amlogic,meson8-ddr-clkc";
+      reg = <0x400 0x20>;
+      clocks = <&xtal>;
+      clock-names = "xtal";
+      #clock-cells = <1>;
+    };
+
+...
index 4d94091c1d2d880e0a7dc02fab6195e95437d70f..cc51e4746b3b77226852197cc2de6c9de982240b 100644 (file)
@@ -11,6 +11,11 @@ Required Properties:
        - "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
 - #clock-cells: should be 1.
 - #reset-cells: should be 1.
+- clocks: list of clock phandles, one for each entry in clock-names
+- clock-names: should contain the following:
+  * "xtal": the 24MHz system oscillator
+  * "ddr_pll": the DDR PLL clock
+  * "clk_32k": (if present) the 32kHz clock signal from GPIOAO_6 (CLK_32K_IN)
 
 Parent node should have the following properties :
 - compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
index c7674d0267a36fbd25f356482ea7b74e8f5fa27a..f4d153f24a0ff80369cd6768b22c7b3ea48d5d72 100644 (file)
@@ -19,7 +19,7 @@ Required Properties:
       - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
       - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C)
       - "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M)
-      - "renesas,r8a774b1-cpg-mssr" for the r8a774a1 SoC (RZ/G2N)
+      - "renesas,r8a774b1-cpg-mssr" for the r8a774b1 SoC (RZ/G2N)
       - "renesas,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E)
       - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
       - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
index dd0f90c9dd0e3b35558d1cf10aa0dc7d77a6912f..536b59aabd2cba18dab1656e66590628b08b1f6e 100644 (file)
@@ -260,7 +260,6 @@ static void __init asm9260_acc_init(struct device_node *np)
        const char *ref_clk, *pll_clk = "pll";
        u32 rate;
        int n;
-       u32 accuracy = 0;
 
        clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
        if (!clk_data)
@@ -275,10 +274,11 @@ static void __init asm9260_acc_init(struct device_node *np)
        /* register pll */
        rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
 
+       /* TODO: Convert to DT parent scheme */
        ref_clk = of_clk_get_parent_name(np, 0);
-       accuracy = clk_get_accuracy(__clk_lookup(ref_clk));
-       hw = clk_hw_register_fixed_rate_with_accuracy(NULL, pll_clk,
-                       ref_clk, 0, rate, accuracy);
+       hw = __clk_hw_register_fixed_rate_with_accuracy(NULL, NULL, pll_clk,
+                       ref_clk, NULL, NULL, 0, rate, 0,
+                       CLK_FIXED_RATE_PARENT_ACCURACY);
 
        if (IS_ERR(hw))
                panic("%pOFn: can't register REFCLK. Check DT!", np);
index 098b2b01f0afc623658388c9f8c9c4417b0cb368..8de12cb0c43d895fc51608edb50a05ab52a5d5bf 100644 (file)
@@ -463,11 +463,12 @@ const struct clk_ops clk_divider_ro_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
 
-static struct clk_hw *_register_divider(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, const struct clk_div_table *table,
-               spinlock_t *lock)
+struct clk_hw *__clk_hw_register_divider(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+               const struct clk_div_table *table, spinlock_t *lock)
 {
        struct clk_divider *div;
        struct clk_hw *hw;
@@ -514,55 +515,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name,
 
        return hw;
 }
-
-/**
- * clk_register_divider - register a divider clock with the clock framework
- * @dev: device registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @reg: register address to adjust divider
- * @shift: number of bits to shift the bitfield
- * @width: width of the bitfield
- * @clk_divider_flags: divider-specific flags for this clock
- * @lock: shared register lock for this clock
- */
-struct clk *clk_register_divider(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, spinlock_t *lock)
-{
-       struct clk_hw *hw;
-
-       hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
-                       width, clk_divider_flags, NULL, lock);
-       if (IS_ERR(hw))
-               return ERR_CAST(hw);
-       return hw->clk;
-}
-EXPORT_SYMBOL_GPL(clk_register_divider);
-
-/**
- * clk_hw_register_divider - register a divider clock with the clock framework
- * @dev: device registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @reg: register address to adjust divider
- * @shift: number of bits to shift the bitfield
- * @width: width of the bitfield
- * @clk_divider_flags: divider-specific flags for this clock
- * @lock: shared register lock for this clock
- */
-struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, spinlock_t *lock)
-{
-       return _register_divider(dev, name, parent_name, flags, reg, shift,
-                       width, clk_divider_flags, NULL, lock);
-}
-EXPORT_SYMBOL_GPL(clk_hw_register_divider);
+EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
 
 /**
  * clk_register_divider_table - register a table based divider clock with
@@ -586,39 +539,15 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 {
        struct clk_hw *hw;
 
-       hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
-                       width, clk_divider_flags, table, lock);
+       hw =  __clk_hw_register_divider(dev, NULL, name, parent_name, NULL,
+                       NULL, flags, reg, shift, width, clk_divider_flags,
+                       table, lock);
        if (IS_ERR(hw))
                return ERR_CAST(hw);
        return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
 
-/**
- * clk_hw_register_divider_table - register a table based divider clock with
- * the clock framework
- * @dev: device registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @reg: register address to adjust divider
- * @shift: number of bits to shift the bitfield
- * @width: width of the bitfield
- * @clk_divider_flags: divider-specific flags for this clock
- * @table: array of divider/value pairs ending with a div set to 0
- * @lock: shared register lock for this clock
- */
-struct clk_hw *clk_hw_register_divider_table(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, const struct clk_div_table *table,
-               spinlock_t *lock)
-{
-       return _register_divider(dev, name, parent_name, flags, reg, shift,
-                       width, clk_divider_flags, table, lock);
-}
-EXPORT_SYMBOL_GPL(clk_hw_register_divider_table);
-
 void clk_unregister_divider(struct clk *clk)
 {
        struct clk_divider *div;
index 2c4486c09040e192e35859b20a7c8471983c5bf2..77499a27c8fbfeb87e0393c9a135dca538c401bc 100644 (file)
@@ -24,6 +24,8 @@
  * parent - fixed parent.  No clk_set_parent support
  */
 
+#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
+
 static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
@@ -33,7 +35,12 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
 static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw,
                unsigned long parent_accuracy)
 {
-       return to_clk_fixed_rate(hw)->fixed_accuracy;
+       struct clk_fixed_rate *fixed = to_clk_fixed_rate(hw);
+
+       if (fixed->flags & CLK_FIXED_RATE_PARENT_ACCURACY)
+               return parent_accuracy;
+
+       return fixed->fixed_accuracy;
 }
 
 const struct clk_ops clk_fixed_rate_ops = {
@@ -42,24 +49,17 @@ const struct clk_ops clk_fixed_rate_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
 
-/**
- * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
- * the clock framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @fixed_rate: non-adjustable clock rate
- * @fixed_accuracy: non-adjustable clock rate
- */
-struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate, unsigned long fixed_accuracy)
+struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               unsigned long fixed_rate, unsigned long fixed_accuracy,
+               unsigned long clk_fixed_flags)
 {
        struct clk_fixed_rate *fixed;
        struct clk_hw *hw;
        struct clk_init_data init = {};
-       int ret;
+       int ret = -EINVAL;
 
        /* allocate fixed-rate clock */
        fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
@@ -69,17 +69,26 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
        init.name = name;
        init.ops = &clk_fixed_rate_ops;
        init.flags = flags;
-       init.parent_names = (parent_name ? &parent_name: NULL);
-       init.num_parents = (parent_name ? 1 : 0);
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.parent_hws = parent_hw ? &parent_hw : NULL;
+       init.parent_data = parent_data;
+       if (parent_name || parent_hw || parent_data)
+               init.num_parents = 1;
+       else
+               init.num_parents = 0;
 
        /* struct clk_fixed_rate assignments */
+       fixed->flags = clk_fixed_flags;
        fixed->fixed_rate = fixed_rate;
        fixed->fixed_accuracy = fixed_accuracy;
        fixed->hw.init = &init;
 
        /* register the clock */
        hw = &fixed->hw;
-       ret = clk_hw_register(dev, hw);
+       if (dev || !np)
+               ret = clk_hw_register(dev, hw);
+       else if (np)
+               ret = of_clk_hw_register(np, hw);
        if (ret) {
                kfree(fixed);
                hw = ERR_PTR(ret);
@@ -87,47 +96,20 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
 
        return hw;
 }
-EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy);
+EXPORT_SYMBOL_GPL(__clk_hw_register_fixed_rate);
 
-struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate, unsigned long fixed_accuracy)
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               unsigned long fixed_rate)
 {
        struct clk_hw *hw;
 
        hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
-                       flags, fixed_rate, fixed_accuracy);
+                                                     flags, fixed_rate, 0);
        if (IS_ERR(hw))
                return ERR_CAST(hw);
        return hw->clk;
 }
-EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy);
-
-/**
- * clk_hw_register_fixed_rate - register fixed-rate clock with the clock
- * framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of clock's parent
- * @flags: framework-specific flags
- * @fixed_rate: non-adjustable clock rate
- */
-struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate)
-{
-       return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
-                                                    flags, fixed_rate, 0);
-}
-EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate);
-
-struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate)
-{
-       return clk_register_fixed_rate_with_accuracy(dev, name, parent_name,
-                                                    flags, fixed_rate, 0);
-}
 EXPORT_SYMBOL_GPL(clk_register_fixed_rate);
 
 void clk_unregister_fixed_rate(struct clk *clk)
@@ -155,9 +137,9 @@ void clk_hw_unregister_fixed_rate(struct clk_hw *hw)
 EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate);
 
 #ifdef CONFIG_OF
-static struct clk *_of_fixed_clk_setup(struct device_node *node)
+static struct clk_hw *_of_fixed_clk_setup(struct device_node *node)
 {
-       struct clk *clk;
+       struct clk_hw *hw;
        const char *clk_name = node->name;
        u32 rate;
        u32 accuracy = 0;
@@ -170,18 +152,18 @@ static struct clk *_of_fixed_clk_setup(struct device_node *node)
 
        of_property_read_string(node, "clock-output-names", &clk_name);
 
-       clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL,
+       hw = clk_hw_register_fixed_rate_with_accuracy(NULL, clk_name, NULL,
                                                    0, rate, accuracy);
-       if (IS_ERR(clk))
-               return clk;
+       if (IS_ERR(hw))
+               return hw;
 
-       ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
        if (ret) {
-               clk_unregister(clk);
+               clk_hw_unregister_fixed_rate(hw);
                return ERR_PTR(ret);
        }
 
-       return clk;
+       return hw;
 }
 
 /**
@@ -195,27 +177,27 @@ CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);
 
 static int of_fixed_clk_remove(struct platform_device *pdev)
 {
-       struct clk *clk = platform_get_drvdata(pdev);
+       struct clk_hw *hw = platform_get_drvdata(pdev);
 
        of_clk_del_provider(pdev->dev.of_node);
-       clk_unregister_fixed_rate(clk);
+       clk_hw_unregister_fixed_rate(hw);
 
        return 0;
 }
 
 static int of_fixed_clk_probe(struct platform_device *pdev)
 {
-       struct clk *clk;
+       struct clk_hw *hw;
 
        /*
         * This function is not executed when of_fixed_clk_setup
         * succeeded.
         */
-       clk = _of_fixed_clk_setup(pdev->dev.of_node);
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
+       hw = _of_fixed_clk_setup(pdev->dev.of_node);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
 
-       platform_set_drvdata(pdev, clk);
+       platform_set_drvdata(pdev, hw);
 
        return 0;
 }
@@ -224,7 +206,6 @@ static const struct of_device_id of_fixed_clk_ids[] = {
        { .compatible = "fixed-clock" },
        { }
 };
-MODULE_DEVICE_TABLE(of, of_fixed_clk_ids);
 
 static struct platform_driver of_fixed_clk_driver = {
        .driver = {
index 670053c58c1a16dfb065341c30e7ac3e71f5a3a3..2ca1f2ac38a6d66c7f950eaaad6d2c8786c1966e 100644 (file)
@@ -123,26 +123,18 @@ const struct clk_ops clk_gate_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_gate_ops);
 
-/**
- * clk_hw_register_gate - register a gate clock with the clock framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of this clock's parent
- * @flags: framework-specific flags for this clock
- * @reg: register address to control gating of this clock
- * @bit_idx: which bit in the register controls gating of this clock
- * @clk_gate_flags: gate-specific flags for this clock
- * @lock: shared register lock for this clock
- */
-struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
+struct clk_hw *__clk_hw_register_gate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags,
                void __iomem *reg, u8 bit_idx,
                u8 clk_gate_flags, spinlock_t *lock)
 {
        struct clk_gate *gate;
        struct clk_hw *hw;
        struct clk_init_data init = {};
-       int ret;
+       int ret = -EINVAL;
 
        if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
                if (bit_idx > 15) {
@@ -160,7 +152,12 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
        init.ops = &clk_gate_ops;
        init.flags = flags;
        init.parent_names = parent_name ? &parent_name : NULL;
-       init.num_parents = parent_name ? 1 : 0;
+       init.parent_hws = parent_hw ? &parent_hw : NULL;
+       init.parent_data = parent_data;
+       if (parent_name || parent_hw || parent_data)
+               init.num_parents = 1;
+       else
+               init.num_parents = 0;
 
        /* struct clk_gate assignments */
        gate->reg = reg;
@@ -170,15 +167,19 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
        gate->hw.init = &init;
 
        hw = &gate->hw;
-       ret = clk_hw_register(dev, hw);
+       if (dev || !np)
+               ret = clk_hw_register(dev, hw);
+       else if (np)
+               ret = of_clk_hw_register(np, hw);
        if (ret) {
                kfree(gate);
                hw = ERR_PTR(ret);
        }
 
        return hw;
+
 }
-EXPORT_SYMBOL_GPL(clk_hw_register_gate);
+EXPORT_SYMBOL_GPL(__clk_hw_register_gate);
 
 struct clk *clk_register_gate(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
index 13304cf5f2a8faf0320d7343448d33f13baf25ea..70397b4b5ffea84b945b197a69d5a328590560b3 100644 (file)
  * parent - fixed parent.  No clk_set_parent support
  */
 
+/**
+ * struct clk_gpio - gpio gated clock
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @gpiod:     gpio descriptor
+ *
+ * Clock with a gpio control for enabling and disabling the parent clock
+ * or switching between two parents by asserting or deasserting the gpio.
+ *
+ * Implements .enable, .disable and .is_enabled or
+ * .get_parent, .set_parent and .determine_rate depending on which clk_ops
+ * is used.
+ */
+struct clk_gpio {
+       struct clk_hw   hw;
+       struct gpio_desc *gpiod;
+};
+
+#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
+
 static int clk_gpio_gate_enable(struct clk_hw *hw)
 {
        struct clk_gpio *clk = to_clk_gpio(hw);
@@ -51,12 +71,11 @@ static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
        return gpiod_get_value(clk->gpiod);
 }
 
-const struct clk_ops clk_gpio_gate_ops = {
+static const struct clk_ops clk_gpio_gate_ops = {
        .enable = clk_gpio_gate_enable,
        .disable = clk_gpio_gate_disable,
        .is_enabled = clk_gpio_gate_is_enabled,
 };
-EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
 
 static int clk_sleeping_gpio_gate_prepare(struct clk_hw *hw)
 {
@@ -111,67 +130,49 @@ static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
        return 0;
 }
 
-const struct clk_ops clk_gpio_mux_ops = {
+static const struct clk_ops clk_gpio_mux_ops = {
        .get_parent = clk_gpio_mux_get_parent,
        .set_parent = clk_gpio_mux_set_parent,
        .determine_rate = __clk_mux_determine_rate,
 };
-EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
 
-static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
-               unsigned long flags, const struct clk_ops *clk_gpio_ops)
+static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
+                                       struct gpio_desc *gpiod,
+                                       const struct clk_ops *clk_gpio_ops)
 {
        struct clk_gpio *clk_gpio;
        struct clk_hw *hw;
        struct clk_init_data init = {};
        int err;
+       const struct clk_parent_data gpio_parent_data[] = {
+               { .index = 0 },
+               { .index = 1 },
+       };
 
-       if (dev)
-               clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
-       else
-               clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);
-
+       clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
        if (!clk_gpio)
                return ERR_PTR(-ENOMEM);
 
-       init.name = name;
+       init.name = dev->of_node->name;
        init.ops = clk_gpio_ops;
-       init.flags = flags;
-       init.parent_names = parent_names;
+       init.parent_data = gpio_parent_data;
        init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_PARENT;
 
        clk_gpio->gpiod = gpiod;
        clk_gpio->hw.init = &init;
 
        hw = &clk_gpio->hw;
-       if (dev)
-               err = devm_clk_hw_register(dev, hw);
-       else
-               err = clk_hw_register(NULL, hw);
-
-       if (!err)
-               return hw;
-
-       if (!dev) {
-               kfree(clk_gpio);
-       }
+       err = devm_clk_hw_register(dev, hw);
+       if (err)
+               return ERR_PTR(err);
 
-       return ERR_PTR(err);
+       return hw;
 }
 
-/**
- * clk_hw_register_gpio_gate - register a gpio clock gate with the clock
- * framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of this clock's parent
- * @gpiod: gpio descriptor to gate this clock
- * @flags: clock flags
- */
-struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpiod,
-               unsigned long flags)
+static struct clk_hw *clk_hw_register_gpio_gate(struct device *dev,
+                                               int num_parents,
+                                               struct gpio_desc *gpiod)
 {
        const struct clk_ops *ops;
 
@@ -180,88 +181,36 @@ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
        else
                ops = &clk_gpio_gate_ops;
 
-       return clk_register_gpio(dev, name,
-                       (parent_name ? &parent_name : NULL),
-                       (parent_name ? 1 : 0), gpiod, flags, ops);
+       return clk_register_gpio(dev, num_parents, gpiod, ops);
 }
-EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
 
-struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpiod,
-               unsigned long flags)
+static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
+                                              struct gpio_desc *gpiod)
 {
-       struct clk_hw *hw;
-
-       hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags);
-       if (IS_ERR(hw))
-               return ERR_CAST(hw);
-       return hw->clk;
+       return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
 }
-EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
-
-/**
- * clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_names: names of this clock's parents
- * @num_parents: number of parents listed in @parent_names
- * @gpiod: gpio descriptor to gate this clock
- * @flags: clock flags
- */
-struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
-               unsigned long flags)
-{
-       if (num_parents != 2) {
-               pr_err("mux-clock %s must have 2 parents\n", name);
-               return ERR_PTR(-EINVAL);
-       }
-
-       return clk_register_gpio(dev, name, parent_names, num_parents,
-                       gpiod, flags, &clk_gpio_mux_ops);
-}
-EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux);
-
-struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
-               unsigned long flags)
-{
-       struct clk_hw *hw;
-
-       hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents,
-                       gpiod, flags);
-       if (IS_ERR(hw))
-               return ERR_CAST(hw);
-       return hw->clk;
-}
-EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
 
 static int gpio_clk_driver_probe(struct platform_device *pdev)
 {
-       struct device_node *node = pdev->dev.of_node;
-       const char **parent_names, *gpio_name;
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       const char *gpio_name;
        unsigned int num_parents;
        struct gpio_desc *gpiod;
-       struct clk *clk;
+       struct clk_hw *hw;
        bool is_mux;
        int ret;
 
+       is_mux = of_device_is_compatible(node, "gpio-mux-clock");
+
        num_parents = of_clk_get_parent_count(node);
-       if (num_parents) {
-               parent_names = devm_kcalloc(&pdev->dev, num_parents,
-                                           sizeof(char *), GFP_KERNEL);
-               if (!parent_names)
-                       return -ENOMEM;
-
-               of_clk_parent_fill(node, parent_names, num_parents);
-       } else {
-               parent_names = NULL;
+       if (is_mux && num_parents != 2) {
+               dev_err(dev, "mux-clock must have 2 parents\n");
+               return -EINVAL;
        }
 
-       is_mux = of_device_is_compatible(node, "gpio-mux-clock");
-
        gpio_name = is_mux ? "select" : "enable";
-       gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW);
+       gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
        if (IS_ERR(gpiod)) {
                ret = PTR_ERR(gpiod);
                if (ret == -EPROBE_DEFER)
@@ -275,16 +224,13 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
        }
 
        if (is_mux)
-               clk = clk_register_gpio_mux(&pdev->dev, node->name,
-                               parent_names, num_parents, gpiod, 0);
+               hw = clk_hw_register_gpio_mux(dev, gpiod);
        else
-               clk = clk_register_gpio_gate(&pdev->dev, node->name,
-                               parent_names ?  parent_names[0] : NULL, gpiod,
-                               CLK_SET_RATE_PARENT);
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
+               hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
 
-       return of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
 }
 
 static const struct of_device_id gpio_clk_match_table[] = {
index 570b6e5b603bcadc7b5b52e2f5fce2f3a80ac578..e54e79714818f931b8b6a4456b57d4154f114530 100644 (file)
@@ -145,17 +145,19 @@ const struct clk_ops clk_mux_ro_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
-struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u32 mask,
+struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
+               const char *name, u8 num_parents,
+               const char * const *parent_names,
+               const struct clk_hw **parent_hws,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
        struct clk_mux *mux;
        struct clk_hw *hw;
        struct clk_init_data init = {};
        u8 width = 0;
-       int ret;
+       int ret = -EINVAL;
 
        if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
                width = fls(mask) - ffs(mask) + 1;
@@ -177,6 +179,8 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
                init.ops = &clk_mux_ops;
        init.flags = flags;
        init.parent_names = parent_names;
+       init.parent_data = parent_data;
+       init.parent_hws = parent_hws;
        init.num_parents = num_parents;
 
        /* struct clk_mux assignments */
@@ -189,7 +193,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
        mux->hw.init = &init;
 
        hw = &mux->hw;
-       ret = clk_hw_register(dev, hw);
+       if (dev || !np)
+               ret = clk_hw_register(dev, hw);
+       else if (np)
+               ret = of_clk_hw_register(np, hw);
        if (ret) {
                kfree(mux);
                hw = ERR_PTR(ret);
@@ -197,53 +204,24 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
 
        return hw;
 }
-EXPORT_SYMBOL_GPL(clk_hw_register_mux_table);
+EXPORT_SYMBOL_GPL(__clk_hw_register_mux);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
                const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u32 mask,
+               unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
        struct clk_hw *hw;
 
-       hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents,
-                                      flags, reg, shift, mask, clk_mux_flags,
-                                      table, lock);
+       hw = clk_hw_register_mux_table(dev, name, parent_names,
+                                      num_parents, flags, reg, shift, mask,
+                                      clk_mux_flags, table, lock);
        if (IS_ERR(hw))
                return ERR_CAST(hw);
        return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
-struct clk *clk_register_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_mux_flags, spinlock_t *lock)
-{
-       u32 mask = BIT(width) - 1;
-
-       return clk_register_mux_table(dev, name, parent_names, num_parents,
-                                     flags, reg, shift, mask, clk_mux_flags,
-                                     NULL, lock);
-}
-EXPORT_SYMBOL_GPL(clk_register_mux);
-
-struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_mux_flags, spinlock_t *lock)
-{
-       u32 mask = BIT(width) - 1;
-
-       return clk_hw_register_mux_table(dev, name, parent_names, num_parents,
-                                     flags, reg, shift, mask, clk_mux_flags,
-                                     NULL, lock);
-}
-EXPORT_SYMBOL_GPL(clk_hw_register_mux);
-
 void clk_unregister_mux(struct clk *clk)
 {
        struct clk_mux *mux;
index fa99d0b42ccbbc006c215203f041cd3ae5b4b2e0..d529ad67805c38c5a8184e99690111bb8a6a5ed1 100644 (file)
@@ -2996,6 +2996,41 @@ static int clk_dump_show(struct seq_file *s, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(clk_dump);
 
+#undef CLOCK_ALLOW_WRITE_DEBUGFS
+#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
+/*
+ * This can be dangerous, therefore don't provide any real compile time
+ * configuration option for this feature.
+ * People who want to use this will need to modify the source code directly.
+ */
+static int clk_rate_set(void *data, u64 val)
+{
+       struct clk_core *core = data;
+       int ret;
+
+       clk_prepare_lock();
+       ret = clk_core_set_rate_nolock(core, val);
+       clk_prepare_unlock();
+
+       return ret;
+}
+
+#define clk_rate_mode  0644
+#else
+#define clk_rate_set   NULL
+#define clk_rate_mode  0444
+#endif
+
+static int clk_rate_get(void *data, u64 *val)
+{
+       struct clk_core *core = data;
+
+       *val = core->rate;
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, clk_rate_get, clk_rate_set, "%llu\n");
+
 static const struct {
        unsigned long flag;
        const char *name;
@@ -3145,7 +3180,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
        root = debugfs_create_dir(core->name, pdentry);
        core->dentry = root;
 
-       debugfs_create_ulong("clk_rate", 0444, root, &core->rate);
+       debugfs_create_file("clk_rate", clk_rate_mode, root, core,
+                           &clk_rate_fops);
        debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
        debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
        debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
index 3939f218587abfb324d32a81768eddabfca2d3c9..6eca2a406ee378f0e842a8db6eecdd4f1b05878e 100644 (file)
@@ -18,4 +18,4 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
 obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
 obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
-obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
+obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
index 489092dde3a6bcad91b3c797ebd67a7689622e2b..b17a13e9337c40eb0fe677d6b283f91178ce01f9 100644 (file)
@@ -77,6 +77,15 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
        unsigned int m, n, frac;
 
        n = meson_parm_read(clk->map, &pll->n);
+
+       /*
+        * On some HW, N is set to zero on init. This value is invalid as
+        * it would result in a division by zero. The rate can't be
+        * calculated in this case
+        */
+       if (n == 0)
+               return 0;
+
        m = meson_parm_read(clk->map, &pll->m);
 
        frac = MESON_PARM_APPLICABLE(&pll->frac) ?
index b3af61cc6fb9497059aefa08e015e95c470ea294..d2760a021301d2442d57eb98f16c2f87ecb1afe7 100644 (file)
@@ -4692,6 +4692,7 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
        &g12a_bt656,
        &g12a_usb1_to_ddr,
        &g12a_mmc_pclk,
+       &g12a_uart2,
        &g12a_vpu_intr,
        &g12a_gic,
        &g12a_sd_emmc_a_clk0,
diff --git a/drivers/clk/meson/meson8-ddr.c b/drivers/clk/meson/meson8-ddr.c
new file mode 100644 (file)
index 0000000..4b73ea2
--- /dev/null
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic Meson8 DDR clock controller
+ *
+ * Copyright (C) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <dt-bindings/clock/meson8-ddr-clkc.h>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-regmap.h"
+#include "clk-pll.h"
+
+#define AM_DDR_PLL_CNTL                        0x00
+#define AM_DDR_PLL_CNTL1               0x04
+#define AM_DDR_PLL_CNTL2               0x08
+#define AM_DDR_PLL_CNTL3               0x0c
+#define AM_DDR_PLL_CNTL4               0x10
+#define AM_DDR_PLL_STS                 0x14
+#define DDR_CLK_CNTL                   0x18
+#define DDR_CLK_STS                    0x1c
+
+static struct clk_regmap meson8_ddr_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = AM_DDR_PLL_CNTL,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = AM_DDR_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = AM_DDR_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .l = {
+                       .reg_off = AM_DDR_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = AM_DDR_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ddr_pll_dco",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap meson8_ddr_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = AM_DDR_PLL_CNTL,
+               .shift = 16,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ddr_pll",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &meson8_ddr_pll_dco.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_hw_onecell_data meson8_ddr_clk_hw_onecell_data = {
+       .hws = {
+               [DDR_CLKID_DDR_PLL_DCO]         = &meson8_ddr_pll_dco.hw,
+               [DDR_CLKID_DDR_PLL]             = &meson8_ddr_pll.hw,
+       },
+       .num = 2,
+};
+
+static struct clk_regmap *const meson8_ddr_clk_regmaps[] = {
+       &meson8_ddr_pll_dco,
+       &meson8_ddr_pll,
+};
+
+static const struct regmap_config meson8_ddr_clkc_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = DDR_CLK_STS,
+};
+
+static int meson8_ddr_clkc_probe(struct platform_device *pdev)
+{
+       struct regmap *regmap;
+       void __iomem *base;
+       struct clk_hw *hw;
+       int ret, i;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                      &meson8_ddr_clkc_regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       /* Populate regmap */
+       for (i = 0; i < ARRAY_SIZE(meson8_ddr_clk_regmaps); i++)
+               meson8_ddr_clk_regmaps[i]->map = regmap;
+
+       /* Register all clks */
+       for (i = 0; i < meson8_ddr_clk_hw_onecell_data.num; i++) {
+               hw = meson8_ddr_clk_hw_onecell_data.hws[i];
+
+               ret = devm_clk_hw_register(&pdev->dev, hw);
+               if (ret) {
+                       dev_err(&pdev->dev, "Clock registration failed\n");
+                       return ret;
+               }
+       }
+
+       return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
+                                          &meson8_ddr_clk_hw_onecell_data);
+}
+
+static const struct of_device_id meson8_ddr_clkc_match_table[] = {
+       { .compatible = "amlogic,meson8-ddr-clkc" },
+       { .compatible = "amlogic,meson8b-ddr-clkc" },
+       { /* sentinel */ }
+};
+
+static struct platform_driver meson8_ddr_clkc_driver = {
+       .probe          = meson8_ddr_clkc_probe,
+       .driver         = {
+               .name   = "meson8-ddr-clkc",
+               .of_match_table = meson8_ddr_clkc_match_table,
+       },
+};
+
+builtin_platform_driver(meson8_ddr_clkc_driver);
index 67e6691e080c111ce8784818aa1aac9a4284ea2b..9fd31f23b2a9381ea26f796bdb2db7e2d90aa638 100644 (file)
@@ -97,8 +97,10 @@ static struct clk_regmap meson8b_fixed_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+                       .name = "xtal",
+                       .index = -1,
                },
                .num_parents = 1,
        },
@@ -162,8 +164,10 @@ static struct clk_regmap meson8b_hdmi_pll_dco = {
                /* sometimes also called "HPLL" or "HPLL PLL" */
                .name = "hdmi_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+                       .name = "xtal",
+                       .index = -1,
                },
                .num_parents = 1,
        },
@@ -237,8 +241,10 @@ static struct clk_regmap meson8b_sys_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+                       .name = "xtal",
+                       .index = -1,
                },
                .num_parents = 1,
        },
@@ -631,9 +637,9 @@ static struct clk_regmap meson8b_cpu_in_sel = {
        .hw.init = &(struct clk_init_data){
                .name = "cpu_in_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw,
-                       &meson8b_sys_pll.hw,
+               .parent_data = (const struct clk_parent_data[]) {
+                       { .fw_name = "xtal", .name = "xtal", .index = -1, },
+                       { .hw = &meson8b_sys_pll.hw, },
                },
                .num_parents = 2,
                .flags = (CLK_SET_RATE_PARENT |
@@ -736,9 +742,9 @@ static struct clk_regmap meson8b_cpu_clk = {
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk",
                .ops = &clk_regmap_mux_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw,
-                       &meson8b_cpu_scale_out_sel.hw,
+               .parent_data = (const struct clk_parent_data[]) {
+                       { .fw_name = "xtal", .name = "xtal", .index = -1, },
+                       { .hw = &meson8b_cpu_scale_out_sel.hw, },
                },
                .num_parents = 2,
                .flags = (CLK_SET_RATE_PARENT |
@@ -758,12 +764,12 @@ static struct clk_regmap meson8b_nand_clk_sel = {
                .name = "nand_clk_sel",
                .ops = &clk_regmap_mux_ops,
                /* FIXME all other parents are unknown: */
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_fclk_div4.hw,
-                       &meson8b_fclk_div3.hw,
-                       &meson8b_fclk_div5.hw,
-                       &meson8b_fclk_div7.hw,
-                       &meson8b_xtal.hw,
+               .parent_data = (const struct clk_parent_data[]) {
+                       { .hw = &meson8b_fclk_div4.hw, },
+                       { .hw = &meson8b_fclk_div3.hw, },
+                       { .hw = &meson8b_fclk_div5.hw, },
+                       { .hw = &meson8b_fclk_div7.hw, },
+                       { .fw_name = "xtal", .name = "xtal", .index = -1, },
                },
                .num_parents = 5,
                .flags = CLK_SET_RATE_PARENT,
@@ -1721,8 +1727,10 @@ static struct clk_regmap meson8b_hdmi_sys_sel = {
                .name = "hdmi_sys_sel",
                .ops = &clk_regmap_mux_ro_ops,
                /* FIXME: all other parents are unknown */
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+                       .name = "xtal",
+                       .index = -1,
                },
                .num_parents = 1,
                .flags = CLK_SET_RATE_NO_REPARENT,
@@ -1764,17 +1772,20 @@ static struct clk_regmap meson8b_hdmi_sys = {
 
 /*
  * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
- * muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only
- * has mali_0 and no glitch-free mux.
+ * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
+ * actually manage this glitch-free mux because it does top-to-bottom
+ * updates the each clock tree and switches to the "inactive" one when
+ * CLK_SET_RATE_GATE is set.
+ * Meson8 only has mali_0 and no glitch-free mux.
  */
-static const struct clk_hw *meson8b_mali_0_1_parent_hws[] = {
-       &meson8b_xtal.hw,
-       &meson8b_mpll2.hw,
-       &meson8b_mpll1.hw,
-       &meson8b_fclk_div7.hw,
-       &meson8b_fclk_div4.hw,
-       &meson8b_fclk_div3.hw,
-       &meson8b_fclk_div5.hw,
+static const struct clk_parent_data meson8b_mali_0_1_parent_data[] = {
+       { .fw_name = "xtal", .name = "xtal", .index = -1, },
+       { .hw = &meson8b_mpll2.hw, },
+       { .hw = &meson8b_mpll1.hw, },
+       { .hw = &meson8b_fclk_div7.hw, },
+       { .hw = &meson8b_fclk_div4.hw, },
+       { .hw = &meson8b_fclk_div3.hw, },
+       { .hw = &meson8b_fclk_div5.hw, },
 };
 
 static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 };
@@ -1789,8 +1800,8 @@ static struct clk_regmap meson8b_mali_0_sel = {
        .hw.init = &(struct clk_init_data){
                .name = "mali_0_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_hws = meson8b_mali_0_1_parent_hws,
-               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws),
+               .parent_data = meson8b_mali_0_1_parent_data,
+               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
                /*
                 * Don't propagate rate changes up because the only changeable
                 * parents are mpll1 and mpll2 but we need those for audio and
@@ -1830,7 +1841,7 @@ static struct clk_regmap meson8b_mali_0 = {
                        &meson8b_mali_0_div.hw
                },
                .num_parents = 1,
-               .flags = CLK_SET_RATE_PARENT,
+               .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
        },
 };
 
@@ -1844,8 +1855,8 @@ static struct clk_regmap meson8b_mali_1_sel = {
        .hw.init = &(struct clk_init_data){
                .name = "mali_1_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_hws = meson8b_mali_0_1_parent_hws,
-               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws),
+               .parent_data = meson8b_mali_0_1_parent_data,
+               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
                /*
                 * Don't propagate rate changes up because the only changeable
                 * parents are mpll1 and mpll2 but we need those for audio and
@@ -1885,7 +1896,7 @@ static struct clk_regmap meson8b_mali_1 = {
                        &meson8b_mali_1_div.hw
                },
                .num_parents = 1,
-               .flags = CLK_SET_RATE_PARENT,
+               .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
        },
 };
 
@@ -1944,8 +1955,10 @@ static struct clk_regmap meson8m2_gp_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "gp_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_hws = (const struct clk_hw *[]) {
-                       &meson8b_xtal.hw
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+                       .name = "xtal",
+                       .index = -1,
                },
                .num_parents = 1,
        },
@@ -3585,7 +3598,7 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
 
 struct meson8b_nb_data {
        struct notifier_block nb;
-       struct clk_hw_onecell_data *onecell_data;
+       struct clk_hw *cpu_clk;
 };
 
 static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
@@ -3593,30 +3606,25 @@ static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
 {
        struct meson8b_nb_data *nb_data =
                container_of(nb, struct meson8b_nb_data, nb);
-       struct clk_hw **hws = nb_data->onecell_data->hws;
-       struct clk_hw *cpu_clk_hw, *parent_clk_hw;
-       struct clk *cpu_clk, *parent_clk;
+       struct clk_hw *parent_clk;
        int ret;
 
        switch (event) {
        case PRE_RATE_CHANGE:
-               parent_clk_hw = hws[CLKID_XTAL];
+               /* xtal */
+               parent_clk = clk_hw_get_parent_by_index(nb_data->cpu_clk, 0);
                break;
 
        case POST_RATE_CHANGE:
-               parent_clk_hw = hws[CLKID_CPU_SCALE_OUT_SEL];
+               /* cpu_scale_out_sel */
+               parent_clk = clk_hw_get_parent_by_index(nb_data->cpu_clk, 1);
                break;
 
        default:
                return NOTIFY_DONE;
        }
 
-       cpu_clk_hw = hws[CLKID_CPUCLK];
-       cpu_clk = __clk_lookup(clk_hw_get_name(cpu_clk_hw));
-
-       parent_clk = __clk_lookup(clk_hw_get_name(parent_clk_hw));
-
-       ret = clk_set_parent(cpu_clk, parent_clk);
+       ret = clk_hw_set_parent(nb_data->cpu_clk, parent_clk);
        if (ret)
                return notifier_from_errno(ret);
 
@@ -3682,20 +3690,26 @@ static void __init meson8b_clkc_init_common(struct device_node *np,
                meson8b_clk_regmaps[i]->map = map;
 
        /*
-        * register all clks
-        * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
+        * always skip CLKID_UNUSED and also skip XTAL if the .dtb provides the
+        * XTAL clock as input.
         */
-       for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
+       if (!IS_ERR(of_clk_get_by_name(np, "xtal")))
+               i = CLKID_PLL_FIXED;
+       else
+               i = CLKID_XTAL;
+
+       /* register all clks */
+       for (; i < CLK_NR_CLKS; i++) {
                /* array might be sparse */
                if (!clk_hw_onecell_data->hws[i])
                        continue;
 
-               ret = clk_hw_register(NULL, clk_hw_onecell_data->hws[i]);
+               ret = of_clk_hw_register(np, clk_hw_onecell_data->hws[i]);
                if (ret)
                        return;
        }
 
-       meson8b_cpu_nb_data.onecell_data = clk_hw_onecell_data;
+       meson8b_cpu_nb_data.cpu_clk = clk_hw_onecell_data->hws[CLKID_CPUCLK];
 
        /*
         * FIXME we shouldn't program the muxes in notifier handlers. The
index 4cd846bc98cc2ec039916a0c10b7f9d8d6eae38c..250d8165167aa013da6c95a090e3e653bd931de7 100644 (file)
@@ -20,8 +20,8 @@ config CLK_RENESAS
        select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
        select CLK_R8A7792 if ARCH_R8A7792
        select CLK_R8A7794 if ARCH_R8A7794
-       select CLK_R8A7795 if ARCH_R8A7795
-       select CLK_R8A77960 if ARCH_R8A77960 || ARCH_R8A7796
+       select CLK_R8A7795 if ARCH_R8A77950 || ARCH_R8A77951 || ARCH_R8A7795
+       select CLK_R8A77960 if ARCH_R8A77960
        select CLK_R8A77961 if ARCH_R8A77961
        select CLK_R8A77965 if ARCH_R8A77965
        select CLK_R8A77970 if ARCH_R8A77970
index cf65d4e0e116664760ba415205126bc58b2ec4c0..443bff08df4c807227616511bd114a8d1364e5bb 100644 (file)
@@ -93,6 +93,7 @@ static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = {
        DEF_MOD_STB("ether1",    64,    R7S9210_CLK_B),
        DEF_MOD_STB("ether0",    65,    R7S9210_CLK_B),
 
+       DEF_MOD_STB("spibsc",    83,    R7S9210_CLK_P1),
        DEF_MOD_STB("i2c3",      84,    R7S9210_CLK_P1),
        DEF_MOD_STB("i2c2",      85,    R7S9210_CLK_P1),
        DEF_MOD_STB("i2c1",      86,    R7S9210_CLK_P1),
index db2f57ef2f9984e4a5ff55a6a42906890f285361..bdcd4a38d48d01bd4a344448746c80eb05d92268 100644 (file)
@@ -24,10 +24,10 @@ enum rcar_gen2_clk_types {
 };
 
 struct rcar_gen2_cpg_pll_config {
-       unsigned int extal_div;
-       unsigned int pll1_mult;
-       unsigned int pll3_mult;
-       unsigned int pll0_mult;         /* leave as zero if PLL0CR exists */
+       u8 extal_div;
+       u8 pll1_mult;
+       u8 pll3_mult;
+       u8 pll0_mult;           /* leave as zero if PLL0CR exists */
 };
 
 struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
index c97b647db9b68f181dbb83362edbe910ffa48adb..488f8b3980c55072009b1f4642efc6e31186b560 100644 (file)
@@ -470,7 +470,8 @@ static struct clk * __init cpg_rpc_clk_register(const char *name,
 
        clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
                                     &rpc->div.hw,  &clk_divider_ops,
-                                    &rpc->gate.hw, &clk_gate_ops, 0);
+                                    &rpc->gate.hw, &clk_gate_ops,
+                                    CLK_SET_RATE_PARENT);
        if (IS_ERR(clk)) {
                kfree(rpc);
                return clk;
@@ -506,7 +507,8 @@ static struct clk * __init cpg_rpcd2_clk_register(const char *name,
 
        clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
                                     &rpcd2->fixed.hw, &clk_fixed_factor_ops,
-                                    &rpcd2->gate.hw, &clk_gate_ops, 0);
+                                    &rpcd2->gate.hw, &clk_gate_ops,
+                                    CLK_SET_RATE_PARENT);
        if (IS_ERR(clk))
                kfree(rpcd2);
 
index 49bd7a4c015c46d4763d941f8d75ea3bec178ee9..5f66bf879772391f20406ff126bda3ebd615c0ba 100644 (file)
@@ -921,11 +921,26 @@ static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
        .num_resets     = ARRAY_SIZE(sun50i_a64_ccu_resets),
 };
 
+static struct ccu_pll_nb sun50i_a64_pll_cpu_nb = {
+       .common = &pll_cpux_clk.common,
+       /* copy from pll_cpux_clk */
+       .enable = BIT(31),
+       .lock   = BIT(28),
+};
+
+static struct ccu_mux_nb sun50i_a64_cpu_nb = {
+       .common         = &cpux_clk.common,
+       .cm             = &cpux_clk.mux,
+       .delay_us       = 1, /* > 8 clock cycles at 24 MHz */
+       .bypass_index   = 1, /* index of 24 MHz oscillator */
+};
+
 static int sun50i_a64_ccu_probe(struct platform_device *pdev)
 {
        struct resource *res;
        void __iomem *reg;
        u32 val;
+       int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg = devm_ioremap_resource(&pdev->dev, res);
@@ -939,7 +954,18 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
 
        writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
 
-       return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+       ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+       if (ret)
+               return ret;
+
+       /* Gate then ungate PLL CPU after any rate changes */
+       ccu_pll_notifier_register(&sun50i_a64_pll_cpu_nb);
+
+       /* Reparent CPU during PLL CPU rate changes */
+       ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
+                                 &sun50i_a64_cpu_nb);
+
+       return 0;
 }
 
 static const struct of_device_id sun50i_a64_ccu_ids[] = {
index 9799292767092090f385bcb07dabfbb056ca15f0..116e6f826d0423680c940405b0630cc96d16b732 100644 (file)
@@ -36,7 +36,6 @@
 #define CLK_PLL_HSIC                   18
 #define CLK_PLL_DE                     19
 #define CLK_PLL_DDR1                   20
-#define CLK_CPUX                       21
 #define CLK_AXI                                22
 #define CLK_APB                                23
 #define CLK_AHB1                       24
index a361388b4670778244b93b44602386ced1b7e9af..3ed2a59b0dc6ef53825d80044ac5c2ec51576512 100644 (file)
@@ -32,7 +32,9 @@
 /* The PLL_VIDEO1_2X clock is exported */
 
 #define CLK_PLL_GPU            14
-#define CLK_PLL_MIPI           15
+
+/* The PLL_VIDEO1_2X clock is exported */
+
 #define CLK_PLL9               16
 #define CLK_PLL10              17
 
index 72df69291cc6bb050df5009a1c9d65072ec58ce5..5bf5c4d13b4cdfea29c17ed1d0c913a408e2fc59 100644 (file)
@@ -24,7 +24,9 @@
 #define CLK_PLL_PERIPH         10
 #define CLK_PLL_PERIPH_2X      11
 #define CLK_PLL_GPU            12
-#define CLK_PLL_MIPI           13
+
+/* The PLL MIPI clock is exported */
+
 #define CLK_PLL_HSIC           14
 #define CLK_PLL_DE             15
 #define CLK_PLL_DDR1           16
index a69637b6b0c1fa047855ed57044777748ffed380..6f7071df8e1cd95ef7716b14871ac1d0dd881831 100644 (file)
 
 /* Some more module clocks are exported */
 
-#define CLK_MBUS               155
-
-/* Another bunch of module clocks are exported */
-
 #define CLK_NUMBER             (CLK_OUTB + 1)
 
 #endif /* _CCU_SUN8I_R40_H_ */
index a165e7172346a0c8afb4da1df4467760a2a2543d..4c75b0770c74bfbbc4262fb6fded369c42b783d7 100644 (file)
@@ -37,7 +37,6 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct clk_onecell_data *clk_data;
-       const struct of_device_id *device;
        const struct gates_data *data;
        const char *clk_parent;
        const char *clk_name;
@@ -50,10 +49,9 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
        if (!np)
                return -ENODEV;
 
-       device = of_match_device(sun6i_a31_apb0_gates_clk_dt_ids, &pdev->dev);
-       if (!device)
+       data = of_device_get_match_data(&pdev->dev);
+       if (!data)
                return -ENODEV;
-       data = device->data;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg = devm_ioremap_resource(&pdev->dev, r);
index 8f6100db90ed498ef730bc852b8b6185c3fddbd4..1c894548dd725c8365bc4eae9b98446ea36739e1 100644 (file)
@@ -751,9 +751,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
        snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
 
        hw = clk_hw_register_mux(dev, clk_name,
-                                (const char *[]){
+                                ((const char *[]){
                                 parent, parent2, parent3, parent4
-                                }, 4, 0, pll_10nm->phy_cmn_mmio +
+                                }), 4, 0, pll_10nm->phy_cmn_mmio +
                                 REG_DSI_10nm_PHY_CMN_CLK_CFG1,
                                 0, 2, 0, NULL);
        if (IS_ERR(hw)) {
index 8c99e01ae332553c719f49eea273deacd43f1abc..6dffd7f4a99b847b578ae358bde10742b29297f6 100644 (file)
@@ -554,9 +554,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
        snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
        snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
        clks[num++] = clk_register_mux(dev, clk_name,
-                       (const char *[]){
+                       ((const char *[]){
                                parent1, parent2
-                       }, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
+                       }), 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
                        REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
 
        snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
diff --git a/include/dt-bindings/clock/meson8-ddr-clkc.h b/include/dt-bindings/clock/meson8-ddr-clkc.h
new file mode 100644 (file)
index 0000000..a8e0fa2
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define DDR_CLKID_DDR_PLL_DCO                  0
+#define DDR_CLKID_DDR_PLL                      1
index a8ac4cfcdcbc3e912bf2549d8b30da45b61bf86a..e512a1c9b0fc18cbf1f3adc9a5ace1043b3f1b7a 100644 (file)
@@ -46,6 +46,7 @@
 #define CLK_PLL_VIDEO0         7
 #define CLK_PLL_PERIPH0                11
 
+#define CLK_CPUX               21
 #define CLK_BUS_MIPI_DSI       28
 #define CLK_BUS_CE             29
 #define CLK_BUS_DMA            30
index c5d13340184aada0817376a662f7ae247648aeb5..39878d9dce9f7b64a8716856cba0debdd6f6f5c9 100644 (file)
@@ -49,6 +49,8 @@
 
 #define CLK_PLL_VIDEO1_2X      13
 
+#define CLK_PLL_MIPI           15
+
 #define CLK_CPU                        18
 
 #define CLK_AHB1_MIPIDSI       23
index f8222b6b2cc31b83fceb05596eed826186054ceb..eb524d0bbd0131796ac4d9226691684dfa324adb 100644 (file)
@@ -43,6 +43,8 @@
 #ifndef _DT_BINDINGS_CLK_SUN8I_A23_A33_H_
 #define _DT_BINDINGS_CLK_SUN8I_A23_A33_H_
 
+#define CLK_PLL_MIPI           13
+
 #define CLK_CPUX               18
 
 #define CLK_BUS_MIPI_DSI       23
index f9e15a235626521726e88b65096943b1a3868c02..d7337b55a4ef05d3b39d6c675e1fd9e1e75a6bc4 100644 (file)
 #define CLK_AVS                        152
 #define CLK_HDMI               153
 #define CLK_HDMI_SLOW          154
-
+#define CLK_MBUS               155
 #define CLK_DSI_DPHY           156
 #define CLK_TVE0               157
 #define CLK_TVE1               158
index 013dc667a50020d0934ce3540a731f3fa27ea759..3f66b5e440e7ec7cb581db9a540325ae0436bcbd 100644 (file)
@@ -328,29 +328,119 @@ struct clk_hw {
  * struct clk_fixed_rate - fixed-rate clock
  * @hw:                handle between common and hardware-specific interfaces
  * @fixed_rate:        constant frequency of clock
+ * @fixed_accuracy: constant accuracy of clock in ppb (parts per billion)
+ * @flags:     hardware specific flags
+ *
+ * Flags:
+ * * CLK_FIXED_RATE_PARENT_ACCURACY - Use the accuracy of the parent clk
+ *                                    instead of what's set in @fixed_accuracy.
  */
 struct clk_fixed_rate {
        struct          clk_hw hw;
        unsigned long   fixed_rate;
        unsigned long   fixed_accuracy;
+       unsigned long   flags;
 };
 
-#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
+#define CLK_FIXED_RATE_PARENT_ACCURACY         BIT(0)
 
 extern const struct clk_ops clk_fixed_rate_ops;
+struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               unsigned long fixed_rate, unsigned long fixed_accuracy,
+               unsigned long clk_fixed_flags);
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                unsigned long fixed_rate);
-struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate);
-struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate, unsigned long fixed_accuracy);
+/**
+ * clk_hw_register_fixed_rate - register fixed-rate clock with the clock
+ * framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ */
+#define clk_hw_register_fixed_rate(dev, name, parent_name, flags, fixed_rate)  \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), NULL, \
+                                    NULL, (flags), (fixed_rate), 0, 0)
+/**
+ * clk_hw_register_fixed_rate_parent_hw - register fixed-rate clock with
+ * the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_hw: pointer to parent clk
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ */
+#define clk_hw_register_fixed_rate_parent_hw(dev, name, parent_hw, flags,     \
+                                            fixed_rate)                      \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw),  \
+                                    NULL, (flags), (fixed_rate), 0, 0)
+/**
+ * clk_hw_register_fixed_rate_parent_data - register fixed-rate clock with
+ * the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_data: parent clk data
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ */
+#define clk_hw_register_fixed_rate_parent_data(dev, name, parent_hw, flags,   \
+                                            fixed_rate)                      \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,         \
+                                    (parent_data), (flags), (fixed_rate), 0, \
+                                    0)
+/**
+ * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
+ * the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ * @fixed_accuracy: non-adjustable clock accuracy
+ */
+#define clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,      \
+                                                flags, fixed_rate,           \
+                                                fixed_accuracy)              \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name),      \
+                                    NULL, NULL, (flags), (fixed_rate),       \
+                                    (fixed_accuracy), 0)
+/**
+ * clk_hw_register_fixed_rate_with_accuracy_parent_hw - register fixed-rate
+ * clock with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_hw: pointer to parent clk
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ * @fixed_accuracy: non-adjustable clock accuracy
+ */
+#define clk_hw_register_fixed_rate_with_accuracy_parent_hw(dev, name,        \
+               parent_hw, flags, fixed_rate, fixed_accuracy)                 \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw)   \
+                                    NULL, NULL, (flags), (fixed_rate),       \
+                                    (fixed_accuracy), 0)
+/**
+ * clk_hw_register_fixed_rate_with_accuracy_parent_data - register fixed-rate
+ * clock with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ * @fixed_accuracy: non-adjustable clock accuracy
+ */
+#define clk_hw_register_fixed_rate_with_accuracy_parent_data(dev, name,              \
+               parent_data, flags, fixed_rate, fixed_accuracy)               \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,         \
+                                    (parent_data), NULL, (flags),            \
+                                    (fixed_rate), (fixed_accuracy), 0)
+
 void clk_unregister_fixed_rate(struct clk *clk);
-struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               unsigned long fixed_rate, unsigned long fixed_accuracy);
 void clk_hw_unregister_fixed_rate(struct clk_hw *hw);
 
 void of_fixed_clk_setup(struct device_node *np);
@@ -393,14 +483,67 @@ struct clk_gate {
 #define CLK_GATE_BIG_ENDIAN            BIT(2)
 
 extern const struct clk_ops clk_gate_ops;
-struct clk *clk_register_gate(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
+struct clk_hw *__clk_hw_register_gate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags,
                void __iomem *reg, u8 bit_idx,
                u8 clk_gate_flags, spinlock_t *lock);
-struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
+struct clk *clk_register_gate(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 bit_idx,
                u8 clk_gate_flags, spinlock_t *lock);
+/**
+ * clk_hw_register_gate - register a gate clock with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_gate(dev, name, parent_name, flags, reg, bit_idx,     \
+                            clk_gate_flags, lock)                            \
+       __clk_hw_register_gate((dev), NULL, (name), (parent_name), NULL,      \
+                              NULL, (flags), (reg), (bit_idx),               \
+                              (clk_gate_flags), (lock))
+/**
+ * clk_hw_register_gate_parent_hw - register a gate clock with the clock
+ * framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_hw: pointer to parent clk
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_gate_parent_hw(dev, name, parent_name, flags, reg,    \
+                                      bit_idx, clk_gate_flags, lock)         \
+       __clk_hw_register_gate((dev), NULL, (name), (parent_name), NULL,      \
+                              NULL, (flags), (reg), (bit_idx),               \
+                              (clk_gate_flags), (lock))
+/**
+ * clk_hw_register_gate_parent_data - register a gate clock with the clock
+ * framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_data: parent clk data
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_gate_parent_data(dev, name, parent_name, flags, reg,  \
+                                      bit_idx, clk_gate_flags, lock)         \
+       __clk_hw_register_gate((dev), NULL, (name), (parent_name), NULL,      \
+                              NULL, (flags), (reg), (bit_idx),               \
+                              (clk_gate_flags), (lock))
 void clk_unregister_gate(struct clk *clk);
 void clk_hw_unregister_gate(struct clk_hw *hw);
 int clk_gate_is_enabled(struct clk_hw *hw);
@@ -490,24 +633,153 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
                const struct clk_div_table *table, u8 width,
                unsigned long flags);
 
-struct clk *clk_register_divider(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, spinlock_t *lock);
-struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name,
-               const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, spinlock_t *lock);
+struct clk_hw *__clk_hw_register_divider(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+               const struct clk_div_table *table, spinlock_t *lock);
 struct clk *clk_register_divider_table(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
                u8 clk_divider_flags, const struct clk_div_table *table,
                spinlock_t *lock);
-struct clk_hw *clk_hw_register_divider_table(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_divider_flags, const struct clk_div_table *table,
-               spinlock_t *lock);
+/**
+ * clk_register_divider - register a divider clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_register_divider(dev, name, parent_name, flags, reg, shift, width, \
+                            clk_divider_flags, lock)                          \
+       clk_register_divider_table((dev), (name), (parent_name), (flags),      \
+                                  (reg), (shift), (width),                    \
+                                  (clk_divider_flags), NULL, (lock))
+/**
+ * clk_hw_register_divider - register a divider clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider(dev, name, parent_name, flags, reg, shift,    \
+                               width, clk_divider_flags, lock)               \
+       __clk_hw_register_divider((dev), NULL, (name), (parent_name), NULL,   \
+                                 NULL, (flags), (reg), (shift), (width),     \
+                                 (clk_divider_flags), NULL, (lock))
+/**
+ * clk_hw_register_divider_parent_hw - register a divider clock with the clock
+ * framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_hw: pointer to parent clk
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider_parent_hw(dev, name, parent_hw, flags, reg,   \
+                                         shift, width, clk_divider_flags,    \
+                                         lock)                               \
+       __clk_hw_register_divider((dev), NULL, (name), NULL, (parent_hw),     \
+                                 NULL, (flags), (reg), (shift), (width),     \
+                                 (clk_divider_flags), NULL, (lock))
+/**
+ * clk_hw_register_divider_parent_data - register a divider clock with the clock
+ * framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_data: parent clk data
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider_parent_data(dev, name, parent_data, flags,    \
+                                           reg, shift, width,                \
+                                           clk_divider_flags, lock)          \
+       __clk_hw_register_divider((dev), NULL, (name), NULL, NULL,            \
+                                 (parent_data), (flags), (reg), (shift),     \
+                                 (width), (clk_divider_flags), NULL, (lock))
+/**
+ * clk_hw_register_divider_table - register a table based divider clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider_table(dev, name, parent_name, flags, reg,     \
+                                     shift, width, clk_divider_flags, table, \
+                                     lock)                                   \
+       __clk_hw_register_divider((dev), NULL, (name), (parent_name), NULL,   \
+                                 NULL, (flags), (reg), (shift), (width),     \
+                                 (clk_divider_flags), (table), (lock))
+/**
+ * clk_hw_register_divider_table_parent_hw - register a table based divider
+ * clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_hw: pointer to parent clk
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider_table_parent_hw(dev, name, parent_hw, flags,  \
+                                               reg, shift, width,            \
+                                               clk_divider_flags, table,     \
+                                               lock)                         \
+       __clk_hw_register_divider((dev), NULL, (name), NULL, (parent_hw),     \
+                                 NULL, (flags), (reg), (shift), (width),     \
+                                 (clk_divider_flags), (table), (lock))
+/**
+ * clk_hw_register_divider_table_parent_data - register a table based divider
+ * clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_data: parent clk data
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+#define clk_hw_register_divider_table_parent_data(dev, name, parent_data,     \
+                                                 flags, reg, shift, width,   \
+                                                 clk_divider_flags, table,   \
+                                                 lock)                       \
+       __clk_hw_register_divider((dev), NULL, (name), NULL, NULL,            \
+                                 (parent_data), (flags), (reg), (shift),     \
+                                 (width), (clk_divider_flags), (table),      \
+                                 (lock))
+
 void clk_unregister_divider(struct clk *clk);
 void clk_hw_unregister_divider(struct clk_hw *hw);
 
@@ -562,28 +834,48 @@ struct clk_mux {
 extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
 
-struct clk *clk_register_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_mux_flags, spinlock_t *lock);
-struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_mux_flags, spinlock_t *lock);
-
-struct clk *clk_register_mux_table(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u32 mask,
+struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
+               const char *name, u8 num_parents,
+               const char * const *parent_names,
+               const struct clk_hw **parent_hws,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock);
-struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
                const char * const *parent_names, u8 num_parents,
-               unsigned long flags,
-               void __iomem *reg, u8 shift, u32 mask,
+               unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
+#define clk_register_mux(dev, name, parent_names, num_parents, flags, reg,    \
+                        shift, width, clk_mux_flags, lock)                   \
+       clk_register_mux_table((dev), (name), (parent_names), (num_parents),  \
+                              (flags), (reg), (shift), BIT((width)) - 1,     \
+                              (clk_mux_flags), NULL, (lock))
+#define clk_hw_register_mux_table(dev, name, parent_names, num_parents,              \
+                                 flags, reg, shift, mask, clk_mux_flags,     \
+                                 table, lock)                                \
+       __clk_hw_register_mux((dev), NULL, (name), (num_parents),             \
+                             (parent_names), NULL, NULL, (flags), (reg),     \
+                             (shift), (mask), (clk_mux_flags), (table),      \
+                             (lock))
+#define clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
+                           shift, width, clk_mux_flags, lock)                \
+       __clk_hw_register_mux((dev), NULL, (name), (num_parents),             \
+                             (parent_names), NULL, NULL, (flags), (reg),     \
+                             (shift), BIT((width)) - 1, (clk_mux_flags),     \
+                             NULL, (lock))
+#define clk_hw_register_mux_hws(dev, name, parent_hws, num_parents, flags,    \
+                               reg, shift, width, clk_mux_flags, lock)       \
+       __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL,       \
+                             (parent_hws), NULL, (flags), (reg), (shift),    \
+                             BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
+#define clk_hw_register_mux_parent_data(dev, name, parent_data, num_parents,  \
+                                       flags, reg, shift, width,             \
+                                       clk_mux_flags, lock)                  \
+       __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
+                             (parent_data), (flags), (reg), (shift),         \
+                             BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
+
 int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
                         unsigned int val);
 unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
@@ -759,44 +1051,6 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
                unsigned long flags);
 void clk_hw_unregister_composite(struct clk_hw *hw);
 
-/**
- * struct clk_gpio - gpio gated clock
- *
- * @hw:                handle between common and hardware-specific interfaces
- * @gpiod:     gpio descriptor
- *
- * Clock with a gpio control for enabling and disabling the parent clock
- * or switching between two parents by asserting or deasserting the gpio.
- *
- * Implements .enable, .disable and .is_enabled or
- * .get_parent, .set_parent and .determine_rate depending on which clk_ops
- * is used.
- */
-struct clk_gpio {
-       struct clk_hw   hw;
-       struct gpio_desc *gpiod;
-};
-
-#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
-
-extern const struct clk_ops clk_gpio_gate_ops;
-struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpiod,
-               unsigned long flags);
-struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpiod,
-               unsigned long flags);
-void clk_hw_unregister_gpio_gate(struct clk_hw *hw);
-
-extern const struct clk_ops clk_gpio_mux_ops;
-struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
-               unsigned long flags);
-struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
-               const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
-               unsigned long flags);
-void clk_hw_unregister_gpio_mux(struct clk_hw *hw);
-
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
 struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
index 18b7b95a8253c775c58920884e2a151df1e670f9..7fd6a1febcf4f400dd0aaa5b7f128c3a36035793 100644 (file)
@@ -627,6 +627,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
  * @clk: clock source
  * @rate: desired clock rate in Hz
  *
+ * Updating the rate starts at the top-most affected clock and then
+ * walks the tree down to the bottom-most clock that needs updating.
+ *
  * Returns success (0) or negative errno.
  */
 int clk_set_rate(struct clk *clk, unsigned long rate);