imx6_src.c (9069B)
1/* 2 * IMX6 System Reset Controller 3 * 4 * Copyright (c) 2015 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/imx6_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 "arm-powerctl.h" 19#include "hw/core/cpu.h" 20 21#ifndef DEBUG_IMX6_SRC 22#define DEBUG_IMX6_SRC 0 23#endif 24 25#define DPRINTF(fmt, args...) \ 26 do { \ 27 if (DEBUG_IMX6_SRC) { \ 28 fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_SRC, \ 29 __func__, ##args); \ 30 } \ 31 } while (0) 32 33static const char *imx6_src_reg_name(uint32_t reg) 34{ 35 static char unknown[20]; 36 37 switch (reg) { 38 case SRC_SCR: 39 return "SRC_SCR"; 40 case SRC_SBMR1: 41 return "SRC_SBMR1"; 42 case SRC_SRSR: 43 return "SRC_SRSR"; 44 case SRC_SISR: 45 return "SRC_SISR"; 46 case SRC_SIMR: 47 return "SRC_SIMR"; 48 case SRC_SBMR2: 49 return "SRC_SBMR2"; 50 case SRC_GPR1: 51 return "SRC_GPR1"; 52 case SRC_GPR2: 53 return "SRC_GPR2"; 54 case SRC_GPR3: 55 return "SRC_GPR3"; 56 case SRC_GPR4: 57 return "SRC_GPR4"; 58 case SRC_GPR5: 59 return "SRC_GPR5"; 60 case SRC_GPR6: 61 return "SRC_GPR6"; 62 case SRC_GPR7: 63 return "SRC_GPR7"; 64 case SRC_GPR8: 65 return "SRC_GPR8"; 66 case SRC_GPR9: 67 return "SRC_GPR9"; 68 case SRC_GPR10: 69 return "SRC_GPR10"; 70 default: 71 sprintf(unknown, "%u ?", reg); 72 return unknown; 73 } 74} 75 76static const VMStateDescription vmstate_imx6_src = { 77 .name = TYPE_IMX6_SRC, 78 .version_id = 1, 79 .minimum_version_id = 1, 80 .fields = (VMStateField[]) { 81 VMSTATE_UINT32_ARRAY(regs, IMX6SRCState, SRC_MAX), 82 VMSTATE_END_OF_LIST() 83 }, 84}; 85 86static void imx6_src_reset(DeviceState *dev) 87{ 88 IMX6SRCState *s = IMX6_SRC(dev); 89 90 DPRINTF("\n"); 91 92 memset(s->regs, 0, sizeof(s->regs)); 93 94 /* Set reset values */ 95 s->regs[SRC_SCR] = 0x521; 96 s->regs[SRC_SRSR] = 0x1; 97 s->regs[SRC_SIMR] = 0x1F; 98} 99 100static uint64_t imx6_src_read(void *opaque, hwaddr offset, unsigned size) 101{ 102 uint32_t value = 0; 103 IMX6SRCState *s = (IMX6SRCState *)opaque; 104 uint32_t index = offset >> 2; 105 106 if (index < SRC_MAX) { 107 value = s->regs[index]; 108 } else { 109 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 110 HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset); 111 112 } 113 114 DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_src_reg_name(index), value); 115 116 return value; 117} 118 119 120/* The reset is asynchronous so we need to defer clearing the reset 121 * bit until the work is completed. 122 */ 123 124struct SRCSCRResetInfo { 125 IMX6SRCState *s; 126 int reset_bit; 127}; 128 129static void imx6_clear_reset_bit(CPUState *cpu, run_on_cpu_data data) 130{ 131 struct SRCSCRResetInfo *ri = data.host_ptr; 132 IMX6SRCState *s = ri->s; 133 134 assert(qemu_mutex_iothread_locked()); 135 136 s->regs[SRC_SCR] = deposit32(s->regs[SRC_SCR], ri->reset_bit, 1, 0); 137 DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", 138 imx6_src_reg_name(SRC_SCR), s->regs[SRC_SCR]); 139 140 g_free(ri); 141} 142 143static void imx6_defer_clear_reset_bit(int cpuid, 144 IMX6SRCState *s, 145 unsigned long reset_shift) 146{ 147 struct SRCSCRResetInfo *ri; 148 CPUState *cpu = arm_get_cpu_by_id(cpuid); 149 150 if (!cpu) { 151 return; 152 } 153 154 ri = g_malloc(sizeof(struct SRCSCRResetInfo)); 155 ri->s = s; 156 ri->reset_bit = reset_shift; 157 158 async_run_on_cpu(cpu, imx6_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri)); 159} 160 161 162static void imx6_src_write(void *opaque, hwaddr offset, uint64_t value, 163 unsigned size) 164{ 165 IMX6SRCState *s = (IMX6SRCState *)opaque; 166 uint32_t index = offset >> 2; 167 unsigned long change_mask; 168 unsigned long current_value = value; 169 170 if (index >= SRC_MAX) { 171 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" 172 HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset); 173 return; 174 } 175 176 DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_src_reg_name(index), 177 (uint32_t)current_value); 178 179 change_mask = s->regs[index] ^ (uint32_t)current_value; 180 181 switch (index) { 182 case SRC_SCR: 183 /* 184 * On real hardware when the system reset controller starts a 185 * secondary CPU it runs through some boot ROM code which reads 186 * the SRC_GPRX registers controlling the start address and branches 187 * to it. 188 * Here we are taking a short cut and branching directly to the 189 * requested address (we don't want to run the boot ROM code inside 190 * QEMU) 191 */ 192 if (EXTRACT(change_mask, CORE3_ENABLE)) { 193 if (EXTRACT(current_value, CORE3_ENABLE)) { 194 /* CORE 3 is brought up */ 195 arm_set_cpu_on(3, s->regs[SRC_GPR7], s->regs[SRC_GPR8], 196 3, false); 197 } else { 198 /* CORE 3 is shut down */ 199 arm_set_cpu_off(3); 200 } 201 /* We clear the reset bits as the processor changed state */ 202 imx6_defer_clear_reset_bit(3, s, CORE3_RST_SHIFT); 203 clear_bit(CORE3_RST_SHIFT, &change_mask); 204 } 205 if (EXTRACT(change_mask, CORE2_ENABLE)) { 206 if (EXTRACT(current_value, CORE2_ENABLE)) { 207 /* CORE 2 is brought up */ 208 arm_set_cpu_on(2, s->regs[SRC_GPR5], s->regs[SRC_GPR6], 209 3, false); 210 } else { 211 /* CORE 2 is shut down */ 212 arm_set_cpu_off(2); 213 } 214 /* We clear the reset bits as the processor changed state */ 215 imx6_defer_clear_reset_bit(2, s, CORE2_RST_SHIFT); 216 clear_bit(CORE2_RST_SHIFT, &change_mask); 217 } 218 if (EXTRACT(change_mask, CORE1_ENABLE)) { 219 if (EXTRACT(current_value, CORE1_ENABLE)) { 220 /* CORE 1 is brought up */ 221 arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4], 222 3, false); 223 } else { 224 /* CORE 1 is shut down */ 225 arm_set_cpu_off(1); 226 } 227 /* We clear the reset bits as the processor changed state */ 228 imx6_defer_clear_reset_bit(1, s, CORE1_RST_SHIFT); 229 clear_bit(CORE1_RST_SHIFT, &change_mask); 230 } 231 if (EXTRACT(change_mask, CORE0_RST)) { 232 arm_reset_cpu(0); 233 imx6_defer_clear_reset_bit(0, s, CORE0_RST_SHIFT); 234 } 235 if (EXTRACT(change_mask, CORE1_RST)) { 236 arm_reset_cpu(1); 237 imx6_defer_clear_reset_bit(1, s, CORE1_RST_SHIFT); 238 } 239 if (EXTRACT(change_mask, CORE2_RST)) { 240 arm_reset_cpu(2); 241 imx6_defer_clear_reset_bit(2, s, CORE2_RST_SHIFT); 242 } 243 if (EXTRACT(change_mask, CORE3_RST)) { 244 arm_reset_cpu(3); 245 imx6_defer_clear_reset_bit(3, s, CORE3_RST_SHIFT); 246 } 247 if (EXTRACT(change_mask, SW_IPU2_RST)) { 248 /* We pretend the IPU2 is reset */ 249 clear_bit(SW_IPU2_RST_SHIFT, ¤t_value); 250 } 251 if (EXTRACT(change_mask, SW_IPU1_RST)) { 252 /* We pretend the IPU1 is reset */ 253 clear_bit(SW_IPU1_RST_SHIFT, ¤t_value); 254 } 255 s->regs[index] = current_value; 256 break; 257 default: 258 s->regs[index] = current_value; 259 break; 260 } 261} 262 263static const struct MemoryRegionOps imx6_src_ops = { 264 .read = imx6_src_read, 265 .write = imx6_src_write, 266 .endianness = DEVICE_NATIVE_ENDIAN, 267 .valid = { 268 /* 269 * Our device would not work correctly if the guest was doing 270 * unaligned access. This might not be a limitation on the real 271 * device but in practice there is no reason for a guest to access 272 * this device unaligned. 273 */ 274 .min_access_size = 4, 275 .max_access_size = 4, 276 .unaligned = false, 277 }, 278}; 279 280static void imx6_src_realize(DeviceState *dev, Error **errp) 281{ 282 IMX6SRCState *s = IMX6_SRC(dev); 283 284 memory_region_init_io(&s->iomem, OBJECT(dev), &imx6_src_ops, s, 285 TYPE_IMX6_SRC, 0x1000); 286 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); 287} 288 289static void imx6_src_class_init(ObjectClass *klass, void *data) 290{ 291 DeviceClass *dc = DEVICE_CLASS(klass); 292 293 dc->realize = imx6_src_realize; 294 dc->reset = imx6_src_reset; 295 dc->vmsd = &vmstate_imx6_src; 296 dc->desc = "i.MX6 System Reset Controller"; 297} 298 299static const TypeInfo imx6_src_info = { 300 .name = TYPE_IMX6_SRC, 301 .parent = TYPE_SYS_BUS_DEVICE, 302 .instance_size = sizeof(IMX6SRCState), 303 .class_init = imx6_src_class_init, 304}; 305 306static void imx6_src_register_types(void) 307{ 308 type_register_static(&imx6_src_info); 309} 310 311type_init(imx6_src_register_types)