From 66450b1596fddd03204b54cc4f9fb99fb928c857 Mon Sep 17 00:00:00 2001 From: balrog Date: Sat, 3 Nov 2007 00:46:16 +0000 Subject: [PATCH] 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 --- hw/omap.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- hw/omap.h | 11 ++++++ 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/hw/omap.c b/hw/omap.c index d6978d8..a8e00de 100644 --- a/hw/omap.c +++ b/hw/omap.c @@ -22,6 +22,18 @@ #include "arm_pic.h" /* Should signal the TCMI */ +uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) +{ + OMAP_8B_REG(addr); + return 0; +} + +void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + OMAP_8B_REG(addr); +} + uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) { OMAP_16B_REG(addr); @@ -3140,9 +3152,8 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr, return; case 0x04: /* DATA_OUTPUT */ - diff = s->outputs ^ (value & ~s->dir); + diff = (s->outputs ^ value) & ~s->dir; s->outputs = value; - value &= ~s->dir; while ((ln = ffs(diff))) { ln --; if (s->handler[ln]) @@ -3369,7 +3380,7 @@ static CPUWriteMemoryFunc *omap_uwire_writefn[] = { void omap_uwire_reset(struct omap_uwire_s *s) { - s->control= 0; + s->control = 0; s->setup[0] = 0; s->setup[1] = 0; s->setup[2] = 0; @@ -3407,6 +3418,97 @@ void omap_uwire_attach(struct omap_uwire_s *s, s->chip[chipselect] = slave; } +/* Pseudonoise Pulse-Width Light Modulator */ +void omap_pwl_update(struct omap_mpu_state_s *s) +{ + int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0; + + if (output != s->pwl.output) { + s->pwl.output = output; + printf("%s: Backlight now at %i/256\n", __FUNCTION__, output); + } +} + +static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr) +{ + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + int offset = addr - s->pwl.base; + + switch (offset) { + case 0x00: /* PWL_LEVEL */ + return s->pwl.level; + case 0x04: /* PWL_CTRL */ + return s->pwl.enable; + } + OMAP_BAD_REG(addr); + return 0; +} + +static void omap_pwl_write(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + int offset = addr - s->pwl.base; + + switch (offset) { + case 0x00: /* PWL_LEVEL */ + s->pwl.level = value; + omap_pwl_update(s); + break; + case 0x04: /* PWL_CTRL */ + s->pwl.enable = value & 1; + omap_pwl_update(s); + break; + default: + OMAP_BAD_REG(addr); + return; + } +} + +static CPUReadMemoryFunc *omap_pwl_readfn[] = { + omap_badwidth_read8, + omap_badwidth_read8, + omap_pwl_read, +}; + +static CPUWriteMemoryFunc *omap_pwl_writefn[] = { + omap_badwidth_write8, + omap_badwidth_write8, + omap_pwl_write, +}; + +void omap_pwl_reset(struct omap_mpu_state_s *s) +{ + s->pwl.output = 0; + s->pwl.level = 0; + s->pwl.enable = 0; + s->pwl.clk = 1; + omap_pwl_update(s); +} + +static void omap_pwl_clk_update(void *opaque, int line, int on) +{ + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; + + s->pwl.clk = on; + omap_pwl_update(s); +} + +static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, + omap_clk clk) +{ + int iomemtype; + + s->pwl.base = base; + omap_pwl_reset(s); + + iomemtype = cpu_register_io_memory(0, omap_pwl_readfn, + omap_pwl_writefn, s); + cpu_register_physical_memory(s->pwl.base, 0x800, iomemtype); + + omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); +} + /* General chip reset */ static void omap_mpu_reset(void *opaque) { @@ -3437,6 +3539,7 @@ static void omap_mpu_reset(void *opaque) omap_mpuio_reset(mpu->mpuio); omap_gpio_reset(mpu->gpio); omap_uwire_reset(mpu->microwire); + omap_pwl_reset(mpu); cpu_reset(mpu->env); } @@ -3553,11 +3656,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, s->wakeup, omap_findclk(s, "clk32-kHz")); s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1], - omap_findclk(s, "mpuper_ck")); + omap_findclk(s, "arm_gpio_ck")); s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); + omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); + qemu_register_reset(omap_mpu_reset, s); return s; diff --git a/hw/omap.h b/hw/omap.h index e19f8ac..f819549 100644 --- a/hw/omap.h +++ b/hw/omap.h @@ -534,6 +534,14 @@ struct omap_mpu_state_s { struct omap_uwire_s *microwire; + struct { + target_phys_addr_t base; + uint8_t output; + uint8_t level; + uint8_t enable; + int clk; + } pwl; + /* MPU private TIPB peripherals */ struct omap_intr_handler_s *ih[2]; @@ -615,6 +623,9 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, # define OMAP_RO_REG(paddr) \ printf("%s: Read-only register " OMAP_FMT_plx "\n", \ __FUNCTION__, paddr) +# define OMAP_8B_REG(paddr) \ + printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ + __FUNCTION__, paddr) # define OMAP_16B_REG(paddr) \ printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ __FUNCTION__, paddr) -- 2.7.4