aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Riihimäki <juha.riihimaki@nokia.com>2013-02-18 16:58:25 +0000
committerPeter Maydell <peter.maydell@linaro.org>2015-05-03 21:21:55 +0100
commitc2df9434c043db4f828b440b11c243fcd0a9362f (patch)
treecfe483e5177b080d97322f9fba8b6cb93c9f6b5d
parentf165af45bbfe51cda70a0f1d7957c371981aff01 (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.c60
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;