qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x)
@ 2011-07-29 15:35 Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 01/15] hw/omap_l4.c: Add helper function omap_l4_region_base Peter Maydell
                   ` (14 more replies)
  0 siblings, 15 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

This pull request gathers up my recent omap patches:
 * omap-gpio qdevification
 * nand bugfixes and qdevification
 * onenand bugfixes
 * fix crash bug in n810/lm832x when key is pressed

I have omitted patch 11/12 from the nand/onenand patchset
(http://patchwork.ozlabs.org/patch/104841/
 "hw/sysbus: Add sysbus_mmio_unmap() for unmapping a region")
because it needs updating now Avi's memory API changes have landed,
and 12/12 (hw/onenand: qdevify) because that depends on 11/12.
I'll post newer versions of those next week, probably.

The following changes since commit c62f6d1d76aea587556c85b6b7b5c44167006264:

  monitor: fix build breakage with --disable-vnc (2011-07-29 09:33:56 -0500)

are available in the git repository at:
  git://git.linaro.org/people/pmaydell/qemu-arm.git omap-for-upstream

Juha Riihimäki (9):
      hw/omap_l4.c: Add helper function omap_l4_region_base
      hw/omap_gpio.c: Convert to qdev
      hw/nand: Support large NAND devices
      hw/nand: Support devices wider than 8 bits
      hw/nand: Support multiple reads following READ STATUS
      hw/nand: qdevify
      onenand: Handle various ID fields separately
      onenand: Ignore zero writes to boot command space
      hw/onenand: program actions can only clear bits

Peter Maydell (6):
      hw/omap_gpio.c: Don't complain about some writes to r/o registers
      hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module
      lm832x: Take DeviceState pointer in lm832x_key_event()
      hw/nand: Pass block device state to init function
      hw/nand: Writing to NAND can only clear bits
      onenand: Pass BlockDriverState to init function

 hw/axis_dev88.c |    8 +-
 hw/flash.h      |   17 ++--
 hw/i2c.h        |    2 +-
 hw/lm832x.c     |    4 +-
 hw/nand.c       |  345 +++++++++++++++++++++++++++++++++++--------------------
 hw/nseries.c    |   63 +++++-----
 hw/omap.h       |   22 +---
 hw/omap1.c      |   10 +-
 hw/omap2.c      |   34 ++++--
 hw/omap_clk.c   |    6 +-
 hw/omap_gpio.c  |  263 ++++++++++++++++++++++++------------------
 hw/omap_l4.c    |    6 +
 hw/onenand.c    |  183 ++++++++++++++++++++++-------
 hw/palm.c       |   26 ++--
 hw/spitz.c      |    6 +-
 hw/tc6393xb.c   |    7 +-
 16 files changed, 627 insertions(+), 375 deletions(-)

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

* [Qemu-devel] [PATCH 01/15] hw/omap_l4.c: Add helper function omap_l4_region_base
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers Peter Maydell
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Add helper function omap_l4_region_base() to return the base address
of a particular region of an L4 target agent.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/omap.h    |    2 ++
 hw/omap_l4.c |    6 ++++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/hw/omap.h b/hw/omap.h
index c227a82..00a0ea9 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -93,6 +93,8 @@ struct omap_target_agent_s *omap_l4ta_get(
     int cs);
 target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
+target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
+                                       int region);
 int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                 CPUWriteMemoryFunc * const *mem_write, void *opaque);
 
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index 4af0ca8..59c84b1 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -146,6 +146,12 @@ struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
     return bus;
 }
 
+target_phys_addr_t omap_l4_region_base(struct omap_target_agent_s *ta,
+                                       int region)
+{
+    return ta->bus->base + ta->start[region].offset;
+}
+
 static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
 {
     struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 01/15] hw/omap_l4.c: Add helper function omap_l4_region_base Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-30  4:53   ` andrzej zaborowski
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 03/15] hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module Peter Maydell
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

Don't complain about some writes to r/o OMAP2 GPIO registers, because the
kernel will do them anyway.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/omap_gpio.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 478f7d9..b53b13b 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -385,7 +385,7 @@ static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
     case 0x00:	/* GPIO_REVISION */
     case 0x14:	/* GPIO_SYSSTATUS */
     case 0x38:	/* GPIO_DATAIN */
-        OMAP_RO_REG(addr);
+        /* read-only, ignore quietly */
         break;
 
     case 0x10:	/* GPIO_SYSCONFIG */
@@ -531,7 +531,7 @@ static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
     case 0x00:	/* GPIO_REVISION */
     case 0x14:	/* GPIO_SYSSTATUS */
     case 0x38:	/* GPIO_DATAIN */
-        OMAP_RO_REG(addr);
+        /* read-only, ignore quietly */
         break;
 
     case 0x10:	/* GPIO_SYSCONFIG */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 03/15] hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 01/15] hw/omap_l4.c: Add helper function omap_l4_region_base Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 04/15] hw/omap_gpio.c: Convert to qdev Peter Maydell
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

The OMAP2430 has a fifth GPIO module which earlier OMAP2 models lack; add
the clock definition for it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/omap_clk.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/hw/omap_clk.c b/hw/omap_clk.c
index 6bcabef..577b326 100644
--- a/hw/omap_clk.c
+++ b/hw/omap_clk.c
@@ -836,7 +836,7 @@ static struct clk i2c2_iclk = {
     .parent	= &core_l4_iclk,
 };
 
-static struct clk gpio_dbclk[4] = {
+static struct clk gpio_dbclk[5] = {
     {
         .name	= "gpio1_dbclk",
         .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
@@ -853,6 +853,10 @@ static struct clk gpio_dbclk[4] = {
         .name	= "gpio4_dbclk",
         .flags	= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
         .parent	= &wu_32k_clk,
+    }, {
+        .name   = "gpio5_dbclk",
+        .flags  = CLOCK_IN_OMAP243X,
+        .parent = &wu_32k_clk,
     },
 };
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 04/15] hw/omap_gpio.c: Convert to qdev
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (2 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 03/15] hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 05/15] lm832x: Take DeviceState pointer in lm832x_key_event() Peter Maydell
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Convert the OMAP GPIO module to qdev.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/nseries.c   |   47 +++++-----
 hw/omap.h      |   20 +----
 hw/omap1.c     |   10 ++-
 hw/omap2.c     |   34 ++++++--
 hw/omap_gpio.c |  259 ++++++++++++++++++++++++++++++++-----------------------
 hw/palm.c      |   26 +++---
 6 files changed, 220 insertions(+), 176 deletions(-)

diff --git a/hw/nseries.c b/hw/nseries.c
index 2f84f53..32f2f53 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -134,9 +134,9 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
 static void n8x0_gpio_setup(struct n800_s *s)
 {
     qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
 
-    qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]);
+    qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
 }
 
 #define MAEMO_CAL_HEADER(...)				\
@@ -168,8 +168,8 @@ static void n8x0_nand_setup(struct n800_s *s)
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
                     onenand_base_unmap,
                     (s->nand = onenand_init(0xec4800, 1,
-                                            omap2_gpio_in_get(s->cpu->gpif,
-                                                    N8X0_ONENAND_GPIO)[0])));
+                                            qdev_get_gpio_in(s->cpu->gpio,
+                                                    N8X0_ONENAND_GPIO))));
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@@ -180,7 +180,7 @@ static void n8x0_nand_setup(struct n800_s *s)
 static void n8x0_i2c_setup(struct n800_s *s)
 {
     DeviceState *dev;
-    qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0];
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
 
     /* Attach the CPU on one end of our I2C bus.  */
     s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
@@ -249,8 +249,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
     /* XXX: are the three pins inverted inside the chip between the
      * tsc and the cpu (N4111)?  */
     qemu_irq penirq = NULL;	/* NC */
-    qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0];
-    qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0];
+    qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
 
     s->ts.chip = tsc2301_init(penirq, kbirq, dav);
     s->ts.opaque = s->ts.chip->opaque;
@@ -269,7 +269,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
 
 static void n810_tsc_setup(struct n800_s *s)
 {
-    qemu_irq pintdav = omap2_gpio_in_get(s->cpu->gpif, N810_TSC_TS_GPIO)[0];
+    qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
 
     s->ts.opaque = tsc2005_init(pintdav);
     s->ts.txrx = tsc2005_txrx;
@@ -361,7 +361,7 @@ static int n810_keys[0x80] = {
 
 static void n810_kbd_setup(struct n800_s *s)
 {
-    qemu_irq kbd_irq = omap2_gpio_in_get(s->cpu->gpif, N810_KEYBOARD_GPIO)[0];
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
     DeviceState *dev;
     int i;
 
@@ -726,15 +726,15 @@ static void n8x0_dss_setup(struct n800_s *s)
 
 static void n8x0_cbus_setup(struct n800_s *s)
 {
-    qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0];
-    qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0];
-    qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0];
+    qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
 
     CBus *cbus = cbus_init(dat_out);
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
 
     cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@@ -743,13 +743,12 @@ static void n8x0_cbus_setup(struct n800_s *s)
 static void n8x0_uart_setup(struct n800_s *s)
 {
     CharDriverState *radio = uart_hci_init(
-                    omap2_gpio_in_get(s->cpu->gpif,
-                            N8X0_BT_HOST_WKUP_GPIO)[0]);
+                    qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
 
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_RESET_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_reset]);
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_WKUP_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
+                          csrhci_pins_get(radio)[csrhci_pin_reset]);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
+                          csrhci_pins_get(radio)[csrhci_pin_wakeup]);
 
     omap_uart_attach(s->cpu->uart[BT_UART], radio);
 }
@@ -763,7 +762,7 @@ static void n8x0_usb_power_cb(void *opaque, int line, int level)
 
 static void n8x0_usb_setup(struct n800_s *s)
 {
-    qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0];
+    qemu_irq tusb_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO);
     qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0];
     TUSBState *tusb = tusb6010_init(tusb_irq);
 
@@ -774,7 +773,7 @@ static void n8x0_usb_setup(struct n800_s *s)
                     tusb6010_sync_io(tusb), NULL, NULL, tusb);
 
     s->usb = tusb;
-    omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
+    qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
 }
 
 /* Setup done before the main bootloader starts by some early setup code
@@ -1020,7 +1019,7 @@ static void n8x0_boot_init(void *opaque)
 
     /* If the machine has a slided keyboard, open it */
     if (s->kbd)
-        qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N810_SLIDE_GPIO)[0]);
+        qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
 }
 
 #define OMAP_TAG_NOKIA_BT	0x4e01
diff --git a/hw/omap.h b/hw/omap.h
index 00a0ea9..a064353 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -683,22 +683,6 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
 void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
 void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
 
-/* omap1 gpio module interface */
-struct omap_gpio_s;
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-void omap_gpio_reset(struct omap_gpio_s *s);
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
-
-/* omap2 gpio interface */
-struct omap_gpif_s;
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
-void omap_gpif_reset(struct omap_gpif_s *s);
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
-
 struct uWireSlave {
     uint16_t (*receive)(void *opaque);
     void (*send)(void *opaque, uint16_t data);
@@ -852,7 +836,7 @@ struct omap_mpu_state_s {
     /* MPUI-TIPB peripherals */
     struct omap_uart_s *uart[3];
 
-    struct omap_gpio_s *gpio;
+    DeviceState *gpio;
 
     struct omap_mcbsp_s *mcbsp1;
     struct omap_mcbsp_s *mcbsp3;
@@ -950,8 +934,6 @@ struct omap_mpu_state_s {
     struct omap_gpmc_s *gpmc;
     struct omap_sysctl_s *sysc;
 
-    struct omap_gpif_s *gpif;
-
     struct omap_mcspi_s *mcspi[2];
 
     struct omap_dss_s *dss;
diff --git a/hw/omap1.c b/hw/omap1.c
index 364c26f..4c3d43f 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -27,6 +27,7 @@
 #include "pc.h"
 #include "blockdev.h"
 #include "range.h"
+#include "sysbus.h"
 
 /* Should signal the TCMI/GPMC */
 uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
@@ -3585,7 +3586,6 @@ static void omap1_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
     omap_mpuio_reset(mpu->mpuio);
-    omap_gpio_reset(mpu->gpio);
     omap_uwire_reset(mpu->microwire);
     omap_pwl_reset(mpu);
     omap_pwt_reset(mpu);
@@ -3845,8 +3845,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
                     s->wakeup, omap_findclk(s, "clk32-kHz"));
 
-    s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
-                    omap_findclk(s, "arm_gpio_ck"));
+    s->gpio = qdev_create(NULL, "omap-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_init_nofail(s->gpio);
+    sysbus_connect_irq(sysbus_from_qdev(s->gpio), 0,
+                       s->irq[0][OMAP_INT_GPIO_BANK1]);
+    sysbus_mmio_map(sysbus_from_qdev(s->gpio), 0, 0xfffce000);
 
     s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
                     s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
diff --git a/hw/omap2.c b/hw/omap2.c
index 0f13272..c9b3540 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -27,6 +27,7 @@
 #include "qemu-char.h"
 #include "flash.h"
 #include "soc_dma.h"
+#include "sysbus.h"
 #include "audio/audio.h"
 
 /* Enhanced Audio Controller (CODEC only) */
@@ -2203,7 +2204,6 @@ static void omap2_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[1]);
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
-    omap_gpif_reset(mpu->gpif);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
     omap_i2c_reset(mpu->i2c[0]);
@@ -2232,9 +2232,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     ram_addr_t sram_base, q2_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
-    omap_clk gpio_clks[4];
     DriveInfo *dinfo;
     int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
 
     /* Core */
     s->mpu_model = omap2420;
@@ -2377,13 +2378,28 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "i2c2.fclk"),
                     omap_findclk(s, "i2c2.iclk"));
 
-    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
-    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
-    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
-    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
-                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
-                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = sysbus_from_qdev(s->gpio);
+    sysbus_connect_irq(busdev, 0, s->irq[0][OMAP_INT_24XX_GPIO_BANK1]);
+    sysbus_connect_irq(busdev, 3, s->irq[0][OMAP_INT_24XX_GPIO_BANK2]);
+    sysbus_connect_irq(busdev, 6, s->irq[0][OMAP_INT_24XX_GPIO_BANK3]);
+    sysbus_connect_irq(busdev, 9, s->irq[0][OMAP_INT_24XX_GPIO_BANK4]);
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
+    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
 
     s->sdrc = omap_sdrc_init(0x68009000);
     s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index b53b13b..a4280d2 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -20,10 +20,10 @@
 
 #include "hw.h"
 #include "omap.h"
-/* General-Purpose I/O */
+#include "sysbus.h"
+
 struct omap_gpio_s {
     qemu_irq irq;
-    qemu_irq *in;
     qemu_irq handler[16];
 
     uint16_t inputs;
@@ -35,9 +35,17 @@ struct omap_gpio_s {
     uint16_t pins;
 };
 
+struct omap_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *clk;
+    struct omap_gpio_s omap1;
+};
+
+/* General-Purpose I/O of OMAP1 */
 static void omap_gpio_set(void *opaque, int line, int level)
 {
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    struct omap_gpio_s *s = &((struct omap_gpif_s *)opaque)->omap1;
     uint16_t prev = s->inputs;
 
     if (level)
@@ -160,7 +168,7 @@ static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
     omap_badwidth_write16,
 };
 
-void omap_gpio_reset(struct omap_gpio_s *s)
+static void omap_gpio_reset(struct omap_gpio_s *s)
 {
     s->inputs = 0;
     s->outputs = ~0;
@@ -171,43 +179,12 @@ void omap_gpio_reset(struct omap_gpio_s *s)
     s->pins = ~0;
 }
 
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk)
-{
-    int iomemtype;
-    struct omap_gpio_s *s = (struct omap_gpio_s *)
-            qemu_mallocz(sizeof(struct omap_gpio_s));
-
-    s->irq = irq;
-    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
-    omap_gpio_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
-                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
-{
-    return s->in;
-}
-
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
-/* General-Purpose Interface of OMAP2 */
 struct omap2_gpio_s {
     qemu_irq irq[2];
     qemu_irq wkup;
-    qemu_irq *in;
-    qemu_irq handler[32];
+    qemu_irq *handler;
 
+    uint8_t revision;
     uint8_t config[2];
     uint32_t inputs;
     uint32_t outputs;
@@ -221,8 +198,21 @@ struct omap2_gpio_s {
     uint8_t delay;
 };
 
+struct omap2_gpif_s {
+    SysBusDevice busdev;
+    int mpu_model;
+    void *iclk;
+    void *fclk[6];
+    int modulecount;
+    struct omap2_gpio_s *modules;
+    qemu_irq *handler;
+    int autoidle;
+    int gpo;
+};
+
+/* General-Purpose Interface of OMAP2/3 */
 static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
-                int line)
+                                                int line)
 {
     qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 }
@@ -271,8 +261,9 @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
 
 static void omap2_gpio_module_set(void *opaque, int line, int level)
 {
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-
+    struct omap2_gpif_s *p = opaque;
+    struct omap2_gpio_s *s = &p->modules[line >> 5];
+    line &= 31;
     if (level) {
         if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
             omap2_gpio_module_int(s, line);
@@ -308,7 +299,7 @@ static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
 
     switch (addr) {
     case 0x00:	/* GPIO_REVISION */
-        return 0x18;
+        return s->revision;
 
     case 0x10:	/* GPIO_SYSCONFIG */
         return s->config[0];
@@ -583,45 +574,28 @@ static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
     omap2_gpio_module_write,
 };
 
-static void omap2_gpio_module_init(struct omap2_gpio_s *s,
-                struct omap_target_agent_s *ta, int region,
-                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
-                omap_clk fclk, omap_clk iclk)
+static void omap_gpif_reset(DeviceState *dev)
 {
-    int iomemtype;
-
-    s->irq[0] = mpu;
-    s->irq[1] = dsp;
-    s->wkup = wkup;
-    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
-
-    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
-                    omap2_gpio_module_writefn, s);
-    omap_l4_attach(ta, region, iomemtype);
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
+                                        sysbus_from_qdev(dev));
+    omap_gpio_reset(&s->omap1);
 }
 
-struct omap_gpif_s {
-    struct omap2_gpio_s module[5];
-    int modules;
-
-    int autoidle;
-    int gpo;
-};
-
-void omap_gpif_reset(struct omap_gpif_s *s)
+static void omap2_gpif_reset(DeviceState *dev)
 {
     int i;
-
-    for (i = 0; i < s->modules; i ++)
-        omap2_gpio_module_reset(s->module + i);
-
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
+                                        sysbus_from_qdev(dev));
+    for (i = 0; i < s->modulecount; i++) {
+        omap2_gpio_module_reset(&s->modules[i]);
+    }
     s->autoidle = 0;
     s->gpo = 0;
 }
 
-static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
+static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00:	/* IPGENERICOCPSPL_REVISION */
@@ -647,10 +621,10 @@ static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
+                                 uint32_t value)
 {
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 
     switch (addr) {
     case 0x00:	/* IPGENERICOCPSPL_REVISION */
@@ -662,7 +636,7 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
 
     case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
         if (value & (1 << 1))					/* SOFTRESET */
-            omap_gpif_reset(s);
+            omap2_gpif_reset(&s->busdev.qdev);
         s->autoidle = value & 1;
         break;
 
@@ -676,50 +650,119 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
-    omap_gpif_top_read,
-    omap_gpif_top_read,
-    omap_gpif_top_read,
+static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
+    omap2_gpif_top_read,
 };
 
-static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
-    omap_gpif_top_write,
-    omap_gpif_top_write,
-    omap_gpif_top_write,
+static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
+    omap2_gpif_top_write,
 };
 
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
+static int omap_gpio_init(SysBusDevice *dev)
 {
-    int iomemtype, i;
-    struct omap_gpif_s *s = (struct omap_gpif_s *)
-            qemu_mallocz(sizeof(struct omap_gpif_s));
-    int region[4] = { 0, 2, 4, 5 };
+    struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
+    if (!s->clk) {
+        hw_error("omap-gpio: clk not connected\n");
+    }
+    qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
+    qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
+    sysbus_init_irq(dev, &s->omap1.irq);
+    sysbus_init_mmio(dev, 0x1000,
+                     cpu_register_io_memory(omap_gpio_readfn,
+                                            omap_gpio_writefn,
+                                            &s->omap1,
+                                            DEVICE_NATIVE_ENDIAN));
+    return 0;
+}
 
-    s->modules = modules;
-    for (i = 0; i < modules; i ++)
-        omap2_gpio_module_init(s->module + i, ta, region[i],
-                              irq[i], NULL, NULL, fclk[i], iclk);
+static int omap2_gpio_init(SysBusDevice *dev)
+{
+    int i;
+    struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
+    if (!s->iclk) {
+        hw_error("omap2-gpio: iclk not connected\n");
+    }
+    if (s->mpu_model < omap3430) {
+        s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
+        sysbus_init_mmio(dev, 0x1000,
+                         cpu_register_io_memory(omap2_gpif_top_readfn,
+                                                omap2_gpif_top_writefn, s,
+                                                DEVICE_NATIVE_ENDIAN));
+    } else {
+        s->modulecount = 6;
+    }
+    s->modules = qemu_mallocz(s->modulecount * sizeof(struct omap2_gpio_s));
+    s->handler = qemu_mallocz(s->modulecount * 32 * sizeof(qemu_irq));
+    qdev_init_gpio_in(&dev->qdev, omap2_gpio_module_set, s->modulecount * 32);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
+    for (i = 0; i < s->modulecount; i++) {
+        struct omap2_gpio_s *m = &s->modules[i];
+        if (!s->fclk[i]) {
+            hw_error("omap2-gpio: fclk%d not connected\n", i);
+        }
+        m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
+        m->handler = &s->handler[i * 32];
+        sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
+        sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
+        sysbus_init_irq(dev, &m->wkup);
+        sysbus_init_mmio(dev, 0x1000,
+                         cpu_register_io_memory(omap2_gpio_module_readfn,
+                                                omap2_gpio_module_writefn,
+                                                m, DEVICE_NATIVE_ENDIAN));
+    }
+    return 0;
+}
 
-    omap_gpif_reset(s);
+/* Using qdev pointer properties for the clocks is not ideal.
+ * qdev should support a generic means of defining a 'port' with
+ * an arbitrary interface for connecting two devices. Then we
+ * could reframe the omap clock API in terms of clock ports,
+ * and get some type safety. For now the best qdev provides is
+ * passing an arbitrary pointer.
+ * (It's not possible to pass in the string which is the clock
+ * name, because this device does not have the necessary information
+ * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
+ * translation.)
+ */
 
-    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
-                    omap_gpif_top_writefn, s);
-    omap_l4_attach(ta, 1, iomemtype);
+static SysBusDeviceInfo omap_gpio_info = {
+    .init = omap_gpio_init,
+    .qdev.name = "omap-gpio",
+    .qdev.size = sizeof(struct omap_gpif_s),
+    .qdev.reset = omap_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-    return s;
-}
+static SysBusDeviceInfo omap2_gpio_info = {
+    .init = omap2_gpio_init,
+    .qdev.name = "omap2-gpio",
+    .qdev.size = sizeof(struct omap2_gpif_s),
+    .qdev.reset = omap2_gpif_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
+        DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
+        DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
+        DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
+        DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
+        DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
+        DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
+        DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
 
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
+static void omap_gpio_register_device(void)
 {
-    if (start >= s->modules * 32 || start < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
-    return s->module[start >> 5].in + (start & 31);
+    sysbus_register_withprop(&omap_gpio_info);
+    sysbus_register_withprop(&omap2_gpio_info);
 }
 
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
-{
-    if (line >= s->modules * 32 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->module[line >> 5].handler[line & 31] = handler;
-}
+device_init(omap_gpio_register_device)
diff --git a/hw/palm.c b/hw/palm.c
index f22d777..1c97394 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -94,7 +94,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
 {
     uWireSlave *tsc;
 
-    tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]);
+    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
 
     omap_uwire_attach(cpu->microwire, tsc, 0);
     omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
@@ -163,24 +163,24 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
     qemu_irq *misc_gpio;
 
     omap_mmc_handlers(cpu->mmc,
-                    omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO],
-                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
-                            [PALMTE_MMC_SWITCH_GPIO]));
+                      qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
+                      qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
+                                      [PALMTE_MMC_SWITCH_GPIO]));
 
     misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-    omap_gpio_out_set(cpu->gpio, PALMTE_MMC_POWER_GPIO,	misc_gpio[0]);
-    omap_gpio_out_set(cpu->gpio, PALMTE_SPEAKER_GPIO,	misc_gpio[1]);
-    omap_gpio_out_set(cpu->gpio, 11,			misc_gpio[2]);
-    omap_gpio_out_set(cpu->gpio, 12,			misc_gpio[3]);
-    omap_gpio_out_set(cpu->gpio, 13,			misc_gpio[4]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,   misc_gpio[1]);
+    qdev_connect_gpio_out(cpu->gpio, 11,                    misc_gpio[2]);
+    qdev_connect_gpio_out(cpu->gpio, 12,                    misc_gpio[3]);
+    qdev_connect_gpio_out(cpu->gpio, 13,                    misc_gpio[4]);
     omap_mpuio_out_set(cpu->mpuio, 1,			misc_gpio[5]);
     omap_mpuio_out_set(cpu->mpuio, 3,			misc_gpio[6]);
 
     /* Reset some inputs to initial state.  */
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USBDETECT_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USB_OR_DC_GPIO]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[4]);
-    qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_HEADPHONES_GPIO]);
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
     qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
     qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 05/15] lm832x: Take DeviceState pointer in lm832x_key_event()
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (3 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 04/15] hw/omap_gpio.c: Convert to qdev Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 06/15] hw/nand: Pass block device state to init function Peter Maydell
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

Since lm832x has been qdev'ified, its users will generally
have a DeviceState pointer rather than an i2c_slave pointer,
so adjust lm832x_key_event's prototype to suit.

This allows the n810 (its only user) to actually pass a correct
pointer to it rather than NULL. The effect is that we no longer
segfault when a key is pressed.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/i2c.h     |    2 +-
 hw/lm832x.c  |    4 ++--
 hw/nseries.c |    7 +++----
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/i2c.h b/hw/i2c.h
index 5514402..9381d01 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -72,6 +72,6 @@ void wm8750_set_bclk_in(void *opaque, int new_hz);
 void tmp105_set(i2c_slave *i2c, int temp);
 
 /* lm832x.c */
-void lm832x_key_event(i2c_slave *i2c, int key, int state);
+void lm832x_key_event(DeviceState *dev, int key, int state);
 
 #endif
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 590a4cc..992ce49 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -474,9 +474,9 @@ static int lm8323_init(i2c_slave *i2c)
     return 0;
 }
 
-void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
+void lm832x_key_event(DeviceState *dev, int key, int state)
 {
-    LM823KbdState *s = (LM823KbdState *) i2c;
+    LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, I2C_SLAVE_FROM_QDEV(dev));
 
     if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
         return;
diff --git a/hw/nseries.c b/hw/nseries.c
index 32f2f53..45b52bb 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -45,7 +45,7 @@ struct n800_s {
     i2c_bus *i2c;
 
     int keymap[0x80];
-    i2c_slave *kbd;
+    DeviceState *kbd;
 
     TUSBState *usb;
     void *retu;
@@ -362,7 +362,6 @@ static int n810_keys[0x80] = {
 static void n810_kbd_setup(struct n800_s *s)
 {
     qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
-    DeviceState *dev;
     int i;
 
     for (i = 0; i < 0x80; i ++)
@@ -375,8 +374,8 @@ static void n810_kbd_setup(struct n800_s *s)
 
     /* Attach the LM8322 keyboard to the I2C bus,
      * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    dev = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
-    qdev_connect_gpio_out(dev, 0, kbd_irq);
+    s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
+    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
 }
 
 /* LCD MIPI DBI-C controller (URAL) */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 06/15] hw/nand: Pass block device state to init function
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (4 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 05/15] lm832x: Take DeviceState pointer in lm832x_key_event() Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 07/15] hw/nand: Support large NAND devices Peter Maydell
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

Pass the BlockDeviceState to the nand_init() function rather
than having it look it up via drive_get() itself.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/axis_dev88.c |    6 +++++-
 hw/flash.h      |    2 +-
 hw/nand.c       |    8 ++------
 hw/spitz.c      |    4 +++-
 hw/tc6393xb.c   |    5 ++++-
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 0e2135a..de1f5a5 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -30,6 +30,7 @@
 #include "loader.h"
 #include "elf.h"
 #include "cris-boot.h"
+#include "blockdev.h"
 
 #define D(x)
 #define DNAND(x)
@@ -251,6 +252,7 @@ void axisdev88_init (ram_addr_t ram_size,
     CPUState *env;
     DeviceState *dev;
     SysBusDevice *s;
+    DriveInfo *nand;
     qemu_irq irq[30], nmi[2], *cpu_irq;
     void *etraxfs_dmac;
     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
@@ -278,7 +280,9 @@ void axisdev88_init (ram_addr_t ram_size,
 
 
       /* Attach a NAND flash to CS1.  */
-    nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39);
+    nand = drive_get(IF_MTD, 0, 0);
+    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
+                                NAND_MFR_STMICRO, 0x39);
     nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state,
                                        DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
diff --git a/hw/flash.h b/hw/flash.h
index c22e1a9..a992bb8 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -19,7 +19,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
 
 /* nand.c */
 typedef struct NANDFlashState NANDFlashState;
-NANDFlashState *nand_init(int manf_id, int chip_id);
+NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
 void nand_done(NANDFlashState *s);
 void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
diff --git a/hw/nand.c b/hw/nand.c
index 37e51d7..d6204d9 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -14,7 +14,6 @@
 # include "hw.h"
 # include "flash.h"
 # include "blockdev.h"
-/* FIXME: Pass block device as an argument.  */
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -451,20 +450,17 @@ uint8_t nand_getio(NANDFlashState *s)
     return *(s->ioaddr ++);
 }
 
-NANDFlashState *nand_init(int manf_id, int chip_id)
+NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
 {
     int pagesize;
     NANDFlashState *s;
-    DriveInfo *dinfo;
 
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
 
     s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo)
-        s->bdrv = dinfo->bdrv;
+    s->bdrv = bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
     s->size = nand_flash_ids[s->chip_id].size << 20;
diff --git a/hw/spitz.c b/hw/spitz.c
index 006f7a9..78e9c34 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -169,11 +169,13 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
 static int sl_nand_init(SysBusDevice *dev) {
     int iomemtype;
     SLNANDState *s;
+    DriveInfo *nand;
 
     s = FROM_SYSBUS(SLNANDState, dev);
 
     s->ctl = 0;
-    s->nand = nand_init(s->manf_id, s->chip_id);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
     iomemtype = cpu_register_io_memory(sl_readfn,
                     sl_writefn, s, DEVICE_NATIVE_ENDIAN);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index ed49e94..4de0819 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -12,6 +12,7 @@
 #include "flash.h"
 #include "console.h"
 #include "pixel_ops.h"
+#include "blockdev.h"
 
 #define IRQ_TC6393_NAND		0
 #define IRQ_TC6393_MMC		1
@@ -566,6 +567,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     TC6393xbState *s;
+    DriveInfo *nand;
     CPUReadMemoryFunc * const tc6393xb_readfn[] = {
         tc6393xb_readb,
         tc6393xb_readw,
@@ -586,7 +588,8 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
 
     s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
-    s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
+    nand = drive_get(IF_MTD, 0, 0);
+    s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
 
     iomemtype = cpu_register_io_memory(tc6393xb_readfn,
                     tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 07/15] hw/nand: Support large NAND devices
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (5 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 06/15] hw/nand: Pass block device state to init function Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 08/15] hw/nand: Support devices wider than 8 bits Peter Maydell
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Add support for NAND devices of over 1Gb.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/nand.c |   48 +++++++++++++++++++++++++++---------------------
 1 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/hw/nand.c b/hw/nand.c
index d6204d9..18aa226 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -6,6 +6,10 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog@zabor.org>
  *
+ * Support for additional features based on "MT29F2G16ABCWP 2Gx16"
+ * datasheet from Micron Technology and "NAND02G-B2C" datasheet
+ * from ST Microelectronics.
+ *
  * This code is licensed under the GNU GPL v2.
  */
 
@@ -57,14 +61,15 @@ struct NANDFlashState {
     uint8_t *ioaddr;
     int iolen;
 
-    uint32_t cmd, addr;
+    uint32_t cmd;
+    uint64_t addr;
     int addrlen;
     int status;
     int offset;
 
     void (*blk_write)(NANDFlashState *s);
     void (*blk_erase)(NANDFlashState *s);
-    void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+    void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
 
     uint32_t ioaddr_vmstate;
 };
@@ -318,7 +323,7 @@ static const VMStateDescription vmstate_nand = {
         VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
         VMSTATE_INT32(iolen, NANDFlashState),
         VMSTATE_UINT32(cmd, NANDFlashState),
-        VMSTATE_UINT32(addr, NANDFlashState),
+        VMSTATE_UINT64(addr, NANDFlashState),
         VMSTATE_INT32(addrlen, NANDFlashState),
         VMSTATE_INT32(status, NANDFlashState),
         VMSTATE_INT32(offset, NANDFlashState),
@@ -432,7 +437,7 @@ uint8_t nand_getio(NANDFlashState *s)
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
-        offset = (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
+        offset = (int)(s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
         s->offset = 0;
 
         s->blk_load(s, s->addr, offset);
@@ -526,7 +531,7 @@ void nand_done(NANDFlashState *s)
 /* Program a single page */
 static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t off, page, sector, soff;
+    uint64_t off, page, sector, soff;
     uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
     if (PAGE(s->addr) >= s->pages)
         return;
@@ -539,7 +544,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         off = (s->addr & PAGE_MASK) + s->offset;
         soff = SECTOR_OFFSET(s->addr);
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
@@ -551,20 +556,20 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         }
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     } else {
         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
         sector = off >> 9;
         soff = off & 0x1ff;
         if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1) {
-            printf("%s: read error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
         memcpy(iobuf + soff, s->io, s->iolen);
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, sector);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
     }
     s->offset = 0;
 }
@@ -572,7 +577,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
 /* Erase a single block */
 static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
 {
-    uint32_t i, page, addr;
+    uint64_t i, page, addr;
     uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
     addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
 
@@ -589,34 +594,35 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
         for (; i < page; i ++)
             if (bdrv_write(s->bdrv, i, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i);
+                printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
     } else {
         addr = PAGE_START(addr);
         page = addr >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
 
         memset(iobuf, 0xff, 0x200);
         i = (addr & ~0x1ff) + 0x200;
         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
                         i < addr; i += 0x200)
             if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
-                printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
+                printf("%s: write error in sector %" PRIu64 "\n",
+                       __func__, i >> 9);
 
         page = i >> 9;
         if (bdrv_read(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: read error in sector %i\n", __FUNCTION__, page);
+            printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
         if (bdrv_write(s->bdrv, page, iobuf, 1) == -1)
-            printf("%s: write error in sector %i\n", __FUNCTION__, page);
+            printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
     }
 }
 
 static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
-                uint32_t addr, int offset)
+                uint64_t addr, int offset)
 {
     if (PAGE(addr) >= s->pages)
         return;
@@ -624,8 +630,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
     if (s->bdrv) {
         if (s->mem_oob) {
             if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, SECTOR(addr));
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, SECTOR(addr));
             memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
                             s->storage + (PAGE(s->addr) << OOB_SHIFT),
                             OOB_SIZE);
@@ -633,8 +639,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
         } else {
             if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
                                     s->io, (PAGE_SECTORS + 2)) == -1)
-                printf("%s: read error in sector %i\n",
-                                __FUNCTION__, PAGE_START(addr) >> 9);
+                printf("%s: read error in sector %" PRIu64 "\n",
+                                __func__, PAGE_START(addr) >> 9);
             s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
         }
     } else {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 08/15] hw/nand: Support devices wider than 8 bits
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (6 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 07/15] hw/nand: Support large NAND devices Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 09/15] hw/nand: Support multiple reads following READ STATUS Peter Maydell
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Support NAND devices which are wider than 8 bits.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/flash.h |    5 ++-
 hw/nand.c  |  119 +++++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 89 insertions(+), 35 deletions(-)

diff --git a/hw/flash.h b/hw/flash.h
index a992bb8..132ad29 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -24,8 +24,9 @@ void nand_done(NANDFlashState *s);
 void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
 void nand_getpins(NANDFlashState *s, int *rb);
-void nand_setio(NANDFlashState *s, uint8_t value);
-uint8_t nand_getio(NANDFlashState *s);
+void nand_setio(NANDFlashState *s, uint32_t value);
+uint32_t nand_getio(NANDFlashState *s);
+uint32_t nand_getbuswidth(NANDFlashState *s);
 
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
diff --git a/hw/nand.c b/hw/nand.c
index 18aa226..2e98f25 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -49,6 +49,7 @@
 
 struct NANDFlashState {
     uint8_t manf_id, chip_id;
+    uint8_t buswidth; /* in BYTES */
     int size, pages;
     int page_shift, oob_shift, erase_shift, addr_shift;
     uint8_t *storage;
@@ -215,6 +216,14 @@ static void nand_reset(NANDFlashState *s)
     s->status &= NAND_IOSTATUS_UNPROTCT;
 }
 
+static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
+{
+    s->ioaddr[s->iolen++] = value;
+    for (value = s->buswidth; --value;) {
+        s->ioaddr[s->iolen++] = 0;
+    }
+}
+
 static void nand_command(NANDFlashState *s)
 {
     unsigned int offset;
@@ -224,15 +233,19 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READID:
-        s->io[0] = s->manf_id;
-        s->io[1] = s->chip_id;
-        s->io[2] = 'Q';		/* Don't-care byte (often 0xa5) */
-        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
-            s->io[3] = 0x15;	/* Page Size, Block Size, Spare Size.. */
-        else
-            s->io[3] = 0xc0;	/* Multi-plane */
         s->ioaddr = s->io;
-        s->iolen = 4;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->manf_id);
+        nand_pushio_byte(s, s->chip_id);
+        nand_pushio_byte(s, 'Q'); /* Don't-care byte (often 0xa5) */
+        if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+            /* Page Size, Block Size, Spare Size; bit 6 indicates
+             * 8 vs 16 bit width NAND.
+             */
+            nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15);
+        } else {
+            nand_pushio_byte(s, 0xc0); /* Multi-plane */
+        }
         break;
 
     case NAND_CMD_RANDOMREAD2:
@@ -277,9 +290,9 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_READSTATUS:
-        s->io[0] = s->status;
         s->ioaddr = s->io;
-        s->iolen = 1;
+        s->iolen = 0;
+        nand_pushio_byte(s, s->status);
         break;
 
     default:
@@ -357,8 +370,10 @@ void nand_getpins(NANDFlashState *s, int *rb)
     *rb = 1;
 }
 
-void nand_setio(NANDFlashState *s, uint8_t value)
+void nand_setio(NANDFlashState *s, uint32_t value)
 {
+    int i;
+
     if (!s->ce && s->cle) {
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
@@ -404,36 +419,64 @@ void nand_setio(NANDFlashState *s, uint8_t value)
         s->addr = (s->addr & mask) | v;
         s->addrlen ++;
 
-        if (s->addrlen == 1 && s->cmd == NAND_CMD_READID)
-            nand_command(s);
-
-        if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-                s->addrlen == 3 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
-        if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
-               s->addrlen == 4 && (
-                    s->cmd == NAND_CMD_READ0 ||
-                    s->cmd == NAND_CMD_PAGEPROGRAM1))
-            nand_command(s);
+        switch (s->addrlen) {
+        case 1:
+            if (s->cmd == NAND_CMD_READID) {
+                nand_command(s);
+            }
+            break;
+        case 2: /* fix cache address as a byte address */
+            s->addr <<= (s->buswidth - 1);
+            break;
+        case 3:
+            if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
+                && (s->cmd == NAND_CMD_READ0
+                    || s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 4:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
+                && nand_flash_ids[s->chip_id].size < 256 /* 1Gb or less */
+                && (s->cmd == NAND_CMD_READ0 ||
+                    s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        case 5:
+            if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
+                && nand_flash_ids[s->chip_id].size >= 256 /* 2Gb or more */
+                && (s->cmd == NAND_CMD_READ0 ||
+                    s->cmd == NAND_CMD_PAGEPROGRAM1)) {
+                nand_command(s);
+            }
+            break;
+        default:
+            break;
+        }
     }
 
     if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
-        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift))
-            s->io[s->iolen ++] = value;
+        if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) {
+            for (i = s->buswidth; i--; value >>= 8) {
+                s->io[s->iolen++] = (uint8_t)(value & 0xff);
+            }
+        }
     } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
         if ((s->addr & ((1 << s->addr_shift) - 1)) <
-                (1 << s->page_shift) + (1 << s->oob_shift)) {
-            s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] = value;
-            s->addr ++;
+            (1 << s->page_shift) + (1 << s->oob_shift)) {
+            for (i = s->buswidth; i--; s->addr++, value >>= 8) {
+                s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] =
+                    (uint8_t)(value & 0xff);
+            }
         }
     }
 }
 
-uint8_t nand_getio(NANDFlashState *s)
+uint32_t nand_getio(NANDFlashState *s)
 {
     int offset;
+    uint32_t x = 0;
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
@@ -450,9 +493,18 @@ uint8_t nand_getio(NANDFlashState *s)
     if (s->ce || s->iolen <= 0)
         return 0;
 
-    s->iolen --;
-    s->addr++;
-    return *(s->ioaddr ++);
+    for (offset = s->buswidth; offset--;) {
+        x |= s->ioaddr[offset] << (offset << 3);
+    }
+    s->addr   += s->buswidth;
+    s->ioaddr += s->buswidth;
+    s->iolen  -= s->buswidth;
+    return x;
+}
+
+uint32_t nand_getbuswidth(NANDFlashState *s)
+{
+    return s->buswidth << 3;
 }
 
 NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
@@ -468,6 +520,7 @@ NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
     s->bdrv = bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
+    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
     s->size = nand_flash_ids[s->chip_id].size << 20;
     if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
         s->page_shift = 11;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 09/15] hw/nand: Support multiple reads following READ STATUS
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (7 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 08/15] hw/nand: Support devices wider than 8 bits Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 10/15] hw/nand: Writing to NAND can only clear bits Peter Maydell
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

After receiving READ STATUS command all subsequent IO reads should return
the status register value until another command is issued.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/nand.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/hw/nand.c b/hw/nand.c
index 2e98f25..e6c551d 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -496,9 +496,14 @@ uint32_t nand_getio(NANDFlashState *s)
     for (offset = s->buswidth; offset--;) {
         x |= s->ioaddr[offset] << (offset << 3);
     }
-    s->addr   += s->buswidth;
-    s->ioaddr += s->buswidth;
-    s->iolen  -= s->buswidth;
+    /* after receiving READ STATUS command all subsequent reads will
+     * return the status register value until another command is issued
+     */
+    if (s->cmd != NAND_CMD_READSTATUS) {
+        s->addr   += s->buswidth;
+        s->ioaddr += s->buswidth;
+        s->iolen  -= s->buswidth;
+    }
     return x;
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 10/15] hw/nand: Writing to NAND can only clear bits
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (8 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 09/15] hw/nand: Support multiple reads following READ STATUS Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 11/15] hw/nand: qdevify Peter Maydell
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

Writing to a NAND device cannot set bits, it can only clear them;
implement this rather than simply copying the data.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/nand.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/hw/nand.c b/hw/nand.c
index e6c551d..d068eb6 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -75,6 +75,15 @@ struct NANDFlashState {
     uint32_t ioaddr_vmstate;
 };
 
+static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
+{
+    /* Like memcpy() but we logical-AND the data into the destination */
+    int i;
+    for (i = 0; i < n; i++) {
+        dest[i] &= src[i];
+    }
+}
+
 # define NAND_NO_AUTOINCR	0x00000001
 # define NAND_BUSWIDTH_16	0x00000002
 # define NAND_NO_PADDING	0x00000004
@@ -595,7 +604,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
         return;
 
     if (!s->bdrv) {
-        memcpy(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
+        mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
                         s->offset, s->io, s->iolen);
     } else if (s->mem_oob) {
         sector = SECTOR(s->addr);
@@ -606,10 +615,10 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
             return;
         }
 
-        memcpy(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
+        mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
         if (off + s->iolen > PAGE_SIZE) {
             page = PAGE(s->addr);
-            memcpy(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
+            mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
         }
 
@@ -624,7 +633,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
             return;
         }
 
-        memcpy(iobuf + soff, s->io, s->iolen);
+        mem_and(iobuf + soff, s->io, s->iolen);
 
         if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) == -1)
             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 11/15] hw/nand: qdevify
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (9 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 10/15] hw/nand: Writing to NAND can only clear bits Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 12/15] onenand: Pass BlockDriverState to init function Peter Maydell
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Qdevify the NAND device.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/axis_dev88.c |    2 +-
 hw/flash.h      |   14 ++---
 hw/nand.c       |  164 +++++++++++++++++++++++++++++++------------------------
 hw/spitz.c      |    2 +-
 hw/tc6393xb.c   |    2 +-
 5 files changed, 102 insertions(+), 82 deletions(-)

diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index de1f5a5..e0a8c14 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -37,7 +37,7 @@
 
 struct nand_state_t
 {
-    NANDFlashState *nand;
+    DeviceState *nand;
     unsigned int rdy:1;
     unsigned int ale:1;
     unsigned int cle:1;
diff --git a/hw/flash.h b/hw/flash.h
index 132ad29..43260ce 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -18,15 +18,13 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
                                 int be);
 
 /* nand.c */
-typedef struct NANDFlashState NANDFlashState;
-NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
-void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
-void nand_getpins(NANDFlashState *s, int *rb);
-void nand_setio(NANDFlashState *s, uint32_t value);
-uint32_t nand_getio(NANDFlashState *s);
-uint32_t nand_getbuswidth(NANDFlashState *s);
+void nand_getpins(DeviceState *dev, int *rb);
+void nand_setio(DeviceState *dev, uint32_t value);
+uint32_t nand_getio(DeviceState *dev);
+uint32_t nand_getbuswidth(DeviceState *dev);
 
 #define NAND_MFR_TOSHIBA	0x98
 #define NAND_MFR_SAMSUNG	0xec
diff --git a/hw/nand.c b/hw/nand.c
index d068eb6..2f5a40e 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -18,6 +18,7 @@
 # include "hw.h"
 # include "flash.h"
 # include "blockdev.h"
+# include "sysbus.h"
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
@@ -47,7 +48,9 @@
 # define MAX_PAGE		0x800
 # define MAX_OOB		0x40
 
+typedef struct NANDFlashState NANDFlashState;
 struct NANDFlashState {
+    SysBusDevice busdev;
     uint8_t manf_id, chip_id;
     uint8_t buswidth; /* in BYTES */
     int size, pages;
@@ -215,8 +218,9 @@ static const struct {
     [0xc5] = { 2048,	16,	0, 0, LP_OPTIONS16 },
 };
 
-static void nand_reset(NANDFlashState *s)
+static void nand_reset(DeviceState *dev)
 {
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
     s->cmd = NAND_CMD_READ0;
     s->addr = 0;
     s->addrlen = 0;
@@ -270,7 +274,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_RESET:
-        nand_reset(s);
+        nand_reset(&s->busdev.qdev);
         break;
 
     case NAND_CMD_PAGEPROGRAM1:
@@ -354,15 +358,84 @@ static const VMStateDescription vmstate_nand = {
     }
 };
 
+static int nand_device_init(SysBusDevice *dev)
+{
+    int pagesize;
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev);
+    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
+    s->size = nand_flash_ids[s->chip_id].size << 20;
+    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
+        s->page_shift = 11;
+        s->erase_shift = 6;
+    } else {
+        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
+        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
+    }
+
+    switch (1 << s->page_shift) {
+    case 256:
+        nand_init_256(s);
+        break;
+    case 512:
+        nand_init_512(s);
+        break;
+    case 2048:
+        nand_init_2048(s);
+        break;
+    default:
+        hw_error("%s: Unsupported NAND block size.\n", __func__);
+    }
+
+    pagesize = 1 << s->oob_shift;
+    s->mem_oob = 1;
+    if (s->bdrv && bdrv_getlength(s->bdrv) >=
+        (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
+        pagesize = 0;
+        s->mem_oob = 0;
+    }
+
+    if (!s->bdrv) {
+        pagesize += 1 << s->page_shift;
+    }
+    if (pagesize) {
+        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
+                                        0xff, s->pages * pagesize);
+    }
+    /* Give s->ioaddr a sane value in case we save state before it is used. */
+    s->ioaddr = s->io;
+
+    return 0;
+}
+
+static SysBusDeviceInfo nand_info = {
+    .init = nand_device_init,
+    .qdev.name = "nand",
+    .qdev.size = sizeof(NANDFlashState),
+    .qdev.reset = nand_reset,
+    .qdev.vmsd = &vmstate_nand,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
+        DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
+        DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void nand_create_device(void)
+{
+    sysbus_register_withprop(&nand_info);
+}
+
 /*
  * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins.  Chip
  * outputs are R/B and eight I/O pins.
  *
  * CE, WP and R/B are active low.
  */
-void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd)
 {
+    NANDFlashState *s = (NANDFlashState *)dev;
     s->cle = cle;
     s->ale = ale;
     s->ce = ce;
@@ -374,15 +447,15 @@ void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
         s->status &= ~NAND_IOSTATUS_UNPROTCT;
 }
 
-void nand_getpins(NANDFlashState *s, int *rb)
+void nand_getpins(DeviceState *dev, int *rb)
 {
     *rb = 1;
 }
 
-void nand_setio(NANDFlashState *s, uint32_t value)
+void nand_setio(DeviceState *dev, uint32_t value)
 {
     int i;
-
+    NANDFlashState *s = (NANDFlashState *)dev;
     if (!s->ce && s->cle) {
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
             if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
@@ -482,10 +555,11 @@ void nand_setio(NANDFlashState *s, uint32_t value)
     }
 }
 
-uint32_t nand_getio(NANDFlashState *s)
+uint32_t nand_getio(DeviceState *dev)
 {
     int offset;
     uint32_t x = 0;
+    NANDFlashState *s = (NANDFlashState *)dev;
 
     /* Allow sequential reading */
     if (!s->iolen && s->cmd == NAND_CMD_READ0) {
@@ -516,82 +590,30 @@ uint32_t nand_getio(NANDFlashState *s)
     return x;
 }
 
-uint32_t nand_getbuswidth(NANDFlashState *s)
+uint32_t nand_getbuswidth(DeviceState *dev)
 {
+    NANDFlashState *s = (NANDFlashState *)dev;
     return s->buswidth << 3;
 }
 
-NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
+DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
 {
-    int pagesize;
-    NANDFlashState *s;
-
+    DeviceState *dev;
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
-
-    s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    s->bdrv = bdrv;
-    s->manf_id = manf_id;
-    s->chip_id = chip_id;
-    s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
-    s->size = nand_flash_ids[s->chip_id].size << 20;
-    if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
-        s->page_shift = 11;
-        s->erase_shift = 6;
-    } else {
-        s->page_shift = nand_flash_ids[s->chip_id].page_shift;
-        s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
+    dev = qdev_create(NULL, "nand");
+    qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
+    qdev_prop_set_uint8(dev, "chip_id", chip_id);
+    if (bdrv) {
+        qdev_prop_set_drive_nofail(dev, "drive", bdrv);
     }
 
-    switch (1 << s->page_shift) {
-    case 256:
-        nand_init_256(s);
-        break;
-    case 512:
-        nand_init_512(s);
-        break;
-    case 2048:
-        nand_init_2048(s);
-        break;
-    default:
-        hw_error("%s: Unsupported NAND block size.\n", __FUNCTION__);
-    }
-
-    pagesize = 1 << s->oob_shift;
-    s->mem_oob = 1;
-    if (s->bdrv && bdrv_getlength(s->bdrv) >=
-                    (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
-        pagesize = 0;
-        s->mem_oob = 0;
-    }
-
-    if (!s->bdrv)
-        pagesize += 1 << s->page_shift;
-    if (pagesize)
-        s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),
-                        0xff, s->pages * pagesize);
-    /* Give s->ioaddr a sane value in case we save state before it
-       is used.  */
-    s->ioaddr = s->io;
-
-    vmstate_register(NULL, -1, &vmstate_nand, s);
-
-    return s;
+    qdev_init_nofail(dev);
+    return dev;
 }
 
-void nand_done(NANDFlashState *s)
-{
-    if (s->bdrv) {
-        bdrv_close(s->bdrv);
-        bdrv_delete(s->bdrv);
-    }
-
-    if (!s->bdrv || s->mem_oob)
-        qemu_free(s->storage);
-
-    qemu_free(s);
-}
+device_init(nand_create_device)
 
 #else
 
diff --git a/hw/spitz.c b/hw/spitz.c
index 78e9c34..c05b5f7 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -48,7 +48,7 @@
 
 typedef struct {
     SysBusDevice busdev;
-    NANDFlashState *nand;
+    DeviceState *nand;
     uint8_t ctl;
     uint8_t manf_id;
     uint8_t chip_id;
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 4de0819..a1c48bf 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -118,7 +118,7 @@ struct TC6393xbState {
     } nand;
     int nand_enable;
     uint32_t nand_phys;
-    NANDFlashState *flash;
+    DeviceState *flash;
     ECCState ecc;
 
     DisplayState *ds;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 12/15] onenand: Pass BlockDriverState to init function
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (10 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 11/15] hw/nand: qdevify Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 13/15] onenand: Handle various ID fields separately Peter Maydell
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

Pass the BlockDriverState to the onenand init function so it doesn't
need to look up the drive itself.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/flash.h   |    3 ++-
 hw/nseries.c |   10 ++++++----
 hw/onenand.c |   14 ++++++++------
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/flash.h b/hw/flash.h
index 43260ce..1aae43d 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev);
 /* onenand.c */
 void onenand_base_update(void *opaque, target_phys_addr_t new);
 void onenand_base_unmap(void *opaque);
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq);
+void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+                   int regshift, qemu_irq irq);
 void *onenand_raw_otp(void *opaque);
 
 /* ecc.c */
diff --git a/hw/nseries.c b/hw/nseries.c
index 45b52bb..96cc490 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -31,6 +31,7 @@
 #include "hw.h"
 #include "bt.h"
 #include "loader.h"
+#include "blockdev.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -163,13 +164,14 @@ static const uint8_t n8x0_cal_bt_id[] = {
 static void n8x0_nand_setup(struct n800_s *s)
 {
     char *otp_region;
+    DriveInfo *dinfo;
 
+    dinfo = drive_get(IF_MTD, 0, 0);
     /* Either ec40xx or ec48xx are OK for the ID */
+    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1,
+                           qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
-                    onenand_base_unmap,
-                    (s->nand = onenand_init(0xec4800, 1,
-                                            qdev_get_gpio_in(s->cpu->gpio,
-                                                    N8X0_ONENAND_GPIO))));
+                     onenand_base_unmap, s->nand);
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
diff --git a/hw/onenand.c b/hw/onenand.c
index 71c1ab4..3a19d7f 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -615,10 +615,10 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = {
     onenand_write,
 };
 
-void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
+void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+                   int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
     uint32_t size = 1 << (24 + ((id >> 12) & 7));
     void *ram;
 
@@ -632,11 +632,13 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
     s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
-    if (!dinfo)
+    s->bdrv = bdrv;
+    if (!s->bdrv) {
         s->image = memset(qemu_malloc(size + (size >> 5)),
-                        0xff, size + (size >> 5));
-    else
-        s->bdrv = dinfo->bdrv;
+                          0xff, size + (size >> 5));
+    } else {
+        s->bdrv_cur = s->bdrv;
+    }
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
     s->ram = qemu_ram_alloc(NULL, "onenand.ram", 0xc000 << s->shift);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 13/15] onenand: Handle various ID fields separately
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (11 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 12/15] onenand: Pass BlockDriverState to init function Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 14/15] onenand: Ignore zero writes to boot command space Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits Peter Maydell
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Handle the manufacturer, device and version IDs separately rather than
smooshing them all together into a single uint32_t. Note that the ID
registers are actually 16 bit, even though typically the top bits are 0
and the Read Identification Data command only returns the bottom 8 bits.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/flash.h   |    3 ++-
 hw/nseries.c |    5 +++--
 hw/onenand.c |   29 ++++++++++++++++++-----------
 3 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/hw/flash.h b/hw/flash.h
index 1aae43d..1064fd0 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -38,7 +38,8 @@ uint32_t nand_getbuswidth(DeviceState *dev);
 /* onenand.c */
 void onenand_base_update(void *opaque, target_phys_addr_t new);
 void onenand_base_unmap(void *opaque);
-void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+void *onenand_init(BlockDriverState *bdrv,
+                   uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
                    int regshift, qemu_irq irq);
 void *onenand_raw_otp(void *opaque);
 
diff --git a/hw/nseries.c b/hw/nseries.c
index 96cc490..7cdba25 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -167,8 +167,9 @@ static void n8x0_nand_setup(struct n800_s *s)
     DriveInfo *dinfo;
 
     dinfo = drive_get(IF_MTD, 0, 0);
-    /* Either ec40xx or ec48xx are OK for the ID */
-    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0, 0xec4800, 1,
+    /* Either 0x40 or 0x48 are OK for the device ID */
+    s->nand = onenand_init(dinfo ? dinfo->bdrv : 0,
+                           NAND_MFR_SAMSUNG, 0x48, 0, 1,
                            qdev_get_gpio_in(s->cpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
                      onenand_base_unmap, s->nand);
diff --git a/hw/onenand.c b/hw/onenand.c
index 3a19d7f..9f02736 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -31,7 +31,11 @@
 #define BLOCK_SHIFT	(PAGE_SHIFT + 6)
 
 typedef struct {
-    uint32_t id;
+    struct {
+        uint16_t man;
+        uint16_t dev;
+        uint16_t ver;
+    } id;
     int shift;
     target_phys_addr_t base;
     qemu_irq intr;
@@ -453,12 +457,12 @@ static uint32_t onenand_read(void *opaque, target_phys_addr_t addr)
         return lduw_le_p(s->boot[0] + addr);
 
     case 0xf000:	/* Manufacturer ID */
-        return (s->id >> 16) & 0xff;
+        return s->id.man;
     case 0xf001:	/* Device ID */
-        return (s->id >>  8) & 0xff;
-    /* TODO: get the following values from a real chip!  */
+        return s->id.dev;
     case 0xf002:	/* Version ID */
-        return (s->id >>  0) & 0xff;
+        return s->id.ver;
+    /* TODO: get the following values from a real chip!  */
     case 0xf003:	/* Data Buffer size */
         return 1 << PAGE_SHIFT;
     case 0xf004:	/* Boot Buffer size */
@@ -541,8 +545,8 @@ static void onenand_write(void *opaque, target_phys_addr_t addr,
 
         case 0x0090:	/* Read Identification Data */
             memset(s->boot[0], 0, 3 << s->shift);
-            s->boot[0][0 << s->shift] = (s->id >> 16) & 0xff;
-            s->boot[0][1 << s->shift] = (s->id >>  8) & 0xff;
+            s->boot[0][0 << s->shift] = s->id.man & 0xff;
+            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
             s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
             break;
 
@@ -615,21 +619,24 @@ static CPUWriteMemoryFunc * const onenand_writefn[] = {
     onenand_write,
 };
 
-void *onenand_init(BlockDriverState *bdrv, uint32_t id,
+void *onenand_init(BlockDriverState *bdrv,
+                   uint16_t man_id, uint16_t dev_id, uint16_t ver_id,
                    int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    uint32_t size = 1 << (24 + ((id >> 12) & 7));
+    uint32_t size = 1 << (24 + ((dev_id >> 4) & 7));
     void *ram;
 
     s->shift = regshift;
     s->intr = irq;
     s->rdy = NULL;
-    s->id = id;
+    s->id.man = man_id;
+    s->id.dev = dev_id;
+    s->id.ver = ver_id;
     s->blocks = size >> BLOCK_SHIFT;
     s->secs = size >> 9;
     s->blockwp = qemu_malloc(s->blocks);
-    s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
+    s->density_mask = (dev_id & 0x08) ? (1 << (6 + ((dev_id >> 4) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
     s->bdrv = bdrv;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 14/15] onenand: Ignore zero writes to boot command space
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (12 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 13/15] onenand: Handle various ID fields separately Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits Peter Maydell
  14 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

Ignore zero writes to the boot command space; Linux will issue
these in the powerdown/reset sequence.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/onenand.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/hw/onenand.c b/hw/onenand.c
index 9f02736..0edcfe2 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -550,6 +550,13 @@ static void onenand_write(void *opaque, target_phys_addr_t addr,
             s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
             break;
 
+        case 0x0000:
+            /* ignore zero writes without error messages,
+             * linux omap2/3 kernel will issue these upon
+             * powerdown/reset sequence.
+             */
+            break;
+
         default:
             fprintf(stderr, "%s: unknown OneNAND boot command %x\n",
                             __FUNCTION__, value);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits
  2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
                   ` (13 preceding siblings ...)
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 14/15] onenand: Ignore zero writes to boot command space Peter Maydell
@ 2011-07-29 15:35 ` Peter Maydell
  2011-07-30  5:19   ` andrzej zaborowski
  14 siblings, 1 reply; 19+ messages in thread
From: Peter Maydell @ 2011-07-29 15:35 UTC (permalink / raw)
  To: qemu-devel, Anthony Liguori

From: Juha Riihimäki <juha.riihimaki@nokia.com>

The program actions onenand_prog_main() and onenand_prog_spare()
can only set bits.

This implies a rewrite of onenand_erase() to not use the program
functions, since erase does need to set bits.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
---
 hw/onenand.c |  135 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 106 insertions(+), 29 deletions(-)

diff --git a/hw/onenand.c b/hw/onenand.c
index 0edcfe2..981d23c 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -179,14 +179,39 @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    if (s->bdrv_cur)
-        return bdrv_write(s->bdrv_cur, sec, src, secn) < 0;
-    else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (sec << 9), src, secn << 9);
+    int result = 0;
+
+    if (secn > 0) {
+        uint32_t size = (uint32_t)secn * 512;
+        const uint8_t *sp = (const uint8_t *)src;
+        uint8_t *dp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(size);
+            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
+                result = 1;
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dp = (uint8_t *)s->current + (sec << 9);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < size; i++) {
+                dp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
+            }
+        }
+        if (dp && s->bdrv_cur) {
+            qemu_free(dp);
+        }
+    }
 
-    return 0;
+    return result;
 }
 
 static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
@@ -209,35 +234,87 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
 static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
                 void *src)
 {
-    uint8_t buf[512];
-
-    if (s->bdrv_cur) {
-        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
-            return 1;
-        memcpy(buf + ((sec & 31) << 4), src, secn << 4);
-        return bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0;
-    } else if (sec + secn > s->secs_cur)
-        return 1;
-
-    memcpy(s->current + (s->secs_cur << 9) + (sec << 4), src, secn << 4);
- 
-    return 0;
+    int result = 0;
+    if (secn > 0) {
+        const uint8_t *sp = (const uint8_t *)src;
+        uint8_t *dp = 0, *dpp = 0;
+        if (s->bdrv_cur) {
+            dp = qemu_malloc(512);
+            if (!dp || bdrv_read(s->bdrv_cur,
+                                 s->secs_cur + (sec >> 5),
+                                 dp, 1) < 0) {
+                result = 1;
+            } else {
+                dpp = dp + ((sec & 31) << 4);
+            }
+        } else {
+            if (sec + secn > s->secs_cur) {
+                result = 1;
+            } else {
+                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
+            }
+        }
+        if (!result) {
+            uint32_t i;
+            for (i = 0; i < (secn << 4); i++) {
+                dpp[i] &= sp[i];
+            }
+            if (s->bdrv_cur) {
+                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
+                                    dp, 1) < 0;
+            }
+        }
+        if (dp) {
+            qemu_free(dp);
+        }
+    }
+    return result;
 }
 
 static inline int onenand_erase(OneNANDState *s, int sec, int num)
 {
-    /* TODO: optimise */
-    uint8_t buf[512];
-
-    memset(buf, 0xff, sizeof(buf));
-    for (; num > 0; num --, sec ++) {
-        if (onenand_prog_main(s, sec, 1, buf))
-            return 1;
-        if (onenand_prog_spare(s, sec, 1, buf))
-            return 1;
+    uint8_t *blankbuf, *tmpbuf;
+    blankbuf = qemu_malloc(512);
+    if (!blankbuf) {
+        return 1;
+    }
+    tmpbuf = qemu_malloc(512);
+    if (!tmpbuf) {
+        qemu_free(blankbuf);
+        return 1;
+    }
+    memset(blankbuf, 0xff, 512);
+    for (; num > 0; num--, sec++) {
+        if (s->bdrv_cur) {
+            int erasesec = s->secs_cur + (sec >> 5);
+            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) {
+                goto fail;
+            }
+            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
+            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+                goto fail;
+            }
+        } else {
+            if (sec + 1 > s->secs_cur) {
+                goto fail;
+            }
+            memcpy(s->current + (sec << 9), blankbuf, 512);
+            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
+                   blankbuf, 1 << 4);
+        }
     }
 
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
     return 0;
+
+fail:
+    qemu_free(tmpbuf);
+    qemu_free(blankbuf);
+    return 1;
 }
 
 static void onenand_command(OneNANDState *s, int cmd)
-- 
1.7.1

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

* Re: [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers Peter Maydell
@ 2011-07-30  4:53   ` andrzej zaborowski
  2011-07-30 12:44     ` Peter Maydell
  0 siblings, 1 reply; 19+ messages in thread
From: andrzej zaborowski @ 2011-07-30  4:53 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Anthony Liguori, qemu-devel

Hi,

I went ahead and pushed the series with the exception of this patch
and 14/15 because I think these are the types of patches that should
remain in downstream as a reminder, is there an argument for not
fixing these things in Linux?

In patch 04 I renamed omap2_gpio_module_set to omap2_gpio_set because
the parameter is no longer the module pointer.  By the way I think we
should also pass the target agent pointer on creation the same way
clocks are passed and use omap_l4_attach.

In patch 07 I bumped the vmstate version because the structure seems
to have changed.

In patch 12 I removed the
else {
    s->bdrv_cur = s->bdrv;
} part because there seemed to be no reason to add it, please check
that I haven't broken something.

Cheers

On 29 July 2011 17:35, Peter Maydell <peter.maydell@linaro.org> wrote:
> Don't complain about some writes to r/o OMAP2 GPIO registers, because the
> kernel will do them anyway.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/omap_gpio.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
> index 478f7d9..b53b13b 100644
> --- a/hw/omap_gpio.c
> +++ b/hw/omap_gpio.c
> @@ -385,7 +385,7 @@ static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
>     case 0x00: /* GPIO_REVISION */
>     case 0x14: /* GPIO_SYSSTATUS */
>     case 0x38: /* GPIO_DATAIN */
> -        OMAP_RO_REG(addr);
> +        /* read-only, ignore quietly */
>         break;
>
>     case 0x10: /* GPIO_SYSCONFIG */
> @@ -531,7 +531,7 @@ static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
>     case 0x00: /* GPIO_REVISION */
>     case 0x14: /* GPIO_SYSSTATUS */
>     case 0x38: /* GPIO_DATAIN */
> -        OMAP_RO_REG(addr);
> +        /* read-only, ignore quietly */
>         break;
>
>     case 0x10: /* GPIO_SYSCONFIG */
> --
> 1.7.1
>
>

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

* Re: [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits
  2011-07-29 15:35 ` [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits Peter Maydell
@ 2011-07-30  5:19   ` andrzej zaborowski
  0 siblings, 0 replies; 19+ messages in thread
From: andrzej zaborowski @ 2011-07-30  5:19 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Anthony Liguori, qemu-devel

On 29 July 2011 17:35, Peter Maydell <peter.maydell@linaro.org> wrote:
> From: Juha Riihimäki <juha.riihimaki@nokia.com>
>
> The program actions onenand_prog_main() and onenand_prog_spare()
> can only set bits.
>
> This implies a rewrite of onenand_erase() to not use the program
> functions, since erase does need to set bits.
>
> Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
> [Riku Voipio: Fixes and restructuring patchset]
> Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
> [Peter Maydell: More fixes and cleanups for upstream submission]
> Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/onenand.c |  135 +++++++++++++++++++++++++++++++++++++++++++++------------
>  1 files changed, 106 insertions(+), 29 deletions(-)
>
> diff --git a/hw/onenand.c b/hw/onenand.c
...
>  static inline int onenand_erase(OneNANDState *s, int sec, int num)
>  {
> -    /* TODO: optimise */
> -    uint8_t buf[512];
> -
> -    memset(buf, 0xff, sizeof(buf));
> -    for (; num > 0; num --, sec ++) {
> -        if (onenand_prog_main(s, sec, 1, buf))
> -            return 1;
> -        if (onenand_prog_spare(s, sec, 1, buf))
> -            return 1;
> +    uint8_t *blankbuf, *tmpbuf;
> +    blankbuf = qemu_malloc(512);
> +    if (!blankbuf) {
> +        return 1;
> +    }
> +    tmpbuf = qemu_malloc(512);
> +    if (!tmpbuf) {
> +        qemu_free(blankbuf);
> +        return 1;
> +    }
> +    memset(blankbuf, 0xff, 512);
> +    for (; num > 0; num--, sec++) {
> +        if (s->bdrv_cur) {
> +            int erasesec = s->secs_cur + (sec >> 5);
> +            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) {
> +                goto fail;
> +            }
> +            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
> +                goto fail;
> +            }
> +            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
> +            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
> +                goto fail;
> +            }

By the way it seems that this can be optimised to require just one
read for the entire erase.

Cheers

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

* Re: [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers
  2011-07-30  4:53   ` andrzej zaborowski
@ 2011-07-30 12:44     ` Peter Maydell
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2011-07-30 12:44 UTC (permalink / raw)
  To: andrzej zaborowski; +Cc: Anthony Liguori, qemu-devel

On 30 July 2011 05:53, andrzej zaborowski <balrogg@gmail.com> wrote:
> I went ahead and pushed the series

Thanks.

> with the exception of this patch
> and 14/15 because I think these are the types of patches that should
> remain in downstream as a reminder, is there an argument for not
> fixing these things in Linux?

I think the only arguments are "it's too hard" and "I'd like to
run legacy images without having qemu constantly complaining and
making '-serial stdio' unusable" :-) [have you seen how much chatter
you get out of n810 running a meego image?] I think I've said before
that really we ought to have this kind of message more consistently
and conveniently enablable/disablable.

I'll leave this sort of change out of future patches; when I get
down to the point where they're the only thing left in my patch
stack (a) I'll be very happy and (b) I might look at a nicer way
to handle them.

> In patch 04 I renamed omap2_gpio_module_set to omap2_gpio_set because
> the parameter is no longer the module pointer.  By the way I think we
> should also pass the target agent pointer on creation the same way
> clocks are passed and use omap_l4_attach.

The clock passing thing is (as per comments) a bit nasty; at
the moment sysbus is the closest we have to a nice way of exposing
"I have some MMIO regions" so I'm a bit reluctant to hide it behind
another magic pointer property. I'll have a think about this, though.

> In patch 07 I bumped the vmstate version because the structure seems
> to have changed.

Oops, yes. I had a note at some point to look more carefully at
the vmstate change but I must have forgotten about it :-(
I agree we can just bump the version.

> In patch 12 I removed the
> else {
>    s->bdrv_cur = s->bdrv;
> } part because there seemed to be no reason to add it, please check
> that I haven't broken something.

That looks like it should be OK, we'll always call onenand_reset()
which will set bdrv_cur to bdrv.

-- PMM

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

end of thread, other threads:[~2011-07-30 12:44 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-29 15:35 [Qemu-devel] [PULL 00/15] omap patches (gpio, nand, onenand, lm832x) Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 01/15] hw/omap_l4.c: Add helper function omap_l4_region_base Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 02/15] hw/omap_gpio.c: Don't complain about some writes to r/o registers Peter Maydell
2011-07-30  4:53   ` andrzej zaborowski
2011-07-30 12:44     ` Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 03/15] hw/omap_clk: Add the clock for the OMAP2430-specific fifth GPIO module Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 04/15] hw/omap_gpio.c: Convert to qdev Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 05/15] lm832x: Take DeviceState pointer in lm832x_key_event() Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 06/15] hw/nand: Pass block device state to init function Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 07/15] hw/nand: Support large NAND devices Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 08/15] hw/nand: Support devices wider than 8 bits Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 09/15] hw/nand: Support multiple reads following READ STATUS Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 10/15] hw/nand: Writing to NAND can only clear bits Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 11/15] hw/nand: qdevify Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 12/15] onenand: Pass BlockDriverState to init function Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 13/15] onenand: Handle various ID fields separately Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 14/15] onenand: Ignore zero writes to boot command space Peter Maydell
2011-07-29 15:35 ` [Qemu-devel] [PATCH 15/15] hw/onenand: program actions can only clear bits Peter Maydell
2011-07-30  5:19   ` andrzej zaborowski

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).