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); |