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