1*3948a36bSJia Wang // SPDX-License-Identifier: GPL-2.0-only
2*3948a36bSJia Wang /*
3*3948a36bSJia Wang * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
4*3948a36bSJia Wang */
5*3948a36bSJia Wang
6*3948a36bSJia Wang #include <linux/module.h>
7*3948a36bSJia Wang
8*3948a36bSJia Wang #include <dt-bindings/clock/ultrarisc,dp1000-clk.h>
9*3948a36bSJia Wang
10*3948a36bSJia Wang #include "clk-ultrarisc.h"
11*3948a36bSJia Wang
12*3948a36bSJia Wang #define DP1000_PLL_CFG1_OFFSET 0x400
13*3948a36bSJia Wang #define DP1000_PLL_CFG2_OFFSET 0x404
14*3948a36bSJia Wang
15*3948a36bSJia Wang #define DP1000_CCR_UART_OFFSET 0x220
16*3948a36bSJia Wang #define DP1000_CCR_I2C_OFFSET 0x224
17*3948a36bSJia Wang #define DP1000_CCR_GMAC_OFFSET 0x228
18*3948a36bSJia Wang #define DP1000_CCR_SPI_OFFSET 0x22c
19*3948a36bSJia Wang #define DP1000_PERI_CLKENA_OFFSET 0x270
20*3948a36bSJia Wang
21*3948a36bSJia Wang #define DP1000_CCR_LOAD BIT(16)
22*3948a36bSJia Wang
23*3948a36bSJia Wang #define DP1000_PERI_MAX_RATE 62500000UL
24*3948a36bSJia Wang #define DP1000_CLK_NUM 21
25*3948a36bSJia Wang
26*3948a36bSJia Wang static const struct ultrarisc_pll_layout dp1000_pll_layout = {
27*3948a36bSJia Wang .cfg1_offset = DP1000_PLL_CFG1_OFFSET,
28*3948a36bSJia Wang .cfg2_offset = DP1000_PLL_CFG2_OFFSET,
29*3948a36bSJia Wang .frac_mask = GENMASK(23, 0),
30*3948a36bSJia Wang .m_mask = GENMASK(23, 16),
31*3948a36bSJia Wang .n_mask = GENMASK(11, 6),
32*3948a36bSJia Wang .oddiv1_mask = GENMASK(1, 0),
33*3948a36bSJia Wang .oddiv2_mask = GENMASK(4, 3),
34*3948a36bSJia Wang };
35*3948a36bSJia Wang
36*3948a36bSJia Wang static const struct ultrarisc_pll_desc dp1000_plls[] = {
37*3948a36bSJia Wang {
38*3948a36bSJia Wang .id = DP1000_CLK_SYSPLL,
39*3948a36bSJia Wang .name = "syspll_clk",
40*3948a36bSJia Wang },
41*3948a36bSJia Wang };
42*3948a36bSJia Wang
43*3948a36bSJia Wang #define DP1000_FIXED_FACTOR(_id, _name, _parent, _mult, _div) \
44*3948a36bSJia Wang { \
45*3948a36bSJia Wang .id = (_id), \
46*3948a36bSJia Wang .name = (_name), \
47*3948a36bSJia Wang .parent_id = (_parent), \
48*3948a36bSJia Wang .mult = (_mult), \
49*3948a36bSJia Wang .div = (_div), \
50*3948a36bSJia Wang }
51*3948a36bSJia Wang
52*3948a36bSJia Wang #define DP1000_DIV(_id, _name, _offset, _parent, _max_rate) \
53*3948a36bSJia Wang { \
54*3948a36bSJia Wang .id = (_id), \
55*3948a36bSJia Wang .name = (_name), \
56*3948a36bSJia Wang .offset = (_offset), \
57*3948a36bSJia Wang .parent_id = (_parent), \
58*3948a36bSJia Wang .max_rate = (_max_rate), \
59*3948a36bSJia Wang .load_mask = DP1000_CCR_LOAD, \
60*3948a36bSJia Wang .div_shift = 8, \
61*3948a36bSJia Wang .div_width = 4, \
62*3948a36bSJia Wang .gate_bit = 0, \
63*3948a36bSJia Wang .divider_flags = CLK_DIVIDER_ONE_BASED, \
64*3948a36bSJia Wang .gate_flags = 0, \
65*3948a36bSJia Wang }
66*3948a36bSJia Wang
67*3948a36bSJia Wang #define DP1000_GATE(_id, _name, _parent, _bit) \
68*3948a36bSJia Wang { \
69*3948a36bSJia Wang .id = (_id), \
70*3948a36bSJia Wang .name = (_name), \
71*3948a36bSJia Wang .offset = DP1000_PERI_CLKENA_OFFSET, \
72*3948a36bSJia Wang .parent_id = (_parent), \
73*3948a36bSJia Wang .gate_bit = (_bit), \
74*3948a36bSJia Wang .gate_flags = 0, \
75*3948a36bSJia Wang }
76*3948a36bSJia Wang
77*3948a36bSJia Wang static const struct ultrarisc_fixed_factor_desc dp1000_fixed_factor_clks[] = {
78*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_SYSPLL_DIV2, "syspll_div2_clk",
79*3948a36bSJia Wang DP1000_CLK_SYSPLL, 1, 2),
80*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_SUBSYS, "subsys_clk",
81*3948a36bSJia Wang DP1000_CLK_SYSPLL_DIV2, 1, 2),
82*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_PCIE_DBI, "pcie_dbi_clk",
83*3948a36bSJia Wang DP1000_CLK_SYSPLL, 1, 10),
84*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_PCIEX4_CORE, "pciex4_core_clk",
85*3948a36bSJia Wang DP1000_CLK_SYSPLL, 1, 2),
86*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_PCIEX16_CORE, "pciex16_core_clk",
87*3948a36bSJia Wang DP1000_CLK_SYSPLL, 1, 1),
88*3948a36bSJia Wang DP1000_FIXED_FACTOR(DP1000_CLK_PCIE_AUX, "pcie_aux_clk",
89*3948a36bSJia Wang DP1000_CLK_SYSPLL, 1, 40),
90*3948a36bSJia Wang };
91*3948a36bSJia Wang
92*3948a36bSJia Wang static const struct ultrarisc_divider_desc dp1000_divider_clks[] = {
93*3948a36bSJia Wang DP1000_DIV(DP1000_CLK_GMAC, "gmac_clk", DP1000_CCR_GMAC_OFFSET,
94*3948a36bSJia Wang DP1000_CLK_SYSPLL_DIV2, 0),
95*3948a36bSJia Wang DP1000_DIV(DP1000_CLK_UART_ROOT, "uart_root_clk",
96*3948a36bSJia Wang DP1000_CCR_UART_OFFSET, DP1000_CLK_SUBSYS,
97*3948a36bSJia Wang DP1000_PERI_MAX_RATE),
98*3948a36bSJia Wang DP1000_DIV(DP1000_CLK_I2C_ROOT, "i2c_root_clk",
99*3948a36bSJia Wang DP1000_CCR_I2C_OFFSET, DP1000_CLK_SUBSYS,
100*3948a36bSJia Wang DP1000_PERI_MAX_RATE),
101*3948a36bSJia Wang DP1000_DIV(DP1000_CLK_SPI_ROOT, "spi_root_clk",
102*3948a36bSJia Wang DP1000_CCR_SPI_OFFSET, DP1000_CLK_SUBSYS,
103*3948a36bSJia Wang DP1000_PERI_MAX_RATE),
104*3948a36bSJia Wang };
105*3948a36bSJia Wang
106*3948a36bSJia Wang static const struct ultrarisc_gate_desc dp1000_gate_clks[] = {
107*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_UART0, "uart0_clk", DP1000_CLK_UART_ROOT, 0),
108*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_UART1, "uart1_clk", DP1000_CLK_UART_ROOT, 1),
109*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_UART2, "uart2_clk", DP1000_CLK_UART_ROOT, 2),
110*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_UART3, "uart3_clk", DP1000_CLK_UART_ROOT, 3),
111*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_I2C0, "i2c0_clk", DP1000_CLK_I2C_ROOT, 4),
112*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_I2C1, "i2c1_clk", DP1000_CLK_I2C_ROOT, 5),
113*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_I2C2, "i2c2_clk", DP1000_CLK_I2C_ROOT, 6),
114*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_I2C3, "i2c3_clk", DP1000_CLK_I2C_ROOT, 7),
115*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_SPI0, "spi0_clk", DP1000_CLK_SPI_ROOT, 8),
116*3948a36bSJia Wang DP1000_GATE(DP1000_CLK_SPI1, "spi1_clk", DP1000_CLK_SPI_ROOT, 9),
117*3948a36bSJia Wang };
118*3948a36bSJia Wang
119*3948a36bSJia Wang static const struct ultrarisc_clk_soc_data dp1000_clk_soc_data = {
120*3948a36bSJia Wang .num_clks = DP1000_CLK_NUM,
121*3948a36bSJia Wang .pll_layout = &dp1000_pll_layout,
122*3948a36bSJia Wang .plls = dp1000_plls,
123*3948a36bSJia Wang .num_plls = ARRAY_SIZE(dp1000_plls),
124*3948a36bSJia Wang .fixed_factors = dp1000_fixed_factor_clks,
125*3948a36bSJia Wang .num_fixed_factors = ARRAY_SIZE(dp1000_fixed_factor_clks),
126*3948a36bSJia Wang .dividers = dp1000_divider_clks,
127*3948a36bSJia Wang .num_dividers = ARRAY_SIZE(dp1000_divider_clks),
128*3948a36bSJia Wang .gates = dp1000_gate_clks,
129*3948a36bSJia Wang .num_gates = ARRAY_SIZE(dp1000_gate_clks),
130*3948a36bSJia Wang };
131*3948a36bSJia Wang
dp1000_clk_probe(struct platform_device * pdev)132*3948a36bSJia Wang static int dp1000_clk_probe(struct platform_device *pdev)
133*3948a36bSJia Wang {
134*3948a36bSJia Wang return ultrarisc_clk_probe(pdev, &dp1000_clk_soc_data);
135*3948a36bSJia Wang }
136*3948a36bSJia Wang
137*3948a36bSJia Wang static const struct of_device_id dp1000_clk_of_match[] = {
138*3948a36bSJia Wang { .compatible = "ultrarisc,dp1000-clk" },
139*3948a36bSJia Wang { }
140*3948a36bSJia Wang };
141*3948a36bSJia Wang MODULE_DEVICE_TABLE(of, dp1000_clk_of_match);
142*3948a36bSJia Wang
143*3948a36bSJia Wang static struct platform_driver dp1000_clk_driver = {
144*3948a36bSJia Wang .probe = dp1000_clk_probe,
145*3948a36bSJia Wang .driver = {
146*3948a36bSJia Wang .name = "ultrarisc-dp1000-clk",
147*3948a36bSJia Wang .of_match_table = dp1000_clk_of_match,
148*3948a36bSJia Wang },
149*3948a36bSJia Wang };
150*3948a36bSJia Wang module_platform_driver(dp1000_clk_driver);
151*3948a36bSJia Wang
152*3948a36bSJia Wang MODULE_IMPORT_NS("CLK_ULTRARISC");
153*3948a36bSJia Wang MODULE_DESCRIPTION("UltraRISC DP1000 clock controller");
154*3948a36bSJia Wang MODULE_LICENSE("GPL");
155