Revision f9d43072 hw/omap.c
b/hw/omap.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 |
|
Also available in: Unified diff