Merge branches 'clk-tenstorrent', 'clk-rockchip', 'clk-imx' and 'clk-allwinner' into clk-next

* clk-tenstorrent:
  clk: tenstorrent: Add Atlantis clock controller driver
  reset: tenstorrent: Add reset controller for Atlantis
  dt-bindings: clk: tenstorrent: Add tenstorrent,atlantis-prcm-rcpu

* clk-rockchip:
  clk: rockchip: rk3568: Add PCIe pipe clock gates
  clk: rockchip: Add clock controller for the RV1103B
  dt-bindings: clock: rockchip: Add RV1103B CRU support

* clk-imx:
  clk: imx8mq: Correct the CSI PHY sels
  clk: vf610: Add support for the Ethernet switch clocks
  dt-bindings: clock: vf610: Add definitions for MTIP L2 switch
  dt-bindings: clock: vf610: Drop VF610_CLK_END define
  clk: vf610: Move VF610_CLK_END define to clk-vf610 driver
  clk: imx: imx8-acm: fix flags for acm clocks
  clk: imx: imx6q: Fix device node reference leak in of_assigned_ldb_sels()
  clk: imx: imx6q: Fix device node reference leak in pll6_bypassed()
  clk: imx: fracn-gppll: Add 477.4MHz support
  clk: imx: fracn-gppll: Add 333.333333 MHz support
  clk: imx: pll14xx: Use unsigned format specifier
  dt-bindings: clock: imx6q[ul]-clock: add optional clock enet[1]_ref_pad

* clk-allwinner:
  clk: sunxi-ng: sun55i-a523-r: Add missing r-spi module clock
This commit is contained in:
Stephen Boyd 2026-04-16 10:12:33 -07:00
No known key found for this signature in database
GPG Key ID: AD028897C6E49525
28 changed files with 2238 additions and 9 deletions

View File

@ -29,20 +29,24 @@ properties:
const: 1
clocks:
minItems: 5
items:
- description: 24m osc
- description: 32k osc
- description: ckih1 clock input
- description: anaclk1 clock input
- description: anaclk2 clock input
- description: clock input from enet ref pad
clock-names:
minItems: 5
items:
- const: osc
- const: ckil
- const: ckih1
- const: anaclk1
- const: anaclk2
- const: enet_ref_pad
fsl,pmic-stby-poweroff:
$ref: /schemas/types.yaml#/definitions/flag

View File

@ -29,18 +29,22 @@ properties:
const: 1
clocks:
minItems: 4
items:
- description: 32k osc
- description: 24m osc
- description: ipp_di0 clock input
- description: ipp_di1 clock input
- description: clock input from enet1 ref pad
clock-names:
minItems: 4
items:
- const: ckil
- const: osc
- const: ipp_di0
- const: ipp_di1
- const: enet1_ref_pad
required:
- compatible

View File

@ -17,6 +17,7 @@ description:
properties:
compatible:
enum:
- rockchip,rv1103b-cru
- rockchip,rv1126b-cru
reg:

View File

@ -0,0 +1,54 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/tenstorrent,atlantis-prcm-rcpu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Tenstorrent Atlantis PRCM (Power, Reset, Clock Management) Module
maintainers:
- Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
description:
Multifunctional register block found in Tenstorrent Atlantis SoC whose main
function is to control clocks and resets. This block is instantiated multiple
times in the SoC, each block controls clock and resets for a different
subsystem. RCPU prcm serves low speed IO interfaces.
properties:
compatible:
enum:
- tenstorrent,atlantis-prcm-rcpu
reg:
maxItems: 1
clocks:
maxItems: 1
"#clock-cells":
const: 1
description:
See <dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h> for valid indices.
"#reset-cells":
const: 1
required:
- compatible
- reg
- clocks
- "#clock-cells"
- "#reset-cells"
additionalProperties: false
examples:
- |
clock-controller@a8000000 {
compatible = "tenstorrent,atlantis-prcm-rcpu";
reg = <0xa8000000 0x10000>;
clocks = <&osc_24m>;
#clock-cells = <1>;
#reset-cells = <1>;
};

View File

@ -22812,8 +22812,12 @@ M: Joel Stanley <jms@oss.tenstorrent.com>
L: linux-riscv@lists.infradead.org
S: Maintained
T: git https://github.com/tenstorrent/linux.git
F: Documentation/devicetree/bindings/clock/tenstorrent,atlantis-prcm-rcpu.yaml
F: Documentation/devicetree/bindings/riscv/tenstorrent.yaml
F: arch/riscv/boot/dts/tenstorrent/
F: drivers/clk/tenstorrent/
F: drivers/reset/reset-tenstorrent-atlantis.c
F: include/dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h
RISC-V THEAD SoC SUPPORT
M: Drew Fustini <fustini@kernel.org>

View File

@ -532,6 +532,7 @@ source "drivers/clk/starfive/Kconfig"
source "drivers/clk/sunxi/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/tenstorrent/Kconfig"
source "drivers/clk/thead/Kconfig"
source "drivers/clk/stm32/Kconfig"
source "drivers/clk/ti/Kconfig"

View File

@ -156,6 +156,7 @@ obj-y += starfive/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-y += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += tenstorrent/
obj-$(CONFIG_ARCH_THEAD) += thead/
obj-y += ti/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/

View File

@ -85,9 +85,11 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
PLL_FRACN_GP(519750000U, 173, 25, 100, 1, 8),
PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8),
PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
PLL_FRACN_GP(477400000U, 119, 35, 100, 0, 6),
PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12),
PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10),
PLL_FRACN_GP(333333333U, 125, 0, 1, 1, 9),
PLL_FRACN_GP(332600000U, 138, 584, 1000, 0, 10),
PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12),
PLL_FRACN_GP(241900000U, 201, 584, 1000, 0, 20),

View File

@ -188,9 +188,11 @@ static void of_assigned_ldb_sels(struct device_node *node,
}
if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
pr_err("ccm: parent clock %d not in ccm\n", index);
of_node_put(clkspec.np);
return;
}
parent = clkspec.args[0];
of_node_put(clkspec.np);
rc = of_parse_phandle_with_args(node, "assigned-clocks",
"#clock-cells", index, &clkspec);
@ -198,9 +200,11 @@ static void of_assigned_ldb_sels(struct device_node *node,
return;
if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
pr_err("ccm: child clock %d not in ccm\n", index);
of_node_put(clkspec.np);
return;
}
child = clkspec.args[0];
of_node_put(clkspec.np);
if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
child != IMX6QDL_CLK_LDB_DI1_SEL)
@ -238,8 +242,11 @@ static bool pll6_bypassed(struct device_node *node)
return false;
if (clkspec.np == node &&
clkspec.args[0] == IMX6QDL_PLL6_BYPASS)
clkspec.args[0] == IMX6QDL_PLL6_BYPASS) {
of_node_put(clkspec.np);
break;
}
of_node_put(clkspec.np);
}
/* PLL6 bypass is not part of the assigned clock list */
@ -249,6 +256,9 @@ static bool pll6_bypassed(struct device_node *node)
ret = of_parse_phandle_with_args(node, "assigned-clock-parents",
"#clock-cells", index, &clkspec);
if (!ret)
of_node_put(clkspec.np);
if (clkspec.args[0] != IMX6QDL_CLK_PLL6)
return true;

View File

@ -371,7 +371,8 @@ static int imx8_acm_clk_probe(struct platform_device *pdev)
for (i = 0; i < priv->soc_data->num_sels; i++) {
hws[sels[i].clkid] = devm_clk_hw_register_mux_parent_data_table(dev,
sels[i].name, sels[i].parents,
sels[i].num_parents, 0,
sels[i].num_parents,
CLK_SET_RATE_NO_REPARENT,
base + sels[i].reg,
sels[i].shift, sels[i].width,
0, NULL, NULL);

View File

@ -237,7 +237,7 @@ static const char * const imx8mq_dsi_esc_sels[] = {"osc_25m", "sys2_pll_100m", "
static const char * const imx8mq_csi1_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
static const char * const imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_333m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
@ -246,7 +246,7 @@ static const char * const imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m",
static const char * const imx8mq_csi2_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
static const char * const imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_333m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi2_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",

View File

@ -151,7 +151,7 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat
/* First try if we can get the desired rate from one of the static entries */
tt = imx_get_pll_settings(pll, rate);
if (tt) {
pr_debug("%s: in=%ld, want=%ld, Using PLL setting from table\n",
pr_debug("%s: in=%lu, want=%lu, Using PLL setting from table\n",
clk_hw_get_name(&pll->hw), prate, rate);
t->rate = tt->rate;
t->mdiv = tt->mdiv;
@ -173,7 +173,7 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat
if (rate >= rate_min && rate <= rate_max) {
kdiv = pll1443x_calc_kdiv(mdiv, pdiv, sdiv, rate, prate);
pr_debug("%s: in=%ld, want=%ld Only adjust kdiv %ld -> %d\n",
pr_debug("%s: in=%lu, want=%lu Only adjust kdiv %ld -> %d\n",
clk_hw_get_name(&pll->hw), prate, rate,
FIELD_GET(KDIV_MASK, pll_div_ctl1), kdiv);
fout = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, kdiv, prate);
@ -211,7 +211,7 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat
}
}
found:
pr_debug("%s: in=%ld, want=%ld got=%d (pdiv=%d sdiv=%d mdiv=%d kdiv=%d)\n",
pr_debug("%s: in=%lu, want=%lu got=%u (pdiv=%d sdiv=%d mdiv=%d kdiv=%d)\n",
clk_hw_get_name(&pll->hw), prate, rate, t->rate, t->pdiv, t->sdiv,
t->mdiv, t->kdiv);
}

View File

@ -11,6 +11,13 @@
#include "clk.h"
/*
* The VF610_CLK_END corresponds to ones defined in
* include/dt-bindings/clock/vf610-clock.h
* It shall be the value of the last defined clock +1
*/
#define VF610_CLK_END 196
#define CCM_CCR (ccm_base + 0x00)
#define CCM_CSR (ccm_base + 0x04)
#define CCM_CCSR (ccm_base + 0x08)
@ -313,6 +320,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", CCM_CSCDR1, 23);
clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(0));
clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(1));
clk[VF610_CLK_ESW] = imx_clk_gate2("esw", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(8));
clk[VF610_CLK_ESW_MAC_TAB0] = imx_clk_gate2("esw_tab0", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(12));
clk[VF610_CLK_ESW_MAC_TAB1] = imx_clk_gate2("esw_tab1", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(13));
clk[VF610_CLK_ESW_MAC_TAB2] = imx_clk_gate2("esw_tab2", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(14));
clk[VF610_CLK_ESW_MAC_TAB3] = imx_clk_gate2("esw_tab3", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(15));
clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7));

View File

@ -16,6 +16,13 @@ config CLK_PX30
help
Build the driver for PX30 Clock Driver.
config CLK_RV1103B
bool "Rockchip RV1103B clock controller support"
depends on ARM || COMPILE_TEST
default y
help
Build the driver for RV1103B Clock Driver.
config CLK_RV110X
bool "Rockchip RV110x clock controller support"
depends on ARM || COMPILE_TEST

View File

@ -18,6 +18,7 @@ clk-rockchip-y += gate-link.o
clk-rockchip-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-$(CONFIG_CLK_PX30) += clk-px30.o
obj-$(CONFIG_CLK_RV1103B) += clk-rv1103b.o
obj-$(CONFIG_CLK_RV110X) += clk-rv1108.o
obj-$(CONFIG_CLK_RV1126) += clk-rv1126.o
obj-$(CONFIG_CLK_RV1126B) += clk-rv1126b.o rst-rv1126b.o

View File

@ -827,6 +827,8 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
RK3568_CLKGATE_CON(12), 3, GFLAGS),
GATE(CLK_PCIE20_AUX_NDFT, "clk_pcie20_aux_ndft", "xin24m", 0,
RK3568_CLKGATE_CON(12), 4, GFLAGS),
GATE(CLK_PCIE20_PIPE_DFT, "clk_pcie20_pipe_dft", "aclk_pipe", CLK_IGNORE_UNUSED,
RK3568_CLKGATE_CON(12), 5, GFLAGS),
GATE(ACLK_PCIE30X1_MST, "aclk_pcie30x1_mst", "aclk_pipe", 0,
RK3568_CLKGATE_CON(12), 8, GFLAGS),
GATE(ACLK_PCIE30X1_SLV, "aclk_pcie30x1_slv", "aclk_pipe", 0,
@ -837,6 +839,8 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
RK3568_CLKGATE_CON(12), 11, GFLAGS),
GATE(CLK_PCIE30X1_AUX_NDFT, "clk_pcie30x1_aux_ndft", "xin24m", 0,
RK3568_CLKGATE_CON(12), 12, GFLAGS),
GATE(CLK_PCIE30X1_PIPE_DFT, "clk_pcie30x1_pipe_dft", "aclk_pipe", CLK_IGNORE_UNUSED,
RK3568_CLKGATE_CON(12), 13, GFLAGS),
GATE(ACLK_PCIE30X2_MST, "aclk_pcie30x2_mst", "aclk_pipe", 0,
RK3568_CLKGATE_CON(13), 0, GFLAGS),
GATE(ACLK_PCIE30X2_SLV, "aclk_pcie30x2_slv", "aclk_pipe", 0,
@ -847,6 +851,8 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
RK3568_CLKGATE_CON(13), 3, GFLAGS),
GATE(CLK_PCIE30X2_AUX_NDFT, "clk_pcie30x2_aux_ndft", "xin24m", 0,
RK3568_CLKGATE_CON(13), 4, GFLAGS),
GATE(CLK_PCIE30X2_PIPE_DFT, "clk_pcie30x2_pipe_dft", "aclk_pipe", CLK_IGNORE_UNUSED,
RK3568_CLKGATE_CON(13), 5, GFLAGS),
GATE(ACLK_SATA0, "aclk_sata0", "aclk_pipe", 0,
RK3568_CLKGATE_CON(11), 0, GFLAGS),
GATE(CLK_SATA0_PMALIVE, "clk_sata0_pmalive", "gpll_20m", 0,

View File

@ -0,0 +1,658 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Rockchip Electronics Co. Ltd.
* Author: Elaine Zhang <zhangqing@rock-chips.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/rockchip,rv1103b-cru.h>
#include "clk.h"
#define RV1103B_GRF_SOC_STATUS0 0x10
#define RV1103B_FRAC_MAX_PRATE 1200000000
#define PVTPLL_SRC_SEL_PVTPLL (BIT(0) | BIT(16))
enum rv1103b_plls {
dpll,
gpll,
};
static struct rockchip_pll_rate_table rv1103b_pll_rates[] = {
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
{ /* sentinel */ },
};
#define RV1103B_DIV_ACLK_CORE_MASK 0x1f
#define RV1103B_DIV_ACLK_CORE_SHIFT 0
#define RV1103B_DIV_PCLK_DBG_MASK 0x1f
#define RV1103B_DIV_PCLK_DBG_SHIFT 8
#define RV1103B_CLKSEL0(_aclk_core) \
{ \
.reg = RV1103B_CORECLKSEL_CON(2), \
.val = HIWORD_UPDATE(_aclk_core - 1, RV1103B_DIV_ACLK_CORE_MASK, \
RV1103B_DIV_ACLK_CORE_SHIFT), \
}
#define RV1103B_CLKSEL1(_pclk_dbg) \
{ \
.reg = RV1103B_CORECLKSEL_CON(2), \
.val = HIWORD_UPDATE(_pclk_dbg - 1, RV1103B_DIV_PCLK_DBG_MASK, \
RV1103B_DIV_PCLK_DBG_SHIFT), \
}
#define RV1103B_CPUCLK_RATE(_prate, _aclk_core, _pclk_dbg) \
{ \
.prate = _prate, \
.divs = { \
RV1103B_CLKSEL0(_aclk_core), \
RV1103B_CLKSEL1(_pclk_dbg), \
}, \
}
static struct rockchip_cpuclk_rate_table rv1103b_cpuclk_rates[] __initdata = {
RV1103B_CPUCLK_RATE(1608000000, 4, 10),
RV1103B_CPUCLK_RATE(1512000000, 4, 10),
RV1103B_CPUCLK_RATE(1416000000, 4, 10),
RV1103B_CPUCLK_RATE(1296000000, 3, 10),
RV1103B_CPUCLK_RATE(1200000000, 3, 10),
RV1103B_CPUCLK_RATE(1188000000, 3, 8),
RV1103B_CPUCLK_RATE(1104000000, 2, 8),
RV1103B_CPUCLK_RATE(1008000000, 2, 8),
RV1103B_CPUCLK_RATE(816000000, 2, 6),
RV1103B_CPUCLK_RATE(600000000, 2, 4),
RV1103B_CPUCLK_RATE(594000000, 2, 4),
RV1103B_CPUCLK_RATE(408000000, 1, 3),
RV1103B_CPUCLK_RATE(396000000, 1, 3),
};
PNAME(mux_pll_p) = { "xin24m" };
PNAME(mux_200m_100m_p) = { "clk_gpll_div6", "clk_gpll_div12" };
PNAME(mux_gpll_24m_p) = { "gpll", "xin24m" };
PNAME(mux_480m_400m_300m_200m_p) = { "clk_gpll_div2p5", "clk_gpll_div3", "clk_gpll_div4", "clk_gpll_div6" };
PNAME(mux_480m_400m_300m_p) = { "clk_gpll_div2p5", "clk_gpll_div3", "clk_gpll_div4" };
PNAME(mux_300m_200m_p) = { "clk_gpll_div4", "clk_gpll_div6" };
PNAME(mux_600m_480m_400m_p) = { "clk_gpll_div2", "clk_gpll_div2p5", "clk_gpll_div3" };
PNAME(mux_400m_300m_p) = { "clk_gpll_div3", "clk_gpll_div4" };
PNAME(mux_100m_24m_p) = { "clk_gpll_div12", "xin24m" };
PNAME(mux_200m_24m_p) = { "clk_gpll_div6", "xin24m" };
PNAME(mux_200m_100m_50m_24m_p) = { "clk_gpll_div6", "clk_gpll_div12", "clk_gpll_div24", "xin24m" };
PNAME(mux_300m_200m_100m_p) = { "clk_gpll_div4", "clk_gpll_div6", "clk_gpll_div12" };
PNAME(sclk_uart0_src_p) = { "clk_uart0_src", "clk_uart0_frac", "xin24m" };
PNAME(sclk_uart1_src_p) = { "clk_uart1_src", "clk_uart1_frac", "xin24m" };
PNAME(sclk_uart2_src_p) = { "clk_uart2_src", "clk_uart2_frac", "xin24m" };
PNAME(mclk_sai_src_p) = { "clk_sai_src", "clk_sai_frac", "mclk_sai_from_io", "xin_osc0_half" };
PNAME(clk_freq_pwm0_src_p) = { "sclk_sai_from_io", "mclk_sai_from_io", "clk_testout_out" };
PNAME(clk_counter_pwm0_src_p) = { "sclk_sai_from_io", "mclk_sai_from_io", "clk_testout_out" };
PNAME(clk_mipi0_out2io_p) = { "clk_ref_mipi0", "xin24m" };
PNAME(clk_mipi1_out2io_p) = { "clk_ref_mipi1", "xin24m" };
PNAME(mclk_sai_out2io_p) = { "mclk_sai_src", "xin_osc0_half" };
PNAME(aclk_npu_root_p) = { "clk_npu_src", "clk_npu_pvtpll" };
PNAME(clk_core_vepu_p) = { "clk_vepu_src", "clk_vepu_pvtpll" };
PNAME(lsclk_vi_root_p) = { "clk_gpll_div6", "lsclk_vi_100m" };
PNAME(clk_core_isp_p) = { "clk_isp_src", "clk_isp_pvtpll_src" };
PNAME(lsclk_pmu_root_p) = { "xin24m", "clk_rc_osc_io" };
PNAME(xin_rc_div_p) = { "xin24m", "clk_rc_osc_io" };
PNAME(clk_32k_p) = { "xin_rc_div", "clk_32k_rtc", "clk_32k_io" };
PNAME(dbclk_pmu_gpio0_p) = { "xin24m", "clk_32k" };
PNAME(sclk_sfc_2x_pmu1_p) = { "clk_gpll_div12", "clk_rc_osc_io" };
PNAME(mux_armclk_p) = { "armclk_gpll", "clk_core_pvtpll" };
static struct rockchip_pll_clock rv1103b_pll_clks[] __initdata = {
[dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p,
CLK_IS_CRITICAL, RV1103B_PLL_CON(16),
RV1103B_MODE_CON, 0, 10, 0, rv1103b_pll_rates),
[gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p,
CLK_IS_CRITICAL, RV1103B_PLL_CON(24),
RV1103B_MODE_CON, 0, 10, 0, rv1103b_pll_rates),
};
#define MFLAGS CLK_MUX_HIWORD_MASK
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
static struct rockchip_clk_branch rv1103b_clk_uart0_fracmux __initdata =
MUX(SCLK_UART0_SRC, "sclk_uart0_src", sclk_uart0_src_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(32), 8, 2, MFLAGS);
static struct rockchip_clk_branch rv1103b_clk_uart1_fracmux __initdata =
MUX(SCLK_UART1_SRC, "sclk_uart1_src", sclk_uart1_src_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(32), 10, 2, MFLAGS);
static struct rockchip_clk_branch rv1103b_clk_uart2_fracmux __initdata =
MUX(SCLK_UART2_SRC, "sclk_uart2_src", sclk_uart2_src_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(32), 12, 2, MFLAGS);
static struct rockchip_clk_branch rv1103b_rcdiv_pmu_fracmux __initdata =
MUX(CLK_32K, "clk_32k", clk_32k_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
RK3568_PMU_CLKSEL_CON(0), 0, 2, MFLAGS);
static struct rockchip_clk_branch rv1103b_clk_branches[] __initdata = {
/* Clock Definition */
FACTOR(XIN_OSC0_HALF, "xin_osc0_half", "xin24m", 0, 1, 2),
COMPOSITE_NOGATE(0, "armclk_gpll", mux_gpll_24m_p, CLK_IS_CRITICAL,
RV1103B_CLKSEL_CON(37), 12, 1, MFLAGS, 13, 3, DFLAGS),
/* pd_top */
COMPOSITE_NOMUX(CLK_GPLL_DIV24, "clk_gpll_div24", "gpll", 0,
RV1103B_CLKSEL_CON(0), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 0, GFLAGS),
COMPOSITE_NOMUX(CLK_GPLL_DIV12, "clk_gpll_div12", "gpll", 0,
RV1103B_CLKSEL_CON(0), 5, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 1, GFLAGS),
COMPOSITE_NOMUX(CLK_GPLL_DIV6, "clk_gpll_div6", "gpll", 0,
RV1103B_CLKSEL_CON(1), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 3, GFLAGS),
COMPOSITE_NOMUX(CLK_GPLL_DIV4, "clk_gpll_div4", "gpll", 0,
RV1103B_CLKSEL_CON(1), 10, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 5, GFLAGS),
COMPOSITE_NOMUX(CLK_GPLL_DIV3, "clk_gpll_div3", "gpll", 0,
RV1103B_CLKSEL_CON(2), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 7, GFLAGS),
COMPOSITE_NOMUX_HALFDIV(CLK_GPLL_DIV2P5, "clk_gpll_div2p5", "gpll", 0,
RV1103B_CLKSEL_CON(2), 5, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 8, GFLAGS),
COMPOSITE_NOMUX(CLK_GPLL_DIV2, "clk_gpll_div2", "gpll", 0,
RV1103B_CLKSEL_CON(2), 10, 5, DFLAGS,
RV1103B_CLKGATE_CON(0), 9, GFLAGS),
COMPOSITE_NOMUX(CLK_UART0_SRC, "clk_uart0_src", "gpll", 0,
RV1103B_CLKSEL_CON(5), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(1), 0, GFLAGS),
COMPOSITE_NOMUX(CLK_UART1_SRC, "clk_uart1_src", "gpll", 0,
RV1103B_CLKSEL_CON(5), 5, 5, DFLAGS,
RV1103B_CLKGATE_CON(1), 1, GFLAGS),
COMPOSITE_NOMUX(CLK_UART2_SRC, "clk_uart2_src", "gpll", 0,
RV1103B_CLKSEL_CON(5), 10, 5, DFLAGS,
RV1103B_CLKGATE_CON(1), 2, GFLAGS),
COMPOSITE_FRACMUX(CLK_UART0_FRAC, "clk_uart0_frac", "clk_uart0_src", 0,
RV1103B_CLKSEL_CON(10), 0,
RV1103B_CLKGATE_CON(1), 6, GFLAGS,
&rv1103b_clk_uart0_fracmux),
COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", 0,
RV1103B_CLKSEL_CON(11), 0,
RV1103B_CLKGATE_CON(1), 7, GFLAGS,
&rv1103b_clk_uart1_fracmux),
COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", 0,
RV1103B_CLKSEL_CON(12), 0,
RV1103B_CLKGATE_CON(1), 8, GFLAGS,
&rv1103b_clk_uart2_fracmux),
GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_src", 0,
RV1103B_CLKGATE_CON(3), 3, GFLAGS),
GATE(SCLK_UART1, "sclk_uart1", "sclk_uart1_src", 0,
RV1103B_CLKGATE_CON(3), 4, GFLAGS),
GATE(SCLK_UART2, "sclk_uart2", "sclk_uart2_src", 0,
RV1103B_CLKGATE_CON(3), 8, GFLAGS),
COMPOSITE_NOMUX(CLK_SAI_SRC, "clk_sai_src", "gpll", 0,
RV1103B_CLKSEL_CON(20), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(1), 12, GFLAGS),
MUX(MCLK_SAI_SRC, "mclk_sai_src", mclk_sai_src_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(35), 10, 2, MFLAGS),
GATE(MCLK_SAI, "mclk_sai", "mclk_sai_src", 0,
RV1103B_CLKGATE_CON(5), 5, GFLAGS),
COMPOSITE_NODIV(LSCLK_NPU_SRC, "lsclk_npu_src", mux_200m_100m_p, CLK_IS_CRITICAL,
RV1103B_CLKSEL_CON(30), 0, 1, MFLAGS,
RV1103B_CLKGATE_CON(2), 0, GFLAGS),
COMPOSITE(CLK_NPU_SRC, "clk_npu_src", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(37), 0, 1, MFLAGS, 1, 2, DFLAGS,
RV1103B_CLKGATE_CON(5), 12, GFLAGS),
COMPOSITE_NODIV(ACLK_VEPU_SRC, "aclk_vepu_src", mux_480m_400m_300m_200m_p, 0,
RV1103B_CLKSEL_CON(30), 8, 2, MFLAGS,
RV1103B_CLKGATE_CON(2), 4, GFLAGS),
COMPOSITE(CLK_VEPU_SRC, "clk_vepu_src", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(37), 4, 1, MFLAGS, 5, 2, DFLAGS,
RV1103B_CLKGATE_CON(5), 13, GFLAGS),
COMPOSITE_NODIV(ACLK_VI_SRC, "aclk_vi_src", mux_480m_400m_300m_p, CLK_IS_CRITICAL,
RV1103B_CLKSEL_CON(30), 12, 2, MFLAGS,
RV1103B_CLKGATE_CON(2), 8, GFLAGS),
COMPOSITE(CLK_ISP_SRC, "clk_isp_src", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(37), 8, 1, MFLAGS, 9, 2, DFLAGS,
RV1103B_CLKGATE_CON(5), 14, GFLAGS),
COMPOSITE_NODIV(DCLK_VICAP, "dclk_vicap", mux_300m_200m_p, 0,
RV1103B_CLKSEL_CON(30), 14, 1, MFLAGS,
RV1103B_CLKGATE_CON(2), 9, GFLAGS),
COMPOSITE(CCLK_EMMC, "cclk_emmc", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(31), 15, 1, MFLAGS, 0, 8, DFLAGS,
RV1103B_CLKGATE_CON(2), 10, GFLAGS),
COMPOSITE(CCLK_SDMMC0, "cclk_sdmmc0", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 8, DFLAGS,
RV1103B_CLKGATE_CON(2), 11, GFLAGS),
COMPOSITE(SCLK_SFC_2X, "sclk_sfc_2x", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(33), 15, 1, MFLAGS, 0, 8, DFLAGS,
RV1103B_CLKGATE_CON(2), 12, GFLAGS),
COMPOSITE_NODIV(LSCLK_PERI_SRC, "lsclk_peri_src", mux_300m_200m_p, CLK_IS_CRITICAL,
RV1103B_CLKSEL_CON(31), 9, 1, MFLAGS,
RV1103B_CLKGATE_CON(3), 0, GFLAGS),
COMPOSITE_NODIV(ACLK_PERI_SRC, "aclk_peri_src", mux_600m_480m_400m_p, CLK_IS_CRITICAL,
RV1103B_CLKSEL_CON(31), 10, 2, MFLAGS,
RV1103B_CLKGATE_CON(3), 1, GFLAGS),
COMPOSITE_NODIV(HCLK_HPMCU, "hclk_hpmcu", mux_400m_300m_p, 0,
RV1103B_CLKSEL_CON(31), 12, 1, MFLAGS,
RV1103B_CLKGATE_CON(3), 2, GFLAGS),
COMPOSITE_NODIV(CLK_I2C_PMU, "clk_i2c_pmu", mux_100m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 0, 1, MFLAGS,
RV1103B_CLKGATE_CON(4), 0, GFLAGS),
COMPOSITE_NODIV(CLK_I2C_PERI, "clk_i2c_peri", mux_200m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 1, 1, MFLAGS,
RV1103B_CLKGATE_CON(4), 4, GFLAGS),
COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", mux_200m_100m_50m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 2, 2, MFLAGS,
RV1103B_CLKGATE_CON(4), 5, GFLAGS),
COMPOSITE_NODIV(CLK_PWM0_SRC, "clk_pwm0_src", mux_100m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 12, 1, MFLAGS,
RV1103B_CLKGATE_CON(4), 10, GFLAGS),
COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", mux_100m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 13, 1, MFLAGS,
RV1103B_CLKGATE_CON(4), 11, GFLAGS),
COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", mux_100m_24m_p, 0,
RV1103B_CLKSEL_CON(34), 14, 1, MFLAGS,
RV1103B_CLKGATE_CON(4), 12, GFLAGS),
COMPOSITE_NODIV(DCLK_DECOM_SRC, "dclk_decom_src", mux_480m_400m_300m_p, 0,
RV1103B_CLKSEL_CON(35), 0, 2, MFLAGS,
RV1103B_CLKGATE_CON(5), 0, GFLAGS),
COMPOSITE(CCLK_SDMMC1, "cclk_sdmmc1", mux_gpll_24m_p, 0,
RV1103B_CLKSEL_CON(36), 15, 1, MFLAGS, 0, 8, DFLAGS,
RV1103B_CLKGATE_CON(5), 1, GFLAGS),
COMPOSITE_NODIV(CLK_CORE_CRYPTO, "clk_core_crypto", mux_300m_200m_100m_p, 0,
RV1103B_CLKSEL_CON(35), 2, 2, MFLAGS,
RV1103B_CLKGATE_CON(5), 2, GFLAGS),
COMPOSITE_NODIV(CLK_PKA_CRYPTO, "clk_pka_crypto", mux_300m_200m_100m_p, 0,
RV1103B_CLKSEL_CON(35), 4, 2, MFLAGS,
RV1103B_CLKGATE_CON(5), 3, GFLAGS),
COMPOSITE_NODIV(CLK_CORE_RGA, "clk_core_rga", mux_400m_300m_p, 0,
RV1103B_CLKSEL_CON(35), 8, 1, MFLAGS,
RV1103B_CLKGATE_CON(5), 4, GFLAGS),
GATE(PCLK_TOP_ROOT, "pclk_top_root", "clk_gpll_div12", CLK_IS_CRITICAL,
RV1103B_CLKGATE_CON(6), 0, GFLAGS),
COMPOSITE_NOMUX(CLK_REF_MIPI0, "clk_ref_mipi0", "clk_gpll_div2", 0,
RV1103B_CLKSEL_CON(40), 0, 5, DFLAGS,
RV1103B_CLKGATE_CON(6), 3, GFLAGS),
COMPOSITE_NODIV(CLK_MIPI0_OUT2IO, "clk_mipi0_out2io", clk_mipi0_out2io_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(40), 6, 1, MFLAGS,
RV1103B_CLKGATE_CON(6), 4, GFLAGS),
COMPOSITE_NOMUX(CLK_REF_MIPI1, "clk_ref_mipi1", "clk_gpll_div2", 0,
RV1103B_CLKSEL_CON(40), 8, 5, DFLAGS,
RV1103B_CLKGATE_CON(6), 5, GFLAGS),
COMPOSITE_NODIV(CLK_MIPI1_OUT2IO, "clk_mipi1_out2io", clk_mipi1_out2io_p, CLK_SET_RATE_PARENT,
RV1103B_CLKSEL_CON(40), 14, 1, MFLAGS,
RV1103B_CLKGATE_CON(6), 6, GFLAGS),
COMPOSITE(MCLK_SAI_OUT2IO, "mclk_sai_out2io", mclk_sai_out2io_p, 0,
RV1103B_CLKSEL_CON(41), 7, 1, MFLAGS, 13, 3, DFLAGS,
RV1103B_CLKGATE_CON(6), 9, GFLAGS),
/* pd_vpu */
COMPOSITE_NODIV(ACLK_NPU_ROOT, "aclk_npu_root", aclk_npu_root_p, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
RV1103B_NPUCLKSEL_CON(0), 1, 1, MFLAGS,
RV1103B_NPUCLKGATE_CON(0), 1, GFLAGS),
GATE(HCLK_RKNN, "hclk_rknn", "lsclk_npu_src", 0,
RV1103B_NPUCLKGATE_CON(0), 4, GFLAGS),
GATE(ACLK_RKNN, "aclk_rknn", "aclk_npu_root", 0,
RV1103B_NPUCLKGATE_CON(0), 5, GFLAGS),
/* pd_vepu */
COMPOSITE_NOMUX(LSCLK_VEPU_ROOT, "lsclk_vepu_root", "aclk_vepu_src", CLK_IS_CRITICAL,
RV1103B_VEPUCLKSEL_CON(0), 2, 2, DFLAGS,
RV1103B_VEPUCLKGATE_CON(0), 0, GFLAGS),
GATE(HCLK_VEPU, "hclk_vepu", "lsclk_vepu_root", 0,
RV1103B_VEPUCLKGATE_CON(0), 4, GFLAGS),
GATE(ACLK_VEPU, "aclk_vepu", "aclk_vepu_src", 0,
RV1103B_VEPUCLKGATE_CON(0), 5, GFLAGS),
COMPOSITE_NODIV(CLK_CORE_VEPU, "clk_core_vepu", clk_core_vepu_p, 0,
RV1103B_VEPUCLKSEL_CON(0), 1, 1, MFLAGS,
RV1103B_VEPUCLKGATE_CON(0), 6, GFLAGS),
GATE(PCLK_ACODEC, "pclk_acodec", "lsclk_vepu_root", 0,
RV1103B_VEPUCLKGATE_CON(0), 13, GFLAGS),
GATE(PCLK_USBPHY, "pclk_usbphy", "lsclk_vepu_root", 0,
RV1103B_VEPUCLKGATE_CON(0), 14, GFLAGS),
/* pd_vi */
FACTOR(LSCLK_VI_100M, "lsclk_vi_100m", "clk_gpll_div6", 0, 1, 2),
COMPOSITE_NODIV(LSCLK_VI_ROOT, "lsclk_vi_root", lsclk_vi_root_p, CLK_IS_CRITICAL,
RV1103B_VICLKSEL_CON(0), 3, 1, MFLAGS,
RV1103B_VICLKGATE_CON(0), 0, GFLAGS),
GATE(HCLK_ISP, "hclk_isp", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(0), 4, GFLAGS),
GATE(ACLK_ISP, "aclk_isp", "aclk_vi_src", 0,
RV1103B_VICLKGATE_CON(0), 5, GFLAGS),
COMPOSITE_NODIV(CLK_CORE_ISP, "clk_core_isp", clk_core_isp_p, 0,
RV1103B_VICLKSEL_CON(0), 1, 1, MFLAGS,
RV1103B_VICLKGATE_CON(0), 6, GFLAGS),
GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi_src", 0,
RV1103B_VICLKGATE_CON(1), 2, GFLAGS),
GATE(HCLK_VICAP, "hclk_vicap", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 3, GFLAGS),
GATE(ISP0CLK_VICAP, "isp0clk_vicap", "clk_core_isp", 0,
RV1103B_VICLKGATE_CON(1), 8, GFLAGS),
GATE(PCLK_CSI2HOST0, "pclk_csi2host0", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 9, GFLAGS),
GATE(PCLK_CSI2HOST1, "pclk_csi2host1", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 11, GFLAGS),
GATE(HCLK_EMMC, "hclk_emmc", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 13, GFLAGS),
GATE(HCLK_SFC, "hclk_sfc", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 14, GFLAGS),
GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(1), 15, GFLAGS),
GATE(HCLK_SDMMC0, "hclk_sdmmc0", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(2), 0, GFLAGS),
GATE(PCLK_CSIPHY, "pclk_csiphy", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(2), 2, GFLAGS),
GATE(PCLK_GPIO1, "pclk_gpio1", "lsclk_vi_root", 0,
RV1103B_VICLKGATE_CON(2), 3, GFLAGS),
GATE(DBCLK_GPIO1, "dbclk_gpio1", "xin24m", 0,
RV1103B_VICLKGATE_CON(2), 4, GFLAGS),
/* pd_ddr */
GATE(LSCLK_DDR_ROOT, "lsclk_ddr_root", "clk_gpll_div12", CLK_IS_CRITICAL,
RV1103B_DDRCLKGATE_CON(0), 0, GFLAGS),
GATE(CLK_TIMER_DDRMON, "clk_timer_ddrmon", "xin24m", 0,
RV1103B_DDRCLKGATE_CON(0), 4, GFLAGS),
FACTOR(0, "sclk_ddr", "dpll", 0, 1, 2),
/* pd_pmu */
COMPOSITE(LSCLK_PMU_ROOT, "lsclk_pmu_root", lsclk_pmu_root_p, CLK_IS_CRITICAL,
RV1103B_PMUCLKSEL_CON(2), 4, 1, MFLAGS, 0, 2, DFLAGS,
RV1103B_PMUCLKGATE_CON(0), 0, GFLAGS),
GATE(PCLK_PMU, "pclk_pmu", "lsclk_pmu_root", CLK_IS_CRITICAL,
RV1103B_PMUCLKGATE_CON(0), 2, GFLAGS),
MUX(XIN_RC_SRC, "xin_rc_src", xin_rc_div_p, 0,
RV1103B_PMUCLKSEL_CON(0), 2, 1, MFLAGS),
COMPOSITE_FRACMUX(XIN_RC_DIV, "xin_rc_div", "xin_rc_src", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
RV1103B_PMUCLKSEL_CON(1), 0,
RV1103B_PMUCLKGATE_CON(0), 3, GFLAGS,
&rv1103b_rcdiv_pmu_fracmux),
GATE(PCLK_PMU_GPIO0, "pclk_pmu_gpio0", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(0), 4, GFLAGS),
COMPOSITE_NODIV(DBCLK_PMU_GPIO0, "dbclk_pmu_gpio0", dbclk_pmu_gpio0_p, 0,
RK3568_PMU_CLKSEL_CON(0), 3, 1, MFLAGS,
RV1103B_PMUCLKGATE_CON(0), 5, GFLAGS),
GATE(PCLK_PWM0, "pclk_pwm0", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(2), 0, GFLAGS),
GATE(CLK_PWM0, "clk_pwm0", "clk_pwm0_src", 0,
RV1103B_PMUCLKGATE_CON(2), 1, GFLAGS),
GATE(CLK_OSC_PWM0, "clk_osc_pwm0", "xin24m", 0,
RV1103B_PMUCLKGATE_CON(2), 2, GFLAGS),
GATE(CLK_RC_PWM0, "clk_rc_pwm0", "clk_32k", 0,
RV1103B_PMUCLKGATE_CON(2), 3, GFLAGS),
GATE(PCLK_I2C0, "pclk_i2c0", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(0), 12, GFLAGS),
GATE(CLK_I2C0, "clk_i2c0", "clk_i2c_pmu", 0,
RV1103B_PMUCLKGATE_CON(0), 13, GFLAGS),
GATE(PCLK_UART0, "pclk_uart0", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(0), 14, GFLAGS),
GATE(CLK_REFOUT, "clk_refout", "xin24m", 0,
RV1103B_PMUCLKGATE_CON(1), 4, GFLAGS),
GATE(CLK_PREROLL, "clk_preroll", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(1), 6, GFLAGS),
GATE(CLK_PREROLL_32K, "clk_preroll_32k", "clk_32k", 0,
RV1103B_PMUCLKGATE_CON(1), 7, GFLAGS),
GATE(CLK_LPMCU_PMU, "clk_lpmcu_pmu", "lsclk_pmu_root", 0,
RV1103B_PMUCLKGATE_CON(2), 12, GFLAGS),
/* pd_pmu1 */
GATE(PCLK_SPI2AHB, "pclk_spi2ahb", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(0), 0, GFLAGS),
GATE(HCLK_SPI2AHB, "hclk_spi2ahb", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(0), 1, GFLAGS),
GATE(PCLK_WDT_LPMCU, "pclk_wdt_lpmcu", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(0), 9, GFLAGS),
GATE(TCLK_WDT_LPMCU, "tclk_wdt_lpmcu", "xin24m", 0,
RV1103B_PMU1CLKGATE_CON(0), 10, GFLAGS),
GATE(HCLK_SFC_PMU1, "hclk_sfc_pmu1", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(0), 12, GFLAGS),
GATE(HCLK_SFC_XIP_PMU1, "hclk_sfc_xip_pmu1", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(0), 13, GFLAGS),
COMPOSITE_NODIV(SCLK_SFC_2X_PMU1, "sclk_sfc_2x_pmu1", sclk_sfc_2x_pmu1_p, 0,
RV1103B_PMU1CLKSEL_CON(0), 8, 1, MFLAGS,
RV1103B_PMU1CLKGATE_CON(0), 14, GFLAGS),
GATE(CLK_LPMCU, "clk_lpmcu", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(1), 0, GFLAGS),
GATE(CLK_LPMCU_RTC, "clk_lpmcu_rtc", "xin24m", 0,
RV1103B_PMU1CLKGATE_CON(1), 4, GFLAGS),
GATE(PCLK_LPMCU_MAILBOX, "pclk_lpmcu_mailbox", "lsclk_pmu_root", 0,
RV1103B_PMU1CLKGATE_CON(1), 8, GFLAGS),
/* pd_peri */
COMPOSITE_NOMUX(PCLK_PERI_ROOT, "pclk_peri_root", "lsclk_peri_src", CLK_IS_CRITICAL,
RV1103B_PERICLKSEL_CON(0), 0, 2, DFLAGS,
RV1103B_PERICLKGATE_CON(0), 0, GFLAGS),
COMPOSITE_NOMUX(PCLK_RTC_ROOT, "pclk_rtc_root", "lsclk_peri_src", CLK_IS_CRITICAL,
RV1103B_PERICLKSEL_CON(2), 12, 4, DFLAGS,
RV1103B_PERICLKGATE_CON(0), 8, GFLAGS),
GATE(CLK_TIMER_ROOT, "clk_timer_root", "xin24m", 0,
RV1103B_PERICLKGATE_CON(0), 1, GFLAGS),
GATE(PCLK_TIMER, "pclk_timer", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(1), 0, GFLAGS),
GATE(CLK_TIMER0, "clk_timer0", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 1, GFLAGS),
GATE(CLK_TIMER1, "clk_timer1", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 2, GFLAGS),
GATE(CLK_TIMER2, "clk_timer2", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 3, GFLAGS),
GATE(CLK_TIMER3, "clk_timer3", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 4, GFLAGS),
GATE(CLK_TIMER4, "clk_timer4", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 5, GFLAGS),
GATE(CLK_TIMER5, "clk_timer5", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 6, GFLAGS),
GATE(PCLK_STIMER, "pclk_stimer", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(1), 7, GFLAGS),
GATE(CLK_STIMER0, "clk_stimer0", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 8, GFLAGS),
GATE(CLK_STIMER1, "clk_stimer1", "clk_timer_root", 0,
RV1103B_PERICLKGATE_CON(1), 9, GFLAGS),
GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 0, GFLAGS),
GATE(TCLK_WDT_NS, "tclk_wdt_ns", "xin24m", 0,
RV1103B_PERICLKGATE_CON(2), 1, GFLAGS),
GATE(PCLK_WDT_S, "pclk_wdt_s", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 2, GFLAGS),
GATE(TCLK_WDT_S, "tclk_wdt_s", "xin24m", 0,
RV1103B_PERICLKGATE_CON(2), 3, GFLAGS),
GATE(PCLK_WDT_HPMCU, "pclk_wdt_hpmcu", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 4, GFLAGS),
GATE(TCLK_WDT_HPMCU, "tclk_wdt_hpmcu", "xin24m", 0,
RV1103B_PERICLKGATE_CON(2), 5, GFLAGS),
GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 6, GFLAGS),
GATE(CLK_I2C1, "clk_i2c1", "clk_i2c_peri", 0,
RV1103B_PERICLKGATE_CON(2), 7, GFLAGS),
GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 8, GFLAGS),
GATE(CLK_I2C2, "clk_i2c2", "clk_i2c_peri", 0,
RV1103B_PERICLKGATE_CON(2), 9, GFLAGS),
GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 10, GFLAGS),
GATE(CLK_I2C3, "clk_i2c3", "clk_i2c_peri", 0,
RV1103B_PERICLKGATE_CON(2), 11, GFLAGS),
GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(2), 12, GFLAGS),
GATE(CLK_I2C4, "clk_i2c4", "clk_i2c_peri", 0,
RV1103B_PERICLKGATE_CON(2), 13, GFLAGS),
GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(3), 10, GFLAGS),
GATE(PCLK_PWM1, "pclk_pwm1", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(4), 6, GFLAGS),
GATE(CLK_OSC_PWM1, "clk_osc_pwm1", "xin24m", 0,
RV1103B_PERICLKGATE_CON(4), 8, GFLAGS),
GATE(PCLK_PWM2, "pclk_pwm2", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(4), 12, GFLAGS),
GATE(CLK_OSC_PWM2, "clk_osc_pwm2", "xin24m", 0,
RV1103B_PERICLKGATE_CON(4), 13, GFLAGS),
GATE(PCLK_UART2, "pclk_uart2", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(3), 0, GFLAGS),
GATE(PCLK_UART1, "pclk_uart1", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(3), 2, GFLAGS),
GATE(ACLK_RKDMA, "aclk_rkdma", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(5), 8, GFLAGS),
GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(5), 9, GFLAGS),
COMPOSITE_NOMUX(CLK_TSADC, "clk_tsadc", "xin24m", 0,
RV1103B_PERICLKSEL_CON(0), 4, 5, DFLAGS,
RV1103B_PERICLKGATE_CON(5), 10, GFLAGS),
COMPOSITE_NOMUX(CLK_TSADC_TSEN, "clk_tsadc_tsen", "xin24m", 0,
RV1103B_PERICLKSEL_CON(0), 10, 5, DFLAGS,
RV1103B_PERICLKGATE_CON(5), 11, GFLAGS),
GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(5), 12, GFLAGS),
COMPOSITE_NOMUX(CLK_SARADC, "clk_saradc", "xin24m", 0,
RV1103B_PERICLKSEL_CON(1), 0, 3, DFLAGS,
RV1103B_PERICLKGATE_CON(5), 13, GFLAGS),
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(6), 3, GFLAGS),
GATE(DBCLK_GPIO2, "dbclk_gpio2", "xin24m", 0,
RV1103B_PERICLKGATE_CON(6), 4, GFLAGS),
GATE(ACLK_USBOTG, "aclk_usbotg", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(6), 9, GFLAGS),
GATE(CLK_REF_USBOTG, "clk_ref_usbotg", "xin24m", 0,
RV1103B_PERICLKGATE_CON(6), 10, GFLAGS),
GATE(HCLK_SDMMC1, "hclk_sdmmc1", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(7), 0, GFLAGS),
GATE(HCLK_SAI, "hclk_sai", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(7), 1, GFLAGS),
GATE(ACLK_CRYPTO, "aclk_crypto", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(8), 2, GFLAGS),
GATE(HCLK_CRYPTO, "hclk_crypto", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(8), 3, GFLAGS),
GATE(HCLK_RK_RNG_S, "hclk_rk_rng_s", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(8), 5, GFLAGS),
GATE(HCLK_RK_RNG_NS, "hclk_rk_rng_ns", "hclk_rk_rng_s", 0,
RV1103B_PERICLKGATE_CON(8), 4, GFLAGS),
GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(8), 6, GFLAGS),
GATE(CLK_OTPC_ROOT_NS, "clk_otpc_root_ns", "xin24m", 0,
RV1103B_PERICLKGATE_CON(8), 7, GFLAGS),
GATE(CLK_SBPI_OTPC_NS, "clk_sbpi_otpc_ns", "clk_otpc_root_ns", 0,
RV1103B_PERICLKGATE_CON(8), 8, GFLAGS),
COMPOSITE_NOMUX(CLK_USER_OTPC_NS, "clk_user_otpc_ns", "clk_otpc_root_ns", 0,
RV1103B_PERICLKSEL_CON(1), 4, 3, DFLAGS,
RV1103B_PERICLKGATE_CON(8), 9, GFLAGS),
GATE(PCLK_OTPC_S, "pclk_otpc_s", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(8), 10, GFLAGS),
GATE(CLK_OTPC_ROOT_S, "clk_otpc_root_s", "xin24m", 0,
RV1103B_PERICLKGATE_CON(8), 11, GFLAGS),
GATE(CLK_SBPI_OTPC_S, "clk_sbpi_otpc_s", "clk_otpc_root_s", 0,
RV1103B_PERICLKGATE_CON(8), 12, GFLAGS),
COMPOSITE_NOMUX(CLK_USER_OTPC_S, "clk_user_otpc_s", "clk_otpc_root_s", 0,
RV1103B_PERICLKSEL_CON(1), 8, 3, DFLAGS,
RV1103B_PERICLKGATE_CON(8), 13, GFLAGS),
GATE(PCLK_OTP_MASK, "pclk_otp_mask", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(8), 15, GFLAGS),
GATE(HCLK_RGA, "hclk_rga", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(9), 0, GFLAGS),
GATE(ACLK_RGA, "aclk_rga", "aclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(9), 1, GFLAGS),
GATE(ACLK_MAC, "aclk_mac", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(9), 3, GFLAGS),
GATE(PCLK_MAC, "pclk_mac", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(9), 4, GFLAGS),
GATE(CLK_MACPHY, "clk_macphy", "xin24m", 0,
RV1103B_PERICLKGATE_CON(9), 11, GFLAGS),
GATE(ACLK_SPINLOCK, "aclk_spinlock", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(10), 0, GFLAGS),
GATE(HCLK_CACHE, "hclk_cache", "hclk_hpmcu", 0,
RV1103B_PERICLKGATE_CON(10), 1, GFLAGS),
GATE(PCLK_HPMCU_MAILBOX, "pclk_hpmcu_mailbox", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(10), 2, GFLAGS),
GATE(PCLK_HPMCU_INTMUX, "pclk_hpmcu_intmux", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(10), 3, GFLAGS),
GATE(CLK_HPMCU, "clk_hpmcu", "hclk_hpmcu", 0,
RV1103B_PERICLKGATE_CON(10), 4, GFLAGS),
GATE(CLK_HPMCU_RTC, "clk_hpmcu_rtc", "xin24m", 0,
RV1103B_PERICLKGATE_CON(10), 8, GFLAGS),
GATE(DCLK_DECOM, "dclk_decom", "dclk_decom_src", 0,
RV1103B_PERICLKGATE_CON(11), 0, GFLAGS),
GATE(ACLK_DECOM, "aclk_decom", "aclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(11), 1, GFLAGS),
GATE(PCLK_DECOM, "pclk_decom", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(11), 2, GFLAGS),
GATE(ACLK_SYS_SRAM, "aclk_sys_sram", "lsclk_peri_src", CLK_IS_CRITICAL,
RV1103B_PERICLKGATE_CON(11), 3, GFLAGS),
GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(11), 4, GFLAGS),
GATE(ACLK_DMA2DDR, "aclk_dma2ddr", "aclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(11), 5, GFLAGS),
GATE(PCLK_DCF, "pclk_dcf", "pclk_peri_root", 0,
RV1103B_PERICLKGATE_CON(11), 6, GFLAGS),
GATE(ACLK_DCF, "aclk_dcf", "lsclk_peri_src", 0,
RV1103B_PERICLKGATE_CON(11), 7, GFLAGS),
COMPOSITE_NOMUX(MCLK_ACODEC_TX, "mclk_acodec_tx", "mclk_sai_src", 0,
RV1103B_PERICLKSEL_CON(2), 0, 3, DFLAGS,
RV1103B_PERICLKGATE_CON(11), 9, GFLAGS),
GATE(CLK_REF_USBPHY, "clk_ref_usbphy", "xin24m", 0,
RV1103B_PERICLKGATE_CON(11), 12, GFLAGS),
/* io */
COMPOSITE_NODIV(CLK_FREQ_PWM0_SRC, "clk_freq_pwm0_src", clk_freq_pwm0_src_p, 0,
RV1103B_CLKSEL_CON(35), 12, 2, MFLAGS,
RV1103B_CLKGATE_CON(5), 6, GFLAGS),
GATE(CLK_FREQ_PWM0, "clk_freq_pwm0", "clk_freq_pwm0_src", 0,
RV1103B_PMUCLKGATE_CON(2), 4, GFLAGS),
COMPOSITE_NODIV(CLK_COUNTER_PWM0_SRC, "clk_counter_pwm0_src", clk_counter_pwm0_src_p, 0,
RV1103B_CLKSEL_CON(35), 14, 2, MFLAGS,
RV1103B_CLKGATE_CON(5), 7, GFLAGS),
GATE(CLK_COUNTER_PWM0, "clk_counter_pwm0", "clk_counter_pwm0_src", 0,
RV1103B_PMUCLKGATE_CON(2), 5, GFLAGS),
GATE(SCLK_SPI2AHB, "sclk_spi2ahb", "sclk_spi2ahb_io", 0,
RV1103B_PMU1CLKGATE_CON(0), 2, GFLAGS),
GATE(CLK_UTMI_USBOTG, "clk_utmi_usbotg", "clk_utmi_usbotg_io", 0,
RV1103B_PERICRU_IP_CON, 14, GFLAGS),
};
static struct rockchip_clk_branch rv1103b_armclk __initdata =
MUX(ARMCLK, "armclk", mux_armclk_p, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
RV1103B_CORECLKSEL_CON(0), 1, 1, MFLAGS);
static void __init rv1103b_clk_init(struct device_node *np)
{
struct rockchip_clk_provider *ctx;
unsigned long clk_nr;
void __iomem *reg_base;
clk_nr = rockchip_clk_find_max_clk_id(rv1103b_clk_branches,
ARRAY_SIZE(rv1103b_clk_branches)) + 1;
reg_base = of_iomap(np, 0);
if (!reg_base) {
pr_err("%s: could not map cru region\n", __func__);
return;
}
ctx = rockchip_clk_init(np, reg_base, clk_nr);
if (IS_ERR(ctx)) {
pr_err("%s: rockchip clk init failed\n", __func__);
iounmap(reg_base);
return;
}
rockchip_clk_register_plls(ctx, rv1103b_pll_clks,
ARRAY_SIZE(rv1103b_pll_clks),
RV1103B_GRF_SOC_STATUS0);
rockchip_clk_register_branches(ctx, rv1103b_clk_branches,
ARRAY_SIZE(rv1103b_clk_branches));
rockchip_clk_register_armclk_multi_pll(ctx, &rv1103b_armclk,
rv1103b_cpuclk_rates,
ARRAY_SIZE(rv1103b_cpuclk_rates));
rockchip_register_restart_notifier(ctx, RV1103B_GLB_SRST_FST, NULL);
rockchip_clk_of_add_provider(np, ctx);
/* pvtpll src init */
writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1103B_CORECLKSEL_CON(0));
writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1103B_NPUCLKSEL_CON(0));
writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1103B_VICLKSEL_CON(0));
writel_relaxed(PVTPLL_SRC_SEL_PVTPLL, reg_base + RV1103B_VEPUCLKSEL_CON(0));
}
CLK_OF_DECLARE(rv1103b_cru, "rockchip,rv1103b-cru", rv1103b_clk_init);

View File

@ -66,6 +66,55 @@ struct clk;
#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80)
#define PX30_PMU_MODE 0x0020
#define RV1103B_TOPCRU_BASE 0x60000
#define RV1103B_PERICRU_BASE 0x0
#define RV1103B_VICRU_BASE 0x30000
#define RV1103B_NPUCRU_BASE 0x20000
#define RV1103B_CORECRU_BASE 0x40000
#define RV1103B_VEPUCRU_BASE 0x10000
#define RV1103B_DDRCRU_BASE 0x50000
#define RV1103B_SUBDDRCRU_BASE 0x58000
#define RV1103B_PMUCRU_BASE 0x70000
#define RV1103B_PMU1CRU_BASE 0x80000
#define RV1103B_PMUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_PMUCRU_BASE)
#define RV1103B_PMUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_PMUCRU_BASE)
#define RV1103B_PMUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_PMUCRU_BASE)
#define RV1103B_PMU1CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_PMU1CRU_BASE)
#define RV1103B_PMU1CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_PMU1CRU_BASE)
#define RV1103B_PMU1SOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_PMU1CRU_BASE)
#define RV1103B_PLL_CON(x) ((x) * 0x4 + RV1103B_TOPCRU_BASE)
#define RV1103B_MODE_CON (0x280 + RV1103B_TOPCRU_BASE)
#define RV1103B_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_TOPCRU_BASE)
#define RV1103B_CLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_TOPCRU_BASE)
#define RV1103B_SOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_TOPCRU_BASE)
#define RV1103B_GLB_SRST_FST (0xc08 + RV1103B_TOPCRU_BASE)
#define RV1103B_GLB_SRST_SND (0xc0c + RV1103B_TOPCRU_BASE)
#define RV1103B_CLK_SAI_FRAC_DIV_HIGH (0xcc0 + RV1103B_TOPCRU_BASE)
#define RV1103B_PERICLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_PERICRU_BASE)
#define RV1103B_PERICLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_PERICRU_BASE)
#define RV1103B_PERISOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_PERICRU_BASE)
#define RV1103B_PERICRU_IP_CON (0xc08 + RV1103B_PERICRU_BASE)
#define RV1103B_VICLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_VICRU_BASE)
#define RV1103B_VICLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_VICRU_BASE)
#define RV1103B_VISOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_VICRU_BASE)
#define RV1103B_NPUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_NPUCRU_BASE)
#define RV1103B_NPUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_NPUCRU_BASE)
#define RV1103B_NPUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_NPUCRU_BASE)
#define RV1103B_CORECLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_CORECRU_BASE)
#define RV1103B_CORECLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_CORECRU_BASE)
#define RV1103B_CORESOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_CORECRU_BASE)
#define RV1103B_VEPUCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_VEPUCRU_BASE)
#define RV1103B_VEPUCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_VEPUCRU_BASE)
#define RV1103B_VEPUSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_VEPUCRU_BASE)
#define RV1103B_DDRCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_DDRCRU_BASE)
#define RV1103B_DDRCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_DDRCRU_BASE)
#define RV1103B_DDRSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_DDRCRU_BASE)
#define RV1103B_SUBDDRCLKSEL_CON(x) ((x) * 0x4 + 0x300 + RV1103B_SUBDDRCRU_BASE)
#define RV1103B_SUBDDRCLKGATE_CON(x) ((x) * 0x4 + 0x800 + RV1103B_SUBDDRCRU_BASE)
#define RV1103B_SUBDDRSOFTRST_CON(x) ((x) * 0x4 + 0xa00 + RV1103B_SUBDDRCRU_BASE)
#define RV1103B_SUBDDRMODE_CON (0x280 + RV1103B_SUBDDRCRU_BASE)
#define RV1108_PLL_CON(x) ((x) * 0x4)
#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)

View File

@ -83,9 +83,22 @@ static SUNXI_CCU_MUX_DATA_WITH_GATE(r_pwmctrl_clk, "r-pwmctrl",
static SUNXI_CCU_GATE_HW(bus_r_pwmctrl_clk, "bus-r-pwmctrl",
&r_apb0_clk.common.hw, 0x13c, BIT(0), 0);
/* SPI clock is /M/N (same as new MMC?) */
static const struct clk_parent_data r_spi_parents[] = {
{ .fw_name = "hosc" },
{ .fw_name = "pll-periph" },
{ .name = "pll-periph0-300M" },
{ .name = "pll-periph1-300M" },
{ .name = "pll-audio" },
};
static SUNXI_CCU_DUALDIV_MUX_GATE(r_spi_clk, "r-spi", r_spi_parents, 0x150,
0, 5, /* M */
8, 5, /* P */
24, 3, /* mux */
BIT(31), /* gate */
0);
static SUNXI_CCU_GATE_HW(bus_r_spi_clk, "bus-r-spi",
&r_ahb_clk.common.hw, 0x15c, BIT(0), 0);
static SUNXI_CCU_GATE_HW(bus_r_spinlock_clk, "bus-r-spinlock",
&r_ahb_clk.common.hw, 0x16c, BIT(0), 0);
static SUNXI_CCU_GATE_HW(bus_r_msgbox_clk, "bus-r-msgbox",
@ -138,6 +151,7 @@ static struct ccu_common *sun55i_a523_r_ccu_clks[] = {
&bus_r_twd_clk.common,
&r_pwmctrl_clk.common,
&bus_r_pwmctrl_clk.common,
&r_spi_clk.common,
&bus_r_spi_clk.common,
&bus_r_spinlock_clk.common,
&bus_r_msgbox_clk.common,
@ -169,6 +183,7 @@ static struct clk_hw_onecell_data sun55i_a523_r_hw_clks = {
[CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw,
[CLK_R_PWMCTRL] = &r_pwmctrl_clk.common.hw,
[CLK_BUS_R_PWMCTRL] = &bus_r_pwmctrl_clk.common.hw,
[CLK_R_SPI] = &r_spi_clk.common.hw,
[CLK_BUS_R_SPI] = &bus_r_spi_clk.common.hw,
[CLK_BUS_R_SPINLOCK] = &bus_r_spinlock_clk.common.hw,
[CLK_BUS_R_MSGBOX] = &bus_r_msgbox_clk.common.hw,

View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-only
config TENSTORRENT_ATLANTIS_PRCM
tristate "Support for Tenstorrent Atlantis PRCM Clock Controller"
depends on ARCH_TENSTORRENT || COMPILE_TEST
default ARCH_TENSTORRENT
select REGMAP_MMIO
select AUXILIARY_BUS
select MFD_SYSCON
help
Say yes here to support the different clock
controllers found in the Tenstorrent Atlantis SoC.
This includes the clocks from the RCPU, HSIO, MMIO
and PCIE domain.

View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_TENSTORRENT_ATLANTIS_PRCM) += atlantis-prcm.o

View File

@ -0,0 +1,870 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Tenstorrent Atlantis PRCM Clock Driver
*
* Copyright (c) 2026 Tenstorrent
*/
#include <dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h>
#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
/* RCPU Clock Register Offsets */
#define PLL_RCPU_CFG_REG 0x0000
#define PLL_NOCC_CFG_REG 0x0004
#define NOCC_CLK_CFG_REG 0x0008
#define RCPU_DIV_CFG_REG 0x000C
#define RCPU_BLK_CG_REG 0x0014
#define LSIO_BLK_CG_REG 0x0018
#define PLL_RCPU_EN_REG 0x011C
#define PLL_NOCC_EN_REG 0x0120
#define BUS_CG_REG 0x01FC
/* PLL Bit Definitions */
#define PLL_CFG_EN_BIT BIT(0)
#define PLL_CFG_BYPASS_BIT BIT(1)
#define PLL_CFG_REFDIV_MASK GENMASK(7, 2)
#define PLL_CFG_REFDIV_SHIFT 2
#define PLL_CFG_POSTDIV1_MASK GENMASK(10, 8)
#define PLL_CFG_POSTDIV1_SHIFT 8
#define PLL_CFG_POSTDIV2_MASK GENMASK(13, 11)
#define PLL_CFG_POSTDIV2_SHIFT 11
#define PLL_CFG_FBDIV_MASK GENMASK(25, 14)
#define PLL_CFG_FBDIV_SHIFT 14
#define PLL_CFG_LKDT_BIT BIT(30)
#define PLL_CFG_LOCK_BIT BIT(31)
#define PLL_LOCK_TIMEOUT_US 1000
#define PLL_BYPASS_WAIT_US 500
struct atlantis_clk_common {
int clkid;
struct regmap *regmap;
struct clk_hw hw;
};
static inline struct atlantis_clk_common *
hw_to_atlantis_clk_common(struct clk_hw *hw)
{
return container_of(hw, struct atlantis_clk_common, hw);
}
struct atlantis_clk_mux_config {
u8 shift;
u8 width;
u32 reg_offset;
};
struct atlantis_clk_mux {
struct atlantis_clk_common common;
struct atlantis_clk_mux_config config;
};
struct atlantis_clk_gate_config {
u32 reg_offset;
u32 enable;
};
struct atlantis_clk_gate {
struct atlantis_clk_common common;
struct atlantis_clk_gate_config config;
};
struct atlantis_clk_divider_config {
u8 shift;
u8 width;
u32 flags;
u32 reg_offset;
};
struct atlantis_clk_divider {
struct atlantis_clk_common common;
struct atlantis_clk_divider_config config;
};
struct atlantis_clk_pll_config {
u32 tbl_num;
u32 reg_offset;
u32 en_reg_offset;
u32 cg_reg_offset;
u32 cg_reg_enable;
};
/* Models a PLL with Bypass Functionality and Enable Bit + an optional Gate Clock at it's output */
struct atlantis_clk_pll {
struct atlantis_clk_common common;
struct atlantis_clk_pll_config config;
};
struct atlantis_clk_gate_shared_config {
u32 reg_offset;
u32 enable;
unsigned int *share_count;
spinlock_t *refcount_lock;
};
struct atlantis_clk_gate_shared {
struct atlantis_clk_common common;
struct atlantis_clk_gate_shared_config config;
};
struct atlantis_clk_fixed_factor_config {
unsigned int mult;
unsigned int div;
};
struct atlantis_clk_fixed_factor {
struct atlantis_clk_fixed_factor_config config;
struct atlantis_clk_common common;
};
static inline struct atlantis_clk_mux *hw_to_atlantis_clk_mux(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_mux, common);
}
static inline struct atlantis_clk_gate *
hw_to_atlantis_clk_gate(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_gate, common);
}
static inline struct atlantis_clk_divider *
hw_to_atlantis_clk_divider(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_divider, common);
}
static inline struct atlantis_clk_pll *hw_to_atlantis_pll(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_pll, common);
}
static inline struct atlantis_clk_gate_shared *
hw_to_atlantis_clk_gate_shared(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_gate_shared, common);
}
static inline struct atlantis_clk_fixed_factor *
hw_to_atlantis_clk_fixed_factor(struct clk_hw *hw)
{
struct atlantis_clk_common *common = hw_to_atlantis_clk_common(hw);
return container_of(common, struct atlantis_clk_fixed_factor, common);
}
static u8 atlantis_clk_mux_get_parent(struct clk_hw *hw)
{
struct atlantis_clk_mux *mux = hw_to_atlantis_clk_mux(hw);
u32 val;
regmap_read(mux->common.regmap, mux->config.reg_offset, &val);
val >>= mux->config.shift;
val &= (BIT(mux->config.width) - 1);
return val;
}
static int atlantis_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct atlantis_clk_mux *mux = hw_to_atlantis_clk_mux(hw);
u32 val = index;
return regmap_update_bits(mux->common.regmap, mux->config.reg_offset,
(BIT(mux->config.width) - 1) << mux->config.shift,
val << mux->config.shift);
}
static int atlantis_clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return clk_mux_determine_rate_flags(hw, req, hw->init->flags);
}
static const struct clk_ops atlantis_clk_mux_ops = {
.get_parent = atlantis_clk_mux_get_parent,
.set_parent = atlantis_clk_mux_set_parent,
.determine_rate = atlantis_clk_mux_determine_rate,
};
static int atlantis_clk_gate_endisable(struct clk_hw *hw, int enable)
{
struct atlantis_clk_gate *gate = hw_to_atlantis_clk_gate(hw);
if (enable)
return regmap_set_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable);
else
return regmap_clear_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable);
}
static int atlantis_clk_gate_enable(struct clk_hw *hw)
{
return atlantis_clk_gate_endisable(hw, 1);
}
static void atlantis_clk_gate_disable(struct clk_hw *hw)
{
atlantis_clk_gate_endisable(hw, 0);
}
static int atlantis_clk_gate_is_enabled(struct clk_hw *hw)
{
struct atlantis_clk_gate *gate = hw_to_atlantis_clk_gate(hw);
return regmap_test_bits(gate->common.regmap, gate->config.reg_offset, gate->config.enable);
}
static const struct clk_ops atlantis_clk_gate_ops = {
.enable = atlantis_clk_gate_enable,
.disable = atlantis_clk_gate_disable,
.is_enabled = atlantis_clk_gate_is_enabled,
};
static unsigned long atlantis_clk_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct atlantis_clk_divider *divider = hw_to_atlantis_clk_divider(hw);
u32 val;
regmap_read(divider->common.regmap, divider->config.reg_offset, &val);
val >>= divider->config.shift;
val &= ((1 << (divider->config.width)) - 1);
return DIV_ROUND_UP_ULL((u64)parent_rate, val + 1);
}
static const struct clk_ops atlantis_clk_divider_ops = {
.recalc_rate = atlantis_clk_divider_recalc_rate,
};
static unsigned long
atlantis_clk_fixed_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct atlantis_clk_fixed_factor *factor =
hw_to_atlantis_clk_fixed_factor(hw);
unsigned long long rate;
rate = (unsigned long long)parent_rate * factor->config.mult;
do_div(rate, factor->config.div);
return (unsigned long)rate;
}
static const struct clk_ops atlantis_clk_fixed_factor_ops = {
.recalc_rate = atlantis_clk_fixed_factor_recalc_rate,
};
static int atlantis_clk_pll_is_enabled(struct clk_hw *hw)
{
struct atlantis_clk_pll *pll = hw_to_atlantis_pll(hw);
u32 val, en_val, cg_val;
regmap_read(pll->common.regmap, pll->config.reg_offset, &val);
regmap_read(pll->common.regmap, pll->config.en_reg_offset, &en_val);
regmap_read(pll->common.regmap, pll->config.cg_reg_offset, &cg_val);
/* Check if PLL is powered on, locked, not bypassed and Gate clk is enabled */
return !!(en_val & PLL_CFG_EN_BIT) && !!(val & PLL_CFG_LOCK_BIT) &&
(!pll->config.cg_reg_enable || (cg_val & pll->config.cg_reg_enable)) &&
!(val & PLL_CFG_BYPASS_BIT);
}
static int atlantis_clk_pll_enable(struct clk_hw *hw)
{
struct atlantis_clk_pll *pll = hw_to_atlantis_pll(hw);
u32 val, en_val, cg_val;
int ret;
regmap_read(pll->common.regmap, pll->config.reg_offset, &val);
regmap_read(pll->common.regmap, pll->config.en_reg_offset, &en_val);
regmap_read(pll->common.regmap, pll->config.cg_reg_offset, &cg_val);
/* Check if PLL is already enabled, locked, not bypassed and Gate clk is enabled */
if ((en_val & PLL_CFG_EN_BIT) && (val & PLL_CFG_LOCK_BIT) &&
(!pll->config.cg_reg_enable || (cg_val & pll->config.cg_reg_enable)) &&
!(val & PLL_CFG_BYPASS_BIT)) {
return 0;
}
/* Step 1: Set bypass mode first */
regmap_update_bits(pll->common.regmap, pll->config.reg_offset,
PLL_CFG_BYPASS_BIT, PLL_CFG_BYPASS_BIT);
/* Step 2: Enable PLL (clear then set power bit) */
regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset,
PLL_CFG_EN_BIT, 0);
regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset,
PLL_CFG_EN_BIT, PLL_CFG_EN_BIT);
/* Step 3: Wait for PLL lock */
ret = regmap_read_poll_timeout(pll->common.regmap,
pll->config.reg_offset, val,
val & PLL_CFG_LOCK_BIT,
PLL_BYPASS_WAIT_US, PLL_LOCK_TIMEOUT_US);
if (ret) {
pr_err("PLL failed to lock within timeout\n");
return ret;
}
/* Step 4: Switch from bypass to PLL output */
regmap_update_bits(pll->common.regmap, pll->config.reg_offset,
PLL_CFG_BYPASS_BIT, 0);
/* Enable Gate clk at PLL Output */
return regmap_update_bits(pll->common.regmap, pll->config.cg_reg_offset,
pll->config.cg_reg_enable,
pll->config.cg_reg_enable);
}
static void atlantis_clk_pll_disable(struct clk_hw *hw)
{
struct atlantis_clk_pll *pll = hw_to_atlantis_pll(hw);
/* Step 1: Switch to bypass mode before disabling */
regmap_update_bits(pll->common.regmap, pll->config.reg_offset,
PLL_CFG_BYPASS_BIT, PLL_CFG_BYPASS_BIT);
/* Step 2: Power down PLL */
regmap_update_bits(pll->common.regmap, pll->config.en_reg_offset,
PLL_CFG_EN_BIT, 0);
}
static unsigned long atlantis_clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct atlantis_clk_pll *pll = hw_to_atlantis_pll(hw);
u32 val, refdiv, fbdiv, postdiv1, postdiv2;
u64 fout;
regmap_read(pll->common.regmap, pll->config.reg_offset, &val);
if (val & PLL_CFG_BYPASS_BIT)
return parent_rate;
refdiv = FIELD_GET(PLL_CFG_REFDIV_MASK, val);
fbdiv = FIELD_GET(PLL_CFG_FBDIV_MASK, val);
postdiv1 = FIELD_GET(PLL_CFG_POSTDIV1_MASK, val);
postdiv2 = FIELD_GET(PLL_CFG_POSTDIV2_MASK, val);
if (!refdiv)
refdiv = 1;
if (!postdiv1)
postdiv1 = 1;
if (!postdiv2)
postdiv2 = 1;
if (!fbdiv)
return 0;
fout = div64_u64((u64)parent_rate * fbdiv,
refdiv * postdiv1 * postdiv2);
return fout;
}
static const struct clk_ops atlantis_clk_pll_ops = {
.enable = atlantis_clk_pll_enable,
.disable = atlantis_clk_pll_disable,
.recalc_rate = atlantis_clk_pll_recalc_rate,
.is_enabled = atlantis_clk_pll_is_enabled,
};
static int atlantis_clk_gate_shared_enable(struct clk_hw *hw)
{
struct atlantis_clk_gate_shared *gate =
hw_to_atlantis_clk_gate_shared(hw);
bool need_enable;
scoped_guard(spinlock_irqsave, gate->config.refcount_lock)
{
need_enable = (*gate->config.share_count)++ == 0;
if (need_enable) {
regmap_set_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable);
}
}
if (need_enable) {
if (!regmap_test_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable)) {
pr_warn("%s: gate enable %d failed to enable\n",
clk_hw_get_name(hw), gate->config.enable);
return -EIO;
}
}
return 0;
}
static void atlantis_clk_gate_shared_disable(struct clk_hw *hw)
{
struct atlantis_clk_gate_shared *gate =
hw_to_atlantis_clk_gate_shared(hw);
scoped_guard(spinlock_irqsave, gate->config.refcount_lock)
{
if (WARN_ON(*gate->config.share_count == 0))
return;
if (--(*gate->config.share_count) > 0)
return;
regmap_clear_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable);
}
}
static int atlantis_clk_gate_shared_is_enabled(struct clk_hw *hw)
{
struct atlantis_clk_gate_shared *gate =
hw_to_atlantis_clk_gate_shared(hw);
return regmap_test_bits(gate->common.regmap, gate->config.reg_offset, gate->config.enable);
}
static void atlantis_clk_gate_shared_disable_unused(struct clk_hw *hw)
{
struct atlantis_clk_gate_shared *gate =
hw_to_atlantis_clk_gate_shared(hw);
scoped_guard(spinlock_irqsave, gate->config.refcount_lock)
{
if (*gate->config.share_count == 0)
regmap_clear_bits(gate->common.regmap,
gate->config.reg_offset,
gate->config.enable);
}
}
static const struct clk_ops atlantis_clk_gate_shared_ops = {
.enable = atlantis_clk_gate_shared_enable,
.disable = atlantis_clk_gate_shared_disable,
.disable_unused = atlantis_clk_gate_shared_disable_unused,
.is_enabled = atlantis_clk_gate_shared_is_enabled,
};
#define ATLANTIS_PLL_CONFIG(_reg_offset, _en_reg_offset, _cg_reg_offset, \
_cg_reg_enable) \
{ \
.reg_offset = (_reg_offset), \
.en_reg_offset = (_en_reg_offset), \
.cg_reg_offset = (_cg_reg_offset), \
.cg_reg_enable = (_cg_reg_enable), \
}
#define ATLANTIS_PLL_DEFINE(_clkid, _name, _parent, _reg_offset, \
_en_reg_offset, _cg_reg_offset, _cg_reg_enable, \
_flags) \
static struct atlantis_clk_pll _name = { \
.config = ATLANTIS_PLL_CONFIG(_reg_offset, _en_reg_offset, \
_cg_reg_offset, _cg_reg_enable), \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_PARENTS_DATA( \
#_name, _parent, &atlantis_clk_pll_ops, \
_flags) }, \
}
#define ATLANTIS_MUX_CONFIG(_shift, _width, _reg_offset) \
{ \
.shift = _shift, .width = _width, .reg_offset = _reg_offset \
}
#define ATLANTIS_MUX_DEFINE(_clkid, _name, _parents, _reg_offset, _shift, \
_width, _flags) \
static struct atlantis_clk_mux _name = { \
.config = ATLANTIS_MUX_CONFIG(_shift, _width, _reg_offset), \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_PARENTS_DATA( \
#_name, _parents, &atlantis_clk_mux_ops, \
_flags) } \
}
#define ATLANTIS_DIVIDER_CONFIG(_shift, _width, _flags, _reg_offset) \
{ \
.shift = _shift, .width = _width, .flags = _flags, \
.reg_offset = _reg_offset \
}
#define ATLANTIS_DIVIDER_DEFINE(_clkid, _name, _parent, _reg_offset, _shift, \
_width, _divflags, _flags) \
static struct atlantis_clk_divider _name = { \
.config = ATLANTIS_DIVIDER_CONFIG(_shift, _width, _divflags, \
_reg_offset), \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_HW( \
#_name, &_parent.common.hw, \
&atlantis_clk_divider_ops, _flags) } \
}
#define ATLANTIS_GATE_CONFIG(_enable, _reg_offset) \
{ \
.enable = _enable, .reg_offset = _reg_offset \
}
#define ATLANTIS_GATE_DEFINE(_clkid, _name, _parent, _reg_offset, _enable, \
_flags) \
static struct atlantis_clk_gate _name = { \
.config = ATLANTIS_GATE_CONFIG(_enable, _reg_offset), \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_HW( \
#_name, &_parent.common.hw, \
&atlantis_clk_gate_ops, _flags) } \
}
#define ATLANTIS_GATE_SHARED_CONFIG(_reg_offset, _enable, _share_count) \
{ \
.reg_offset = _reg_offset, .enable = _enable, \
.share_count = _share_count, .refcount_lock = &refcount_lock \
}
#define ATLANTIS_GATE_SHARED_DEFINE(_clkid, _name, _parent, _reg_offset, \
_enable, _share_count, _flags) \
static struct atlantis_clk_gate_shared _name = { \
.config = ATLANTIS_GATE_SHARED_CONFIG(_reg_offset, _enable, \
_share_count), \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_HW( \
#_name, &_parent.common.hw, \
&atlantis_clk_gate_shared_ops, _flags) } \
}
#define ATLANTIS_FIXED_FACTOR_DEFINE(_clkid, _name, _parent, _mult, _div, \
_flags) \
static struct atlantis_clk_fixed_factor _name = { \
.config = { .mult = _mult, .div = _div }, \
.common = { .clkid = _clkid, \
.hw.init = CLK_HW_INIT_HW( \
#_name, &_parent.common.hw, \
&atlantis_clk_fixed_factor_ops, _flags) } \
}
static DEFINE_SPINLOCK(refcount_lock); /* Lock for refcount value accesses */
static const struct regmap_config atlantis_prcm_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xFFFC,
.cache_type = REGCACHE_NONE,
};
struct atlantis_prcm_data {
struct clk_hw **hws;
size_t num;
const char *reset_name;
};
static const struct clk_parent_data osc_24m_clk[] = {
{ .index = 0 },
};
ATLANTIS_PLL_DEFINE(CLK_RCPU_PLL, rcpu_pll_clk, osc_24m_clk, PLL_RCPU_CFG_REG,
PLL_RCPU_EN_REG, BUS_CG_REG, 0, /* No Gate Clk at Output */
CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL);
static const struct clk_parent_data rcpu_root_parents[] = {
{ .index = 0 },
{ .hw = &rcpu_pll_clk.common.hw },
};
ATLANTIS_MUX_DEFINE(CLK_RCPU_ROOT, rcpu_root_clk, rcpu_root_parents,
RCPU_DIV_CFG_REG, 0, 1, CLK_SET_RATE_NO_REPARENT);
ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_DIV2, rcpu_div2_clk, rcpu_root_clk,
RCPU_DIV_CFG_REG, 2, 4, 0, 0);
ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_DIV4, rcpu_div4_clk, rcpu_root_clk,
RCPU_DIV_CFG_REG, 7, 4, 0, 0);
ATLANTIS_DIVIDER_DEFINE(CLK_RCPU_RTC, rcpu_rtc_clk, rcpu_div4_clk,
RCPU_DIV_CFG_REG, 12, 6, 0, 0);
ATLANTIS_GATE_DEFINE(CLK_SMNDMA0_ACLK, rcpu_dma0_clk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(0), 0);
ATLANTIS_GATE_DEFINE(CLK_SMNDMA1_ACLK, rcpu_dma1_clk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(1), 0);
ATLANTIS_GATE_DEFINE(CLK_WDT0_PCLK, sl_wdt0_pclk, rcpu_div4_clk,
RCPU_BLK_CG_REG, BIT(2), 0);
ATLANTIS_GATE_DEFINE(CLK_WDT1_PCLK, sl_wdt1_pclk, rcpu_div4_clk,
RCPU_BLK_CG_REG, BIT(3), 0);
ATLANTIS_GATE_DEFINE(CLK_TIMER_PCLK, sl_timer_pclk, rcpu_div4_clk,
RCPU_BLK_CG_REG, BIT(4), 0);
ATLANTIS_GATE_DEFINE(CLK_PVTC_PCLK, sl_pvtc_pclk, rcpu_div4_clk,
RCPU_BLK_CG_REG, BIT(12), 0);
ATLANTIS_GATE_DEFINE(CLK_PMU_PCLK, sl_pmu_pclk, rcpu_div4_clk, RCPU_BLK_CG_REG,
BIT(13), 0);
ATLANTIS_GATE_DEFINE(CLK_MAILBOX_HCLK, rcpu_ipc_clk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(14), 0);
ATLANTIS_GATE_DEFINE(CLK_SEC_SPACC_HCLK, sec_spacc_hclk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(26), 0);
ATLANTIS_GATE_DEFINE(CLK_SEC_OTP_HCLK, sec_otp_hclk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(28), 0);
ATLANTIS_GATE_DEFINE(CLK_TRNG_PCLK, sec_trng_pclk, rcpu_div4_clk,
RCPU_BLK_CG_REG, BIT(29), 0);
ATLANTIS_GATE_DEFINE(CLK_SEC_CRC_HCLK, sec_crc_hclk, rcpu_div2_clk,
RCPU_BLK_CG_REG, BIT(30), 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_SMN_HCLK, rcpu_smn_hclk, rcpu_div2_clk, 1, 1,
0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_AHB0_HCLK, rcpu_ahb0_hclk, rcpu_div2_clk, 1, 1,
0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_SMN_PCLK, rcpu_smn_pclk, rcpu_div4_clk, 1, 1,
0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_SMN_CLK, rcpu_smn_clk, rcpu_root_clk, 1, 1, 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_SCRATCHPAD_CLK, rcpu_scratchpad_aclk,
rcpu_root_clk, 1, 1, 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_RCPU_CORE_CLK, rcpu_core_clk, rcpu_root_clk, 1,
1, 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_RCPU_ROM_CLK, rcpu_rom_aclk, rcpu_root_clk, 1,
1, 0);
static struct atlantis_clk_fixed_factor
otp_load_clk = { .config = { .mult = 1, .div = 1 },
.common = {
.clkid = CLK_OTP_LOAD_CLK,
.hw.init = CLK_HW_INIT_PARENTS_DATA(
"otp_load_clk", osc_24m_clk,
&atlantis_clk_fixed_factor_ops,
CLK_SET_RATE_NO_REPARENT),
} };
ATLANTIS_PLL_DEFINE(CLK_NOC_PLL, nocc_pll_clk, osc_24m_clk, PLL_NOCC_CFG_REG,
PLL_NOCC_EN_REG, BUS_CG_REG, BIT(0),
CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL);
static const struct clk_parent_data nocc_mux_parents[] = {
{ .index = 0 },
{ .hw = &nocc_pll_clk.common.hw },
};
ATLANTIS_MUX_DEFINE(CLK_NOCC_CLK, nocc_clk, nocc_mux_parents, NOCC_CLK_CFG_REG,
0, 1, CLK_SET_RATE_NO_REPARENT);
ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_DIV2, nocc_div2_clk, nocc_clk,
NOCC_CLK_CFG_REG, 1, 4, 0, 0);
ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_DIV4, nocc_div4_clk, nocc_clk,
NOCC_CLK_CFG_REG, 5, 4, 0, 0);
ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_RTC, nocc_rtc_clk, nocc_div4_clk,
NOCC_CLK_CFG_REG, 9, 6, 0, 0);
ATLANTIS_DIVIDER_DEFINE(CLK_NOCC_CAN, nocc_can_clk, nocc_clk, NOCC_CLK_CFG_REG,
15, 4, 0, 0);
static unsigned int refcnt_qspi;
ATLANTIS_GATE_SHARED_DEFINE(CLK_QSPI_SCLK, lsio_qspi_sclk, nocc_clk,
LSIO_BLK_CG_REG, BIT(0), &refcnt_qspi, 0);
ATLANTIS_GATE_SHARED_DEFINE(CLK_QSPI_HCLK, lsio_qspi_hclk, nocc_div2_clk,
LSIO_BLK_CG_REG, BIT(0), &refcnt_qspi, 0);
ATLANTIS_GATE_DEFINE(CLK_I2C0_PCLK, lsio_i2c0_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(1), 0);
ATLANTIS_GATE_DEFINE(CLK_I2C1_PCLK, lsio_i2c1_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(2), 0);
ATLANTIS_GATE_DEFINE(CLK_I2C2_PCLK, lsio_i2c2_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(3), 0);
ATLANTIS_GATE_DEFINE(CLK_I2C3_PCLK, lsio_i2c3_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(4), 0);
ATLANTIS_GATE_DEFINE(CLK_I2C4_PCLK, lsio_i2c4_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(5), 0);
ATLANTIS_GATE_DEFINE(CLK_UART0_PCLK, lsio_uart0_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(6), 0);
ATLANTIS_GATE_DEFINE(CLK_UART1_PCLK, lsio_uart1_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(7), 0);
ATLANTIS_GATE_DEFINE(CLK_UART2_PCLK, lsio_uart2_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(8), 0);
ATLANTIS_GATE_DEFINE(CLK_UART3_PCLK, lsio_uart3_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(9), 0);
ATLANTIS_GATE_DEFINE(CLK_UART4_PCLK, lsio_uart4_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(10), 0);
ATLANTIS_GATE_DEFINE(CLK_SPI0_PCLK, lsio_spi0_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(11), 0);
ATLANTIS_GATE_DEFINE(CLK_SPI1_PCLK, lsio_spi1_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(12), 0);
ATLANTIS_GATE_DEFINE(CLK_SPI2_PCLK, lsio_spi2_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(13), 0);
ATLANTIS_GATE_DEFINE(CLK_SPI3_PCLK, lsio_spi3_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(14), 0);
ATLANTIS_GATE_DEFINE(CLK_GPIO_PCLK, lsio_gpio_pclk, nocc_div4_clk,
LSIO_BLK_CG_REG, BIT(15), 0);
static unsigned int refcnt_can0;
ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN0_HCLK, lsio_can0_hclk, nocc_div2_clk,
LSIO_BLK_CG_REG, BIT(17), &refcnt_can0, 0);
ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN0_CLK, lsio_can0_clk, nocc_can_clk,
LSIO_BLK_CG_REG, BIT(17), &refcnt_can0, 0);
static unsigned int refcnt_can1;
ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN1_HCLK, lsio_can1_hclk, nocc_div2_clk,
LSIO_BLK_CG_REG, BIT(18), &refcnt_can1, 0);
ATLANTIS_GATE_SHARED_DEFINE(CLK_CAN1_CLK, lsio_can1_clk, nocc_can_clk,
LSIO_BLK_CG_REG, BIT(18), &refcnt_can1, 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_CAN0_TIMER_CLK, lsio_can0_timer_clk,
nocc_rtc_clk, 1, 1, 0);
ATLANTIS_FIXED_FACTOR_DEFINE(CLK_CAN1_TIMER_CLK, lsio_can1_timer_clk,
nocc_rtc_clk, 1, 1, 0);
static struct clk_hw *atlantis_rcpu_clks[] = {
[CLK_RCPU_PLL] = &rcpu_pll_clk.common.hw,
[CLK_RCPU_ROOT] = &rcpu_root_clk.common.hw,
[CLK_RCPU_DIV2] = &rcpu_div2_clk.common.hw,
[CLK_RCPU_DIV4] = &rcpu_div4_clk.common.hw,
[CLK_RCPU_RTC] = &rcpu_rtc_clk.common.hw,
[CLK_SMNDMA0_ACLK] = &rcpu_dma0_clk.common.hw,
[CLK_SMNDMA1_ACLK] = &rcpu_dma1_clk.common.hw,
[CLK_WDT0_PCLK] = &sl_wdt0_pclk.common.hw,
[CLK_WDT1_PCLK] = &sl_wdt1_pclk.common.hw,
[CLK_TIMER_PCLK] = &sl_timer_pclk.common.hw,
[CLK_PVTC_PCLK] = &sl_pvtc_pclk.common.hw,
[CLK_PMU_PCLK] = &sl_pmu_pclk.common.hw,
[CLK_MAILBOX_HCLK] = &rcpu_ipc_clk.common.hw,
[CLK_SEC_SPACC_HCLK] = &sec_spacc_hclk.common.hw,
[CLK_SEC_OTP_HCLK] = &sec_otp_hclk.common.hw,
[CLK_TRNG_PCLK] = &sec_trng_pclk.common.hw,
[CLK_SEC_CRC_HCLK] = &sec_crc_hclk.common.hw,
[CLK_SMN_HCLK] = &rcpu_smn_hclk.common.hw,
[CLK_AHB0_HCLK] = &rcpu_ahb0_hclk.common.hw,
[CLK_SMN_PCLK] = &rcpu_smn_pclk.common.hw,
[CLK_SMN_CLK] = &rcpu_smn_clk.common.hw,
[CLK_SCRATCHPAD_CLK] = &rcpu_scratchpad_aclk.common.hw,
[CLK_RCPU_CORE_CLK] = &rcpu_core_clk.common.hw,
[CLK_RCPU_ROM_CLK] = &rcpu_rom_aclk.common.hw,
[CLK_OTP_LOAD_CLK] = &otp_load_clk.common.hw,
[CLK_NOC_PLL] = &nocc_pll_clk.common.hw,
[CLK_NOCC_CLK] = &nocc_clk.common.hw,
[CLK_NOCC_DIV2] = &nocc_div2_clk.common.hw,
[CLK_NOCC_DIV4] = &nocc_div4_clk.common.hw,
[CLK_NOCC_RTC] = &nocc_rtc_clk.common.hw,
[CLK_NOCC_CAN] = &nocc_can_clk.common.hw,
[CLK_QSPI_SCLK] = &lsio_qspi_sclk.common.hw,
[CLK_QSPI_HCLK] = &lsio_qspi_hclk.common.hw,
[CLK_I2C0_PCLK] = &lsio_i2c0_pclk.common.hw,
[CLK_I2C1_PCLK] = &lsio_i2c1_pclk.common.hw,
[CLK_I2C2_PCLK] = &lsio_i2c2_pclk.common.hw,
[CLK_I2C3_PCLK] = &lsio_i2c3_pclk.common.hw,
[CLK_I2C4_PCLK] = &lsio_i2c4_pclk.common.hw,
[CLK_UART0_PCLK] = &lsio_uart0_pclk.common.hw,
[CLK_UART1_PCLK] = &lsio_uart1_pclk.common.hw,
[CLK_UART2_PCLK] = &lsio_uart2_pclk.common.hw,
[CLK_UART3_PCLK] = &lsio_uart3_pclk.common.hw,
[CLK_UART4_PCLK] = &lsio_uart4_pclk.common.hw,
[CLK_SPI0_PCLK] = &lsio_spi0_pclk.common.hw,
[CLK_SPI1_PCLK] = &lsio_spi1_pclk.common.hw,
[CLK_SPI2_PCLK] = &lsio_spi2_pclk.common.hw,
[CLK_SPI3_PCLK] = &lsio_spi3_pclk.common.hw,
[CLK_GPIO_PCLK] = &lsio_gpio_pclk.common.hw,
[CLK_CAN0_HCLK] = &lsio_can0_hclk.common.hw,
[CLK_CAN0_CLK] = &lsio_can0_clk.common.hw,
[CLK_CAN1_HCLK] = &lsio_can1_hclk.common.hw,
[CLK_CAN1_CLK] = &lsio_can1_clk.common.hw,
[CLK_CAN0_TIMER_CLK] = &lsio_can0_timer_clk.common.hw,
[CLK_CAN1_TIMER_CLK] = &lsio_can1_timer_clk.common.hw,
};
static const struct atlantis_prcm_data atlantis_prcm_rcpu_data = {
.hws = atlantis_rcpu_clks,
.num = ARRAY_SIZE(atlantis_rcpu_clks),
.reset_name = "rcpu-reset"
};
static int atlantis_prcm_clocks_register(struct device *dev,
struct regmap *regmap,
const struct atlantis_prcm_data *data)
{
struct clk_hw_onecell_data *clk_data;
int i, ret;
size_t num_clks = data->num;
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, data->num),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
for (i = 0; i < data->num; i++) {
struct clk_hw *hw = data->hws[i];
struct atlantis_clk_common *common =
hw_to_atlantis_clk_common(hw);
common->regmap = regmap;
ret = devm_clk_hw_register(dev, hw);
if (ret)
return ret;
clk_data->hws[common->clkid] = hw;
}
clk_data->num = num_clks;
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
}
static int atlantis_prcm_probe(struct platform_device *pdev)
{
const struct atlantis_prcm_data *data;
struct auxiliary_device *reset_adev;
struct regmap *regmap;
void __iomem *base;
struct device *dev = &pdev->dev;
int ret;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return dev_err_probe(dev, PTR_ERR(base),
"Failed to map registers\n");
regmap = devm_regmap_init_mmio(dev, base, &atlantis_prcm_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to init regmap\n");
data = of_device_get_match_data(dev);
ret = atlantis_prcm_clocks_register(dev, regmap, data);
if (ret)
return dev_err_probe(dev, ret, "failed to register clocks\n");
reset_adev = devm_auxiliary_device_create(dev, data->reset_name, NULL);
if (!reset_adev)
return dev_err_probe(dev, -ENODEV, "failed to register resets\n");
return 0;
}
static const struct of_device_id atlantis_prcm_of_match[] = {
{
.compatible = "tenstorrent,atlantis-prcm-rcpu",
.data = &atlantis_prcm_rcpu_data,
},
{}
};
MODULE_DEVICE_TABLE(of, atlantis_prcm_of_match);
static struct platform_driver atlantis_prcm_driver = {
.probe = atlantis_prcm_probe,
.driver = {
.name = "atlantis-prcm",
.of_match_table = atlantis_prcm_of_match,
},
};
module_platform_driver(atlantis_prcm_driver);
MODULE_DESCRIPTION("Tenstorrent Atlantis PRCM Clock Controller Driver");
MODULE_AUTHOR("Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>");
MODULE_LICENSE("GPL");

View File

@ -315,6 +315,17 @@ config RESET_SUNXI
help
This enables the reset driver for Allwinner SoCs.
config RESET_TENSTORRENT_ATLANTIS
tristate "Tenstorrent atlantis reset driver"
depends on ARCH_TENSTORRENT || COMPILE_TEST
select AUXILIARY_BUS
default ARCH_TENSTORRENT
help
This enables the driver for the reset controller
present in the Tenstorrent Atlantis SoC.
Enable this option to be able to use hardware
resets on Atalantis based systems.
config RESET_TH1520
tristate "T-HEAD TH1520 reset controller"
depends on ARCH_THEAD || COMPILE_TEST

View File

@ -41,6 +41,7 @@ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TENSTORRENT_ATLANTIS) += reset-tenstorrent-atlantis.o
obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o

View File

@ -0,0 +1,173 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Tenstorrent Atlantis PRCM Reset Driver
*
* Copyright (c) 2026 Tenstorrent
*/
#include <dt-bindings/clock/tenstorrent,atlantis-prcm-rcpu.h>
#include <linux/auxiliary_bus.h>
#include <linux/reset-controller.h>
#include <linux/regmap.h>
/* RCPU Reset Register Offsets */
#define RCPU_BLK_RST_REG 0x001c
#define LSIO_BLK_RST_REG 0x0020
#define HSIO_BLK_RST_REG 0x000c
#define PCIE_SUBS_RST_REG 0x0000
#define MM_RSTN_REG 0x0014
struct atlantis_reset_data {
u8 bit;
u16 reg;
bool active_low;
};
struct atlantis_reset_controller_data {
const struct atlantis_reset_data *reset_data;
size_t count;
};
struct atlantis_reset_controller {
struct reset_controller_dev rcdev;
const struct atlantis_reset_controller_data *data;
struct regmap *regmap;
};
static inline struct atlantis_reset_controller *
to_atlantis_reset_controller(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct atlantis_reset_controller, rcdev);
}
#define RESET_DATA(_reg, _bit, _active_low) \
{ \
.bit = _bit, .reg = _reg, .active_low = _active_low, \
}
static const struct atlantis_reset_data atlantis_rcpu_resets[] = {
[RST_SMNDMA0] = RESET_DATA(RCPU_BLK_RST_REG, 0, true),
[RST_SMNDMA1] = RESET_DATA(RCPU_BLK_RST_REG, 1, true),
[RST_WDT0] = RESET_DATA(RCPU_BLK_RST_REG, 2, true),
[RST_WDT1] = RESET_DATA(RCPU_BLK_RST_REG, 3, true),
[RST_TMR] = RESET_DATA(RCPU_BLK_RST_REG, 4, true),
[RST_PVTC] = RESET_DATA(RCPU_BLK_RST_REG, 12, true),
[RST_PMU] = RESET_DATA(RCPU_BLK_RST_REG, 13, true),
[RST_MAILBOX] = RESET_DATA(RCPU_BLK_RST_REG, 14, true),
[RST_SPACC] = RESET_DATA(RCPU_BLK_RST_REG, 26, true),
[RST_OTP] = RESET_DATA(RCPU_BLK_RST_REG, 28, true),
[RST_TRNG] = RESET_DATA(RCPU_BLK_RST_REG, 29, true),
[RST_CRC] = RESET_DATA(RCPU_BLK_RST_REG, 30, true),
[RST_QSPI] = RESET_DATA(LSIO_BLK_RST_REG, 0, true),
[RST_I2C0] = RESET_DATA(LSIO_BLK_RST_REG, 1, true),
[RST_I2C1] = RESET_DATA(LSIO_BLK_RST_REG, 2, true),
[RST_I2C2] = RESET_DATA(LSIO_BLK_RST_REG, 3, true),
[RST_I2C3] = RESET_DATA(LSIO_BLK_RST_REG, 4, true),
[RST_I2C4] = RESET_DATA(LSIO_BLK_RST_REG, 5, true),
[RST_UART0] = RESET_DATA(LSIO_BLK_RST_REG, 6, true),
[RST_UART1] = RESET_DATA(LSIO_BLK_RST_REG, 7, true),
[RST_UART2] = RESET_DATA(LSIO_BLK_RST_REG, 8, true),
[RST_UART3] = RESET_DATA(LSIO_BLK_RST_REG, 9, true),
[RST_UART4] = RESET_DATA(LSIO_BLK_RST_REG, 10, true),
[RST_SPI0] = RESET_DATA(LSIO_BLK_RST_REG, 11, true),
[RST_SPI1] = RESET_DATA(LSIO_BLK_RST_REG, 12, true),
[RST_SPI2] = RESET_DATA(LSIO_BLK_RST_REG, 13, true),
[RST_SPI3] = RESET_DATA(LSIO_BLK_RST_REG, 14, true),
[RST_GPIO] = RESET_DATA(LSIO_BLK_RST_REG, 15, true),
[RST_CAN0] = RESET_DATA(LSIO_BLK_RST_REG, 17, true),
[RST_CAN1] = RESET_DATA(LSIO_BLK_RST_REG, 18, true),
[RST_I2S0] = RESET_DATA(LSIO_BLK_RST_REG, 19, true),
[RST_I2S1] = RESET_DATA(LSIO_BLK_RST_REG, 20, true),
};
static const struct atlantis_reset_controller_data atlantis_rcpu_reset_data = {
.reset_data = atlantis_rcpu_resets,
.count = ARRAY_SIZE(atlantis_rcpu_resets),
};
static int atlantis_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
unsigned int val;
struct atlantis_reset_controller *rst =
to_atlantis_reset_controller(rcdev);
const struct atlantis_reset_data *data = &rst->data->reset_data[id];
unsigned int mask = BIT(data->bit);
struct regmap *regmap = rst->regmap;
if (data->active_low ^ assert)
val = mask;
else
val = 0;
return regmap_update_bits(regmap, data->reg, mask, val);
}
static int atlantis_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return atlantis_reset_update(rcdev, id, true);
}
static int atlantis_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return atlantis_reset_update(rcdev, id, false);
}
static const struct reset_control_ops atlantis_reset_control_ops = {
.assert = atlantis_reset_assert,
.deassert = atlantis_reset_deassert,
};
static int
atlantis_reset_controller_register(struct device *dev,
struct atlantis_reset_controller *controller)
{
struct reset_controller_dev *rcdev = &controller->rcdev;
rcdev->ops = &atlantis_reset_control_ops;
rcdev->owner = THIS_MODULE;
rcdev->of_node = dev->of_node;
rcdev->nr_resets = controller->data->count;
return devm_reset_controller_register(dev, &controller->rcdev);
}
static int atlantis_reset_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
struct atlantis_reset_controller *controller;
struct device *dev = &adev->dev;
struct regmap *regmap;
regmap = dev_get_regmap(dev->parent, NULL);
if (!regmap)
return -ENODEV;
controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
if (!controller)
return -ENOMEM;
controller->data =
(const struct atlantis_reset_controller_data *)id->driver_data;
controller->regmap = regmap;
return atlantis_reset_controller_register(dev, controller);
}
static const struct auxiliary_device_id atlantis_reset_ids[] = {
{ .name = "atlantis_prcm.rcpu-reset",
.driver_data = (kernel_ulong_t)&atlantis_rcpu_reset_data },
{},
};
MODULE_DEVICE_TABLE(auxiliary, atlantis_reset_ids);
static struct auxiliary_driver atlantis_reset_driver = {
.probe = atlantis_reset_probe,
.id_table = atlantis_reset_ids,
};
module_auxiliary_driver(atlantis_reset_driver);
MODULE_AUTHOR("Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>");
MODULE_DESCRIPTION("Atlantis PRCM reset controller driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,220 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (c) 2024 Rockchip Electronics Co. Ltd.
* Author: Elaine Zhang <zhangqing@rock-chips.com>
*/
#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H
#define _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H
#define PLL_GPLL 0
#define ARMCLK 1
#define PLL_DPLL 2
#define XIN_OSC0_HALF 3
#define CLK_GPLL_DIV24 4
#define CLK_GPLL_DIV12 5
#define CLK_GPLL_DIV6 6
#define CLK_GPLL_DIV4 7
#define CLK_GPLL_DIV3 8
#define CLK_GPLL_DIV2P5 9
#define CLK_GPLL_DIV2 10
#define CLK_UART0_SRC 11
#define CLK_UART1_SRC 12
#define CLK_UART2_SRC 13
#define CLK_UART0_FRAC 14
#define CLK_UART1_FRAC 15
#define CLK_UART2_FRAC 16
#define CLK_SAI_SRC 17
#define CLK_SAI_FRAC 18
#define LSCLK_NPU_SRC 19
#define CLK_NPU_SRC 20
#define ACLK_VEPU_SRC 21
#define CLK_VEPU_SRC 22
#define ACLK_VI_SRC 23
#define CLK_ISP_SRC 24
#define DCLK_VICAP 25
#define CCLK_EMMC 26
#define CCLK_SDMMC0 27
#define SCLK_SFC_2X 28
#define LSCLK_PERI_SRC 29
#define ACLK_PERI_SRC 30
#define HCLK_HPMCU 31
#define SCLK_UART0 32
#define SCLK_UART1 33
#define SCLK_UART2 34
#define CLK_I2C_PMU 35
#define CLK_I2C_PERI 36
#define CLK_SPI0 37
#define CLK_PWM0_SRC 38
#define CLK_PWM1 39
#define CLK_PWM2 40
#define DCLK_DECOM_SRC 41
#define CCLK_SDMMC1 42
#define CLK_CORE_CRYPTO 43
#define CLK_PKA_CRYPTO 44
#define CLK_CORE_RGA 45
#define MCLK_SAI_SRC 46
#define CLK_FREQ_PWM0_SRC 47
#define CLK_COUNTER_PWM0_SRC 48
#define PCLK_TOP_ROOT 49
#define CLK_REF_MIPI0 50
#define CLK_MIPI0_OUT2IO 51
#define CLK_REF_MIPI1 52
#define CLK_MIPI1_OUT2IO 53
#define MCLK_SAI_OUT2IO 54
#define ACLK_NPU_ROOT 55
#define HCLK_RKNN 56
#define ACLK_RKNN 57
#define LSCLK_VEPU_ROOT 58
#define HCLK_VEPU 59
#define ACLK_VEPU 60
#define CLK_CORE_VEPU 61
#define PCLK_IOC_VCCIO3 62
#define PCLK_ACODEC 63
#define PCLK_USBPHY 64
#define LSCLK_VI_100M 65
#define LSCLK_VI_ROOT 66
#define HCLK_ISP 67
#define ACLK_ISP 68
#define CLK_CORE_ISP 69
#define ACLK_VICAP 70
#define HCLK_VICAP 71
#define ISP0CLK_VICAP 72
#define PCLK_CSI2HOST0 73
#define PCLK_CSI2HOST1 74
#define HCLK_EMMC 75
#define HCLK_SFC 76
#define HCLK_SFC_XIP 77
#define HCLK_SDMMC0 78
#define PCLK_CSIPHY 79
#define PCLK_GPIO1 80
#define DBCLK_GPIO1 81
#define PCLK_IOC_VCCIO47 82
#define LSCLK_DDR_ROOT 83
#define CLK_TIMER_DDRMON 84
#define LSCLK_PMU_ROOT 85
#define PCLK_PMU 86
#define XIN_RC_DIV 87
#define CLK_32K 88
#define PCLK_PMU_GPIO0 89
#define DBCLK_PMU_GPIO0 90
#define CLK_DDR_FAIL_SAFE 91
#define PCLK_PMU_HP_TIMER 92
#define CLK_PMU_32K_HP_TIMER 93
#define PCLK_PWM0 94
#define CLK_PWM0 95
#define CLK_OSC_PWM0 96
#define CLK_RC_PWM0 97
#define CLK_FREQ_PWM0 98
#define CLK_COUNTER_PWM0 99
#define PCLK_I2C0 100
#define CLK_I2C0 101
#define PCLK_UART0 102
#define PCLK_IOC_PMUIO0 103
#define CLK_REFOUT 104
#define CLK_PREROLL 105
#define CLK_PREROLL_32K 106
#define CLK_LPMCU_PMU 107
#define PCLK_SPI2AHB 108
#define HCLK_SPI2AHB 109
#define SCLK_SPI2AHB 110
#define PCLK_WDT_LPMCU 111
#define TCLK_WDT_LPMCU 112
#define HCLK_SFC_PMU1 113
#define HCLK_SFC_XIP_PMU1 114
#define SCLK_SFC_2X_PMU1 115
#define CLK_LPMCU 116
#define CLK_LPMCU_RTC 117
#define PCLK_LPMCU_MAILBOX 118
#define PCLK_IOC_PMUIO1 119
#define PCLK_CRU_PMU1 120
#define PCLK_PERI_ROOT 121
#define PCLK_RTC_ROOT 122
#define CLK_TIMER_ROOT 123
#define PCLK_TIMER 124
#define CLK_TIMER0 125
#define CLK_TIMER1 126
#define CLK_TIMER2 127
#define CLK_TIMER3 128
#define CLK_TIMER4 129
#define CLK_TIMER5 130
#define PCLK_STIMER 131
#define CLK_STIMER0 132
#define CLK_STIMER1 133
#define PCLK_WDT_NS 134
#define TCLK_WDT_NS 135
#define PCLK_WDT_S 136
#define TCLK_WDT_S 137
#define PCLK_WDT_HPMCU 138
#define TCLK_WDT_HPMCU 139
#define PCLK_I2C1 140
#define CLK_I2C1 141
#define PCLK_I2C2 142
#define CLK_I2C2 143
#define PCLK_I2C3 144
#define CLK_I2C3 145
#define PCLK_I2C4 146
#define CLK_I2C4 147
#define PCLK_SPI0 148
#define PCLK_PWM1 149
#define CLK_OSC_PWM1 150
#define PCLK_PWM2 151
#define CLK_OSC_PWM2 152
#define PCLK_UART2 153
#define PCLK_UART1 154
#define ACLK_RKDMA 155
#define PCLK_TSADC 156
#define CLK_TSADC 157
#define CLK_TSADC_TSEN 158
#define PCLK_SARADC 159
#define CLK_SARADC 160
#define PCLK_GPIO2 161
#define DBCLK_GPIO2 162
#define PCLK_IOC_VCCIO6 163
#define ACLK_USBOTG 164
#define CLK_REF_USBOTG 165
#define HCLK_SDMMC1 166
#define HCLK_SAI 167
#define MCLK_SAI 168
#define ACLK_CRYPTO 169
#define HCLK_CRYPTO 170
#define HCLK_RK_RNG_NS 171
#define HCLK_RK_RNG_S 172
#define PCLK_OTPC_NS 173
#define CLK_OTPC_ROOT_NS 174
#define CLK_SBPI_OTPC_NS 175
#define CLK_USER_OTPC_NS 176
#define PCLK_OTPC_S 177
#define CLK_OTPC_ROOT_S 178
#define CLK_SBPI_OTPC_S 179
#define CLK_USER_OTPC_S 180
#define CLK_OTPC_ARB 181
#define PCLK_OTP_MASK 182
#define HCLK_RGA 183
#define ACLK_RGA 184
#define ACLK_MAC 185
#define PCLK_MAC 186
#define CLK_MACPHY 187
#define ACLK_SPINLOCK 188
#define HCLK_CACHE 189
#define PCLK_HPMCU_MAILBOX 190
#define PCLK_HPMCU_INTMUX 191
#define CLK_HPMCU 192
#define CLK_HPMCU_RTC 193
#define DCLK_DECOM 194
#define ACLK_DECOM 195
#define PCLK_DECOM 196
#define ACLK_SYS_SRAM 197
#define PCLK_DMA2DDR 198
#define ACLK_DMA2DDR 199
#define PCLK_DCF 200
#define ACLK_DCF 201
#define MCLK_ACODEC_TX 202
#define SCLK_UART0_SRC 203
#define SCLK_UART1_SRC 204
#define SCLK_UART2_SRC 205
#define XIN_RC_SRC 206
#define CLK_UTMI_USBOTG 207
#define CLK_REF_USBPHY 208
#endif // _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H

View File

@ -0,0 +1,103 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Tenstorrent Atlantis PRCM Clock and Reset Indices
*
* Copyright (c) 2026 Tenstorrent
*/
#ifndef _DT_BINDINGS_ATLANTIS_PRCM_RCPU_H
#define _DT_BINDINGS_ATLANTIS_PRCM_RCPU_H
/*
* RCPU Domain Clock IDs
*/
#define CLK_RCPU_PLL 0
#define CLK_RCPU_ROOT 1
#define CLK_RCPU_DIV2 2
#define CLK_RCPU_DIV4 3
#define CLK_RCPU_RTC 4
#define CLK_SMNDMA0_ACLK 5
#define CLK_SMNDMA1_ACLK 6
#define CLK_WDT0_PCLK 7
#define CLK_WDT1_PCLK 8
#define CLK_TIMER_PCLK 9
#define CLK_PVTC_PCLK 10
#define CLK_PMU_PCLK 11
#define CLK_MAILBOX_HCLK 12
#define CLK_SEC_SPACC_HCLK 13
#define CLK_SEC_OTP_HCLK 14
#define CLK_TRNG_PCLK 15
#define CLK_SEC_CRC_HCLK 16
#define CLK_SMN_HCLK 17
#define CLK_AHB0_HCLK 18
#define CLK_SMN_PCLK 19
#define CLK_SMN_CLK 20
#define CLK_SCRATCHPAD_CLK 21
#define CLK_RCPU_CORE_CLK 22
#define CLK_RCPU_ROM_CLK 23
#define CLK_OTP_LOAD_CLK 24
#define CLK_NOC_PLL 25
#define CLK_NOCC_CLK 26
#define CLK_NOCC_DIV2 27
#define CLK_NOCC_DIV4 28
#define CLK_NOCC_RTC 29
#define CLK_NOCC_CAN 30
#define CLK_QSPI_SCLK 31
#define CLK_QSPI_HCLK 32
#define CLK_I2C0_PCLK 33
#define CLK_I2C1_PCLK 34
#define CLK_I2C2_PCLK 35
#define CLK_I2C3_PCLK 36
#define CLK_I2C4_PCLK 37
#define CLK_UART0_PCLK 38
#define CLK_UART1_PCLK 39
#define CLK_UART2_PCLK 40
#define CLK_UART3_PCLK 41
#define CLK_UART4_PCLK 42
#define CLK_SPI0_PCLK 43
#define CLK_SPI1_PCLK 44
#define CLK_SPI2_PCLK 45
#define CLK_SPI3_PCLK 46
#define CLK_GPIO_PCLK 47
#define CLK_CAN0_HCLK 48
#define CLK_CAN0_CLK 49
#define CLK_CAN1_HCLK 50
#define CLK_CAN1_CLK 51
#define CLK_CAN0_TIMER_CLK 52
#define CLK_CAN1_TIMER_CLK 53
/* RCPU domain reset */
#define RST_SMNDMA0 0
#define RST_SMNDMA1 1
#define RST_WDT0 2
#define RST_WDT1 3
#define RST_TMR 4
#define RST_PVTC 5
#define RST_PMU 6
#define RST_MAILBOX 7
#define RST_SPACC 8
#define RST_OTP 9
#define RST_TRNG 10
#define RST_CRC 11
#define RST_QSPI 12
#define RST_I2C0 13
#define RST_I2C1 14
#define RST_I2C2 15
#define RST_I2C3 16
#define RST_I2C4 17
#define RST_UART0 18
#define RST_UART1 19
#define RST_UART2 20
#define RST_UART3 21
#define RST_UART4 22
#define RST_SPI0 23
#define RST_SPI1 24
#define RST_SPI2 25
#define RST_SPI3 26
#define RST_GPIO 27
#define RST_CAN0 28
#define RST_CAN1 29
#define RST_I2S0 30
#define RST_I2S1 31
#endif /* _DT_BINDINGS_ATLANTIS_PRCM_RCPU_H */

View File

@ -197,6 +197,10 @@
#define VF610_CLK_TCON1 188
#define VF610_CLK_CAAM 189
#define VF610_CLK_CRC 190
#define VF610_CLK_END 191
#define VF610_CLK_ESW 191
#define VF610_CLK_ESW_MAC_TAB0 192
#define VF610_CLK_ESW_MAC_TAB1 193
#define VF610_CLK_ESW_MAC_TAB2 194
#define VF610_CLK_ESW_MAC_TAB3 195
#endif /* __DT_BINDINGS_CLOCK_VF610_H */