Commit 4946166e authored by Stephen Boyd's avatar Stephen Boyd

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

Pull amlogic meson clk driver updates from Neil Armstrong:

 - Add GX video clocks
 - Switch to HHI syscon for meson8b
 - Fix meson8b cpu clock
 - Add support for meson8b CPU scaling
 - Add Meson8b CPU post-dividers clocks

* tag 'meson-clk-4.21-1' of https://github.com/BayLibre/clk-meson:
  clk: meson: meson8b: add the CPU clock post divider clocks
  clk: meson: meson8b: rename cpu_div2/cpu_div3 to cpu_in_div2/cpu_in_div3
  clk: meson: clk-regmap: add read-only gate ops
  clk: meson: meson8b: allow changing the CPU clock tree
  clk: meson: meson8b: run from the XTAL when changing the CPU frequency
  clk: meson: meson8b: add support for more M/N values in sys_pll
  clk: meson: meson8b: mark the CPU clock as CLK_IS_CRITICAL
  clk: meson: meson8b: do not use cpu_div3 for cpu_scale_out_sel
  clk: meson: clk-pll: check if the clock is already enabled
  clk: meson: meson8b: fix the width of the cpu_scale_div clock
  clk: meson: meson8b: fix incorrect divider mapping in cpu_scale_table
  clk: meson: meson8b: use the HHI syscon if available
  dt-bindings: clock: meson8b: use the registers from the HHI syscon
  clk: meson-gxbb: Add video clocks
  dt-bindings: clk: meson-gxbb: Add Video clock bindings
  clk: meson-gxbb: Fix HDMI PLL for GXL SoCs
  clk: meson: Add vid_pll divider driver
  dt-bindings: clock: meson8b: export the CPU post dividers
parents 65102238 a7d19b05
......@@ -9,15 +9,13 @@ Required Properties:
- "amlogic,meson8-clkc" for Meson8 (S802) SoCs
- "amlogic,meson8b-clkc" for Meson8 (S805) SoCs
- "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
- reg: it must be composed by two tuples:
0) physical base address of the xtal register and length of memory
mapped region.
1) physical base address of the clock controller and length of memory
mapped region.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Parent node should have the following properties :
- compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
- reg: base address and size of the HHI system control register space.
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
......@@ -30,9 +28,8 @@ device tree sources).
Example: Clock controller node:
clkc: clock-controller@c1104000 {
clkc: clock-controller {
compatible = "amlogic,meson8b-clkc";
reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
#clock-cells = <1>;
#reset-cells = <1>;
};
......
......@@ -2,7 +2,7 @@
# Makefile for Meson specific clk
#
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.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
......
......@@ -200,11 +200,28 @@ static void meson_clk_pll_init(struct clk_hw *hw)
}
}
static int meson_clk_pll_is_enabled(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
if (meson_parm_read(clk->map, &pll->rst) ||
!meson_parm_read(clk->map, &pll->en) ||
!meson_parm_read(clk->map, &pll->l))
return 0;
return 1;
}
static int meson_clk_pll_enable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* do nothing if the PLL is already enabled */
if (clk_hw_is_enabled(hw))
return 0;
/* Make sure the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
......@@ -288,10 +305,12 @@ const struct clk_ops meson_clk_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate,
.is_enabled = meson_clk_pll_is_enabled,
.enable = meson_clk_pll_enable,
.disable = meson_clk_pll_disable
};
const struct clk_ops meson_clk_pll_ro_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
.is_enabled = meson_clk_pll_is_enabled,
};
......@@ -50,6 +50,11 @@ const struct clk_ops clk_regmap_gate_ops = {
};
EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
const struct clk_ops clk_regmap_gate_ro_ops = {
.is_enabled = clk_regmap_gate_is_enabled,
};
EXPORT_SYMBOL_GPL(clk_regmap_gate_ro_ops);
static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
......
......@@ -51,6 +51,7 @@ clk_get_regmap_gate_data(struct clk_regmap *clk)
}
extern const struct clk_ops clk_regmap_gate_ops;
extern const struct clk_ops clk_regmap_gate_ro_ops;
/**
* struct clk_regmap_div_data - regmap backed adjustable divider specific data
......
......@@ -90,6 +90,11 @@ struct meson_clk_phase_data {
int meson_clk_degrees_from_val(unsigned int val, unsigned int width);
unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width);
struct meson_vid_pll_div_data {
struct parm val;
struct parm sel;
};
#define MESON_GATE(_name, _reg, _bit) \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
......@@ -112,5 +117,6 @@ extern const struct clk_ops meson_clk_cpu_ops;
extern const struct clk_ops meson_clk_mpll_ro_ops;
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;
#endif /* __CLKC_H */
This diff is collapsed.
......@@ -165,8 +165,30 @@
#define CLKID_HDMI_PLL_OD2 163
#define CLKID_SYS_PLL_DCO 164
#define CLKID_GP0_PLL_DCO 165
#define NR_CLKS 166
#define CLKID_VID_PLL_SEL 167
#define CLKID_VID_PLL_DIV 168
#define CLKID_VCLK_SEL 169
#define CLKID_VCLK2_SEL 170
#define CLKID_VCLK_INPUT 171
#define CLKID_VCLK2_INPUT 172
#define CLKID_VCLK_DIV 173
#define CLKID_VCLK2_DIV 174
#define CLKID_VCLK_DIV2_EN 177
#define CLKID_VCLK_DIV4_EN 178
#define CLKID_VCLK_DIV6_EN 179
#define CLKID_VCLK_DIV12_EN 180
#define CLKID_VCLK2_DIV2_EN 181
#define CLKID_VCLK2_DIV4_EN 182
#define CLKID_VCLK2_DIV6_EN 183
#define CLKID_VCLK2_DIV12_EN 184
#define CLKID_CTS_ENCI_SEL 195
#define CLKID_CTS_ENCP_SEL 196
#define CLKID_CTS_VDAC_SEL 197
#define CLKID_HDMI_TX_SEL 198
#define CLKID_HDMI_SEL 203
#define CLKID_HDMI_DIV 204
#define NR_CLKS 206
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>
......
This diff is collapsed.
......@@ -63,8 +63,8 @@
#define CLKID_MPLL1_DIV 97
#define CLKID_MPLL2_DIV 98
#define CLKID_CPU_IN_SEL 99
#define CLKID_CPU_DIV2 100
#define CLKID_CPU_DIV3 101
#define CLKID_CPU_IN_DIV2 100
#define CLKID_CPU_IN_DIV3 101
#define CLKID_CPU_SCALE_DIV 102
#define CLKID_CPU_SCALE_OUT_SEL 103
#define CLKID_MPLL_PREDIV 104
......@@ -78,8 +78,19 @@
#define CLKID_PLL_FIXED_DCO 113
#define CLKID_PLL_VID_DCO 114
#define CLKID_PLL_SYS_DCO 115
#define CLKID_CPU_CLK_DIV2 116
#define CLKID_CPU_CLK_DIV3 117
#define CLKID_CPU_CLK_DIV4 118
#define CLKID_CPU_CLK_DIV5 119
#define CLKID_CPU_CLK_DIV6 120
#define CLKID_CPU_CLK_DIV7 121
#define CLKID_CPU_CLK_DIV8 122
#define CLKID_ABP_SEL 123
#define CLKID_PERIPH_SEL 125
#define CLKID_AXI_SEL 127
#define CLKID_L2_DRAM_SEL 129
#define CLK_NR_CLKS 116
#define CLK_NR_CLKS 131
/*
* include the CLKID and RESETID that have
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <linux/clk-provider.h>
#include "clkc.h"
static inline struct meson_vid_pll_div_data *
meson_vid_pll_div_data(struct clk_regmap *clk)
{
return (struct meson_vid_pll_div_data *)clk->data;
}
/*
* This vid_pll divided is a fully programmable fractionnal divider to
* achieve complex video clock rates.
*
* Here are provided the commonly used fraction values provided by Amlogic.
*/
struct vid_pll_div {
unsigned int shift_val;
unsigned int shift_sel;
unsigned int divider;
unsigned int multiplier;
};
#define VID_PLL_DIV(_val, _sel, _ft, _fb) \
{ \
.shift_val = (_val), \
.shift_sel = (_sel), \
.divider = (_ft), \
.multiplier = (_fb), \
}
static const struct vid_pll_div vid_pll_div_table[] = {
VID_PLL_DIV(0x0aaa, 0, 2, 1), /* 2/1 => /2 */
VID_PLL_DIV(0x5294, 2, 5, 2), /* 5/2 => /2.5 */
VID_PLL_DIV(0x0db6, 0, 3, 1), /* 3/1 => /3 */
VID_PLL_DIV(0x36cc, 1, 7, 2), /* 7/2 => /3.5 */
VID_PLL_DIV(0x6666, 2, 15, 4), /* 15/4 => /3.75 */
VID_PLL_DIV(0x0ccc, 0, 4, 1), /* 4/1 => /4 */
VID_PLL_DIV(0x739c, 2, 5, 1), /* 5/1 => /5 */
VID_PLL_DIV(0x0e38, 0, 6, 1), /* 6/1 => /6 */
VID_PLL_DIV(0x0000, 3, 25, 4), /* 25/4 => /6.25 */
VID_PLL_DIV(0x3c78, 1, 7, 1), /* 7/1 => /7 */
VID_PLL_DIV(0x78f0, 2, 15, 2), /* 15/2 => /7.5 */
VID_PLL_DIV(0x0fc0, 0, 12, 1), /* 12/1 => /12 */
VID_PLL_DIV(0x3f80, 1, 14, 1), /* 14/1 => /14 */
VID_PLL_DIV(0x7f80, 2, 15, 1), /* 15/1 => /15 */
};
#define to_meson_vid_pll_div(_hw) \
container_of(_hw, struct meson_vid_pll_div, hw)
const struct vid_pll_div *_get_table_val(unsigned int shift_val,
unsigned int shift_sel)
{
int i;
for (i = 0 ; i < ARRAY_SIZE(vid_pll_div_table) ; ++i) {
if (vid_pll_div_table[i].shift_val == shift_val &&
vid_pll_div_table[i].shift_sel == shift_sel)
return &vid_pll_div_table[i];
}
return NULL;
}
static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_vid_pll_div_data *pll_div = meson_vid_pll_div_data(clk);
const struct vid_pll_div *div;
div = _get_table_val(meson_parm_read(clk->map, &pll_div->val),
meson_parm_read(clk->map, &pll_div->sel));
if (!div || !div->divider) {
pr_info("%s: Invalid config value for vid_pll_div\n", __func__);
return parent_rate;
}
return DIV_ROUND_UP_ULL(parent_rate * div->multiplier, div->divider);
}
const struct clk_ops meson_vid_pll_div_ro_ops = {
.recalc_rate = meson_vid_pll_div_recalc_rate,
};
......@@ -128,5 +128,23 @@
#define CLKID_VDEC_1 153
#define CLKID_VDEC_HEVC 156
#define CLKID_GEN_CLK 159
#define CLKID_VID_PLL 166
#define CLKID_VCLK 175
#define CLKID_VCLK2 176
#define CLKID_VCLK_DIV1 185
#define CLKID_VCLK_DIV2 186
#define CLKID_VCLK_DIV4 187
#define CLKID_VCLK_DIV6 188
#define CLKID_VCLK_DIV12 189
#define CLKID_VCLK2_DIV1 190
#define CLKID_VCLK2_DIV2 191
#define CLKID_VCLK2_DIV4 192
#define CLKID_VCLK2_DIV6 193
#define CLKID_VCLK2_DIV12 194
#define CLKID_CTS_ENCI 199
#define CLKID_CTS_ENCP 200
#define CLKID_CTS_VDAC 201
#define CLKID_HDMI_TX 202
#define CLKID_HDMI 205
#endif /* __GXBB_CLKC_H */
......@@ -103,5 +103,9 @@
#define CLKID_MPLL1 94
#define CLKID_MPLL2 95
#define CLKID_NAND_CLK 112
#define CLKID_ABP 124
#define CLKID_PERIPH 126
#define CLKID_AXI 128
#define CLKID_L2_DRAM 130
#endif /* __MESON8B_CLKC_H */
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