mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
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
This commit is contained in:
commit
6e7a9f0c4e
@ -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>;
|
||||
};
|
||||
|
||||
...
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,46 +96,19 @@ 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);
|
||||
|
||||
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_hw *hw;
|
||||
|
||||
hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
|
||||
flags, fixed_rate, fixed_accuracy);
|
||||
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);
|
||||
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);
|
||||
struct clk_hw *hw;
|
||||
|
||||
hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
|
||||
flags, fixed_rate, 0);
|
||||
if (IS_ERR(hw))
|
||||
return ERR_CAST(hw);
|
||||
return hw->clk;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_register_fixed_rate);
|
||||
|
||||
@ -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 = {
|
||||
|
@ -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,
|
||||
|
@ -28,6 +28,26 @@
|
||||
* 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);
|
||||
err = devm_clk_hw_register(dev, hw);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (!err)
|
||||
return hw;
|
||||
|
||||
if (!dev) {
|
||||
kfree(clk_gpio);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
|
||||
|
||||
num_parents = of_clk_get_parent_count(node);
|
||||
if (is_mux && num_parents != 2) {
|
||||
dev_err(dev, "mux-clock must have 2 parents\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) ?
|
||||
|
@ -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,
|
||||
|
149
drivers/clk/meson/meson8-ddr.c
Normal file
149
drivers/clk/meson/meson8-ddr.c
Normal file
@ -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);
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -55,10 +55,6 @@
|
||||
|
||||
/* 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_ */
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
4
include/dt-bindings/clock/meson8-ddr-clkc.h
Normal file
4
include/dt-bindings/clock/meson8-ddr-clkc.h
Normal file
@ -0,0 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#define DDR_CLKID_DDR_PLL_DCO 0
|
||||
#define DDR_CLKID_DDR_PLL 1
|
@ -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
|
||||
|
@ -49,6 +49,8 @@
|
||||
|
||||
#define CLK_PLL_VIDEO1_2X 13
|
||||
|
||||
#define CLK_PLL_MIPI 15
|
||||
|
||||
#define CLK_CPU 18
|
||||
|
||||
#define CLK_AHB1_MIPIDSI 23
|
||||
|
@ -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
|
||||
|
@ -176,7 +176,7 @@
|
||||
#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
|
||||
|
@ -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_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 *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);
|
||||
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,
|
||||
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_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 *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);
|
||||
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,
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user