Commit 66450b1596fddd03204b54cc4f9fb99fb928c857

Authored by balrog
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,6 +22,18 @@
22 #include "arm_pic.h" 22 #include "arm_pic.h"
23 23
24 /* Should signal the TCMI */ 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 uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) 37 uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr)
26 { 38 {
27 OMAP_16B_REG(addr); 39 OMAP_16B_REG(addr);
@@ -3140,9 +3152,8 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr, @@ -3140,9 +3152,8 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3140 return; 3152 return;
3141 3153
3142 case 0x04: /* DATA_OUTPUT */ 3154 case 0x04: /* DATA_OUTPUT */
3143 - diff = s->outputs ^ (value & ~s->dir); 3155 + diff = (s->outputs ^ value) & ~s->dir;
3144 s->outputs = value; 3156 s->outputs = value;
3145 - value &= ~s->dir;  
3146 while ((ln = ffs(diff))) { 3157 while ((ln = ffs(diff))) {
3147 ln --; 3158 ln --;
3148 if (s->handler[ln]) 3159 if (s->handler[ln])
@@ -3369,7 +3380,7 @@ static CPUWriteMemoryFunc *omap_uwire_writefn[] = { @@ -3369,7 +3380,7 @@ static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
3369 3380
3370 void omap_uwire_reset(struct omap_uwire_s *s) 3381 void omap_uwire_reset(struct omap_uwire_s *s)
3371 { 3382 {
3372 - s->control= 0; 3383 + s->control = 0;
3373 s->setup[0] = 0; 3384 s->setup[0] = 0;
3374 s->setup[1] = 0; 3385 s->setup[1] = 0;
3375 s->setup[2] = 0; 3386 s->setup[2] = 0;
@@ -3407,6 +3418,97 @@ void omap_uwire_attach(struct omap_uwire_s *s, @@ -3407,6 +3418,97 @@ void omap_uwire_attach(struct omap_uwire_s *s,
3407 s->chip[chipselect] = slave; 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 /* General chip reset */ 3512 /* General chip reset */
3411 static void omap_mpu_reset(void *opaque) 3513 static void omap_mpu_reset(void *opaque)
3412 { 3514 {
@@ -3437,6 +3539,7 @@ static void omap_mpu_reset(void *opaque) @@ -3437,6 +3539,7 @@ static void omap_mpu_reset(void *opaque)
3437 omap_mpuio_reset(mpu->mpuio); 3539 omap_mpuio_reset(mpu->mpuio);
3438 omap_gpio_reset(mpu->gpio); 3540 omap_gpio_reset(mpu->gpio);
3439 omap_uwire_reset(mpu->microwire); 3541 omap_uwire_reset(mpu->microwire);
  3542 + omap_pwl_reset(mpu);
3440 cpu_reset(mpu->env); 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,11 +3656,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3553 s->wakeup, omap_findclk(s, "clk32-kHz")); 3656 s->wakeup, omap_findclk(s, "clk32-kHz"));
3554 3657
3555 s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1], 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 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], 3661 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
3559 s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); 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 qemu_register_reset(omap_mpu_reset, s); 3666 qemu_register_reset(omap_mpu_reset, s);
3562 3667
3563 return s; 3668 return s;
hw/omap.h
@@ -534,6 +534,14 @@ struct omap_mpu_state_s { @@ -534,6 +534,14 @@ struct omap_mpu_state_s {
534 534
535 struct omap_uwire_s *microwire; 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 /* MPU private TIPB peripherals */ 545 /* MPU private TIPB peripherals */
538 struct omap_intr_handler_s *ih[2]; 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,6 +623,9 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
615 # define OMAP_RO_REG(paddr) \ 623 # define OMAP_RO_REG(paddr) \
616 printf("%s: Read-only register " OMAP_FMT_plx "\n", \ 624 printf("%s: Read-only register " OMAP_FMT_plx "\n", \
617 __FUNCTION__, paddr) 625 __FUNCTION__, paddr)
  626 +# define OMAP_8B_REG(paddr) \
  627 + printf("%s: 8-bit register " OMAP_FMT_plx "\n", \
  628 + __FUNCTION__, paddr)
618 # define OMAP_16B_REG(paddr) \ 629 # define OMAP_16B_REG(paddr) \
619 printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ 630 printf("%s: 16-bit register " OMAP_FMT_plx "\n", \
620 __FUNCTION__, paddr) 631 __FUNCTION__, paddr)