Commit f9d43072e25715911b3ef7594132e4f87ead8ba0

Authored by balrog
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  
... ...