mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-02 16:42:00 -05:00
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:
@@ -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:
|
||||
|
||||
50
Documentation/devicetree/bindings/clock/spacemit,k1-pll.yaml
Normal file
50
Documentation/devicetree/bindings/clock/spacemit,k1-pll.yaml
Normal 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>;
|
||||
};
|
||||
@@ -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:
|
||||
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a09g047-sys # RZ/G3E
|
||||
- renesas,r9a09g056-sys # RZ/V2N
|
||||
- renesas,r9a09g057-sys # RZ/V2H
|
||||
|
||||
reg:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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"
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
152
drivers/clk/renesas/r9a09g056-cpg.c
Normal file
152
drivers/clk/renesas/r9a09g056-cpg.c
Normal 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,
|
||||
};
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */ }
|
||||
};
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
18
drivers/clk/spacemit/Kconfig
Normal file
18
drivers/clk/spacemit/Kconfig
Normal 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
|
||||
5
drivers/clk/spacemit/Makefile
Normal file
5
drivers/clk/spacemit/Makefile
Normal 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
|
||||
1164
drivers/clk/spacemit/ccu-k1.c
Normal file
1164
drivers/clk/spacemit/ccu-k1.c
Normal file
File diff suppressed because it is too large
Load Diff
48
drivers/clk/spacemit/ccu_common.h
Normal file
48
drivers/clk/spacemit/ccu_common.h
Normal 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_ */
|
||||
83
drivers/clk/spacemit/ccu_ddn.c
Normal file
83
drivers/clk/spacemit/ccu_ddn.c
Normal 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,
|
||||
};
|
||||
48
drivers/clk/spacemit/ccu_ddn.h
Normal file
48
drivers/clk/spacemit/ccu_ddn.h
Normal 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
|
||||
268
drivers/clk/spacemit/ccu_mix.c
Normal file
268
drivers/clk/spacemit/ccu_mix.c
Normal 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,
|
||||
};
|
||||
218
drivers/clk/spacemit/ccu_mix.h
Normal file
218
drivers/clk/spacemit/ccu_mix.h
Normal 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_ */
|
||||
157
drivers/clk/spacemit/ccu_pll.c
Normal file
157
drivers/clk/spacemit/ccu_pll.c
Normal 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,
|
||||
};
|
||||
86
drivers/clk/spacemit/ccu_pll.h
Normal file
86
drivers/clk/spacemit/ccu_pll.h
Normal 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
|
||||
@@ -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__ */
|
||||
|
||||
24
include/dt-bindings/clock/renesas,r9a09g056-cpg.h
Normal file
24
include/dt-bindings/clock/renesas,r9a09g056-cpg.h
Normal 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__ */
|
||||
@@ -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__ */
|
||||
|
||||
247
include/dt-bindings/clock/spacemit,k1-syscon.h
Normal file
247
include/dt-bindings/clock/spacemit,k1-syscon.h
Normal 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_ */
|
||||
@@ -6,6 +6,7 @@ struct clk;
|
||||
struct clk_hw;
|
||||
struct device;
|
||||
struct device_node;
|
||||
struct of_phandle_args;
|
||||
struct kunit;
|
||||
|
||||
struct clk *
|
||||
|
||||
Reference in New Issue
Block a user