1 // SPDX-License-Identifier: GPL-2.0+
4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
6 * Common Clock Framework [CCF] driver for Sandbox
13 #include <clk-uclass.h>
14 #include <linux/clk-provider.h>
15 #include <sandbox-clk.h>
18 * Sandbox implementation of CCF primitives necessary for clk-uclass testing
20 * --- Sandbox PLLv3 ---
28 static ulong
clk_pllv3_get_rate(struct clk
*clk
)
30 unsigned long parent_rate
= clk_get_parent_rate(clk
);
32 return parent_rate
* 24;
35 static const struct clk_ops clk_pllv3_generic_ops
= {
36 .get_rate
= clk_pllv3_get_rate
,
39 struct clk
*sandbox_clk_pllv3(enum sandbox_pllv3_type type
, const char *name
,
40 const char *parent_name
, void __iomem
*base
,
43 struct clk_pllv3
*pll
;
45 char *drv_name
= "sandbox_clk_pllv3";
48 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
50 return ERR_PTR(-ENOMEM
);
52 pll
->div_mask
= div_mask
;
55 ret
= clk_register(clk
, drv_name
, name
, parent_name
);
64 U_BOOT_DRIVER(sandbox_clk_pll_generic
) = {
65 .name
= "sandbox_clk_pllv3",
67 .ops
= &clk_pllv3_generic_ops
,
70 /* --- Sandbox PLLv3 --- */
71 /* --- Sandbox Gate --- */
77 #define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk)
79 static int clk_gate2_enable(struct clk
*clk
)
81 struct clk_gate2
*gate
= to_clk_gate2(dev_get_clk_ptr(clk
->dev
));
87 static int clk_gate2_disable(struct clk
*clk
)
89 struct clk_gate2
*gate
= to_clk_gate2(dev_get_clk_ptr(clk
->dev
));
95 static const struct clk_ops clk_gate2_ops
= {
96 .enable
= clk_gate2_enable
,
97 .disable
= clk_gate2_disable
,
98 .get_rate
= clk_generic_get_rate
,
101 struct clk
*sandbox_clk_register_gate2(struct device
*dev
, const char *name
,
102 const char *parent_name
,
103 unsigned long flags
, void __iomem
*reg
,
104 u8 bit_idx
, u8 cgr_val
,
107 struct clk_gate2
*gate
;
111 gate
= kzalloc(sizeof(*gate
), GFP_KERNEL
);
113 return ERR_PTR(-ENOMEM
);
118 ret
= clk_register(clk
, "sandbox_clk_gate2", name
, parent_name
);
127 U_BOOT_DRIVER(sandbox_clk_gate2
) = {
128 .name
= "sandbox_clk_gate2",
130 .ops
= &clk_gate2_ops
,
133 /* --- Sandbox Gate --- */
134 /* The CCF core driver itself */
135 static const struct udevice_id sandbox_clk_ccf_test_ids
[] = {
136 { .compatible
= "sandbox,clk-ccf" },
140 static const char *const usdhc_sels
[] = { "pll3_60m", "pll3_80m", };
142 static int sandbox_clk_ccf_probe(struct udevice
*dev
)
147 clk_dm(SANDBOX_CLK_PLL3
,
148 sandbox_clk_pllv3(SANDBOX_PLLV3_USB
, "pll3_usb_otg", "osc",
151 clk_dm(SANDBOX_CLK_PLL3_60M
,
152 sandbox_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8));
154 clk_dm(SANDBOX_CLK_PLL3_80M
,
155 sandbox_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6));
157 /* The HW adds +1 to the divider value (2+1) is the divider */
159 clk_dm(SANDBOX_CLK_ECSPI_ROOT
,
160 sandbox_clk_divider("ecspi_root", "pll3_60m", ®
, 19, 6));
162 clk_dm(SANDBOX_CLK_ECSPI1
,
163 sandbox_clk_gate2("ecspi1", "ecspi_root", base
+ 0x6c, 0));
165 /* Select 'pll3_60m' */
167 clk_dm(SANDBOX_CLK_USDHC1_SEL
,
168 sandbox_clk_mux("usdhc1_sel", ®
, 16, 1, usdhc_sels
,
169 ARRAY_SIZE(usdhc_sels
)));
171 /* Select 'pll3_80m' */
173 clk_dm(SANDBOX_CLK_USDHC2_SEL
,
174 sandbox_clk_mux("usdhc2_sel", ®
, 17, 1, usdhc_sels
,
175 ARRAY_SIZE(usdhc_sels
)));
180 U_BOOT_DRIVER(sandbox_clk_ccf
) = {
181 .name
= "sandbox_clk_ccf",
183 .probe
= sandbox_clk_ccf_probe
,
184 .of_match
= sandbox_clk_ccf_test_ids
,