Merge branches 'clk-socfpga', 'clk-sophgo', 'clk-thead' and 'clk-samsung' into clk-next

* clk-socfpga:
  clk: socfpga: stratix10: Optimize local variables
  clk: socfpga: clk-pll: Optimize local variables

* clk-sophgo:
  clk: sophgo: Add clock controller support for SG2044 SoC
  clk: sophgo: Add PLL clock controller support for SG2044 SoC
  dt-bindings: clock: sophgo: add clock controller for SG2044
  dt-bindings: soc: sophgo: Add SG2044 top syscon device
  clk: sophgo: Add support for newly added precise compatible
  dt-bindings: clock: sophgo: Use precise compatible for CV1800 series SoC

* clk-thead:
  clk: thead: Add clock support for VO subsystem in T-HEAD TH1520 SoC
  dt-bindings: clock: thead: Add TH1520 VO clock controller

* clk-samsung:
  clk: samsung: correct clock summary for hsi1 block
  clk: samsung: exynosautov920: Fix incorrect CLKS_NR_CPUCL0 definition
  clk: samsung: exynosautov920: add cpucl1/2 clock support
  dt-bindings: clock: exynosautov920: add cpucl1/2 clock definitions
  clk: samsung: exynosautov920: add cpucl0 clock support
  dt-bindings: clock: exynosautov920: add cpucl0 clock definitions
  clk: samsung: Use samsung CCF common function
This commit is contained in:
Stephen Boyd
2025-05-29 00:30:28 -07:00
19 changed files with 3523 additions and 73 deletions
@@ -8,6 +8,7 @@ title: Samsung ExynosAuto v920 SoC clock controller
maintainers:
- Sunyeal Hong <sunyeal.hong@samsung.com>
- Shin Son <shin.son@samsung.com>
- Chanwoo Choi <cw00.choi@samsung.com>
- Krzysztof Kozlowski <krzk@kernel.org>
- Sylwester Nawrocki <s.nawrocki@samsung.com>
@@ -32,6 +33,9 @@ properties:
compatible:
enum:
- samsung,exynosautov920-cmu-top
- samsung,exynosautov920-cmu-cpucl0
- samsung,exynosautov920-cmu-cpucl1
- samsung,exynosautov920-cmu-cpucl2
- samsung,exynosautov920-cmu-peric0
- samsung,exynosautov920-cmu-peric1
- samsung,exynosautov920-cmu-misc
@@ -69,6 +73,71 @@ allOf:
items:
- const: oscclk
- if:
properties:
compatible:
contains:
enum:
- samsung,exynosautov920-cmu-cpucl0
then:
properties:
clocks:
items:
- description: External reference clock (38.4 MHz)
- description: CMU_CPUCL0 SWITCH clock (from CMU_TOP)
- description: CMU_CPUCL0 CLUSTER clock (from CMU_TOP)
- description: CMU_CPUCL0 DBG clock (from CMU_TOP)
clock-names:
items:
- const: oscclk
- const: switch
- const: cluster
- const: dbg
- if:
properties:
compatible:
contains:
enum:
- samsung,exynosautov920-cmu-cpucl1
then:
properties:
clocks:
items:
- description: External reference clock (38.4 MHz)
- description: CMU_CPUCL1 SWITCH clock (from CMU_TOP)
- description: CMU_CPUCL1 CLUSTER clock (from CMU_TOP)
clock-names:
items:
- const: oscclk
- const: switch
- const: cluster
- if:
properties:
compatible:
contains:
enum:
- samsung,exynosautov920-cmu-cpucl2
then:
properties:
clocks:
items:
- description: External reference clock (38.4 MHz)
- description: CMU_CPUCL2 SWITCH clock (from CMU_TOP)
- description: CMU_CPUCL2 CLUSTER clock (from CMU_TOP)
clock-names:
items:
- const: oscclk
- const: switch
- const: cluster
- if:
properties:
compatible:
@@ -11,10 +11,18 @@ maintainers:
properties:
compatible:
enum:
- sophgo,cv1800-clk
- sophgo,cv1810-clk
- sophgo,sg2000-clk
oneOf:
- enum:
- sophgo,cv1800b-clk
- sophgo,cv1812h-clk
- sophgo,sg2000-clk
- items:
- const: sophgo,sg2002-clk
- const: sophgo,sg2000-clk
- const: sophgo,cv1800-clk
deprecated: true
- const: sophgo,cv1810-clk
deprecated: true
reg:
maxItems: 1
@@ -0,0 +1,99 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/sophgo,sg2044-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo SG2044 Clock Controller
maintainers:
- Inochi Amaoto <inochiama@gmail.com>
description: |
The Sophgo SG2044 clock controller requires an external oscillator
as input clock.
All available clocks are defined as preprocessor macros in
include/dt-bindings/clock/sophgo,sg2044-clk.h
properties:
compatible:
const: sophgo,sg2044-clk
reg:
maxItems: 1
clocks:
items:
- description: fpll0
- description: fpll1
- description: fpll2
- description: dpll0
- description: dpll1
- description: dpll2
- description: dpll3
- description: dpll4
- description: dpll5
- description: dpll6
- description: dpll7
- description: mpll0
- description: mpll1
- description: mpll2
- description: mpll3
- description: mpll4
- description: mpll5
clock-names:
items:
- const: fpll0
- const: fpll1
- const: fpll2
- const: dpll0
- const: dpll1
- const: dpll2
- const: dpll3
- const: dpll4
- const: dpll5
- const: dpll6
- const: dpll7
- const: mpll0
- const: mpll1
- const: mpll2
- const: mpll3
- const: mpll4
- const: mpll5
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/sophgo,sg2044-pll.h>
clock-controller@50002000 {
compatible = "sophgo,sg2044-clk";
reg = <0x50002000 0x1000>;
#clock-cells = <1>;
clocks = <&syscon CLK_FPLL0>, <&syscon CLK_FPLL1>,
<&syscon CLK_FPLL2>, <&syscon CLK_DPLL0>,
<&syscon CLK_DPLL1>, <&syscon CLK_DPLL2>,
<&syscon CLK_DPLL3>, <&syscon CLK_DPLL4>,
<&syscon CLK_DPLL5>, <&syscon CLK_DPLL6>,
<&syscon CLK_DPLL7>, <&syscon CLK_MPLL0>,
<&syscon CLK_MPLL1>, <&syscon CLK_MPLL2>,
<&syscon CLK_MPLL3>, <&syscon CLK_MPLL4>,
<&syscon CLK_MPLL5>;
clock-names = "fpll0", "fpll1", "fpll2", "dpll0",
"dpll1", "dpll2", "dpll3", "dpll4",
"dpll5", "dpll6", "dpll7", "mpll0",
"mpll1", "mpll2", "mpll3", "mpll4",
"mpll5";
};
@@ -8,7 +8,8 @@ title: T-HEAD TH1520 AP sub-system clock controller
description: |
The T-HEAD TH1520 AP sub-system clock controller configures the
CPU, DPU, GMAC and TEE PLLs.
CPU, DPU, GMAC and TEE PLLs. Additionally the VO subsystem configures
the clock gates for the HDMI, MIPI and the GPU.
SoC reference manual
https://openbeagle.org/beaglev-ahead/beaglev-ahead/-/blob/main/docs/TH1520%20System%20User%20Manual.pdf
@@ -20,14 +21,24 @@ maintainers:
properties:
compatible:
const: thead,th1520-clk-ap
enum:
- thead,th1520-clk-ap
- thead,th1520-clk-vo
reg:
maxItems: 1
clocks:
items:
- description: main oscillator (24MHz)
- description: |
One input clock:
- For "thead,th1520-clk-ap": the clock input must be the 24 MHz
main oscillator.
- For "thead,th1520-clk-vo": the clock input must be the VIDEO_PLL,
which is configured by the AP clock controller. According to the
TH1520 manual, VIDEO_PLL is a Silicon Creations Sigma-Delta PLL
(integer PLL) typically running at 792 MHz (FOUTPOSTDIV), with
a maximum FOUTVCO of 2376 MHz.
"#clock-cells":
const: 1
@@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/sophgo/sophgo,sg2044-top-syscon.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo SG2044 SoC TOP system controller
maintainers:
- Inochi Amaoto <inochiama@gmail.com>
description:
The Sophgo SG2044 TOP system controller is a hardware block grouping
multiple small functions, such as clocks and some other internal
function.
properties:
compatible:
items:
- const: sophgo,sg2044-top-syscon
- const: syscon
reg:
maxItems: 1
clocks:
maxItems: 1
'#clock-cells':
const: 1
description:
See <dt-bindings/clock/sophgo,sg2044-pll.h> for valid clock.
required:
- compatible
- reg
- clocks
- '#clock-cells'
additionalProperties: false
examples:
- |
syscon@50000000 {
compatible = "sophgo,sg2044-top-syscon", "syscon";
reg = <0x50000000 0x1000>;
#clock-cells = <1>;
clocks = <&osc>;
};
+42 -32
View File
@@ -1269,6 +1269,45 @@ static const struct samsung_cpu_clock exynos4412_cpu_clks[] __initconst = {
CPUCLK_LAYOUT_E4210, e4412_armclk_d),
};
static const struct samsung_cmu_info cmu_info_exynos4 __initconst = {
.mux_clks = exynos4_mux_clks,
.nr_mux_clks = ARRAY_SIZE(exynos4_mux_clks),
.div_clks = exynos4_div_clks,
.nr_div_clks = ARRAY_SIZE(exynos4_div_clks),
.gate_clks = exynos4_gate_clks,
.nr_gate_clks = ARRAY_SIZE(exynos4_gate_clks),
.fixed_factor_clks = exynos4_fixed_factor_clks,
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4_fixed_factor_clks),
.fixed_clks = exynos4_fixed_rate_clks,
.nr_fixed_clks = ARRAY_SIZE(exynos4_fixed_rate_clks),
};
static const struct samsung_cmu_info cmu_info_exynos4210 __initconst = {
.mux_clks = exynos4210_mux_clks,
.nr_mux_clks = ARRAY_SIZE(exynos4210_mux_clks),
.div_clks = exynos4210_div_clks,
.nr_div_clks = ARRAY_SIZE(exynos4210_div_clks),
.gate_clks = exynos4210_gate_clks,
.nr_gate_clks = ARRAY_SIZE(exynos4210_gate_clks),
.fixed_factor_clks = exynos4210_fixed_factor_clks,
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4210_fixed_factor_clks),
.fixed_clks = exynos4210_fixed_rate_clks,
.nr_fixed_clks = ARRAY_SIZE(exynos4210_fixed_rate_clks),
.cpu_clks = exynos4210_cpu_clks,
.nr_cpu_clks = ARRAY_SIZE(exynos4210_cpu_clks),
};
static const struct samsung_cmu_info cmu_info_exynos4x12 __initconst = {
.mux_clks = exynos4x12_mux_clks,
.nr_mux_clks = ARRAY_SIZE(exynos4x12_mux_clks),
.div_clks = exynos4x12_div_clks,
.nr_div_clks = ARRAY_SIZE(exynos4x12_div_clks),
.gate_clks = exynos4x12_gate_clks,
.nr_gate_clks = ARRAY_SIZE(exynos4x12_gate_clks),
.fixed_factor_clks = exynos4x12_fixed_factor_clks,
.nr_fixed_factor_clks = ARRAY_SIZE(exynos4x12_fixed_factor_clks),
};
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
enum exynos4_soc soc)
@@ -1322,41 +1361,12 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4x12_plls));
}
samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(ctx, exynos4_mux_clks,
ARRAY_SIZE(exynos4_mux_clks));
samsung_clk_register_div(ctx, exynos4_div_clks,
ARRAY_SIZE(exynos4_div_clks));
samsung_clk_register_gate(ctx, exynos4_gate_clks,
ARRAY_SIZE(exynos4_gate_clks));
samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
ARRAY_SIZE(exynos4_fixed_factor_clks));
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4);
if (exynos4_soc == EXYNOS4210) {
samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
ARRAY_SIZE(exynos4210_fixed_rate_clks));
samsung_clk_register_mux(ctx, exynos4210_mux_clks,
ARRAY_SIZE(exynos4210_mux_clks));
samsung_clk_register_div(ctx, exynos4210_div_clks,
ARRAY_SIZE(exynos4210_div_clks));
samsung_clk_register_gate(ctx, exynos4210_gate_clks,
ARRAY_SIZE(exynos4210_gate_clks));
samsung_clk_register_fixed_factor(ctx,
exynos4210_fixed_factor_clks,
ARRAY_SIZE(exynos4210_fixed_factor_clks));
samsung_clk_register_cpu(ctx, exynos4210_cpu_clks,
ARRAY_SIZE(exynos4210_cpu_clks));
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4210);
} else {
samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks));
samsung_clk_register_div(ctx, exynos4x12_div_clks,
ARRAY_SIZE(exynos4x12_div_clks));
samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
ARRAY_SIZE(exynos4x12_gate_clks));
samsung_clk_register_fixed_factor(ctx,
exynos4x12_fixed_factor_clks,
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
samsung_cmu_register_clocks(ctx, &cmu_info_exynos4x12);
if (soc == EXYNOS4412)
samsung_clk_register_cpu(ctx, exynos4412_cpu_clks,
ARRAY_SIZE(exynos4412_cpu_clks));
+337 -1
View File
@@ -18,6 +18,9 @@
/* NOTE: Must be equal to the last clock ID increased by one */
#define CLKS_NR_TOP (DOUT_CLKCMU_TAA_NOC + 1)
#define CLKS_NR_CPUCL0 (CLK_DOUT_CPUCL0_NOCP + 1)
#define CLKS_NR_CPUCL1 (CLK_DOUT_CPUCL1_NOCP + 1)
#define CLKS_NR_CPUCL2 (CLK_DOUT_CPUCL2_NOCP + 1)
#define CLKS_NR_PERIC0 (CLK_DOUT_PERIC0_I3C + 1)
#define CLKS_NR_PERIC1 (CLK_DOUT_PERIC1_I3C + 1)
#define CLKS_NR_MISC (CLK_DOUT_MISC_OSC_DIV2 + 1)
@@ -1005,6 +1008,339 @@ static void __init exynosautov920_cmu_top_init(struct device_node *np)
CLK_OF_DECLARE(exynosautov920_cmu_top, "samsung,exynosautov920-cmu-top",
exynosautov920_cmu_top_init);
/* ---- CMU_CPUCL0 --------------------------------------------------------- */
/* Register Offset definitions for CMU_CPUCL0 (0x1EC00000) */
#define PLL_LOCKTIME_PLL_CPUCL0 0x0000
#define PLL_CON0_PLL_CPUCL0 0x0100
#define PLL_CON1_PLL_CPUCL0 0x0104
#define PLL_CON3_PLL_CPUCL0 0x010c
#define PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER 0x0600
#define PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER 0x0610
#define PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER 0x0620
#define CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER 0x1000
#define CLK_CON_MUX_MUX_CLK_CPUCL0_CORE 0x1004
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK 0x1800
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK 0x1804
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK 0x1808
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK 0x180c
#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK 0x1810
#define CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC 0x181c
#define CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG 0x1820
#define CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP 0x1824
static const unsigned long cpucl0_clk_regs[] __initconst = {
PLL_LOCKTIME_PLL_CPUCL0,
PLL_CON0_PLL_CPUCL0,
PLL_CON1_PLL_CPUCL0,
PLL_CON3_PLL_CPUCL0,
PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER,
PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER,
PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER,
CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER,
CLK_CON_MUX_MUX_CLK_CPUCL0_CORE,
CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK,
CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK,
CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC,
CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG,
CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP,
};
/* List of parent clocks for Muxes in CMU_CPUCL0 */
PNAME(mout_pll_cpucl0_p) = { "oscclk", "fout_cpucl0_pll" };
PNAME(mout_cpucl0_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl0_cluster" };
PNAME(mout_cpucl0_dbg_user_p) = { "oscclk", "dout_clkcmu_cpucl0_dbg" };
PNAME(mout_cpucl0_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl0_switch" };
PNAME(mout_cpucl0_cluster_p) = { "oscclk", "mout_cpucl0_cluster_user",
"mout_cpucl0_switch_user"};
PNAME(mout_cpucl0_core_p) = { "oscclk", "mout_pll_cpucl0",
"mout_cpucl0_switch_user"};
static const struct samsung_pll_rate_table cpu_pll_rates[] __initconst = {
PLL_35XX_RATE(38400000U, 2400000000U, 250, 4, 0),
PLL_35XX_RATE(38400000U, 2304000000U, 240, 4, 0),
PLL_35XX_RATE(38400000U, 2208000000U, 230, 4, 0),
PLL_35XX_RATE(38400000U, 2112000000U, 220, 4, 0),
PLL_35XX_RATE(38400000U, 2016000000U, 210, 4, 0),
PLL_35XX_RATE(38400000U, 1824000000U, 190, 4, 0),
PLL_35XX_RATE(38400000U, 1680000000U, 175, 4, 0),
PLL_35XX_RATE(38400000U, 1344000000U, 140, 4, 0),
PLL_35XX_RATE(38400000U, 1152000000U, 120, 4, 0),
PLL_35XX_RATE(38400000U, 576000000U, 120, 4, 1),
PLL_35XX_RATE(38400000U, 288000000U, 120, 4, 2),
};
static const struct samsung_pll_clock cpucl0_pll_clks[] __initconst = {
/* CMU_CPUCL0_PURECLKCOMP */
PLL(pll_531x, CLK_FOUT_CPUCL0_PLL, "fout_cpucl0_pll", "oscclk",
PLL_LOCKTIME_PLL_CPUCL0, PLL_CON3_PLL_CPUCL0, cpu_pll_rates),
};
static const struct samsung_mux_clock cpucl0_mux_clks[] __initconst = {
MUX(CLK_MOUT_PLL_CPUCL0, "mout_pll_cpucl0", mout_pll_cpucl0_p,
PLL_CON0_PLL_CPUCL0, 4, 1),
MUX(CLK_MOUT_CPUCL0_CLUSTER_USER, "mout_cpucl0_cluster_user", mout_cpucl0_cluster_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL0_CLUSTER_USER, 4, 1),
MUX(CLK_MOUT_CPUCL0_DBG_USER, "mout_cpucl0_dbg_user", mout_cpucl0_dbg_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER, 4, 1),
MUX(CLK_MOUT_CPUCL0_SWITCH_USER, "mout_cpucl0_switch_user", mout_cpucl0_switch_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER, 4, 1),
MUX(CLK_MOUT_CPUCL0_CLUSTER, "mout_cpucl0_cluster", mout_cpucl0_cluster_p,
CLK_CON_MUX_MUX_CLK_CPUCL0_CLUSTER, 0, 2),
MUX(CLK_MOUT_CPUCL0_CORE, "mout_cpucl0_core", mout_cpucl0_core_p,
CLK_CON_MUX_MUX_CLK_CPUCL0_CORE, 0, 2),
};
static const struct samsung_div_clock cpucl0_div_clks[] __initconst = {
DIV(CLK_DOUT_CLUSTER0_ACLK, "dout_cluster0_aclk",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK, 0, 4),
DIV(CLK_DOUT_CLUSTER0_ATCLK, "dout_cluster0_atclk",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER0_MPCLK, "dout_cluster0_mpclk",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_MPCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER0_PCLK, "dout_cluster0_pclk",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER0_PERIPHCLK, "dout_cluster0_periphclk",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK, 0, 4),
DIV(CLK_DOUT_CPUCL0_DBG_NOC, "dout_cpucl0_dbg_noc",
"mout_cpucl0_dbg_user", CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_NOC, 0, 3),
DIV(CLK_DOUT_CPUCL0_DBG_PCLKDBG, "dout_cpucl0_dbg_pclkdbg",
"mout_cpucl0_dbg_user", CLK_CON_DIV_DIV_CLK_CPUCL0_DBG_PCLKDBG, 0, 3),
DIV(CLK_DOUT_CPUCL0_NOCP, "dout_cpucl0_nocp",
"mout_cpucl0_cluster", CLK_CON_DIV_DIV_CLK_CPUCL0_NOCP, 0, 4),
};
static const struct samsung_cmu_info cpucl0_cmu_info __initconst = {
.pll_clks = cpucl0_pll_clks,
.nr_pll_clks = ARRAY_SIZE(cpucl0_pll_clks),
.mux_clks = cpucl0_mux_clks,
.nr_mux_clks = ARRAY_SIZE(cpucl0_mux_clks),
.div_clks = cpucl0_div_clks,
.nr_div_clks = ARRAY_SIZE(cpucl0_div_clks),
.nr_clk_ids = CLKS_NR_CPUCL0,
.clk_regs = cpucl0_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cpucl0_clk_regs),
.clk_name = "cpucl0",
};
static void __init exynosautov920_cmu_cpucl0_init(struct device_node *np)
{
exynos_arm64_register_cmu(NULL, np, &cpucl0_cmu_info);
}
/* Register CMU_CPUCL0 early, as CPU clocks should be available ASAP */
CLK_OF_DECLARE(exynosautov920_cmu_cpucl0, "samsung,exynosautov920-cmu-cpucl0",
exynosautov920_cmu_cpucl0_init);
/* ---- CMU_CPUCL1 --------------------------------------------------------- */
/* Register Offset definitions for CMU_CPUCL1 (0x1ED00000) */
#define PLL_LOCKTIME_PLL_CPUCL1 0x0000
#define PLL_CON0_PLL_CPUCL1 0x0100
#define PLL_CON1_PLL_CPUCL1 0x0104
#define PLL_CON3_PLL_CPUCL1 0x010c
#define PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER 0x0600
#define PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER 0x0610
#define CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER 0x1000
#define CLK_CON_MUX_MUX_CLK_CPUCL1_CORE 0x1004
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK 0x1800
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK 0x1804
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK 0x1808
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK 0x180c
#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK 0x1810
#define CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP 0x181c
static const unsigned long cpucl1_clk_regs[] __initconst = {
PLL_LOCKTIME_PLL_CPUCL1,
PLL_CON0_PLL_CPUCL1,
PLL_CON1_PLL_CPUCL1,
PLL_CON3_PLL_CPUCL1,
PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER,
PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER,
CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER,
CLK_CON_MUX_MUX_CLK_CPUCL1_CORE,
CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK,
CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK,
CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP,
};
/* List of parent clocks for Muxes in CMU_CPUCL1 */
PNAME(mout_pll_cpucl1_p) = { "oscclk", "fout_cpucl1_pll" };
PNAME(mout_cpucl1_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl1_cluster" };
PNAME(mout_cpucl1_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl1_switch" };
PNAME(mout_cpucl1_cluster_p) = { "oscclk", "mout_cpucl1_cluster_user",
"mout_cpucl1_switch_user"};
PNAME(mout_cpucl1_core_p) = { "oscclk", "mout_pll_cpucl1",
"mout_cpucl1_switch_user"};
static const struct samsung_pll_clock cpucl1_pll_clks[] __initconst = {
/* CMU_CPUCL1_PURECLKCOMP */
PLL(pll_531x, CLK_FOUT_CPUCL1_PLL, "fout_cpucl1_pll", "oscclk",
PLL_LOCKTIME_PLL_CPUCL1, PLL_CON3_PLL_CPUCL1, cpu_pll_rates),
};
static const struct samsung_mux_clock cpucl1_mux_clks[] __initconst = {
MUX(CLK_MOUT_PLL_CPUCL1, "mout_pll_cpucl1", mout_pll_cpucl1_p,
PLL_CON0_PLL_CPUCL1, 4, 1),
MUX(CLK_MOUT_CPUCL1_CLUSTER_USER, "mout_cpucl1_cluster_user", mout_cpucl1_cluster_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL1_CLUSTER_USER, 4, 1),
MUX(CLK_MOUT_CPUCL1_SWITCH_USER, "mout_cpucl1_switch_user", mout_cpucl1_switch_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER, 4, 1),
MUX(CLK_MOUT_CPUCL1_CLUSTER, "mout_cpucl1_cluster", mout_cpucl1_cluster_p,
CLK_CON_MUX_MUX_CLK_CPUCL1_CLUSTER, 0, 2),
MUX(CLK_MOUT_CPUCL1_CORE, "mout_cpucl1_core", mout_cpucl1_core_p,
CLK_CON_MUX_MUX_CLK_CPUCL1_CORE, 0, 2),
};
static const struct samsung_div_clock cpucl1_div_clks[] __initconst = {
DIV(CLK_DOUT_CLUSTER1_ACLK, "dout_cluster1_aclk",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK, 0, 4),
DIV(CLK_DOUT_CLUSTER1_ATCLK, "dout_cluster1_atclk",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER1_MPCLK, "dout_cluster1_mpclk",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_MPCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER1_PCLK, "dout_cluster1_pclk",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER1_PERIPHCLK, "dout_cluster1_periphclk",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK, 0, 4),
DIV(CLK_DOUT_CPUCL1_NOCP, "dout_cpucl1_nocp",
"mout_cpucl1_cluster", CLK_CON_DIV_DIV_CLK_CPUCL1_NOCP, 0, 4),
};
static const struct samsung_cmu_info cpucl1_cmu_info __initconst = {
.pll_clks = cpucl1_pll_clks,
.nr_pll_clks = ARRAY_SIZE(cpucl1_pll_clks),
.mux_clks = cpucl1_mux_clks,
.nr_mux_clks = ARRAY_SIZE(cpucl1_mux_clks),
.div_clks = cpucl1_div_clks,
.nr_div_clks = ARRAY_SIZE(cpucl1_div_clks),
.nr_clk_ids = CLKS_NR_CPUCL1,
.clk_regs = cpucl1_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cpucl1_clk_regs),
.clk_name = "cpucl1",
};
static void __init exynosautov920_cmu_cpucl1_init(struct device_node *np)
{
exynos_arm64_register_cmu(NULL, np, &cpucl1_cmu_info);
}
/* Register CMU_CPUCL1 early, as CPU clocks should be available ASAP */
CLK_OF_DECLARE(exynosautov920_cmu_cpucl1, "samsung,exynosautov920-cmu-cpucl1",
exynosautov920_cmu_cpucl1_init);
/* ---- CMU_CPUCL2 --------------------------------------------------------- */
/* Register Offset definitions for CMU_CPUCL2 (0x1EE00000) */
#define PLL_LOCKTIME_PLL_CPUCL2 0x0000
#define PLL_CON0_PLL_CPUCL2 0x0100
#define PLL_CON1_PLL_CPUCL2 0x0104
#define PLL_CON3_PLL_CPUCL2 0x010c
#define PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER 0x0600
#define PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER 0x0610
#define CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER 0x1000
#define CLK_CON_MUX_MUX_CLK_CPUCL2_CORE 0x1004
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK 0x1800
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK 0x1804
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK 0x1808
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK 0x180c
#define CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK 0x1810
#define CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP 0x181c
static const unsigned long cpucl2_clk_regs[] __initconst = {
PLL_LOCKTIME_PLL_CPUCL2,
PLL_CON0_PLL_CPUCL2,
PLL_CON1_PLL_CPUCL2,
PLL_CON3_PLL_CPUCL2,
PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER,
PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER,
CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER,
CLK_CON_MUX_MUX_CLK_CPUCL2_CORE,
CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK,
CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK,
CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK,
CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP,
};
/* List of parent clocks for Muxes in CMU_CPUCL2 */
PNAME(mout_pll_cpucl2_p) = { "oscclk", "fout_cpucl2_pll" };
PNAME(mout_cpucl2_cluster_user_p) = { "oscclk", "dout_clkcmu_cpucl2_cluster" };
PNAME(mout_cpucl2_switch_user_p) = { "oscclk", "dout_clkcmu_cpucl2_switch" };
PNAME(mout_cpucl2_cluster_p) = { "oscclk", "mout_cpucl2_cluster_user",
"mout_cpucl2_switch_user"};
PNAME(mout_cpucl2_core_p) = { "oscclk", "mout_pll_cpucl2",
"mout_cpucl2_switch_user"};
static const struct samsung_pll_clock cpucl2_pll_clks[] __initconst = {
/* CMU_CPUCL2_PURECLKCOMP */
PLL(pll_531x, CLK_FOUT_CPUCL2_PLL, "fout_cpucl2_pll", "oscclk",
PLL_LOCKTIME_PLL_CPUCL2, PLL_CON3_PLL_CPUCL2, cpu_pll_rates),
};
static const struct samsung_mux_clock cpucl2_mux_clks[] __initconst = {
MUX(CLK_MOUT_PLL_CPUCL2, "mout_pll_cpucl2", mout_pll_cpucl2_p,
PLL_CON0_PLL_CPUCL2, 4, 1),
MUX(CLK_MOUT_CPUCL2_CLUSTER_USER, "mout_cpucl2_cluster_user", mout_cpucl2_cluster_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL2_CLUSTER_USER, 4, 1),
MUX(CLK_MOUT_CPUCL2_SWITCH_USER, "mout_cpucl2_switch_user", mout_cpucl2_switch_user_p,
PLL_CON0_MUX_CLKCMU_CPUCL2_SWITCH_USER, 4, 1),
MUX(CLK_MOUT_CPUCL2_CLUSTER, "mout_cpucl2_cluster", mout_cpucl2_cluster_p,
CLK_CON_MUX_MUX_CLK_CPUCL2_CLUSTER, 0, 2),
MUX(CLK_MOUT_CPUCL2_CORE, "mout_cpucl2_core", mout_cpucl2_core_p,
CLK_CON_MUX_MUX_CLK_CPUCL2_CORE, 0, 2),
};
static const struct samsung_div_clock cpucl2_div_clks[] __initconst = {
DIV(CLK_DOUT_CLUSTER2_ACLK, "dout_cluster2_aclk",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_ACLK, 0, 4),
DIV(CLK_DOUT_CLUSTER2_ATCLK, "dout_cluster2_atclk",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_ATCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER2_MPCLK, "dout_cluster2_mpclk",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_MPCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER2_PCLK, "dout_cluster2_pclk",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_PCLK, 0, 4),
DIV(CLK_DOUT_CLUSTER2_PERIPHCLK, "dout_cluster2_periphclk",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CLUSTER2_PERIPHCLK, 0, 4),
DIV(CLK_DOUT_CPUCL2_NOCP, "dout_cpucl2_nocp",
"mout_cpucl2_cluster", CLK_CON_DIV_DIV_CLK_CPUCL2_NOCP, 0, 4),
};
static const struct samsung_cmu_info cpucl2_cmu_info __initconst = {
.pll_clks = cpucl2_pll_clks,
.nr_pll_clks = ARRAY_SIZE(cpucl2_pll_clks),
.mux_clks = cpucl2_mux_clks,
.nr_mux_clks = ARRAY_SIZE(cpucl2_mux_clks),
.div_clks = cpucl2_div_clks,
.nr_div_clks = ARRAY_SIZE(cpucl2_div_clks),
.nr_clk_ids = CLKS_NR_CPUCL2,
.clk_regs = cpucl2_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cpucl2_clk_regs),
.clk_name = "cpucl2",
};
static void __init exynosautov920_cmu_cpucl2_init(struct device_node *np)
{
exynos_arm64_register_cmu(NULL, np, &cpucl2_cmu_info);
}
/* Register CMU_CPUCL2 early, as CPU clocks should be available ASAP */
CLK_OF_DECLARE(exynosautov920_cmu_cpucl2, "samsung,exynosautov920-cmu-cpucl2",
exynosautov920_cmu_cpucl2_init);
/* ---- CMU_PERIC0 --------------------------------------------------------- */
/* Register Offset definitions for CMU_PERIC0 (0x10800000) */
@@ -1393,7 +1729,7 @@ static const unsigned long hsi1_clk_regs[] __initconst = {
/* List of parent clocks for Muxes in CMU_HSI1 */
PNAME(mout_hsi1_mmc_card_user_p) = {"oscclk", "dout_clkcmu_hsi1_mmc_card"};
PNAME(mout_hsi1_noc_user_p) = { "oscclk", "dout_clkcmu_hsi1_noc" };
PNAME(mout_hsi1_usbdrd_user_p) = { "oscclk", "mout_clkcmu_hsi1_usbdrd" };
PNAME(mout_hsi1_usbdrd_user_p) = { "oscclk", "dout_clkcmu_hsi1_usbdrd" };
PNAME(mout_hsi1_usbdrd_p) = { "dout_tcxo_div2", "mout_hsi1_usbdrd_user" };
static const struct samsung_mux_clock hsi1_mux_clks[] __initconst = {
+3 -3
View File
@@ -83,9 +83,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
unsigned long parent_rate)
{
struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
unsigned long mdiv;
unsigned long refdiv;
unsigned long reg;
u32 mdiv;
u32 refdiv;
u32 reg;
unsigned long long vco_freq;
/* read VCO1 reg for numerator and denominator */
+2 -2
View File
@@ -39,9 +39,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
unsigned long parent_rate)
{
struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
unsigned long divf, divq, reg;
u32 divf, divq, reg;
unsigned long long vco_freq;
unsigned long bypass;
u32 bypass;
reg = readl(socfpgaclk->hw.reg);
bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
+19
View File
@@ -37,3 +37,22 @@ config CLK_SOPHGO_SG2042_RPGATE
This clock IP depends on SG2042 Clock Generator because it uses
clock from Clock Generator IP as input.
This driver provides Gate function for RP.
config CLK_SOPHGO_SG2044
tristate "Sophgo SG2044 clock controller support"
depends on ARCH_SOPHGO || COMPILE_TEST
help
This driver supports the clock controller on the Sophgo SG2044
SoC. This controller requires mulitple PLL clock as input.
This clock control provides PLL clocks and common clock function
for various IPs on the SoC.
config CLK_SOPHGO_SG2044_PLL
tristate "Sophgo SG2044 PLL clock controller support"
depends on ARCH_SOPHGO || COMPILE_TEST
select MFD_SYSCON
select REGMAP_MMIO
help
This driver supports the PLL clock controller on the Sophgo
SG2044 SoC. This controller requires 25M oscillator as input.
This clock control provides PLL clocks on the SoC.
+2
View File
@@ -9,3 +9,5 @@ clk-sophgo-cv1800-y += clk-cv18xx-pll.o
obj-$(CONFIG_CLK_SOPHGO_SG2042_CLKGEN) += clk-sg2042-clkgen.o
obj-$(CONFIG_CLK_SOPHGO_SG2042_PLL) += clk-sg2042-pll.o
obj-$(CONFIG_CLK_SOPHGO_SG2042_RPGATE) += clk-sg2042-rpgate.o
obj-$(CONFIG_CLK_SOPHGO_SG2044) += clk-sg2044.o
obj-$(CONFIG_CLK_SOPHGO_SG2044_PLL) += clk-sg2044-pll.o
+2
View File
@@ -1519,7 +1519,9 @@ static int cv1800_clk_probe(struct platform_device *pdev)
static const struct of_device_id cv1800_clk_ids[] = {
{ .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc },
{ .compatible = "sophgo,cv1800b-clk", .data = &cv1800_desc },
{ .compatible = "sophgo,cv1810-clk", .data = &cv1810_desc },
{ .compatible = "sophgo,cv1812h-clk", .data = &cv1810_desc },
{ .compatible = "sophgo,sg2000-clk", .data = &sg2000_desc },
{ }
};
+628
View File
@@ -0,0 +1,628 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Sophgo SG2044 PLL clock controller driver
*
* Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com>
*/
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/math64.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <dt-bindings/clock/sophgo,sg2044-pll.h>
/* Low Control part */
#define PLL_VCOSEL_MASK GENMASK(17, 16)
/* High Control part */
#define PLL_FBDIV_MASK GENMASK(11, 0)
#define PLL_REFDIV_MASK GENMASK(17, 12)
#define PLL_POSTDIV1_MASK GENMASK(20, 18)
#define PLL_POSTDIV2_MASK GENMASK(23, 21)
#define PLL_CALIBRATE_EN BIT(24)
#define PLL_CALIBRATE_MASK GENMASK(29, 27)
#define PLL_CALIBRATE_DEFAULT FIELD_PREP(PLL_CALIBRATE_MASK, 2)
#define PLL_UPDATE_EN BIT(30)
#define PLL_HIGH_CTRL_MASK \
(PLL_FBDIV_MASK | PLL_REFDIV_MASK | \
PLL_POSTDIV1_MASK | PLL_POSTDIV2_MASK | \
PLL_CALIBRATE_EN | PLL_CALIBRATE_MASK | \
PLL_UPDATE_EN)
#define PLL_HIGH_CTRL_OFFSET 4
#define PLL_VCOSEL_1G6 0x2
#define PLL_VCOSEL_2G4 0x3
#define PLL_LIMIT_FOUTVCO 0
#define PLL_LIMIT_FOUT 1
#define PLL_LIMIT_REFDIV 2
#define PLL_LIMIT_FBDIV 3
#define PLL_LIMIT_POSTDIV1 4
#define PLL_LIMIT_POSTDIV2 5
#define for_each_pll_limit_range(_var, _limit) \
for (_var = (_limit)->min; _var <= (_limit)->max; _var++)
struct sg2044_pll_limit {
u64 min;
u64 max;
};
struct sg2044_pll_internal {
u32 ctrl_offset;
u32 status_offset;
u32 enable_offset;
u8 status_lock_bit;
u8 status_updating_bit;
u8 enable_bit;
const struct sg2044_pll_limit *limits;
};
struct sg2044_clk_common {
struct clk_hw hw;
struct regmap *regmap;
spinlock_t *lock;
unsigned int id;
};
struct sg2044_pll {
struct sg2044_clk_common common;
struct sg2044_pll_internal pll;
unsigned int syscon_offset;
};
struct sg2044_pll_desc_data {
struct sg2044_clk_common * const *pll;
u16 num_pll;
};
#define SG2044_SYSCON_PLL_OFFSET 0x98
struct sg2044_pll_ctrl {
spinlock_t lock;
struct clk_hw_onecell_data data;
};
#define hw_to_sg2044_clk_common(_hw) \
container_of((_hw), struct sg2044_clk_common, hw)
static inline bool sg2044_clk_fit_limit(u64 value,
const struct sg2044_pll_limit *limit)
{
return value >= limit->min && value <= limit->max;
}
static inline struct sg2044_pll *hw_to_sg2044_pll(struct clk_hw *hw)
{
return container_of(hw_to_sg2044_clk_common(hw),
struct sg2044_pll, common);
}
static unsigned long sg2044_pll_calc_vco_rate(unsigned long parent_rate,
unsigned long refdiv,
unsigned long fbdiv)
{
u64 numerator = parent_rate * fbdiv;
return div64_ul(numerator, refdiv);
}
static unsigned long sg2044_pll_calc_rate(unsigned long parent_rate,
unsigned long refdiv,
unsigned long fbdiv,
unsigned long postdiv1,
unsigned long postdiv2)
{
u64 numerator, denominator;
numerator = parent_rate * fbdiv;
denominator = refdiv * (postdiv1 + 1) * (postdiv2 + 1);
return div64_u64(numerator, denominator);
}
static unsigned long sg2044_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
u32 value;
int ret;
ret = regmap_read(pll->common.regmap,
pll->syscon_offset + pll->pll.ctrl_offset + PLL_HIGH_CTRL_OFFSET,
&value);
if (ret < 0)
return 0;
return sg2044_pll_calc_rate(parent_rate,
FIELD_GET(PLL_REFDIV_MASK, value),
FIELD_GET(PLL_FBDIV_MASK, value),
FIELD_GET(PLL_POSTDIV1_MASK, value),
FIELD_GET(PLL_POSTDIV2_MASK, value));
}
static bool pll_is_better_rate(unsigned long target, unsigned long now,
unsigned long best)
{
return abs_diff(target, now) < abs_diff(target, best);
}
static int sg2042_pll_compute_postdiv(const struct sg2044_pll_limit *limits,
unsigned long target,
unsigned long parent_rate,
unsigned int refdiv,
unsigned int fbdiv,
unsigned int *postdiv1,
unsigned int *postdiv2)
{
unsigned int div1, div2;
unsigned long tmp, best_rate = 0;
unsigned int best_div1 = 0, best_div2 = 0;
for_each_pll_limit_range(div2, &limits[PLL_LIMIT_POSTDIV2]) {
for_each_pll_limit_range(div1, &limits[PLL_LIMIT_POSTDIV1]) {
tmp = sg2044_pll_calc_rate(parent_rate,
refdiv, fbdiv,
div1, div2);
if (tmp > target)
continue;
if (pll_is_better_rate(target, tmp, best_rate)) {
best_div1 = div1;
best_div2 = div2;
best_rate = tmp;
if (tmp == target)
goto find;
}
}
}
find:
if (best_rate) {
*postdiv1 = best_div1;
*postdiv2 = best_div2;
return 0;
}
return -EINVAL;
}
static int sg2044_compute_pll_setting(const struct sg2044_pll_limit *limits,
unsigned long req_rate,
unsigned long parent_rate,
unsigned int *value)
{
unsigned int refdiv, fbdiv, postdiv1, postdiv2;
unsigned int best_refdiv, best_fbdiv, best_postdiv1, best_postdiv2;
unsigned long tmp, best_rate = 0;
int ret;
for_each_pll_limit_range(fbdiv, &limits[PLL_LIMIT_FBDIV]) {
for_each_pll_limit_range(refdiv, &limits[PLL_LIMIT_REFDIV]) {
u64 vco = sg2044_pll_calc_vco_rate(parent_rate,
refdiv, fbdiv);
if (!sg2044_clk_fit_limit(vco, &limits[PLL_LIMIT_FOUTVCO]))
continue;
ret = sg2042_pll_compute_postdiv(limits,
req_rate, parent_rate,
refdiv, fbdiv,
&postdiv1, &postdiv2);
if (ret)
continue;
tmp = sg2044_pll_calc_rate(parent_rate,
refdiv, fbdiv,
postdiv1, postdiv2);
if (pll_is_better_rate(req_rate, tmp, best_rate)) {
best_refdiv = refdiv;
best_fbdiv = fbdiv;
best_postdiv1 = postdiv1;
best_postdiv2 = postdiv2;
best_rate = tmp;
if (tmp == req_rate)
goto find;
}
}
}
find:
if (best_rate) {
*value = FIELD_PREP(PLL_REFDIV_MASK, best_refdiv) |
FIELD_PREP(PLL_FBDIV_MASK, best_fbdiv) |
FIELD_PREP(PLL_POSTDIV1_MASK, best_postdiv1) |
FIELD_PREP(PLL_POSTDIV2_MASK, best_postdiv2);
return 0;
}
return -EINVAL;
}
static int sg2044_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
unsigned int value;
u64 target;
int ret;
target = clamp(req->rate, pll->pll.limits[PLL_LIMIT_FOUT].min,
pll->pll.limits[PLL_LIMIT_FOUT].max);
ret = sg2044_compute_pll_setting(pll->pll.limits, target,
req->best_parent_rate, &value);
if (ret < 0)
return ret;
req->rate = sg2044_pll_calc_rate(req->best_parent_rate,
FIELD_GET(PLL_REFDIV_MASK, value),
FIELD_GET(PLL_FBDIV_MASK, value),
FIELD_GET(PLL_POSTDIV1_MASK, value),
FIELD_GET(PLL_POSTDIV2_MASK, value));
return 0;
}
static int sg2044_pll_poll_update(struct sg2044_pll *pll)
{
int ret;
unsigned int value;
ret = regmap_read_poll_timeout_atomic(pll->common.regmap,
pll->syscon_offset + pll->pll.status_offset,
value,
(value & BIT(pll->pll.status_lock_bit)),
1, 100000);
if (ret)
return ret;
return regmap_read_poll_timeout_atomic(pll->common.regmap,
pll->syscon_offset + pll->pll.status_offset,
value,
(!(value & BIT(pll->pll.status_updating_bit))),
1, 100000);
}
static int sg2044_pll_enable(struct sg2044_pll *pll, bool en)
{
if (en) {
if (sg2044_pll_poll_update(pll) < 0)
pr_warn("%s: fail to lock pll\n", clk_hw_get_name(&pll->common.hw));
return regmap_set_bits(pll->common.regmap,
pll->syscon_offset + pll->pll.enable_offset,
BIT(pll->pll.enable_bit));
}
return regmap_clear_bits(pll->common.regmap,
pll->syscon_offset + pll->pll.enable_offset,
BIT(pll->pll.enable_bit));
}
static int sg2044_pll_update_vcosel(struct sg2044_pll *pll, u64 rate)
{
unsigned int sel;
if (rate < U64_C(2400000000))
sel = PLL_VCOSEL_1G6;
else
sel = PLL_VCOSEL_2G4;
return regmap_write_bits(pll->common.regmap,
pll->syscon_offset + pll->pll.ctrl_offset,
PLL_VCOSEL_MASK,
FIELD_PREP(PLL_VCOSEL_MASK, sel));
}
static int sg2044_pll_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
unsigned int value;
u64 vco;
int ret;
ret = sg2044_compute_pll_setting(pll->pll.limits, rate,
parent_rate, &value);
if (ret < 0)
return ret;
vco = sg2044_pll_calc_vco_rate(parent_rate,
FIELD_GET(PLL_REFDIV_MASK, value),
FIELD_GET(PLL_FBDIV_MASK, value));
value |= PLL_CALIBRATE_EN;
value |= PLL_CALIBRATE_DEFAULT;
value |= PLL_UPDATE_EN;
guard(spinlock_irqsave)(pll->common.lock);
ret = sg2044_pll_enable(pll, false);
if (ret)
return ret;
sg2044_pll_update_vcosel(pll, vco);
regmap_write_bits(pll->common.regmap,
pll->syscon_offset + pll->pll.ctrl_offset +
PLL_HIGH_CTRL_OFFSET,
PLL_HIGH_CTRL_MASK, value);
sg2044_pll_enable(pll, true);
return ret;
}
static const struct clk_ops sg2044_pll_ops = {
.recalc_rate = sg2044_pll_recalc_rate,
.determine_rate = sg2044_pll_determine_rate,
.set_rate = sg2044_pll_set_rate,
};
static const struct clk_ops sg2044_pll_ro_ops = {
.recalc_rate = sg2044_pll_recalc_rate,
};
#define SG2044_CLK_COMMON_PDATA(_id, _name, _parents, _op, _flags) \
{ \
.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents, \
_op, (_flags)), \
.id = (_id), \
}
#define DEFINE_SG2044_PLL(_id, _name, _parent, _flags, \
_ctrl_offset, \
_status_offset, _status_lock_bit, \
_status_updating_bit, \
_enable_offset, _enable_bit, \
_limits) \
struct sg2044_pll _name = { \
.common = SG2044_CLK_COMMON_PDATA(_id, #_name, _parent, \
&sg2044_pll_ops, \
(_flags)), \
.pll = { \
.ctrl_offset = (_ctrl_offset), \
.status_offset = (_status_offset), \
.enable_offset = (_enable_offset), \
.status_lock_bit = (_status_lock_bit), \
.status_updating_bit = (_status_updating_bit), \
.enable_bit = (_enable_bit), \
.limits = (_limits), \
}, \
}
#define DEFINE_SG2044_PLL_RO(_id, _name, _parent, _flags, \
_ctrl_offset, \
_status_offset, _status_lock_bit, \
_status_updating_bit, \
_enable_offset, _enable_bit, \
_limits) \
struct sg2044_pll _name = { \
.common = SG2044_CLK_COMMON_PDATA(_id, #_name, _parent, \
&sg2044_pll_ro_ops, \
(_flags)), \
.pll = { \
.ctrl_offset = (_ctrl_offset), \
.status_offset = (_status_offset), \
.enable_offset = (_enable_offset), \
.status_lock_bit = (_status_lock_bit), \
.status_updating_bit = (_status_updating_bit), \
.enable_bit = (_enable_bit), \
.limits = (_limits), \
}, \
}
static const struct clk_parent_data osc_parents[] = {
{ .index = 0 },
};
static const struct sg2044_pll_limit pll_limits[] = {
[PLL_LIMIT_FOUTVCO] = {
.min = U64_C(1600000000),
.max = U64_C(3200000000),
},
[PLL_LIMIT_FOUT] = {
.min = U64_C(25000),
.max = U64_C(3200000000),
},
[PLL_LIMIT_REFDIV] = {
.min = U64_C(1),
.max = U64_C(63),
},
[PLL_LIMIT_FBDIV] = {
.min = U64_C(8),
.max = U64_C(1066),
},
[PLL_LIMIT_POSTDIV1] = {
.min = U64_C(0),
.max = U64_C(7),
},
[PLL_LIMIT_POSTDIV2] = {
.min = U64_C(0),
.max = U64_C(7),
},
};
static DEFINE_SG2044_PLL_RO(CLK_FPLL0, clk_fpll0, osc_parents, CLK_IS_CRITICAL,
0x58, 0x00, 22, 6,
0x04, 6, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_FPLL1, clk_fpll1, osc_parents, CLK_IS_CRITICAL,
0x60, 0x00, 23, 7,
0x04, 7, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_FPLL2, clk_fpll2, osc_parents, CLK_IS_CRITICAL,
0x20, 0x08, 16, 0,
0x0c, 0, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL0, clk_dpll0, osc_parents, CLK_IS_CRITICAL,
0x68, 0x00, 24, 8,
0x04, 8, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL1, clk_dpll1, osc_parents, CLK_IS_CRITICAL,
0x70, 0x00, 25, 9,
0x04, 9, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL2, clk_dpll2, osc_parents, CLK_IS_CRITICAL,
0x78, 0x00, 26, 10,
0x04, 10, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL3, clk_dpll3, osc_parents, CLK_IS_CRITICAL,
0x80, 0x00, 27, 11,
0x04, 11, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL4, clk_dpll4, osc_parents, CLK_IS_CRITICAL,
0x88, 0x00, 28, 12,
0x04, 12, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL5, clk_dpll5, osc_parents, CLK_IS_CRITICAL,
0x90, 0x00, 29, 13,
0x04, 13, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL6, clk_dpll6, osc_parents, CLK_IS_CRITICAL,
0x98, 0x00, 30, 14,
0x04, 14, pll_limits);
static DEFINE_SG2044_PLL_RO(CLK_DPLL7, clk_dpll7, osc_parents, CLK_IS_CRITICAL,
0xa0, 0x00, 31, 15,
0x04, 15, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL0, clk_mpll0, osc_parents, CLK_IS_CRITICAL,
0x28, 0x00, 16, 0,
0x04, 0, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL1, clk_mpll1, osc_parents, CLK_IS_CRITICAL,
0x30, 0x00, 17, 1,
0x04, 1, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL2, clk_mpll2, osc_parents, CLK_IS_CRITICAL,
0x38, 0x00, 18, 2,
0x04, 2, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL3, clk_mpll3, osc_parents, CLK_IS_CRITICAL,
0x40, 0x00, 19, 3,
0x04, 3, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL4, clk_mpll4, osc_parents, CLK_IS_CRITICAL,
0x48, 0x00, 20, 4,
0x04, 4, pll_limits);
static DEFINE_SG2044_PLL(CLK_MPLL5, clk_mpll5, osc_parents, CLK_IS_CRITICAL,
0x50, 0x00, 21, 5,
0x04, 5, pll_limits);
static struct sg2044_clk_common * const sg2044_pll_commons[] = {
&clk_fpll0.common,
&clk_fpll1.common,
&clk_fpll2.common,
&clk_dpll0.common,
&clk_dpll1.common,
&clk_dpll2.common,
&clk_dpll3.common,
&clk_dpll4.common,
&clk_dpll5.common,
&clk_dpll6.common,
&clk_dpll7.common,
&clk_mpll0.common,
&clk_mpll1.common,
&clk_mpll2.common,
&clk_mpll3.common,
&clk_mpll4.common,
&clk_mpll5.common,
};
static int sg2044_pll_init_ctrl(struct device *dev, struct regmap *regmap,
struct sg2044_pll_ctrl *ctrl,
const struct sg2044_pll_desc_data *desc)
{
int ret, i;
spin_lock_init(&ctrl->lock);
for (i = 0; i < desc->num_pll; i++) {
struct sg2044_clk_common *common = desc->pll[i];
struct sg2044_pll *pll = hw_to_sg2044_pll(&common->hw);
common->lock = &ctrl->lock;
common->regmap = regmap;
pll->syscon_offset = SG2044_SYSCON_PLL_OFFSET;
ret = devm_clk_hw_register(dev, &common->hw);
if (ret)
return ret;
ctrl->data.hws[common->id] = &common->hw;
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
&ctrl->data);
}
static int sg2044_pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sg2044_pll_ctrl *ctrl;
const struct sg2044_pll_desc_data *desc;
struct regmap *regmap;
regmap = device_node_to_regmap(pdev->dev.parent->of_node);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"fail to get the regmap for PLL\n");
desc = (const struct sg2044_pll_desc_data *)platform_get_device_id(pdev)->driver_data;
if (!desc)
return dev_err_probe(dev, -EINVAL, "no match data for platform\n");
ctrl = devm_kzalloc(dev, struct_size(ctrl, data.hws, desc->num_pll), GFP_KERNEL);
if (!ctrl)
return -ENOMEM;
ctrl->data.num = desc->num_pll;
return sg2044_pll_init_ctrl(dev, regmap, ctrl, desc);
}
static const struct sg2044_pll_desc_data sg2044_pll_desc_data = {
.pll = sg2044_pll_commons,
.num_pll = ARRAY_SIZE(sg2044_pll_commons),
};
static const struct platform_device_id sg2044_pll_match[] = {
{ .name = "sg2044-pll",
.driver_data = (unsigned long)&sg2044_pll_desc_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, sg2044_pll_match);
static struct platform_driver sg2044_clk_driver = {
.probe = sg2044_pll_probe,
.driver = {
.name = "sg2044-pll",
},
.id_table = sg2044_pll_match,
};
module_platform_driver(sg2044_clk_driver);
MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>");
MODULE_DESCRIPTION("Sophgo SG2044 pll clock driver");
MODULE_LICENSE("GPL");
File diff suppressed because it is too large Load Diff
+168 -28
View File
@@ -847,6 +847,67 @@ static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, BIT(3), 0);
static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, BIT(2), 0);
static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, BIT(1), 0);
static CCU_GATE(CLK_AXI4_VO_ACLK, axi4_vo_aclk, "axi4-vo-aclk",
video_pll_clk_pd, 0x0, BIT(0), 0);
static CCU_GATE(CLK_GPU_CORE, gpu_core_clk, "gpu-core-clk", video_pll_clk_pd,
0x0, BIT(3), 0);
static CCU_GATE(CLK_GPU_CFG_ACLK, gpu_cfg_aclk, "gpu-cfg-aclk",
video_pll_clk_pd, 0x0, BIT(4), 0);
static CCU_GATE(CLK_DPU_PIXELCLK0, dpu0_pixelclk, "dpu0-pixelclk",
video_pll_clk_pd, 0x0, BIT(5), 0);
static CCU_GATE(CLK_DPU_PIXELCLK1, dpu1_pixelclk, "dpu1-pixelclk",
video_pll_clk_pd, 0x0, BIT(6), 0);
static CCU_GATE(CLK_DPU_HCLK, dpu_hclk, "dpu-hclk", video_pll_clk_pd, 0x0,
BIT(7), 0);
static CCU_GATE(CLK_DPU_ACLK, dpu_aclk, "dpu-aclk", video_pll_clk_pd, 0x0,
BIT(8), 0);
static CCU_GATE(CLK_DPU_CCLK, dpu_cclk, "dpu-cclk", video_pll_clk_pd, 0x0,
BIT(9), 0);
static CCU_GATE(CLK_HDMI_SFR, hdmi_sfr_clk, "hdmi-sfr-clk", video_pll_clk_pd,
0x0, BIT(10), 0);
static CCU_GATE(CLK_HDMI_PCLK, hdmi_pclk, "hdmi-pclk", video_pll_clk_pd, 0x0,
BIT(11), 0);
static CCU_GATE(CLK_HDMI_CEC, hdmi_cec_clk, "hdmi-cec-clk", video_pll_clk_pd,
0x0, BIT(12), 0);
static CCU_GATE(CLK_MIPI_DSI0_PCLK, mipi_dsi0_pclk, "mipi-dsi0-pclk",
video_pll_clk_pd, 0x0, BIT(13), 0);
static CCU_GATE(CLK_MIPI_DSI1_PCLK, mipi_dsi1_pclk, "mipi-dsi1-pclk",
video_pll_clk_pd, 0x0, BIT(14), 0);
static CCU_GATE(CLK_MIPI_DSI0_CFG, mipi_dsi0_cfg_clk, "mipi-dsi0-cfg-clk",
video_pll_clk_pd, 0x0, BIT(15), 0);
static CCU_GATE(CLK_MIPI_DSI1_CFG, mipi_dsi1_cfg_clk, "mipi-dsi1-cfg-clk",
video_pll_clk_pd, 0x0, BIT(16), 0);
static CCU_GATE(CLK_MIPI_DSI0_REFCLK, mipi_dsi0_refclk, "mipi-dsi0-refclk",
video_pll_clk_pd, 0x0, BIT(17), 0);
static CCU_GATE(CLK_MIPI_DSI1_REFCLK, mipi_dsi1_refclk, "mipi-dsi1-refclk",
video_pll_clk_pd, 0x0, BIT(18), 0);
static CCU_GATE(CLK_HDMI_I2S, hdmi_i2s_clk, "hdmi-i2s-clk", video_pll_clk_pd,
0x0, BIT(19), 0);
static CCU_GATE(CLK_X2H_DPU1_ACLK, x2h_dpu1_aclk, "x2h-dpu1-aclk",
video_pll_clk_pd, 0x0, BIT(20), 0);
static CCU_GATE(CLK_X2H_DPU_ACLK, x2h_dpu_aclk, "x2h-dpu-aclk",
video_pll_clk_pd, 0x0, BIT(21), 0);
static CCU_GATE(CLK_AXI4_VO_PCLK, axi4_vo_pclk, "axi4-vo-pclk",
video_pll_clk_pd, 0x0, BIT(22), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_DPU_PCLK, iopmp_vosys_dpu_pclk,
"iopmp-vosys-dpu-pclk", video_pll_clk_pd, 0x0, BIT(23), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_DPU1_PCLK, iopmp_vosys_dpu1_pclk,
"iopmp-vosys-dpu1-pclk", video_pll_clk_pd, 0x0, BIT(24), 0);
static CCU_GATE(CLK_IOPMP_VOSYS_GPU_PCLK, iopmp_vosys_gpu_pclk,
"iopmp-vosys-gpu-pclk", video_pll_clk_pd, 0x0, BIT(25), 0);
static CCU_GATE(CLK_IOPMP_DPU1_ACLK, iopmp_dpu1_aclk, "iopmp-dpu1-aclk",
video_pll_clk_pd, 0x0, BIT(27), 0);
static CCU_GATE(CLK_IOPMP_DPU_ACLK, iopmp_dpu_aclk, "iopmp-dpu-aclk",
video_pll_clk_pd, 0x0, BIT(28), 0);
static CCU_GATE(CLK_IOPMP_GPU_ACLK, iopmp_gpu_aclk, "iopmp-gpu-aclk",
video_pll_clk_pd, 0x0, BIT(29), 0);
static CCU_GATE(CLK_MIPIDSI0_PIXCLK, mipi_dsi0_pixclk, "mipi-dsi0-pixclk",
video_pll_clk_pd, 0x0, BIT(30), 0);
static CCU_GATE(CLK_MIPIDSI1_PIXCLK, mipi_dsi1_pixclk, "mipi-dsi1-pixclk",
video_pll_clk_pd, 0x0, BIT(31), 0);
static CCU_GATE(CLK_HDMI_PIXCLK, hdmi_pixclk, "hdmi-pixclk", video_pll_clk_pd,
0x4, BIT(0), 0);
static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m",
&gmac_pll_clk.common.hw, 10, 1, 0);
@@ -963,7 +1024,38 @@ static struct ccu_common *th1520_gate_clks[] = {
&sram3_clk.common,
};
#define NR_CLKS (CLK_UART_SCLK + 1)
static struct ccu_common *th1520_vo_gate_clks[] = {
&axi4_vo_aclk.common,
&gpu_core_clk.common,
&gpu_cfg_aclk.common,
&dpu0_pixelclk.common,
&dpu1_pixelclk.common,
&dpu_hclk.common,
&dpu_aclk.common,
&dpu_cclk.common,
&hdmi_sfr_clk.common,
&hdmi_pclk.common,
&hdmi_cec_clk.common,
&mipi_dsi0_pclk.common,
&mipi_dsi1_pclk.common,
&mipi_dsi0_cfg_clk.common,
&mipi_dsi1_cfg_clk.common,
&mipi_dsi0_refclk.common,
&mipi_dsi1_refclk.common,
&hdmi_i2s_clk.common,
&x2h_dpu1_aclk.common,
&x2h_dpu_aclk.common,
&axi4_vo_pclk.common,
&iopmp_vosys_dpu_pclk.common,
&iopmp_vosys_dpu1_pclk.common,
&iopmp_vosys_gpu_pclk.common,
&iopmp_dpu1_aclk.common,
&iopmp_dpu_aclk.common,
&iopmp_gpu_aclk.common,
&mipi_dsi0_pixclk.common,
&mipi_dsi1_pixclk.common,
&hdmi_pixclk.common
};
static const struct regmap_config th1520_clk_regmap_config = {
.reg_bits = 32,
@@ -972,8 +1064,44 @@ static const struct regmap_config th1520_clk_regmap_config = {
.fast_io = true,
};
struct th1520_plat_data {
struct ccu_common **th1520_pll_clks;
struct ccu_common **th1520_div_clks;
struct ccu_common **th1520_mux_clks;
struct ccu_common **th1520_gate_clks;
int nr_clks;
int nr_pll_clks;
int nr_div_clks;
int nr_mux_clks;
int nr_gate_clks;
};
static const struct th1520_plat_data th1520_ap_platdata = {
.th1520_pll_clks = th1520_pll_clks,
.th1520_div_clks = th1520_div_clks,
.th1520_mux_clks = th1520_mux_clks,
.th1520_gate_clks = th1520_gate_clks,
.nr_clks = CLK_UART_SCLK + 1,
.nr_pll_clks = ARRAY_SIZE(th1520_pll_clks),
.nr_div_clks = ARRAY_SIZE(th1520_div_clks),
.nr_mux_clks = ARRAY_SIZE(th1520_mux_clks),
.nr_gate_clks = ARRAY_SIZE(th1520_gate_clks),
};
static const struct th1520_plat_data th1520_vo_platdata = {
.th1520_gate_clks = th1520_vo_gate_clks,
.nr_clks = CLK_HDMI_PIXCLK + 1,
.nr_gate_clks = ARRAY_SIZE(th1520_vo_gate_clks),
};
static int th1520_clk_probe(struct platform_device *pdev)
{
const struct th1520_plat_data *plat_data;
struct device *dev = &pdev->dev;
struct clk_hw_onecell_data *priv;
@@ -982,11 +1110,16 @@ static int th1520_clk_probe(struct platform_device *pdev)
struct clk_hw *hw;
int ret, i;
priv = devm_kzalloc(dev, struct_size(priv, hws, NR_CLKS), GFP_KERNEL);
plat_data = device_get_match_data(&pdev->dev);
if (!plat_data)
return dev_err_probe(&pdev->dev, -ENODEV,
"No device match data found\n");
priv = devm_kzalloc(dev, struct_size(priv, hws, plat_data->nr_clks), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->num = NR_CLKS;
priv->num = plat_data->nr_clks;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -996,35 +1129,35 @@ static int th1520_clk_probe(struct platform_device *pdev)
if (IS_ERR(map))
return PTR_ERR(map);
for (i = 0; i < ARRAY_SIZE(th1520_pll_clks); i++) {
struct ccu_pll *cp = hw_to_ccu_pll(&th1520_pll_clks[i]->hw);
for (i = 0; i < plat_data->nr_pll_clks; i++) {
struct ccu_pll *cp = hw_to_ccu_pll(&plat_data->th1520_pll_clks[i]->hw);
th1520_pll_clks[i]->map = map;
plat_data->th1520_pll_clks[i]->map = map;
ret = devm_clk_hw_register(dev, &th1520_pll_clks[i]->hw);
ret = devm_clk_hw_register(dev, &plat_data->th1520_pll_clks[i]->hw);
if (ret)
return ret;
priv->hws[cp->common.clkid] = &cp->common.hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_div_clks); i++) {
struct ccu_div *cd = hw_to_ccu_div(&th1520_div_clks[i]->hw);
for (i = 0; i < plat_data->nr_div_clks; i++) {
struct ccu_div *cd = hw_to_ccu_div(&plat_data->th1520_div_clks[i]->hw);
th1520_div_clks[i]->map = map;
plat_data->th1520_div_clks[i]->map = map;
ret = devm_clk_hw_register(dev, &th1520_div_clks[i]->hw);
ret = devm_clk_hw_register(dev, &plat_data->th1520_div_clks[i]->hw);
if (ret)
return ret;
priv->hws[cd->common.clkid] = &cd->common.hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_mux_clks); i++) {
struct ccu_mux *cm = hw_to_ccu_mux(&th1520_mux_clks[i]->hw);
for (i = 0; i < plat_data->nr_mux_clks; i++) {
struct ccu_mux *cm = hw_to_ccu_mux(&plat_data->th1520_mux_clks[i]->hw);
const struct clk_init_data *init = cm->common.hw.init;
th1520_mux_clks[i]->map = map;
plat_data->th1520_mux_clks[i]->map = map;
hw = devm_clk_hw_register_mux_parent_data_table(dev,
init->name,
init->parent_data,
@@ -1040,10 +1173,10 @@ static int th1520_clk_probe(struct platform_device *pdev)
priv->hws[cm->common.clkid] = hw;
}
for (i = 0; i < ARRAY_SIZE(th1520_gate_clks); i++) {
struct ccu_gate *cg = hw_to_ccu_gate(&th1520_gate_clks[i]->hw);
for (i = 0; i < plat_data->nr_gate_clks; i++) {
struct ccu_gate *cg = hw_to_ccu_gate(&plat_data->th1520_gate_clks[i]->hw);
th1520_gate_clks[i]->map = map;
plat_data->th1520_gate_clks[i]->map = map;
hw = devm_clk_hw_register_gate_parent_data(dev,
cg->common.hw.init->name,
@@ -1057,19 +1190,21 @@ static int th1520_clk_probe(struct platform_device *pdev)
priv->hws[cg->common.clkid] = hw;
}
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
if (ret)
return ret;
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
if (plat_data == &th1520_ap_platdata) {
ret = devm_clk_hw_register(dev, &osc12m_clk.hw);
if (ret)
return ret;
priv->hws[CLK_OSC12M] = &osc12m_clk.hw;
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
if (ret)
return ret;
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);
if (ret)
return ret;
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
if (ret)
return ret;
ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
if (ret)
return ret;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
if (ret)
@@ -1081,6 +1216,11 @@ static int th1520_clk_probe(struct platform_device *pdev)
static const struct of_device_id th1520_clk_match[] = {
{
.compatible = "thead,th1520-clk-ap",
.data = &th1520_ap_platdata,
},
{
.compatible = "thead,th1520-clk-vo",
.data = &th1520_vo_platdata,
},
{ /* sentinel */ },
};
@@ -162,6 +162,57 @@
#define DOUT_CLKCMU_TAA_NOC 146
#define DOUT_TCXO_DIV2 147
/* CMU_CPUCL0 */
#define CLK_FOUT_CPUCL0_PLL 1
#define CLK_MOUT_PLL_CPUCL0 2
#define CLK_MOUT_CPUCL0_CLUSTER_USER 3
#define CLK_MOUT_CPUCL0_DBG_USER 4
#define CLK_MOUT_CPUCL0_SWITCH_USER 5
#define CLK_MOUT_CPUCL0_CLUSTER 6
#define CLK_MOUT_CPUCL0_CORE 7
#define CLK_DOUT_CLUSTER0_ACLK 8
#define CLK_DOUT_CLUSTER0_ATCLK 9
#define CLK_DOUT_CLUSTER0_MPCLK 10
#define CLK_DOUT_CLUSTER0_PCLK 11
#define CLK_DOUT_CLUSTER0_PERIPHCLK 12
#define CLK_DOUT_CPUCL0_DBG_NOC 13
#define CLK_DOUT_CPUCL0_DBG_PCLKDBG 14
#define CLK_DOUT_CPUCL0_NOCP 15
/* CMU_CPUCL1 */
#define CLK_FOUT_CPUCL1_PLL 1
#define CLK_MOUT_PLL_CPUCL1 2
#define CLK_MOUT_CPUCL1_CLUSTER_USER 3
#define CLK_MOUT_CPUCL1_SWITCH_USER 4
#define CLK_MOUT_CPUCL1_CLUSTER 5
#define CLK_MOUT_CPUCL1_CORE 6
#define CLK_DOUT_CLUSTER1_ACLK 7
#define CLK_DOUT_CLUSTER1_ATCLK 8
#define CLK_DOUT_CLUSTER1_MPCLK 9
#define CLK_DOUT_CLUSTER1_PCLK 10
#define CLK_DOUT_CLUSTER1_PERIPHCLK 11
#define CLK_DOUT_CPUCL1_NOCP 12
/* CMU_CPUCL2 */
#define CLK_FOUT_CPUCL2_PLL 1
#define CLK_MOUT_PLL_CPUCL2 2
#define CLK_MOUT_CPUCL2_CLUSTER_USER 3
#define CLK_MOUT_CPUCL2_SWITCH_USER 4
#define CLK_MOUT_CPUCL2_CLUSTER 5
#define CLK_MOUT_CPUCL2_CORE 6
#define CLK_DOUT_CLUSTER2_ACLK 7
#define CLK_DOUT_CLUSTER2_ATCLK 8
#define CLK_DOUT_CLUSTER2_MPCLK 9
#define CLK_DOUT_CLUSTER2_PCLK 10
#define CLK_DOUT_CLUSTER2_PERIPHCLK 11
#define CLK_DOUT_CPUCL2_NOCP 12
/* CMU_PERIC0 */
#define CLK_MOUT_PERIC0_IP_USER 1
#define CLK_MOUT_PERIC0_NOC_USER 2
@@ -0,0 +1,153 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
* Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
*/
#ifndef __DT_BINDINGS_SOPHGO_SG2044_CLK_H__
#define __DT_BINDINGS_SOPHGO_SG2044_CLK_H__
#define CLK_DIV_AP_SYS_FIXED 0
#define CLK_DIV_AP_SYS_MAIN 1
#define CLK_DIV_RP_SYS_FIXED 2
#define CLK_DIV_RP_SYS_MAIN 3
#define CLK_DIV_TPU_SYS_FIXED 4
#define CLK_DIV_TPU_SYS_MAIN 5
#define CLK_DIV_NOC_SYS_FIXED 6
#define CLK_DIV_NOC_SYS_MAIN 7
#define CLK_DIV_VC_SRC0_FIXED 8
#define CLK_DIV_VC_SRC0_MAIN 9
#define CLK_DIV_VC_SRC1_FIXED 10
#define CLK_DIV_VC_SRC1_MAIN 11
#define CLK_DIV_CXP_MAC_FIXED 12
#define CLK_DIV_CXP_MAC_MAIN 13
#define CLK_DIV_DDR0_FIXED 14
#define CLK_DIV_DDR0_MAIN 15
#define CLK_DIV_DDR1_FIXED 16
#define CLK_DIV_DDR1_MAIN 17
#define CLK_DIV_DDR2_FIXED 18
#define CLK_DIV_DDR2_MAIN 19
#define CLK_DIV_DDR3_FIXED 20
#define CLK_DIV_DDR3_MAIN 21
#define CLK_DIV_DDR4_FIXED 22
#define CLK_DIV_DDR4_MAIN 23
#define CLK_DIV_DDR5_FIXED 24
#define CLK_DIV_DDR5_MAIN 25
#define CLK_DIV_DDR6_FIXED 26
#define CLK_DIV_DDR6_MAIN 27
#define CLK_DIV_DDR7_FIXED 28
#define CLK_DIV_DDR7_MAIN 29
#define CLK_DIV_TOP_50M 30
#define CLK_DIV_TOP_AXI0 31
#define CLK_DIV_TOP_AXI_HSPERI 32
#define CLK_DIV_TIMER0 33
#define CLK_DIV_TIMER1 34
#define CLK_DIV_TIMER2 35
#define CLK_DIV_TIMER3 36
#define CLK_DIV_TIMER4 37
#define CLK_DIV_TIMER5 38
#define CLK_DIV_TIMER6 39
#define CLK_DIV_TIMER7 40
#define CLK_DIV_CXP_TEST_PHY 41
#define CLK_DIV_CXP_TEST_ETH_PHY 42
#define CLK_DIV_C2C0_TEST_PHY 43
#define CLK_DIV_C2C1_TEST_PHY 44
#define CLK_DIV_PCIE_1G 45
#define CLK_DIV_UART_500M 46
#define CLK_DIV_GPIO_DB 47
#define CLK_DIV_SD 48
#define CLK_DIV_SD_100K 49
#define CLK_DIV_EMMC 50
#define CLK_DIV_EMMC_100K 51
#define CLK_DIV_EFUSE 52
#define CLK_DIV_TX_ETH0 53
#define CLK_DIV_PTP_REF_I_ETH0 54
#define CLK_DIV_REF_ETH0 55
#define CLK_DIV_PKA 56
#define CLK_MUX_DDR0 57
#define CLK_MUX_DDR1 58
#define CLK_MUX_DDR2 59
#define CLK_MUX_DDR3 60
#define CLK_MUX_DDR4 61
#define CLK_MUX_DDR5 62
#define CLK_MUX_DDR6 63
#define CLK_MUX_DDR7 64
#define CLK_MUX_NOC_SYS 65
#define CLK_MUX_TPU_SYS 66
#define CLK_MUX_RP_SYS 67
#define CLK_MUX_AP_SYS 68
#define CLK_MUX_VC_SRC0 69
#define CLK_MUX_VC_SRC1 70
#define CLK_MUX_CXP_MAC 71
#define CLK_GATE_AP_SYS 72
#define CLK_GATE_RP_SYS 73
#define CLK_GATE_TPU_SYS 74
#define CLK_GATE_NOC_SYS 75
#define CLK_GATE_VC_SRC0 76
#define CLK_GATE_VC_SRC1 77
#define CLK_GATE_DDR0 78
#define CLK_GATE_DDR1 79
#define CLK_GATE_DDR2 80
#define CLK_GATE_DDR3 81
#define CLK_GATE_DDR4 82
#define CLK_GATE_DDR5 83
#define CLK_GATE_DDR6 84
#define CLK_GATE_DDR7 85
#define CLK_GATE_TOP_50M 86
#define CLK_GATE_SC_RX 87
#define CLK_GATE_SC_RX_X0Y1 88
#define CLK_GATE_TOP_AXI0 89
#define CLK_GATE_INTC0 90
#define CLK_GATE_INTC1 91
#define CLK_GATE_INTC2 92
#define CLK_GATE_INTC3 93
#define CLK_GATE_MAILBOX0 94
#define CLK_GATE_MAILBOX1 95
#define CLK_GATE_MAILBOX2 96
#define CLK_GATE_MAILBOX3 97
#define CLK_GATE_TOP_AXI_HSPERI 98
#define CLK_GATE_APB_TIMER 99
#define CLK_GATE_TIMER0 100
#define CLK_GATE_TIMER1 101
#define CLK_GATE_TIMER2 102
#define CLK_GATE_TIMER3 103
#define CLK_GATE_TIMER4 104
#define CLK_GATE_TIMER5 105
#define CLK_GATE_TIMER6 106
#define CLK_GATE_TIMER7 107
#define CLK_GATE_CXP_CFG 108
#define CLK_GATE_CXP_MAC 109
#define CLK_GATE_CXP_TEST_PHY 110
#define CLK_GATE_CXP_TEST_ETH_PHY 111
#define CLK_GATE_PCIE_1G 112
#define CLK_GATE_C2C0_TEST_PHY 113
#define CLK_GATE_C2C1_TEST_PHY 114
#define CLK_GATE_UART_500M 115
#define CLK_GATE_APB_UART 116
#define CLK_GATE_APB_SPI 117
#define CLK_GATE_AHB_SPIFMC 118
#define CLK_GATE_APB_I2C 119
#define CLK_GATE_AXI_DBG_I2C 120
#define CLK_GATE_GPIO_DB 121
#define CLK_GATE_APB_GPIO_INTR 122
#define CLK_GATE_APB_GPIO 123
#define CLK_GATE_SD 124
#define CLK_GATE_AXI_SD 125
#define CLK_GATE_SD_100K 126
#define CLK_GATE_EMMC 127
#define CLK_GATE_AXI_EMMC 128
#define CLK_GATE_EMMC_100K 129
#define CLK_GATE_EFUSE 130
#define CLK_GATE_APB_EFUSE 131
#define CLK_GATE_SYSDMA_AXI 132
#define CLK_GATE_TX_ETH0 133
#define CLK_GATE_AXI_ETH0 134
#define CLK_GATE_PTP_REF_I_ETH0 135
#define CLK_GATE_REF_ETH0 136
#define CLK_GATE_APB_RTC 137
#define CLK_GATE_APB_PWM 138
#define CLK_GATE_APB_WDT 139
#define CLK_GATE_AXI_SRAM 140
#define CLK_GATE_AHB_ROM 141
#define CLK_GATE_PKA 142
#endif /* __DT_BINDINGS_SOPHGO_SG2044_CLK_H__ */
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
/*
* Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
*/
#ifndef __DT_BINDINGS_SOPHGO_SG2044_PLL_H__
#define __DT_BINDINGS_SOPHGO_SG2044_PLL_H__
#define CLK_FPLL0 0
#define CLK_FPLL1 1
#define CLK_FPLL2 2
#define CLK_DPLL0 3
#define CLK_DPLL1 4
#define CLK_DPLL2 5
#define CLK_DPLL3 6
#define CLK_DPLL4 7
#define CLK_DPLL5 8
#define CLK_DPLL6 9
#define CLK_DPLL7 10
#define CLK_MPLL0 11
#define CLK_MPLL1 12
#define CLK_MPLL2 13
#define CLK_MPLL3 14
#define CLK_MPLL4 15
#define CLK_MPLL5 16
#endif /* __DT_BINDINGS_SOPHGO_SG2044_PLL_H__ */
@@ -93,4 +93,38 @@
#define CLK_SRAM3 83
#define CLK_PLL_GMAC_100M 84
#define CLK_UART_SCLK 85
/* VO clocks */
#define CLK_AXI4_VO_ACLK 0
#define CLK_GPU_MEM 1
#define CLK_GPU_CORE 2
#define CLK_GPU_CFG_ACLK 3
#define CLK_DPU_PIXELCLK0 4
#define CLK_DPU_PIXELCLK1 5
#define CLK_DPU_HCLK 6
#define CLK_DPU_ACLK 7
#define CLK_DPU_CCLK 8
#define CLK_HDMI_SFR 9
#define CLK_HDMI_PCLK 10
#define CLK_HDMI_CEC 11
#define CLK_MIPI_DSI0_PCLK 12
#define CLK_MIPI_DSI1_PCLK 13
#define CLK_MIPI_DSI0_CFG 14
#define CLK_MIPI_DSI1_CFG 15
#define CLK_MIPI_DSI0_REFCLK 16
#define CLK_MIPI_DSI1_REFCLK 17
#define CLK_HDMI_I2S 18
#define CLK_X2H_DPU1_ACLK 19
#define CLK_X2H_DPU_ACLK 20
#define CLK_AXI4_VO_PCLK 21
#define CLK_IOPMP_VOSYS_DPU_PCLK 22
#define CLK_IOPMP_VOSYS_DPU1_PCLK 23
#define CLK_IOPMP_VOSYS_GPU_PCLK 24
#define CLK_IOPMP_DPU1_ACLK 25
#define CLK_IOPMP_DPU_ACLK 26
#define CLK_IOPMP_GPU_ACLK 27
#define CLK_MIPIDSI0_PIXCLK 28
#define CLK_MIPIDSI1_PIXCLK 29
#define CLK_HDMI_PIXCLK 30
#endif