diff options
author | Juha Riihimäki <juha.riihimaki@nokia.com> | 2013-02-18 16:58:25 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-05-03 21:21:55 +0100 |
commit | c2df9434c043db4f828b440b11c243fcd0a9362f (patch) | |
tree | cfe483e5177b080d97322f9fba8b6cb93c9f6b5d | |
parent | f165af45bbfe51cda70a0f1d7957c371981aff01 (diff) |
hw/omap_synctimer.c: Add OMAP3 synctimer
Add the OMAP3 synctimer.
TODO: is the handling of halfword reads really correct??
-- yes, this is allowing a 32 bit counter to be read as two
16 bit reads without getting two out-of-sync parts
(the trm talks about this albeit extremely vaguely)
TODO: can we avoid using the backcompat old_mmio ?
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/timer/omap_synctimer.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c index 8e50488d1..8b6af6930 100644 --- a/hw/timer/omap_synctimer.c +++ b/hw/timer/omap_synctimer.c @@ -24,6 +24,7 @@ struct omap_synctimer_s { MemoryRegion iomem; uint32_t val; uint16_t readh; + uint32_t sysconfig; /*OMAP3*/ }; /* 32-kHz Sync Timer of the OMAP2 */ @@ -52,6 +53,14 @@ static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr) return 0; } +static uint32_t omap3_synctimer_readw(void *opaque, hwaddr addr) +{ + struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque; + return (addr == 0x04) + ? s->sysconfig + : omap_synctimer_readw(opaque, addr); +} + static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr) { struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; @@ -66,12 +75,38 @@ static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr) } } +static uint32_t omap3_synctimer_readh(void *opaque, hwaddr addr) +{ + struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque; + uint32_t ret; + + if (addr & 2) { + return s->readh; + } + + ret = omap3_synctimer_readw(opaque, addr); + s->readh = ret >> 16; + return ret & 0xffff; +} + static void omap_synctimer_write(void *opaque, hwaddr addr, uint32_t value) { OMAP_BAD_REG(addr); } + +static void omap3_synctimer_write(void *opaque, hwaddr addr, + uint32_t value) +{ + struct omap_synctimer_s *s = (struct omap_synctimer_s *)opaque; + if (addr == 0x04) { + s->sysconfig = value & 0x0c; + } else { + OMAP_BAD_REG(addr); + } +} + static const MemoryRegionOps omap_synctimer_ops = { .old_mmio = { .read = { @@ -88,14 +123,35 @@ static const MemoryRegionOps omap_synctimer_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static const MemoryRegionOps omap3_synctimer_ops = { + .old_mmio = { + .read = { + omap_badwidth_read32, + omap3_synctimer_readh, + omap3_synctimer_readw, + }, + .write = { + omap_badwidth_write32, + omap3_synctimer_write, + omap3_synctimer_write, + }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta, struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk) { struct omap_synctimer_s *s = g_malloc0(sizeof(*s)); omap_synctimer_reset(s); - memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, "omap.synctimer", - omap_l4_region_size(ta, 0)); + if (cpu_class_omap3(mpu)) { + memory_region_init_io(&s->iomem, NULL, &omap3_synctimer_ops, s, + "omap.synctimer", omap_l4_region_size(ta, 0)); + } else { + memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, + "omap.synctimer", omap_l4_region_size(ta, 0)); + } omap_l4_attach(ta, 0, &s->iomem); return s; |