1 /* 2 * IMX7 System Reset Controller 3 * 4 * Copyright (c) 2023 Jean-Christophe Dubois <jcd@tribudubois.net> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 * 9 */ 10 11 #include "qemu/osdep.h" 12 #include "hw/misc/imx7_src.h" 13 #include "migration/vmstate.h" 14 #include "qemu/bitops.h" 15 #include "qemu/log.h" 16 #include "qemu/main-loop.h" 17 #include "qemu/module.h" 18 #include "target/arm/arm-powerctl.h" 19 #include "hw/core/cpu.h" 20 #include "hw/registerfields.h" 21 22 #include "trace.h" 23 24 static const char *imx7_src_reg_name(uint32_t reg) 25 { 26 static char unknown[20]; 27 28 switch (reg) { 29 case SRC_SCR: 30 return "SRC_SCR"; 31 case SRC_A7RCR0: 32 return "SRC_A7RCR0"; 33 case SRC_A7RCR1: 34 return "SRC_A7RCR1"; 35 case SRC_M4RCR: 36 return "SRC_M4RCR"; 37 case SRC_ERCR: 38 return "SRC_ERCR"; 39 case SRC_HSICPHY_RCR: 40 return "SRC_HSICPHY_RCR"; 41 case SRC_USBOPHY1_RCR: 42 return "SRC_USBOPHY1_RCR"; 43 case SRC_USBOPHY2_RCR: 44 return "SRC_USBOPHY2_RCR"; 45 case SRC_PCIEPHY_RCR: 46 return "SRC_PCIEPHY_RCR"; 47 case SRC_SBMR1: 48 return "SRC_SBMR1"; 49 case SRC_SRSR: 50 return "SRC_SRSR"; 51 case SRC_SISR: 52 return "SRC_SISR"; 53 case SRC_SIMR: 54 return "SRC_SIMR"; 55 case SRC_SBMR2: 56 return "SRC_SBMR2"; 57 case SRC_GPR1: 58 return "SRC_GPR1"; 59 case SRC_GPR2: 60 return "SRC_GPR2"; 61 case SRC_GPR3: 62 return "SRC_GPR3"; 63 case SRC_GPR4: 64 return "SRC_GPR4"; 65 case SRC_GPR5: 66 return "SRC_GPR5"; 67 case SRC_GPR6: 68 return "SRC_GPR6"; 69 case SRC_GPR7: 70 return "SRC_GPR7"; 71 case SRC_GPR8: 72 return "SRC_GPR8"; 73 case SRC_GPR9: 74 return "SRC_GPR9"; 75 case SRC_GPR10: 76 return "SRC_GPR10"; 77 default: 78 sprintf(unknown, "%u ?", reg); 79 return unknown; 80 } 81 } 82 83 static const VMStateDescription vmstate_imx7_src = { 84 .name = TYPE_IMX7_SRC, 85 .version_id = 1, 86 .minimum_version_id = 1, 87 .fields = (const VMStateField[]) { 88 VMSTATE_UINT32_ARRAY(regs, IMX7SRCState, SRC_MAX), 89 VMSTATE_END_OF_LIST() 90 }, 91 }; 92 93 static void imx7_src_reset(DeviceState *dev) 94 { 95 IMX7SRCState *s = IMX7_SRC(dev); 96 97 memset(s->regs, 0, sizeof(s->regs)); 98 99 /* Set reset values */ 100 s->regs[SRC_SCR] = 0xA0; 101 s->regs[SRC_SRSR] = 0x1; 102 s->regs[SRC_SIMR] = 0x1F; 103 } 104 105 static uint64_t imx7_src_read(void *opaque, hwaddr offset, unsigned size) 106 { 107 uint32_t value = 0; 108 IMX7SRCState *s = (IMX7SRCState *)opaque; 109 uint32_t index = offset >> 2; 110 111 if (index < SRC_MAX) { 112 value = s->regs[index]; 113 } else { 114 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 115 HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset); 116 } 117 118 trace_imx7_src_read(imx7_src_reg_name(index), value); 119 120 return value; 121 } 122 123 124 /* 125 * The reset is asynchronous so we need to defer clearing the reset 126 * bit until the work is completed. 127 */ 128 129 struct SRCSCRResetInfo { 130 IMX7SRCState *s; 131 uint32_t reset_bit; 132 }; 133 134 static void imx7_clear_reset_bit(CPUState *cpu, run_on_cpu_data data) 135 { 136 struct SRCSCRResetInfo *ri = data.host_ptr; 137 IMX7SRCState *s = ri->s; 138 139 assert(bql_locked()); 140 141 s->regs[SRC_A7RCR0] = deposit32(s->regs[SRC_A7RCR0], ri->reset_bit, 1, 0); 142 143 trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]); 144 145 g_free(ri); 146 } 147 148 static void imx7_defer_clear_reset_bit(uint32_t cpuid, 149 IMX7SRCState *s, 150 uint32_t reset_shift) 151 { 152 struct SRCSCRResetInfo *ri; 153 CPUState *cpu = arm_get_cpu_by_id(cpuid); 154 155 if (!cpu) { 156 return; 157 } 158 159 ri = g_new(struct SRCSCRResetInfo, 1); 160 ri->s = s; 161 ri->reset_bit = reset_shift; 162 163 async_run_on_cpu(cpu, imx7_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri)); 164 } 165 166 167 static void imx7_src_write(void *opaque, hwaddr offset, uint64_t value, 168 unsigned size) 169 { 170 IMX7SRCState *s = (IMX7SRCState *)opaque; 171 uint32_t index = offset >> 2; 172 long unsigned int change_mask; 173 uint32_t current_value = value; 174 175 if (index >= SRC_MAX) { 176 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 177 HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset); 178 return; 179 } 180 181 trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]); 182 183 change_mask = s->regs[index] ^ (uint32_t)current_value; 184 185 switch (index) { 186 case SRC_A7RCR0: 187 if (FIELD_EX32(change_mask, CORE0, RST)) { 188 arm_reset_cpu(0); 189 imx7_defer_clear_reset_bit(0, s, R_CORE0_RST_SHIFT); 190 } 191 if (FIELD_EX32(change_mask, CORE1, RST)) { 192 arm_reset_cpu(1); 193 imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT); 194 } 195 s->regs[index] = current_value; 196 break; 197 case SRC_A7RCR1: 198 /* 199 * On real hardware when the system reset controller starts a 200 * secondary CPU it runs through some boot ROM code which reads 201 * the SRC_GPRX registers controlling the start address and branches 202 * to it. 203 * Here we are taking a short cut and branching directly to the 204 * requested address (we don't want to run the boot ROM code inside 205 * QEMU) 206 */ 207 if (FIELD_EX32(change_mask, CORE1, ENABLE)) { 208 if (FIELD_EX32(current_value, CORE1, ENABLE)) { 209 /* CORE 1 is brought up */ 210 arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4], 211 3, false); 212 } else { 213 /* CORE 1 is shut down */ 214 arm_set_cpu_off(1); 215 } 216 /* We clear the reset bits as the processor changed state */ 217 imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT); 218 clear_bit(R_CORE1_RST_SHIFT, &change_mask); 219 } 220 s->regs[index] = current_value; 221 break; 222 default: 223 s->regs[index] = current_value; 224 break; 225 } 226 } 227 228 static const struct MemoryRegionOps imx7_src_ops = { 229 .read = imx7_src_read, 230 .write = imx7_src_write, 231 .endianness = DEVICE_NATIVE_ENDIAN, 232 .valid = { 233 /* 234 * Our device would not work correctly if the guest was doing 235 * unaligned access. This might not be a limitation on the real 236 * device but in practice there is no reason for a guest to access 237 * this device unaligned. 238 */ 239 .min_access_size = 4, 240 .max_access_size = 4, 241 .unaligned = false, 242 }, 243 }; 244 245 static void imx7_src_realize(DeviceState *dev, Error **errp) 246 { 247 IMX7SRCState *s = IMX7_SRC(dev); 248 249 memory_region_init_io(&s->iomem, OBJECT(dev), &imx7_src_ops, s, 250 TYPE_IMX7_SRC, 0x1000); 251 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); 252 } 253 254 static void imx7_src_class_init(ObjectClass *klass, void *data) 255 { 256 DeviceClass *dc = DEVICE_CLASS(klass); 257 258 dc->realize = imx7_src_realize; 259 dc->reset = imx7_src_reset; 260 dc->vmsd = &vmstate_imx7_src; 261 dc->desc = "i.MX6 System Reset Controller"; 262 } 263 264 static const TypeInfo imx7_src_info = { 265 .name = TYPE_IMX7_SRC, 266 .parent = TYPE_SYS_BUS_DEVICE, 267 .instance_size = sizeof(IMX7SRCState), 268 .class_init = imx7_src_class_init, 269 }; 270 271 static void imx7_src_register_types(void) 272 { 273 type_register_static(&imx7_src_info); 274 } 275 276 type_init(imx7_src_register_types) 277