Implement OMAP MicroWire controller.

Fix GPIO interrupt number.
Reorder a couple of variables.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3477 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
balrog 2007-10-29 01:50:05 +00:00
parent 1b6fd0bc55
commit d951f6ff3f
3 changed files with 200 additions and 16 deletions

188
hw/omap.c
View file

@ -3101,7 +3101,6 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
{
struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
int offset = addr - s->base;
uint16_t ret;
switch (offset) {
case 0x00: /* DATA_INPUT */
@ -3238,6 +3237,175 @@ void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
s->handler[line] = handler;
}
/* MicroWire Interface */
struct omap_uwire_s {
target_phys_addr_t base;
qemu_irq txirq;
qemu_irq rxirq;
qemu_irq txdrq;
uint16_t txbuf;
uint16_t rxbuf;
uint16_t control;
uint16_t setup[5];
struct uwire_slave_s *chip[4];
};
static void omap_uwire_transfer_start(struct omap_uwire_s *s)
{
int chipselect = (s->control >> 10) & 3; /* INDEX */
struct uwire_slave_s *slave = s->chip[chipselect];
if ((s->control >> 5) & 0x1f) { /* NB_BITS_WR */
if (s->control & (1 << 12)) /* CS_CMD */
if (slave && slave->send)
slave->send(slave->opaque,
s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
s->control &= ~(1 << 14); /* CSRB */
/* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
* a DRQ. When is the level IRQ supposed to be reset? */
}
if ((s->control >> 0) & 0x1f) { /* NB_BITS_RD */
if (s->control & (1 << 12)) /* CS_CMD */
if (slave && slave->receive)
s->rxbuf = slave->receive(slave->opaque);
s->control |= 1 << 15; /* RDRB */
/* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
* a DRQ. When is the level IRQ supposed to be reset? */
}
}
static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
{
struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
int offset = addr - s->base;
switch (offset) {
case 0x00: /* RDR */
s->control &= ~(1 << 15); /* RDRB */
return s->rxbuf;
case 0x04: /* CSR */
return s->control;
case 0x08: /* SR1 */
return s->setup[0];
case 0x0c: /* SR2 */
return s->setup[1];
case 0x10: /* SR3 */
return s->setup[2];
case 0x14: /* SR4 */
return s->setup[3];
case 0x18: /* SR5 */
return s->setup[4];
}
OMAP_BAD_REG(addr);
return 0;
}
static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
int offset = addr - s->base;
switch (offset) {
case 0x00: /* TDR */
s->txbuf = value; /* TD */
s->control |= 1 << 14; /* CSRB */
if ((s->setup[4] & (1 << 2)) && /* AUTO_TX_EN */
((s->setup[4] & (1 << 3)) || /* CS_TOGGLE_TX_EN */
(s->control & (1 << 12)))) /* CS_CMD */
omap_uwire_transfer_start(s);
break;
case 0x04: /* CSR */
s->control = value & 0x1fff;
if (value & (1 << 13)) /* START */
omap_uwire_transfer_start(s);
break;
case 0x08: /* SR1 */
s->setup[0] = value & 0x003f;
break;
case 0x0c: /* SR2 */
s->setup[1] = value & 0x0fc0;
break;
case 0x10: /* SR3 */
s->setup[2] = value & 0x0003;
break;
case 0x14: /* SR4 */
s->setup[3] = value & 0x0001;
break;
case 0x18: /* SR5 */
s->setup[4] = value & 0x000f;
break;
default:
OMAP_BAD_REG(addr);
return;
}
}
static CPUReadMemoryFunc *omap_uwire_readfn[] = {
omap_badwidth_read16,
omap_uwire_read,
omap_badwidth_read16,
};
static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
omap_badwidth_write16,
omap_uwire_write,
omap_badwidth_write16,
};
void omap_uwire_reset(struct omap_uwire_s *s)
{
s->control= 0;
s->setup[0] = 0;
s->setup[1] = 0;
s->setup[2] = 0;
s->setup[3] = 0;
s->setup[4] = 0;
}
struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
qemu_irq *irq, qemu_irq dma, omap_clk clk)
{
int iomemtype;
struct omap_uwire_s *s = (struct omap_uwire_s *)
qemu_mallocz(sizeof(struct omap_uwire_s));
s->base = base;
s->txirq = irq[0];
s->rxirq = irq[1];
s->txdrq = dma;
omap_uwire_reset(s);
iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
omap_uwire_writefn, s);
cpu_register_physical_memory(s->base, 0x800, iomemtype);
return s;
}
void omap_uwire_attach(struct omap_uwire_s *s,
struct uwire_slave_s *slave, int chipselect)
{
if (chipselect < 0 || chipselect > 3)
cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
chipselect);
s->chip[chipselect] = slave;
}
/* General chip reset */
static void omap_mpu_reset(void *opaque)
{
@ -3261,12 +3429,13 @@ static void omap_mpu_reset(void *opaque)
omap_dpll_reset(&mpu->dpll[0]);
omap_dpll_reset(&mpu->dpll[1]);
omap_dpll_reset(&mpu->dpll[2]);
omap_uart_reset(mpu->uart1);
omap_uart_reset(mpu->uart2);
omap_uart_reset(mpu->uart3);
omap_uart_reset(mpu->uart[0]);
omap_uart_reset(mpu->uart[1]);
omap_uart_reset(mpu->uart[2]);
omap_mmc_reset(mpu->mmc);
omap_mpuio_reset(mpu->mpuio);
omap_gpio_reset(mpu->gpio);
omap_uwire_reset(mpu->microwire);
cpu_reset(mpu->env);
}
@ -3361,13 +3530,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
omap_tcmi_init(0xfffecc00, s);
s->uart1 = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
omap_findclk(s, "uart1_ck"),
serial_hds[0]);
s->uart2 = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
omap_findclk(s, "uart2_ck"),
serial_hds[0] ? serial_hds[1] : 0);
s->uart3 = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
omap_findclk(s, "uart3_ck"),
serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
@ -3382,9 +3551,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
s->wakeup, omap_findclk(s, "clk32-kHz"));
s->gpio = omap_gpio_init(0xfffcf000, s->irq[1][OMAP_INT_KEYBOARD],
s->gpio = omap_gpio_init(0xfffcf000, s->irq[0][OMAP_INT_GPIO_BANK1],
omap_findclk(s, "mpuper_ck"));
s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
qemu_register_reset(omap_mpu_reset, s);
return s;

View file

@ -464,6 +464,17 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
struct uwire_slave_s {
uint16_t (*receive)(void *opaque);
void (*send)(void *opaque, uint16_t data);
void *opaque;
};
struct omap_uwire_s;
struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
qemu_irq *irq, qemu_irq dma, omap_clk clk);
void omap_uwire_attach(struct omap_uwire_s *s,
struct uwire_slave_s *slave, int chipselect);
/* omap_lcdc.c */
struct omap_lcd_panel_s;
void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@ -510,16 +521,19 @@ struct omap_mpu_state_s {
unsigned long sram_size;
/* MPUI-TIPB peripherals */
struct omap_uart_s *uart3;
struct omap_uart_s *uart[3];
struct omap_gpio_s *gpio;
/* MPU public TIPB peripherals */
struct omap_32khz_timer_s *os_timer;
struct omap_uart_s *uart1;
struct omap_uart_s *uart2;
struct omap_mmc_s *mmc;
struct omap_mpuio_s *mpuio;
struct omap_uwire_s *microwire;
/* MPU private TIPB peripherals */
struct omap_intr_handler_s *ih[2];
@ -578,9 +592,6 @@ struct omap_mpu_state_s {
uint16_t dsp_idlect2;
uint16_t dsp_rstct2;
} clkm;
struct omap_mpuio_s *mpuio;
struct omap_gpio_s *gpio;
} *omap310_mpu_init(unsigned long sdram_size,
DisplayState *ds, const char *core);

View file

@ -37,7 +37,8 @@ static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
}
static void static_write(void *opaque, target_phys_addr_t offset,
uint32_t value) {
uint32_t value)
{
#ifdef SPY
printf("%s: value %08lx written at " PA_FMT "\n",
__FUNCTION__, value, offset);