Commit f34c417ba63cd379ad7e1953bc3f520454601e27
1 parent
66450b15
Add OMAP Pulse-width Tone module.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3513 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
103 additions
and
0 deletions
hw/omap.c
@@ -3509,6 +3509,100 @@ static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | @@ -3509,6 +3509,100 @@ static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | ||
3509 | omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); | 3509 | omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); |
3510 | } | 3510 | } |
3511 | 3511 | ||
3512 | +/* Pulse-Width Tone module */ | ||
3513 | +static uint32_t omap_pwt_read(void *opaque, target_phys_addr_t addr) | ||
3514 | +{ | ||
3515 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | ||
3516 | + int offset = addr - s->pwt.base; | ||
3517 | + | ||
3518 | + switch (offset) { | ||
3519 | + case 0x00: /* FRC */ | ||
3520 | + return s->pwt.frc; | ||
3521 | + case 0x04: /* VCR */ | ||
3522 | + return s->pwt.vrc; | ||
3523 | + case 0x08: /* GCR */ | ||
3524 | + return s->pwt.gcr; | ||
3525 | + } | ||
3526 | + OMAP_BAD_REG(addr); | ||
3527 | + return 0; | ||
3528 | +} | ||
3529 | + | ||
3530 | +static void omap_pwt_write(void *opaque, target_phys_addr_t addr, | ||
3531 | + uint32_t value) | ||
3532 | +{ | ||
3533 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | ||
3534 | + int offset = addr - s->pwt.base; | ||
3535 | + | ||
3536 | + switch (offset) { | ||
3537 | + case 0x00: /* FRC */ | ||
3538 | + s->pwt.frc = value & 0x3f; | ||
3539 | + break; | ||
3540 | + case 0x04: /* VRC */ | ||
3541 | + if ((value ^ s->pwt.vrc) & 1) { | ||
3542 | + if (value & 1) | ||
3543 | + printf("%s: %iHz buzz on\n", __FUNCTION__, (int) | ||
3544 | + /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */ | ||
3545 | + ((omap_clk_getrate(s->pwt.clk) >> 3) / | ||
3546 | + /* Pre-multiplexer divider */ | ||
3547 | + ((s->pwt.gcr & 2) ? 1 : 154) / | ||
3548 | + /* Octave multiplexer */ | ||
3549 | + (2 << (value & 3)) * | ||
3550 | + /* 101/107 divider */ | ||
3551 | + ((value & (1 << 2)) ? 101 : 107) * | ||
3552 | + /* 49/55 divider */ | ||
3553 | + ((value & (1 << 3)) ? 49 : 55) * | ||
3554 | + /* 50/63 divider */ | ||
3555 | + ((value & (1 << 4)) ? 50 : 63) * | ||
3556 | + /* 80/127 divider */ | ||
3557 | + ((value & (1 << 5)) ? 80 : 127) / | ||
3558 | + (107 * 55 * 63 * 127))); | ||
3559 | + else | ||
3560 | + printf("%s: silence!\n", __FUNCTION__); | ||
3561 | + } | ||
3562 | + s->pwt.vrc = value & 0x7f; | ||
3563 | + break; | ||
3564 | + case 0x08: /* GCR */ | ||
3565 | + s->pwt.gcr = value & 3; | ||
3566 | + break; | ||
3567 | + default: | ||
3568 | + OMAP_BAD_REG(addr); | ||
3569 | + return; | ||
3570 | + } | ||
3571 | +} | ||
3572 | + | ||
3573 | +static CPUReadMemoryFunc *omap_pwt_readfn[] = { | ||
3574 | + omap_badwidth_read8, | ||
3575 | + omap_badwidth_read8, | ||
3576 | + omap_pwt_read, | ||
3577 | +}; | ||
3578 | + | ||
3579 | +static CPUWriteMemoryFunc *omap_pwt_writefn[] = { | ||
3580 | + omap_badwidth_write8, | ||
3581 | + omap_badwidth_write8, | ||
3582 | + omap_pwt_write, | ||
3583 | +}; | ||
3584 | + | ||
3585 | +void omap_pwt_reset(struct omap_mpu_state_s *s) | ||
3586 | +{ | ||
3587 | + s->pwt.frc = 0; | ||
3588 | + s->pwt.vrc = 0; | ||
3589 | + s->pwt.gcr = 0; | ||
3590 | +} | ||
3591 | + | ||
3592 | +static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | ||
3593 | + omap_clk clk) | ||
3594 | +{ | ||
3595 | + int iomemtype; | ||
3596 | + | ||
3597 | + s->pwt.base = base; | ||
3598 | + s->pwt.clk = clk; | ||
3599 | + omap_pwt_reset(s); | ||
3600 | + | ||
3601 | + iomemtype = cpu_register_io_memory(0, omap_pwt_readfn, | ||
3602 | + omap_pwt_writefn, s); | ||
3603 | + cpu_register_physical_memory(s->pwt.base, 0x800, iomemtype); | ||
3604 | +} | ||
3605 | + | ||
3512 | /* General chip reset */ | 3606 | /* General chip reset */ |
3513 | static void omap_mpu_reset(void *opaque) | 3607 | static void omap_mpu_reset(void *opaque) |
3514 | { | 3608 | { |
@@ -3662,6 +3756,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -3662,6 +3756,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
3662 | s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); | 3756 | s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); |
3663 | 3757 | ||
3664 | omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); | 3758 | omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); |
3759 | + omap_pwt_init(0xfffb6000, s, omap_findclk(s, "xtal_osc_12m")); | ||
3665 | 3760 | ||
3666 | qemu_register_reset(omap_mpu_reset, s); | 3761 | qemu_register_reset(omap_mpu_reset, s); |
3667 | 3762 |
hw/omap.h
@@ -542,6 +542,14 @@ struct omap_mpu_state_s { | @@ -542,6 +542,14 @@ struct omap_mpu_state_s { | ||
542 | int clk; | 542 | int clk; |
543 | } pwl; | 543 | } pwl; |
544 | 544 | ||
545 | + struct { | ||
546 | + target_phys_addr_t base; | ||
547 | + uint8_t frc; | ||
548 | + uint8_t vrc; | ||
549 | + uint8_t gcr; | ||
550 | + omap_clk clk; | ||
551 | + } pwt; | ||
552 | + | ||
545 | /* MPU private TIPB peripherals */ | 553 | /* MPU private TIPB peripherals */ |
546 | struct omap_intr_handler_s *ih[2]; | 554 | struct omap_intr_handler_s *ih[2]; |
547 | 555 |