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, "QEMU %s: " format, __FUNCTION__, ##__VA_ARGS__)
28 #define MINI2440_GPIO_BACKLIGHT S3C_GPG(4)
29 #define MINI2440_GPIO_LCD_RESET S3C_GPC(6)
30 #define MINI2440_GPIO_nSD_DETECT S3C_GPG(8)
31 #define MINI2440_GPIO_WP_SD S3C_GPH(8)
32 #define MINI2440_GPIO_DM9000 S3C_GPF(7)
33 #define MINI2440_GPIO_USB_PULLUP S3C_GPC(5)
35 #define MINI2440_IRQ_nSD_DETECT S3C_EINT(16)
36 #define MINI2440_IRQ_DM9000 S3C_EINT(7)
38 #define FLASH_NOR_SIZE (2*1024*1024)
44 struct mini2440_board_s
{
45 struct s3c_state_s
*cpu
;
47 struct ee24c08_s
* eeprom
;
57 * the 24c08 sits on 4 addresses on the bus, and uses the lower address bits
58 * to address the 256 byte "page" of the eeprom. We thus need to use 4 i2c_slaves
59 * and keep track of which one was used to set the read/write pointer into the data
62 typedef struct ee24cxx_page_s
{
64 struct ee24c08_s
* eeprom
;
67 typedef struct ee24c08_s
{
68 /* that memory takes 4 addresses */
75 static void ee24c08_event(i2c_slave
*i2c
, enum i2c_event event
)
77 ee24cxx_page_s
*s
= FROM_I2C_SLAVE(ee24cxx_page_s
, i2c
);
82 s
->eeprom
->ptr
= s
->page
* 256;
86 static int ee24c08_tx(i2c_slave
*i2c
, uint8_t data
)
88 ee24cxx_page_s
*s
= FROM_I2C_SLAVE(ee24cxx_page_s
, i2c
);
92 if (s
->eeprom
->count
++ == 0) {
93 /* first byte is address offset */
94 s
->eeprom
->ptr
= (s
->page
* 256) + data
;
96 mini2440_printf("write %04x=%02x\n", s
->eeprom
->ptr
, data
);
97 s
->eeprom
->data
[s
->eeprom
->ptr
] = data
;
98 s
->eeprom
->ptr
= (s
->eeprom
->ptr
& ~0xff) | ((s
->eeprom
->ptr
+ 1) & 0xff);
104 static int ee24c08_rx(i2c_slave
*i2c
)
106 ee24cxx_page_s
*s
= FROM_I2C_SLAVE(ee24cxx_page_s
, i2c
);
111 res
= s
->eeprom
->data
[s
->eeprom
->ptr
];
113 s
->eeprom
->ptr
= (s
->eeprom
->ptr
& ~0xff) | ((s
->eeprom
->ptr
+ 1) & 0xff);
118 static void ee24c08_save(QEMUFile
*f
, void *opaque
)
120 struct ee24c08_s
*s
= (struct ee24c08_s
*) opaque
;
123 qemu_put_be16s(f
, &s
->ptr
);
124 qemu_put_be16s(f
, &s
->count
);
125 qemu_put_buffer(f
, s
->data
, sizeof(s
->data
));
127 for (i
= 0; i
< 4; i
++)
128 i2c_slave_save(f
, s
->slave
[i
]);
131 static int ee24c08_load(QEMUFile
*f
, void *opaque
, int version_id
)
133 struct ee24c08_s
*s
= (struct ee24c08_s
*) opaque
;
136 qemu_get_be16s(f
, &s
->ptr
);
137 qemu_get_be16s(f
, &s
->count
);
138 qemu_get_buffer(f
, s
->data
, sizeof(s
->data
));
140 for (i
= 0; i
< 4; i
++)
141 i2c_slave_load(f
, s
->slave
[i
]);
145 static void ee24c08_page_init(i2c_slave
*i2c
)
147 /* nothing to do here */
150 static I2CSlaveInfo ee24c08_info
= {
151 .init
= ee24c08_page_init
,
152 .event
= ee24c08_event
,
157 static void ee24c08_register_devices(void)
159 i2c_register_slave("24C08", sizeof(ee24cxx_page_s
), &ee24c08_info
);
162 device_init(ee24c08_register_devices
);
164 static ee24c08
* ee24c08_init(i2c_bus
* bus
)
166 ee24c08
*s
= qemu_malloc(sizeof(ee24c08
));
169 printf("QEMU: %s\n", __FUNCTION__
);
171 memset(s
->data
, 0xff, sizeof(s
->data
));
173 for (i
= 0; i
< 4; i
++) {
174 DeviceState
*dev
= i2c_create_slave(bus
, "24C08", 0x50 + i
);
176 mini2440_printf("failed address %02x\n", 0x50+i
);
178 s
->slave
[i
] = I2C_SLAVE_FROM_QDEV(dev
);
179 ee24cxx_page_s
*ss
= FROM_I2C_SLAVE(ee24cxx_page_s
, s
->slave
[i
]);
183 register_savevm("ee24c08", -1, 0, ee24c08_save
, ee24c08_load
, s
);
187 /* Handlers for output ports */
188 static void mini2440_bl_switch(void *opaque
, int line
, int level
)
190 printf("QEMU: %s: LCD Backlight now %s (%d).\n", __FUNCTION__
, level
? "on" : "off", level
);
193 static void mini2440_bl_intensity(int line
, int level
, void *opaque
)
195 struct mini2440_board_s
*s
= (struct mini2440_board_s
*) opaque
;
197 if ((level
>> 8) != s
->bl_level
) {
198 s
->bl_level
= level
>> 8;
199 printf("%s: LCD Backlight now at %04x\n", __FUNCTION__
, level
);
203 static void mini2440_gpio_setup(struct mini2440_board_s
*s
)
205 /* set the "input" pin values */
206 s3c_gpio_set_dat(s
->cpu
->io
, S3C_GPG(13), 1);
207 s3c_gpio_set_dat(s
->cpu
->io
, S3C_GPG(14), 1);
208 s3c_gpio_set_dat(s
->cpu
->io
, S3C_GPG(15), 0);
210 s3c_gpio_out_set(s
->cpu
->io
, MINI2440_GPIO_BACKLIGHT
,
211 *qemu_allocate_irqs(mini2440_bl_switch
, s
, 1));
213 s3c_timers_cmp_handler_set(s
->cpu
->timers
, 1, mini2440_bl_intensity
, s
);
215 /* Register the SD card pins to the lower SD driver */
217 s3c_gpio_in_get(s
->cpu
->io
)[MINI2440_GPIO_WP_SD
],
218 qemu_irq_invert(s3c_gpio_in_get(s
->cpu
->io
)[MINI2440_IRQ_nSD_DETECT
]));
223 static void hexdump(const void* address
, uint32_t len
)
225 const unsigned char* p
= address
;
228 for (i
= 0; i
< len
; i
+= 16) {
229 for (j
= 0; j
< 16 && i
+ j
< len
; j
++)
230 fprintf(stderr
, "%02x ", p
[i
+ j
]);
232 fprintf(stderr
, " ");
233 fprintf(stderr
, " ");
234 for (j
= 0; j
< 16 && i
+ j
< len
; j
++)
235 fprintf(stderr
, "%c", (p
[i
+ j
] < ' ' || p
[i
+ j
] > 0x7f) ? '.' : p
[i
+ j
]);
236 fprintf(stderr
, "\n");
241 static int mini2440_load_from_nand(NANDFlashState
*nand
,
242 uint32_t nand_offset
, uint32_t s3c_base_offset
, uint32_t size
)
252 for (page
= 0; page
< (size
/ 512); page
++, src
+= 512 + 16, dst
+= 512) {
253 if (nand_readraw(nand
, nand_offset
+ src
, buffer
, 512)) {
254 cpu_physical_memory_write(s3c_base_offset
+ dst
, buffer
, 512);
256 mini2440_printf("failed to load nand %d:%d\n",
257 nand_offset
+ src
, 512 + 16);
264 static void mini2440_reset(void *opaque
)
266 struct mini2440_board_s
*s
= (struct mini2440_board_s
*) opaque
;
269 s
->cpu
->env
->regs
[15] = 0;
271 if (s
->boot_mode
== BOOT_NAND
) {
273 * Normally we would load 4 KB of nand to SRAM and jump there, but
274 * it is not working perfectly as expected, so we cheat and load
275 * it from nand directly relocated to 0x33f80000 and jump there
277 if (mini2440_load_from_nand(s
->nand
, 0, S3C_RAM_BASE
| 0x03f80000, 256*1024)> 0) {
278 mini2440_printf("loaded default u-boot from NAND\n");
279 s
->cpu
->env
->regs
[15] = S3C_RAM_BASE
| 0x03f80000; /* start address, u-boot already relocated */
281 #if 0 && defined(LATER)
282 if (mini2440_load_from_nand(s
->nand
, 0, S3C_SRAM_BASE_NANDBOOT
, S3C_SRAM_SIZE
) > 0) {
283 s
->cpu
->env
->regs
[15] = S3C_SRAM_BASE_NANDBOOT
; /* start address, u-boot relocating code */
284 mini2440_printf("4KB SteppingStone loaded from NAND\n");
289 * if a u--boot is available as a file, we always use it
292 image_size
= load_image("mini2440/u-boot.bin", qemu_get_ram_ptr(0x03f80000));
294 image_size
= load_image("u-boot.bin", qemu_get_ram_ptr(0x03f80000));
295 if (image_size
> 0) {
296 if (image_size
& (512 -1)) /* round size to a NAND block size */
297 image_size
= (image_size
+ 512) & ~(512-1);
298 mini2440_printf("loaded override u-boot (size %x)\n", image_size
);
299 s
->cpu
->env
->regs
[15] = S3C_RAM_BASE
| 0x03f80000; /* start address, u-boot already relocated */
304 * if a kernel was explicitly specified, we load it too
307 image_size
= load_image(s
->kernel
, qemu_get_ram_ptr(0x02000000));
308 if (image_size
> 0) {
309 if (image_size
& (512 -1)) /* round size to a NAND block size */
310 image_size
= (image_size
+ 512) & ~(512-1);
311 mini2440_printf("loaded %s (size %x)\n", s
->kernel
, image_size
);
317 /* Typical touchscreen calibration values */
318 static const int mini2440_ts_scale
[6] = {
319 0, (90 - 960) * 256 / 1021, -90 * 256 * 32,
320 (940 - 75) * 256 / 1021, 0, 75 * 256 * 32,
326 const char *boot_device
,
327 const char *kernel_filename
,
328 const char *kernel_cmdline
,
329 const char *initrd_filename
,
330 const char *cpu_model
)
332 struct mini2440_board_s
*mini
=
333 (struct mini2440_board_s
*)qemu_mallocz(sizeof(struct mini2440_board_s
));
334 int sd_idx
= drive_get_index(IF_SD
, 0, 0);
335 int nor_idx
= drive_get_index(IF_PFLASH
, 0, 0);
336 int nand_idx
= drive_get_index(IF_MTD
, 0, 0);
337 int nand_cid
= 0x76; // 128MB flash == 0xf1
339 mini
->ram
= 0x04000000;
340 mini
->kernel
= kernel_filename
;
341 mini
->mmc
= sd_idx
>= 0 ? sd_init(drives_table
[sd_idx
].bdrv
, 0) : NULL
;
342 mini
->boot_mode
= BOOT_NAND
;
344 if (cpu_model
&& strcmp(cpu_model
, "arm920t")) {
345 mini2440_printf("This platform requires an ARM920T core\n");
349 uint32_t sram_base
= 0;
351 * Use an environment variable to set the boot mode "switch"
353 const char * boot_mode
= getenv("MINI2440_BOOT");
356 if (!strcasecmp(boot_mode
, "nor")) {
358 printf("%s MINI2440_BOOT(nor) error, no flash file specified", __func__
);
361 mini
->boot_mode
= BOOT_NOR
;
362 } else if (!strcasecmp(boot_mode
, "nand")) {
364 printf("%s MINI2440_BOOT(nand) error, no flash file specified", __func__
);
367 mini
->boot_mode
= BOOT_NOR
;
369 printf("%s MINI2440_BOOT(%s) ignored, invalid value", __func__
, boot_mode
);
371 printf("%s: Boot mode: %s\n", __func__
, mini
->boot_mode
== BOOT_NOR
? "NOR": "NAND");
372 /* Check the boot mode */
373 switch (mini
->boot_mode
) {
375 sram_base
= S3C_SRAM_BASE_NANDBOOT
;
376 int size
= bdrv_getlength(drives_table
[nand_idx
].bdrv
);
378 case 2 * 65536 * (512 + 16):
381 case 4 * 65536 * (512 + 16):
385 printf("%s: Unknown NAND size/id %d (%dMB) defaulting to old 64MB\n",
386 __func__
, size
, ((size
/ (512 + 16)) * 512) / 1024 / 1024);
391 sram_base
= S3C_SRAM_BASE_NORBOOT
;
392 int nor_size
= bdrv_getlength(drives_table
[nor_idx
].bdrv
);
393 if (nor_size
> FLASH_NOR_SIZE
)
394 printf("%s: file too big (2MBytes)\n", __func__
);
395 printf("%s: Register parallel flash %d size 0x%x '%s'\n", __func__
,
397 bdrv_get_device_name(drives_table
[nor_idx
].bdrv
));
401 mini
->cpu
= s3c24xx_init(S3C_CPU_2440
, 12000000 /* 12 mhz */, mini
->ram
, sram_base
, mini
->mmc
);
403 /* Setup peripherals */
404 mini2440_gpio_setup(mini
);
406 mini
->eeprom
= ee24c08_init(s3c_i2c_bus(mini
->cpu
->i2c
));
412 nd
->model
= "dm9000";
413 if (strcmp(nd
->model
, "dm9000") == 0) {
414 dm9000_init(nd
, 0x20000000, 0x300, 0x304, s3c_gpio_in_get(mini
->cpu
->io
)[MINI2440_IRQ_DM9000
]);
418 s3c_adc_setscale(mini
->cpu
->adc
, mini2440_ts_scale
);
420 /* Setup initial (reset) machine state */
421 qemu_register_reset(mini2440_reset
, mini
);
423 // Original 64MB NAND (obsolete part)
424 // mini->nand = nand_init(NAND_MFR_SAMSUNG, 0x76);
425 // 128MB nand -- the hardware can also have 256, 1GB parts
426 mini
->nand
= nand_init(NAND_MFR_SAMSUNG
, nand_cid
);
427 mini
->cpu
->nand
->reg(mini
->cpu
->nand
, mini
->nand
);
429 mini
->nor
= pflash_cfi02_register(0,
430 qemu_ram_alloc(FLASH_NOR_SIZE
),
431 nor_idx
!= -1 ? drives_table
[nor_idx
].bdrv
: NULL
, (64 * 1024),
432 FLASH_NOR_SIZE
>> 16,
433 1, 2, 0x0000, 0x0000, 0x0000, 0x0000,
436 mini2440_reset(mini
);
439 QEMUMachine mini2440_machine
= {
441 "MINI2440 Chinese Samsung SoC dev board (S3C2440A)",
442 .init
= mini2440_init
,