1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, STMicroelectronics 4 */ 5 #include <assert.h> 6 #include <compiler.h> 7 #include <drivers/scmi-msg.h> 8 #include <drivers/scmi.h> 9 #include <dt-bindings/reset/stm32mp1-resets.h> 10 #include <initcall.h> 11 #include <mm/core_memprot.h> 12 #include <mm/core_mmu.h> 13 #include <platform_config.h> 14 #include <stdint.h> 15 #include <speculation_barrier.h> 16 #include <stm32_util.h> 17 #include <string.h> 18 #include <tee_api_defines.h> 19 #include <util.h> 20 21 #define TIMEOUT_US_1MS 1000 22 23 #define SCMI_RD_NAME_SIZE 16 24 25 /* 26 * struct stm32_scmi_rd - Data for the exposed reset controller 27 * @reset_id: Reset identifier in RCC reset driver 28 * @name: Reset string ID exposed to agent 29 */ 30 struct stm32_scmi_rd { 31 unsigned long reset_id; 32 const char *name; 33 }; 34 35 /* Locate all non-secure SMT message buffers in last page of SYSRAM */ 36 #define SMT_BUFFER_BASE CFG_STM32MP1_SCMI_SHM_BASE 37 #define SMT_BUFFER0_BASE SMT_BUFFER_BASE 38 #define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200) 39 40 #if (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE > \ 41 CFG_STM32MP1_SCMI_SHM_BASE + CFG_STM32MP1_SCMI_SHM_SIZE) 42 #error "SCMI shared memory mismatch" 43 #endif 44 45 register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE, 46 CFG_STM32MP1_SCMI_SHM_SIZE); 47 48 static struct scmi_msg_channel scmi_channel[] = { 49 [0] = { 50 .agent_name = "stm32mp1-agent-0", 51 .shm_addr = { .pa = SMT_BUFFER0_BASE, }, 52 .shm_size = SMT_BUF_SLOT_SIZE, 53 }, 54 [1] = { 55 .agent_name = "stm32mp1-agent-1", 56 .shm_addr = { .pa = SMT_BUFFER1_BASE, }, 57 .shm_size = SMT_BUF_SLOT_SIZE, 58 }, 59 }; 60 61 struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id) 62 { 63 assert(agent_id < ARRAY_SIZE(scmi_channel)); 64 65 return &scmi_channel[agent_id]; 66 } 67 68 #define RESET_CELL(_scmi_id, _id, _name) \ 69 [_scmi_id] = { \ 70 .reset_id = _id, \ 71 .name = _name, \ 72 } 73 74 struct stm32_scmi_rd stm32_scmi0_reset_domain[] = { 75 RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"), 76 RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"), 77 RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"), 78 RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"), 79 RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"), 80 RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"), 81 RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"), 82 RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"), 83 RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), 84 RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), 85 RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), 86 }; 87 88 struct scmi_agent_resources { 89 struct stm32_scmi_clk *clock; 90 size_t clock_count; 91 struct stm32_scmi_rd *rd; 92 size_t rd_count; 93 struct stm32_scmi_pd *pd; 94 size_t pd_count; 95 struct stm32_scmi_perfs *perfs; 96 size_t perfs_count; 97 }; 98 99 const struct scmi_agent_resources agent_resources[] = { 100 [0] = { 101 .rd = stm32_scmi0_reset_domain, 102 .rd_count = ARRAY_SIZE(stm32_scmi0_reset_domain), 103 }, 104 [1] = { }, 105 }; 106 107 static const struct scmi_agent_resources *find_resource(unsigned int agent_id) 108 { 109 assert(agent_id < ARRAY_SIZE(agent_resources)); 110 111 return &agent_resources[agent_id]; 112 } 113 114 static size_t __maybe_unused plat_scmi_protocol_count_paranoid(void) 115 { 116 unsigned int n = 0; 117 unsigned int count = 0; 118 const size_t agent_count = ARRAY_SIZE(agent_resources); 119 120 for (n = 0; n < agent_count; n++) 121 if (agent_resources[n].clock_count) 122 break; 123 if (n < agent_count) 124 count++; 125 126 for (n = 0; n < agent_count; n++) 127 if (agent_resources[n].rd_count) 128 break; 129 if (n < agent_count) 130 count++; 131 132 for (n = 0; n < agent_count; n++) 133 if (agent_resources[n].pd_count) 134 break; 135 if (n < agent_count) 136 count++; 137 138 for (n = 0; n < agent_count; n++) 139 if (agent_resources[n].perfs_count) 140 break; 141 if (n < agent_count) 142 count++; 143 144 return count; 145 } 146 147 static const char vendor[] = "ST"; 148 static const char sub_vendor[] = ""; 149 150 const char *plat_scmi_vendor_name(void) 151 { 152 return vendor; 153 } 154 155 const char *plat_scmi_sub_vendor_name(void) 156 { 157 return sub_vendor; 158 } 159 160 /* Currently supporting Reset Domains */ 161 static const uint8_t plat_protocol_list[] = { 162 SCMI_PROTOCOL_ID_RESET_DOMAIN, 163 0 /* Null termination */ 164 }; 165 166 size_t plat_scmi_protocol_count(void) 167 { 168 const size_t count = ARRAY_SIZE(plat_protocol_list) - 1; 169 170 assert(count == plat_scmi_protocol_count_paranoid()); 171 172 return count; 173 } 174 175 const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused) 176 { 177 assert(plat_scmi_protocol_count_paranoid() == 178 (ARRAY_SIZE(plat_protocol_list) - 1)); 179 180 return plat_protocol_list; 181 } 182 183 /* 184 * Platform SCMI reset domains 185 */ 186 static struct stm32_scmi_rd *find_rd(unsigned int agent_id, 187 unsigned int scmi_id) 188 { 189 const struct scmi_agent_resources *resource = find_resource(agent_id); 190 size_t n = 0; 191 192 if (resource) { 193 for (n = 0; n < resource->rd_count; n++) 194 if (n == scmi_id) 195 return &resource->rd[n]; 196 } 197 198 return NULL; 199 } 200 201 const char *plat_scmi_rd_get_name(unsigned int agent_id, unsigned int scmi_id) 202 { 203 const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); 204 205 if (!rd) 206 return NULL; 207 208 return rd->name; 209 } 210 211 size_t plat_scmi_rd_count(unsigned int agent_id) 212 { 213 const struct scmi_agent_resources *resource = find_resource(agent_id); 214 215 if (!resource) 216 return 0; 217 218 return resource->rd_count; 219 } 220 221 int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id, 222 uint32_t state) 223 { 224 const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); 225 226 if (!rd) 227 return SCMI_NOT_FOUND; 228 229 if (!stm32mp_nsec_can_access_reset(rd->reset_id)) 230 return SCMI_DENIED; 231 232 /* Supports only reset with context loss */ 233 if (state) 234 return SCMI_NOT_SUPPORTED; 235 236 DMSG("SCMI reset %u cycle", scmi_id); 237 238 if (stm32_reset_assert(rd->reset_id, TIMEOUT_US_1MS)) 239 return SCMI_HARDWARE_ERROR; 240 241 if (stm32_reset_deassert(rd->reset_id, TIMEOUT_US_1MS)) 242 return SCMI_HARDWARE_ERROR; 243 244 return SCMI_SUCCESS; 245 } 246 247 int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id, 248 bool assert_not_deassert) 249 { 250 const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id); 251 252 if (!rd) 253 return SCMI_NOT_FOUND; 254 255 if (!stm32mp_nsec_can_access_reset(rd->reset_id)) 256 return SCMI_DENIED; 257 258 if (assert_not_deassert) { 259 DMSG("SCMI reset %u set", scmi_id); 260 stm32_reset_set(rd->reset_id); 261 } else { 262 DMSG("SCMI reset %u release", scmi_id); 263 stm32_reset_release(rd->reset_id); 264 } 265 266 return SCMI_SUCCESS; 267 } 268 269 /* 270 * Initialize platform SCMI resources 271 */ 272 static TEE_Result stm32mp1_init_scmi_server(void) 273 { 274 size_t i = 0; 275 size_t j = 0; 276 277 for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) { 278 struct scmi_msg_channel *chan = &scmi_channel[i]; 279 280 /* Enforce non-secure shm mapped as device memory */ 281 chan->shm_addr.va = (vaddr_t)phys_to_virt(chan->shm_addr.pa, 282 MEM_AREA_IO_NSEC); 283 assert(chan->shm_addr.va); 284 285 scmi_smt_init_agent_channel(chan); 286 } 287 288 for (i = 0; i < ARRAY_SIZE(agent_resources); i++) { 289 const struct scmi_agent_resources *res = &agent_resources[i]; 290 291 for (j = 0; j < res->rd_count; j++) { 292 struct stm32_scmi_rd *rd = &res->rd[j]; 293 294 if (!rd->name || 295 strlen(rd->name) >= SCMI_RD_NAME_SIZE) 296 panic("SCMI reset domain name invalid"); 297 } 298 } 299 300 return TEE_SUCCESS; 301 } 302 303 driver_init_late(stm32mp1_init_scmi_server); 304