Commit d951f6ff3fff1121e8b20e7655cb88b2601b61e6

Authored by balrog
1 parent 1b6fd0bc

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
hw/omap.c
@@ -3101,7 +3101,6 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr) @@ -3101,7 +3101,6 @@ static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3101 { 3101 {
3102 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; 3102 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3103 int offset = addr - s->base; 3103 int offset = addr - s->base;
3104 - uint16_t ret;  
3105 3104
3106 switch (offset) { 3105 switch (offset) {
3107 case 0x00: /* DATA_INPUT */ 3106 case 0x00: /* DATA_INPUT */
@@ -3238,6 +3237,175 @@ void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler) @@ -3238,6 +3237,175 @@ void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
3238 s->handler[line] = handler; 3237 s->handler[line] = handler;
3239 } 3238 }
3240 3239
  3240 +/* MicroWire Interface */
  3241 +struct omap_uwire_s {
  3242 + target_phys_addr_t base;
  3243 + qemu_irq txirq;
  3244 + qemu_irq rxirq;
  3245 + qemu_irq txdrq;
  3246 +
  3247 + uint16_t txbuf;
  3248 + uint16_t rxbuf;
  3249 + uint16_t control;
  3250 + uint16_t setup[5];
  3251 +
  3252 + struct uwire_slave_s *chip[4];
  3253 +};
  3254 +
  3255 +static void omap_uwire_transfer_start(struct omap_uwire_s *s)
  3256 +{
  3257 + int chipselect = (s->control >> 10) & 3; /* INDEX */
  3258 + struct uwire_slave_s *slave = s->chip[chipselect];
  3259 +
  3260 + if ((s->control >> 5) & 0x1f) { /* NB_BITS_WR */
  3261 + if (s->control & (1 << 12)) /* CS_CMD */
  3262 + if (slave && slave->send)
  3263 + slave->send(slave->opaque,
  3264 + s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
  3265 + s->control &= ~(1 << 14); /* CSRB */
  3266 + /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
  3267 + * a DRQ. When is the level IRQ supposed to be reset? */
  3268 + }
  3269 +
  3270 + if ((s->control >> 0) & 0x1f) { /* NB_BITS_RD */
  3271 + if (s->control & (1 << 12)) /* CS_CMD */
  3272 + if (slave && slave->receive)
  3273 + s->rxbuf = slave->receive(slave->opaque);
  3274 + s->control |= 1 << 15; /* RDRB */
  3275 + /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
  3276 + * a DRQ. When is the level IRQ supposed to be reset? */
  3277 + }
  3278 +}
  3279 +
  3280 +static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
  3281 +{
  3282 + struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
  3283 + int offset = addr - s->base;
  3284 +
  3285 + switch (offset) {
  3286 + case 0x00: /* RDR */
  3287 + s->control &= ~(1 << 15); /* RDRB */
  3288 + return s->rxbuf;
  3289 +
  3290 + case 0x04: /* CSR */
  3291 + return s->control;
  3292 +
  3293 + case 0x08: /* SR1 */
  3294 + return s->setup[0];
  3295 + case 0x0c: /* SR2 */
  3296 + return s->setup[1];
  3297 + case 0x10: /* SR3 */
  3298 + return s->setup[2];
  3299 + case 0x14: /* SR4 */
  3300 + return s->setup[3];
  3301 + case 0x18: /* SR5 */
  3302 + return s->setup[4];
  3303 + }
  3304 +
  3305 + OMAP_BAD_REG(addr);
  3306 + return 0;
  3307 +}
  3308 +
  3309 +static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
  3310 + uint32_t value)
  3311 +{
  3312 + struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
  3313 + int offset = addr - s->base;
  3314 +
  3315 + switch (offset) {
  3316 + case 0x00: /* TDR */
  3317 + s->txbuf = value; /* TD */
  3318 + s->control |= 1 << 14; /* CSRB */
  3319 + if ((s->setup[4] & (1 << 2)) && /* AUTO_TX_EN */
  3320 + ((s->setup[4] & (1 << 3)) || /* CS_TOGGLE_TX_EN */
  3321 + (s->control & (1 << 12)))) /* CS_CMD */
  3322 + omap_uwire_transfer_start(s);
  3323 + break;
  3324 +
  3325 + case 0x04: /* CSR */
  3326 + s->control = value & 0x1fff;
  3327 + if (value & (1 << 13)) /* START */
  3328 + omap_uwire_transfer_start(s);
  3329 + break;
  3330 +
  3331 + case 0x08: /* SR1 */
  3332 + s->setup[0] = value & 0x003f;
  3333 + break;
  3334 +
  3335 + case 0x0c: /* SR2 */
  3336 + s->setup[1] = value & 0x0fc0;
  3337 + break;
  3338 +
  3339 + case 0x10: /* SR3 */
  3340 + s->setup[2] = value & 0x0003;
  3341 + break;
  3342 +
  3343 + case 0x14: /* SR4 */
  3344 + s->setup[3] = value & 0x0001;
  3345 + break;
  3346 +
  3347 + case 0x18: /* SR5 */
  3348 + s->setup[4] = value & 0x000f;
  3349 + break;
  3350 +
  3351 + default:
  3352 + OMAP_BAD_REG(addr);
  3353 + return;
  3354 + }
  3355 +}
  3356 +
  3357 +static CPUReadMemoryFunc *omap_uwire_readfn[] = {
  3358 + omap_badwidth_read16,
  3359 + omap_uwire_read,
  3360 + omap_badwidth_read16,
  3361 +};
  3362 +
  3363 +static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
  3364 + omap_badwidth_write16,
  3365 + omap_uwire_write,
  3366 + omap_badwidth_write16,
  3367 +};
  3368 +
  3369 +void omap_uwire_reset(struct omap_uwire_s *s)
  3370 +{
  3371 + s->control= 0;
  3372 + s->setup[0] = 0;
  3373 + s->setup[1] = 0;
  3374 + s->setup[2] = 0;
  3375 + s->setup[3] = 0;
  3376 + s->setup[4] = 0;
  3377 +}
  3378 +
  3379 +struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
  3380 + qemu_irq *irq, qemu_irq dma, omap_clk clk)
  3381 +{
  3382 + int iomemtype;
  3383 + struct omap_uwire_s *s = (struct omap_uwire_s *)
  3384 + qemu_mallocz(sizeof(struct omap_uwire_s));
  3385 +
  3386 + s->base = base;
  3387 + s->txirq = irq[0];
  3388 + s->rxirq = irq[1];
  3389 + s->txdrq = dma;
  3390 + omap_uwire_reset(s);
  3391 +
  3392 + iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
  3393 + omap_uwire_writefn, s);
  3394 + cpu_register_physical_memory(s->base, 0x800, iomemtype);
  3395 +
  3396 + return s;
  3397 +}
  3398 +
  3399 +void omap_uwire_attach(struct omap_uwire_s *s,
  3400 + struct uwire_slave_s *slave, int chipselect)
  3401 +{
  3402 + if (chipselect < 0 || chipselect > 3)
  3403 + cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
  3404 + chipselect);
  3405 +
  3406 + s->chip[chipselect] = slave;
  3407 +}
  3408 +
3241 /* General chip reset */ 3409 /* General chip reset */
3242 static void omap_mpu_reset(void *opaque) 3410 static void omap_mpu_reset(void *opaque)
3243 { 3411 {
@@ -3261,12 +3429,13 @@ static void omap_mpu_reset(void *opaque) @@ -3261,12 +3429,13 @@ static void omap_mpu_reset(void *opaque)
3261 omap_dpll_reset(&mpu->dpll[0]); 3429 omap_dpll_reset(&mpu->dpll[0]);
3262 omap_dpll_reset(&mpu->dpll[1]); 3430 omap_dpll_reset(&mpu->dpll[1]);
3263 omap_dpll_reset(&mpu->dpll[2]); 3431 omap_dpll_reset(&mpu->dpll[2]);
3264 - omap_uart_reset(mpu->uart1);  
3265 - omap_uart_reset(mpu->uart2);  
3266 - omap_uart_reset(mpu->uart3); 3432 + omap_uart_reset(mpu->uart[0]);
  3433 + omap_uart_reset(mpu->uart[1]);
  3434 + omap_uart_reset(mpu->uart[2]);
3267 omap_mmc_reset(mpu->mmc); 3435 omap_mmc_reset(mpu->mmc);
3268 omap_mpuio_reset(mpu->mpuio); 3436 omap_mpuio_reset(mpu->mpuio);
3269 omap_gpio_reset(mpu->gpio); 3437 omap_gpio_reset(mpu->gpio);
  3438 + omap_uwire_reset(mpu->microwire);
3270 cpu_reset(mpu->env); 3439 cpu_reset(mpu->env);
3271 } 3440 }
3272 3441
@@ -3361,13 +3530,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, @@ -3361,13 +3530,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3361 3530
3362 omap_tcmi_init(0xfffecc00, s); 3531 omap_tcmi_init(0xfffecc00, s);
3363 3532
3364 - s->uart1 = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1], 3533 + s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
3365 omap_findclk(s, "uart1_ck"), 3534 omap_findclk(s, "uart1_ck"),
3366 serial_hds[0]); 3535 serial_hds[0]);
3367 - s->uart2 = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2], 3536 + s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
3368 omap_findclk(s, "uart2_ck"), 3537 omap_findclk(s, "uart2_ck"),
3369 serial_hds[0] ? serial_hds[1] : 0); 3538 serial_hds[0] ? serial_hds[1] : 0);
3370 - s->uart3 = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3], 3539 + s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
3371 omap_findclk(s, "uart3_ck"), 3540 omap_findclk(s, "uart3_ck"),
3372 serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0); 3541 serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
3373 3542
@@ -3382,9 +3551,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, @@ -3382,9 +3551,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3382 s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO], 3551 s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
3383 s->wakeup, omap_findclk(s, "clk32-kHz")); 3552 s->wakeup, omap_findclk(s, "clk32-kHz"));
3384 3553
3385 - s->gpio = omap_gpio_init(0xfffcf000, s->irq[1][OMAP_INT_KEYBOARD], 3554 + s->gpio = omap_gpio_init(0xfffcf000, s->irq[0][OMAP_INT_GPIO_BANK1],
3386 omap_findclk(s, "mpuper_ck")); 3555 omap_findclk(s, "mpuper_ck"));
3387 3556
  3557 + s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
  3558 + s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
  3559 +
3388 qemu_register_reset(omap_mpu_reset, s); 3560 qemu_register_reset(omap_mpu_reset, s);
3389 3561
3390 return s; 3562 return s;
hw/omap.h
@@ -464,6 +464,17 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base, @@ -464,6 +464,17 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
464 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s); 464 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
465 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler); 465 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
466 466
  467 +struct uwire_slave_s {
  468 + uint16_t (*receive)(void *opaque);
  469 + void (*send)(void *opaque, uint16_t data);
  470 + void *opaque;
  471 +};
  472 +struct omap_uwire_s;
  473 +struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
  474 + qemu_irq *irq, qemu_irq dma, omap_clk clk);
  475 +void omap_uwire_attach(struct omap_uwire_s *s,
  476 + struct uwire_slave_s *slave, int chipselect);
  477 +
467 /* omap_lcdc.c */ 478 /* omap_lcdc.c */
468 struct omap_lcd_panel_s; 479 struct omap_lcd_panel_s;
469 void omap_lcdc_reset(struct omap_lcd_panel_s *s); 480 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@@ -510,16 +521,19 @@ struct omap_mpu_state_s { @@ -510,16 +521,19 @@ struct omap_mpu_state_s {
510 unsigned long sram_size; 521 unsigned long sram_size;
511 522
512 /* MPUI-TIPB peripherals */ 523 /* MPUI-TIPB peripherals */
513 - struct omap_uart_s *uart3; 524 + struct omap_uart_s *uart[3];
  525 +
  526 + struct omap_gpio_s *gpio;
514 527
515 /* MPU public TIPB peripherals */ 528 /* MPU public TIPB peripherals */
516 struct omap_32khz_timer_s *os_timer; 529 struct omap_32khz_timer_s *os_timer;
517 530
518 - struct omap_uart_s *uart1;  
519 - struct omap_uart_s *uart2;  
520 -  
521 struct omap_mmc_s *mmc; 531 struct omap_mmc_s *mmc;
522 532
  533 + struct omap_mpuio_s *mpuio;
  534 +
  535 + struct omap_uwire_s *microwire;
  536 +
523 /* MPU private TIPB peripherals */ 537 /* MPU private TIPB peripherals */
524 struct omap_intr_handler_s *ih[2]; 538 struct omap_intr_handler_s *ih[2];
525 539
@@ -578,9 +592,6 @@ struct omap_mpu_state_s { @@ -578,9 +592,6 @@ struct omap_mpu_state_s {
578 uint16_t dsp_idlect2; 592 uint16_t dsp_idlect2;
579 uint16_t dsp_rstct2; 593 uint16_t dsp_rstct2;
580 } clkm; 594 } clkm;
581 -  
582 - struct omap_mpuio_s *mpuio;  
583 - struct omap_gpio_s *gpio;  
584 } *omap310_mpu_init(unsigned long sdram_size, 595 } *omap310_mpu_init(unsigned long sdram_size,
585 DisplayState *ds, const char *core); 596 DisplayState *ds, const char *core);
586 597
hw/palm.c
@@ -37,7 +37,8 @@ static uint32_t static_readw(void *opaque, target_phys_addr_t offset) { @@ -37,7 +37,8 @@ static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
37 } 37 }
38 38
39 static void static_write(void *opaque, target_phys_addr_t offset, 39 static void static_write(void *opaque, target_phys_addr_t offset,
40 - uint32_t value) { 40 + uint32_t value)
  41 +{
41 #ifdef SPY 42 #ifdef SPY
42 printf("%s: value %08lx written at " PA_FMT "\n", 43 printf("%s: value %08lx written at " PA_FMT "\n",
43 __FUNCTION__, value, offset); 44 __FUNCTION__, value, offset);