#include "hw.h"
#include "block.h"
-#define BEAGLE_NAND_CS 0
+#define BEAGLE_NAND_CS 0
+#define BEAGLE_NAND_PAGESIZE 0x800
#define GPMC_NOR 0
#define GPMC_NAND 1
#define HS_DEVICE 0x2
#define GP_DEVICE 0x3
-#define DEBUG_BEAGLE
-
-#ifdef DEBUG_BEAGLE
-#define BEAGLE_DEBUG(...) do { fprintf(stderr, __VA_ARGS__); } while(0)
-#else
-#define BEAGLE_DEBUG(x)
-#endif
-
/* Beagle board support */
struct beagle_s {
struct omap_mpu_state_s *cpu;
struct twl4030_s *twl4030;
};
-
-
static struct arm_boot_info beagle_binfo = {
.ram_size = 0x08000000,
};
-
-static void beagle_nand_setup(struct beagle_s *s)
-{
- 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_set_mem_type(s->cpu, GPMC_NAND);
-}
-
-static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint32_t addr)
+static void beagle_nand_pread(struct nand_flash_s *nand,
+ uint64_t addr,
+ uint8_t *data,
+ uint32_t len)
{
- uint16_t *p = (uint16_t *)buf;
- int i;
-
+ uint16_t x;
+ uint32_t i;
+
+ if ((len&1) || (addr&1)) {
+ fprintf(stderr, "%s: read byte length and address must be even (x16 device!)\n",
+ __FUNCTION__);
+ exit(-1);
+ }
/* send command: reset */
- nand_setpins(s->nand, 1, 0, 0, 1, 0);
- nand_setio(s->nand, 0xff);
- /* send command: read page (cycle1) */
- nand_setpins(s->nand, 1, 0, 0, 1, 0);
- nand_setio(s->nand, 0);
- /* send page address (x16 device):
- bits 0-11 define cache address in words (bit11 set only for OOB access)
- bits 16-33 define page and block address */
- nand_setpins(s->nand, 0, 1, 0, 1, 0);
- nand_setio(s->nand, (addr >> 1) & 0xff);
- nand_setio(s->nand, (addr >> 9) & 0x3);
- nand_setio(s->nand, (addr >> 11) & 0xff);
- nand_setio(s->nand, (addr >> 19) & 0xff);
- nand_setio(s->nand, (addr >> 27) & 0x1);
- /* send command: read page (cycle2) */
- nand_setpins(s->nand, 1, 0, 0, 1, 0);
- nand_setio(s->nand, 0x30);
- /* read page data */
- nand_setpins(s->nand, 0, 0, 0, 1, 0);
- for (i = 0; i < 0x800 / 2; i++)
- *(p++) = nand_getio(s->nand);
- return 1;
-}
-
-/*read the xloader from NAND Flash into internal RAM*/
-static int beagle_boot_from_nand(struct beagle_s *s)
-{
- uint32_t loadaddr, len;
- uint8_t nand_page[0x800],*load_dest;
- uint32_t nand_pages,i;
-
- /* The first two words(8 bytes) in first nand flash page have special meaning.
- First word:x-loader len
- Second word: x-load address in internal ram */
- beagle_nand_read_page(s,nand_page,0);
- len = *((uint32_t*)nand_page);
- loadaddr = *((uint32_t*)(nand_page+4));
- fprintf(stderr, "%s: len = 0x%08x, addr = 0x%08x\n", __FUNCTION__, len, loadaddr);
- if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))
- return (-1);
-
- /*put the first page into internal ram*/
- load_dest = phys_ram_base + beagle_binfo.ram_size;
- load_dest += loadaddr-OMAP3_SRAM_BASE;
-
- memcpy(load_dest,nand_page+8,0x800-8);
- load_dest += 0x800-8;
-
- nand_pages = len/0x800;
- if (len%0x800!=0)
- nand_pages++;
-
- for (i=1;i<nand_pages;i++)
- {
- beagle_nand_read_page(s,nand_page,i*0x800);
- memcpy(load_dest,nand_page,0x800);
- load_dest += 0x800;
- }
- s->cpu->env->regs[15] = loadaddr;
- return 0;
-
-}
-
-static int beagle_rom_emu(struct beagle_s *s)
-{
- if (!omap3_mmc_boot(s->cpu))
- if (beagle_boot_from_nand(s) < 0)
- return -1;
- return 0;
-}
-
-static void beagle_dss_setup(struct beagle_s *s)
-{
- s->lcd_panel = omap3_lcd_panel_init();
- omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
-}
-
-//static void beagle_mmc_cs_cb(void *opaque, int line, int level)
-//{
-// /* TODO: this seems to actually be connected to the menelaus, to
-// * which also both MMC slots connect. */
-// omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-//
-// printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
-//}
-
-static void beagle_i2c_setup(struct beagle_s *s)
-{
- /* Attach the CPU on one end of our I2C bus. */
- s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
-
- s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]);
+ nand_setpins(nand, 1, 0, 0, 1, 0);
+ nand_setio(nand, 0xff);
+ while (len) {
+ /* send command: read page (cycle1) */
+ nand_setpins(nand, 1, 0, 0, 1, 0);
+ nand_setio(nand, 0);
+ /* send address */
+ nand_setpins(nand, 0, 1, 0, 1, 0);
+ nand_setio(nand, (uint32_t)((addr >> 1) & 0xff));
+ nand_setio(nand, (uint32_t)((addr >> 9) & 0x3));
+ nand_setio(nand, (uint32_t)((addr >> 11) & 0xff));
+ nand_setio(nand, (uint32_t)((addr >> 19) & 0xff));
+ nand_setio(nand, (uint32_t)((addr >> 27) & 0x1));
+ /* send command: read page (cycle2) */
+ nand_setpins(nand, 1, 0, 0, 1, 0);
+ nand_setio(nand, 0x30);
+ /* read page data */
+ nand_setpins(nand, 0, 0, 0, 1, 0);
+ for (i = (BEAGLE_NAND_PAGESIZE / 2) - (addr & 0x3ff); i && len; i--) {
+ x = nand_getio(nand);
+ *(data++) = (uint8_t)(x & 0xff);
+ *(data++) = (uint8_t)((x >> 8) & 0xff);
+ len -= 2;
+ addr += 2;
+ }
+ }
}
-
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,
{
struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));
int sdram_size = beagle_binfo.ram_size;
-
+ int sdindex = drive_get_index(IF_SD, 0, 0);
+
+ if (sdindex == -1) {
+ fprintf(stderr, "qemu: missing SecureDigital device\n");
+ exit(1);
+ }
+
if (ram_size < sdram_size + OMAP3530_SRAM_SIZE) {
fprintf(stderr, "This architecture uses %i bytes of memory\n",
sdram_size + OMAP3530_SRAM_SIZE);
exit(1);
}
s->cpu = omap3530_mpu_init(sdram_size, NULL);
- beagle_nand_setup(s);
- beagle_i2c_setup(s);
- beagle_dss_setup(s);
- omap3_set_device_type(s->cpu,GP_DEVICE);
- if (beagle_rom_emu(s) < 0) {
- fprintf(stderr,"boot from MMC and nand failed \n");
- exit(-1);
- }
-}
+
+ 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_35XX_SYS_NIRQ]);
+ s->lcd_panel = omap3_lcd_panel_init();
+ omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
+
+ omap3_set_mem_type(s->cpu, GPMC_NAND);
+ omap3_set_device_type(s->cpu,GP_DEVICE);
+ if (!omap3_mmc_boot(s->cpu)
+ && !omap3_nand_boot(s->cpu, s->nand, beagle_nand_pread)) {
+ fprintf(stderr, "%s: boot from MMC and NAND failed\n",
+ __FUNCTION__);
+ exit(-1);
+ }
+}
QEMUMachine beagle_machine = {
.name = "beagle",
/* omap3_mmc.c */
struct omap3_mmc_s;
struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
- BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
- omap_clk fclk, omap_clk iclk);
+ qemu_irq irq, qemu_irq dma[],
+ omap_clk fclk, omap_clk iclk);
+void omap3_mmc_attach(struct omap3_mmc_s *s,
+ BlockDriverState *bd);
/* omap_i2c.c */
struct omap_i2c_s;
void omap3_set_mem_type(struct omap_mpu_state_s *s, int bootfrom);
void omap3_set_device_type(struct omap_mpu_state_s *s, int device_type);
int omap3_mmc_boot(struct omap_mpu_state_s *s);
+int omap3_nand_boot(struct omap_mpu_state_s *mpu,
+ struct nand_flash_s *nand,
+ void (*nand_pread_f)(struct nand_flash_s *nand,
+ uint64_t address,
+ uint8_t *data,
+ uint32_t len));
# if TARGET_PHYS_ADDR_BITS == 32
# define OMAP_FMT_plx "0x%08x"
qemu_irq *cpu_irq;
qemu_irq dma_irqs[4];
int i;
- int sdindex;
- //omap_clk gpio_clks[4];
s->mpu_model = omap3530;
s->env = cpu_init("cortex-a8-r2");
s->sdram_size = sdram_size;
s->sram_size = OMAP3530_SRAM_SIZE;
- sdindex = drive_get_index(IF_SD, 0, 0);
- if (sdindex == -1) {
- fprintf(stderr, "qemu: missing SecureDigital device\n");
- exit(1);
- }
-
/* Clocks */
omap_clk_init(s);
omap_findclk(s, "omap3_sdma_iclk"));
s->port->addr_valid = omap3_validate_addr;
-
/* Register SDRAM and SRAM ports for fast DMA transfers. */
soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
omap_findclk(s, "omap3_uart1_fclk"),
omap_findclk(s, "omap3_uart1_iclk"),
s->drq[OMAP35XX_DMA_UART1_TX],
- s->drq[OMAP35XX_DMA_UART1_RX], serial_hds[0]);
+ s->drq[OMAP35XX_DMA_UART1_RX], 0);
s->uart[1] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART2),
s->irq[0][OMAP_INT_35XX_UART2_IRQ],
omap_findclk(s, "omap3_uart2_fclk"),
omap_findclk(s, "omap3_uart2_iclk"),
s->drq[OMAP35XX_DMA_UART2_TX],
- s->drq[OMAP35XX_DMA_UART2_RX],
- serial_hds[0] ? serial_hds[1] : 0);
+ s->drq[OMAP35XX_DMA_UART2_RX], 0);
s->uart[2] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART3),
s->irq[0][OMAP_INT_35XX_UART3_IRQ],
omap_findclk(s, "omap3_uart2_fclk"),
omap_findclk(s, "omap3_uart3_iclk"),
s->drq[OMAP35XX_DMA_UART3_TX],
- s->drq[OMAP35XX_DMA_UART3_RX],
- serial_hds[0]
- && serial_hds[1] ? serial_hds[2] : 0);
+ s->drq[OMAP35XX_DMA_UART3_RX], 0);
- /*attach serial[0] to uart 2 for beagle board */
- omap_uart_attach(s->uart[2], serial_hds[0]);
-
s->dss = omap_dss_init(s, omap3_l4ta_init(s->l4, L4A_DSS),
s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
NULL,NULL,NULL,NULL,NULL);
- //gpio_clks[0] = NULL;
- //gpio_clks[1] = NULL;
- //gpio_clks[2] = NULL;
- //gpio_clks[3] = NULL;
-
s->gpif = omap3_gpif_init();
omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO1),
&s->irq[0][OMAP_INT_35XX_GPIO1_MPU_IRQ],
omap_tap_init(omap3_l4ta_init(s->l4, L4A_TAP), s);
s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC1),
- drives_table[sdindex].bdrv,
s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
&s->drq[OMAP35XX_DMA_MMC1_TX],
omap_findclk(s, "omap3_mmc1_fclk"),
omap_findclk(s, "omap3_mmc1_iclk"));
s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC2),
- NULL,
s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
&s->drq[OMAP35XX_DMA_MMC2_TX],
omap_findclk(s, "omap3_mmc2_fclk"),
omap_findclk(s, "omap3_mmc2_iclk"));
s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC3),
- NULL,
s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
&s->drq[OMAP35XX_DMA_MMC3_TX],
omap_findclk(s, "omap3_mmc3_fclk"),
s->state = imagehdr;
/* fallthrough */
case imagehdr:
+ if (!data_len)
+ return 1;
if (data_len < 8)
break;
s->count = omap3_get_le32(data);
s->addr = omap3_get_le32(data + 4);
+ if (!s->count || !s->addr || s->addr == 0xffffffff)
+ break;
s->mpu->env->regs[15] = s->addr;
data += 8;
data_len -= 8;
cpu_physical_memory_write(s->addr, data, i);
s->addr += i;
s->count -= i;
- if (!s->count)
+ if (!s->count)
s->state = done;
return s->count;
default:
boot->state = imagehdr; /* override CH detection */
while (omap3_boot_block(data, j, boot))
i = omap3_read_fat_cluster(data, &drv, i);
+ result = (boot->state == done);
free(boot);
- result = 1;
} else
fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
__FUNCTION__);
{
struct omap3_boot_s *boot;
uint32_t i = 0;
+ int result = 0;
if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
boot = omap3_boot_init(sector, 0x200, mpu);
}
}
}
+ result = (boot->state == done);
free(boot);
}
- return 0;
+ return result;
}
/* returns non-zero if successful, zero if unsuccessful */
return result;
}
+/* returns non-zero if successful, zero if unsuccessful */
+int omap3_nand_boot(struct omap_mpu_state_s *mpu,
+ struct nand_flash_s *nand,
+ void (*nand_pread_f)(struct nand_flash_s *nand,
+ uint64_t address,
+ uint8_t *data,
+ uint32_t len))
+{
+ struct omap3_boot_s *boot;
+ uint8_t *data;
+ uint64_t addr = 0;
+ int result = 0;
+
+ data = qemu_mallocz(0x1000);
+ nand_pread_f(nand, 0, data, 0x1000);
+ boot = omap3_boot_init(data, 0x1000, mpu);
+ while (omap3_boot_block(data, 0x1000, boot)) {
+ addr += 0x1000;
+ nand_pread_f(nand, addr, data, 0x1000);
+ }
+ result = (boot->state == done);
+ free(boot);
+ free(data);
+ return result;
+}
? "complete"
: "aborted --> complete");
host->stat_pending |= 0x2; /* TC */
+ if (host->cmd & 0x04) { /* ACEN */
+ host->stop = 0x0cc30000;
+ state = aborted;
+ }
if (state == aborted) {
host->cmd = host->stop;
host->stop = 0;
break;
case 0x02c: /* MMCHS_CON */
TRACE2("CON = %08x", value);
- if (value & 0x10) {
- fprintf(stderr, "%s: SYSTEST mode is not supported\n", __FUNCTION__);
- exit(-1);
- }
- if (value & 0x20) {
- fprintf(stderr, "%s: 8-bit data width is not supported\n", __FUNCTION__);
- exit(-1);
- }
+ if (value & 0x10) /* MODE */
+ fprintf(stderr, "%s: SYSTEST mode is not supported\n",
+ __FUNCTION__);
+ if (value & 0x20) /* DW8 */
+ fprintf(stderr, "%s: 8-bit data width is not supported\n",
+ __FUNCTION__);
+ if (value & 0x1000) /* CEATA */
+ fprintf(stderr, "%s: CE-ATA control mode not supported\n",
+ __FUNCTION__);
s->con = value & 0x1ffff;
break;
case 0x030:
break;
case 0x10c: /* MMCHS_CMD */
TRACE2("CMD = %08x", value);
- /* TODO: writing to bits 0-15 should have no effect during
- an active data transfer */
- if (value & 4) { /* ACEN */
- fprintf(stderr, "%s: AutoCMD12 not supported!\n", __FUNCTION__);
- exit(-1);
- }
- if (!s->stop
- && (((value >> 24) & 0x3f) == 12 || ((value >> 24) & 0x3f) == 52)) {
- s->stop = value & 0x3ffb0037;
+ if (!s->card) {
+ s->stat_pending |= (1 << 16); /* CTO */
} else {
- s->cmd = value & 0x3ffb0037;
- omap3_mmc_command(s);
+ /* TODO: writing to bits 0-15 should have no effect during
+ an active data transfer */
+ if (!s->stop
+ && (((value >> 24) & 0x3f) == 12
+ || ((value >> 24) & 0x3f) == 52)) {
+ s->stop = value & 0x3ffb0037;
+ } else {
+ s->cmd = value & 0x3ffb0037;
+ omap3_mmc_command(s);
+ }
+ omap3_mmc_transfer(s);
+ omap3_mmc_fifolevel_update(s);
}
- omap3_mmc_transfer(s);
- omap3_mmc_fifolevel_update(s);
omap3_mmc_interrupts_update(s);
break;
case 0x120:
omap3_mmc_write,
};
-static void omap3_mmc_enable(struct omap3_mmc_s *s, int enable)
-{
- sd_enable(s->card, enable);
-}
-
struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
- BlockDriverState * bd, qemu_irq irq,
- qemu_irq dma[], omap_clk fclk, omap_clk iclk)
+ qemu_irq irq, qemu_irq dma[],
+ omap_clk fclk, omap_clk iclk)
{
int iomemtype;
struct omap3_mmc_s *s = (struct omap3_mmc_s *)
omap3_mmc_writefn, s);
omap_l4_attach(ta, 0, iomemtype);
- /* Instantiate the storage */
- if (bd!=NULL) {
- s->card = sd_init(bd, 0);
- omap3_mmc_enable(s,1);
- }
-
return s;
}
+
+void omap3_mmc_attach(struct omap3_mmc_s *s,
+ BlockDriverState *bd)
+{
+ if (s->card) {
+ fprintf(stderr, "%s: SD card already attached!\n", __FUNCTION__);
+ exit(-1);
+ }
+ s->card = sd_init(bd, 0);
+ sd_enable(s->card, 1);
+}
sd_rsp_type_t rtype;
int rsplen;
- if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) {
+ if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) {
return 0;
}