1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022-2024, STMicroelectronics 4 */ 5 #include <drivers/clk.h> 6 #include <drivers/clk_dt.h> 7 #include <drivers/stm32_rif.h> 8 #include <io.h> 9 #include <kernel/boot.h> 10 #include <kernel/dt.h> 11 #include <kernel/interrupt.h> 12 #include <kernel/panic.h> 13 #include <kernel/pm.h> 14 #include <libfdt.h> 15 #include <mm/core_memprot.h> 16 #include <tee_api_defines.h> 17 #include <trace.h> 18 #include <util.h> 19 20 /* SERC offset register */ 21 #define _SERC_IER0 U(0x000) 22 #define _SERC_ISR0 U(0x040) 23 #define _SERC_ICR0 U(0x080) 24 #define _SERC_ENABLE U(0x100) 25 26 #define _SERC_HWCFGR U(0x3F0) 27 #define _SERC_VERR U(0x3F4) 28 29 /* SERC_ENABLE register fields */ 30 #define _SERC_ENABLE_SERFEN BIT(0) 31 32 /* SERC_HWCFGR register fields */ 33 #define _SERC_HWCFGR_CFG1_MASK GENMASK_32(7, 0) 34 #define _SERC_HWCFGR_CFG1_SHIFT U(0) 35 #define _SERC_HWCFGR_CFG2_MASK GENMASK_32(18, 16) 36 #define _SERC_HWCFGR_CFG2_SHIFT U(16) 37 38 /* SERC_VERR register fields */ 39 #define _SERC_VERR_MINREV_MASK GENMASK_32(3, 0) 40 #define _SERC_VERR_MINREV_SHIFT U(0) 41 #define _SERC_VERR_MAJREV_MASK GENMASK_32(7, 4) 42 #define _SERC_VERR_MAJREV_SHIFT U(4) 43 44 /* Periph id per register */ 45 #define _PERIPH_IDS_PER_REG U(32) 46 47 #define _SERC_FLD_PREP(field, value) (SHIFT_U32((value), \ 48 (field ## _SHIFT)) & \ 49 (field ## _MASK)) 50 #define _SERC_FLD_GET(field, value) (((uint32_t)(value) & \ 51 (field ## _MASK)) >> \ 52 (field ## _SHIFT)) 53 54 #define SERC_EXCEPT_MSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG + \ 55 _PERIPH_IDS_PER_REG - 1) 56 #define SERC_EXCEPT_LSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG) 57 58 /** 59 * struct serc_driver_data - Hardware information on the SERC peripheral 60 * 61 * @version: Peripheral version number 62 * @num_ilac: Number of SERC lines 63 */ 64 struct serc_driver_data { 65 uint32_t version; 66 uint8_t num_ilac; 67 }; 68 69 /** 70 * struct stm32_serc_platdata - Platform data for the SERC driver 71 * 72 * @irq_chip: Reference to the SERC's IRQ chip 73 * @clock: Reference on the SERC clock 74 * @base: Base address of the SERC peripheral 75 * @irq: ID of the SERC interrupt 76 */ 77 struct stm32_serc_platdata { 78 struct itr_chip *irq_chip; 79 struct clk *clock; 80 vaddr_t base; 81 size_t irq; 82 }; 83 84 /** 85 * struct serc_device - SERC device private data 86 * @pdata: Platform data read from the DT 87 * @ddata: Device data read from the hardware 88 * @itr: Interrupt handler reference 89 */ 90 struct serc_device { 91 struct stm32_serc_platdata pdata; 92 struct serc_driver_data *ddata; 93 struct itr_handler *itr; 94 }; 95 96 static struct serc_device serc_dev; 97 98 static __noreturn void access_violation_action(void) 99 { 100 DMSG("Ooops..."); 101 panic(); 102 } 103 104 static void stm32_serc_get_hwdata(void) 105 { 106 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 107 struct serc_driver_data *ddata = serc_dev.ddata; 108 vaddr_t base = pdata->base; 109 uint32_t regval = 0; 110 111 regval = io_read32(base + _SERC_HWCFGR); 112 113 ddata->num_ilac = _SERC_FLD_GET(_SERC_HWCFGR_CFG1, regval); 114 115 ddata->version = io_read32(base + _SERC_VERR); 116 117 DMSG("SERC version %"PRIu32".%"PRIu32, 118 _SERC_FLD_GET(_SERC_VERR_MAJREV, ddata->version), 119 _SERC_FLD_GET(_SERC_VERR_MINREV, ddata->version)); 120 121 DMSG("HW cap: num ilac:[%"PRIu8"]", ddata->num_ilac); 122 } 123 124 static TEE_Result stm32_serc_parse_fdt(const void *fdt, int node) 125 { 126 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 127 TEE_Result res = TEE_ERROR_GENERIC; 128 struct dt_node_info dt_info = { }; 129 struct io_pa_va base = { }; 130 131 fdt_fill_device_info(fdt, &dt_info, node); 132 if (dt_info.reg == DT_INFO_INVALID_REG) 133 return TEE_ERROR_BAD_PARAMETERS; 134 135 res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq); 136 if (res) 137 return res; 138 139 base.pa = dt_info.reg; 140 pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size); 141 142 return clk_dt_get_by_index(fdt, node, 0, &pdata->clock); 143 } 144 145 static void stm32_serc_handle_ilac(void) 146 { 147 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 148 struct serc_driver_data *ddata = serc_dev.ddata; 149 unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG); 150 vaddr_t base = pdata->base; 151 unsigned int i = 0; 152 uint32_t isr = 0; 153 154 for (i = 0; i < nreg; i++) { 155 uint32_t offset = sizeof(uint32_t) * i; 156 unsigned int j = 0; 157 158 isr = io_read32(base + _SERC_ISR0 + offset); 159 isr &= io_read32(base + _SERC_IER0 + offset); 160 161 if (!isr) 162 continue; 163 164 EMSG("SERC exceptions [%d:%d]: %#"PRIx32, 165 SERC_EXCEPT_MSB_BIT(i), SERC_EXCEPT_LSB_BIT(i), isr); 166 167 for (j = 0; j < _PERIPH_IDS_PER_REG; j++) { 168 EMSG("SERC exception ID: %d", 169 SERC_EXCEPT_LSB_BIT(i) + __builtin_ffs(isr) - 1); 170 171 io_write32(base + _SERC_ICR0 + offset, 172 BIT(__builtin_ffs(isr) - 1)); 173 174 isr = io_read32(base + _SERC_ISR0 + offset); 175 isr &= io_read32(base + _SERC_IER0 + offset); 176 177 if (!isr) 178 break; 179 } 180 } 181 182 access_violation_action(); 183 } 184 185 static enum itr_return stm32_serc_itr(struct itr_handler *h __unused) 186 { 187 stm32_serc_handle_ilac(); 188 189 return ITRR_HANDLED; 190 } 191 192 static void stm32_serc_setup(void) 193 { 194 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 195 struct serc_driver_data *ddata = serc_dev.ddata; 196 vaddr_t base = serc_dev.pdata.base; 197 uint32_t nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG); 198 uint32_t i = 0; 199 200 io_setbits32(pdata->base + _SERC_ENABLE, _SERC_ENABLE_SERFEN); 201 202 for (i = 0; i < nreg; i++) { 203 vaddr_t reg_ofst = base + sizeof(uint32_t) * i; 204 205 /* Clear status flags */ 206 io_write32(reg_ofst + _SERC_ICR0, ~0x0); 207 /* Enable all peripherals of nreg */ 208 io_write32(reg_ofst + _SERC_IER0, ~0x0); 209 } 210 } 211 212 static TEE_Result probe_serc_device(const void *fdt, int node) 213 { 214 TEE_Result res = TEE_ERROR_GENERIC; 215 216 res = stm32_serc_parse_fdt(fdt, node); 217 if (res) 218 return res; 219 220 /* Unbalanced clock enable to have the SERC running */ 221 if (clk_enable(serc_dev.pdata.clock)) 222 panic(); 223 224 stm32_serc_get_hwdata(); 225 stm32_serc_setup(); 226 227 res = interrupt_alloc_add_handler(serc_dev.pdata.irq_chip, 228 serc_dev.pdata.irq, stm32_serc_itr, 229 ITRF_TRIGGER_LEVEL, NULL, 230 &serc_dev.itr); 231 if (res) 232 panic(); 233 234 interrupt_enable(serc_dev.pdata.irq_chip, serc_dev.itr->it); 235 236 return TEE_SUCCESS; 237 } 238 239 static TEE_Result stm32_serc_pm(enum pm_op op, unsigned int pm_hint, 240 const struct pm_callback_handle *hdl __unused) 241 { 242 if (!PM_HINT_IS_STATE(pm_hint, CONTEXT)) 243 return TEE_SUCCESS; 244 245 if (op == PM_OP_RESUME) { 246 if (clk_enable(serc_dev.pdata.clock)) 247 panic(); 248 stm32_serc_setup(); 249 } else { 250 clk_disable(serc_dev.pdata.clock); 251 } 252 253 return TEE_SUCCESS; 254 } 255 256 static TEE_Result stm32_serc_probe(const void *fdt, int node, 257 const void *compat_data __unused) 258 { 259 TEE_Result res = TEE_ERROR_GENERIC; 260 261 serc_dev.ddata = calloc(1, sizeof(*serc_dev.ddata)); 262 if (!serc_dev.ddata) 263 return TEE_ERROR_OUT_OF_MEMORY; 264 265 res = probe_serc_device(fdt, node); 266 if (res) { 267 free(serc_dev.ddata); 268 return res; 269 } 270 271 register_pm_core_service_cb(stm32_serc_pm, NULL, "stm32-serc"); 272 273 return TEE_SUCCESS; 274 } 275 276 static const struct dt_device_match stm32_serc_match_table[] = { 277 { .compatible = "st,stm32mp25-serc" }, 278 { } 279 }; 280 281 DEFINE_DT_DRIVER(stm32_serc_dt_driver) = { 282 .name = "stm32-serc", 283 .match_table = stm32_serc_match_table, 284 .probe = stm32_serc_probe, 285 }; 286