1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause
2 /*
3  *  Copyright (C) 2021 Microchip
4  */
5 
6 #include <dt-bindings/clock/at91.h>
7 #include <io.h>
8 #include <kernel/panic.h>
9 #include <kernel/pm.h>
10 #include <malloc.h>
11 #include <string.h>
12 #include <trace.h>
13 #include <types_ext.h>
14 
15 #include "at91_clk.h"
16 
17 #define PMC_MAX_IDS 128
18 #define PMC_MAX_PCKS 8
19 
pmc_clk_get_by_id(struct pmc_clk * clks,unsigned int nclk,unsigned int id)20 static struct clk *pmc_clk_get_by_id(struct pmc_clk *clks, unsigned int nclk,
21 				     unsigned int id)
22 {
23 	unsigned int i = 0;
24 
25 	for (i = 0; i < nclk; i++) {
26 		if (clks[i].clk && clks[i].id == id)
27 			return clks[i].clk;
28 	}
29 
30 	return NULL;
31 }
32 
pmc_clk_get_by_name(struct pmc_clk * clks,unsigned int nclk,const char * name)33 struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk,
34 				const char *name)
35 {
36 	unsigned int i = 0;
37 
38 	for (i = 0; i < nclk; i++)
39 		if (strcmp(clks[i].clk->name, name) == 0)
40 			return clks[i].clk;
41 
42 	return NULL;
43 }
44 
clk_dt_pmc_get(struct dt_driver_phandle_args * clkspec,void * data,TEE_Result * res)45 struct clk *clk_dt_pmc_get(struct dt_driver_phandle_args *clkspec, void *data,
46 			   TEE_Result *res)
47 {
48 	unsigned int type = clkspec->args[0];
49 	unsigned int idx = clkspec->args[1];
50 	struct pmc_data *pmc_data = data;
51 	struct pmc_clk *clks = NULL;
52 	struct clk *clk = NULL;
53 	unsigned int nclk = 0;
54 	*res = TEE_ERROR_GENERIC;
55 
56 	if (clkspec->args_count != 2) {
57 		*res = TEE_ERROR_BAD_PARAMETERS;
58 		return NULL;
59 	}
60 
61 	switch (type) {
62 	case PMC_TYPE_CORE:
63 		nclk = pmc_data->ncore;
64 		clks = pmc_data->chws;
65 		break;
66 	case PMC_TYPE_SYSTEM:
67 		nclk = pmc_data->nsystem;
68 		clks = pmc_data->shws;
69 		break;
70 	case PMC_TYPE_PERIPHERAL:
71 		nclk = pmc_data->nperiph;
72 		clks = pmc_data->phws;
73 		break;
74 	case PMC_TYPE_GCK:
75 		nclk = pmc_data->ngck;
76 		clks = pmc_data->ghws;
77 		break;
78 	case PMC_TYPE_PROGRAMMABLE:
79 		nclk = pmc_data->npck;
80 		clks = pmc_data->pchws;
81 		break;
82 	default:
83 		return NULL;
84 	}
85 
86 	clk = pmc_clk_get_by_id(clks, nclk, idx);
87 	if (clk)
88 		*res = TEE_SUCCESS;
89 
90 	return clk;
91 }
92 
pmc_data_allocate(unsigned int ncore,unsigned int nsystem,unsigned int nperiph,unsigned int ngck,unsigned int npck)93 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
94 				   unsigned int nperiph, unsigned int ngck,
95 				   unsigned int npck)
96 {
97 	unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
98 	unsigned int alloc_size = sizeof(struct pmc_data) +
99 				  num_clks * sizeof(struct pmc_clk);
100 	struct pmc_data *pmc_data = NULL;
101 
102 	pmc_data = calloc(1, alloc_size);
103 	if (!pmc_data)
104 		return NULL;
105 
106 	pmc_data->ncore = ncore;
107 	pmc_data->chws = pmc_data->hwtable;
108 
109 	pmc_data->nsystem = nsystem;
110 	pmc_data->shws = pmc_data->chws + ncore;
111 
112 	pmc_data->nperiph = nperiph;
113 	pmc_data->phws = pmc_data->shws + nsystem;
114 
115 	pmc_data->ngck = ngck;
116 	pmc_data->ghws = pmc_data->phws + nperiph;
117 
118 	pmc_data->npck = npck;
119 	pmc_data->pchws = pmc_data->ghws + ngck;
120 
121 	return pmc_data;
122 }
123 
124 #ifdef CFG_PM_ARM32
125 static uint8_t registered_ids[PMC_MAX_IDS];
126 static uint8_t registered_pcks[PMC_MAX_PCKS];
127 
128 static struct
129 {
130 	uint32_t scsr;
131 	uint32_t pcsr0;
132 	uint32_t uckr;
133 	uint32_t mor;
134 	uint32_t mcfr;
135 	uint32_t pllar;
136 	uint32_t mckr;
137 	uint32_t usb;
138 	uint32_t imr;
139 	uint32_t pcsr1;
140 	uint32_t pcr[PMC_MAX_IDS];
141 	uint32_t audio_pll0;
142 	uint32_t audio_pll1;
143 	uint32_t pckr[PMC_MAX_PCKS];
144 } pmc_cache;
145 
146 /*
147  * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
148  * without alteration in the table, and 0 is for unused clocks.
149  */
pmc_register_id(uint8_t id)150 void pmc_register_id(uint8_t id)
151 {
152 	int i = 0;
153 
154 	for (i = 0; i < PMC_MAX_IDS; i++) {
155 		if (registered_ids[i] == 0) {
156 			registered_ids[i] = id;
157 			return;
158 		}
159 		if (registered_ids[i] == id)
160 			return;
161 	}
162 
163 	panic("Invalid clock ID");
164 }
165 
166 /*
167  * As Programmable Clock 0 is valid on AT91 chips, there is an offset
168  * of 1 between the stored value and the real clock ID.
169  */
pmc_register_pck(uint8_t pck)170 void pmc_register_pck(uint8_t pck)
171 {
172 	int i = 0;
173 
174 	for (i = 0; i < PMC_MAX_PCKS; i++) {
175 		if (registered_pcks[i] == 0) {
176 			registered_pcks[i] = pck + 1;
177 			return;
178 		}
179 		if (registered_pcks[i] == pck + 1)
180 			return;
181 	}
182 
183 	panic("Invalid clock ID");
184 }
185 
pmc_suspend(void)186 static void pmc_suspend(void)
187 {
188 	int i = 0;
189 	uint8_t num = 0;
190 	vaddr_t pmc_base = at91_pmc_get_base();
191 
192 	pmc_cache.scsr = io_read32(pmc_base + AT91_PMC_SCSR);
193 	pmc_cache.pcsr0 = io_read32(pmc_base + AT91_PMC_PCSR);
194 	pmc_cache.uckr = io_read32(pmc_base + AT91_CKGR_UCKR);
195 	pmc_cache.mor = io_read32(pmc_base + AT91_CKGR_MOR);
196 	pmc_cache.mcfr = io_read32(pmc_base + AT91_CKGR_MCFR);
197 	pmc_cache.pllar = io_read32(pmc_base + AT91_CKGR_PLLAR);
198 	pmc_cache.mckr = io_read32(pmc_base + AT91_PMC_MCKR);
199 	pmc_cache.usb = io_read32(pmc_base + AT91_PMC_USB);
200 	pmc_cache.imr = io_read32(pmc_base + AT91_PMC_IMR);
201 	pmc_cache.pcsr1 = io_read32(pmc_base + AT91_PMC_PCSR1);
202 
203 	for (i = 0; registered_ids[i]; i++) {
204 		io_write32(pmc_base + AT91_PMC_PCR,
205 			   registered_ids[i] & AT91_PMC_PCR_PID_MASK);
206 		pmc_cache.pcr[registered_ids[i]] = io_read32(pmc_base +
207 							     AT91_PMC_PCR);
208 	}
209 	for (i = 0; registered_pcks[i]; i++) {
210 		num = registered_pcks[i] - 1;
211 		pmc_cache.pckr[num] = io_read32(pmc_base + AT91_PMC_PCKR(num));
212 	}
213 }
214 
pmc_ready(vaddr_t pmc_base,unsigned int mask)215 static bool pmc_ready(vaddr_t pmc_base, unsigned int mask)
216 {
217 	uint32_t status = 0;
218 
219 	status = io_read32(pmc_base + AT91_PMC_SR);
220 
221 	return (status & mask) == mask;
222 }
223 
pmc_resume(void)224 static void pmc_resume(void)
225 {
226 	int i = 0;
227 	uint8_t num = 0;
228 	uint32_t tmp = 0;
229 	vaddr_t pmc_base = at91_pmc_get_base();
230 	uint32_t mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
231 
232 	tmp = io_read32(pmc_base + AT91_PMC_MCKR);
233 	if (pmc_cache.mckr != tmp)
234 		panic("MCKR was not configured properly by the previous bootstage");
235 	tmp = io_read32(pmc_base + AT91_CKGR_PLLAR);
236 	if (pmc_cache.pllar != tmp)
237 		panic("PLLAR was not configured properly by the previous bootstage");
238 
239 	io_write32(pmc_base + AT91_PMC_SCER, pmc_cache.scsr);
240 	io_write32(pmc_base + AT91_PMC_PCER, pmc_cache.pcsr0);
241 	io_write32(pmc_base + AT91_CKGR_UCKR, pmc_cache.uckr);
242 	io_write32(pmc_base + AT91_CKGR_MOR, pmc_cache.mor);
243 	io_write32(pmc_base + AT91_CKGR_MCFR, pmc_cache.mcfr);
244 	io_write32(pmc_base + AT91_PMC_USB, pmc_cache.usb);
245 	io_write32(pmc_base + AT91_PMC_IMR, pmc_cache.imr);
246 	io_write32(pmc_base + AT91_PMC_PCER1, pmc_cache.pcsr1);
247 
248 	for (i = 0; registered_ids[i]; i++) {
249 		io_write32(pmc_base + AT91_PMC_PCR,
250 			   pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD);
251 	}
252 	for (i = 0; registered_pcks[i]; i++) {
253 		num = registered_pcks[i] - 1;
254 		io_write32(pmc_base + AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
255 	}
256 
257 	if (pmc_cache.uckr & AT91_PMC_UPLLEN)
258 		mask |= AT91_PMC_LOCKU;
259 
260 	while (!pmc_ready(pmc_base, mask))
261 		;
262 }
263 
pmc_pm(enum pm_op op,uint32_t pm_hint __unused,const struct pm_callback_handle * hdl __unused)264 static TEE_Result pmc_pm(enum pm_op op, uint32_t pm_hint __unused,
265 			 const struct pm_callback_handle *hdl __unused)
266 {
267 	switch (op) {
268 	case PM_OP_RESUME:
269 		pmc_resume();
270 		break;
271 	case PM_OP_SUSPEND:
272 		pmc_suspend();
273 		break;
274 	default:
275 		panic("Invalid PM operation");
276 	}
277 
278 	return TEE_SUCCESS;
279 }
280 
pmc_register_pm(void)281 void pmc_register_pm(void)
282 {
283 	/*
284 	 * We register the clock as a core service since clocks must be
285 	 * re-enable prior to accessing devices
286 	 */
287 	register_pm_core_service_cb(pmc_pm, NULL, "pmc");
288 }
289 
290 #endif
291