Merge branches 'clk-bindings', 'clk-renesas', 'clk-spacemit' and 'clk-cleanup' into clk-next

* clk-bindings:
  dt-bindings: clock: Drop st,stm32h7-rcc.txt
  dt-bindings: clock: convert bcm2835-aux-clock to yaml
  dt-bindings: clock: Drop maxim,max77686.txt
  dt-bindings: clock: convert vf610-clock.txt to yaml format

* clk-renesas: (26 commits)
  clk: renesas: r9a09g047: Add XSPI clock/reset
  clk: renesas: r9a09g047: Add support for xspi mux and divider
  dt-bindings: clock: renesas,r9a09g047-cpg: Add XSPI and GBETH PTP core clocks
  clk: renesas: Use str_on_off() helper
  clk: renesas: r9a09g057: Add clock and reset entries for USB2
  dt-bindings: clock: renesas,r9a09g057-cpg: Add USB2 PHY and GBETH PTP core clocks
  clk: renesas: rzv2h: Use both CLK_ON and CLK_MON bits for clock state validation
  clk: renesas: rzv2h: Use str_on_off() helper in rzv2h_mod_clock_endisable()
  clk: renesas: rzv2h: Support static dividers without RMW
  clk: renesas: rzv2h: Add macro for defining static dividers
  clk: renesas: rzv2h: Add support for static mux clocks
  clk: renesas: r9a09g047: Add clock and reset entries for GE3D
  clk: renesas: rzv2h: Fix a typo
  clk: renesas: rzv2h: Add support for RZ/V2N SoC
  clk: renesas: rzv2h: Sort compatible list based on SoC part number
  dt-bindings: pinctrl: renesas: Document RZ/V2N SoC
  dt-bindings: clock: renesas: Document RZ/V2N SoC CPG
  dt-bindings: soc: renesas: Document SYS for RZ/V2N SoC
  dt-bindings: soc: renesas: Document Renesas RZ/V2N SoC variants and EVK
  clk: renesas: rzv2h: Simplify rzv2h_cpg_assert()/rzv2h_cpg_deassert()
  ...

* clk-spacemit:
  clk: spacemit: k1: Add TWSI8 bus and function clocks
  clk: spacemit: Add clock support for SpacemiT K1 SoC
  dt-bindings: clock: spacemit: Add spacemit,k1-pll
  dt-bindings: soc: spacemit: Add spacemit,k1-syscon

* clk-cleanup:
  clk: test: Forward-declare struct of_phandle_args in kunit/clk.h
  clk: davinci: Use of_get_available_child_by_name()
  clk: bcm: rpi: Add NULL check in raspberrypi_clk_register()
  clk: bcm: rpi: Drop module alias
  clk: bcm: kona: Remove unused scaled_div_build
This commit is contained in:
Stephen Boyd
2025-05-29 00:30:17 -07:00
36 changed files with 3011 additions and 101 deletions

View File

@@ -4,13 +4,13 @@
$id: http://devicetree.org/schemas/clock/renesas,rzv2h-cpg.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/{G3E,V2H(P)} Clock Pulse Generator (CPG)
title: Renesas RZ/{G3E,V2H(P),V2N} Clock Pulse Generator (CPG)
maintainers:
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
description:
On Renesas RZ/{G3E,V2H(P)} SoCs, the CPG (Clock Pulse Generator) handles
On Renesas RZ/{G3E,V2H(P),V2N} SoCs, the CPG (Clock Pulse Generator) handles
generation and control of clock signals for the IP modules, generation and
control of resets, and control over booting, low power consumption and power
supply domains.
@@ -19,6 +19,7 @@ properties:
compatible:
enum:
- renesas,r9a09g047-cpg # RZ/G3E
- renesas,r9a09g056-cpg # RZ/V2N
- renesas,r9a09g057-cpg # RZ/V2H
reg:

View File

@@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/spacemit,k1-pll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SpacemiT K1 PLL
maintainers:
- Haylen Chu <heylenay@4d2.org>
properties:
compatible:
const: spacemit,k1-pll
reg:
maxItems: 1
clocks:
description: External 24MHz oscillator
spacemit,mpmu:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to the "Main PMU (MPMU)" syscon. It is used to check PLL
lock status.
"#clock-cells":
const: 1
description:
See <dt-bindings/clock/spacemit,k1-syscon.h> for valid indices.
required:
- compatible
- reg
- clocks
- spacemit,mpmu
- "#clock-cells"
additionalProperties: false
examples:
- |
clock-controller@d4090000 {
compatible = "spacemit,k1-pll";
reg = <0xd4090000 0x1000>;
clocks = <&vctcxo_24m>;
spacemit,mpmu = <&sysctl_mpmu>;
#clock-cells = <1>;
};

View File

@@ -27,6 +27,7 @@ properties:
- renesas,r9a07g044-pinctrl # RZ/G2{L,LC}
- renesas,r9a08g045-pinctrl # RZ/G3S
- renesas,r9a09g047-pinctrl # RZ/G3E
- renesas,r9a09g056-pinctrl # RZ/V2N
- renesas,r9a09g057-pinctrl # RZ/V2H(P)
- items:
@@ -145,6 +146,7 @@ allOf:
contains:
enum:
- renesas,r9a09g047-pinctrl
- renesas,r9a09g056-pinctrl
- renesas,r9a09g057-pinctrl
then:
properties:

View File

@@ -25,6 +25,7 @@ properties:
items:
- enum:
- renesas,r9a09g047-sys # RZ/G3E
- renesas,r9a09g056-sys # RZ/V2N
- renesas,r9a09g057-sys # RZ/V2H
reg:

View File

@@ -551,6 +551,21 @@ properties:
- renesas,r9a09g047e58 # Quad Cortex-A55 + Cortex-M33 + Ethos-U55 (21mm BGA)
- const: renesas,r9a09g047
- description: RZ/V2N (R9A09G056)
items:
- enum:
- renesas,rzv2n-evk # RZ/V2N EVK (RTK0EF0186C03000BJ)
- enum:
- renesas,r9a09g056n41 # RZ/V2N
- renesas,r9a09g056n42 # RZ/V2N with Mali-G31 support
- renesas,r9a09g056n43 # RZ/V2N with Mali-C55 support
- renesas,r9a09g056n44 # RZ/V2N with Mali-G31 + Mali-C55 support
- renesas,r9a09g056n45 # RZ/V2N with cryptographic extension support
- renesas,r9a09g056n46 # RZ/V2N with Mali-G31 + cryptographic extension support
- renesas,r9a09g056n47 # RZ/V2N with Mali-C55 + cryptographic extension support
- renesas,r9a09g056n48 # RZ/V2N with Mali-G31 + Mali-C55 + cryptographic extension support
- const: renesas,r9a09g056
- description: RZ/V2H(P) (R9A09G057)
items:
- enum:

View File

@@ -0,0 +1,80 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/spacemit/spacemit,k1-syscon.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SpacemiT K1 SoC System Controller
maintainers:
- Haylen Chu <heylenay@4d2.org>
description:
System controllers found on SpacemiT K1 SoC, which are capable of
clock, reset and power-management functions.
properties:
compatible:
enum:
- spacemit,k1-syscon-apbc
- spacemit,k1-syscon-apmu
- spacemit,k1-syscon-mpmu
reg:
maxItems: 1
clocks:
maxItems: 4
clock-names:
items:
- const: osc
- const: vctcxo_1m
- const: vctcxo_3m
- const: vctcxo_24m
"#clock-cells":
const: 1
description:
See <dt-bindings/clock/spacemit,k1-syscon.h> for valid indices.
"#power-domain-cells":
const: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- "#clock-cells"
- "#reset-cells"
allOf:
- if:
properties:
compatible:
contains:
const: spacemit,k1-syscon-apbc
then:
properties:
"#power-domain-cells": false
else:
required:
- "#power-domain-cells"
additionalProperties: false
examples:
- |
system-controller@d4050000 {
compatible = "spacemit,k1-syscon-mpmu";
reg = <0xd4050000 0x209c>;
clocks = <&osc>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>;
clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m";
#clock-cells = <1>;
#power-domain-cells = <1>;
#reset-cells = <1>;
};

View File

@@ -517,6 +517,7 @@ source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sifive/Kconfig"
source "drivers/clk/socfpga/Kconfig"
source "drivers/clk/sophgo/Kconfig"
source "drivers/clk/spacemit/Kconfig"
source "drivers/clk/sprd/Kconfig"
source "drivers/clk/starfive/Kconfig"
source "drivers/clk/sunxi/Kconfig"

View File

@@ -145,6 +145,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-y += socfpga/
obj-y += sophgo/
obj-y += spacemit/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-y += sprd/
obj-$(CONFIG_ARCH_STI) += st/

View File

@@ -53,24 +53,6 @@ static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
}
/*
* Build a scaled divider value as close as possible to the
* given whole part (div_value) and fractional part (expressed
* in billionths).
*/
u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
{
u64 combined;
BUG_ON(!div_value);
BUG_ON(billionths >= BILLION);
combined = (u64)div_value * BILLION + billionths;
combined <<= div->u.s.frac_width;
return DIV_ROUND_CLOSEST_ULL(combined, BILLION);
}
/* The scaled minimum divisor representable by a divider */
static inline u64
scaled_div_min(struct bcm_clk_div *div)

View File

@@ -492,8 +492,6 @@ extern struct clk_ops kona_peri_clk_ops;
/* Externally visible functions */
extern u64 scaled_div_max(struct bcm_clk_div *div);
extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value,
u32 billionths);
extern void __init kona_dt_ccu_setup(struct ccu_data *ccu,
struct device_node *node);

View File

@@ -286,6 +286,8 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
"fw-clk-%s",
rpi_firmware_clk_names[id]);
if (!init.name)
return ERR_PTR(-ENOMEM);
init.ops = &raspberrypi_firmware_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
@@ -480,4 +482,3 @@ module_platform_driver(raspberrypi_clk_driver);
MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:raspberrypi-clk");

View File

@@ -763,13 +763,14 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
return PTR_ERR(clk);
}
child = of_get_child_by_name(node, "pllout");
if (of_device_is_available(child))
child = of_get_available_child_by_name(node, "pllout");
if (child) {
of_clk_add_provider(child, of_clk_src_simple_get, clk);
of_node_put(child);
of_node_put(child);
}
child = of_get_child_by_name(node, "sysclk");
if (of_device_is_available(child)) {
child = of_get_available_child_by_name(node, "sysclk");
if (child) {
struct clk_onecell_data *clk_data;
struct clk **clks;
int n_clks = max_sysclk_id + 1;
@@ -803,11 +804,11 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
clks[(*div_info)->id] = clk;
}
of_clk_add_provider(child, of_clk_src_onecell_get, clk_data);
of_node_put(child);
}
of_node_put(child);
child = of_get_child_by_name(node, "auxclk");
if (of_device_is_available(child)) {
child = of_get_available_child_by_name(node, "auxclk");
if (child) {
char child_name[MAX_NAME_SIZE];
snprintf(child_name, MAX_NAME_SIZE, "%s_auxclk", info->name);
@@ -818,11 +819,12 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
child_name, PTR_ERR(clk));
else
of_clk_add_provider(child, of_clk_src_simple_get, clk);
}
of_node_put(child);
child = of_get_child_by_name(node, "obsclk");
if (of_device_is_available(child)) {
of_node_put(child);
}
child = of_get_available_child_by_name(node, "obsclk");
if (child) {
if (obsclk_info)
clk = davinci_pll_obsclk_register(dev, obsclk_info, base);
else
@@ -833,8 +835,8 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
PTR_ERR(clk));
else
of_clk_add_provider(child, of_clk_src_simple_get, clk);
of_node_put(child);
}
of_node_put(child);
return 0;
}

View File

@@ -41,6 +41,7 @@ config CLK_RENESAS
select CLK_R9A08G045 if ARCH_R9A08G045
select CLK_R9A09G011 if ARCH_R9A09G011
select CLK_R9A09G047 if ARCH_R9A09G047
select CLK_R9A09G056 if ARCH_R9A09G056
select CLK_R9A09G057 if ARCH_R9A09G057
select CLK_SH73A0 if ARCH_SH73A0
@@ -199,6 +200,10 @@ config CLK_R9A09G047
bool "RZ/G3E clock support" if COMPILE_TEST
select CLK_RZV2H
config CLK_R9A09G056
bool "RZ/V2N clock support" if COMPILE_TEST
select CLK_RZV2H
config CLK_R9A09G057
bool "RZ/V2H(P) clock support" if COMPILE_TEST
select CLK_RZV2H

View File

@@ -38,6 +38,7 @@ obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o
obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o
obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o
obj-$(CONFIG_CLK_R9A09G047) += r9a09g047-cpg.o
obj-$(CONFIG_CLK_R9A09G056) += r9a09g056-cpg.o
obj-$(CONFIG_CLK_R9A09G057) += r9a09g057-cpg.o
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o

View File

@@ -16,7 +16,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G047_IOTOP_0_SHCLK,
LAST_DT_CORE_CLK = R9A09G047_GBETH_1_CLK_PTP_REF_I,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
@@ -31,7 +31,14 @@ enum clk_ids {
CLK_PLLVDO,
/* Internal Core Clocks */
CLK_PLLCM33_DIV3,
CLK_PLLCM33_DIV4,
CLK_PLLCM33_DIV5,
CLK_PLLCM33_DIV16,
CLK_PLLCM33_GEAR,
CLK_SMUX2_XSPI_CLK0,
CLK_SMUX2_XSPI_CLK1,
CLK_PLLCM33_XSPI,
CLK_PLLCLN_DIV2,
CLK_PLLCLN_DIV8,
CLK_PLLCLN_DIV16,
@@ -41,6 +48,7 @@ enum clk_ids {
CLK_PLLDTY_ACPU_DIV4,
CLK_PLLDTY_DIV16,
CLK_PLLVDO_CRU0,
CLK_PLLVDO_GPU,
/* Module Clocks */
MOD_CLK_BASE,
@@ -60,6 +68,14 @@ static const struct clk_div_table dtable_2_4[] = {
{0, 0},
};
static const struct clk_div_table dtable_2_16[] = {
{0, 2},
{1, 4},
{2, 8},
{3, 16},
{0, 0},
};
static const struct clk_div_table dtable_2_64[] = {
{0, 2},
{1, 4},
@@ -69,6 +85,10 @@ static const struct clk_div_table dtable_2_64[] = {
{0, 0},
};
/* Mux clock tables */
static const char * const smux2_xspi_clk0[] = { ".pllcm33_div3", ".pllcm33_div4" };
static const char * const smux2_xspi_clk1[] = { ".smux2_xspi_clk0", ".pllcm33_div5" };
static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
@@ -79,12 +99,21 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLL_CONF(0x64)),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
/* Internal Core Clocks */
DEF_FIXED(".pllcm33_div3", CLK_PLLCM33_DIV3, CLK_PLLCM33, 1, 3),
DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
DEF_FIXED(".pllcm33_div5", CLK_PLLCM33_DIV5, CLK_PLLCM33, 1, 5),
DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
DEF_DDIV(".pllcm33_gear", CLK_PLLCM33_GEAR, CLK_PLLCM33_DIV4, CDDIV0_DIVCTL1, dtable_2_64),
DEF_SMUX(".smux2_xspi_clk0", CLK_SMUX2_XSPI_CLK0, SSEL1_SELCTL2, smux2_xspi_clk0),
DEF_SMUX(".smux2_xspi_clk1", CLK_SMUX2_XSPI_CLK1, SSEL1_SELCTL3, smux2_xspi_clk1),
DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3,
dtable_2_16),
DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
@@ -96,6 +125,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
DEF_DDIV(".pllvdo_cru0", CLK_PLLVDO_CRU0, CLK_PLLVDO, CDDIV3_DIVCTL3, dtable_2_4),
DEF_DDIV(".pllvdo_gpu", CLK_PLLVDO_GPU, CLK_PLLVDO, CDDIV3_DIVCTL1, dtable_2_64),
/* Core Clocks */
DEF_FIXED("sys_0_pclk", R9A09G047_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
@@ -108,6 +138,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = {
DEF_DDIV("ca55_0_coreclk3", R9A09G047_CA55_0_CORECLK3, CLK_PLLCA55,
CDDIV1_DIVCTL3, dtable_1_8),
DEF_FIXED("iotop_0_shclk", R9A09G047_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
DEF_FIXED("spi_clk_spi", R9A09G047_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2),
};
static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
@@ -153,6 +184,12 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
BUS_MSTOP(10, BIT(14))),
DEF_MOD("canfd_0_clkc", CLK_PLLCLN_DIV20, 9, 14, 4, 30,
BUS_MSTOP(10, BIT(14))),
DEF_MOD("spi_hclk", CLK_PLLCM33_GEAR, 9, 15, 4, 31,
BUS_MSTOP(4, BIT(5))),
DEF_MOD("spi_aclk", CLK_PLLCM33_GEAR, 10, 0, 5, 0,
BUS_MSTOP(4, BIT(5))),
DEF_MOD_NO_PM("spi_clk_spix2", CLK_PLLCM33_XSPI, 10, 1, 5, 2,
BUS_MSTOP(4, BIT(5))),
DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
BUS_MSTOP(8, BIT(2))),
DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
@@ -183,6 +220,12 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = {
BUS_MSTOP(9, BIT(4))),
DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20,
BUS_MSTOP(9, BIT(4))),
DEF_MOD("ge3d_clk", CLK_PLLVDO_GPU, 15, 0, 7, 16,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("ge3d_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("ge3d_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10,
BUS_MSTOP(2, BIT(15))),
};
@@ -207,12 +250,17 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = {
DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
DEF_RST(10, 1, 4, 18), /* CANFD_0_RSTP_N */
DEF_RST(10, 2, 4, 19), /* CANFD_0_RSTC_N */
DEF_RST(10, 3, 4, 20), /* SPI_HRESETN */
DEF_RST(10, 4, 4, 21), /* SPI_ARESETN */
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
DEF_RST(13, 13, 6, 14), /* GE3D_RESETN */
DEF_RST(13, 14, 6, 15), /* GE3D_AXI_RESETN */
DEF_RST(13, 15, 6, 16), /* GE3D_ACE_RESETN */
DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */
};

View File

@@ -0,0 +1,152 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/V2N CPG driver
*
* Copyright (C) 2025 Renesas Electronics Corp.
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <dt-bindings/clock/renesas,r9a09g056-cpg.h>
#include "rzv2h-cpg.h"
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G056_GBETH_1_CLK_PTP_REF_I,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
CLK_RTXIN,
CLK_QEXTAL,
/* PLL Clocks */
CLK_PLLCM33,
CLK_PLLCLN,
CLK_PLLDTY,
CLK_PLLCA55,
/* Internal Core Clocks */
CLK_PLLCM33_DIV16,
CLK_PLLCLN_DIV2,
CLK_PLLCLN_DIV8,
CLK_PLLDTY_ACPU,
CLK_PLLDTY_ACPU_DIV4,
/* Module Clocks */
MOD_CLK_BASE,
};
static const struct clk_div_table dtable_1_8[] = {
{0, 1},
{1, 2},
{2, 4},
{3, 8},
{0, 0},
};
static const struct clk_div_table dtable_2_64[] = {
{0, 2},
{1, 4},
{2, 8},
{3, 16},
{4, 64},
{0, 0},
};
static const struct cpg_core_clk r9a09g056_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
DEF_INPUT("rtxin", CLK_RTXIN),
DEF_INPUT("qextal", CLK_QEXTAL),
/* PLL Clocks */
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
/* Internal Core Clocks */
DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
/* Core Clocks */
DEF_FIXED("sys_0_pclk", R9A09G056_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
DEF_DDIV("ca55_0_coreclk0", R9A09G056_CA55_0_CORE_CLK0, CLK_PLLCA55,
CDDIV1_DIVCTL0, dtable_1_8),
DEF_DDIV("ca55_0_coreclk1", R9A09G056_CA55_0_CORE_CLK1, CLK_PLLCA55,
CDDIV1_DIVCTL1, dtable_1_8),
DEF_DDIV("ca55_0_coreclk2", R9A09G056_CA55_0_CORE_CLK2, CLK_PLLCA55,
CDDIV1_DIVCTL2, dtable_1_8),
DEF_DDIV("ca55_0_coreclk3", R9A09G056_CA55_0_CORE_CLK3, CLK_PLLCA55,
CDDIV1_DIVCTL3, dtable_1_8),
DEF_FIXED("iotop_0_shclk", R9A09G056_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
};
static const struct rzv2h_mod_clk r9a09g056_mod_clks[] __initconst = {
DEF_MOD_CRITICAL("gic_0_gicclk", CLK_PLLDTY_ACPU_DIV4, 1, 3, 0, 19,
BUS_MSTOP(3, BIT(5))),
DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15,
BUS_MSTOP(3, BIT(14))),
DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3,
BUS_MSTOP(8, BIT(2))),
DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4,
BUS_MSTOP(8, BIT(2))),
DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5,
BUS_MSTOP(8, BIT(2))),
DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6,
BUS_MSTOP(8, BIT(2))),
DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7,
BUS_MSTOP(8, BIT(3))),
DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8,
BUS_MSTOP(8, BIT(3))),
DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9,
BUS_MSTOP(8, BIT(3))),
DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10,
BUS_MSTOP(8, BIT(3))),
DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
BUS_MSTOP(8, BIT(4))),
};
static const struct rzv2h_reset r9a09g056_resets[] __initconst = {
DEF_RST(3, 0, 1, 1), /* SYS_0_PRESETN */
DEF_RST(3, 8, 1, 9), /* GIC_0_GICRESET_N */
DEF_RST(3, 9, 1, 10), /* GIC_0_DBG_GICRESET_N */
DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
};
const struct rzv2h_cpg_info r9a09g056_cpg_info __initconst = {
/* Core Clocks */
.core_clks = r9a09g056_core_clks,
.num_core_clks = ARRAY_SIZE(r9a09g056_core_clks),
.last_dt_core_clk = LAST_DT_CORE_CLK,
.num_total_core_clks = MOD_CLK_BASE,
/* Module Clocks */
.mod_clks = r9a09g056_mod_clks,
.num_mod_clks = ARRAY_SIZE(r9a09g056_mod_clks),
.num_hw_mod_clks = 25 * 16,
/* Resets */
.resets = r9a09g056_resets,
.num_resets = ARRAY_SIZE(r9a09g056_resets),
.num_mstop_bits = 192,
};

View File

@@ -16,7 +16,7 @@
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R9A09G057_IOTOP_0_SHCLK,
LAST_DT_CORE_CLK = R9A09G057_GBETH_1_CLK_PTP_REF_I,
/* External Input Clocks */
CLK_AUDIO_EXTAL,
@@ -29,6 +29,7 @@ enum clk_ids {
CLK_PLLDTY,
CLK_PLLCA55,
CLK_PLLVDO,
CLK_PLLGPU,
/* Internal Core Clocks */
CLK_PLLCM33_DIV4,
@@ -40,6 +41,7 @@ enum clk_ids {
CLK_PLLDTY_ACPU,
CLK_PLLDTY_ACPU_DIV2,
CLK_PLLDTY_ACPU_DIV4,
CLK_PLLDTY_DIV8,
CLK_PLLDTY_DIV16,
CLK_PLLDTY_RCPU,
CLK_PLLDTY_RCPU_DIV4,
@@ -47,6 +49,7 @@ enum clk_ids {
CLK_PLLVDO_CRU1,
CLK_PLLVDO_CRU2,
CLK_PLLVDO_CRU3,
CLK_PLLGPU_GEAR,
/* Module Clocks */
MOD_CLK_BASE,
@@ -85,8 +88,9 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLL_CONF(0x64)),
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
/* Internal Core Clocks */
DEF_FIXED(".pllcm33_div4", CLK_PLLCM33_DIV4, CLK_PLLCM33, 1, 4),
@@ -101,6 +105,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2),
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8),
DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16),
DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64),
DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4),
@@ -110,6 +115,8 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_DDIV(".pllvdo_cru2", CLK_PLLVDO_CRU2, CLK_PLLVDO, CDDIV4_DIVCTL1, dtable_2_4),
DEF_DDIV(".pllvdo_cru3", CLK_PLLVDO_CRU3, CLK_PLLVDO, CDDIV4_DIVCTL2, dtable_2_4),
DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
/* Core Clocks */
DEF_FIXED("sys_0_pclk", R9A09G057_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
DEF_DDIV("ca55_0_coreclk0", R9A09G057_CA55_0_CORE_CLK0, CLK_PLLCA55,
@@ -121,6 +128,8 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
DEF_DDIV("ca55_0_coreclk3", R9A09G057_CA55_0_CORE_CLK3, CLK_PLLCA55,
CDDIV1_DIVCTL3, dtable_1_8),
DEF_FIXED("iotop_0_shclk", R9A09G057_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
DEF_FIXED("usb2_0_clk_core0", R9A09G057_USB2_0_CLK_CORE0, CLK_QEXTAL, 1, 1),
DEF_FIXED("usb2_0_clk_core1", R9A09G057_USB2_0_CLK_CORE1, CLK_QEXTAL, 1, 1),
};
static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
@@ -214,6 +223,16 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
BUS_MSTOP(8, BIT(4))),
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14,
BUS_MSTOP(8, BIT(4))),
DEF_MOD("usb2_0_u2h0_hclk", CLK_PLLDTY_DIV8, 11, 3, 5, 19,
BUS_MSTOP(7, BIT(7))),
DEF_MOD("usb2_0_u2h1_hclk", CLK_PLLDTY_DIV8, 11, 4, 5, 20,
BUS_MSTOP(7, BIT(8))),
DEF_MOD("usb2_0_u2p_exr_cpuclk", CLK_PLLDTY_ACPU_DIV4, 11, 5, 5, 21,
BUS_MSTOP(7, BIT(9))),
DEF_MOD("usb2_0_pclk_usbtst0", CLK_PLLDTY_ACPU_DIV4, 11, 6, 5, 22,
BUS_MSTOP(7, BIT(10))),
DEF_MOD("usb2_0_pclk_usbtst1", CLK_PLLDTY_ACPU_DIV4, 11, 7, 5, 23,
BUS_MSTOP(7, BIT(11))),
DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18,
BUS_MSTOP(9, BIT(4))),
DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19,
@@ -238,6 +257,12 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
BUS_MSTOP(9, BIT(7))),
DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29,
BUS_MSTOP(9, BIT(7))),
DEF_MOD("gpu_0_clk", CLK_PLLGPU_GEAR, 15, 0, 7, 16,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("gpu_0_axi_clk", CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
BUS_MSTOP(3, BIT(4))),
DEF_MOD("gpu_0_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18,
BUS_MSTOP(3, BIT(4))),
};
static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
@@ -275,6 +300,10 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
DEF_RST(10, 12, 4, 29), /* USB2_0_U2H0_HRESETN */
DEF_RST(10, 13, 4, 30), /* USB2_0_U2H1_HRESETN */
DEF_RST(10, 14, 4, 31), /* USB2_0_U2P_EXL_SYSRST */
DEF_RST(10, 15, 5, 0), /* USB2_0_PRESETN */
DEF_RST(12, 5, 5, 22), /* CRU_0_PRESETN */
DEF_RST(12, 6, 5, 23), /* CRU_0_ARESETN */
DEF_RST(12, 7, 5, 24), /* CRU_0_S_RESETN */
@@ -287,6 +316,9 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
DEF_RST(12, 14, 5, 31), /* CRU_3_PRESETN */
DEF_RST(12, 15, 6, 0), /* CRU_3_ARESETN */
DEF_RST(13, 0, 6, 1), /* CRU_3_S_RESETN */
DEF_RST(13, 13, 6, 14), /* GPU_0_RESETN */
DEF_RST(13, 14, 6, 15), /* GPU_0_AXI_RESETN */
DEF_RST(13, 15, 6, 16), /* GPU_0_ACE_RESETN */
};
const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {

View File

@@ -27,6 +27,7 @@
#include <linux/psci.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <dt-bindings/clock/renesas-cpg-mssr.h>
@@ -204,7 +205,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
int error;
dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
enable ? "ON" : "OFF");
str_on_off(enable));
spin_lock_irqsave(&priv->rmw_lock, flags);
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {

View File

@@ -27,6 +27,7 @@
#include <linux/pm_domain.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <linux/units.h>
#include <dt-bindings/clock/renesas-cpg-mssr.h>
@@ -1217,7 +1218,7 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
}
dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk,
enable ? "ON" : "OFF");
str_on_off(enable));
value = bitmask << 16;
if (enable)

View File

@@ -25,6 +25,7 @@
#include <linux/pm_domain.h>
#include <linux/refcount.h>
#include <linux/reset-controller.h>
#include <linux/string_choices.h>
#include <dt-bindings/clock/renesas-cpg-mssr.h>
@@ -44,10 +45,18 @@
#define CPG_BUS_1_MSTOP (0xd00)
#define CPG_BUS_MSTOP(m) (CPG_BUS_1_MSTOP + ((m) - 1) * 4)
#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), (val)))
#define MDIV(val) FIELD_GET(GENMASK(15, 6), (val))
#define PDIV(val) FIELD_GET(GENMASK(5, 0), (val))
#define SDIV(val) FIELD_GET(GENMASK(2, 0), (val))
#define CPG_PLL_STBY(x) ((x))
#define CPG_PLL_STBY_RESETB BIT(0)
#define CPG_PLL_STBY_RESETB_WEN BIT(16)
#define CPG_PLL_CLK1(x) ((x) + 0x004)
#define CPG_PLL_CLK1_KDIV(x) ((s16)FIELD_GET(GENMASK(31, 16), (x)))
#define CPG_PLL_CLK1_MDIV(x) FIELD_GET(GENMASK(15, 6), (x))
#define CPG_PLL_CLK1_PDIV(x) FIELD_GET(GENMASK(5, 0), (x))
#define CPG_PLL_CLK2(x) ((x) + 0x008)
#define CPG_PLL_CLK2_SDIV(x) FIELD_GET(GENMASK(2, 0), (x))
#define CPG_PLL_MON(x) ((x) + 0x010)
#define CPG_PLL_MON_RESETB BIT(0)
#define CPG_PLL_MON_LOCK BIT(4)
#define DDIV_DIVCTL_WEN(shift) BIT((shift) + 16)
@@ -94,8 +103,7 @@ struct pll_clk {
struct rzv2h_cpg_priv *priv;
void __iomem *base;
struct clk_hw hw;
unsigned int conf;
unsigned int type;
struct pll pll;
};
#define to_pll(_hw) container_of(_hw, struct pll_clk, hw)
@@ -110,7 +118,7 @@ struct pll_clk {
* @on_index: register offset
* @on_bit: ON/MON bit
* @mon_index: monitor register offset
* @mon_bit: montor bit
* @mon_bit: monitor bit
*/
struct mod_clock {
struct rzv2h_cpg_priv *priv;
@@ -140,27 +148,78 @@ struct ddiv_clk {
#define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)
{
struct pll_clk *pll_clk = to_pll(hw);
struct rzv2h_cpg_priv *priv = pll_clk->priv;
u32 val = readl(priv->base + CPG_PLL_MON(pll_clk->pll.offset));
/* Ensure both RESETB and LOCK bits are set */
return (val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
(CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK);
}
static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
{
struct pll_clk *pll_clk = to_pll(hw);
struct rzv2h_cpg_priv *priv = pll_clk->priv;
struct pll pll = pll_clk->pll;
u32 stby_offset;
u32 mon_offset;
u32 val;
int ret;
if (rzv2h_cpg_pll_clk_is_enabled(hw))
return 0;
stby_offset = CPG_PLL_STBY(pll.offset);
mon_offset = CPG_PLL_MON(pll.offset);
writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
priv->base + stby_offset);
/*
* Ensure PLL enters into normal mode
*
* Note: There is no HW information about the worst case latency.
*
* Since this latency might depend on external crystal or PLL rate,
* use a "super" safe timeout value.
*/
ret = readl_poll_timeout_atomic(priv->base + mon_offset, val,
(val & (CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK)) ==
(CPG_PLL_MON_RESETB | CPG_PLL_MON_LOCK), 200, 2000);
if (ret)
dev_err(priv->dev, "Failed to enable PLL 0x%x/%pC\n",
stby_offset, hw->clk);
return ret;
}
static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pll_clk *pll_clk = to_pll(hw);
struct rzv2h_cpg_priv *priv = pll_clk->priv;
struct pll pll = pll_clk->pll;
unsigned int clk1, clk2;
u64 rate;
if (!PLL_CLK_ACCESS(pll_clk->conf))
if (!pll.has_clkn)
return 0;
clk1 = readl(priv->base + PLL_CLK1_OFFSET(pll_clk->conf));
clk2 = readl(priv->base + PLL_CLK2_OFFSET(pll_clk->conf));
clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
rate = mul_u64_u32_shr(parent_rate, (MDIV(clk1) << 16) + KDIV(clk1),
16 + SDIV(clk2));
rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) +
CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2));
return DIV_ROUND_CLOSEST_ULL(rate, PDIV(clk1));
return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1));
}
static const struct clk_ops rzv2h_cpg_pll_ops = {
.is_enabled = rzv2h_cpg_pll_clk_is_enabled,
.enable = rzv2h_cpg_pll_clk_enable,
.recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
};
@@ -193,10 +252,9 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
init.num_parents = 1;
pll_clk->hw.init = &init;
pll_clk->conf = core->cfg.conf;
pll_clk->pll = core->cfg.pll;
pll_clk->base = base;
pll_clk->priv = priv;
pll_clk->type = core->type;
ret = devm_clk_hw_register(dev, &pll_clk->hw);
if (ret)
@@ -241,6 +299,9 @@ static inline int rzv2h_cpg_wait_ddiv_clk_update_done(void __iomem *base, u8 mon
u32 bitmask = BIT(mon);
u32 val;
if (mon == CSDIV_NO_MON)
return 0;
return readl_poll_timeout_atomic(base + CPG_CLKSTATUS0, val, !(val & bitmask), 10, 200);
}
@@ -272,12 +333,6 @@ static int rzv2h_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
writel(val, divider->reg);
ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
if (ret)
goto ddiv_timeout;
spin_unlock_irqrestore(divider->lock, flags);
return 0;
ddiv_timeout:
spin_unlock_irqrestore(divider->lock, flags);
@@ -320,7 +375,10 @@ rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
return ERR_PTR(-ENOMEM);
init.name = core->name;
init.ops = &rzv2h_ddiv_clk_divider_ops;
if (cfg_ddiv.no_rmw)
init.ops = &clk_divider_ops;
else
init.ops = &rzv2h_ddiv_clk_divider_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
@@ -342,6 +400,24 @@ rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
return div->hw.clk;
}
static struct clk * __init
rzv2h_cpg_mux_clk_register(const struct cpg_core_clk *core,
struct rzv2h_cpg_priv *priv)
{
struct smuxed mux = core->cfg.smux;
const struct clk_hw *clk_hw;
clk_hw = devm_clk_hw_register_mux(priv->dev, core->name,
core->parent_names, core->num_parents,
core->flag, priv->base + mux.offset,
mux.shift, mux.width,
core->mux_flags, &priv->rmw_lock);
if (IS_ERR(clk_hw))
return ERR_CAST(clk_hw);
return clk_hw->clk;
}
static struct clk
*rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
void *data)
@@ -426,6 +502,9 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
case CLK_TYPE_DDIV:
clk = rzv2h_cpg_ddiv_clk_register(core, priv);
break;
case CLK_TYPE_SMUX:
clk = rzv2h_cpg_mux_clk_register(core, priv);
break;
default:
goto fail;
}
@@ -494,11 +573,14 @@ static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw)
if (clock->mon_index >= 0) {
offset = GET_CLK_MON_OFFSET(clock->mon_index);
bitmask = BIT(clock->mon_bit);
} else {
offset = GET_CLK_ON_OFFSET(clock->on_index);
bitmask = BIT(clock->on_bit);
if (!(readl(priv->base + offset) & bitmask))
return 0;
}
offset = GET_CLK_ON_OFFSET(clock->on_index);
bitmask = BIT(clock->on_bit);
return readl(priv->base + offset) & bitmask;
}
@@ -514,7 +596,7 @@ static int rzv2h_mod_clock_endisable(struct clk_hw *hw, bool enable)
int error;
dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk,
enable ? "ON" : "OFF");
str_on_off(enable));
if (enabled == enable)
return 0;
@@ -658,8 +740,8 @@ rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
mod->name, PTR_ERR(clk));
}
static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
unsigned long id)
static int __rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = GET_RST_OFFSET(priv->resets[id].reset_index);
@@ -667,35 +749,31 @@ static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
u8 monbit = priv->resets[id].mon_bit;
u32 value = mask << 16;
dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, reg);
dev_dbg(rcdev->dev, "%s id:%ld offset:0x%x\n",
assert ? "assert" : "deassert", id, reg);
if (!assert)
value |= mask;
writel(value, priv->base + reg);
reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
mask = BIT(monbit);
return readl_poll_timeout_atomic(priv->base + reg, value,
value & mask, 10, 200);
assert ? (value & mask) : !(value & mask),
10, 200);
}
static int rzv2h_cpg_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return __rzv2h_cpg_assert(rcdev, id, true);
}
static int rzv2h_cpg_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzv2h_cpg_priv *priv = rcdev_to_priv(rcdev);
unsigned int reg = GET_RST_OFFSET(priv->resets[id].reset_index);
u32 mask = BIT(priv->resets[id].reset_bit);
u8 monbit = priv->resets[id].mon_bit;
u32 value = (mask << 16) | mask;
dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id, reg);
writel(value, priv->base + reg);
reg = GET_RST_MON_OFFSET(priv->resets[id].mon_index);
mask = BIT(monbit);
return readl_poll_timeout_atomic(priv->base + reg, value,
!(value & mask), 10, 200);
return __rzv2h_cpg_assert(rcdev, id, false);
}
static int rzv2h_cpg_reset(struct reset_controller_dev *rcdev,
@@ -967,17 +1045,23 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev)
}
static const struct of_device_id rzv2h_cpg_match[] = {
#ifdef CONFIG_CLK_R9A09G057
{
.compatible = "renesas,r9a09g057-cpg",
.data = &r9a09g057_cpg_info,
},
#endif
#ifdef CONFIG_CLK_R9A09G047
{
.compatible = "renesas,r9a09g047-cpg",
.data = &r9a09g047_cpg_info,
},
#endif
#ifdef CONFIG_CLK_R9A09G056
{
.compatible = "renesas,r9a09g056-cpg",
.data = &r9a09g056_cpg_info,
},
#endif
#ifdef CONFIG_CLK_R9A09G057
{
.compatible = "renesas,r9a09g057-cpg",
.data = &r9a09g057_cpg_info,
},
#endif
{ /* sentinel */ }
};

View File

@@ -10,6 +10,26 @@
#include <linux/bitfield.h>
/**
* struct pll - Structure for PLL configuration
*
* @offset: STBY register offset
* @has_clkn: Flag to indicate if CLK1/2 are accessible or not
*/
struct pll {
unsigned int offset:9;
unsigned int has_clkn:1;
};
#define PLL_PACK(_offset, _has_clkn) \
((struct pll){ \
.offset = _offset, \
.has_clkn = _has_clkn \
})
#define PLLCA55 PLL_PACK(0x60, 1)
#define PLLGPU PLL_PACK(0x120, 1)
/**
* struct ddiv - Structure for dynamic switching divider
*
@@ -17,14 +37,25 @@
* @shift: position of the divider bit
* @width: width of the divider
* @monbit: monitor bit in CPG_CLKSTATUS0 register
* @no_rmw: flag to indicate if the register is read-modify-write
* (1: no RMW, 0: RMW)
*/
struct ddiv {
unsigned int offset:11;
unsigned int shift:4;
unsigned int width:4;
unsigned int monbit:5;
unsigned int no_rmw:1;
};
/*
* On RZ/V2H(P), the dynamic divider clock supports up to 19 monitor bits,
* while on RZ/G3E, it supports up to 16 monitor bits. Use the maximum value
* `0x1f` to indicate that monitor bits are not supported for static divider
* clocks.
*/
#define CSDIV_NO_MON (0x1f)
#define DDIV_PACK(_offset, _shift, _width, _monbit) \
((struct ddiv){ \
.offset = _offset, \
@@ -33,10 +64,41 @@ struct ddiv {
.monbit = _monbit \
})
#define DDIV_PACK_NO_RMW(_offset, _shift, _width, _monbit) \
((struct ddiv){ \
.offset = (_offset), \
.shift = (_shift), \
.width = (_width), \
.monbit = (_monbit), \
.no_rmw = 1 \
})
/**
* struct smuxed - Structure for static muxed clocks
*
* @offset: register offset
* @shift: position of the divider field
* @width: width of the divider field
*/
struct smuxed {
unsigned int offset:11;
unsigned int shift:4;
unsigned int width:4;
};
#define SMUX_PACK(_offset, _shift, _width) \
((struct smuxed){ \
.offset = (_offset), \
.shift = (_shift), \
.width = (_width), \
})
#define CPG_SSEL1 (0x304)
#define CPG_CDDIV0 (0x400)
#define CPG_CDDIV1 (0x404)
#define CPG_CDDIV3 (0x40C)
#define CPG_CDDIV4 (0x410)
#define CPG_CSDIV0 (0x500)
#define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1)
#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
@@ -44,12 +106,18 @@ struct ddiv {
#define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5)
#define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6)
#define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7)
#define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13)
#define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14)
#define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15)
#define CDDIV4_DIVCTL0 DDIV_PACK(CPG_CDDIV4, 0, 1, 16)
#define CDDIV4_DIVCTL1 DDIV_PACK(CPG_CDDIV4, 4, 1, 17)
#define CDDIV4_DIVCTL2 DDIV_PACK(CPG_CDDIV4, 8, 1, 18)
#define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON)
#define SSEL1_SELCTL2 SMUX_PACK(CPG_SSEL1, 8, 1)
#define SSEL1_SELCTL3 SMUX_PACK(CPG_SSEL1, 12, 1)
#define BUS_MSTOP_IDX_MASK GENMASK(31, 16)
#define BUS_MSTOP_BITS_MASK GENMASK(15, 0)
#define BUS_MSTOP(idx, mask) (FIELD_PREP_CONST(BUS_MSTOP_IDX_MASK, (idx)) | \
@@ -74,8 +142,13 @@ struct cpg_core_clk {
union {
unsigned int conf;
struct ddiv ddiv;
struct pll pll;
struct smuxed smux;
} cfg;
const struct clk_div_table *dtable;
const char * const *parent_names;
unsigned int num_parents;
u8 mux_flags;
u32 flag;
};
@@ -85,20 +158,15 @@ enum clk_types {
CLK_TYPE_FF, /* Fixed Factor Clock */
CLK_TYPE_PLL,
CLK_TYPE_DDIV, /* Dynamic Switching Divider */
CLK_TYPE_SMUX, /* Static Mux */
};
/* BIT(31) indicates if CLK1/2 are accessible or not */
#define PLL_CONF(n) (BIT(31) | ((n) & ~GENMASK(31, 16)))
#define PLL_CLK_ACCESS(n) ((n) & BIT(31) ? 1 : 0)
#define PLL_CLK1_OFFSET(n) ((n) & ~GENMASK(31, 16))
#define PLL_CLK2_OFFSET(n) (((n) & ~GENMASK(31, 16)) + (0x4))
#define DEF_TYPE(_name, _id, _type...) \
{ .name = _name, .id = _id, .type = _type }
#define DEF_BASE(_name, _id, _type, _parent...) \
DEF_TYPE(_name, _id, _type, .parent = _parent)
#define DEF_PLL(_name, _id, _parent, _conf) \
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.conf = _conf)
#define DEF_PLL(_name, _id, _parent, _pll_packed) \
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.pll = _pll_packed)
#define DEF_INPUT(_name, _id) \
DEF_TYPE(_name, _id, CLK_TYPE_IN)
#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
@@ -109,6 +177,15 @@ enum clk_types {
.parent = _parent, \
.dtable = _dtable, \
.flag = CLK_DIVIDER_HIWORD_MASK)
#define DEF_CSDIV(_name, _id, _parent, _ddiv_packed, _dtable) \
DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable)
#define DEF_SMUX(_name, _id, _smux_packed, _parent_names) \
DEF_TYPE(_name, _id, CLK_TYPE_SMUX, \
.cfg.smux = _smux_packed, \
.parent_names = _parent_names, \
.num_parents = ARRAY_SIZE(_parent_names), \
.flag = CLK_SET_RATE_PARENT, \
.mux_flags = CLK_MUX_HIWORD_MASK)
/**
* struct rzv2h_mod_clk - Module Clocks definitions
@@ -221,6 +298,7 @@ struct rzv2h_cpg_info {
};
extern const struct rzv2h_cpg_info r9a09g047_cpg_info;
extern const struct rzv2h_cpg_info r9a09g056_cpg_info;
extern const struct rzv2h_cpg_info r9a09g057_cpg_info;
#endif /* __RENESAS_RZV2H_CPG_H__ */

View File

@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0-only
config SPACEMIT_CCU
tristate "Clock support for SpacemiT SoCs"
depends on ARCH_SPACEMIT || COMPILE_TEST
select MFD_SYSCON
help
Say Y to enable clock controller unit support for SpacemiT SoCs.
if SPACEMIT_CCU
config SPACEMIT_K1_CCU
tristate "Support for SpacemiT K1 SoC"
depends on ARCH_SPACEMIT || COMPILE_TEST
help
Support for clock controller unit in SpacemiT K1 SoC.
endif

View File

@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SPACEMIT_K1_CCU) = spacemit-ccu-k1.o
spacemit-ccu-k1-y = ccu_pll.o ccu_mix.o ccu_ddn.o
spacemit-ccu-k1-y += ccu-k1.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*/
#ifndef _CCU_COMMON_H_
#define _CCU_COMMON_H_
#include <linux/regmap.h>
struct ccu_common {
struct regmap *regmap;
struct regmap *lock_regmap;
union {
/* For DDN and MIX */
struct {
u32 reg_ctrl;
u32 reg_fc;
u32 mask_fc;
};
/* For PLL */
struct {
u32 reg_swcr1;
u32 reg_swcr3;
};
};
struct clk_hw hw;
};
static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
{
return container_of(hw, struct ccu_common, hw);
}
#define ccu_read(c, reg) \
({ \
u32 tmp; \
regmap_read((c)->regmap, (c)->reg_##reg, &tmp); \
tmp; \
})
#define ccu_update(c, reg, mask, val) \
regmap_update_bits((c)->regmap, (c)->reg_##reg, mask, val)
#endif /* _CCU_COMMON_H_ */

View File

@@ -0,0 +1,83 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*
* DDN stands for "Divider Denominator Numerator", it's M/N clock with a
* constant x2 factor. This clock hardware follows the equation below,
*
* numerator Fin
* 2 * ------------- = -------
* denominator Fout
*
* Thus, Fout could be calculated with,
*
* Fin denominator
* Fout = ----- * -------------
* 2 numerator
*/
#include <linux/clk-provider.h>
#include <linux/rational.h>
#include "ccu_ddn.h"
static unsigned long ccu_ddn_calc_rate(unsigned long prate,
unsigned long num, unsigned long den)
{
return prate * den / 2 / num;
}
static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn,
unsigned long rate, unsigned long prate,
unsigned long *num, unsigned long *den)
{
rational_best_approximation(rate, prate / 2,
ddn->den_mask >> ddn->den_shift,
ddn->num_mask >> ddn->num_shift,
den, num);
return ccu_ddn_calc_rate(prate, *num, *den);
}
static long ccu_ddn_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
unsigned long num, den;
return ccu_ddn_calc_best_rate(ddn, rate, *prate, &num, &den);
}
static unsigned long ccu_ddn_recalc_rate(struct clk_hw *hw, unsigned long prate)
{
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
unsigned int val, num, den;
val = ccu_read(&ddn->common, ctrl);
num = (val & ddn->num_mask) >> ddn->num_shift;
den = (val & ddn->den_mask) >> ddn->den_shift;
return ccu_ddn_calc_rate(prate, num, den);
}
static int ccu_ddn_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct ccu_ddn *ddn = hw_to_ccu_ddn(hw);
unsigned long num, den;
ccu_ddn_calc_best_rate(ddn, rate, prate, &num, &den);
ccu_update(&ddn->common, ctrl,
ddn->num_mask | ddn->den_mask,
(num << ddn->num_shift) | (den << ddn->den_shift));
return 0;
}
const struct clk_ops spacemit_ccu_ddn_ops = {
.recalc_rate = ccu_ddn_recalc_rate,
.round_rate = ccu_ddn_round_rate,
.set_rate = ccu_ddn_set_rate,
};

View File

@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*/
#ifndef _CCU_DDN_H_
#define _CCU_DDN_H_
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include "ccu_common.h"
struct ccu_ddn {
struct ccu_common common;
unsigned int num_mask;
unsigned int num_shift;
unsigned int den_mask;
unsigned int den_shift;
};
#define CCU_DDN_INIT(_name, _parent, _flags) \
CLK_HW_INIT_HW(#_name, &_parent.common.hw, &spacemit_ccu_ddn_ops, _flags)
#define CCU_DDN_DEFINE(_name, _parent, _reg_ctrl, _num_shift, _num_width, \
_den_shift, _den_width, _flags) \
static struct ccu_ddn _name = { \
.common = { \
.reg_ctrl = _reg_ctrl, \
.hw.init = CCU_DDN_INIT(_name, _parent, _flags), \
}, \
.num_mask = GENMASK(_num_shift + _num_width - 1, _num_shift), \
.num_shift = _num_shift, \
.den_mask = GENMASK(_den_shift + _den_width - 1, _den_shift), \
.den_shift = _den_shift, \
}
static inline struct ccu_ddn *hw_to_ccu_ddn(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
return container_of(common, struct ccu_ddn, common);
}
extern const struct clk_ops spacemit_ccu_ddn_ops;
#endif

View File

@@ -0,0 +1,268 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*
* MIX clock type is the combination of mux, factor or divider, and gate
*/
#include <linux/clk-provider.h>
#include "ccu_mix.h"
#define MIX_FC_TIMEOUT_US 10000
#define MIX_FC_DELAY_US 5
static void ccu_gate_disable(struct clk_hw *hw)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
ccu_update(&mix->common, ctrl, mix->gate.mask, 0);
}
static int ccu_gate_enable(struct clk_hw *hw)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_gate_config *gate = &mix->gate;
ccu_update(&mix->common, ctrl, gate->mask, gate->mask);
return 0;
}
static int ccu_gate_is_enabled(struct clk_hw *hw)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_gate_config *gate = &mix->gate;
return (ccu_read(&mix->common, ctrl) & gate->mask) == gate->mask;
}
static unsigned long ccu_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
return parent_rate * mix->factor.mul / mix->factor.div;
}
static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_div_config *div = &mix->div;
unsigned long val;
val = ccu_read(&mix->common, ctrl) >> div->shift;
val &= (1 << div->width) - 1;
return divider_recalc_rate(hw, parent_rate, val, NULL, 0, div->width);
}
/*
* Some clocks require a "FC" (frequency change) bit to be set after changing
* their rates or reparenting. This bit will be automatically cleared by
* hardware in MIX_FC_TIMEOUT_US, which indicates the operation is completed.
*/
static int ccu_mix_trigger_fc(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
unsigned int val;
if (common->reg_fc)
return 0;
ccu_update(common, fc, common->mask_fc, common->mask_fc);
return regmap_read_poll_timeout_atomic(common->regmap, common->reg_fc,
val, !(val & common->mask_fc),
MIX_FC_DELAY_US,
MIX_FC_TIMEOUT_US);
}
static long ccu_factor_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return ccu_factor_recalc_rate(hw, *prate);
}
static int ccu_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return 0;
}
static unsigned long
ccu_mix_calc_best_rate(struct clk_hw *hw, unsigned long rate,
struct clk_hw **best_parent,
unsigned long *best_parent_rate,
u32 *div_val)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
unsigned int parent_num = clk_hw_get_num_parents(hw);
struct ccu_div_config *div = &mix->div;
u32 div_max = 1 << div->width;
unsigned long best_rate = 0;
for (int i = 0; i < parent_num; i++) {
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
unsigned long parent_rate;
if (!parent)
continue;
parent_rate = clk_hw_get_rate(parent);
for (int j = 1; j <= div_max; j++) {
unsigned long tmp = DIV_ROUND_CLOSEST_ULL(parent_rate, j);
if (abs(tmp - rate) < abs(best_rate - rate)) {
best_rate = tmp;
if (div_val)
*div_val = j - 1;
if (best_parent) {
*best_parent = parent;
*best_parent_rate = parent_rate;
}
}
}
}
return best_rate;
}
static int ccu_mix_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
req->rate = ccu_mix_calc_best_rate(hw, req->rate,
&req->best_parent_hw,
&req->best_parent_rate,
NULL);
return 0;
}
static int ccu_mix_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_common *common = &mix->common;
struct ccu_div_config *div = &mix->div;
u32 current_div, target_div, mask;
ccu_mix_calc_best_rate(hw, rate, NULL, NULL, &target_div);
current_div = ccu_read(common, ctrl) >> div->shift;
current_div &= (1 << div->width) - 1;
if (current_div == target_div)
return 0;
mask = GENMASK(div->width + div->shift - 1, div->shift);
ccu_update(common, ctrl, mask, target_div << div->shift);
return ccu_mix_trigger_fc(hw);
}
static u8 ccu_mux_get_parent(struct clk_hw *hw)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_mux_config *mux = &mix->mux;
u8 parent;
parent = ccu_read(&mix->common, ctrl) >> mux->shift;
parent &= (1 << mux->width) - 1;
return parent;
}
static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct ccu_mix *mix = hw_to_ccu_mix(hw);
struct ccu_mux_config *mux = &mix->mux;
u32 mask;
mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
ccu_update(&mix->common, ctrl, mask, index << mux->shift);
return ccu_mix_trigger_fc(hw);
}
const struct clk_ops spacemit_ccu_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
};
const struct clk_ops spacemit_ccu_factor_ops = {
.round_rate = ccu_factor_round_rate,
.recalc_rate = ccu_factor_recalc_rate,
.set_rate = ccu_factor_set_rate,
};
const struct clk_ops spacemit_ccu_mux_ops = {
.determine_rate = ccu_mix_determine_rate,
.get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent,
};
const struct clk_ops spacemit_ccu_div_ops = {
.determine_rate = ccu_mix_determine_rate,
.recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_mix_set_rate,
};
const struct clk_ops spacemit_ccu_factor_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
.round_rate = ccu_factor_round_rate,
.recalc_rate = ccu_factor_recalc_rate,
.set_rate = ccu_factor_set_rate,
};
const struct clk_ops spacemit_ccu_mux_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
.determine_rate = ccu_mix_determine_rate,
.get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent,
};
const struct clk_ops spacemit_ccu_div_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
.determine_rate = ccu_mix_determine_rate,
.recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_mix_set_rate,
};
const struct clk_ops spacemit_ccu_mux_div_gate_ops = {
.disable = ccu_gate_disable,
.enable = ccu_gate_enable,
.is_enabled = ccu_gate_is_enabled,
.get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent,
.determine_rate = ccu_mix_determine_rate,
.recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_mix_set_rate,
};
const struct clk_ops spacemit_ccu_mux_div_ops = {
.get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent,
.determine_rate = ccu_mix_determine_rate,
.recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_mix_set_rate,
};

View File

@@ -0,0 +1,218 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*/
#ifndef _CCU_MIX_H_
#define _CCU_MIX_H_
#include <linux/clk-provider.h>
#include "ccu_common.h"
/**
* struct ccu_gate_config - Gate configuration
*
* @mask: Mask to enable the gate. Some clocks may have more than one bit
* set in this field.
*/
struct ccu_gate_config {
u32 mask;
};
struct ccu_factor_config {
u32 div;
u32 mul;
};
struct ccu_mux_config {
u8 shift;
u8 width;
};
struct ccu_div_config {
u8 shift;
u8 width;
};
struct ccu_mix {
struct ccu_factor_config factor;
struct ccu_gate_config gate;
struct ccu_div_config div;
struct ccu_mux_config mux;
struct ccu_common common;
};
#define CCU_GATE_INIT(_mask) { .mask = _mask }
#define CCU_FACTOR_INIT(_div, _mul) { .div = _div, .mul = _mul }
#define CCU_MUX_INIT(_shift, _width) { .shift = _shift, .width = _width }
#define CCU_DIV_INIT(_shift, _width) { .shift = _shift, .width = _width }
#define CCU_PARENT_HW(_parent) { .hw = &_parent.common.hw }
#define CCU_PARENT_NAME(_name) { .fw_name = #_name }
#define CCU_MIX_INITHW(_name, _parent, _ops, _flags) \
.hw.init = &(struct clk_init_data) { \
.flags = _flags, \
.name = #_name, \
.parent_data = (const struct clk_parent_data[]) \
{ _parent }, \
.num_parents = 1, \
.ops = &_ops, \
}
#define CCU_MIX_INITHW_PARENTS(_name, _parents, _ops, _flags) \
.hw.init = CLK_HW_INIT_PARENTS_DATA(#_name, _parents, &_ops, _flags)
#define CCU_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _flags) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags), \
} \
}
#define CCU_FACTOR_DEFINE(_name, _parent, _div, _mul) \
static struct ccu_mix _name = { \
.factor = CCU_FACTOR_INIT(_div, _mul), \
.common = { \
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_ops, 0), \
} \
}
#define CCU_MUX_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, _flags) \
static struct ccu_mix _name = { \
.mux = CCU_MUX_INIT(_shift, _width), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
_flags), \
} \
}
#define CCU_DIV_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, _flags) \
static struct ccu_mix _name = { \
.div = CCU_DIV_INIT(_shift, _width), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_ops, _flags) \
} \
}
#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \
_mul) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.factor = CCU_FACTOR_INIT(_div, _mul), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, 0) \
} \
}
#define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, \
_mask_gate, _flags) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.mux = CCU_MUX_INIT(_shift, _width), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW_PARENTS(_name, _parents, \
spacemit_ccu_mux_gate_ops, _flags), \
} \
}
#define CCU_DIV_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, \
_mask_gate, _flags) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.div = CCU_DIV_INIT(_shift, _width), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops, \
_flags), \
} \
}
#define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
_muxshift, _muxwidth, _mask_gate, _flags) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.div = CCU_DIV_INIT(_mshift, _mwidth), \
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
.common = { \
.reg_ctrl = _reg_ctrl, \
CCU_MIX_INITHW_PARENTS(_name, _parents, \
spacemit_ccu_mux_div_gate_ops, _flags), \
}, \
}
#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_fc, \
_mshift, _mwidth, _mask_fc, _muxshift, \
_muxwidth, _mask_gate, _flags) \
static struct ccu_mix _name = { \
.gate = CCU_GATE_INIT(_mask_gate), \
.div = CCU_DIV_INIT(_mshift, _mwidth), \
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
.common = { \
.reg_ctrl = _reg_ctrl, \
.reg_fc = _reg_fc, \
.mask_fc = _mask_fc, \
CCU_MIX_INITHW_PARENTS(_name, _parents, \
spacemit_ccu_mux_div_gate_ops, _flags), \
}, \
}
#define CCU_MUX_DIV_GATE_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,\
_mask_fc, _muxshift, _muxwidth, _mask_gate, \
_flags) \
CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_ctrl, _mshift,\
_mwidth, _mask_fc, _muxshift, _muxwidth, \
_mask_gate, _flags)
#define CCU_MUX_DIV_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
_mask_fc, _muxshift, _muxwidth, _flags) \
static struct ccu_mix _name = { \
.div = CCU_DIV_INIT(_mshift, _mwidth), \
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
.common = { \
.reg_ctrl = _reg_ctrl, \
.reg_fc = _reg_ctrl, \
.mask_fc = _mask_fc, \
CCU_MIX_INITHW_PARENTS(_name, _parents, \
spacemit_ccu_mux_div_ops, _flags), \
}, \
}
#define CCU_MUX_FC_DEFINE(_name, _parents, _reg_ctrl, _mask_fc, _muxshift, \
_muxwidth, _flags) \
static struct ccu_mix _name = { \
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
.common = { \
.reg_ctrl = _reg_ctrl, \
.reg_fc = _reg_ctrl, \
.mask_fc = _mask_fc, \
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
_flags) \
}, \
}
static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
return container_of(common, struct ccu_mix, common);
}
extern const struct clk_ops spacemit_ccu_gate_ops;
extern const struct clk_ops spacemit_ccu_factor_ops;
extern const struct clk_ops spacemit_ccu_mux_ops;
extern const struct clk_ops spacemit_ccu_div_ops;
extern const struct clk_ops spacemit_ccu_factor_gate_ops;
extern const struct clk_ops spacemit_ccu_div_gate_ops;
extern const struct clk_ops spacemit_ccu_mux_gate_ops;
extern const struct clk_ops spacemit_ccu_mux_div_ops;
extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
#endif /* _CCU_DIV_H_ */

View File

@@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*/
#include <linux/clk-provider.h>
#include <linux/math.h>
#include <linux/regmap.h>
#include "ccu_common.h"
#include "ccu_pll.h"
#define PLL_TIMEOUT_US 3000
#define PLL_DELAY_US 5
#define PLL_SWCR3_EN ((u32)BIT(31))
#define PLL_SWCR3_MASK GENMASK(30, 0)
static const struct ccu_pll_rate_tbl *ccu_pll_lookup_best_rate(struct ccu_pll *pll,
unsigned long rate)
{
struct ccu_pll_config *config = &pll->config;
const struct ccu_pll_rate_tbl *best_entry;
unsigned long best_delta = ULONG_MAX;
int i;
for (i = 0; i < config->tbl_num; i++) {
const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
unsigned long delta = abs_diff(entry->rate, rate);
if (delta < best_delta) {
best_delta = delta;
best_entry = entry;
}
}
return best_entry;
}
static const struct ccu_pll_rate_tbl *ccu_pll_lookup_matched_entry(struct ccu_pll *pll)
{
struct ccu_pll_config *config = &pll->config;
u32 swcr1, swcr3;
int i;
swcr1 = ccu_read(&pll->common, swcr1);
swcr3 = ccu_read(&pll->common, swcr3);
swcr3 &= PLL_SWCR3_MASK;
for (i = 0; i < config->tbl_num; i++) {
const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
if (swcr1 == entry->swcr1 && swcr3 == entry->swcr3)
return entry;
}
return NULL;
}
static void ccu_pll_update_param(struct ccu_pll *pll, const struct ccu_pll_rate_tbl *entry)
{
struct ccu_common *common = &pll->common;
regmap_write(common->regmap, common->reg_swcr1, entry->swcr1);
ccu_update(common, swcr3, PLL_SWCR3_MASK, entry->swcr3);
}
static int ccu_pll_is_enabled(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
return ccu_read(common, swcr3) & PLL_SWCR3_EN;
}
static int ccu_pll_enable(struct clk_hw *hw)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
struct ccu_common *common = &pll->common;
unsigned int tmp;
ccu_update(common, swcr3, PLL_SWCR3_EN, PLL_SWCR3_EN);
/* check lock status */
return regmap_read_poll_timeout_atomic(common->lock_regmap,
pll->config.reg_lock,
tmp,
tmp & pll->config.mask_lock,
PLL_DELAY_US, PLL_TIMEOUT_US);
}
static void ccu_pll_disable(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
ccu_update(common, swcr3, PLL_SWCR3_EN, 0);
}
/*
* PLLs must be gated before changing rate, which is ensured by
* flag CLK_SET_RATE_GATE.
*/
static int ccu_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
const struct ccu_pll_rate_tbl *entry;
entry = ccu_pll_lookup_best_rate(pll, rate);
ccu_pll_update_param(pll, entry);
return 0;
}
static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
const struct ccu_pll_rate_tbl *entry;
entry = ccu_pll_lookup_matched_entry(pll);
WARN_ON_ONCE(!entry);
return entry ? entry->rate : -EINVAL;
}
static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
return ccu_pll_lookup_best_rate(pll, rate)->rate;
}
static int ccu_pll_init(struct clk_hw *hw)
{
struct ccu_pll *pll = hw_to_ccu_pll(hw);
if (ccu_pll_lookup_matched_entry(pll))
return 0;
ccu_pll_disable(hw);
ccu_pll_update_param(pll, &pll->config.rate_tbl[0]);
return 0;
}
const struct clk_ops spacemit_ccu_pll_ops = {
.init = ccu_pll_init,
.enable = ccu_pll_enable,
.disable = ccu_pll_disable,
.set_rate = ccu_pll_set_rate,
.recalc_rate = ccu_pll_recalc_rate,
.round_rate = ccu_pll_round_rate,
.is_enabled = ccu_pll_is_enabled,
};

View File

@@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
*/
#ifndef _CCU_PLL_H_
#define _CCU_PLL_H_
#include <linux/clk-provider.h>
#include "ccu_common.h"
/**
* struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register
* configuration.
*
* @rate: PLL rate
* @swcr1: Register value of PLLX_SW1_CTRL (PLLx_SWCR1).
* @swcr3: Register value of the PLLx_SW3_CTRL's lowest 31 bits of
* PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling
* the PLL and not contained in this field.
*/
struct ccu_pll_rate_tbl {
unsigned long rate;
u32 swcr1;
u32 swcr3;
};
struct ccu_pll_config {
const struct ccu_pll_rate_tbl *rate_tbl;
u32 tbl_num;
u32 reg_lock;
u32 mask_lock;
};
#define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \
{ \
.rate = _rate, \
.swcr1 = _swcr1, \
.swcr3 = _swcr3, \
}
struct ccu_pll {
struct ccu_common common;
struct ccu_pll_config config;
};
#define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \
{ \
.rate_tbl = _table, \
.tbl_num = ARRAY_SIZE(_table), \
.reg_lock = (_reg_lock), \
.mask_lock = (_mask_lock), \
}
#define CCU_PLL_HWINIT(_name, _flags) \
(&(struct clk_init_data) { \
.name = #_name, \
.ops = &spacemit_ccu_pll_ops, \
.parent_data = &(struct clk_parent_data) { .index = 0 }, \
.num_parents = 1, \
.flags = _flags, \
})
#define CCU_PLL_DEFINE(_name, _table, _reg_swcr1, _reg_swcr3, _reg_lock, \
_mask_lock, _flags) \
static struct ccu_pll _name = { \
.config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \
.common = { \
.reg_swcr1 = _reg_swcr1, \
.reg_swcr3 = _reg_swcr3, \
.hw.init = CCU_PLL_HWINIT(_name, _flags) \
} \
}
static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)
{
struct ccu_common *common = hw_to_ccu_common(hw);
return container_of(common, struct ccu_pll, common);
}
extern const struct clk_ops spacemit_ccu_pll_ops;
#endif

View File

@@ -17,5 +17,8 @@
#define R9A09G047_CM33_CLK0 6
#define R9A09G047_CST_0_SWCLKTCK 7
#define R9A09G047_IOTOP_0_SHCLK 8
#define R9A09G047_SPI_CLK_SPI 9
#define R9A09G047_GBETH_0_CLK_PTP_REF_I 10
#define R9A09G047_GBETH_1_CLK_PTP_REF_I 11
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G047_CPG_H__ */

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
*
* Copyright (C) 2025 Renesas Electronics Corp.
*/
#ifndef __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__
#define __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__
#include <dt-bindings/clock/renesas-cpg-mssr.h>
/* Core Clock list */
#define R9A09G056_SYS_0_PCLK 0
#define R9A09G056_CA55_0_CORE_CLK0 1
#define R9A09G056_CA55_0_CORE_CLK1 2
#define R9A09G056_CA55_0_CORE_CLK2 3
#define R9A09G056_CA55_0_CORE_CLK3 4
#define R9A09G056_CA55_0_PERIPHCLK 5
#define R9A09G056_CM33_CLK0 6
#define R9A09G056_CST_0_SWCLKTCK 7
#define R9A09G056_IOTOP_0_SHCLK 8
#define R9A09G056_USB2_0_CLK_CORE0 9
#define R9A09G056_GBETH_0_CLK_PTP_REF_I 10
#define R9A09G056_GBETH_1_CLK_PTP_REF_I 11
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G056_CPG_H__ */

View File

@@ -17,5 +17,9 @@
#define R9A09G057_CM33_CLK0 6
#define R9A09G057_CST_0_SWCLKTCK 7
#define R9A09G057_IOTOP_0_SHCLK 8
#define R9A09G057_USB2_0_CLK_CORE0 9
#define R9A09G057_USB2_0_CLK_CORE1 10
#define R9A09G057_GBETH_0_CLK_PTP_REF_I 11
#define R9A09G057_GBETH_1_CLK_PTP_REF_I 12
#endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G057_CPG_H__ */

View File

@@ -0,0 +1,247 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (C) 2024-2025 Haylen Chu <heylenay@outlook.com>
*/
#ifndef _DT_BINDINGS_SPACEMIT_CCU_H_
#define _DT_BINDINGS_SPACEMIT_CCU_H_
/* APBS (PLL) clocks */
#define CLK_PLL1 0
#define CLK_PLL2 1
#define CLK_PLL3 2
#define CLK_PLL1_D2 3
#define CLK_PLL1_D3 4
#define CLK_PLL1_D4 5
#define CLK_PLL1_D5 6
#define CLK_PLL1_D6 7
#define CLK_PLL1_D7 8
#define CLK_PLL1_D8 9
#define CLK_PLL1_D11 10
#define CLK_PLL1_D13 11
#define CLK_PLL1_D23 12
#define CLK_PLL1_D64 13
#define CLK_PLL1_D10_AUD 14
#define CLK_PLL1_D100_AUD 15
#define CLK_PLL2_D1 16
#define CLK_PLL2_D2 17
#define CLK_PLL2_D3 18
#define CLK_PLL2_D4 19
#define CLK_PLL2_D5 20
#define CLK_PLL2_D6 21
#define CLK_PLL2_D7 22
#define CLK_PLL2_D8 23
#define CLK_PLL3_D1 24
#define CLK_PLL3_D2 25
#define CLK_PLL3_D3 26
#define CLK_PLL3_D4 27
#define CLK_PLL3_D5 28
#define CLK_PLL3_D6 29
#define CLK_PLL3_D7 30
#define CLK_PLL3_D8 31
#define CLK_PLL3_80 32
#define CLK_PLL3_40 33
#define CLK_PLL3_20 34
/* MPMU clocks */
#define CLK_PLL1_307P2 0
#define CLK_PLL1_76P8 1
#define CLK_PLL1_61P44 2
#define CLK_PLL1_153P6 3
#define CLK_PLL1_102P4 4
#define CLK_PLL1_51P2 5
#define CLK_PLL1_51P2_AP 6
#define CLK_PLL1_57P6 7
#define CLK_PLL1_25P6 8
#define CLK_PLL1_12P8 9
#define CLK_PLL1_12P8_WDT 10
#define CLK_PLL1_6P4 11
#define CLK_PLL1_3P2 12
#define CLK_PLL1_1P6 13
#define CLK_PLL1_0P8 14
#define CLK_PLL1_409P6 15
#define CLK_PLL1_204P8 16
#define CLK_PLL1_491 17
#define CLK_PLL1_245P76 18
#define CLK_PLL1_614 19
#define CLK_PLL1_47P26 20
#define CLK_PLL1_31P5 21
#define CLK_PLL1_819 22
#define CLK_PLL1_1228 23
#define CLK_SLOW_UART 24
#define CLK_SLOW_UART1 25
#define CLK_SLOW_UART2 26
#define CLK_WDT 27
#define CLK_RIPC 28
#define CLK_I2S_SYSCLK 29
#define CLK_I2S_BCLK 30
#define CLK_APB 31
#define CLK_WDT_BUS 32
/* APBC clocks */
#define CLK_UART0 0
#define CLK_UART2 1
#define CLK_UART3 2
#define CLK_UART4 3
#define CLK_UART5 4
#define CLK_UART6 5
#define CLK_UART7 6
#define CLK_UART8 7
#define CLK_UART9 8
#define CLK_GPIO 9
#define CLK_PWM0 10
#define CLK_PWM1 11
#define CLK_PWM2 12
#define CLK_PWM3 13
#define CLK_PWM4 14
#define CLK_PWM5 15
#define CLK_PWM6 16
#define CLK_PWM7 17
#define CLK_PWM8 18
#define CLK_PWM9 19
#define CLK_PWM10 20
#define CLK_PWM11 21
#define CLK_PWM12 22
#define CLK_PWM13 23
#define CLK_PWM14 24
#define CLK_PWM15 25
#define CLK_PWM16 26
#define CLK_PWM17 27
#define CLK_PWM18 28
#define CLK_PWM19 29
#define CLK_SSP3 30
#define CLK_RTC 31
#define CLK_TWSI0 32
#define CLK_TWSI1 33
#define CLK_TWSI2 34
#define CLK_TWSI4 35
#define CLK_TWSI5 36
#define CLK_TWSI6 37
#define CLK_TWSI7 38
#define CLK_TWSI8 39
#define CLK_TIMERS1 40
#define CLK_TIMERS2 41
#define CLK_AIB 42
#define CLK_ONEWIRE 43
#define CLK_SSPA0 44
#define CLK_SSPA1 45
#define CLK_DRO 46
#define CLK_IR 47
#define CLK_TSEN 48
#define CLK_IPC_AP2AUD 49
#define CLK_CAN0 50
#define CLK_CAN0_BUS 51
#define CLK_UART0_BUS 52
#define CLK_UART2_BUS 53
#define CLK_UART3_BUS 54
#define CLK_UART4_BUS 55
#define CLK_UART5_BUS 56
#define CLK_UART6_BUS 57
#define CLK_UART7_BUS 58
#define CLK_UART8_BUS 59
#define CLK_UART9_BUS 60
#define CLK_GPIO_BUS 61
#define CLK_PWM0_BUS 62
#define CLK_PWM1_BUS 63
#define CLK_PWM2_BUS 64
#define CLK_PWM3_BUS 65
#define CLK_PWM4_BUS 66
#define CLK_PWM5_BUS 67
#define CLK_PWM6_BUS 68
#define CLK_PWM7_BUS 69
#define CLK_PWM8_BUS 70
#define CLK_PWM9_BUS 71
#define CLK_PWM10_BUS 72
#define CLK_PWM11_BUS 73
#define CLK_PWM12_BUS 74
#define CLK_PWM13_BUS 75
#define CLK_PWM14_BUS 76
#define CLK_PWM15_BUS 77
#define CLK_PWM16_BUS 78
#define CLK_PWM17_BUS 79
#define CLK_PWM18_BUS 80
#define CLK_PWM19_BUS 81
#define CLK_SSP3_BUS 82
#define CLK_RTC_BUS 83
#define CLK_TWSI0_BUS 84
#define CLK_TWSI1_BUS 85
#define CLK_TWSI2_BUS 86
#define CLK_TWSI4_BUS 87
#define CLK_TWSI5_BUS 88
#define CLK_TWSI6_BUS 89
#define CLK_TWSI7_BUS 90
#define CLK_TWSI8_BUS 91
#define CLK_TIMERS1_BUS 92
#define CLK_TIMERS2_BUS 93
#define CLK_AIB_BUS 94
#define CLK_ONEWIRE_BUS 95
#define CLK_SSPA0_BUS 96
#define CLK_SSPA1_BUS 97
#define CLK_TSEN_BUS 98
#define CLK_IPC_AP2AUD_BUS 99
/* APMU clocks */
#define CLK_CCI550 0
#define CLK_CPU_C0_HI 1
#define CLK_CPU_C0_CORE 2
#define CLK_CPU_C0_ACE 3
#define CLK_CPU_C0_TCM 4
#define CLK_CPU_C1_HI 5
#define CLK_CPU_C1_CORE 6
#define CLK_CPU_C1_ACE 7
#define CLK_CCIC_4X 8
#define CLK_CCIC1PHY 9
#define CLK_SDH_AXI 10
#define CLK_SDH0 11
#define CLK_SDH1 12
#define CLK_SDH2 13
#define CLK_USB_P1 14
#define CLK_USB_AXI 15
#define CLK_USB30 16
#define CLK_QSPI 17
#define CLK_QSPI_BUS 18
#define CLK_DMA 19
#define CLK_AES 20
#define CLK_VPU 21
#define CLK_GPU 22
#define CLK_EMMC 23
#define CLK_EMMC_X 24
#define CLK_AUDIO 25
#define CLK_HDMI 26
#define CLK_PMUA_ACLK 27
#define CLK_PCIE0_MASTER 28
#define CLK_PCIE0_SLAVE 29
#define CLK_PCIE0_DBI 30
#define CLK_PCIE1_MASTER 31
#define CLK_PCIE1_SLAVE 32
#define CLK_PCIE1_DBI 33
#define CLK_PCIE2_MASTER 34
#define CLK_PCIE2_SLAVE 35
#define CLK_PCIE2_DBI 36
#define CLK_EMAC0_BUS 37
#define CLK_EMAC0_PTP 38
#define CLK_EMAC1_BUS 39
#define CLK_EMAC1_PTP 40
#define CLK_JPG 41
#define CLK_CCIC2PHY 42
#define CLK_CCIC3PHY 43
#define CLK_CSI 44
#define CLK_CAMM0 45
#define CLK_CAMM1 46
#define CLK_CAMM2 47
#define CLK_ISP_CPP 48
#define CLK_ISP_BUS 49
#define CLK_ISP 50
#define CLK_DPU_MCLK 51
#define CLK_DPU_ESC 52
#define CLK_DPU_BIT 53
#define CLK_DPU_PXCLK 54
#define CLK_DPU_HCLK 55
#define CLK_DPU_SPI 56
#define CLK_DPU_SPI_HBUS 57
#define CLK_DPU_SPIBUS 58
#define CLK_DPU_SPI_ACLK 59
#define CLK_V2D 60
#define CLK_EMMC_BUS 61
#endif /* _DT_BINDINGS_SPACEMIT_CCU_H_ */

View File

@@ -6,6 +6,7 @@ struct clk;
struct clk_hw;
struct device;
struct device_node;
struct of_phandle_args;
struct kunit;
struct clk *