Commit d951f6ff3fff1121e8b20e7655cb88b2601b61e6
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
Showing
3 changed files
with
200 additions
and
16 deletions
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); |