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,6 +4626,184 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave) | ||
4626 | slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0]; | 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 | /* General chip reset */ | 4807 | /* General chip reset */ |
4630 | static void omap_mpu_reset(void *opaque) | 4808 | static void omap_mpu_reset(void *opaque) |
4631 | { | 4809 | { |
@@ -4663,6 +4841,8 @@ static void omap_mpu_reset(void *opaque) | @@ -4663,6 +4841,8 @@ static void omap_mpu_reset(void *opaque) | ||
4663 | omap_mcbsp_reset(mpu->mcbsp1); | 4841 | omap_mcbsp_reset(mpu->mcbsp1); |
4664 | omap_mcbsp_reset(mpu->mcbsp2); | 4842 | omap_mcbsp_reset(mpu->mcbsp2); |
4665 | omap_mcbsp_reset(mpu->mcbsp3); | 4843 | omap_mcbsp_reset(mpu->mcbsp3); |
4844 | + omap_lpg_reset(mpu->led[0]); | ||
4845 | + omap_lpg_reset(mpu->led[1]); | ||
4666 | cpu_reset(mpu->env); | 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,6 +5026,9 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4846 | s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX], | 5026 | s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX], |
4847 | &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck")); | 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 | /* Register mappings not currenlty implemented: | 5032 | /* Register mappings not currenlty implemented: |
4850 | * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310) | 5033 | * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310) |
4851 | * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310) | 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,8 +5038,6 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4855 | * FAC fffba800 - fffbafff | 5038 | * FAC fffba800 - fffbafff |
4856 | * HDQ/1-Wire fffbc000 - fffbc7ff | 5039 | * HDQ/1-Wire fffbc000 - fffbc7ff |
4857 | * TIPB switches fffbc800 - fffbcfff | 5040 | * TIPB switches fffbc800 - fffbcfff |
4858 | - * LED1 fffbd000 - fffbd7ff | ||
4859 | - * LED2 fffbd800 - fffbdfff | ||
4860 | * Mailbox fffcf000 - fffcf7ff | 5041 | * Mailbox fffcf000 - fffcf7ff |
4861 | * Local bus IF fffec100 - fffec1ff | 5042 | * Local bus IF fffec100 - fffec1ff |
4862 | * Local bus MMU fffec200 - fffec2ff | 5043 | * Local bus MMU fffec200 - fffec2ff |
@@ -4864,6 +5045,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -4864,6 +5045,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4864 | */ | 5045 | */ |
4865 | 5046 | ||
4866 | omap_setup_dsp_mapping(omap15xx_dsp_mm); | 5047 | omap_setup_dsp_mapping(omap15xx_dsp_mm); |
5048 | + omap_setup_mpui_io(s); | ||
4867 | 5049 | ||
4868 | qemu_register_reset(omap_mpu_reset, s); | 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,6 +508,9 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, | ||
508 | qemu_irq *irq, qemu_irq *dma, omap_clk clk); | 508 | qemu_irq *irq, qemu_irq *dma, omap_clk clk); |
509 | void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave); | 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 | /* omap_lcdc.c */ | 514 | /* omap_lcdc.c */ |
512 | struct omap_lcd_panel_s; | 515 | struct omap_lcd_panel_s; |
513 | void omap_lcdc_reset(struct omap_lcd_panel_s *s); | 516 | void omap_lcdc_reset(struct omap_lcd_panel_s *s); |
@@ -598,6 +601,8 @@ struct omap_mpu_state_s { | @@ -598,6 +601,8 @@ struct omap_mpu_state_s { | ||
598 | 601 | ||
599 | struct omap_mcbsp_s *mcbsp2; | 602 | struct omap_mcbsp_s *mcbsp2; |
600 | 603 | ||
604 | + struct omap_lpg_s *led[2]; | ||
605 | + | ||
601 | /* MPU private TIPB peripherals */ | 606 | /* MPU private TIPB peripherals */ |
602 | struct omap_intr_handler_s *ih[2]; | 607 | struct omap_intr_handler_s *ih[2]; |
603 | 608 |