xref: /qemu/hw/arm/fsl-imx25.c (revision a81df1b6)
1 /*
2  * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
3  *
4  * i.MX25 SOC emulation.
5  *
6  * Based on hw/arm/xlnx-zynqmp.c
7  *
8  * Copyright (C) 2015 Xilinx Inc
9  * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
10  *
11  *  This program is free software; you can redistribute it and/or modify it
12  *  under the terms of the GNU General Public License as published by the
13  *  Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful, but WITHOUT
17  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  *  for more details.
20  *
21  *  You should have received a copy of the GNU General Public License along
22  *  with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qapi/error.h"
27 #include "cpu.h"
28 #include "hw/arm/fsl-imx25.h"
29 #include "sysemu/sysemu.h"
30 #include "exec/address-spaces.h"
31 #include "hw/qdev-properties.h"
32 #include "chardev/char.h"
33 
34 #define IMX25_ESDHC_CAPABILITIES     0x07e20000
35 
36 static void fsl_imx25_init(Object *obj)
37 {
38     FslIMX25State *s = FSL_IMX25(obj);
39     int i;
40 
41     object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("arm926"));
42 
43     object_initialize_child(obj, "avic", &s->avic, TYPE_IMX_AVIC);
44 
45     object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX25_CCM);
46 
47     for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
48         object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_IMX_SERIAL);
49     }
50 
51     for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
52         object_initialize_child(obj, "gpt[*]", &s->gpt[i], TYPE_IMX25_GPT);
53     }
54 
55     for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
56         object_initialize_child(obj, "epit[*]", &s->epit[i], TYPE_IMX_EPIT);
57     }
58 
59     object_initialize_child(obj, "fec", &s->fec, TYPE_IMX_FEC);
60 
61     object_initialize_child(obj, "rngc", &s->rngc, TYPE_IMX_RNGC);
62 
63     for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
64         object_initialize_child(obj, "i2c[*]", &s->i2c[i], TYPE_IMX_I2C);
65     }
66 
67     for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
68         object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_IMX_GPIO);
69     }
70 
71     for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
72         object_initialize_child(obj, "sdhc[*]", &s->esdhc[i], TYPE_IMX_USDHC);
73     }
74 
75     for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
76         object_initialize_child(obj, "usb[*]", &s->usb[i], TYPE_CHIPIDEA);
77     }
78 
79     object_initialize_child(obj, "wdt", &s->wdt, TYPE_IMX2_WDT);
80 }
81 
82 static void fsl_imx25_realize(DeviceState *dev, Error **errp)
83 {
84     FslIMX25State *s = FSL_IMX25(dev);
85     uint8_t i;
86     Error *err = NULL;
87 
88     if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) {
89         return;
90     }
91 
92     if (!sysbus_realize(SYS_BUS_DEVICE(&s->avic), errp)) {
93         return;
94     }
95     sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR);
96     sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
97                        qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
98     sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
99                        qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
100 
101     if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
102         return;
103     }
104     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR);
105 
106     /* Initialize all UARTs */
107     for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
108         static const struct {
109             hwaddr addr;
110             unsigned int irq;
111         } serial_table[FSL_IMX25_NUM_UARTS] = {
112             { FSL_IMX25_UART1_ADDR, FSL_IMX25_UART1_IRQ },
113             { FSL_IMX25_UART2_ADDR, FSL_IMX25_UART2_IRQ },
114             { FSL_IMX25_UART3_ADDR, FSL_IMX25_UART3_IRQ },
115             { FSL_IMX25_UART4_ADDR, FSL_IMX25_UART4_IRQ },
116             { FSL_IMX25_UART5_ADDR, FSL_IMX25_UART5_IRQ }
117         };
118 
119         qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
120 
121         if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
122             return;
123         }
124         sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
125         sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
126                            qdev_get_gpio_in(DEVICE(&s->avic),
127                                             serial_table[i].irq));
128     }
129 
130     /* Initialize all GPT timers */
131     for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
132         static const struct {
133             hwaddr addr;
134             unsigned int irq;
135         } gpt_table[FSL_IMX25_NUM_GPTS] = {
136             { FSL_IMX25_GPT1_ADDR, FSL_IMX25_GPT1_IRQ },
137             { FSL_IMX25_GPT2_ADDR, FSL_IMX25_GPT2_IRQ },
138             { FSL_IMX25_GPT3_ADDR, FSL_IMX25_GPT3_IRQ },
139             { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
140         };
141 
142         s->gpt[i].ccm = IMX_CCM(&s->ccm);
143 
144         if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
145             return;
146         }
147         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
148         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
149                            qdev_get_gpio_in(DEVICE(&s->avic),
150                                             gpt_table[i].irq));
151     }
152 
153     /* Initialize all EPIT timers */
154     for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
155         static const struct {
156             hwaddr addr;
157             unsigned int irq;
158         } epit_table[FSL_IMX25_NUM_EPITS] = {
159             { FSL_IMX25_EPIT1_ADDR, FSL_IMX25_EPIT1_IRQ },
160             { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
161         };
162 
163         s->epit[i].ccm = IMX_CCM(&s->ccm);
164 
165         if (!sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), errp)) {
166             return;
167         }
168         sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
169         sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
170                            qdev_get_gpio_in(DEVICE(&s->avic),
171                                             epit_table[i].irq));
172     }
173 
174     object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err);
175     qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
176 
177     if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) {
178         return;
179     }
180     sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR);
181     sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
182                        qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ));
183 
184     if (!sysbus_realize(SYS_BUS_DEVICE(&s->rngc), errp)) {
185         return;
186     }
187     sysbus_mmio_map(SYS_BUS_DEVICE(&s->rngc), 0, FSL_IMX25_RNGC_ADDR);
188     sysbus_connect_irq(SYS_BUS_DEVICE(&s->rngc), 0,
189                        qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_RNGC_IRQ));
190 
191     /* Initialize all I2C */
192     for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
193         static const struct {
194             hwaddr addr;
195             unsigned int irq;
196         } i2c_table[FSL_IMX25_NUM_I2CS] = {
197             { FSL_IMX25_I2C1_ADDR, FSL_IMX25_I2C1_IRQ },
198             { FSL_IMX25_I2C2_ADDR, FSL_IMX25_I2C2_IRQ },
199             { FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ }
200         };
201 
202         if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
203             return;
204         }
205         sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
206         sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
207                            qdev_get_gpio_in(DEVICE(&s->avic),
208                                             i2c_table[i].irq));
209     }
210 
211     /* Initialize all GPIOs */
212     for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
213         static const struct {
214             hwaddr addr;
215             unsigned int irq;
216         } gpio_table[FSL_IMX25_NUM_GPIOS] = {
217             { FSL_IMX25_GPIO1_ADDR, FSL_IMX25_GPIO1_IRQ },
218             { FSL_IMX25_GPIO2_ADDR, FSL_IMX25_GPIO2_IRQ },
219             { FSL_IMX25_GPIO3_ADDR, FSL_IMX25_GPIO3_IRQ },
220             { FSL_IMX25_GPIO4_ADDR, FSL_IMX25_GPIO4_IRQ }
221         };
222 
223         if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
224             return;
225         }
226         sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
227         /* Connect GPIO IRQ to PIC */
228         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
229                            qdev_get_gpio_in(DEVICE(&s->avic),
230                                             gpio_table[i].irq));
231     }
232 
233     /* Initialize all SDHC */
234     for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
235         static const struct {
236             hwaddr addr;
237             unsigned int irq;
238         } esdhc_table[FSL_IMX25_NUM_ESDHCS] = {
239             { FSL_IMX25_ESDHC1_ADDR, FSL_IMX25_ESDHC1_IRQ },
240             { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ },
241         };
242 
243         object_property_set_uint(OBJECT(&s->esdhc[i]), "sd-spec-version", 2,
244                                  &error_abort);
245         object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
246                                  IMX25_ESDHC_CAPABILITIES, &error_abort);
247         object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
248                                  SDHCI_VENDOR_IMX, &error_abort);
249         if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
250             return;
251         }
252         sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
253         sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
254                            qdev_get_gpio_in(DEVICE(&s->avic),
255                                             esdhc_table[i].irq));
256     }
257 
258     /* USB */
259     for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
260         static const struct {
261             hwaddr addr;
262             unsigned int irq;
263         } usb_table[FSL_IMX25_NUM_USBS] = {
264             { FSL_IMX25_USB1_ADDR, FSL_IMX25_USB1_IRQ },
265             { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ },
266         };
267 
268         sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort);
269         sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
270         sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
271                            qdev_get_gpio_in(DEVICE(&s->avic),
272                                             usb_table[i].irq));
273     }
274 
275     /* Watchdog */
276     object_property_set_bool(OBJECT(&s->wdt), "pretimeout-support", true,
277                              &error_abort);
278     sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_abort);
279     sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR);
280     sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0,
281                                       qdev_get_gpio_in(DEVICE(&s->avic),
282                                                        FSL_IMX25_WDT_IRQ));
283 
284     /* initialize 2 x 16 KB ROM */
285     memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0",
286                            FSL_IMX25_ROM0_SIZE, &err);
287     if (err) {
288         error_propagate(errp, err);
289         return;
290     }
291     memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
292                                 &s->rom[0]);
293     memory_region_init_rom(&s->rom[1], OBJECT(dev), "imx25.rom1",
294                            FSL_IMX25_ROM1_SIZE, &err);
295     if (err) {
296         error_propagate(errp, err);
297         return;
298     }
299     memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM1_ADDR,
300                                 &s->rom[1]);
301 
302     /* initialize internal RAM (128 KB) */
303     memory_region_init_ram(&s->iram, NULL, "imx25.iram", FSL_IMX25_IRAM_SIZE,
304                            &err);
305     if (err) {
306         error_propagate(errp, err);
307         return;
308     }
309     memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ADDR,
310                                 &s->iram);
311 
312     /* internal RAM (128 KB) is aliased over 128 MB - 128 KB */
313     memory_region_init_alias(&s->iram_alias, OBJECT(dev), "imx25.iram_alias",
314                              &s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE);
315     memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR,
316                                 &s->iram_alias);
317 }
318 
319 static Property fsl_imx25_properties[] = {
320     DEFINE_PROP_UINT32("fec-phy-num", FslIMX25State, phy_num, 0),
321     DEFINE_PROP_END_OF_LIST(),
322 };
323 
324 static void fsl_imx25_class_init(ObjectClass *oc, void *data)
325 {
326     DeviceClass *dc = DEVICE_CLASS(oc);
327 
328     device_class_set_props(dc, fsl_imx25_properties);
329     dc->realize = fsl_imx25_realize;
330     dc->desc = "i.MX25 SOC";
331     /*
332      * Reason: uses serial_hds in realize and the imx25 board does not
333      * support multiple CPUs
334      */
335     dc->user_creatable = false;
336 }
337 
338 static const TypeInfo fsl_imx25_type_info = {
339     .name = TYPE_FSL_IMX25,
340     .parent = TYPE_DEVICE,
341     .instance_size = sizeof(FslIMX25State),
342     .instance_init = fsl_imx25_init,
343     .class_init = fsl_imx25_class_init,
344 };
345 
346 static void fsl_imx25_register_types(void)
347 {
348     type_register_static(&fsl_imx25_type_info);
349 }
350 
351 type_init(fsl_imx25_register_types)
352