Fix some compiler warnings related to format strings
[qemu/ar7.git] / hw / arm / s3c2440.c
blob2d43aa56815004da1dd3efa0bcbbb6dc163f2054
1 /* hw/s3c2440.c
3 * Samsung S3C2440 emulation
5 * Copyright 2009 Daniel Silverstone and Vincent Sanders
7 * Copyright 2010, 2013 Stefan Weil
9 * This file is under the terms of the GNU General Public License Version 2.
12 #include "qemu/osdep.h"
13 #include "cpu.h"
14 #include "hw/sysbus.h"
15 #include "qapi/error.h" /* error_abort */
16 #include "sysemu/sysemu.h"
17 #include "exec/address-spaces.h" /* get_system_memory */
19 #include "s3c2440.h"
21 #define logout(fmt, ...) \
22 fprintf(stderr, "S3C24xx\t%-24s" fmt, __func__, ##__VA_ARGS__)
24 #define TODO() logout("%s:%u: missing\n", __FILE__, __LINE__)
26 /* S3C2440 SoC ID */
27 #define CPU_S3C2440_IDENT_S3C2440A 0x32440001
29 /* Integrated peripherals */
31 /* SRAM */
32 #define CPU_S3C2440_SRAM_BASE (CPU_S3C2440_PERIPHERAL + 0x00000000)
33 #define CPU_S3C2440_SRAM_SIZE 4096
35 /* Memory control */
36 #define CPU_S3C2440_MEMC_BASE (CPU_S3C2440_PERIPHERAL + 0x8000000)
38 /* USB controller */
39 #define CPU_S3C2440_OHCI_BASE (CPU_S3C2440_PERIPHERAL + 0x9000000)
41 /* Interrupt controller */
42 #define CPU_S3C2440_IRQ_BASE (CPU_S3C2440_PERIPHERAL + 0xA000000)
44 /* Clock control */
45 #define CPU_S3C2440_CLKCON_BASE (CPU_S3C2440_PERIPHERAL + 0x0c000000)
47 /* LCD controller */
48 #define CPU_S3C2440_LCD_BASE (CPU_S3C2440_PERIPHERAL + 0xD000000)
50 /* NAND */
51 #define CPU_S3C2440_NAND_BASE (CPU_S3C2440_PERIPHERAL + 0xE000000)
53 /* serial port bases */
54 #define CPU_S3C2440_SERIAL0_BASE (CPU_S3C2440_PERIPHERAL + 0x10000000)
55 #define CPU_S3C2440_SERIAL1_BASE (CPU_S3C2440_PERIPHERAL + 0x10004000)
56 #define CPU_S3C2440_SERIAL2_BASE (CPU_S3C2440_PERIPHERAL + 0x10008000)
58 /* Timer controller */
59 #define CPU_S3C2440_TIMERS_BASE (CPU_S3C2440_PERIPHERAL + 0x11000000)
61 /* IIC */
62 #define CPU_S3C2440_IIC_BASE (CPU_S3C2440_PERIPHERAL + 0x14000000)
64 /* GPIO */
65 #define CPU_S3C2440_GPIO_BASE (CPU_S3C2440_PERIPHERAL + 0x16000000)
67 /* Real time clock */
68 #define CPU_S3C2440_RTC_BASE (CPU_S3C2440_PERIPHERAL + 0x17000000)
69 #define CPU_S3C2440_ADC_BASE (CPU_S3C2440_PERIPHERAL + 0x18000000)
71 /*----------------------------------------------------------------------------*/
73 /* Camera interface. */
75 #define TYPE_S3C24XX_CAM "s3c24xx_cam"
76 #define S3C24XX_CAM(obj) OBJECT_CHECK(S3C24xxCamState, (obj), TYPE_S3C24XX_CAM)
78 typedef struct {
79 SysBusDevice busdev;
80 MemoryRegion mmio;
81 } S3C24xxCamState;
83 static uint64_t s3c24xx_cam_read(void *opaque, hwaddr offset,
84 unsigned size)
86 //~ S3C24xxCamState *s = opaque;
87 logout("0x" TARGET_FMT_plx "\n", offset);
89 switch (offset) {
90 default:
91 return 0;
95 static void s3c24xx_cam_write(void *opaque, hwaddr offset,
96 uint64_t value, unsigned size)
98 //~ S3C24xxCamState *s = opaque;
100 logout("0x" TARGET_FMT_plx " 0x%08" PRIx64 "\n", offset, value);
102 switch (offset) {
106 static void s3c24xx_cam_reset(DeviceState *d)
108 //~ S3C24xxCamState *s = S3C24XX_CAM(d);
111 static const MemoryRegionOps s3c24xx_cam_ops = {
112 .read = s3c24xx_cam_read,
113 .write = s3c24xx_cam_write,
114 .endianness = DEVICE_NATIVE_ENDIAN,
115 .valid = {
116 .min_access_size = 4,
117 .max_access_size = 4
121 static int s3c24xx_cam_init(SysBusDevice *sbd)
123 DeviceState *dev = DEVICE(sbd);
124 S3C24xxCamState *s = S3C24XX_CAM(dev);
126 logout("\n");
127 memory_region_init_io(&s->mmio, OBJECT(s), &s3c24xx_cam_ops, s, "s3c24xx-cam", 3 * 4);
128 sysbus_init_mmio(sbd, &s->mmio);
130 //~ qdev_init_gpio_in(dev, mv88w8618_pic_set_irq, 32);
131 //~ sysbus_init_irq(sbd, &s->parent_irq);
132 return 0;
135 static const VMStateDescription s3c24xx_cam_vmsd = {
136 .name = TYPE_S3C24XX_CAM,
137 .version_id = 1,
138 .minimum_version_id = 1,
139 .minimum_version_id_old = 1,
140 .fields = (VMStateField[]) {
141 VMSTATE_END_OF_LIST()
145 static void s3c24xx_cam_class_init(ObjectClass *klass, void *data)
147 DeviceClass *dc = DEVICE_CLASS(klass);
148 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
149 dc->reset = s3c24xx_cam_reset;
150 dc->vmsd = &s3c24xx_cam_vmsd;
151 k->init = s3c24xx_cam_init;
154 static const TypeInfo s3c24xx_cam_info = {
155 .name = TYPE_S3C24XX_CAM,
156 .parent = TYPE_SYS_BUS_DEVICE,
157 .instance_size = sizeof(S3C24xxCamState),
158 .class_init = s3c24xx_cam_class_init
161 static void s3c24xx_cam_register_types(void)
163 type_register_static(&s3c24xx_cam_info);
166 type_init(s3c24xx_cam_register_types)
168 /*----------------------------------------------------------------------------*/
170 /* Watchdog timer. */
172 #define TYPE_S3C24XX_WDG "s3c24xx_wdg"
173 #define S3C24XX_WDG(obj) OBJECT_CHECK(S3C24xxWdgState, (obj), TYPE_S3C24XX_WDG)
175 typedef struct {
176 SysBusDevice busdev;
177 MemoryRegion mmio;
178 } S3C24xxWdgState;
180 static uint64_t s3c24xx_wdg_read(void *opaque, hwaddr offset,
181 unsigned size)
183 //~ S3C24xxWdgState *s = opaque;
184 logout("0x" TARGET_FMT_plx "\n", offset);
186 switch (offset) {
187 default:
188 return 0;
192 static void s3c24xx_wdg_write(void *opaque, hwaddr offset,
193 uint64_t value, unsigned size)
195 //~ S3C24xxWdgState *s = opaque;
197 logout("0x" TARGET_FMT_plx " 0x%08" PRIx64 "\n", offset, value);
199 switch (offset) {
203 static void s3c24xx_wdg_reset(DeviceState *d)
205 //~ S3C24xxWdgState *s = S3C24XX_WDG(d);
208 static const MemoryRegionOps s3c24xx_wdg_ops = {
209 .read = s3c24xx_wdg_read,
210 .write = s3c24xx_wdg_write,
211 .endianness = DEVICE_NATIVE_ENDIAN,
212 .valid = {
213 .min_access_size = 4,
214 .max_access_size = 4
218 static int s3c24xx_wdg_init(SysBusDevice *sbd)
220 DeviceState *dev = DEVICE(sbd);
221 S3C24xxWdgState *s = S3C24XX_WDG(dev);
223 logout("\n");
224 memory_region_init_io(&s->mmio, OBJECT(s),
225 &s3c24xx_wdg_ops, s, "s3c24xx-wdg", 3 * 4);
226 sysbus_init_mmio(sbd, &s->mmio);
228 //~ qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
229 //~ sysbus_init_irq(dev, &s->parent_irq);
230 return 0;
233 static const VMStateDescription s3c24xx_wdg_vmsd = {
234 .name = TYPE_S3C24XX_WDG,
235 .version_id = 1,
236 .minimum_version_id = 1,
237 .minimum_version_id_old = 1,
238 .fields = (VMStateField[]) {
239 VMSTATE_END_OF_LIST()
243 static void s3c24xx_wdg_class_init(ObjectClass *klass, void *data)
245 DeviceClass *dc = DEVICE_CLASS(klass);
246 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
247 dc->reset = s3c24xx_wdg_reset;
248 dc->vmsd = &s3c24xx_wdg_vmsd;
249 k->init = s3c24xx_wdg_init;
252 static const TypeInfo s3c24xx_wdg_info = {
253 .name = TYPE_S3C24XX_WDG,
254 .parent = TYPE_SYS_BUS_DEVICE,
255 .instance_size = sizeof(S3C24xxWdgState),
256 .class_init = s3c24xx_wdg_class_init
259 static void s3c24xx_wdg_register_types(void)
261 type_register_static(&s3c24xx_wdg_info);
264 type_init(s3c24xx_wdg_register_types)
266 /*----------------------------------------------------------------------------*/
268 /* ADC. */
270 #define TYPE_S3C24XX_ADC "s3c24xx_adc"
271 #define S3C24XX_ADC(obj) OBJECT_CHECK(S3C24xxAdcState, (obj), TYPE_S3C24XX_ADC)
273 typedef struct {
274 SysBusDevice busdev;
275 MemoryRegion mmio;
276 } S3C24xxAdcState;
278 static uint64_t s3c24xx_adc_read(void *opaque, hwaddr offset,
279 unsigned size)
281 //~ S3C24xxAdcState *s = opaque;
282 logout("0x" TARGET_FMT_plx "\n", offset);
284 switch (offset) {
285 //~ case MP_PIC_STATUS:
286 //~ return s->level & s->enabled;
288 default:
289 return 0;
293 static void s3c24xx_adc_write(void *opaque, hwaddr offset,
294 uint64_t value, unsigned size)
296 //~ S3C24xxAdcState *s = opaque;
298 logout("0x" TARGET_FMT_plx " 0x%08" PRIx64 "\n", offset, value);
300 switch (offset) {
301 //~ case MP_PIC_ENABLE_SET:
302 //~ s->enabled |= value;
303 //~ break;
305 //~ case MP_PIC_ENABLE_CLR:
306 //~ s->enabled &= ~value;
307 //~ s->level &= ~value;
308 //~ break;
310 //~ mv88w8618_pic_update(s);
313 static void s3c24xx_adc_reset(DeviceState *d)
315 //~ S3C24xxAdcState *s = S3C24XX_ADC(d);
318 static const MemoryRegionOps s3c24xx_adc_ops = {
319 .read = s3c24xx_adc_read,
320 .write = s3c24xx_adc_write,
321 .endianness = DEVICE_NATIVE_ENDIAN,
322 .valid = {
323 .min_access_size = 4,
324 .max_access_size = 4
328 static int s3c24xx_adc_init(SysBusDevice *sbd)
330 DeviceState *dev = DEVICE(sbd);
331 S3C24xxAdcState *s = S3C24XX_ADC(dev);
333 logout("\n");
334 memory_region_init_io(&s->mmio, OBJECT(s),
335 &s3c24xx_adc_ops, s, "s3c24xx-adc", 7 * 4);
336 sysbus_init_mmio(sbd, &s->mmio);
338 //~ qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
339 //~ sysbus_init_irq(dev, &s->parent_irq);
340 return 0;
343 static const VMStateDescription s3c24xx_adc_vmsd = {
344 .name = TYPE_S3C24XX_ADC,
345 .version_id = 1,
346 .minimum_version_id = 1,
347 .minimum_version_id_old = 1,
348 .fields = (VMStateField[]) {
349 VMSTATE_END_OF_LIST()
353 static void s3c24xx_adc_class_init(ObjectClass *klass, void *data)
355 DeviceClass *dc = DEVICE_CLASS(klass);
356 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
357 dc->reset = s3c24xx_adc_reset;
358 dc->vmsd = &s3c24xx_adc_vmsd;
359 k->init = s3c24xx_adc_init;
362 static const TypeInfo s3c24xx_adc_info = {
363 .name = TYPE_S3C24XX_ADC,
364 .parent = TYPE_SYS_BUS_DEVICE,
365 .instance_size = sizeof(S3C24xxAdcState),
366 .class_init = s3c24xx_adc_class_init
369 static void s3c24xx_adc_register_types(void)
371 type_register_static(&s3c24xx_adc_info);
374 type_init(s3c24xx_adc_register_types)
376 /*----------------------------------------------------------------------------*/
378 /* Initialise a Samsung S3C2440 SOC ARM core and internal peripherals. */
379 S3CState *
380 s3c2440_init(int sdram_size)
382 DeviceState *dev;
383 MemoryRegion *sysmem = get_system_memory();
384 S3CState *s = g_new0(S3CState, 1);
386 /* Prepare the ARM 920T core. */
387 s->cpu = ARM_CPU(cpu_generic_init(TYPE_ARM_CPU, "arm920t"));
389 /* S3C2440X SDRAM memory is always at the same physical location. */
390 memory_region_init_ram(&s->sdram0, OBJECT(s), "s3c2440.sdram0",
391 sdram_size, &error_abort);
392 memory_region_init_alias(&s->sdram1, NULL, "s3c2440.sdram1",
393 &s->sdram0, 0, sdram_size);
394 memory_region_init_alias(&s->sdram2, NULL, "s3c2440.sdram2",
395 &s->sdram0, 0, sdram_size);
396 memory_region_add_subregion(sysmem, CPU_S3C2440_DRAM, &s->sdram0);
397 memory_region_add_subregion(sysmem,
398 CPU_S3C2440_DRAM + 0x80000000, &s->sdram1);
399 memory_region_add_subregion(sysmem,
400 CPU_S3C2440_DRAM + 0x90000000, &s->sdram2);
402 /* S3C2440 SRAM */
403 memory_region_init_ram(&s->sram, OBJECT(s), "s3c2440.sram",
404 CPU_S3C2440_SRAM_SIZE, &error_abort);
405 memory_region_add_subregion(sysmem, CPU_S3C2440_SRAM_BASE, &s->sram);
407 /* SDRAM memory controller */
408 s->memc = s3c24xx_memc_init(CPU_S3C2440_MEMC_BASE);
410 /* Interrupt controller */
411 s->irq = s3c24xx_irq_init(s, CPU_S3C2440_IRQ_BASE);
413 /* Clock and power control */
414 s->clkcon = s3c24xx_clkcon_init(s, CPU_S3C2440_CLKCON_BASE, 12000000);
416 /* Timer controller */
417 s->timers = s3c24xx_timers_init(s, CPU_S3C2440_TIMERS_BASE, 0, 12000000);
419 /* Serial port controllers */
420 s->uart[0] = s3c24xx_serial_init(s, serial_hds[0], CPU_S3C2440_SERIAL0_BASE, 32);
421 s->uart[1] = s3c24xx_serial_init(s, serial_hds[1], CPU_S3C2440_SERIAL1_BASE, 35);
422 s->uart[2] = s3c24xx_serial_init(s, serial_hds[2], CPU_S3C2440_SERIAL2_BASE, 38);
424 /* Real time clock */
425 s->rtc = s3c24xx_rtc_init(CPU_S3C2440_RTC_BASE);
427 /* And some GPIO */
428 //~ dev = sysbus_create_simple("s3c24xx_gpio", CPU_S3C2440_GPIO_BASE, NULL);
429 s->gpio = s3c24xx_gpio_init(s, CPU_S3C2440_GPIO_BASE, CPU_S3C2440_IDENT_S3C2440A);
431 /* I2C */
432 s->iic = s3c24xx_iic_init(s3c24xx_get_irq(s->irq, 27),
433 CPU_S3C2440_IIC_BASE);
435 /* LCD controller */
436 dev = sysbus_create_simple("s3c24xx_lcd", CPU_S3C2440_LCD_BASE,
437 s3c24xx_get_irq(s->irq, 16));
439 /* NAND controller */
440 s->nand = s3c24xx_nand_init(CPU_S3C2440_NAND_BASE);
442 /* A two port OHCI controller */
443 dev = qdev_create(NULL, "sysbus-ohci");
444 qdev_prop_set_uint32(dev, "num-ports", 2);
445 //~ qdev_prop_set_taddr(dev, "dma-offset", base);
446 qdev_init_nofail(dev);
447 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, CPU_S3C2440_OHCI_BASE);
448 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, s3c24xx_get_irq(s->irq, 26));
450 dev = sysbus_create_simple(TYPE_S3C24XX_ADC, CPU_S3C2440_ADC_BASE, NULL);
452 return s;