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