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 | ... | ... |