Update for meson clocks targeted at v4.21, round 2:

- Fix GXL HDMI Pll fractional bits (from first round)
 - Add the Meson8/Meson8b video clocks
 - Add clk-input helper and use it for axg-audio clock driver
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJcD9O0AAoJEHfc29rIyEnR12UQAId2Kix9fd1XCm7TSC0YIi7o
 w5Ld0a8Fu2lAQQQRwgZj6joFw3NXaUGPc7v5uHABJU4fVHA1JXDBoedTu2xTpIJ1
 pWXuyWustFRl+XKO339nJNwwDeVmTZ7+Lrt55RjGjMqvEPw5XZuhttZPzI/aa23i
 LRpswCcNOftWl3WHnfjLIUKeiMYbXB08vWUbHuzIDYfQ1MgeNWXmXkgIcUNilb9j
 55PGsjH/v9ZAhIU3BmUCJ4ZYg3llO7ywPqNP0EKqSAkIcgKOdqk2umyRUFHk1oTm
 YSDyYZQbd4PUBWx0fzI3c67l+DaONkBWasubzdIuioTJ8M9HW83IDbatiCLZM+Ze
 CpgZoh1z7rYkhEzl2ru1vq48R8GCa1cGzhOpEskJPX4huJSW8FnImchzKj8nvLhb
 VpCpUvnip4iJ4T4QA9ctBidi+T83sjLVxCB8HXQRFLRBODFajkoV6CuUlEy/a83b
 6jb+K6Ury9xmn+4tjthdQM92YsNymUP660QkFLdcUw/lSQX51r7Vwf6z7+NhFrd4
 f/Lib5QE6iuDEyCsCEkyDI6AzTt5OzlE9aBYCG79iWveMoy4GiotvqMLqaeIGN7p
 AgPRJDWK4J3tQrbQiFJeJhOa20qKtPFEnHAWYHWGqsp8FUGP7ICqSGy0BycMHa4X
 83qTBazbqYwcruGSWpfx
 =paYp
 -----END PGP SIGNATURE-----

Merge tag 'meson-clk-4.21-2' of https://github.com/BayLibre/clk-meson into clk-meson

Pull more meson clk driver updates from Neil Armstrong:

 - Fix GXL HDMI Pll fractional bits (from first round)
 - Add the Meson8/Meson8b video clocks
 - Add clk-input helper and use it for axg-audio clock driver

* tag 'meson-clk-4.21-2' of https://github.com/BayLibre/clk-meson:
  clk: meson: axg-audio: use the clk input helper function
  clk: meson: add clk-input helper function
  clk: meson: meson8b: add the read-only video clock trees
  clk: meson: meson8b: add the fractional divider for vid_pll_dco
  clk: meson: meson8b: fix the offset of vid_pll_dco's N value
  clk: meson: Fix GXL HDMI PLL fractional bits width
This commit is contained in:
Stephen Boyd 2018-12-13 01:05:44 -08:00
commit e74581b79d
7 changed files with 870 additions and 71 deletions

View File

@ -3,6 +3,7 @@
#
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-input.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO) += clk-triphase.o sclk-div.o
obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o

View File

@ -631,22 +631,23 @@ static struct clk_regmap *const axg_audio_clk_regmaps[] = {
&axg_tdmout_c_lrclk,
};
static struct clk *devm_clk_get_enable(struct device *dev, char *id)
static int devm_clk_get_enable(struct device *dev, char *id)
{
struct clk *clk;
int ret;
clk = devm_clk_get(dev, id);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) != -EPROBE_DEFER)
ret = PTR_ERR(clk);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get %s", id);
return clk;
return ret;
}
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "failed to enable %s", id);
return ERR_PTR(ret);
return ret;
}
ret = devm_add_action_or_reset(dev,
@ -654,74 +655,40 @@ static struct clk *devm_clk_get_enable(struct device *dev, char *id)
clk);
if (ret) {
dev_err(dev, "failed to add reset action on %s", id);
return ERR_PTR(ret);
return ret;
}
return clk;
}
static const struct clk_ops axg_clk_no_ops = {};
static struct clk_hw *axg_clk_hw_register_bypass(struct device *dev,
const char *name,
const char *parent_name)
{
struct clk_hw *hw;
struct clk_init_data init;
char *clk_name;
int ret;
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
clk_name = kasprintf(GFP_KERNEL, "axg_%s", name);
if (!clk_name)
return ERR_PTR(-ENOMEM);
init.name = clk_name;
init.ops = &axg_clk_no_ops;
init.flags = 0;
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
kfree(clk_name);
return ret ? ERR_PTR(ret) : hw;
return 0;
}
static int axg_register_clk_hw_input(struct device *dev,
const char *name,
unsigned int clkid)
{
struct clk *parent_clk = devm_clk_get(dev, name);
struct clk_hw *hw = NULL;
char *clk_name;
struct clk_hw *hw;
int err = 0;
if (IS_ERR(parent_clk)) {
int err = PTR_ERR(parent_clk);
clk_name = kasprintf(GFP_KERNEL, "axg_%s", name);
if (!clk_name)
return -ENOMEM;
hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
if (IS_ERR(hw)) {
/* It is ok if an input clock is missing */
if (err == -ENOENT) {
if (PTR_ERR(hw) == -ENOENT) {
dev_dbg(dev, "%s not provided", name);
} else {
err = PTR_ERR(hw);
if (err != -EPROBE_DEFER)
dev_err(dev, "failed to get %s clock", name);
return err;
}
} else {
hw = axg_clk_hw_register_bypass(dev, name,
__clk_get_name(parent_clk));
axg_audio_hw_onecell_data.hws[clkid] = hw;
}
if (IS_ERR(hw)) {
dev_err(dev, "failed to register %s clock", name);
return PTR_ERR(hw);
}
axg_audio_hw_onecell_data.hws[clkid] = hw;
return 0;
kfree(clk_name);
return err;
}
static int axg_register_clk_hw_inputs(struct device *dev,
@ -759,7 +726,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
struct regmap *map;
struct resource *res;
void __iomem *regs;
struct clk *clk;
struct clk_hw *hw;
int ret, i;
@ -775,9 +741,9 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
}
/* Get the mandatory peripheral clock */
clk = devm_clk_get_enable(dev, "pclk");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = devm_clk_get_enable(dev, "pclk");
if (ret)
return ret;
ret = device_reset(dev);
if (ret) {
@ -786,8 +752,7 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
}
/* Register the peripheral input clock */
hw = axg_clk_hw_register_bypass(dev, "audio_pclk",
__clk_get_name(clk));
hw = meson_clk_hw_register_input(dev, "pclk", "axg_audio_pclk", 0);
if (IS_ERR(hw))
return PTR_ERR(hw);

View File

@ -0,0 +1,44 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2018 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include "clkc.h"
static const struct clk_ops meson_clk_no_ops = {};
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags)
{
struct clk *parent_clk = devm_clk_get(dev, of_name);
struct clk_init_data init;
const char *parent_name;
struct clk_hw *hw;
int ret;
if (IS_ERR(parent_clk))
return (struct clk_hw *)parent_clk;
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
parent_name = __clk_get_name(parent_clk);
init.name = clk_name;
init.ops = &meson_clk_no_ops;
init.flags = flags;
init.parent_names = &parent_name;
init.num_parents = 1;
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
return ret ? ERR_PTR(ret) : hw;
}
EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);

View File

@ -119,4 +119,9 @@ extern const struct clk_ops meson_clk_mpll_ops;
extern const struct clk_ops meson_clk_phase_ops;
extern const struct clk_ops meson_vid_pll_div_ro_ops;
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags);
#endif /* __CLKC_H */

View File

@ -216,10 +216,16 @@ static struct clk_regmap gxl_hdmi_pll_dco = {
.shift = 9,
.width = 5,
},
/*
* On gxl, there is a register shift due to
* HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
* so we use the HHI_HDMI_PLL_CNTL2 define from GXBB
* instead which is defined at the same offset.
*/
.frac = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 0,
.width = 12,
.width = 10,
},
.l = {
.reg_off = HHI_HDMI_PLL_CNTL,

View File

@ -120,7 +120,7 @@ static struct clk_regmap meson8b_fixed_pll = {
},
};
static struct clk_regmap meson8b_vid_pll_dco = {
static struct clk_regmap meson8b_hdmi_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_VID_PLL_CNTL,
@ -134,9 +134,14 @@ static struct clk_regmap meson8b_vid_pll_dco = {
},
.n = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 9,
.shift = 10,
.width = 5,
},
.frac = {
.reg_off = HHI_VID_PLL_CNTL2,
.shift = 0,
.width = 12,
},
.l = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 31,
@ -149,14 +154,15 @@ static struct clk_regmap meson8b_vid_pll_dco = {
},
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_dco",
/* sometimes also called "HPLL" or "HPLL PLL" */
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
static struct clk_regmap meson8b_vid_pll = {
static struct clk_regmap meson8b_hdmi_pll_lvds_out = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_PLL_CNTL,
.shift = 16,
@ -164,9 +170,25 @@ static struct clk_regmap meson8b_vid_pll = {
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll",
.name = "hdmi_pll_lvds_out",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "vid_pll_dco" },
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_hdmi_pll_hdmi_out = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_PLL_CNTL,
.shift = 18,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_hdmi_out",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -925,6 +947,632 @@ static struct clk_regmap meson8b_l2_dram_clk_gate = {
},
};
static struct clk_regmap meson8b_vid_pll_in_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_DIVIDER_CNTL,
.mask = 0x1,
.shift = 15,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_in_sel",
.ops = &clk_regmap_mux_ro_ops,
/*
* TODO: depending on the SoC there is also a second parent:
* Meson8: unknown
* Meson8b: hdmi_pll_dco
* Meson8m2: vid2_pll
*/
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vid_pll_in_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_DIVIDER_CNTL,
.bit_idx = 16,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_in_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vid_pll_in_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vid_pll_pre_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_DIVIDER_CNTL,
.shift = 4,
.width = 3,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_pre_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "vid_pll_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vid_pll_post_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_DIVIDER_CNTL,
.shift = 12,
.width = 3,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_post_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "vid_pll_pre_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vid_pll = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_DIVIDER_CNTL,
.mask = 0x3,
.shift = 8,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll",
.ops = &clk_regmap_mux_ro_ops,
/* TODO: parent 0x2 is vid_pll_pre_div_mult7_div2 */
.parent_names = (const char *[]){ "vid_pll_pre_div",
"vid_pll_post_div" },
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vid_pll_final_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_CLK_DIV,
.shift = 0,
.width = 8,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll_final_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "vid_pll" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const char * const meson8b_vclk_mux_parents[] = {
"vid_pll_final_div", "fclk_div4", "fclk_div3", "fclk_div5",
"vid_pll_final_div", "fclk_div7", "mpll1"
};
static struct clk_regmap meson8b_vclk_in_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_CLK_CNTL,
.mask = 0x7,
.shift = 16,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_in_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk_in_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 16,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_in_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_in_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk_div1_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 0,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_div1_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "vclk_div2",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk_div2_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 1,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_div2_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_div2" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "vclk_div4",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk_div4_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 2,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_div4_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_div4" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk_div6_div = {
.mult = 1,
.div = 6,
.hw.init = &(struct clk_init_data){
.name = "vclk_div6",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk_div6_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 3,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_div6_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_div6" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk_div12_div = {
.mult = 1,
.div = 12,
.hw.init = &(struct clk_init_data){
.name = "vclk_div12",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk_div12_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.bit_idx = 4,
},
.hw.init = &(struct clk_init_data){
.name = "vclk_div12_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk_div12" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk2_in_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VIID_CLK_CNTL,
.mask = 0x7,
.shift = 16,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_in_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk2_clk_in_en = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 16,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_in_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_in_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_vclk2_div1_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 0,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_div1_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk2_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk2_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk2_div2_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 1,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_div2_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_div2" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk2_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk2_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk2_div4_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 2,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_div4_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_div4" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk2_div6_div = {
.mult = 1,
.div = 6,
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk2_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk2_div6_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 3,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_div6_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_div6" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor meson8b_vclk2_div12_div = {
.mult = 1,
.div = 12,
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "vclk2_in_en" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}
};
static struct clk_regmap meson8b_vclk2_div12_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VIID_CLK_DIV,
.bit_idx = 4,
},
.hw.init = &(struct clk_init_data){
.name = "vclk2_div12_en",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "vclk2_div12" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const char * const meson8b_vclk_enc_mux_parents[] = {
"vclk_div1_en", "vclk_div2_en", "vclk_div4_en", "vclk_div6_en",
"vclk_div12_en",
};
static struct clk_regmap meson8b_cts_enct_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_CLK_DIV,
.mask = 0xf,
.shift = 20,
},
.hw.init = &(struct clk_init_data){
.name = "cts_enct_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_enct = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 1,
},
.hw.init = &(struct clk_init_data){
.name = "cts_enct",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "cts_enct_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_encp_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_CLK_DIV,
.mask = 0xf,
.shift = 24,
},
.hw.init = &(struct clk_init_data){
.name = "cts_encp_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_encp = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 2,
},
.hw.init = &(struct clk_init_data){
.name = "cts_encp",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "cts_encp_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_enci_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VID_CLK_DIV,
.mask = 0xf,
.shift = 28,
},
.hw.init = &(struct clk_init_data){
.name = "cts_enci_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_enci = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 0,
},
.hw.init = &(struct clk_init_data){
.name = "cts_enci",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "cts_enci_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_hdmi_tx_pixel_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_HDMI_CLK_CNTL,
.mask = 0xf,
.shift = 16,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_tx_pixel_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_hdmi_tx_pixel = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 5,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_tx_pixel",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "hdmi_tx_pixel_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const char * const meson8b_vclk2_enc_mux_parents[] = {
"vclk2_div1_en", "vclk2_div2_en", "vclk2_div4_en", "vclk2_div6_en",
"vclk2_div12_en",
};
static struct clk_regmap meson8b_cts_encl_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VIID_CLK_DIV,
.mask = 0xf,
.shift = 12,
},
.hw.init = &(struct clk_init_data){
.name = "cts_encl_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk2_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_encl = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 3,
},
.hw.init = &(struct clk_init_data){
.name = "cts_encl",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "cts_encl_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_vdac0_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VIID_CLK_DIV,
.mask = 0xf,
.shift = 28,
},
.hw.init = &(struct clk_init_data){
.name = "cts_vdac0_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = meson8b_vclk2_enc_mux_parents,
.num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parents),
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_cts_vdac0 = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_CNTL2,
.bit_idx = 4,
},
.hw.init = &(struct clk_init_data){
.name = "cts_vdac0",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "cts_vdac0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_hdmi_sys_sel = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_HDMI_CLK_CNTL,
.mask = 0x3,
.shift = 9,
.flags = CLK_MUX_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_sys_sel",
.ops = &clk_regmap_mux_ro_ops,
/* FIXME: all other parents are unknown */
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_regmap meson8b_hdmi_sys_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_CLK_CNTL,
.shift = 0,
.width = 7,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_sys_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_sys_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_hdmi_sys = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_HDMI_CLK_CNTL,
.bit_idx = 8,
},
.hw.init = &(struct clk_init_data) {
.name = "hdmi_sys",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ "hdmi_sys_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
/* Everything Else (EE) domain gates */
static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@ -1124,7 +1772,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw,
[CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw,
[CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
[CLKID_PLL_VID_DCO] = &meson8b_vid_pll_dco.hw,
[CLKID_HDMI_PLL_DCO] = &meson8b_hdmi_pll_dco.hw,
[CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
[CLKID_CPU_CLK_DIV2] = &meson8b_cpu_clk_div2.hw,
[CLKID_CPU_CLK_DIV3] = &meson8b_cpu_clk_div3.hw,
@ -1141,6 +1789,50 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_AXI] = &meson8b_axi_clk_gate.hw,
[CLKID_L2_DRAM_SEL] = &meson8b_l2_dram_clk_sel.hw,
[CLKID_L2_DRAM] = &meson8b_l2_dram_clk_gate.hw,
[CLKID_HDMI_PLL_LVDS_OUT] = &meson8b_hdmi_pll_lvds_out.hw,
[CLKID_HDMI_PLL_HDMI_OUT] = &meson8b_hdmi_pll_hdmi_out.hw,
[CLKID_VID_PLL_IN_SEL] = &meson8b_vid_pll_in_sel.hw,
[CLKID_VID_PLL_IN_EN] = &meson8b_vid_pll_in_en.hw,
[CLKID_VID_PLL_PRE_DIV] = &meson8b_vid_pll_pre_div.hw,
[CLKID_VID_PLL_POST_DIV] = &meson8b_vid_pll_post_div.hw,
[CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw,
[CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw,
[CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw,
[CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw,
[CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw,
[CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw,
[CLKID_VCLK_DIV4_DIV] = &meson8b_vclk_div4_div.hw,
[CLKID_VCLK_DIV4] = &meson8b_vclk_div4_div_gate.hw,
[CLKID_VCLK_DIV6_DIV] = &meson8b_vclk_div6_div.hw,
[CLKID_VCLK_DIV6] = &meson8b_vclk_div6_div_gate.hw,
[CLKID_VCLK_DIV12_DIV] = &meson8b_vclk_div12_div.hw,
[CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw,
[CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw,
[CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw,
[CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw,
[CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw,
[CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw,
[CLKID_VCLK2_DIV4_DIV] = &meson8b_vclk2_div4_div.hw,
[CLKID_VCLK2_DIV4] = &meson8b_vclk2_div4_div_gate.hw,
[CLKID_VCLK2_DIV6_DIV] = &meson8b_vclk2_div6_div.hw,
[CLKID_VCLK2_DIV6] = &meson8b_vclk2_div6_div_gate.hw,
[CLKID_VCLK2_DIV12_DIV] = &meson8b_vclk2_div12_div.hw,
[CLKID_VCLK2_DIV12] = &meson8b_vclk2_div12_div_gate.hw,
[CLKID_CTS_ENCT_SEL] = &meson8b_cts_enct_sel.hw,
[CLKID_CTS_ENCT] = &meson8b_cts_enct.hw,
[CLKID_CTS_ENCP_SEL] = &meson8b_cts_encp_sel.hw,
[CLKID_CTS_ENCP] = &meson8b_cts_encp.hw,
[CLKID_CTS_ENCI_SEL] = &meson8b_cts_enci_sel.hw,
[CLKID_CTS_ENCI] = &meson8b_cts_enci.hw,
[CLKID_HDMI_TX_PIXEL_SEL] = &meson8b_hdmi_tx_pixel_sel.hw,
[CLKID_HDMI_TX_PIXEL] = &meson8b_hdmi_tx_pixel.hw,
[CLKID_CTS_ENCL_SEL] = &meson8b_cts_encl_sel.hw,
[CLKID_CTS_ENCL] = &meson8b_cts_encl.hw,
[CLKID_CTS_VDAC0_SEL] = &meson8b_cts_vdac0_sel.hw,
[CLKID_CTS_VDAC0] = &meson8b_cts_vdac0.hw,
[CLKID_HDMI_SYS_SEL] = &meson8b_hdmi_sys_sel.hw,
[CLKID_HDMI_SYS_DIV] = &meson8b_hdmi_sys_div.hw,
[CLKID_HDMI_SYS] = &meson8b_hdmi_sys.hw,
[CLK_NR_CLKS] = NULL,
},
.num = CLK_NR_CLKS,
@ -1234,7 +1926,6 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_mpll1_div,
&meson8b_mpll2_div,
&meson8b_fixed_pll,
&meson8b_vid_pll,
&meson8b_sys_pll,
&meson8b_cpu_in_sel,
&meson8b_cpu_scale_div,
@ -1250,7 +1941,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_nand_clk_div,
&meson8b_nand_clk_gate,
&meson8b_fixed_pll_dco,
&meson8b_vid_pll_dco,
&meson8b_hdmi_pll_dco,
&meson8b_sys_pll_dco,
&meson8b_abp_clk_sel,
&meson8b_abp_clk_gate,
@ -1260,6 +1951,43 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_axi_clk_gate,
&meson8b_l2_dram_clk_sel,
&meson8b_l2_dram_clk_gate,
&meson8b_hdmi_pll_lvds_out,
&meson8b_hdmi_pll_hdmi_out,
&meson8b_vid_pll_in_sel,
&meson8b_vid_pll_in_en,
&meson8b_vid_pll_pre_div,
&meson8b_vid_pll_post_div,
&meson8b_vid_pll,
&meson8b_vid_pll_final_div,
&meson8b_vclk_in_sel,
&meson8b_vclk_in_en,
&meson8b_vclk_div1_gate,
&meson8b_vclk_div2_div_gate,
&meson8b_vclk_div4_div_gate,
&meson8b_vclk_div6_div_gate,
&meson8b_vclk_div12_div_gate,
&meson8b_vclk2_in_sel,
&meson8b_vclk2_clk_in_en,
&meson8b_vclk2_div1_gate,
&meson8b_vclk2_div2_div_gate,
&meson8b_vclk2_div4_div_gate,
&meson8b_vclk2_div6_div_gate,
&meson8b_vclk2_div12_div_gate,
&meson8b_cts_enct_sel,
&meson8b_cts_enct,
&meson8b_cts_encp_sel,
&meson8b_cts_encp,
&meson8b_cts_enci_sel,
&meson8b_cts_enci,
&meson8b_hdmi_tx_pixel_sel,
&meson8b_hdmi_tx_pixel,
&meson8b_cts_encl_sel,
&meson8b_cts_encl,
&meson8b_cts_vdac0_sel,
&meson8b_cts_vdac0,
&meson8b_hdmi_sys_sel,
&meson8b_hdmi_sys_div,
&meson8b_hdmi_sys,
};
static const struct meson8b_clk_reset_line {

View File

@ -19,20 +19,26 @@
*
* [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
*/
#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
#define HHI_GCLK_MPEG0 0x140 /* 0x50 offset in data sheet */
#define HHI_GCLK_MPEG1 0x144 /* 0x51 offset in data sheet */
#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
#define HHI_GCLK_OTHER 0x150 /* 0x54 offset in data sheet */
#define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */
#define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */
#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
#define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */
#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
#define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */
#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */
#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
#define HHI_NAND_CLK_CNTL 0x25c /* 0x97 offset in data sheet */
#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */
#define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
#define HHI_VID_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
/*
* MPLL register offeset taken from the S905 datasheet. Vendor kernel source
@ -76,7 +82,7 @@
#define CLKID_NAND_SEL 110
#define CLKID_NAND_DIV 111
#define CLKID_PLL_FIXED_DCO 113
#define CLKID_PLL_VID_DCO 114
#define CLKID_HDMI_PLL_DCO 114
#define CLKID_PLL_SYS_DCO 115
#define CLKID_CPU_CLK_DIV2 116
#define CLKID_CPU_CLK_DIV3 117
@ -89,8 +95,52 @@
#define CLKID_PERIPH_SEL 125
#define CLKID_AXI_SEL 127
#define CLKID_L2_DRAM_SEL 129
#define CLKID_HDMI_PLL_LVDS_OUT 131
#define CLKID_HDMI_PLL_HDMI_OUT 132
#define CLKID_VID_PLL_IN_SEL 133
#define CLKID_VID_PLL_IN_EN 134
#define CLKID_VID_PLL_PRE_DIV 135
#define CLKID_VID_PLL_POST_DIV 136
#define CLKID_VID_PLL_FINAL_DIV 137
#define CLKID_VCLK_IN_SEL 138
#define CLKID_VCLK_IN_EN 139
#define CLKID_VCLK_DIV1 140
#define CLKID_VCLK_DIV2_DIV 141
#define CLKID_VCLK_DIV2 142
#define CLKID_VCLK_DIV4_DIV 143
#define CLKID_VCLK_DIV4 144
#define CLKID_VCLK_DIV6_DIV 145
#define CLKID_VCLK_DIV6 146
#define CLKID_VCLK_DIV12_DIV 147
#define CLKID_VCLK_DIV12 148
#define CLKID_VCLK2_IN_SEL 149
#define CLKID_VCLK2_IN_EN 150
#define CLKID_VCLK2_DIV1 151
#define CLKID_VCLK2_DIV2_DIV 152
#define CLKID_VCLK2_DIV2 153
#define CLKID_VCLK2_DIV4_DIV 154
#define CLKID_VCLK2_DIV4 155
#define CLKID_VCLK2_DIV6_DIV 156
#define CLKID_VCLK2_DIV6 157
#define CLKID_VCLK2_DIV12_DIV 158
#define CLKID_VCLK2_DIV12 159
#define CLKID_CTS_ENCT_SEL 160
#define CLKID_CTS_ENCT 161
#define CLKID_CTS_ENCP_SEL 162
#define CLKID_CTS_ENCP 163
#define CLKID_CTS_ENCI_SEL 164
#define CLKID_CTS_ENCI 165
#define CLKID_HDMI_TX_PIXEL_SEL 166
#define CLKID_HDMI_TX_PIXEL 167
#define CLKID_CTS_ENCL_SEL 168
#define CLKID_CTS_ENCL 169
#define CLKID_CTS_VDAC0_SEL 170
#define CLKID_CTS_VDAC0 171
#define CLKID_HDMI_SYS_SEL 172
#define CLKID_HDMI_SYS_DIV 173
#define CLKID_HDMI_SYS 174
#define CLK_NR_CLKS 131
#define CLK_NR_CLKS 175
/*
* include the CLKID and RESETID that have