[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/2] Add ARM versatile I2C emulation
From: |
Benoit Canet |
Subject: |
[Qemu-devel] [PATCH 2/2] Add ARM versatile I2C emulation |
Date: |
Wed, 3 Jun 2009 11:34:42 +0200 |
From: Benoit canet <address@hidden>
Signed-off-by: Benoit Canet <address@hidden>
---
Makefile.target | 1 +
hw/versatile_i2c.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/versatile_i2c.h | 15 +++++++++
hw/versatilepb.c | 5 +++
4 files changed, 109 insertions(+), 0 deletions(-)
create mode 100644 hw/versatile_i2c.c
create mode 100644 hw/versatile_i2c.h
diff --git a/Makefile.target b/Makefile.target
index d049a73..fa7efed 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -657,6 +657,7 @@ ifeq ($(TARGET_BASE_ARCH), arm)
OBJS+= integratorcp.o versatilepb.o smc91c111.o arm_pic.o arm_timer.o
OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
OBJS+= versatile_pci.o
+OBJS+= versatile_i2c.o
OBJS+= realview_gic.o realview.o arm_sysctl.o mpcore.o
OBJS+= armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
OBJS+= pl061.o
diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c
new file mode 100644
index 0000000..c905562
--- /dev/null
+++ b/hw/versatile_i2c.c
@@ -0,0 +1,88 @@
+/*
+ * Arm versatile i2c interface
+ *
+ * Copyright (c) 2009 Benoît Canet
+ * Benoît Canet <address@hidden>
+ *
+ * This code is licenced under the GPL.
+ */
+#include "hw.h"
+#include "smbus.h"
+#include "i2c.h"
+#include "bitbang_i2c.h"
+#include "versatile_i2c.h"
+
+#define I2C_CONTROL 0x0
+#define I2C_CONTROLS 0x0
+#define I2C_CONTROLC 0x4
+
+#define DATA 1<<1
+#define CLOCK 1
+
+static uint32_t versatile_i2c_read(void *opaque, target_phys_addr_t offset)
+{
+ bitbang_i2c_interface *i2c = (bitbang_i2c_interface *) opaque;
+
+ switch (offset) {
+ case I2C_CONTROL:
+ return (bitbang_i2c_get_data(i2c) << 1) | i2c->last_clock;
+ default:
+ hw_error("versatile_i2c_read: Bad offset %x\n", (int)offset);
+ return 0;
+ }
+}
+
+static void versatile_i2c_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ bitbang_i2c_interface *i2c = (bitbang_i2c_interface *) opaque;
+ int data = i2c->last_data;
+ int clock = i2c->last_clock;
+
+ switch (offset) {
+ case I2C_CONTROLS:
+ if (value & DATA)
+ data = 1;
+ if (value & CLOCK)
+ clock = 1;
+ break;
+ case I2C_CONTROLC:
+ if (value & DATA)
+ data = 0;
+ if (value & CLOCK)
+ clock = 0;
+ break;
+ default:
+ hw_error("versatile_i2c_write: Bad offset %x\n", (int)offset);
+ }
+
+ bitbang_i2c_state_update(i2c, data, clock);
+}
+
+static CPUReadMemoryFunc *versatile_i2c_readfn[] = {
+ versatile_i2c_read,
+ versatile_i2c_read,
+ versatile_i2c_read
+};
+
+static CPUWriteMemoryFunc *versatile_i2c_writefn[] = {
+ versatile_i2c_write,
+ versatile_i2c_write,
+ versatile_i2c_write
+};
+
+i2c_bus *versatile_i2c_init(uint32_t base)
+{
+ int iomemtype;
+ bitbang_i2c_interface *i2c;
+
+ i2c = qemu_mallocz(sizeof(bitbang_i2c_interface));
+ i2c->bus = i2c_init_bus(NULL, "i2c");
+ i2c->current_addr = -1;
+
+ iomemtype = cpu_register_io_memory(0, versatile_i2c_readfn,
+ versatile_i2c_writefn, i2c);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
+
+ return i2c->bus;
+}
diff --git a/hw/versatile_i2c.h b/hw/versatile_i2c.h
new file mode 100644
index 0000000..41f8a01
--- /dev/null
+++ b/hw/versatile_i2c.h
@@ -0,0 +1,15 @@
+/*
+ * Arm versatile i2c interface
+ *
+ * Copyright (c) 2009 Benoît Canet
+ * Benoît Canet <address@hidden>
+ *
+ * This code is licenced under the GPL.
+ */
+#ifndef I2C_VERSATILE_H
+#define I2C_VERSATILE_H
+#include "i2c.h"
+
+i2c_bus *versatile_i2c_init(uint32_t base);
+
+#endif
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 03cf4d8..4f924be 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -9,6 +9,8 @@
#include "sysbus.h"
#include "arm-misc.h"
+#include "i2c.h"
+#include "versatile_i2c.h"
#include "primecell.h"
#include "devices.h"
#include "net.h"
@@ -170,6 +172,7 @@ static void versatile_init(ram_addr_t ram_size,
NICInfo *nd;
int n;
int done_smc = 0;
+ i2c_bus *i2c;
if (!cpu_model)
cpu_model = "arm926";
@@ -224,6 +227,8 @@ static void versatile_init(ram_addr_t ram_size,
n--;
}
+ i2c = versatile_i2c_init(0x10002000);
+
sysbus_create_simple("pl011", 0x101f1000, pic[12]);
sysbus_create_simple("pl011", 0x101f2000, pic[13]);
sysbus_create_simple("pl011", 0x101f3000, pic[14]);
--
1.5.6.3