let beagleboard understand the -m switch
[qemu] / hw / beagle.c
index aa8c0ae..ddceefd 100644 (file)
-/*\r
- * Beagle board emulation. http://beagleboard.org/\r
- * \r
- * Copyright (C) 2008 yajin(yajin@vm-kernel.org)\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License as\r
- * published by the Free Software Foundation; either version 2 or\r
- * (at your option) version 3 of the License.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,\r
- * MA 02111-1307 USA\r
- */\r
-\r
-#include "qemu-common.h"\r
-#include "sysemu.h"\r
-#include "omap.h"\r
-#include "arm-misc.h"\r
-#include "irq.h"\r
-#include "console.h"\r
-#include "boards.h"\r
-#include "i2c.h"\r
-#include "devices.h"\r
-#include "flash.h"\r
-#include "hw.h"\r
-#include "block.h"\r
-\r
-#define BEAGLE_NAND_CS                 0\r
-#define BEAGLE_TWL4030_ADDR            0x4b    /* Power management */\r
-\r
-#define GPMC_NOR             0\r
-#define GPMC_NAND           1\r
-#define GPMC_MDOC           2\r
-#define GPMC_ONENAND    3\r
-#define MMC_NAND            4\r
-#define MMC_ONENAND     5\r
-\r
-\r
-#define TST_DEVICE              0x0\r
-#define EMU_DEVICE              0x1\r
-#define HS_DEVICE               0x2\r
-#define GP_DEVICE               0x3\r
-\r
-#define DEBUG_BEAGLE\r
-\r
-#ifdef DEBUG_BEAGLE\r
-#define BEAGLE_DEBUG(...)    do { fprintf(stderr, __VA_ARGS__); } while(0)\r
-#else\r
-#define BEAGLE_DEBUG(x)    \r
-#endif\r
-\r
-/* Beagle board support */\r
-struct beagle_s {\r
-    struct omap_mpu_state_s *cpu;\r
-    \r
-    struct nand_bflash_s *nand;\r
-    struct omap3_lcd_panel_s *lcd_panel;\r
-    i2c_bus *i2c;\r
-};\r
-\r
-\r
-\r
-static struct arm_boot_info beagle_binfo = {\r
-    .ram_size = 0x08000000,\r
-};\r
-\r
-\r
-static uint32_t beagle_nand_read16(void *opaque, target_phys_addr_t addr)\r
-{\r
-       struct beagle_s *s = (struct beagle_s *) opaque;\r
-    //BEAGLE_DEBUG("beagle_nand_read16 offset %x\n",addr);\r
-\r
-       switch (addr)\r
-       {\r
-               case 0x7C: /*NAND_COMMAND*/\r
-               case 0x80: /*NAND_ADDRESS*/\r
-                       OMAP_BAD_REG(addr);\r
-                       break;\r
-               case 0x84: /*NAND_DATA*/\r
-                       return nandb_read_data16(s->nand);\r
-                       break;\r
-               default:\r
-                       OMAP_BAD_REG(addr);\r
-                       break;\r
-       }\r
-    return 0;\r
-}\r
-\r
-static void beagle_nand_write16(void *opaque, target_phys_addr_t addr,\r
-                uint32_t value)\r
-{\r
-       struct beagle_s *s = (struct beagle_s *) opaque;\r
-    switch (addr)\r
-       {\r
-               case 0x7C: /*NAND_COMMAND*/\r
-                       nandb_write_command(s->nand,value);\r
-                       break;\r
-               case 0x80: /*NAND_ADDRESS*/\r
-                       nandb_write_address(s->nand,value);\r
-                       break;\r
-               case 0x84: /*NAND_DATA*/\r
-                       nandb_write_data16(s->nand,value);\r
-                       break;\r
-               default:\r
-                       OMAP_BAD_REG(addr);\r
-                       break;\r
-       }\r
-}\r
-\r
-\r
-static CPUReadMemoryFunc *beagle_nand_readfn[] = {\r
-        beagle_nand_read16,\r
-        beagle_nand_read16,\r
-        omap_badwidth_read32,\r
-};\r
-\r
-static CPUWriteMemoryFunc *beagle_nand_writefn[] = {\r
-        beagle_nand_write16,\r
-        beagle_nand_write16,\r
-        omap_badwidth_write32,\r
-};\r
-\r
-static void beagle_nand_setup(struct beagle_s *s)\r
-{\r
-       //int iomemtype;\r
-       \r
-       /*MT29F2G16ABC*/\r
-       s->nand = nandb_init(NAND_MFR_MICRON,0xba);\r
-       /*wp=1, no write protect!!! */\r
-       //nand_set_wp(s->nand, 1);\r
-\r
-/*     iomemtype = cpu_register_io_memory(0, beagle_nand_readfn,\r
-                    beagle_nand_writefn, s);\r
-    cpu_register_physical_memory(0x6e00007c, 0xc, iomemtype);*/\r
-    omap_gpmc_attach(s->cpu->gpmc, 0, 0, NULL, NULL, s, beagle_nand_readfn, beagle_nand_writefn);\r
-\r
-        /*BOOT from nand*/\r
-    omap3_set_mem_type(s->cpu,GPMC_NAND);\r
-\r
-}\r
-\r
-static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint16_t page_addr)\r
-{\r
-       uint16_t *p;\r
-       int i;\r
-\r
-       p=(uint16_t *)buf;\r
-\r
-       /*send command 0x0*/\r
-       beagle_nand_write16(s,0x7C,0);\r
-       /*send page address */\r
-       beagle_nand_write16(s,0x80,page_addr&0xff);\r
-       beagle_nand_write16(s,0x80,(page_addr>>8)&0x7);\r
-       beagle_nand_write16(s,0x80,(page_addr>>11)&0xff);\r
-       beagle_nand_write16(s,0x80,(page_addr>>19)&0xff);\r
-       beagle_nand_write16(s,0x80,(page_addr>>27)&0xff);\r
-       /*send command 0x30*/\r
-       beagle_nand_write16(s,0x7C,0x30);\r
-\r
-       for (i=0;i<0x800/2;i++)\r
-       {\r
-               *p++ = beagle_nand_read16(s,0x84);\r
-       }\r
-       return 1;\r
-}\r
-\r
-static uint32_t get_le32(void *p)\r
-{\r
-    uint8_t *q = (uint8_t *)p;\r
-    uint32_t v;\r
-    v = q[3]; v <<= 8;\r
-    v |= q[2]; v <<= 8;\r
-    v |= q[1]; v <<= 8;\r
-    v |= q[0];\r
-    return v;\r
-}\r
-\r
-static uint32_t get_le16(void *p)\r
-{\r
-    uint8_t *q = (uint8_t *)p;\r
-    uint32_t v;\r
-    v = q[1]; v <<= 8;\r
-    v |= q[0];\r
-    return v;\r
-}\r
-\r
-/* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */\r
-static uint8_t *beagle_scan_fat_dir_sector(uint8_t *s)\r
-{\r
-    int i;\r
-\r
-    /* there are 0x10 items with 0x20 bytes per item */\r
-    for (i = 0x10; i--; s += 0x20) {\r
-        if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased or LFN */\r
-        if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;\r
-    }\r
-    return 0;\r
-}\r
-\r
-struct beagle_fat_drv_s {\r
-    BlockDriverState *bs;\r
-    uint8_t ptype; // 12, 16, 32\r
-    uint64_t c0; // physical byte offset for data cluster 0\r
-    uint64_t fat; // physical byte offset for used FAT sector 0\r
-    uint32_t spc; // sectors per cluster\r
-};\r
-\r
-/* returns cluster data in the buffer and next cluster chain number or 0 if unsuccessful */\r
-static uint32_t beagle_read_fat_cluster(uint8_t *data,\r
-                                        struct beagle_fat_drv_s *drv,\r
-                                        uint32_t cl)\r
-{\r
-    uint8_t buf[ 4 ];\r
-    uint32_t len = drv->spc * 0x200; // number of bytes to read i.e. bytes per cluster\r
-    \r
-    switch (drv->ptype) { /* check for EOF */\r
-        case 12: if (cl > 0xff0) return 0; break;\r
-        case 16: if (cl > 0xfff0) return 0; break;\r
-        case 32: if (cl > 0x0ffffff0) return 0; break;\r
-        default: return 0;\r
-    }\r
-\r
-    if (bdrv_pread(drv->bs, drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len), data, len) != len) return 0;\r
-    \r
-    switch (drv->ptype) { /* determine next cluster # */\r
-        case 12: fprintf(stderr, "%s: FAT12 parsing not implemented!\n", __FUNCTION__); break;\r
-        case 16: return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2) ? 0 : get_le16(buf);\r
-        case 32: return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4) ? 0 : get_le32(buf) & 0x0fffffff;\r
-        default: break;\r
-    }\r
-    return 0;\r
-}\r
-\r
-static int beagle_boot_from_mmc(struct beagle_s *s)\r
-{\r
-    struct beagle_fat_drv_s drv;\r
-    int sdindex = drive_get_index(IF_SD, 0, 0);\r
-    uint8_t sector[0x200], *p, *q;\r
-    uint32_t pstart, i, j, k, cluster0, fatsize, bootsize, rootsize;\r
-    uint32_t img_size, img_addr;\r
-    int result = -1;\r
-    \r
-    /* very simple implementation, requires MBR partitioning with an active FAT partition\r
-       and does no sanity checks for the partition table or FAT boot sector entries */\r
-    if (sdindex >= 0) {\r
-        drv.bs = drives_table[sdindex].bdrv;\r
-        if (bdrv_pread(drv.bs, 0, sector, 0x200) == 0x200\r
-            && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) { /* MBR signature */\r
-            for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) if (p[0] == 0x80) break;\r
-            if (i < 4 /* was there an active partition? */\r
-                && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11 \r
-                    || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT partition type */\r
-                && bdrv_pread(drv.bs, (pstart = get_le32(p + 8)) * 0x200, sector, 0x200) == 0x200\r
-                && sector[0x1fe] ==0x55 && sector[0x1ff] == 0xaa) { /* boot sector signature */\r
-                /* determine FAT type */\r
-                fatsize = get_le16(sector + 0x16); if (!fatsize) fatsize = get_le32(sector + 0x24);\r
-                bootsize = get_le16(sector + 0x0e);\r
-                cluster0 = bootsize + fatsize * sector[0x10];\r
-                rootsize = get_le16(sector + 0x11); if (rootsize & 0x0f) rootsize += 0x10; rootsize >>= 4;\r
-                drv.spc = sector[0x0d];\r
-                i = get_le16(sector + 0x13); if (!i) i = get_le32(sector + 0x20);\r
-                i = (i - (cluster0 + rootsize)) / drv.spc;\r
-                drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;\r
-                /* search for MLO file */\r
-                drv.fat = (bootsize + pstart) * 0x200;\r
-                drv.c0 = (cluster0 + pstart) * 0x200;\r
-                if (drv.ptype == 32) {\r
-                    i = get_le32(sector + 0x2c); /* first root cluster # */\r
-                    j = get_le16(sector + 0x28);\r
-                    if (j & 0x80) drv.fat += (j & 0x0f) * fatsize * 0x200;\r
-                    uint8_t *cluster = qemu_mallocz(drv.spc * 0x200);\r
-                    for (p = 0; !p && (i = beagle_read_fat_cluster(cluster, &drv, i)); ) {\r
-                        for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)\r
-                            p = beagle_scan_fat_dir_sector(q);\r
-                        if (p) memcpy(sector, q - 0x200, 0x200); // save the sector\r
-                    }\r
-                    free(cluster);\r
-                } else { /* FAT12/16 */\r
-                    for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {\r
-                        if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200) break;\r
-                        p = beagle_scan_fat_dir_sector(sector);\r
-                    }\r
-                }\r
-                if (p && *p) { // did we indeed find the file?\r
-                    i = get_le16(p + 0x14); i <<= 16; i |= get_le16(p + 0x1a);\r
-                    j = drv.spc * 0x200;\r
-                    uint8 *data = qemu_mallocz(j);\r
-                    if ((i = beagle_read_fat_cluster(data, &drv, i))) {\r
-                        /* TODO: support HS device boot - for now only GP device is supported */\r
-                        img_size = get_le32(data);\r
-                        img_addr = get_le32(data + 4);\r
-                        s->cpu->env->regs[15] = img_addr;\r
-                        cpu_physical_memory_write(img_addr, data + 8, \r
-                                                  (k = (j - 8 >= img_size) ? img_size : j - 8));\r
-                        for (img_addr += k, img_size -= k;\r
-                             img_size && (i = beagle_read_fat_cluster(data, &drv, i));\r
-                             img_addr += k, img_size -= k) {\r
-                            cpu_physical_memory_write(img_addr, data, \r
-                                                      (k = (j >= img_size) ? img_size : j));\r
-                        }\r
-                        result = 0;\r
-                    } else\r
-                        fprintf(stderr, "%s: unable to read MLO file contents from SD card\n", __FUNCTION__);\r
-                    free(data);\r
-                } else\r
-                    fprintf(stderr, "%s: MLO file not found in the root directory\n", __FUNCTION__);\r
-            } else\r
-                fprintf(stderr, "%s: no active FAT partition found on SD card\n", __FUNCTION__);\r
-        } else\r
-            fprintf(stderr, "%s: MBR not found on SD card\n", __FUNCTION__);\r
-    }\r
-    \r
-       return result;\r
-}\r
-\r
-/*read the xloader from NAND Flash into internal RAM*/\r
-static int beagle_boot_from_nand(struct beagle_s *s)\r
-{\r
-       uint32_t        loadaddr, len;\r
-       uint8_t nand_page[0x800],*load_dest;\r
-       uint32_t nand_pages,i;\r
-\r
-       /* The first two words(8 bytes) in first nand flash page have special meaning.\r
-               First word:x-loader len\r
-               Second word: x-load address in internal ram */\r
-       beagle_nand_read_page(s,nand_page,0);\r
-       len = *((uint32_t*)nand_page);\r
-       loadaddr =  *((uint32_t*)(nand_page+4));\r
-       if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))\r
-               return (-1);\r
-\r
-       /*put the first page into internal ram*/\r
-       load_dest = phys_ram_base +beagle_binfo.ram_size;\r
-       load_dest += loadaddr-OMAP3_SRAM_BASE;\r
-       \r
-       BEAGLE_DEBUG("load_dest %x phys_ram_base %x \n",(unsigned)load_dest,(unsigned)phys_ram_base);\r
-       \r
-       memcpy(load_dest,nand_page+8,0x800-8);\r
-       load_dest += 0x800-8;\r
-\r
-       nand_pages = len/0x800;\r
-       if (len%0x800!=0)\r
-               nand_pages++;\r
-\r
-       for (i=1;i<nand_pages;i++)\r
-       {\r
-               beagle_nand_read_page(s,nand_page,i*0x800);\r
-               memcpy(load_dest,nand_page,0x800);\r
-               load_dest += 0x800;\r
-       }\r
-       s->cpu->env->regs[15] = loadaddr;\r
-       return 0;\r
-\r
-}\r
- static int beagle_rom_emu(struct beagle_s *s)\r
-{\r
-       if (beagle_boot_from_mmc(s)<0)\r
-       {\r
-               if (beagle_boot_from_nand(s)<0)\r
-                       return (-1); \r
-       }\r
-       return (0);\r
-}\r
-\r
-static void beagle_dss_setup(struct beagle_s *s, DisplayState *ds)\r
-{\r
-       s->lcd_panel = omap3_lcd_panel_init(ds);\r
-       omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);\r
-       s->lcd_panel->dss = s->cpu->dss;\r
-}\r
-\r
-static void beagle_mmc_cs_cb(void *opaque, int line, int level)\r
-{\r
-    /* TODO: this seems to actually be connected to the menelaus, to\r
-     * which also both MMC slots connect.  */\r
-    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);\r
-\r
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);\r
-}\r
-\r
-static void beagle_i2c_setup(struct beagle_s *s)\r
-{\r
-\r
-    /* Attach the CPU on one end of our I2C bus.  */\r
-    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);\r
-\r
-    /* Attach a menelaus PM chip */\r
-    i2c_set_slave_address(\r
-                    twl4030_init(s->i2c,\r
-                            s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]),\r
-                    BEAGLE_TWL4030_ADDR);\r
-}\r
-\r
-\r
-static void beagle_init(ram_addr_t ram_size, int vga_ram_size,\r
-                const char *boot_device, DisplayState *ds,\r
-                const char *kernel_filename, const char *kernel_cmdline,\r
-                const char *initrd_filename, const char *cpu_model)\r
-{\r
-    struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));\r
-    int sdram_size = beagle_binfo.ram_size;\r
-\r
-       if (ram_size < sdram_size +  OMAP3530_SRAM_SIZE) {\r
-        fprintf(stderr, "This architecture uses %i bytes of memory\n",\r
-                        sdram_size + OMAP3530_SRAM_SIZE);\r
-        exit(1);\r
-    }\r
-       s->cpu = omap3530_mpu_init(sdram_size, NULL, NULL);\r
-       beagle_nand_setup(s);\r
-       beagle_i2c_setup(s);\r
-       beagle_dss_setup(s,ds);\r
-       omap3_set_device_type(s->cpu,GP_DEVICE);\r
-    if (beagle_rom_emu(s) < 0) {\r
-               fprintf(stderr,"boot from MMC and nand failed \n");\r
-               exit(-1);\r
-       }\r
-}\r
-\r
-\r
-\r
-QEMUMachine beagle_machine = {\r
-    .name = "beagle",\r
-    .desc =     "Beagle board (OMAP3530)",\r
-    .init =     beagle_init,\r
-    .ram_require =     (0x08000000 +  OMAP3530_SRAM_SIZE) | RAMSIZE_FIXED,\r
-};\r
-\r
+/*
+ * Beagle board emulation. http://beagleboard.org/
+ * 
+ * Original code Copyright (C) 2008 yajin(yajin@vm-kernel.org)
+ * Rewrite Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "omap.h"
+#include "arm-misc.h"
+#include "boards.h"
+#include "i2c.h"
+#include "devices.h"
+#include "flash.h"
+
+#define BEAGLE_NAND_CS       0
+#define BEAGLE_NAND_PAGESIZE 0x800
+#define BEAGLE_SDRAM_SIZE    (128 * 1024 * 1024) /* 128MB */
+
+/* Beagle board support */
+struct beagle_s {
+    struct omap_mpu_state_s *cpu;
+    
+    struct nand_flash_s *nand;
+    struct omap3_lcd_panel_s *lcd_panel;
+    i2c_bus *i2c;
+    struct twl4030_s *twl4030;
+};
+
+static void beagle_init(ram_addr_t ram_size, int vga_ram_size,
+                const char *boot_device,
+                const char *kernel_filename, const char *kernel_cmdline,
+                const char *initrd_filename, const char *cpu_model)
+{
+    struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));
+    int sdindex = drive_get_index(IF_SD, 0, 0);
+    
+    if (sdindex == -1) {
+        fprintf(stderr, "%s: missing SecureDigital device\n", __FUNCTION__);
+        exit(1);
+    }
+       s->cpu = omap3530_mpu_init(ram_size, NULL);
+    
+    if (serial_hds[0])
+        omap_uart_attach(s->cpu->uart[2], serial_hds[0]);
+
+       s->nand = nand_init(NAND_MFR_MICRON, 0xba); /* MT29F2G16ABC */
+       nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */
+    omap_gpmc_attach(s->cpu->gpmc, BEAGLE_NAND_CS, 0, NULL, NULL, s, s->nand);
+    omap3_mmc_attach(s->cpu->omap3_mmc[0], drives_table[sdindex].bdrv);
+
+    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
+    s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_3XXX_SYS_NIRQ]);
+
+       s->lcd_panel = omap3_lcd_panel_init();
+       omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
+    
+    omap3_boot_rom_emu(s->cpu);
+}
+
+QEMUMachine beagle_machine = {
+    .name =        "beagle",
+    .desc =        "Beagle board (OMAP3530)",
+    .init =        beagle_init,
+    .ram_require = OMAP3XXX_SRAM_SIZE + OMAP3XXX_BOOTROM_SIZE,
+};
+