Commit 6e7a9f0c authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-debugfs-danger', 'clk-basic-hw', 'clk-renesas',...

Merge branches 'clk-debugfs-danger', 'clk-basic-hw', 'clk-renesas', 'clk-amlogic' and 'clk-allwinner' into clk-next

 - 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
# 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>;
};
...
...@@ -11,6 +11,11 @@ Required Properties: ...@@ -11,6 +11,11 @@ Required Properties:
- "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs - "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
- #clock-cells: should be 1. - #clock-cells: should be 1.
- #reset-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 : Parent node should have the following properties :
- compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon" - compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
......
...@@ -19,7 +19,7 @@ Required Properties: ...@@ -19,7 +19,7 @@ Required Properties:
- "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E) - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
- "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C) - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C)
- "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M) - "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,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E)
- "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2) - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
- "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W) - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
......
...@@ -260,7 +260,6 @@ static void __init asm9260_acc_init(struct device_node *np) ...@@ -260,7 +260,6 @@ static void __init asm9260_acc_init(struct device_node *np)
const char *ref_clk, *pll_clk = "pll"; const char *ref_clk, *pll_clk = "pll";
u32 rate; u32 rate;
int n; int n;
u32 accuracy = 0;
clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
if (!clk_data) if (!clk_data)
...@@ -275,10 +274,11 @@ static void __init asm9260_acc_init(struct device_node *np) ...@@ -275,10 +274,11 @@ static void __init asm9260_acc_init(struct device_node *np)
/* register pll */ /* register pll */
rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000; rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
/* TODO: Convert to DT parent scheme */
ref_clk = of_clk_get_parent_name(np, 0); 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, NULL, pll_clk,
hw = clk_hw_register_fixed_rate_with_accuracy(NULL, pll_clk, ref_clk, NULL, NULL, 0, rate, 0,
ref_clk, 0, rate, accuracy); CLK_FIXED_RATE_PARENT_ACCURACY);
if (IS_ERR(hw)) if (IS_ERR(hw))
panic("%pOFn: can't register REFCLK. Check DT!", np); panic("%pOFn: can't register REFCLK. Check DT!", np);
......
...@@ -463,11 +463,12 @@ const struct clk_ops clk_divider_ro_ops = { ...@@ -463,11 +463,12 @@ const struct clk_ops clk_divider_ro_ops = {
}; };
EXPORT_SYMBOL_GPL(clk_divider_ro_ops); EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
static struct clk_hw *_register_divider(struct device *dev, const char *name, struct clk_hw *__clk_hw_register_divider(struct device *dev,
const char *parent_name, unsigned long flags, struct device_node *np, const char *name,
void __iomem *reg, u8 shift, u8 width, const char *parent_name, const struct clk_hw *parent_hw,
u8 clk_divider_flags, const struct clk_div_table *table, const struct clk_parent_data *parent_data, unsigned long flags,
spinlock_t *lock) 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_divider *div;
struct clk_hw *hw; struct clk_hw *hw;
...@@ -514,55 +515,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name, ...@@ -514,55 +515,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name,
return hw; return hw;
} }
EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
/**
* 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);
/** /**
* clk_register_divider_table - register a table based divider clock with * 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, ...@@ -586,39 +539,15 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
{ {
struct clk_hw *hw; struct clk_hw *hw;
hw = _register_divider(dev, name, parent_name, flags, reg, shift, hw = __clk_hw_register_divider(dev, NULL, name, parent_name, NULL,
width, clk_divider_flags, table, lock); NULL, flags, reg, shift, width, clk_divider_flags,
table, lock);
if (IS_ERR(hw)) if (IS_ERR(hw))
return ERR_CAST(hw); return ERR_CAST(hw);
return hw->clk; return hw->clk;
} }
EXPORT_SYMBOL_GPL(clk_register_divider_table); 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) void clk_unregister_divider(struct clk *clk)
{ {
struct clk_divider *div; struct clk_divider *div;
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* parent - fixed parent. No clk_set_parent support * 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, static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
...@@ -33,7 +35,12 @@ static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, ...@@ -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, static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw,
unsigned long parent_accuracy) 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 = { const struct clk_ops clk_fixed_rate_ops = {
...@@ -42,24 +49,17 @@ 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); EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
/** struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
* clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with struct device_node *np, const char *name,
* the clock framework const char *parent_name, const struct clk_hw *parent_hw,
* @dev: device that is registering this clock const struct clk_parent_data *parent_data, unsigned long flags,
* @name: name of this clock unsigned long fixed_rate, unsigned long fixed_accuracy,
* @parent_name: name of clock's parent unsigned long clk_fixed_flags)
* @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_fixed_rate *fixed; struct clk_fixed_rate *fixed;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init = {}; struct clk_init_data init = {};
int ret; int ret = -EINVAL;
/* allocate fixed-rate clock */ /* allocate fixed-rate clock */
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
...@@ -69,17 +69,26 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, ...@@ -69,17 +69,26 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
init.name = name; init.name = name;
init.ops = &clk_fixed_rate_ops; init.ops = &clk_fixed_rate_ops;
init.flags = flags; init.flags = flags;
init.parent_names = (parent_name ? &parent_name: NULL); 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_fixed_rate assignments */ /* struct clk_fixed_rate assignments */
fixed->flags = clk_fixed_flags;
fixed->fixed_rate = fixed_rate; fixed->fixed_rate = fixed_rate;
fixed->fixed_accuracy = fixed_accuracy; fixed->fixed_accuracy = fixed_accuracy;
fixed->hw.init = &init; fixed->hw.init = &init;
/* register the clock */ /* register the clock */
hw = &fixed->hw; hw = &fixed->hw;
if (dev || !np)
ret = clk_hw_register(dev, hw); ret = clk_hw_register(dev, hw);
else if (np)
ret = of_clk_hw_register(np, hw);
if (ret) { if (ret) {
kfree(fixed); kfree(fixed);
hw = ERR_PTR(ret); hw = ERR_PTR(ret);
...@@ -87,47 +96,20 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, ...@@ -87,47 +96,20 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
return hw; 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, struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
const char *name, const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
unsigned long fixed_rate, unsigned long fixed_accuracy) unsigned long fixed_rate)
{ {
struct clk_hw *hw; struct clk_hw *hw;
hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, 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)) if (IS_ERR(hw))
return ERR_CAST(hw); return ERR_CAST(hw);
return hw->clk; 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); EXPORT_SYMBOL_GPL(clk_register_fixed_rate);
void clk_unregister_fixed_rate(struct clk *clk) void clk_unregister_fixed_rate(struct clk *clk)
...@@ -155,9 +137,9 @@ void clk_hw_unregister_fixed_rate(struct clk_hw *hw) ...@@ -155,9 +137,9 @@ void clk_hw_unregister_fixed_rate(struct clk_hw *hw)
EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate); EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate);
#ifdef CONFIG_OF #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; const char *clk_name = node->name;
u32 rate; u32 rate;
u32 accuracy = 0; u32 accuracy = 0;
...@@ -170,18 +152,18 @@ static struct clk *_of_fixed_clk_setup(struct device_node *node) ...@@ -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); 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); 0, rate, accuracy);
if (IS_ERR(clk)) if (IS_ERR(hw))
return clk; 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) { if (ret) {
clk_unregister(clk); clk_hw_unregister_fixed_rate(hw);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
return clk; return hw;
} }
/** /**
...@@ -195,27 +177,27 @@ CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); ...@@ -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) 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); of_clk_del_provider(pdev->dev.of_node);
clk_unregister_fixed_rate(clk); clk_hw_unregister_fixed_rate(hw);
return 0; return 0;
} }
static int of_fixed_clk_probe(struct platform_device *pdev) 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 * This function is not executed when of_fixed_clk_setup
* succeeded. * succeeded.
*/ */
clk = _of_fixed_clk_setup(pdev->dev.of_node); hw = _of_fixed_clk_setup(pdev->dev.of_node);
if (IS_ERR(clk)) if (IS_ERR(hw))
return PTR_ERR(clk); return PTR_ERR(hw);
platform_set_drvdata(pdev, clk); platform_set_drvdata(pdev, hw);
return 0; return 0;
} }
...@@ -224,7 +206,6 @@ static const struct of_device_id of_fixed_clk_ids[] = { ...@@ -224,7 +206,6 @@ static const struct of_device_id of_fixed_clk_ids[] = {
{ .compatible = "fixed-clock" }, { .compatible = "fixed-clock" },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, of_fixed_clk_ids);
static struct platform_driver of_fixed_clk_driver = { static struct platform_driver of_fixed_clk_driver = {
.driver = { .driver = {
......
...@@ -123,26 +123,18 @@ const struct clk_ops clk_gate_ops = { ...@@ -123,26 +123,18 @@ const struct clk_ops clk_gate_ops = {
}; };
EXPORT_SYMBOL_GPL(clk_gate_ops); EXPORT_SYMBOL_GPL(clk_gate_ops);
/** struct clk_hw *__clk_hw_register_gate(struct device *dev,
* clk_hw_register_gate - register a gate clock with the clock framework struct device_node *np, const char *name,
* @dev: device that is registering this clock const char *parent_name, const struct clk_hw *parent_hw,
* @name: name of this clock const struct clk_parent_data *parent_data,
* @parent_name: name of this clock's parent unsigned long flags,
* @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,
void __iomem *reg, u8 bit_idx, void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock) u8 clk_gate_flags, spinlock_t *lock)
{ {
struct clk_gate *gate; struct clk_gate *gate;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init = {}; struct clk_init_data init = {};
int ret; int ret = -EINVAL;
if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
if (bit_idx > 15) { if (bit_idx > 15) {
...@@ -160,7 +152,12 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, ...@@ -160,7 +152,12 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
init.ops = &clk_gate_ops; init.ops = &clk_gate_ops;
init.flags = flags; init.flags = flags;
init.parent_names = parent_name ? &parent_name : NULL; 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 */ /* struct clk_gate assignments */
gate->reg = reg; gate->reg = reg;
...@@ -170,15 +167,19 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, ...@@ -170,15 +167,19 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
gate->hw.init = &init; gate->hw.init = &init;
hw = &gate->hw; hw = &gate->hw;
if (dev || !np)
ret = clk_hw_register(dev, hw); ret = clk_hw_register(dev, hw);
else if (np)
ret = of_clk_hw_register(np, hw);
if (ret) { if (ret) {
kfree(gate); kfree(gate);
hw = ERR_PTR(ret); hw = ERR_PTR(ret);
} }
return hw; 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, struct clk *clk_register_gate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
......
...@@ -28,6 +28,26 @@ ...@@ -28,6 +28,26 @@
* parent - fixed parent. No clk_set_parent support * 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) static int clk_gpio_gate_enable(struct clk_hw *hw)
{ {
struct clk_gpio *clk = to_clk_gpio(hw); struct clk_gpio *clk = to_clk_gpio(hw);
...@@ -51,12 +71,11 @@ static int clk_gpio_gate_is_enabled(struct clk_hw *hw) ...@@ -51,12 +71,11 @@ static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
return gpiod_get_value(clk->gpiod); 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, .enable = clk_gpio_gate_enable,
.disable = clk_gpio_gate_disable, .disable = clk_gpio_gate_disable,
.is_enabled = clk_gpio_gate_is_enabled, .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) 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) ...@@ -111,67 +130,49 @@ static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
return 0; 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, .get_parent = clk_gpio_mux_get_parent,
.set_parent = clk_gpio_mux_set_parent, .set_parent = clk_gpio_mux_set_parent,
.determine_rate = __clk_mux_determine_rate, .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, static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, struct gpio_desc *gpiod,
unsigned long flags, const struct clk_ops *clk_gpio_ops) const struct clk_ops *clk_gpio_ops)
{ {
struct clk_gpio *clk_gpio; struct clk_gpio *clk_gpio;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init = {}; struct clk_init_data init = {};
int err; 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); clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
else
clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);
if (!clk_gpio) if (!clk_gpio)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
init.name = name; init.name = dev->of_node->name;
init.ops = clk_gpio_ops; init.ops = clk_gpio_ops;
init.flags = flags; init.parent_data = gpio_parent_data;
init.parent_names = parent_names;
init.num_parents = num_parents; init.num_parents = num_parents;
init.flags = CLK_SET_RATE_PARENT;
clk_gpio->gpiod = gpiod; clk_gpio->gpiod = gpiod;
clk_gpio->hw.init = &init; clk_gpio->hw.init = &init;
hw = &clk_gpio->hw; hw = &clk_gpio->hw;
if (dev)
err = devm_clk_hw_register(dev, hw); err = devm_clk_hw_register(dev, hw);
else if (err)
err = clk_hw_register(NULL, hw); return ERR_PTR(err);
if (!err)
return hw; return hw;
if (!dev) {
kfree(clk_gpio);
}
return ERR_PTR(err);
} }
/** static struct clk_hw *clk_hw_register_gpio_gate(struct device *dev,
* clk_hw_register_gpio_gate - register a gpio clock gate with the clock int num_parents,
* framework struct gpio_desc *gpiod)
* @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)
{ {
const struct clk_ops *ops; const struct clk_ops *ops;
...@@ -180,88 +181,36 @@ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, ...@@ -180,88 +181,36 @@ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
else else
ops = &clk_gpio_gate_ops; ops = &clk_gpio_gate_ops;
return clk_register_gpio(dev, name, return clk_register_gpio(dev, num_parents, gpiod, ops);
(parent_name ? &parent_name : NULL),
(parent_name ? 1 : 0), gpiod, flags, ops);
} }
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
struct clk *clk_register_gpio_gate(struct device *dev, const char *name, static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
const char *parent_name, struct gpio_desc *gpiod, struct gpio_desc *gpiod)
unsigned long flags)
{ {
struct clk_hw *hw; return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags);
if (IS_ERR(hw))
return ERR_CAST(hw);
return hw->clk;
}
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) static int gpio_clk_driver_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev;
const char **parent_names, *gpio_name; struct device_node *node = dev->of_node;
const char *gpio_name;
unsigned int num_parents; unsigned int num_parents;
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
struct clk *clk; struct clk_hw *hw;
bool is_mux; bool is_mux;
int ret; int ret;
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
num_parents = of_clk_get_parent_count(node); num_parents = of_clk_get_parent_count(node);
if (num_parents) { if (is_mux && num_parents != 2) {
parent_names = devm_kcalloc(&pdev->dev, num_parents, dev_err(dev, "mux-clock must have 2 parents\n");
sizeof(char *), GFP_KERNEL); return -EINVAL;
if (!parent_names)
return -ENOMEM;
of_clk_parent_fill(node, parent_names, num_parents);
} else {
parent_names = NULL;
} }
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
gpio_name = is_mux ? "select" : "enable"; 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)) { if (IS_ERR(gpiod)) {
ret = PTR_ERR(gpiod); ret = PTR_ERR(gpiod);
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
...@@ -275,16 +224,13 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) ...@@ -275,16 +224,13 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
} }
if (is_mux) if (is_mux)
clk = clk_register_gpio_mux(&pdev->dev, node->name, hw = clk_hw_register_gpio_mux(dev, gpiod);
parent_names, num_parents, gpiod, 0);
else else
clk = clk_register_gpio_gate(&pdev->dev, node->name, hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod);
parent_names ? parent_names[0] : NULL, gpiod, if (IS_ERR(hw))
CLK_SET_RATE_PARENT); return PTR_ERR(hw);
if (IS_ERR(clk))
return PTR_ERR(clk);
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[] = { static const struct of_device_id gpio_clk_match_table[] = {
......
...@@ -145,17 +145,19 @@ const struct clk_ops clk_mux_ro_ops = { ...@@ -145,17 +145,19 @@ const struct clk_ops clk_mux_ro_ops = {
}; };
EXPORT_SYMBOL_GPL(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, struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
const char * const *parent_names, u8 num_parents, const char *name, u8 num_parents,
unsigned long flags, const char * const *parent_names,
void __iomem *reg, u8 shift, u32 mask, 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) u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{ {
struct clk_mux *mux; struct clk_mux *mux;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init = {}; struct clk_init_data init = {};
u8 width = 0; u8 width = 0;
int ret; int ret = -EINVAL;
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
width = fls(mask) - ffs(mask) + 1; width = fls(mask) - ffs(mask) + 1;
...@@ -177,6 +179,8 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, ...@@ -177,6 +179,8 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
init.ops = &clk_mux_ops; init.ops = &clk_mux_ops;
init.flags = flags; init.flags = flags;
init.parent_names = parent_names; init.parent_names = parent_names;
init.parent_data = parent_data;
init.parent_hws = parent_hws;
init.num_parents = num_parents; init.num_parents = num_parents;
/* struct clk_mux assignments */ /* struct clk_mux assignments */
...@@ -189,7 +193,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, ...@@ -189,7 +193,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
mux->hw.init = &init; mux->hw.init = &init;
hw = &mux->hw; hw = &mux->hw;
if (dev || !np)
ret = clk_hw_register(dev, hw); ret = clk_hw_register(dev, hw);
else if (np)
ret = of_clk_hw_register(np, hw);
if (ret) { if (ret) {
kfree(mux); kfree(mux);
hw = ERR_PTR(ret); hw = ERR_PTR(ret);
...@@ -197,53 +204,24 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, ...@@ -197,53 +204,24 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
return hw; 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, struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, const char * const *parent_names, u8 num_parents,
unsigned long flags, unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock) u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{ {
struct clk_hw *hw; struct clk_hw *hw;
hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents, hw = clk_hw_register_mux_table(dev, name, parent_names,
flags, reg, shift, mask, clk_mux_flags, num_parents, flags, reg, shift, mask,
table, lock); clk_mux_flags, table, lock);
if (IS_ERR(hw)) if (IS_ERR(hw))
return ERR_CAST(hw); return ERR_CAST(hw);
return hw->clk; return hw->clk;
} }
EXPORT_SYMBOL_GPL(clk_register_mux_table); 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) void clk_unregister_mux(struct clk *clk)
{ {
struct clk_mux *mux; struct clk_mux *mux;
......
...@@ -2996,6 +2996,41 @@ static int clk_dump_show(struct seq_file *s, void *data) ...@@ -2996,6 +2996,41 @@ static int clk_dump_show(struct seq_file *s, void *data)
} }
DEFINE_SHOW_ATTRIBUTE(clk_dump); 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 { static const struct {
unsigned long flag; unsigned long flag;
const char *name; const char *name;
...@@ -3145,7 +3180,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) ...@@ -3145,7 +3180,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
root = debugfs_create_dir(core->name, pdentry); root = debugfs_create_dir(core->name, pdentry);
core->dentry = root; 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_min_rate", 0444, root, core, &clk_min_rate_fops);
debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops); debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy); debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
......
...@@ -18,4 +18,4 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o ...@@ -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_AXG_AUDIO) += axg-audio.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.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_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
...@@ -77,6 +77,15 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, ...@@ -77,6 +77,15 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
unsigned int m, n, frac; unsigned int m, n, frac;
n = meson_parm_read(clk->map, &pll->n); 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); m = meson_parm_read(clk->map, &pll->m);
frac = MESON_PARM_APPLICABLE(&pll->frac) ? frac = MESON_PARM_APPLICABLE(&pll->frac) ?
......
...@@ -4692,6 +4692,7 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { ...@@ -4692,6 +4692,7 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
&g12a_bt656, &g12a_bt656,
&g12a_usb1_to_ddr, &g12a_usb1_to_ddr,
&g12a_mmc_pclk, &g12a_mmc_pclk,
&g12a_uart2,
&g12a_vpu_intr, &g12a_vpu_intr,
&g12a_gic, &g12a_gic,
&g12a_sd_emmc_a_clk0, &g12a_sd_emmc_a_clk0,
......
// 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);
...@@ -97,8 +97,10 @@ static struct clk_regmap meson8b_fixed_pll_dco = { ...@@ -97,8 +97,10 @@ static struct clk_regmap meson8b_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco", .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = &(const struct clk_parent_data) {
&meson8b_xtal.hw .fw_name = "xtal",
.name = "xtal",
.index = -1,
}, },
.num_parents = 1, .num_parents = 1,
}, },
...@@ -162,8 +164,10 @@ static struct clk_regmap meson8b_hdmi_pll_dco = { ...@@ -162,8 +164,10 @@ static struct clk_regmap meson8b_hdmi_pll_dco = {
/* sometimes also called "HPLL" or "HPLL PLL" */ /* sometimes also called "HPLL" or "HPLL PLL" */
.name = "hdmi_pll_dco", .name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = &(const struct clk_parent_data) {
&meson8b_xtal.hw .fw_name = "xtal",
.name = "xtal",
.index = -1,
}, },
.num_parents = 1, .num_parents = 1,
}, },
...@@ -237,8 +241,10 @@ static struct clk_regmap meson8b_sys_pll_dco = { ...@@ -237,8 +241,10 @@ static struct clk_regmap meson8b_sys_pll_dco = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "sys_pll_dco", .name = "sys_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = &(const struct clk_parent_data) {
&meson8b_xtal.hw .fw_name = "xtal",
.name = "xtal",
.index = -1,
}, },
.num_parents = 1, .num_parents = 1,
}, },
...@@ -631,9 +637,9 @@ static struct clk_regmap meson8b_cpu_in_sel = { ...@@ -631,9 +637,9 @@ static struct clk_regmap meson8b_cpu_in_sel = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "cpu_in_sel", .name = "cpu_in_sel",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = (const struct clk_parent_data[]) {
&meson8b_xtal.hw, { .fw_name = "xtal", .name = "xtal", .index = -1, },
&meson8b_sys_pll.hw, { .hw = &meson8b_sys_pll.hw, },
}, },
.num_parents = 2, .num_parents = 2,
.flags = (CLK_SET_RATE_PARENT | .flags = (CLK_SET_RATE_PARENT |
...@@ -736,9 +742,9 @@ static struct clk_regmap meson8b_cpu_clk = { ...@@ -736,9 +742,9 @@ static struct clk_regmap meson8b_cpu_clk = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "cpu_clk", .name = "cpu_clk",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = (const struct clk_parent_data[]) {
&meson8b_xtal.hw, { .fw_name = "xtal", .name = "xtal", .index = -1, },
&meson8b_cpu_scale_out_sel.hw, { .hw = &meson8b_cpu_scale_out_sel.hw, },
}, },
.num_parents = 2, .num_parents = 2,
.flags = (CLK_SET_RATE_PARENT | .flags = (CLK_SET_RATE_PARENT |
...@@ -758,12 +764,12 @@ static struct clk_regmap meson8b_nand_clk_sel = { ...@@ -758,12 +764,12 @@ static struct clk_regmap meson8b_nand_clk_sel = {
.name = "nand_clk_sel", .name = "nand_clk_sel",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
/* FIXME all other parents are unknown: */ /* FIXME all other parents are unknown: */
.parent_hws = (const struct clk_hw *[]) { .parent_data = (const struct clk_parent_data[]) {
&meson8b_fclk_div4.hw, { .hw = &meson8b_fclk_div4.hw, },
&meson8b_fclk_div3.hw, { .hw = &meson8b_fclk_div3.hw, },
&meson8b_fclk_div5.hw, { .hw = &meson8b_fclk_div5.hw, },
&meson8b_fclk_div7.hw, { .hw = &meson8b_fclk_div7.hw, },
&meson8b_xtal.hw, { .fw_name = "xtal", .name = "xtal", .index = -1, },
}, },
.num_parents = 5, .num_parents = 5,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
...@@ -1721,8 +1727,10 @@ static struct clk_regmap meson8b_hdmi_sys_sel = { ...@@ -1721,8 +1727,10 @@ static struct clk_regmap meson8b_hdmi_sys_sel = {
.name = "hdmi_sys_sel", .name = "hdmi_sys_sel",
.ops = &clk_regmap_mux_ro_ops, .ops = &clk_regmap_mux_ro_ops,
/* FIXME: all other parents are unknown */ /* FIXME: all other parents are unknown */
.parent_hws = (const struct clk_hw *[]) { .parent_data = &(const struct clk_parent_data) {
&meson8b_xtal.hw .fw_name = "xtal",
.name = "xtal",
.index = -1,
}, },
.num_parents = 1, .num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT, .flags = CLK_SET_RATE_NO_REPARENT,
...@@ -1764,17 +1772,20 @@ static struct clk_regmap meson8b_hdmi_sys = { ...@@ -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) * 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 * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
* has mali_0 and no glitch-free mux. * 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[] = { static const struct clk_parent_data meson8b_mali_0_1_parent_data[] = {
&meson8b_xtal.hw, { .fw_name = "xtal", .name = "xtal", .index = -1, },
&meson8b_mpll2.hw, { .hw = &meson8b_mpll2.hw, },
&meson8b_mpll1.hw, { .hw = &meson8b_mpll1.hw, },
&meson8b_fclk_div7.hw, { .hw = &meson8b_fclk_div7.hw, },
&meson8b_fclk_div4.hw, { .hw = &meson8b_fclk_div4.hw, },
&meson8b_fclk_div3.hw, { .hw = &meson8b_fclk_div3.hw, },
&meson8b_fclk_div5.hw, { .hw = &meson8b_fclk_div5.hw, },
}; };
static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 }; 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 = { ...@@ -1789,8 +1800,8 @@ static struct clk_regmap meson8b_mali_0_sel = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "mali_0_sel", .name = "mali_0_sel",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
.parent_hws = meson8b_mali_0_1_parent_hws, .parent_data = meson8b_mali_0_1_parent_data,
.num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws), .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
/* /*
* Don't propagate rate changes up because the only changeable * Don't propagate rate changes up because the only changeable
* parents are mpll1 and mpll2 but we need those for audio and * parents are mpll1 and mpll2 but we need those for audio and
...@@ -1830,7 +1841,7 @@ static struct clk_regmap meson8b_mali_0 = { ...@@ -1830,7 +1841,7 @@ static struct clk_regmap meson8b_mali_0 = {
&meson8b_mali_0_div.hw &meson8b_mali_0_div.hw
}, },
.num_parents = 1, .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 = { ...@@ -1844,8 +1855,8 @@ static struct clk_regmap meson8b_mali_1_sel = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "mali_1_sel", .name = "mali_1_sel",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
.parent_hws = meson8b_mali_0_1_parent_hws, .parent_data = meson8b_mali_0_1_parent_data,
.num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_hws), .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
/* /*
* Don't propagate rate changes up because the only changeable * Don't propagate rate changes up because the only changeable
* parents are mpll1 and mpll2 but we need those for audio and * parents are mpll1 and mpll2 but we need those for audio and
...@@ -1885,7 +1896,7 @@ static struct clk_regmap meson8b_mali_1 = { ...@@ -1885,7 +1896,7 @@ static struct clk_regmap meson8b_mali_1 = {
&meson8b_mali_1_div.hw &meson8b_mali_1_div.hw
}, },
.num_parents = 1, .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 = { ...@@ -1944,8 +1955,10 @@ static struct clk_regmap meson8m2_gp_pll_dco = {
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "gp_pll_dco", .name = "gp_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_hws = (const struct clk_hw *[]) { .parent_data = &(const struct clk_parent_data) {
&meson8b_xtal.hw .fw_name = "xtal",
.name = "xtal",
.index = -1,
}, },
.num_parents = 1, .num_parents = 1,
}, },
...@@ -3585,7 +3598,7 @@ static const struct reset_control_ops meson8b_clk_reset_ops = { ...@@ -3585,7 +3598,7 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
struct meson8b_nb_data { struct meson8b_nb_data {
struct notifier_block nb; 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, 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, ...@@ -3593,30 +3606,25 @@ static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
{ {
struct meson8b_nb_data *nb_data = struct meson8b_nb_data *nb_data =
container_of(nb, struct meson8b_nb_data, nb); container_of(nb, struct meson8b_nb_data, nb);
struct clk_hw **hws = nb_data->onecell_data->hws; struct clk_hw *parent_clk;
struct clk_hw *cpu_clk_hw, *parent_clk_hw;
struct clk *cpu_clk, *parent_clk;
int ret; int ret;
switch (event) { switch (event) {
case PRE_RATE_CHANGE: 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; break;
case POST_RATE_CHANGE: 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; break;
default: default:
return NOTIFY_DONE; return NOTIFY_DONE;
} }
cpu_clk_hw = hws[CLKID_CPUCLK]; ret = clk_hw_set_parent(nb_data->cpu_clk, parent_clk);
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);
if (ret) if (ret)
return notifier_from_errno(ret); return notifier_from_errno(ret);
...@@ -3682,20 +3690,26 @@ static void __init meson8b_clkc_init_common(struct device_node *np, ...@@ -3682,20 +3690,26 @@ static void __init meson8b_clkc_init_common(struct device_node *np,
meson8b_clk_regmaps[i]->map = map; meson8b_clk_regmaps[i]->map = map;
/* /*
* register all clks * always skip CLKID_UNUSED and also skip XTAL if the .dtb provides the
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 * 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 */ /* array might be sparse */
if (!clk_hw_onecell_data->hws[i]) if (!clk_hw_onecell_data->hws[i])
continue; 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) if (ret)
return; 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 * FIXME we shouldn't program the muxes in notifier handlers. The
......
...@@ -20,8 +20,8 @@ config CLK_RENESAS ...@@ -20,8 +20,8 @@ config CLK_RENESAS
select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
select CLK_R8A7792 if ARCH_R8A7792 select CLK_R8A7792 if ARCH_R8A7792
select CLK_R8A7794 if ARCH_R8A7794 select CLK_R8A7794 if ARCH_R8A7794
select CLK_R8A7795 if ARCH_R8A7795 select CLK_R8A7795 if ARCH_R8A77950 || ARCH_R8A77951 || ARCH_R8A7795
select CLK_R8A77960 if ARCH_R8A77960 || ARCH_R8A7796 select CLK_R8A77960 if ARCH_R8A77960
select CLK_R8A77961 if ARCH_R8A77961 select CLK_R8A77961 if ARCH_R8A77961
select CLK_R8A77965 if ARCH_R8A77965 select CLK_R8A77965 if ARCH_R8A77965
select CLK_R8A77970 if ARCH_R8A77970 select CLK_R8A77970 if ARCH_R8A77970
......
...@@ -93,6 +93,7 @@ static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = { ...@@ -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("ether1", 64, R7S9210_CLK_B),
DEF_MOD_STB("ether0", 65, 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("i2c3", 84, R7S9210_CLK_P1),
DEF_MOD_STB("i2c2", 85, R7S9210_CLK_P1), DEF_MOD_STB("i2c2", 85, R7S9210_CLK_P1),
DEF_MOD_STB("i2c1", 86, R7S9210_CLK_P1), DEF_MOD_STB("i2c1", 86, R7S9210_CLK_P1),
......
...@@ -24,10 +24,10 @@ enum rcar_gen2_clk_types { ...@@ -24,10 +24,10 @@ enum rcar_gen2_clk_types {
}; };
struct rcar_gen2_cpg_pll_config { struct rcar_gen2_cpg_pll_config {
unsigned int extal_div; u8 extal_div;
unsigned int pll1_mult; u8 pll1_mult;
unsigned int pll3_mult; u8 pll3_mult;
unsigned int pll0_mult; /* leave as zero if PLL0CR exists */ u8 pll0_mult; /* leave as zero if PLL0CR exists */
}; };
struct clk *rcar_gen2_cpg_clk_register(struct device *dev, struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
......
...@@ -470,7 +470,8 @@ static struct clk * __init cpg_rpc_clk_register(const char *name, ...@@ -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, clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
&rpc->div.hw, &clk_divider_ops, &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)) { if (IS_ERR(clk)) {
kfree(rpc); kfree(rpc);
return clk; return clk;
...@@ -506,7 +507,8 @@ static struct clk * __init cpg_rpcd2_clk_register(const char *name, ...@@ -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, clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
&rpcd2->fixed.hw, &clk_fixed_factor_ops, &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)) if (IS_ERR(clk))
kfree(rpcd2); kfree(rpcd2);
......
...@@ -921,11 +921,26 @@ static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = { ...@@ -921,11 +921,26 @@ static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets), .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) static int sun50i_a64_ccu_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(&pdev->dev, res); reg = devm_ioremap_resource(&pdev->dev, res);
...@@ -939,7 +954,18 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) ...@@ -939,7 +954,18 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); 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[] = { static const struct of_device_id sun50i_a64_ccu_ids[] = {
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#define CLK_PLL_HSIC 18 #define CLK_PLL_HSIC 18
#define CLK_PLL_DE 19 #define CLK_PLL_DE 19
#define CLK_PLL_DDR1 20 #define CLK_PLL_DDR1 20
#define CLK_CPUX 21
#define CLK_AXI 22 #define CLK_AXI 22
#define CLK_APB 23 #define CLK_APB 23
#define CLK_AHB1 24 #define CLK_AHB1 24
......
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
/* The PLL_VIDEO1_2X clock is exported */ /* The PLL_VIDEO1_2X clock is exported */
#define CLK_PLL_GPU 14 #define CLK_PLL_GPU 14
#define CLK_PLL_MIPI 15
/* The PLL_VIDEO1_2X clock is exported */
#define CLK_PLL9 16 #define CLK_PLL9 16
#define CLK_PLL10 17 #define CLK_PLL10 17
......
...@@ -24,7 +24,9 @@ ...@@ -24,7 +24,9 @@
#define CLK_PLL_PERIPH 10 #define CLK_PLL_PERIPH 10
#define CLK_PLL_PERIPH_2X 11 #define CLK_PLL_PERIPH_2X 11
#define CLK_PLL_GPU 12 #define CLK_PLL_GPU 12
#define CLK_PLL_MIPI 13
/* The PLL MIPI clock is exported */
#define CLK_PLL_HSIC 14 #define CLK_PLL_HSIC 14
#define CLK_PLL_DE 15 #define CLK_PLL_DE 15
#define CLK_PLL_DDR1 16 #define CLK_PLL_DDR1 16
......
...@@ -55,10 +55,6 @@ ...@@ -55,10 +55,6 @@
/* Some more module clocks are exported */ /* Some more module clocks are exported */
#define CLK_MBUS 155
/* Another bunch of module clocks are exported */
#define CLK_NUMBER (CLK_OUTB + 1) #define CLK_NUMBER (CLK_OUTB + 1)
#endif /* _CCU_SUN8I_R40_H_ */ #endif /* _CCU_SUN8I_R40_H_ */
...@@ -37,7 +37,6 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) ...@@ -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 device_node *np = pdev->dev.of_node;
struct clk_onecell_data *clk_data; struct clk_onecell_data *clk_data;
const struct of_device_id *device;
const struct gates_data *data; const struct gates_data *data;
const char *clk_parent; const char *clk_parent;
const char *clk_name; const char *clk_name;
...@@ -50,10 +49,9 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) ...@@ -50,10 +49,9 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
if (!np) if (!np)
return -ENODEV; return -ENODEV;
device = of_match_device(sun6i_a31_apb0_gates_clk_dt_ids, &pdev->dev); data = of_device_get_match_data(&pdev->dev);
if (!device) if (!data)
return -ENODEV; return -ENODEV;
data = device->data;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(&pdev->dev, r); reg = devm_ioremap_resource(&pdev->dev, r);
......
...@@ -751,9 +751,9 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm) ...@@ -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); snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
hw = clk_hw_register_mux(dev, clk_name, hw = clk_hw_register_mux(dev, clk_name,
(const char *[]){ ((const char *[]){
parent, parent2, parent3, parent4 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, REG_DSI_10nm_PHY_CMN_CLK_CFG1,
0, 2, 0, NULL); 0, 2, 0, NULL);
if (IS_ERR(hw)) { if (IS_ERR(hw)) {
......
...@@ -554,9 +554,9 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm) ...@@ -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(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id); snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
clks[num++] = clk_register_mux(dev, clk_name, clks[num++] = clk_register_mux(dev, clk_name,
(const char *[]){ ((const char *[]){
parent1, parent2 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); REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id); snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
......
/* SPDX-License-Identifier: GPL-2.0 */
#define DDR_CLKID_DDR_PLL_DCO 0
#define DDR_CLKID_DDR_PLL 1
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define CLK_PLL_VIDEO0 7 #define CLK_PLL_VIDEO0 7
#define CLK_PLL_PERIPH0 11 #define CLK_PLL_PERIPH0 11
#define CLK_CPUX 21
#define CLK_BUS_MIPI_DSI 28 #define CLK_BUS_MIPI_DSI 28
#define CLK_BUS_CE 29 #define CLK_BUS_CE 29
#define CLK_BUS_DMA 30 #define CLK_BUS_DMA 30
......
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
#define CLK_PLL_VIDEO1_2X 13 #define CLK_PLL_VIDEO1_2X 13
#define CLK_PLL_MIPI 15
#define CLK_CPU 18 #define CLK_CPU 18
#define CLK_AHB1_MIPIDSI 23 #define CLK_AHB1_MIPIDSI 23
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#ifndef _DT_BINDINGS_CLK_SUN8I_A23_A33_H_ #ifndef _DT_BINDINGS_CLK_SUN8I_A23_A33_H_
#define _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_CPUX 18
#define CLK_BUS_MIPI_DSI 23 #define CLK_BUS_MIPI_DSI 23
......
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
#define CLK_AVS 152 #define CLK_AVS 152
#define CLK_HDMI 153 #define CLK_HDMI 153
#define CLK_HDMI_SLOW 154 #define CLK_HDMI_SLOW 154
#define CLK_MBUS 155
#define CLK_DSI_DPHY 156 #define CLK_DSI_DPHY 156
#define CLK_TVE0 157 #define CLK_TVE0 157
#define CLK_TVE1 158 #define CLK_TVE1 158
......
...@@ -328,29 +328,119 @@ struct clk_hw { ...@@ -328,29 +328,119 @@ struct clk_hw {
* struct clk_fixed_rate - fixed-rate clock * struct clk_fixed_rate - fixed-rate clock
* @hw: handle between common and hardware-specific interfaces * @hw: handle between common and hardware-specific interfaces
* @fixed_rate: constant frequency of clock * @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_fixed_rate {
struct clk_hw hw; struct clk_hw hw;
unsigned long fixed_rate; unsigned long fixed_rate;
unsigned long fixed_accuracy; 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; 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, struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
unsigned long fixed_rate); 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, * clk_hw_register_fixed_rate - register fixed-rate clock with the clock
unsigned long fixed_rate); * framework
struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, * @dev: device that is registering this clock
const char *name, const char *parent_name, unsigned long flags, * @name: name of this clock
unsigned long fixed_rate, unsigned long fixed_accuracy); * @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); 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 clk_hw_unregister_fixed_rate(struct clk_hw *hw);
void of_fixed_clk_setup(struct device_node *np); void of_fixed_clk_setup(struct device_node *np);
...@@ -393,14 +483,67 @@ struct clk_gate { ...@@ -393,14 +483,67 @@ struct clk_gate {
#define CLK_GATE_BIG_ENDIAN BIT(2) #define CLK_GATE_BIG_ENDIAN BIT(2)
extern const struct clk_ops clk_gate_ops; extern const struct clk_ops clk_gate_ops;
struct clk *clk_register_gate(struct device *dev, const char *name, struct clk_hw *__clk_hw_register_gate(struct device *dev,
const char *parent_name, unsigned long flags, 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, void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock); 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, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock); 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_unregister_gate(struct clk *clk);
void clk_hw_unregister_gate(struct clk_hw *hw); void clk_hw_unregister_gate(struct clk_hw *hw);
int clk_gate_is_enabled(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, ...@@ -490,24 +633,153 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
const struct clk_div_table *table, u8 width, const struct clk_div_table *table, u8 width,
unsigned long flags); unsigned long flags);
struct clk *clk_register_divider(struct device *dev, const char *name, struct clk_hw *__clk_hw_register_divider(struct device *dev,
const char *parent_name, unsigned long flags, struct device_node *np, const char *name,
void __iomem *reg, u8 shift, u8 width, const char *parent_name, const struct clk_hw *parent_hw,
u8 clk_divider_flags, spinlock_t *lock); const struct clk_parent_data *parent_data, unsigned long flags,
struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
const char *parent_name, unsigned long flags, const struct clk_div_table *table, spinlock_t *lock);
void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, spinlock_t *lock);
struct clk *clk_register_divider_table(struct device *dev, const char *name, struct clk *clk_register_divider_table(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, const struct clk_div_table *table, u8 clk_divider_flags, const struct clk_div_table *table,
spinlock_t *lock); spinlock_t *lock);
struct clk_hw *clk_hw_register_divider_table(struct device *dev, /**
const char *name, const char *parent_name, unsigned long flags, * clk_register_divider - register a divider clock with the clock framework
void __iomem *reg, u8 shift, u8 width, * @dev: device registering this clock
u8 clk_divider_flags, const struct clk_div_table *table, * @name: name of this clock
spinlock_t *lock); * @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_unregister_divider(struct clk *clk);
void clk_hw_unregister_divider(struct clk_hw *hw); void clk_hw_unregister_divider(struct clk_hw *hw);
...@@ -562,28 +834,48 @@ struct clk_mux { ...@@ -562,28 +834,48 @@ struct clk_mux {
extern const struct clk_ops clk_mux_ops; extern const struct clk_ops clk_mux_ops;
extern const struct clk_ops clk_mux_ro_ops; extern const struct clk_ops clk_mux_ro_ops;
struct clk *clk_register_mux(struct device *dev, const char *name, struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
const char * const *parent_names, u8 num_parents, const char *name, u8 num_parents,
unsigned long flags, const char * const *parent_names,
void __iomem *reg, u8 shift, u8 width, const struct clk_hw **parent_hws,
u8 clk_mux_flags, spinlock_t *lock); const struct clk_parent_data *parent_data,
struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
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,
u8 clk_mux_flags, u32 *table, spinlock_t *lock); 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, const char * const *parent_names, u8 num_parents,
unsigned long flags, unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock); 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, int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
unsigned int val); unsigned int val);
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index); 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, ...@@ -759,44 +1051,6 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
unsigned long flags); unsigned long flags);
void clk_hw_unregister_composite(struct clk_hw *hw); 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 *clk_register(struct device *dev, struct clk_hw *hw);
struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
......
...@@ -627,6 +627,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate); ...@@ -627,6 +627,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
* @clk: clock source * @clk: clock source
* @rate: desired clock rate in Hz * @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. * Returns success (0) or negative errno.
*/ */
int clk_set_rate(struct clk *clk, unsigned long rate); int clk_set_rate(struct clk *clk, unsigned long rate);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment