qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c


From: Benoit Canet
Subject: [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c
Date: Wed, 3 Jun 2009 11:34:41 +0200

From: Benoit canet <address@hidden>


Signed-off-by: Benoit Canet <address@hidden>
---
 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]