From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MBmsC-0000ZU-On for qemu-devel@nongnu.org; Wed, 03 Jun 2009 05:35:04 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MBms7-0000YY-Ti for qemu-devel@nongnu.org; Wed, 03 Jun 2009 05:35:04 -0400 Received: from [199.232.76.173] (port=50555 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MBms7-0000YH-4C for qemu-devel@nongnu.org; Wed, 03 Jun 2009 05:34:59 -0400 Received: from mail-bw0-f175.google.com ([209.85.218.175]:35967) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MBms6-0001f3-B0 for qemu-devel@nongnu.org; Wed, 03 Jun 2009 05:34:58 -0400 Received: by bwz23 with SMTP id 23so7607691bwz.34 for ; Wed, 03 Jun 2009 02:34:56 -0700 (PDT) From: Benoit Canet Date: Wed, 3 Jun 2009 11:34:41 +0200 Message-Id: <1244021682-11125-2-git-send-email-benoit.canet@gmail.com> In-Reply-To: <1244021682-11125-1-git-send-email-benoit.canet@gmail.com> References: <1244021682-11125-1-git-send-email-benoit.canet@gmail.com> Subject: [Qemu-devel] [PATCH 1/2] Extract I2C bitbang GPIO code from musicpal.c List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Benoit canet From: Benoit canet Signed-off-by: Benoit Canet --- 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