From patchwork Mon Aug 10 19:01:28 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Canet X-Patchwork-Id: 31098 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id A391DB6EDE for ; Tue, 11 Aug 2009 05:08:26 +1000 (EST) Received: from localhost ([127.0.0.1]:58952 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MaaEJ-0001bo-0z for incoming@patchwork.ozlabs.org; Mon, 10 Aug 2009 15:08:23 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Maa81-00080S-RP for qemu-devel@nongnu.org; Mon, 10 Aug 2009 15:01:53 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Maa7x-0007yX-3Y for qemu-devel@nongnu.org; Mon, 10 Aug 2009 15:01:53 -0400 Received: from [199.232.76.173] (port=35297 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Maa7w-0007yI-Jq for qemu-devel@nongnu.org; Mon, 10 Aug 2009 15:01:48 -0400 Received: from mail-ew0-f210.google.com ([209.85.219.210]:56072) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Maa7v-0007FG-E8 for qemu-devel@nongnu.org; Mon, 10 Aug 2009 15:01:48 -0400 Received: by mail-ew0-f210.google.com with SMTP id 6so1391683ewy.34 for ; Mon, 10 Aug 2009 12:01:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=MGY+xpVnlw0SyvzP4/YmUWRC7ZEmB2iyNLU2gRfUh5c=; b=kEgbQs7DpwB9M90zOpNr+pUYdH7EkwSC6QgxNrN3VyP0HQcTI49lEMfjlK/n9e0gWX V+S58UMlxDMlZy7ACmC4oGAH7DkEU20zxbwoBJB3FQaChJG4/yLORbSDFm/teUUPpvUG cpp54XAK7brbeytY37eZG6P8OuMcRmQv/CCp8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=PpPiAqKDoyBDF4soUSAJ7cfEyettoiHK7gQ9epItj7DUtBGikZ6/5jXWsvuvSCgFcp S/wMGL38SgQF5pcA4nwJwlH49bCv1UD7yySMX646zZ8yTz1JIiV6NEiyc3JWxkWfy59h STz5xtkXWdwHPiA6shvEy1YBsXhWmtZOFFz+M= Received: by 10.210.131.6 with SMTP id e6mr3220016ebd.29.1249930907038; Mon, 10 Aug 2009 12:01:47 -0700 (PDT) Received: from localhost.localdomain (AMontsouris-157-1-65-87.w90-46.abo.wanadoo.fr [90.46.56.87]) by mx.google.com with ESMTPS id 24sm9194738eyx.3.2009.08.10.12.01.45 (version=SSLv3 cipher=RC4-MD5); Mon, 10 Aug 2009 12:01:46 -0700 (PDT) From: Benoit Canet To: qemu-devel@nongnu.org Date: Mon, 10 Aug 2009 21:01:28 +0200 Message-Id: <1249930888-22022-4-git-send-email-benoit.canet@gmail.com> X-Mailer: git-send-email 1.6.0.4 In-Reply-To: <1249930888-22022-3-git-send-email-benoit.canet@gmail.com> References: <1249930888-22022-1-git-send-email-benoit.canet@gmail.com> <1249930888-22022-2-git-send-email-benoit.canet@gmail.com> <1249930888-22022-3-git-send-email-benoit.canet@gmail.com> X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: Benoit Canet Subject: [Qemu-devel] [PATCH 3/3] Make musicpal.c use the generic bitbang I2C device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Benoit Canet --- hw/musicpal.c | 226 +++++++++++++++++---------------------------------------- 1 files changed, 67 insertions(+), 159 deletions(-) diff --git a/hw/musicpal.c b/hw/musicpal.c index 067c228..e36b0dc 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -70,132 +70,6 @@ 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; - -#ifdef HAS_AUDIO - /* Audio register offsets */ #define MP_AUDIO_PLAYBACK_MODE 0x00 #define MP_AUDIO_CLOCK_DIV 0x18 @@ -219,9 +93,9 @@ static i2c_interface *mixer_i2c; /* Wolfson 8750 I2C address */ #define MP_WM_ADDR 0x34 -static const char audio_name[] = "mv88w8618"; - +#ifdef HAS_AUDIO typedef struct musicpal_audio_state { + SysBusDevice busdev; qemu_irq irq; uint32_t playback_mode; uint32_t status; @@ -235,7 +109,7 @@ typedef struct musicpal_audio_state { DeviceState *wm; } musicpal_audio_state; -static void audio_callback(void *opaque, int free_out, int free_in) +static void musicpal_audio_callback(void *opaque, int free_out, int free_in) { musicpal_audio_state *s = opaque; int16_t *codec_buffer; @@ -418,36 +292,36 @@ static CPUWriteMemoryFunc *musicpal_audio_writefn[] = { musicpal_audio_write }; -static i2c_interface *musicpal_audio_init(qemu_irq irq) +static void musicpal_audio_init(SysBusDevice *dev) { - musicpal_audio_state *s; - i2c_interface *i2c; + musicpal_audio_state *s = FROM_SYSBUS(musicpal_audio_state, dev); int iomemtype; - s = qemu_mallocz(sizeof(musicpal_audio_state)); - s->irq = irq; - - i2c = qemu_mallocz(sizeof(i2c_interface)); - i2c->bus = i2c_init_bus(NULL, "i2c"); - i2c->current_addr = -1; + sysbus_init_irq(dev, &s->irq); - s->wm = i2c_create_slave(i2c->bus, "wm8750", MP_WM_ADDR); - wm8750_data_req_set(s->wm, audio_callback, s); + wm8750_data_req_set(s->wm, musicpal_audio_callback, s); iomemtype = cpu_register_io_memory(musicpal_audio_readfn, - musicpal_audio_writefn, s); - cpu_register_physical_memory(MP_AUDIO_BASE, MP_AUDIO_SIZE, iomemtype); + musicpal_audio_writefn, s); + sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype); qemu_register_reset(musicpal_audio_reset, s); - - return i2c; -} -#else /* !HAS_AUDIO */ -static i2c_interface *musicpal_audio_init(qemu_irq irq) -{ - return NULL; } -#endif /* !HAS_AUDIO */ + +static SysBusDeviceInfo musicpal_audio_info = { + .init = musicpal_audio_init, + .qdev.name = "musicpal_audio", + .qdev.size = sizeof(musicpal_audio_state), + .qdev.props = (Property[]) { + { + .name = "wm8750", + .info = &qdev_prop_ptr, + .offset = offsetof(musicpal_audio_state, wm), + }, + {/* end of list */} + } +}; +#endif /* Ethernet register offsets */ #define MP_ETH_SMIR 0x010 @@ -1327,10 +1201,11 @@ typedef struct musicpal_gpio_state { uint32_t out_state; uint32_t in_state; uint32_t isr; + uint32_t i2c_read_data; uint32_t key_released; uint32_t keys_event; /* store the received key event */ qemu_irq irq; - qemu_irq out[3]; + qemu_irq out[5]; } musicpal_gpio_state; static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) { @@ -1400,6 +1275,10 @@ static void musicpal_gpio_irq(void *opaque, int irq, int level) { musicpal_gpio_state *s = (musicpal_gpio_state *) opaque; + if (irq == 10) { + s->i2c_read_data = level; + } + /* receives keys bits */ if (irq <= 7) { s->keys_event &= ~(1 << irq); @@ -1436,7 +1315,7 @@ static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset) case MP_GPIO_IN_HI: /* Update received I2C data */ s->in_state = (s->in_state & ~MP_GPIO_I2C_DATA) | - (i2c_get_data(mixer_i2c) << MP_GPIO_I2C_DATA_BIT); + (s->i2c_read_data << MP_GPIO_I2C_DATA_BIT); return s->in_state >> 16; case MP_GPIO_ISR_LO: @@ -1468,9 +1347,8 @@ static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset, s->lcd_brightness = (s->lcd_brightness & 0xFFFF) | (s->out_state & MP_GPIO_LCD_BRIGHTNESS); musicpal_gpio_brightness_update(s); - i2c_state_update(mixer_i2c, - (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1, - (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1); + qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1); + qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1); break; } @@ -1491,6 +1369,7 @@ static CPUWriteMemoryFunc *musicpal_gpio_writefn[] = { static void musicpal_gpio_reset(musicpal_gpio_state *s) { s->in_state = 0xffffffff; + s->i2c_read_data = 1; s->key_released = 0; s->keys_event = 0; s->isr = 0; @@ -1509,8 +1388,10 @@ static void musicpal_gpio_init(SysBusDevice *dev) musicpal_gpio_reset(s); - qdev_init_gpio_out(&dev->qdev, s->out, 3); - qdev_init_gpio_in(&dev->qdev, musicpal_gpio_irq, 10); + /* 3 brightness out + 2 lcd (data and clock ) */ + qdev_init_gpio_out(&dev->qdev, s->out, 5); + /* 10 gpio button input + 1 I2C data input */ + qdev_init_gpio_in(&dev->qdev, musicpal_gpio_irq, 11); } /* Keyboard codes & masks */ @@ -1647,8 +1528,14 @@ static void musicpal_init(ram_addr_t ram_size, qemu_irq *cpu_pic; qemu_irq pic[32]; DeviceState *dev; + DeviceState *i2c_dev; DeviceState *lcd_dev; DeviceState *key_dev; +#ifdef HAS_AUDIO + DeviceState *wm8750_dev; + SysBusDevice *s; +#endif + i2c_bus *i2c; int i; int index; unsigned long flash_size; @@ -1717,22 +1604,40 @@ static void musicpal_init(ram_addr_t ram_size, sysbus_mmio_map(sysbus_from_qdev(dev), 0, MP_ETH_BASE); sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[MP_ETH_IRQ]); - mixer_i2c = musicpal_audio_init(pic[MP_AUDIO_IRQ]); - sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL); musicpal_misc_init(); dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]); + i2c_dev = sysbus_create_simple("bitbang_i2c", 0, NULL); + i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c"); + lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL); key_dev = sysbus_create_simple("musicpal_key", 0, NULL); + /* I2C read data */ + qdev_connect_gpio_out(i2c_dev, 0, qdev_get_gpio_in(dev, 10)); + /* I2C data */ + qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0)); + /* I2C clock */ + qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1)); + for (i = 0; i < 3; i++) qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i)); for (i = 0; i < 10; i++) qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i)); +#ifdef HAS_AUDIO + wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR); + dev = qdev_create(NULL, "musicpal_audio"); + s = sysbus_from_qdev(dev); + qdev_prop_set_ptr(dev, "wm8750", wm8750_dev); + qdev_init(dev); + sysbus_mmio_map(s, 0, MP_AUDIO_BASE); + sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]); +#endif + musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE; musicpal_binfo.kernel_filename = kernel_filename; musicpal_binfo.kernel_cmdline = kernel_cmdline; @@ -1771,6 +1676,9 @@ static void musicpal_register_devices(void) musicpal_gpio_init); sysbus_register_dev("musicpal_key", sizeof(musicpal_key_state), musicpal_key_init); +#ifdef HAS_AUDIO + sysbus_register_withprop(&musicpal_audio_info); +#endif } device_init(musicpal_register_devices)