2 * mini2440 development board support
4 * Copyright Michel Pollet <buserror@gmail.com>
6 * This code is licensed under the GNU GPL v2.
14 #include "qemu-timer.h"
16 #include "audio/audio.h"
23 #include "eeprom24c0x.h"
25 #define mini2440_printf(format, ...) \
26 fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
28 /* Wiring common to all revisions */
29 #define MINI2440_GPIO_BACKLIGHT S3C_GPB(1)
30 #define MINI2440_GPIO_LCD_RESET S3C_GPC(6)
31 #define MINI2440_GPIO_nSD_DETECT S3C_GPG(8)
32 #define MINI2440_IRQ_nSD_DETECT S3C_EINT(16)
33 #define MINI2440_IRQ_DM9000 S3C_EINT(7)
34 #define MINI2440_GPIO_DM9000 S3C_GPF(7)
36 #define MINI2440_GPIO_SDMMC_ON S3C_GPB(2)
37 #define MINI2440_GPIO_USB_PULLUP S3C_GPB(9)
38 #define MINI2440_GPIO_USB_ATTACH S3C_GPB(10)
40 struct mini2440_board_s
{
41 struct s3c_state_s
*cpu
;
46 struct nand_flash_s
*nand
;
51 /* Handlers for output ports */
52 static void mini2440_bl_switch(void *opaque
, int line
, int level
)
54 printf("%s: LCD Backlight now %s.\n", __FUNCTION__
, level
? "on" : "off");
57 static void mini2440_bl_intensity(int line
, int level
, void *opaque
)
59 struct mini2440_board_s
*s
= (struct mini2440_board_s
*) opaque
;
61 if ((level
>> 8) != s
->bl_level
) {
62 s
->bl_level
= level
>> 8;
63 // printf("%s: LCD Backlight now at %i/64.\n", __FUNCTION__, s->bl_level);
67 static void mini2440_gpio_setup(struct mini2440_board_s
*s
)
69 s3c_gpio_out_set(s
->cpu
->io
, MINI2440_GPIO_BACKLIGHT
,
70 *qemu_allocate_irqs(mini2440_bl_switch
, s
, 1));
72 s3c_timers_cmp_handler_set(s
->cpu
->timers
, 1, mini2440_bl_intensity
, s
);
74 // this confuses the kernel, we will need a way to bridge this IRQ to the SD system
75 // right now without this, qemu will not know how to pass the SD card insert/remove
76 // properly to the kernel
77 // sd_set_cb(s->mmc, 0, s3c_gpio_in_get(s->cpu->io)[MINI2440_IRQ_nSD_DETECT]);
81 static void hexdump(const void* address
, uint32_t len
)
83 const unsigned char* p
= address
;
86 for (i
= 0; i
< len
; i
+= 16) {
87 for (j
= 0; j
< 16 && i
+ j
< len
; j
++)
88 fprintf(stderr
, "%02x ", p
[i
+ j
]);
92 for (j
= 0; j
< 16 && i
+ j
< len
; j
++)
93 fprintf(stderr
, "%c", (p
[i
+ j
] < ' ' || p
[i
+ j
] > 0x7f) ? '.' : p
[i
+ j
]);
94 fprintf(stderr
, "\n");
99 static void mini2440_reset(void *opaque
)
101 struct mini2440_board_s
*s
= (struct mini2440_board_s
*) opaque
;
105 image_size
= load_image("mini2440/u-boot.bin", phys_ram_base
+ 0x03f80000);
107 image_size
= load_image("u-boot.bin", phys_ram_base
+ 0x03f80000);
109 if (image_size
& (512 -1)) /* round size to a NAND block size */
110 image_size
= (image_size
+ 512) & ~(512-1);
111 fprintf(stderr
, "%s: loaded default u-boot (size %x)\n", __FUNCTION__
, image_size
);
112 s
->cpu
->env
->regs
[15] = S3C_RAM_BASE
| 0x03f80000; // start address, u-boot already relocated
117 * Performs Samsung S3C2440 bootup, but loading 4KB of the nand at the base of the RAM
123 uint8_t stone
[S3C_SRAM_SIZE
];
124 uint8_t * dst
= stone
;
126 fprintf(stderr
, "%s: attempting boot from NAND\n", __FUNCTION__
);
128 for (page
= 0; page
< (S3C_SRAM_SIZE
/ 512); page
++, src
+= 512+16, dst
+= 512)
129 if (nand_readraw(s
->nand
, src
, dst
, 512) == 0) {
130 fprintf(stderr
, "%s: failed to load nand %d:%d\n", __FUNCTION__
, src
, 512+16);
132 cpu_physical_memory_write(S3C_SRAM_BASE_NANDBOOT
, stone
, S3C_SRAM_SIZE
);
133 s
->cpu
->env
->regs
[15] = S3C_SRAM_BASE_NANDBOOT
; // start address, u-boot relocating code
134 fprintf(stderr
, "%s: 4KB SteppingStone loaded from NAND\n", __FUNCTION__
);
138 image_size
= load_image(s
->kernel
, phys_ram_base
+ 0x02000000);
140 if (image_size
& (512 -1)) /* round size to a NAND block size */
141 image_size
= (image_size
+ 512) & ~(512-1);
142 fprintf(stderr
, "%s: loaded %s (size %x)\n", __FUNCTION__
, s
->kernel
, image_size
);
146 image_size
= load_image("/tftpboot/minimalist-image-mini2440.jffs2", phys_ram_base
);
148 if (image_size
& (512 -1)) /* round size to a NAND block size */
149 image_size
= (image_size
+ 512) & ~(512-1);
150 fprintf(stderr
, "%s: loaded jffs2 (size %x)\n", __FUNCTION__
, image_size
);
156 /* Typical touchscreen calibration values */
157 static const int mini2440_ts_scale
[6] = {
158 0, (90 - 960) * 256 / 1021, -90 * 256 * 32,
159 (940 - 75) * 256 / 1021, 0, 75 * 256 * 32,
163 static struct mini2440_board_s
*mini2440_init_common(int ram_size
,
164 const char *kernel_filename
, const char *cpu_model
,
167 struct mini2440_board_s
*s
= (struct mini2440_board_s
*)
168 qemu_mallocz(sizeof(struct mini2440_board_s
));
171 s
->kernel
= kernel_filename
;
174 /* Setup CPU & memory */
175 if (ram_size
< s
->ram
+ S3C_SRAM_SIZE
) {
176 fprintf(stderr
, "This platform requires %i bytes of memory (not %d)\n",
177 s
->ram
+ S3C_SRAM_SIZE
, ram_size
);
180 if (cpu_model
&& strcmp(cpu_model
, "arm920t")) {
181 fprintf(stderr
, "This platform requires an ARM920T core\n");
184 s
->cpu
= s3c24xx_init(S3C_CPU_2440
, s
->ram
, S3C_SRAM_BASE_NANDBOOT
, s
->mmc
);
186 /* Setup peripherals */
187 mini2440_gpio_setup(s
);
189 // s->eeprom = eeprom24c0x_new(EE_24C08);
192 // usb_device_attach(usb_bt_init(local_piconet));
198 nd
->model
= "dm9000";
199 if (strcmp(nd
->model
, "dm9000") == 0) {
200 dm9000_init(nd
, 0x20000000, 0x300, 0x304, s3c_gpio_in_get(s
->cpu
->io
)[MINI2440_IRQ_DM9000
]);
204 s3c_adc_setscale(s
->cpu
->adc
, mini2440_ts_scale
);
206 /* Setup initial (reset) machine state */
207 qemu_register_reset(mini2440_reset
, s
);
209 arm_load_kernel(s
->ram
, kernel_filename
, kernel_cmdline
,
210 initrd_filename
, 0x49e, S3C_RAM_BASE
);
216 static void mini2440_init(ram_addr_t ram_size
, int vga_ram_size
,
217 const char *boot_device
,
218 const char *kernel_filename
, const char *kernel_cmdline
,
219 const char *initrd_filename
, const char *cpu_model
)
221 struct mini2440_board_s
*mini
;
222 int sd_idx
= drive_get_index(IF_SD
, 0, 0);
226 sd
= sd_init(drives_table
[sd_idx
].bdrv
, 0);
228 mini
= mini2440_init_common(ram_size
,
229 kernel_filename
, cpu_model
, sd
);
231 mini
->nand
= nand_init(NAND_MFR_SAMSUNG
, 0x36);
232 mini
->cpu
->nand
->reg(mini
->cpu
->nand
, mini
->nand
);
234 mini2440_reset(mini
);
237 QEMUMachine mini2440_machine
= {
239 "MINI2440 Chinese Samsung SoC dev board (S3C2440A)",
240 .init
= mini2440_init
,
241 .ram_require
= (0x04000000 + S3C_SRAM_SIZE
) | RAMSIZE_FIXED