Commit 31ef0917 authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'clk-meson-v5.6-1' of https://github.com/BayLibre/clk-meson into clk-amlogic

Pull Amlogic clk driver updates from Jerome Brunet:

 - Add meson8b DDR clock controller
 - Add input clocks to meson8b controllers
 - Fix meson8b mali clock update using the glitch free mux
 - Fix pll driver division by zero init

* tag 'clk-meson-v5.6-1' of https://github.com/BayLibre/clk-meson:
  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
parents e42617b8 64c76b31
# 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"
......
...@@ -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
......
/* SPDX-License-Identifier: GPL-2.0 */
#define DDR_CLKID_DDR_PLL_DCO 0
#define DDR_CLKID_DDR_PLL 1
...@@ -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