From 18b91f222c2aebb2eb45cb7e6d5f58ca668e2aa2 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Thu, 13 Oct 2011 12:24:48 +0100 Subject: [PATCH] nand: boot code cleanup Refactored the init phase added a MINI2440_BOOT=nor/nand environment variable to act like the hardware switch in the real board, and added a few warnings for when the image doesn't match what's needed. Signed-off-by: Michel Pollet --- hw/mini2440.c | 226 +++++++++++++++++++++++---------------------- hw/nand.c | 5 +- mini2440/mini2440_start.sh | 23 ++--- 3 files changed, 131 insertions(+), 123 deletions(-) diff --git a/hw/mini2440.c b/hw/mini2440.c index 780f4ffae1..40edb06c8f 100644 --- a/hw/mini2440.c +++ b/hw/mini2440.c @@ -35,6 +35,8 @@ #define MINI2440_IRQ_nSD_DETECT S3C_EINT(16) #define MINI2440_IRQ_DM9000 S3C_EINT(7) +#define FLASH_NOR_SIZE (2*1024*1024) + #define BOOT_NONE 0 #define BOOT_NOR 1 #define BOOT_NAND 2 @@ -46,6 +48,7 @@ struct mini2440_board_s { const char * kernel; SDState * mmc; NANDFlashState *nand; + pflash_t * nor; int bl_level; int boot_mode; }; @@ -265,38 +268,38 @@ static void mini2440_reset(void *opaque) s->cpu->env->regs[15] = 0; - if (s->boot_mode == BOOT_NAND) { - /* - * Normally we would load 4 KB of nand to SRAM and jump there, but - * it is not working perfectly as expected, so we cheat and load - * it from nand directly relocated to 0x33f80000 and jump there - */ - if (mini2440_load_from_nand(s->nand, 0, S3C_RAM_BASE | 0x03f80000, 256*1024)> 0) { - mini2440_printf("loaded default u-boot from NAND\n"); - s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; /* start address, u-boot already relocated */ - } + if (s->boot_mode == BOOT_NAND) { + /* + * Normally we would load 4 KB of nand to SRAM and jump there, but + * it is not working perfectly as expected, so we cheat and load + * it from nand directly relocated to 0x33f80000 and jump there + */ + if (mini2440_load_from_nand(s->nand, 0, S3C_RAM_BASE | 0x03f80000, 256*1024)> 0) { + mini2440_printf("loaded default u-boot from NAND\n"); + s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; /* start address, u-boot already relocated */ + } #if 0 && defined(LATER) - if (mini2440_load_from_nand(s->nand, 0, S3C_SRAM_BASE_NANDBOOT, S3C_SRAM_SIZE) > 0) { - s->cpu->env->regs[15] = S3C_SRAM_BASE_NANDBOOT; /* start address, u-boot relocating code */ - mini2440_printf("4KB SteppingStone loaded from NAND\n"); - } + if (mini2440_load_from_nand(s->nand, 0, S3C_SRAM_BASE_NANDBOOT, S3C_SRAM_SIZE) > 0) { + s->cpu->env->regs[15] = S3C_SRAM_BASE_NANDBOOT; /* start address, u-boot relocating code */ + mini2440_printf("4KB SteppingStone loaded from NAND\n"); + } #endif - /* - * if a u--boot is available as a file, we always use it - */ - { - image_size = load_image("mini2440/u-boot.bin", qemu_get_ram_ptr(0x03f80000)); - if (image_size < 0) - image_size = load_image("u-boot.bin", qemu_get_ram_ptr(0x03f80000)); - if (image_size > 0) { - if (image_size & (512 -1)) /* round size to a NAND block size */ - image_size = (image_size + 512) & ~(512-1); - mini2440_printf("loaded override u-boot (size %x)\n", image_size); - s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; /* start address, u-boot already relocated */ - } + /* + * if a u--boot is available as a file, we always use it + */ + { + image_size = load_image("mini2440/u-boot.bin", qemu_get_ram_ptr(0x03f80000)); + if (image_size < 0) + image_size = load_image("u-boot.bin", qemu_get_ram_ptr(0x03f80000)); + if (image_size > 0) { + if (image_size & (512 -1)) /* round size to a NAND block size */ + image_size = (image_size + 512) & ~(512-1); + mini2440_printf("loaded override u-boot (size %x)\n", image_size); + s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000; /* start address, u-boot already relocated */ + } + } } - } /* * if a kernel was explicitly specified, we load it too */ @@ -317,40 +320,90 @@ static const int mini2440_ts_scale[6] = { (940 - 75) * 256 / 1021, 0, 75 * 256 * 32, }; -/* Board init. */ -static struct mini2440_board_s *mini2440_init_common(struct mini2440_board_s *s, - int ram_size, - const char *kernel_filename, const char *cpu_model, - SDState *mmc) +static void +mini2440_init( + ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) { - uint32_t sram_base; + struct mini2440_board_s *mini = + (struct mini2440_board_s *)qemu_mallocz(sizeof(struct mini2440_board_s)); + int sd_idx = drive_get_index(IF_SD, 0, 0); + int nor_idx = drive_get_index(IF_PFLASH, 0, 0); + int nand_idx = drive_get_index(IF_MTD, 0, 0); + int nand_cid = 0x76; // 128MB flash == 0xf1 - s->ram = 0x04000000; - s->kernel = kernel_filename; - s->mmc = mmc; + mini->ram = 0x04000000; + mini->kernel = kernel_filename; + mini->mmc = sd_idx >= 0 ? sd_init(drives_table[sd_idx].bdrv, 0) : NULL; + mini->boot_mode = BOOT_NAND; - /* Setup CPU & memory */ - if (ram_size < s->ram + S3C_SRAM_SIZE) { - mini2440_printf("This platform requires %i bytes of memory (not %d)\n", - s->ram + S3C_SRAM_SIZE, ram_size); - exit(1); - } if (cpu_model && strcmp(cpu_model, "arm920t")) { mini2440_printf("This platform requires an ARM920T core\n"); exit(2); } - if (s->boot_mode == BOOT_NOR) - sram_base = S3C_SRAM_BASE_NORBOOT; - else - sram_base = S3C_SRAM_BASE_NANDBOOT; + uint32_t sram_base = 0; + /* + * Use an environment variable to set the boot mode "switch" + */ + const char * boot_mode = getenv("MINI2440_BOOT"); + + if (boot_mode) { + if (!strcasecmp(boot_mode, "nor")) { + if (nor_idx < 0) { + printf("%s MINI2440_BOOT(nor) error, no flash file specified", __func__); + abort(); + } else + mini->boot_mode = BOOT_NOR; + } else if (!strcasecmp(boot_mode, "nand")) { + if (nor_idx < 0) { + printf("%s MINI2440_BOOT(nand) error, no flash file specified", __func__); + abort(); + } else + mini->boot_mode = BOOT_NOR; + } else + printf("%s MINI2440_BOOT(%s) ignored, invalid value", __func__, boot_mode); + } + printf("%s: Boot mode: %s\n", __func__, mini->boot_mode == BOOT_NOR ? "NOR": "NAND"); + /* Check the boot mode */ + switch (mini->boot_mode) { + case BOOT_NAND: + sram_base = S3C_SRAM_BASE_NANDBOOT; + int size = bdrv_getlength(drives_table[nand_idx].bdrv); + switch (size) { + case 2 * 65536 * (512 + 16): + nand_cid = 0x76; + break; + case 4 * 65536 * (512 + 16): + nand_cid = 0xf1; + break; + default: + printf("%s: Unknown NAND size/id %d (%dMB) defaulting to old 64MB\n", + __func__, size, ((size / (512 + 16)) * 512) / 1024 / 1024); + break; + } + break; + case BOOT_NOR: { + sram_base = S3C_SRAM_BASE_NORBOOT; + int nor_size = bdrv_getlength(drives_table[nor_idx].bdrv); + if (nor_size > FLASH_NOR_SIZE) + printf("%s: file too big (2MBytes)\n", __func__); + printf("%s: Register parallel flash %d size 0x%x '%s'\n", __func__, + nor_idx, nor_size, + bdrv_get_device_name(drives_table[nor_idx].bdrv)); + } break; + } - s->cpu = s3c24xx_init(S3C_CPU_2440, 12000000 /* 12 mhz */, s->ram, sram_base, s->mmc); + mini->cpu = s3c24xx_init(S3C_CPU_2440, 12000000 /* 12 mhz */, mini->ram, sram_base, mini->mmc); /* Setup peripherals */ - mini2440_gpio_setup(s); + mini2440_gpio_setup(mini); - s->eeprom = ee24c08_init(s3c_i2c_bus(s->cpu->i2c)); + mini->eeprom = ee24c08_init(s3c_i2c_bus(mini->cpu->i2c)); { NICInfo* nd; @@ -358,73 +411,28 @@ static struct mini2440_board_s *mini2440_init_common(struct mini2440_board_s *s, if (!nd->model) nd->model = "dm9000"; if (strcmp(nd->model, "dm9000") == 0) { - dm9000_init(nd, 0x20000000, 0x300, 0x304, s3c_gpio_in_get(s->cpu->io)[MINI2440_IRQ_DM9000]); + dm9000_init(nd, 0x20000000, 0x300, 0x304, s3c_gpio_in_get(mini->cpu->io)[MINI2440_IRQ_DM9000]); } } - s3c_adc_setscale(s->cpu->adc, mini2440_ts_scale); + s3c_adc_setscale(mini->cpu->adc, mini2440_ts_scale); /* Setup initial (reset) machine state */ - qemu_register_reset(mini2440_reset, s); + qemu_register_reset(mini2440_reset, mini); - return s; -} - -#define FLASH_NOR_SIZE (2*1024*1024) - -static void mini2440_init(ram_addr_t ram_size, - const char *boot_device, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - const char *cpu_model) -{ - struct mini2440_board_s *mini = (struct mini2440_board_s *) - qemu_mallocz(sizeof(struct mini2440_board_s)); - int sd_idx = drive_get_index(IF_SD, 0, 0); - int nor_idx = drive_get_index(IF_PFLASH, 0, 0); - int nand_idx = drive_get_index(IF_MTD, 0, 0); - SDState *sd = 0; - ram_addr_t phys_flash; - - /* Check the boot mode */ - if (nand_idx == 0) - mini->boot_mode = BOOT_NAND; - if (nor_idx == 0) - mini->boot_mode = BOOT_NOR; - - printf("Boot mode: %s\n", mini->boot_mode == BOOT_NOR ? "NOR": "NAND"); - - /* Flash NOR init */ - if (mini->boot_mode == BOOT_NOR) { - - int nor_size = bdrv_getlength(drives_table[nor_idx].bdrv); - if (nor_size > FLASH_NOR_SIZE) - printf("file too big (2MBytes)\n"); - printf("Register parallel flash %d size 0x%x '%s'\n", - nor_idx, nor_size, - bdrv_get_device_name(drives_table[nor_idx].bdrv)); - - - - phys_flash = qemu_ram_alloc(FLASH_NOR_SIZE); - pflash_cfi02_register(0, phys_flash, - nor_idx != -1 ? drives_table[nor_idx].bdrv : NULL, (64 * 1024), - FLASH_NOR_SIZE >> 16, - 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, - 0x555, 0x2aa); - } - - /* SD init */ - if (sd_idx >= 0) - sd = sd_init(drives_table[sd_idx].bdrv, 0); - - mini = mini2440_init_common(mini, ram_size, - kernel_filename, cpu_model, sd); - - mini->nand = nand_init(NAND_MFR_SAMSUNG, 0x76); + // Original 64MB NAND (obsolete part) + // mini->nand = nand_init(NAND_MFR_SAMSUNG, 0x76); + // 128MB nand -- the hardware can also have 256, 1GB parts + mini->nand = nand_init(NAND_MFR_SAMSUNG, nand_cid); mini->cpu->nand->reg(mini->cpu->nand, mini->nand); + mini->nor = pflash_cfi02_register(0, + qemu_ram_alloc(FLASH_NOR_SIZE), + nor_idx != -1 ? drives_table[nor_idx].bdrv : NULL, (64 * 1024), + FLASH_NOR_SIZE >> 16, + 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x555, 0x2aa); + mini2440_reset(mini); } diff --git a/hw/nand.c b/hw/nand.c index 0b084b445f..c1e7acfa41 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -503,9 +503,12 @@ NANDFlashState *nand_init(int manf_id, int chip_id) if (!s->bdrv) pagesize += 1 << s->page_shift; - if (pagesize) + if (pagesize) { + printf("%s no/invalid block device, allocating %d*%d in ram\n", + __func__, s->pages, pagesize); s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), 0xff, s->pages * pagesize); + } /* Give s->ioaddr a sane value in case we save state before it is used. */ s->ioaddr = s->io; diff --git a/mini2440/mini2440_start.sh b/mini2440/mini2440_start.sh index 6bff64ccd0..49504555c5 100755 --- a/mini2440/mini2440_start.sh +++ b/mini2440/mini2440_start.sh @@ -1,27 +1,27 @@ #!/bin/bash +# +# Run with script with +# -sd to have a SD card loaded +# -kernel to have a kernel preloaded in RAM +# base=$(dirname $0) echo Starting in $base -name_nand="$base/mini2440_nand.bin" -name_snapshots="$base/mini2440_snapshots.img" +name_nand="$base/mini2440_nand128.bin" if [ ! -f "$name_nand" ]; then echo $0 : creating NAND empty image : "$name_nand" - dd if=/dev/zero of="$name_nand" bs=528 count=131072 +# dd if=/dev/zero of="$name_nand" bs=528 count=131072 + dd if=/dev/zero of="$name_nand" bs=2112 count=65536 + echo "** NAND file created - make sure to 'nand scrub' in u-boot" fi -if [ ! -f "$name_snapshots" ]; then - echo $0 : creating empty snapshot image : "$name_snapshots" - qemu-img create "$name_snapshots" 100MB -fi - +# -kernel /tftpboot/uImage cmd="$base/../arm-softmmu/qemu-system-arm \ -M mini2440 $* \ - -drive file=$name_snapshots,snapshot=on \ -serial stdio \ - -kernel /tftpboot/uImage \ -mtdblock "$name_nand" \ -show-cursor \ -usb -usbdevice keyboard -usbdevice mouse \ @@ -29,8 +29,5 @@ cmd="$base/../arm-softmmu/qemu-system-arm \ -net tap,vlan=0,ifname=tap0 \ -monitor telnet::5555,server,nowait" -# cmd="gdbserver :3333 $cmd" -# -monitor unix:.mini2440_monitor,server,nowait" - echo $cmd $cmd -- 2.11.4.GIT