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