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 | 3101 | { |
| 3102 | 3102 | struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; |
| 3103 | 3103 | int offset = addr - s->base; |
| 3104 | - uint16_t ret; | |
| 3105 | 3104 | |
| 3106 | 3105 | switch (offset) { |
| 3107 | 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 | 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 | 3409 | /* General chip reset */ |
| 3242 | 3410 | static void omap_mpu_reset(void *opaque) |
| 3243 | 3411 | { |
| ... | ... | @@ -3261,12 +3429,13 @@ static void omap_mpu_reset(void *opaque) |
| 3261 | 3429 | omap_dpll_reset(&mpu->dpll[0]); |
| 3262 | 3430 | omap_dpll_reset(&mpu->dpll[1]); |
| 3263 | 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 | 3435 | omap_mmc_reset(mpu->mmc); |
| 3268 | 3436 | omap_mpuio_reset(mpu->mpuio); |
| 3269 | 3437 | omap_gpio_reset(mpu->gpio); |
| 3438 | + omap_uwire_reset(mpu->microwire); | |
| 3270 | 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 | 3530 | |
| 3362 | 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 | 3534 | omap_findclk(s, "uart1_ck"), |
| 3366 | 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 | 3537 | omap_findclk(s, "uart2_ck"), |
| 3369 | 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 | 3540 | omap_findclk(s, "uart3_ck"), |
| 3372 | 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 | 3551 | s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO], |
| 3383 | 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 | 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 | 3560 | qemu_register_reset(omap_mpu_reset, s); |
| 3389 | 3561 | |
| 3390 | 3562 | return s; | ... | ... |
hw/omap.h
| ... | ... | @@ -464,6 +464,17 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base, |
| 464 | 464 | qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s); |
| 465 | 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 | 478 | /* omap_lcdc.c */ |
| 468 | 479 | struct omap_lcd_panel_s; |
| 469 | 480 | void omap_lcdc_reset(struct omap_lcd_panel_s *s); |
| ... | ... | @@ -510,16 +521,19 @@ struct omap_mpu_state_s { |
| 510 | 521 | unsigned long sram_size; |
| 511 | 522 | |
| 512 | 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 | 528 | /* MPU public TIPB peripherals */ |
| 516 | 529 | struct omap_32khz_timer_s *os_timer; |
| 517 | 530 | |
| 518 | - struct omap_uart_s *uart1; | |
| 519 | - struct omap_uart_s *uart2; | |
| 520 | - | |
| 521 | 531 | struct omap_mmc_s *mmc; |
| 522 | 532 | |
| 533 | + struct omap_mpuio_s *mpuio; | |
| 534 | + | |
| 535 | + struct omap_uwire_s *microwire; | |
| 536 | + | |
| 523 | 537 | /* MPU private TIPB peripherals */ |
| 524 | 538 | struct omap_intr_handler_s *ih[2]; |
| 525 | 539 | |
| ... | ... | @@ -578,9 +592,6 @@ struct omap_mpu_state_s { |
| 578 | 592 | uint16_t dsp_idlect2; |
| 579 | 593 | uint16_t dsp_rstct2; |
| 580 | 594 | } clkm; |
| 581 | - | |
| 582 | - struct omap_mpuio_s *mpuio; | |
| 583 | - struct omap_gpio_s *gpio; | |
| 584 | 595 | } *omap310_mpu_init(unsigned long sdram_size, |
| 585 | 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 | 37 | } |
| 38 | 38 | |
| 39 | 39 | static void static_write(void *opaque, target_phys_addr_t offset, |
| 40 | - uint32_t value) { | |
| 40 | + uint32_t value) | |
| 41 | +{ | |
| 41 | 42 | #ifdef SPY |
| 42 | 43 | printf("%s: value %08lx written at " PA_FMT "\n", |
| 43 | 44 | __FUNCTION__, value, offset); | ... | ... |