-/*\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,
+};
+