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