1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2022
4  * Author(s): Jesse Taube <Mr.Bossman075@gmail.com>
5  */
6 
7 #include <common.h>
8 #include <clk.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <log.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/imx-regs.h>
14 #include <dt-bindings/clock/imxrt1170-clock.h>
15 
16 #include "clk.h"
17 
imxrt1170_clk_get_rate(struct clk * clk)18 static ulong imxrt1170_clk_get_rate(struct clk *clk)
19 {
20 	struct clk *c;
21 	int ret;
22 
23 	debug("%s(#%lu)\n", __func__, clk->id);
24 
25 	ret = clk_get_by_id(clk->id, &c);
26 	if (ret)
27 		return ret;
28 
29 	return clk_get_rate(c);
30 }
31 
imxrt1170_clk_set_rate(struct clk * clk,ulong rate)32 static ulong imxrt1170_clk_set_rate(struct clk *clk, ulong rate)
33 {
34 	struct clk *c;
35 	int ret;
36 
37 	debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
38 
39 	ret = clk_get_by_id(clk->id, &c);
40 	if (ret)
41 		return ret;
42 
43 	return clk_set_rate(c, rate);
44 }
45 
__imxrt1170_clk_enable(struct clk * clk,bool enable)46 static int __imxrt1170_clk_enable(struct clk *clk, bool enable)
47 {
48 	struct clk *c;
49 	int ret;
50 
51 	debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
52 
53 	ret = clk_get_by_id(clk->id, &c);
54 	if (ret)
55 		return ret;
56 
57 	if (enable)
58 		ret = clk_enable(c);
59 	else
60 		ret = clk_disable(c);
61 
62 	return ret;
63 }
64 
imxrt1170_clk_disable(struct clk * clk)65 static int imxrt1170_clk_disable(struct clk *clk)
66 {
67 	return __imxrt1170_clk_enable(clk, 0);
68 }
69 
imxrt1170_clk_enable(struct clk * clk)70 static int imxrt1170_clk_enable(struct clk *clk)
71 {
72 	return __imxrt1170_clk_enable(clk, 1);
73 }
74 
imxrt1170_clk_set_parent(struct clk * clk,struct clk * parent)75 static int imxrt1170_clk_set_parent(struct clk *clk, struct clk *parent)
76 {
77 	struct clk *c, *cp;
78 	int ret;
79 
80 	debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id);
81 
82 	ret = clk_get_by_id(clk->id, &c);
83 	if (ret)
84 		return ret;
85 
86 	ret = clk_get_by_id(parent->id, &cp);
87 	if (ret)
88 		return ret;
89 
90 	return clk_set_parent(c, cp);
91 }
92 
93 static struct clk_ops imxrt1170_clk_ops = {
94 	.set_rate = imxrt1170_clk_set_rate,
95 	.get_rate = imxrt1170_clk_get_rate,
96 	.enable = imxrt1170_clk_enable,
97 	.disable = imxrt1170_clk_disable,
98 	.set_parent = imxrt1170_clk_set_parent,
99 };
100 
101 static const char * const lpuart1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
102 "pll3_div2", "pll1_div5", "pll2_sys", "pll2_pfd3"};
103 static const char * const gpt1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
104 "pll3_div2", "pll1_div5", "pll3_pfd2", "pll3_pfd3"};
105 static const char * const usdhc1_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
106 "pll2_pfd2", "pll2_pfd0", "pll1_div5", "pll_arm"};
107 static const char * const semc_sels[] = {"rcosc48M_div2", "osc", "rcosc400M", "rcosc16M",
108 "pll1_div5", "pll2_sys", "pll2_pfd2", "pll3_pfd0"};
109 
imxrt1170_clk_probe(struct udevice * dev)110 static int imxrt1170_clk_probe(struct udevice *dev)
111 {
112 	void *base;
113 
114 	/* Anatop clocks */
115 	base = (void *)ofnode_get_addr(ofnode_by_compatible(ofnode_null(), "fsl,imxrt-anatop"));
116 
117 
118 
119 	clk_dm(IMXRT1170_CLK_RCOSC_48M,
120 	       imx_clk_fixed_factor("rcosc48M", "rcosc16M", 3, 1));
121 	clk_dm(IMXRT1170_CLK_RCOSC_400M,
122 	       imx_clk_fixed_factor("rcosc400M",  "rcosc16M", 25, 1));
123 	clk_dm(IMXRT1170_CLK_RCOSC_48M_DIV2,
124 	       imx_clk_fixed_factor("rcosc48M_div2",  "rcosc48M", 1, 2));
125 
126 
127 	clk_dm(IMXRT1170_CLK_PLL_ARM,
128 	       imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm", "osc",
129 			     base + 0x200, 0xff));
130 	clk_dm(IMXRT1170_CLK_PLL3,
131 	       imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll3_sys", "osc",
132 			     base + 0x210, 1));
133 	clk_dm(IMXRT1170_CLK_PLL2,
134 	       imx_clk_pllv3(IMX_PLLV3_GENERICV2, "pll2_sys", "osc",
135 			     base + 0x240, 1));
136 
137 	clk_dm(IMXRT1170_CLK_PLL3_PFD0,
138 	       imx_clk_pfd("pll3_pfd0", "pll3_sys", base + 0x230, 0));
139 	clk_dm(IMXRT1170_CLK_PLL3_PFD1,
140 	       imx_clk_pfd("pll3_pfd1", "pll3_sys", base + 0x230, 1));
141 	clk_dm(IMXRT1170_CLK_PLL3_PFD2,
142 	       imx_clk_pfd("pll3_pfd2", "pll3_sys", base + 0x230, 2));
143 	clk_dm(IMXRT1170_CLK_PLL3_PFD3,
144 	       imx_clk_pfd("pll3_pfd3", "pll3_sys", base + 0x230, 3));
145 
146 	clk_dm(IMXRT1170_CLK_PLL2_PFD0,
147 	       imx_clk_pfd("pll2_pfd0", "pll2_sys", base + 0x270, 0));
148 	clk_dm(IMXRT1170_CLK_PLL2_PFD1,
149 	       imx_clk_pfd("pll2_pfd1", "pll2_sys", base + 0x270, 1));
150 	clk_dm(IMXRT1170_CLK_PLL2_PFD2,
151 	       imx_clk_pfd("pll2_pfd2", "pll2_sys", base + 0x270, 2));
152 	clk_dm(IMXRT1170_CLK_PLL2_PFD3,
153 	       imx_clk_pfd("pll2_pfd3", "pll2_sys", base + 0x270, 3));
154 
155 	clk_dm(IMXRT1170_CLK_PLL3_DIV2,
156 	       imx_clk_fixed_factor("pll3_div2", "pll3_sys", 1, 2));
157 
158 	/* CCM clocks */
159 	base = dev_read_addr_ptr(dev);
160 	if (base == (void *)FDT_ADDR_T_NONE)
161 		return -EINVAL;
162 
163 	clk_dm(IMXRT1170_CLK_LPUART1_SEL,
164 	       imx_clk_mux("lpuart1_sel", base + (25 * 0x80), 8, 3,
165 			   lpuart1_sels, ARRAY_SIZE(lpuart1_sels)));
166 	clk_dm(IMXRT1170_CLK_LPUART1,
167 	       imx_clk_divider("lpuart1", "lpuart1_sel",
168 			       base + (25 * 0x80), 0, 8));
169 
170 	clk_dm(IMXRT1170_CLK_USDHC1_SEL,
171 	       imx_clk_mux("usdhc1_sel", base + (58 * 0x80), 8, 3,
172 			   usdhc1_sels, ARRAY_SIZE(usdhc1_sels)));
173 	clk_dm(IMXRT1170_CLK_USDHC1,
174 	       imx_clk_divider("usdhc1", "usdhc1_sel",
175 			       base + (58 * 0x80), 0, 8));
176 
177 	clk_dm(IMXRT1170_CLK_GPT1_SEL,
178 	       imx_clk_mux("gpt1_sel", base + (14 * 0x80), 8, 3,
179 			   gpt1_sels, ARRAY_SIZE(gpt1_sels)));
180 	clk_dm(IMXRT1170_CLK_GPT1,
181 	       imx_clk_divider("gpt1", "gpt1_sel",
182 			       base + (14 * 0x80), 0, 8));
183 
184 	clk_dm(IMXRT1170_CLK_SEMC_SEL,
185 	       imx_clk_mux("semc_sel", base + (4 * 0x80), 8, 3,
186 			   semc_sels, ARRAY_SIZE(semc_sels)));
187 	clk_dm(IMXRT1170_CLK_SEMC,
188 	       imx_clk_divider("semc", "semc_sel",
189 			       base + (4 * 0x80), 0, 8));
190 	struct clk *clk, *clk1;
191 
192 	clk_get_by_id(IMXRT1170_CLK_PLL2_PFD2, &clk);
193 
194 	clk_get_by_id(IMXRT1170_CLK_SEMC_SEL, &clk1);
195 	clk_enable(clk1);
196 	clk_set_parent(clk1, clk);
197 
198 	clk_get_by_id(IMXRT1170_CLK_SEMC, &clk);
199 	clk_enable(clk);
200 	clk_set_rate(clk, 132000000UL);
201 
202 	clk_get_by_id(IMXRT1170_CLK_GPT1, &clk);
203 	clk_enable(clk);
204 	clk_set_rate(clk, 32000000UL);
205 
206 	return 0;
207 }
208 
209 static const struct udevice_id imxrt1170_clk_ids[] = {
210 	{ .compatible = "fsl,imxrt1170-ccm" },
211 	{ },
212 };
213 
214 U_BOOT_DRIVER(imxrt1170_clk) = {
215 	.name = "clk_imxrt1170",
216 	.id = UCLASS_CLK,
217 	.of_match = imxrt1170_clk_ids,
218 	.ops = &imxrt1170_clk_ops,
219 	.probe = imxrt1170_clk_probe,
220 	.flags = DM_FLAG_PRE_RELOC,
221 };
222