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