Commit 66450b1596fddd03204b54cc4f9fb99fb928c857
1 parent
7fc42b4b
Implement OMAP PWL (backlight) module.
Fix GPIO clock name and output level change notifications. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3512 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
120 additions
and
4 deletions
hw/omap.c
| ... | ... | @@ -22,6 +22,18 @@ |
| 22 | 22 | #include "arm_pic.h" |
| 23 | 23 | |
| 24 | 24 | /* Should signal the TCMI */ |
| 25 | +uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) | |
| 26 | +{ | |
| 27 | + OMAP_8B_REG(addr); | |
| 28 | + return 0; | |
| 29 | +} | |
| 30 | + | |
| 31 | +void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, | |
| 32 | + uint32_t value) | |
| 33 | +{ | |
| 34 | + OMAP_8B_REG(addr); | |
| 35 | +} | |
| 36 | + | |
| 25 | 37 | uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) |
| 26 | 38 | { |
| 27 | 39 | OMAP_16B_REG(addr); |
| ... | ... | @@ -3140,9 +3152,8 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr, |
| 3140 | 3152 | return; |
| 3141 | 3153 | |
| 3142 | 3154 | case 0x04: /* DATA_OUTPUT */ |
| 3143 | - diff = s->outputs ^ (value & ~s->dir); | |
| 3155 | + diff = (s->outputs ^ value) & ~s->dir; | |
| 3144 | 3156 | s->outputs = value; |
| 3145 | - value &= ~s->dir; | |
| 3146 | 3157 | while ((ln = ffs(diff))) { |
| 3147 | 3158 | ln --; |
| 3148 | 3159 | if (s->handler[ln]) |
| ... | ... | @@ -3369,7 +3380,7 @@ static CPUWriteMemoryFunc *omap_uwire_writefn[] = { |
| 3369 | 3380 | |
| 3370 | 3381 | void omap_uwire_reset(struct omap_uwire_s *s) |
| 3371 | 3382 | { |
| 3372 | - s->control= 0; | |
| 3383 | + s->control = 0; | |
| 3373 | 3384 | s->setup[0] = 0; |
| 3374 | 3385 | s->setup[1] = 0; |
| 3375 | 3386 | s->setup[2] = 0; |
| ... | ... | @@ -3407,6 +3418,97 @@ void omap_uwire_attach(struct omap_uwire_s *s, |
| 3407 | 3418 | s->chip[chipselect] = slave; |
| 3408 | 3419 | } |
| 3409 | 3420 | |
| 3421 | +/* Pseudonoise Pulse-Width Light Modulator */ | |
| 3422 | +void omap_pwl_update(struct omap_mpu_state_s *s) | |
| 3423 | +{ | |
| 3424 | + int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0; | |
| 3425 | + | |
| 3426 | + if (output != s->pwl.output) { | |
| 3427 | + s->pwl.output = output; | |
| 3428 | + printf("%s: Backlight now at %i/256\n", __FUNCTION__, output); | |
| 3429 | + } | |
| 3430 | +} | |
| 3431 | + | |
| 3432 | +static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr) | |
| 3433 | +{ | |
| 3434 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
| 3435 | + int offset = addr - s->pwl.base; | |
| 3436 | + | |
| 3437 | + switch (offset) { | |
| 3438 | + case 0x00: /* PWL_LEVEL */ | |
| 3439 | + return s->pwl.level; | |
| 3440 | + case 0x04: /* PWL_CTRL */ | |
| 3441 | + return s->pwl.enable; | |
| 3442 | + } | |
| 3443 | + OMAP_BAD_REG(addr); | |
| 3444 | + return 0; | |
| 3445 | +} | |
| 3446 | + | |
| 3447 | +static void omap_pwl_write(void *opaque, target_phys_addr_t addr, | |
| 3448 | + uint32_t value) | |
| 3449 | +{ | |
| 3450 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
| 3451 | + int offset = addr - s->pwl.base; | |
| 3452 | + | |
| 3453 | + switch (offset) { | |
| 3454 | + case 0x00: /* PWL_LEVEL */ | |
| 3455 | + s->pwl.level = value; | |
| 3456 | + omap_pwl_update(s); | |
| 3457 | + break; | |
| 3458 | + case 0x04: /* PWL_CTRL */ | |
| 3459 | + s->pwl.enable = value & 1; | |
| 3460 | + omap_pwl_update(s); | |
| 3461 | + break; | |
| 3462 | + default: | |
| 3463 | + OMAP_BAD_REG(addr); | |
| 3464 | + return; | |
| 3465 | + } | |
| 3466 | +} | |
| 3467 | + | |
| 3468 | +static CPUReadMemoryFunc *omap_pwl_readfn[] = { | |
| 3469 | + omap_badwidth_read8, | |
| 3470 | + omap_badwidth_read8, | |
| 3471 | + omap_pwl_read, | |
| 3472 | +}; | |
| 3473 | + | |
| 3474 | +static CPUWriteMemoryFunc *omap_pwl_writefn[] = { | |
| 3475 | + omap_badwidth_write8, | |
| 3476 | + omap_badwidth_write8, | |
| 3477 | + omap_pwl_write, | |
| 3478 | +}; | |
| 3479 | + | |
| 3480 | +void omap_pwl_reset(struct omap_mpu_state_s *s) | |
| 3481 | +{ | |
| 3482 | + s->pwl.output = 0; | |
| 3483 | + s->pwl.level = 0; | |
| 3484 | + s->pwl.enable = 0; | |
| 3485 | + s->pwl.clk = 1; | |
| 3486 | + omap_pwl_update(s); | |
| 3487 | +} | |
| 3488 | + | |
| 3489 | +static void omap_pwl_clk_update(void *opaque, int line, int on) | |
| 3490 | +{ | |
| 3491 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
| 3492 | + | |
| 3493 | + s->pwl.clk = on; | |
| 3494 | + omap_pwl_update(s); | |
| 3495 | +} | |
| 3496 | + | |
| 3497 | +static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | |
| 3498 | + omap_clk clk) | |
| 3499 | +{ | |
| 3500 | + int iomemtype; | |
| 3501 | + | |
| 3502 | + s->pwl.base = base; | |
| 3503 | + omap_pwl_reset(s); | |
| 3504 | + | |
| 3505 | + iomemtype = cpu_register_io_memory(0, omap_pwl_readfn, | |
| 3506 | + omap_pwl_writefn, s); | |
| 3507 | + cpu_register_physical_memory(s->pwl.base, 0x800, iomemtype); | |
| 3508 | + | |
| 3509 | + omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); | |
| 3510 | +} | |
| 3511 | + | |
| 3410 | 3512 | /* General chip reset */ |
| 3411 | 3513 | static void omap_mpu_reset(void *opaque) |
| 3412 | 3514 | { |
| ... | ... | @@ -3437,6 +3539,7 @@ static void omap_mpu_reset(void *opaque) |
| 3437 | 3539 | omap_mpuio_reset(mpu->mpuio); |
| 3438 | 3540 | omap_gpio_reset(mpu->gpio); |
| 3439 | 3541 | omap_uwire_reset(mpu->microwire); |
| 3542 | + omap_pwl_reset(mpu); | |
| 3440 | 3543 | cpu_reset(mpu->env); |
| 3441 | 3544 | } |
| 3442 | 3545 | |
| ... | ... | @@ -3553,11 +3656,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, |
| 3553 | 3656 | s->wakeup, omap_findclk(s, "clk32-kHz")); |
| 3554 | 3657 | |
| 3555 | 3658 | s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1], |
| 3556 | - omap_findclk(s, "mpuper_ck")); | |
| 3659 | + omap_findclk(s, "arm_gpio_ck")); | |
| 3557 | 3660 | |
| 3558 | 3661 | s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], |
| 3559 | 3662 | s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); |
| 3560 | 3663 | |
| 3664 | + omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); | |
| 3665 | + | |
| 3561 | 3666 | qemu_register_reset(omap_mpu_reset, s); |
| 3562 | 3667 | |
| 3563 | 3668 | return s; | ... | ... |
hw/omap.h
| ... | ... | @@ -534,6 +534,14 @@ struct omap_mpu_state_s { |
| 534 | 534 | |
| 535 | 535 | struct omap_uwire_s *microwire; |
| 536 | 536 | |
| 537 | + struct { | |
| 538 | + target_phys_addr_t base; | |
| 539 | + uint8_t output; | |
| 540 | + uint8_t level; | |
| 541 | + uint8_t enable; | |
| 542 | + int clk; | |
| 543 | + } pwl; | |
| 544 | + | |
| 537 | 545 | /* MPU private TIPB peripherals */ |
| 538 | 546 | struct omap_intr_handler_s *ih[2]; |
| 539 | 547 | |
| ... | ... | @@ -615,6 +623,9 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, |
| 615 | 623 | # define OMAP_RO_REG(paddr) \ |
| 616 | 624 | printf("%s: Read-only register " OMAP_FMT_plx "\n", \ |
| 617 | 625 | __FUNCTION__, paddr) |
| 626 | +# define OMAP_8B_REG(paddr) \ | |
| 627 | + printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ | |
| 628 | + __FUNCTION__, paddr) | |
| 618 | 629 | # define OMAP_16B_REG(paddr) \ |
| 619 | 630 | printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ |
| 620 | 631 | __FUNCTION__, paddr) | ... | ... |