qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] ARM Versatile I2C support
@ 2009-06-03  9:34 Benoit Canet
  2009-06-03  9:34 ` [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c Benoit Canet
  2009-06-03 11:44 ` [Qemu-devel] ARM Versatile I2C support Paul Brook
  0 siblings, 2 replies; 4+ messages in thread
From: Benoit Canet @ 2009-06-03  9:34 UTC (permalink / raw)
  To: qemu-devel


These two patches implements the ARM Versatile I2C support.
The first one extract the I2C bitbanging code from the musicpal board.
The second implement the versatile I2C hardware.

    Benoit

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c
  2009-06-03  9:34 [Qemu-devel] ARM Versatile I2C support Benoit Canet
@ 2009-06-03  9:34 ` Benoit Canet
  2009-06-03  9:34   ` [Qemu-devel] [PATCH 2/2] Add ARM versatile I2C emulation Benoit Canet
  2009-06-03 11:44 ` [Qemu-devel] ARM Versatile I2C support Paul Brook
  1 sibling, 1 reply; 4+ messages in thread
From: Benoit Canet @ 2009-06-03  9:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Benoit canet

From: Benoit canet <benoit.canet@gmail.com>


Signed-off-by: Benoit Canet <benoit.canet@gmail.com>
---
 Makefile.target  |    2 +-
 hw/bitbang_i2c.c |   99 ++++++++++++++++++++++++++++++++++++++
 hw/bitbang_i2c.h |   50 +++++++++++++++++++
 hw/musicpal.c    |  138 +++--------------------------------------------------
 4 files changed, 158 insertions(+), 131 deletions(-)
 create mode 100644 hw/bitbang_i2c.c
 create mode 100644 hw/bitbang_i2c.h

diff --git a/Makefile.target b/Makefile.target
index 445d55f..d049a73 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -670,7 +670,7 @@ OBJS+= omap2.o omap_dss.o soc_dma.o
 OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
-OBJS+= musicpal.o pflash_cfi02.o
+OBJS+= musicpal.o pflash_cfi02.o bitbang_i2c.o
 OBJS+= framebuffer.o
 OBJS+= syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
 OBJS+= syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
new file mode 100644
index 0000000..4ab500c
--- /dev/null
+++ b/hw/bitbang_i2c.c
@@ -0,0 +1,99 @@
+/*
+ * Bit-Bang i2c emulation extracted from
+ * Marvell MV88W8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008 Jan Kiszka
+ *
+ * This code is licenced under the GNU GPL v2.
+ */
+#include "bitbang_i2c.h"
+
+static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
+{
+    if (i2c->current_addr >= 0)
+        i2c_end_transfer(i2c->bus);
+    i2c->current_addr = -1;
+    i2c->state = STOPPED;
+}
+
+void bitbang_i2c_state_update(bitbang_i2c_interface *i2c, int data, int clock)
+{
+    if (!i2c)
+        return;
+
+    switch (i2c->state) {
+    case STOPPED:
+        if (data == 0 && i2c->last_data == 1 && clock == 1)
+            i2c->state = INITIALIZING;
+        break;
+
+    case INITIALIZING:
+        if (clock == 0 && i2c->last_clock == 1 && data == 0)
+            i2c->state = SENDING_BIT7;
+        else
+            bitbang_i2c_enter_stop(i2c);
+        break;
+
+    case SENDING_BIT7 ... SENDING_BIT0:
+        if (clock == 0 && i2c->last_clock == 1) {
+            i2c->buffer = (i2c->buffer << 1) | data;
+            i2c->state++; /* will end up in WAITING_FOR_ACK */
+        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
+            bitbang_i2c_enter_stop(i2c);
+        break;
+
+    case WAITING_FOR_ACK:
+        if (clock == 0 && i2c->last_clock == 1) {
+            if (i2c->current_addr < 0) {
+                i2c->current_addr = i2c->buffer;
+                i2c_start_transfer(i2c->bus, i2c->current_addr & 0xfe,
+                                   i2c->buffer & 1);
+            } else
+                i2c_send(i2c->bus, i2c->buffer);
+            if (i2c->current_addr & 1) {
+                i2c->state = RECEIVING_BIT7;
+                i2c->buffer = i2c_recv(i2c->bus);
+            } else
+                i2c->state = SENDING_BIT7;
+        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
+            bitbang_i2c_enter_stop(i2c);
+        break;
+
+    case RECEIVING_BIT7 ... RECEIVING_BIT0:
+        if (clock == 0 && i2c->last_clock == 1) {
+            i2c->state++; /* will end up in SENDING_ACK */
+            i2c->buffer <<= 1;
+        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
+            bitbang_i2c_enter_stop(i2c);
+        break;
+
+    case SENDING_ACK:
+        if (clock == 0 && i2c->last_clock == 1) {
+            i2c->state = RECEIVING_BIT7;
+            if (data == 0)
+                i2c->buffer = i2c_recv(i2c->bus);
+            else
+                i2c_nack(i2c->bus);
+        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
+            bitbang_i2c_enter_stop(i2c);
+        break;
+    }
+
+    i2c->last_data = data;
+    i2c->last_clock = clock;
+}
+
+int bitbang_i2c_get_data(bitbang_i2c_interface *i2c)
+{
+    if (!i2c)
+        return 0;
+
+    switch (i2c->state) {
+    case RECEIVING_BIT7 ... RECEIVING_BIT0:
+        return (i2c->buffer >> 7);
+
+    case WAITING_FOR_ACK:
+    default:
+        return 0;
+    }
+}
diff --git a/hw/bitbang_i2c.h b/hw/bitbang_i2c.h
new file mode 100644
index 0000000..322dc40
--- /dev/null
+++ b/hw/bitbang_i2c.h
@@ -0,0 +1,50 @@
+/*
+ * Bit-Bang i2c emulation extracted from
+ * Marvell MV88W8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008 Jan Kiszka
+ *
+ * This code is licenced under the GNU GPL v2.
+ */
+#ifndef BITBANG_I2C_H
+#define BITBANG_I2C_H
+
+#include "hw.h"
+#include "i2c.h"
+
+typedef enum bitbang_i2c_state {
+    STOPPED = 0,
+    INITIALIZING,
+    SENDING_BIT7,
+    SENDING_BIT6,
+    SENDING_BIT5,
+    SENDING_BIT4,
+    SENDING_BIT3,
+    SENDING_BIT2,
+    SENDING_BIT1,
+    SENDING_BIT0,
+    WAITING_FOR_ACK,
+    RECEIVING_BIT7,
+    RECEIVING_BIT6,
+    RECEIVING_BIT5,
+    RECEIVING_BIT4,
+    RECEIVING_BIT3,
+    RECEIVING_BIT2,
+    RECEIVING_BIT1,
+    RECEIVING_BIT0,
+    SENDING_ACK
+} bitbang_i2c_state;
+
+typedef struct bitbang_i2c_interface {
+    i2c_bus *bus;
+    bitbang_i2c_state state;
+    int last_data;
+    int last_clock;
+    uint8_t buffer;
+    int current_addr;
+} bitbang_i2c_interface;
+
+void bitbang_i2c_state_update(bitbang_i2c_interface *i2c, int data, int clock);
+int bitbang_i2c_get_data(bitbang_i2c_interface *i2c);
+
+#endif
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 9389af9..dc496c9 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -18,7 +18,7 @@
 #include "flash.h"
 #include "console.h"
 #include "audio/audio.h"
-#include "i2c.h"
+#include "bitbang_i2c.h"
 
 #define MP_MISC_BASE            0x80002000
 #define MP_MISC_SIZE            0x00001000
@@ -73,129 +73,7 @@ static uint32_t gpio_isr;
 static uint32_t gpio_out_state;
 static ram_addr_t sram_off;
 
-typedef enum i2c_state {
-    STOPPED = 0,
-    INITIALIZING,
-    SENDING_BIT7,
-    SENDING_BIT6,
-    SENDING_BIT5,
-    SENDING_BIT4,
-    SENDING_BIT3,
-    SENDING_BIT2,
-    SENDING_BIT1,
-    SENDING_BIT0,
-    WAITING_FOR_ACK,
-    RECEIVING_BIT7,
-    RECEIVING_BIT6,
-    RECEIVING_BIT5,
-    RECEIVING_BIT4,
-    RECEIVING_BIT3,
-    RECEIVING_BIT2,
-    RECEIVING_BIT1,
-    RECEIVING_BIT0,
-    SENDING_ACK
-} i2c_state;
-
-typedef struct i2c_interface {
-    i2c_bus *bus;
-    i2c_state state;
-    int last_data;
-    int last_clock;
-    uint8_t buffer;
-    int current_addr;
-} i2c_interface;
-
-static void i2c_enter_stop(i2c_interface *i2c)
-{
-    if (i2c->current_addr >= 0)
-        i2c_end_transfer(i2c->bus);
-    i2c->current_addr = -1;
-    i2c->state = STOPPED;
-}
-
-static void i2c_state_update(i2c_interface *i2c, int data, int clock)
-{
-    if (!i2c)
-        return;
-
-    switch (i2c->state) {
-    case STOPPED:
-        if (data == 0 && i2c->last_data == 1 && clock == 1)
-            i2c->state = INITIALIZING;
-        break;
-
-    case INITIALIZING:
-        if (clock == 0 && i2c->last_clock == 1 && data == 0)
-            i2c->state = SENDING_BIT7;
-        else
-            i2c_enter_stop(i2c);
-        break;
-
-    case SENDING_BIT7 ... SENDING_BIT0:
-        if (clock == 0 && i2c->last_clock == 1) {
-            i2c->buffer = (i2c->buffer << 1) | data;
-            i2c->state++; /* will end up in WAITING_FOR_ACK */
-        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
-            i2c_enter_stop(i2c);
-        break;
-
-    case WAITING_FOR_ACK:
-        if (clock == 0 && i2c->last_clock == 1) {
-            if (i2c->current_addr < 0) {
-                i2c->current_addr = i2c->buffer;
-                i2c_start_transfer(i2c->bus, i2c->current_addr & 0xfe,
-                                   i2c->buffer & 1);
-            } else
-                i2c_send(i2c->bus, i2c->buffer);
-            if (i2c->current_addr & 1) {
-                i2c->state = RECEIVING_BIT7;
-                i2c->buffer = i2c_recv(i2c->bus);
-            } else
-                i2c->state = SENDING_BIT7;
-        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
-            i2c_enter_stop(i2c);
-        break;
-
-    case RECEIVING_BIT7 ... RECEIVING_BIT0:
-        if (clock == 0 && i2c->last_clock == 1) {
-            i2c->state++; /* will end up in SENDING_ACK */
-            i2c->buffer <<= 1;
-        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
-            i2c_enter_stop(i2c);
-        break;
-
-    case SENDING_ACK:
-        if (clock == 0 && i2c->last_clock == 1) {
-            i2c->state = RECEIVING_BIT7;
-            if (data == 0)
-                i2c->buffer = i2c_recv(i2c->bus);
-            else
-                i2c_nack(i2c->bus);
-        } else if (data == 1 && i2c->last_data == 0 && clock == 1)
-            i2c_enter_stop(i2c);
-        break;
-    }
-
-    i2c->last_data = data;
-    i2c->last_clock = clock;
-}
-
-static int i2c_get_data(i2c_interface *i2c)
-{
-    if (!i2c)
-        return 0;
-
-    switch (i2c->state) {
-    case RECEIVING_BIT7 ... RECEIVING_BIT0:
-        return (i2c->buffer >> 7);
-
-    case WAITING_FOR_ACK:
-    default:
-        return 0;
-    }
-}
-
-static i2c_interface *mixer_i2c;
+static bitbang_i2c_interface *mixer_i2c;
 
 #ifdef HAS_AUDIO
 
@@ -421,16 +299,16 @@ static CPUWriteMemoryFunc *musicpal_audio_writefn[] = {
     musicpal_audio_write
 };
 
-static i2c_interface *musicpal_audio_init(qemu_irq irq)
+static bitbang_i2c_interface *musicpal_audio_init(qemu_irq irq)
 {
     musicpal_audio_state *s;
-    i2c_interface *i2c;
+    bitbang_i2c_interface *i2c;
     int iomemtype;
 
     s = qemu_mallocz(sizeof(musicpal_audio_state));
     s->irq = irq;
 
-    i2c = qemu_mallocz(sizeof(i2c_interface));
+    i2c = qemu_mallocz(sizeof(bitbang_i2c_interface));
     i2c->bus = i2c_init_bus(NULL, "i2c");
     i2c->current_addr = -1;
 
@@ -446,7 +324,7 @@ static i2c_interface *musicpal_audio_init(qemu_irq irq)
     return i2c;
 }
 #else  /* !HAS_AUDIO */
-static i2c_interface *musicpal_audio_init(qemu_irq irq)
+static bitbang_i2c_interface *musicpal_audio_init(qemu_irq irq)
 {
     return NULL;
 }
@@ -1358,7 +1236,7 @@ static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset)
     case MP_GPIO_IN_HI:
         /* Update received I2C data */
         gpio_in_state = (gpio_in_state & ~MP_GPIO_I2C_DATA) |
-                        (i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT);
+                        (bitbang_i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT);
         return gpio_in_state >> 16;
 
     case MP_GPIO_ISR_LO:
@@ -1387,7 +1265,7 @@ static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset,
         gpio_out_state = (gpio_out_state & 0xFFFF) | (value << 16);
         lcd_brightness = (lcd_brightness & 0xFFFF) |
                          (gpio_out_state & MP_GPIO_LCD_BRIGHTNESS);
-        i2c_state_update(mixer_i2c,
+        bitbang_i2c_state_update(mixer_i2c,
                          (gpio_out_state >> MP_GPIO_I2C_DATA_BIT) & 1,
                          (gpio_out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
         break;
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 2/2] Add ARM versatile I2C emulation
  2009-06-03  9:34 ` [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c Benoit Canet
@ 2009-06-03  9:34   ` Benoit Canet
  0 siblings, 0 replies; 4+ messages in thread
From: Benoit Canet @ 2009-06-03  9:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Benoit canet

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4561 bytes --]

From: Benoit canet <benoit.canet@gmail.com>


Signed-off-by: Benoit Canet <benoit.canet@gmail.com>
---
 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 <benoit.canet@gmail.com>
+ *
+ * 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 <benoit.canet@gmail.com>
+ *
+ * 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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] ARM Versatile I2C support
  2009-06-03  9:34 [Qemu-devel] ARM Versatile I2C support Benoit Canet
  2009-06-03  9:34 ` [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c Benoit Canet
@ 2009-06-03 11:44 ` Paul Brook
  1 sibling, 0 replies; 4+ messages in thread
From: Paul Brook @ 2009-06-03 11:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Benoit Canet

On Wednesday 03 June 2009, Benoit Canet wrote:
> These two patches implements the ARM Versatile I2C support.
> The first one extract the I2C bitbanging code from the musicpal board.
> The second implement the versatile I2C hardware.

Could you convert this to the new device API? I'm reluctant to add new devices 
using the old API.

Paul

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-06-03 11:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-03  9:34 [Qemu-devel] ARM Versatile I2C support Benoit Canet
2009-06-03  9:34 ` [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c Benoit Canet
2009-06-03  9:34   ` [Qemu-devel] [PATCH 2/2] Add ARM versatile I2C emulation Benoit Canet
2009-06-03 11:44 ` [Qemu-devel] ARM Versatile I2C support Paul Brook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).