Commit f9d43072e25715911b3ef7594132e4f87ead8ba0
1 parent
d07b4d0e
OMAP LPGs (LED pulse generators).
OMAP MPUI bridge config register. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3710 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
189 additions
and
2 deletions
hw/omap.c
| ... | ... | @@ -4626,6 +4626,184 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave) |
| 4626 | 4626 | slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0]; |
| 4627 | 4627 | } |
| 4628 | 4628 | |
| 4629 | +/* LED Pulse Generators */ | |
| 4630 | +struct omap_lpg_s { | |
| 4631 | + target_phys_addr_t base; | |
| 4632 | + QEMUTimer *tm; | |
| 4633 | + | |
| 4634 | + uint8_t control; | |
| 4635 | + uint8_t power; | |
| 4636 | + int64_t on; | |
| 4637 | + int64_t period; | |
| 4638 | + int clk; | |
| 4639 | + int cycle; | |
| 4640 | +}; | |
| 4641 | + | |
| 4642 | +static void omap_lpg_tick(void *opaque) | |
| 4643 | +{ | |
| 4644 | + struct omap_lpg_s *s = opaque; | |
| 4645 | + | |
| 4646 | + if (s->cycle) | |
| 4647 | + qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->period - s->on); | |
| 4648 | + else | |
| 4649 | + qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->on); | |
| 4650 | + | |
| 4651 | + s->cycle = !s->cycle; | |
| 4652 | + printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off"); | |
| 4653 | +} | |
| 4654 | + | |
| 4655 | +static void omap_lpg_update(struct omap_lpg_s *s) | |
| 4656 | +{ | |
| 4657 | + int64_t on, period = 1, ticks = 1000; | |
| 4658 | + static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 }; | |
| 4659 | + | |
| 4660 | + if (~s->control & (1 << 6)) /* LPGRES */ | |
| 4661 | + on = 0; | |
| 4662 | + else if (s->control & (1 << 7)) /* PERM_ON */ | |
| 4663 | + on = period; | |
| 4664 | + else { | |
| 4665 | + period = muldiv64(ticks, per[s->control & 7], /* PERCTRL */ | |
| 4666 | + 256 / 32); | |
| 4667 | + on = (s->clk && s->power) ? muldiv64(ticks, | |
| 4668 | + per[(s->control >> 3) & 7], 256) : 0; /* ONCTRL */ | |
| 4669 | + } | |
| 4670 | + | |
| 4671 | + qemu_del_timer(s->tm); | |
| 4672 | + if (on == period && s->on < s->period) | |
| 4673 | + printf("%s: LED is on\n", __FUNCTION__); | |
| 4674 | + else if (on == 0 && s->on) | |
| 4675 | + printf("%s: LED is off\n", __FUNCTION__); | |
| 4676 | + else if (on && (on != s->on || period != s->period)) { | |
| 4677 | + s->cycle = 0; | |
| 4678 | + s->on = on; | |
| 4679 | + s->period = period; | |
| 4680 | + omap_lpg_tick(s); | |
| 4681 | + return; | |
| 4682 | + } | |
| 4683 | + | |
| 4684 | + s->on = on; | |
| 4685 | + s->period = period; | |
| 4686 | +} | |
| 4687 | + | |
| 4688 | +static void omap_lpg_reset(struct omap_lpg_s *s) | |
| 4689 | +{ | |
| 4690 | + s->control = 0x00; | |
| 4691 | + s->power = 0x00; | |
| 4692 | + s->clk = 1; | |
| 4693 | + omap_lpg_update(s); | |
| 4694 | +} | |
| 4695 | + | |
| 4696 | +static uint32_t omap_lpg_read(void *opaque, target_phys_addr_t addr) | |
| 4697 | +{ | |
| 4698 | + struct omap_lpg_s *s = (struct omap_lpg_s *) opaque; | |
| 4699 | + int offset = addr & OMAP_MPUI_REG_MASK; | |
| 4700 | + | |
| 4701 | + switch (offset) { | |
| 4702 | + case 0x00: /* LCR */ | |
| 4703 | + return s->control; | |
| 4704 | + | |
| 4705 | + case 0x04: /* PMR */ | |
| 4706 | + return s->power; | |
| 4707 | + } | |
| 4708 | + | |
| 4709 | + OMAP_BAD_REG(addr); | |
| 4710 | + return 0; | |
| 4711 | +} | |
| 4712 | + | |
| 4713 | +static void omap_lpg_write(void *opaque, target_phys_addr_t addr, | |
| 4714 | + uint32_t value) | |
| 4715 | +{ | |
| 4716 | + struct omap_lpg_s *s = (struct omap_lpg_s *) opaque; | |
| 4717 | + int offset = addr & OMAP_MPUI_REG_MASK; | |
| 4718 | + | |
| 4719 | + switch (offset) { | |
| 4720 | + case 0x00: /* LCR */ | |
| 4721 | + if (~value & (1 << 6)) /* LPGRES */ | |
| 4722 | + omap_lpg_reset(s); | |
| 4723 | + s->control = value & 0xff; | |
| 4724 | + omap_lpg_update(s); | |
| 4725 | + return; | |
| 4726 | + | |
| 4727 | + case 0x04: /* PMR */ | |
| 4728 | + s->power = value & 0x01; | |
| 4729 | + omap_lpg_update(s); | |
| 4730 | + return; | |
| 4731 | + | |
| 4732 | + default: | |
| 4733 | + OMAP_BAD_REG(addr); | |
| 4734 | + return; | |
| 4735 | + } | |
| 4736 | +} | |
| 4737 | + | |
| 4738 | +static CPUReadMemoryFunc *omap_lpg_readfn[] = { | |
| 4739 | + omap_lpg_read, | |
| 4740 | + omap_badwidth_read8, | |
| 4741 | + omap_badwidth_read8, | |
| 4742 | +}; | |
| 4743 | + | |
| 4744 | +static CPUWriteMemoryFunc *omap_lpg_writefn[] = { | |
| 4745 | + omap_lpg_write, | |
| 4746 | + omap_badwidth_write8, | |
| 4747 | + omap_badwidth_write8, | |
| 4748 | +}; | |
| 4749 | + | |
| 4750 | +static void omap_lpg_clk_update(void *opaque, int line, int on) | |
| 4751 | +{ | |
| 4752 | + struct omap_lpg_s *s = (struct omap_lpg_s *) opaque; | |
| 4753 | + | |
| 4754 | + s->clk = on; | |
| 4755 | + omap_lpg_update(s); | |
| 4756 | +} | |
| 4757 | + | |
| 4758 | +struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk) | |
| 4759 | +{ | |
| 4760 | + int iomemtype; | |
| 4761 | + struct omap_lpg_s *s = (struct omap_lpg_s *) | |
| 4762 | + qemu_mallocz(sizeof(struct omap_lpg_s)); | |
| 4763 | + | |
| 4764 | + s->base = base; | |
| 4765 | + s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s); | |
| 4766 | + | |
| 4767 | + omap_lpg_reset(s); | |
| 4768 | + | |
| 4769 | + iomemtype = cpu_register_io_memory(0, omap_lpg_readfn, | |
| 4770 | + omap_lpg_writefn, s); | |
| 4771 | + cpu_register_physical_memory(s->base, 0x800, iomemtype); | |
| 4772 | + | |
| 4773 | + omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]); | |
| 4774 | + | |
| 4775 | + return s; | |
| 4776 | +} | |
| 4777 | + | |
| 4778 | +/* MPUI Peripheral Bridge configuration */ | |
| 4779 | +static uint32_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr) | |
| 4780 | +{ | |
| 4781 | + if (addr == OMAP_MPUI_BASE) /* CMR */ | |
| 4782 | + return 0xfe4d; | |
| 4783 | + | |
| 4784 | + OMAP_BAD_REG(addr); | |
| 4785 | + return 0; | |
| 4786 | +} | |
| 4787 | + | |
| 4788 | +static CPUReadMemoryFunc *omap_mpui_io_readfn[] = { | |
| 4789 | + omap_badwidth_read16, | |
| 4790 | + omap_mpui_io_read, | |
| 4791 | + omap_badwidth_read16, | |
| 4792 | +}; | |
| 4793 | + | |
| 4794 | +static CPUWriteMemoryFunc *omap_mpui_io_writefn[] = { | |
| 4795 | + omap_badwidth_write16, | |
| 4796 | + omap_badwidth_write16, | |
| 4797 | + omap_badwidth_write16, | |
| 4798 | +}; | |
| 4799 | + | |
| 4800 | +static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu) | |
| 4801 | +{ | |
| 4802 | + int iomemtype = cpu_register_io_memory(0, omap_mpui_io_readfn, | |
| 4803 | + omap_mpui_io_writefn, mpu); | |
| 4804 | + cpu_register_physical_memory(OMAP_MPUI_BASE, 0x7fff, iomemtype); | |
| 4805 | +} | |
| 4806 | + | |
| 4629 | 4807 | /* General chip reset */ |
| 4630 | 4808 | static void omap_mpu_reset(void *opaque) |
| 4631 | 4809 | { |
| ... | ... | @@ -4663,6 +4841,8 @@ static void omap_mpu_reset(void *opaque) |
| 4663 | 4841 | omap_mcbsp_reset(mpu->mcbsp1); |
| 4664 | 4842 | omap_mcbsp_reset(mpu->mcbsp2); |
| 4665 | 4843 | omap_mcbsp_reset(mpu->mcbsp3); |
| 4844 | + omap_lpg_reset(mpu->led[0]); | |
| 4845 | + omap_lpg_reset(mpu->led[1]); | |
| 4666 | 4846 | cpu_reset(mpu->env); |
| 4667 | 4847 | } |
| 4668 | 4848 | |
| ... | ... | @@ -4846,6 +5026,9 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, |
| 4846 | 5026 | s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX], |
| 4847 | 5027 | &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck")); |
| 4848 | 5028 | |
| 5029 | + s->led[0] = omap_lpg_init(0xfffbd000, omap_findclk(s, "clk32-kHz")); | |
| 5030 | + s->led[1] = omap_lpg_init(0xfffbd800, omap_findclk(s, "clk32-kHz")); | |
| 5031 | + | |
| 4849 | 5032 | /* Register mappings not currenlty implemented: |
| 4850 | 5033 | * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310) |
| 4851 | 5034 | * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310) |
| ... | ... | @@ -4855,8 +5038,6 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, |
| 4855 | 5038 | * FAC fffba800 - fffbafff |
| 4856 | 5039 | * HDQ/1-Wire fffbc000 - fffbc7ff |
| 4857 | 5040 | * TIPB switches fffbc800 - fffbcfff |
| 4858 | - * LED1 fffbd000 - fffbd7ff | |
| 4859 | - * LED2 fffbd800 - fffbdfff | |
| 4860 | 5041 | * Mailbox fffcf000 - fffcf7ff |
| 4861 | 5042 | * Local bus IF fffec100 - fffec1ff |
| 4862 | 5043 | * Local bus MMU fffec200 - fffec2ff |
| ... | ... | @@ -4864,6 +5045,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, |
| 4864 | 5045 | */ |
| 4865 | 5046 | |
| 4866 | 5047 | omap_setup_dsp_mapping(omap15xx_dsp_mm); |
| 5048 | + omap_setup_mpui_io(s); | |
| 4867 | 5049 | |
| 4868 | 5050 | qemu_register_reset(omap_mpu_reset, s); |
| 4869 | 5051 | ... | ... |
hw/omap.h
| ... | ... | @@ -508,6 +508,9 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, |
| 508 | 508 | qemu_irq *irq, qemu_irq *dma, omap_clk clk); |
| 509 | 509 | void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave); |
| 510 | 510 | |
| 511 | +struct omap_lpg_s; | |
| 512 | +struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk); | |
| 513 | + | |
| 511 | 514 | /* omap_lcdc.c */ |
| 512 | 515 | struct omap_lcd_panel_s; |
| 513 | 516 | void omap_lcdc_reset(struct omap_lcd_panel_s *s); |
| ... | ... | @@ -598,6 +601,8 @@ struct omap_mpu_state_s { |
| 598 | 601 | |
| 599 | 602 | struct omap_mcbsp_s *mcbsp2; |
| 600 | 603 | |
| 604 | + struct omap_lpg_s *led[2]; | |
| 605 | + | |
| 601 | 606 | /* MPU private TIPB peripherals */ |
| 602 | 607 | struct omap_intr_handler_s *ih[2]; |
| 603 | 608 | ... | ... |