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 void stm32_serc_get_hwdata(void) 99 { 100 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 101 struct serc_driver_data *ddata = serc_dev.ddata; 102 vaddr_t base = pdata->base; 103 uint32_t regval = 0; 104 105 regval = io_read32(base + _SERC_HWCFGR); 106 107 ddata->num_ilac = _SERC_FLD_GET(_SERC_HWCFGR_CFG1, regval); 108 109 ddata->version = io_read32(base + _SERC_VERR); 110 111 DMSG("SERC version %"PRIu32".%"PRIu32, 112 _SERC_FLD_GET(_SERC_VERR_MAJREV, ddata->version), 113 _SERC_FLD_GET(_SERC_VERR_MINREV, ddata->version)); 114 115 DMSG("HW cap: num ilac:[%"PRIu8"]", ddata->num_ilac); 116 } 117 118 static TEE_Result stm32_serc_parse_fdt(const void *fdt, int node) 119 { 120 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 121 TEE_Result res = TEE_ERROR_GENERIC; 122 struct dt_node_info dt_info = { }; 123 struct io_pa_va base = { }; 124 125 fdt_fill_device_info(fdt, &dt_info, node); 126 if (dt_info.reg == DT_INFO_INVALID_REG) 127 return TEE_ERROR_BAD_PARAMETERS; 128 129 res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq); 130 if (res) 131 return res; 132 133 base.pa = dt_info.reg; 134 pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size); 135 136 return clk_dt_get_by_index(fdt, node, 0, &pdata->clock); 137 } 138 139 static void stm32_serc_handle_ilac(void) 140 { 141 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 142 struct serc_driver_data *ddata = serc_dev.ddata; 143 unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG); 144 vaddr_t base = pdata->base; 145 unsigned int i = 0; 146 uint32_t isr = 0; 147 148 for (i = 0; i < nreg; i++) { 149 uint32_t offset = sizeof(uint32_t) * i; 150 unsigned int j = 0; 151 152 isr = io_read32(base + _SERC_ISR0 + offset); 153 isr &= io_read32(base + _SERC_IER0 + offset); 154 155 if (!isr) 156 continue; 157 158 EMSG("SERC exceptions [%d:%d]: %#"PRIx32, 159 SERC_EXCEPT_MSB_BIT(i), SERC_EXCEPT_LSB_BIT(i), isr); 160 161 for (j = 0; j < _PERIPH_IDS_PER_REG; j++) { 162 EMSG("SERC exception ID: %d", 163 SERC_EXCEPT_LSB_BIT(i) + __builtin_ffs(isr) - 1); 164 165 io_write32(base + _SERC_ICR0 + offset, 166 BIT(__builtin_ffs(isr) - 1)); 167 168 isr = io_read32(base + _SERC_ISR0 + offset); 169 isr &= io_read32(base + _SERC_IER0 + offset); 170 171 if (!isr) 172 break; 173 } 174 } 175 176 stm32_rif_access_violation_action(); 177 if (IS_ENABLED(CFG_STM32_PANIC_ON_SERC_EVENT)) 178 panic(); 179 } 180 181 static enum itr_return stm32_serc_itr(struct itr_handler *h __unused) 182 { 183 stm32_serc_handle_ilac(); 184 185 return ITRR_HANDLED; 186 } 187 188 static void stm32_serc_setup(void) 189 { 190 struct stm32_serc_platdata *pdata = &serc_dev.pdata; 191 struct serc_driver_data *ddata = serc_dev.ddata; 192 vaddr_t base = serc_dev.pdata.base; 193 uint32_t nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG); 194 uint32_t i = 0; 195 196 io_setbits32(pdata->base + _SERC_ENABLE, _SERC_ENABLE_SERFEN); 197 198 for (i = 0; i < nreg; i++) { 199 vaddr_t reg_ofst = base + sizeof(uint32_t) * i; 200 201 /* Clear status flags */ 202 io_write32(reg_ofst + _SERC_ICR0, ~0x0); 203 /* Enable all peripherals of nreg */ 204 io_write32(reg_ofst + _SERC_IER0, ~0x0); 205 } 206 } 207 208 static TEE_Result probe_serc_device(const void *fdt, int node) 209 { 210 TEE_Result res = TEE_ERROR_GENERIC; 211 212 res = stm32_serc_parse_fdt(fdt, node); 213 if (res) 214 return res; 215 216 /* Unbalanced clock enable to have the SERC running */ 217 if (clk_enable(serc_dev.pdata.clock)) 218 panic(); 219 220 stm32_serc_get_hwdata(); 221 stm32_serc_setup(); 222 223 res = interrupt_alloc_add_handler(serc_dev.pdata.irq_chip, 224 serc_dev.pdata.irq, stm32_serc_itr, 225 ITRF_TRIGGER_LEVEL, NULL, 226 &serc_dev.itr); 227 if (res) 228 panic(); 229 230 interrupt_enable(serc_dev.pdata.irq_chip, serc_dev.itr->it); 231 232 return TEE_SUCCESS; 233 } 234 235 static TEE_Result stm32_serc_pm(enum pm_op op, unsigned int pm_hint, 236 const struct pm_callback_handle *hdl __unused) 237 { 238 if (!PM_HINT_IS_STATE(pm_hint, CONTEXT)) 239 return TEE_SUCCESS; 240 241 if (op == PM_OP_RESUME) { 242 if (clk_enable(serc_dev.pdata.clock)) 243 panic(); 244 stm32_serc_setup(); 245 } else { 246 clk_disable(serc_dev.pdata.clock); 247 } 248 249 return TEE_SUCCESS; 250 } 251 252 static TEE_Result stm32_serc_probe(const void *fdt, int node, 253 const void *compat_data __unused) 254 { 255 TEE_Result res = TEE_ERROR_GENERIC; 256 257 serc_dev.ddata = calloc(1, sizeof(*serc_dev.ddata)); 258 if (!serc_dev.ddata) 259 return TEE_ERROR_OUT_OF_MEMORY; 260 261 res = probe_serc_device(fdt, node); 262 if (res) { 263 free(serc_dev.ddata); 264 return res; 265 } 266 267 register_pm_core_service_cb(stm32_serc_pm, NULL, "stm32-serc"); 268 269 return TEE_SUCCESS; 270 } 271 272 static const struct dt_device_match stm32_serc_match_table[] = { 273 { .compatible = "st,stm32mp25-serc" }, 274 { } 275 }; 276 277 DEFINE_DT_DRIVER(stm32_serc_dt_driver) = { 278 .name = "stm32-serc", 279 .match_table = stm32_serc_match_table, 280 .probe = stm32_serc_probe, 281 }; 282