Re: [Qemu-devel] [PATCH v9 16/24] The FTSSP010 is a multi-function synchronous serial port interface controller which supports SSP, SPI, I2S, AC97 and SPDIF.

2013-03-31 Thread Kuo-Jung Su
2013/3/31 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung

 I think you may have accidentally dropped your subject line and
 promoted your long commit message to subject line. Looks better in
 previous versions.


Yes, it's an accident, I'll fix it later.

 On Mon, Mar 25, 2013 at 10:09 PM, Kuo-Jung Su dant...@gmail.com wrote:

 From: Kuo-Jung Su dant...@faraday-tech.com

 Only I2S and SPI protocol have been implemented in this patch.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs|3 +-
  hw/arm/ftplat_a369.c|   31 +++
  hw/arm/ftplat_a369soc.c |   17 ++
  hw/faraday.h|3 +
  hw/ftssp010.c   |  504 
 +++
  hw/ftssp010.h   |   96 +
  6 files changed, 653 insertions(+), 1 deletion(-)
  create mode 100644 hw/ftssp010.c
  create mode 100644 hw/ftssp010.h

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index 2bb67f7..42c8472 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -25,7 +25,8 @@ obj-y += strongarm.o
  obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
  obj-$(CONFIG_KVM) += kvm/arm_gic.o
  obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 -ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o
 +ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o 
 fti2c010.o \
 +ftssp010.o

  obj-y := $(addprefix ../,$(obj-y))

 diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
 index 827c58a..922fb55 100644
 --- a/hw/arm/ftplat_a369.c
 +++ b/hw/arm/ftplat_a369.c
 @@ -11,6 +11,7 @@
  #include hw/arm-misc.h
  #include hw/devices.h
  #include hw/i2c.h
 +#include hw/audio.h
  #include hw/boards.h
  #include hw/ssi.h
  #include net/net.h
 @@ -28,6 +29,7 @@ static void a369_system_reset(void *opaque)

  static void a369_board_init(QEMUMachineInitArgs *args)
  {
 +int i, nr_flash;
  ARMCPU *cpu;
  DeviceState *ds;
  FaradaySoCState *s;
 @@ -79,6 +81,35 @@ static void a369_board_init(QEMUMachineInitArgs *args)
  abort();
  }

 +/* Attach the spi flash to ftssp010.0 */
 +nr_flash = 1;
 +for (i = 0; i  nr_flash; i++) {
 +SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi[0], spi);
 +DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
 +qemu_irq cs_line;
 +
 +qdev_init_nofail(fl);
 +cs_line = qdev_get_gpio_in(fl, 0);
 +sysbus_connect_irq(SYS_BUS_DEVICE(s-spi[0]), i + 1, cs_line);
 +}
 +
 +/* Attach the wm8731 to fti2c010.0  ftssp010.0 */
 +for (i = 0; i  1; ++i) {
 +i2c_bus *i2c = (i2c_bus *)qdev_get_child_bus(s-i2c[0], i2c);
 +ds = i2c_create_slave(i2c, wm8731, 0x1B);
 +object_property_set_link(OBJECT(s-i2s[0]),
 + OBJECT(ds),
 + codec,
 + local_errp);
 +if (local_errp) {
 +fprintf(stderr, a369: Unable to set codec link for 
 FTSSP010\n);
 +abort();
 +}
 +audio_codec_data_req_set(ds,
 + ftssp010_i2s_data_req,
 + s-i2s[0]);
 +}
 +
  /* System start-up */

  if (args-kernel_filename) {
 diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
 index b6e82ad..9391764 100644
 --- a/hw/arm/ftplat_a369soc.c
 +++ b/hw/arm/ftplat_a369soc.c
 @@ -206,6 +206,23 @@ static void a369soc_chip_init(FaradaySoCState *s)
  s-i2c[0] = ds;
  ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
  s-i2c[1] = ds;
 +
 +/* ftssp010 */
 +ds = sysbus_create_simple(ftssp010, 0x9270, s-pic[49]);
 +s-spi[0] = ds;
 +s-i2s[0] = ds;
 +
 +/* ftssp010 - DMA (Tx) */
 +ack = qdev_get_gpio_in(ds, 0);
 +req = qdev_get_gpio_in(s-pdma[0], 7);
 +qdev_connect_gpio_out(s-pdma[0], 7, ack);
 +qdev_connect_gpio_out(ds, 0, req);
 +
 +/* ftssp010 - DMA (Rx) */
 +ack = qdev_get_gpio_in(ds, 1);
 +req = qdev_get_gpio_in(s-pdma[0], 8);
 +qdev_connect_gpio_out(s-pdma[0], 8, ack);
 +qdev_connect_gpio_out(ds, 1, req);
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/faraday.h b/hw/faraday.h
 index 7373ba0..39a608c 100644
 --- a/hw/faraday.h
 +++ b/hw/faraday.h
 @@ -121,4 +121,7 @@ static inline void faraday_soc_ahb_remap(FaradaySoCState 
 *s, bool active)
  }
  }

 +/* ftssp010.c */
 +void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 +
  #endif
 diff --git a/hw/ftssp010.c b/hw/ftssp010.c
 new file mode 100644
 index 000..fe1ddbb
 --- /dev/null
 +++ b/hw/ftssp010.c
 @@ -0,0 +1,504 @@
 +/*
 + * QEMU model of the FTSSP010 Controller
 + *
 + * Copyright (C) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This file is licensed under GNU GPL v2+.
 + */
 +
 +#include hw/sysbus.h
 +#include hw/i2c.h
 +#include hw/ssi.h

Re: [Qemu-devel] [PATCH v9 24/24] hw/arm: add FTSPI020 SPI flash controller support

2013-03-29 Thread Kuo-Jung Su
2013/3/29 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Mon, Mar 25, 2013 at 10:10 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTSPI020 is an integrated SPI Flash controller
 which supports up to 4 flash chips.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs |2 +-
  hw/arm/ftplat_a369.c |   16 +++
  hw/ftspi020.c|  341 
 ++
  hw/ftspi020.h|   81 
  4 files changed, 439 insertions(+), 1 deletion(-)
  create mode 100644 hw/ftspi020.c
  create mode 100644 hw/ftspi020.h

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index bcfb70a..a34ca41 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -27,7 +27,7 @@ obj-$(CONFIG_KVM) += kvm/arm_gic.o
  obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
  ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o 
 fti2c010.o \
  ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o \
 -ftmac110.o fttmr010.o
 +ftmac110.o fttmr010.o ftspi020.o

  obj-y := $(addprefix ../,$(obj-y))

 diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
 index f22e2ca..77cd44d 100644
 --- a/hw/arm/ftplat_a369.c
 +++ b/hw/arm/ftplat_a369.c
 @@ -125,6 +125,22 @@ static void a369_board_init(QEMUMachineInitArgs *args)
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);

 +/* SPI: FTSPI020 */
 +ds = sysbus_create_simple(ftspi020, 0xC000, s-pic[4]);
 +s-spi_fl[0] = ds;
 +
 +/* Attach the spi flash to ftspi020.0 */
 +nr_flash = 1;
 +for (i = 0; i  nr_flash; i++) {
 +SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi_fl[0], spi);
 +DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);

 You qdev_init straight away, so you can just call ssi_create_slave.
 This is just a hangover from my recent m25p80 cleanup which made the
 original reason for create_slave_no_init redundant. I'll have to send
 some cleanup patches for my own machine models with the equivalent
 change. s/ssi_create_slave_no_init/ssi_create_slave and ...


Got it, thanks

 +qemu_irq cs_line;
 +
 +qdev_init_nofail(fl);

 ... dump this.

 Regards,
 Peter

 +cs_line = qdev_get_gpio_in(fl, 0);
 +sysbus_connect_irq(SYS_BUS_DEVICE(s-spi_fl[0]), i + 1, cs_line);
 +}
 +
  /* System start-up */

  if (args-kernel_filename) {
 diff --git a/hw/ftspi020.c b/hw/ftspi020.c
 new file mode 100644
 index 000..a7253bd
 --- /dev/null
 +++ b/hw/ftspi020.c
 @@ -0,0 +1,341 @@
 +/*
 + * Faraday FTSPI020 Flash Controller
 + *
 + * Copyright (c) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This code is licensed under GNU GPL v2+.
 + */
 +
 +#include hw/hw.h
 +#include hw/sysbus.h
 +#include hw/ssi.h
 +#include sysemu/sysemu.h
 +
 +#include hw/ftspi020.h
 +
 +#define TYPE_FTSPI020   ftspi020
 +
 +typedef struct Ftspi020State {
 +/* private */
 +SysBusDevice parent;
 +
 +/* public */
 +MemoryRegion iomem;
 +qemu_irq irq;
 +
 +/* DMA hardware handshake */
 +qemu_irq req;
 +
 +SSIBus *spi;
 +qemu_irq *cs_lines;
 +
 +int wip;/* SPI Flash Status: Write In Progress BIT shift */
 +
 +/* HW register caches */
 +uint32_t cmd[4];
 +uint32_t ctrl;
 +uint32_t timing;
 +uint32_t icr;
 +uint32_t isr;
 +uint32_t rdsr;
 +} Ftspi020State;
 +
 +#define FTSPI020(obj) \
 +OBJECT_CHECK(Ftspi020State, obj, TYPE_FTSPI020)
 +
 +static void ftspi020_update_irq(Ftspi020State *s)
 +{
 +qemu_set_irq(s-irq, s-isr ? 1 : 0);
 +}
 +
 +static void ftspi020_handle_ack(void *opaque, int line, int level)
 +{
 +Ftspi020State *s = FTSPI020(opaque);
 +
 +if (!(s-icr  ICR_DMA)) {
 +return;
 +}
 +
 +if (level) {
 +qemu_set_irq(s-req, 0);
 +} else if (s-cmd[2]) {
 +qemu_set_irq(s-req, 1);
 +}
 +}
 +
 +static int ftspi020_do_command(Ftspi020State *s)
 +{
 +uint32_t cs   = extract32(s-cmd[3],  8, 2);
 +uint32_t cmd  = extract32(s-cmd[3], 24, 8);
 +uint32_t ilen = extract32(s-cmd[1], 24, 2);
 +uint32_t alen = extract32(s-cmd[1],  0, 3);
 +uint32_t dcyc = extract32(s-cmd[1], 16, 8);
 +
 +if (dcyc % 8) {
 +fprintf(stderr, ftspi020: bad dummy clock (%u) to QEMU\n, dcyc);
 +abort();
 +}
 +
 +/* activate the spi flash */
 +qemu_set_irq(s-cs_lines[cs], 0);
 +
 +/* if it's a SPI flash READ_STATUS command */
 +if ((s-cmd[3]  (CMD3_RDSR | CMD3_WRITE)) == CMD3_RDSR) {
 +uint32_t rdsr;
 +
 +ssi_transfer(s-spi, cmd);
 +do {
 +rdsr = ssi_transfer(s-spi, 0x00);
 +if (s-cmd[3]  CMD3_RDSR_SW) {
 +break;
 +}
 +} while (rdsr  (1  s-wip));
 +s-rdsr = rdsr

Re: [Qemu-devel] [PATCH v9 10/24] hw/arm: add FTDMAC020 AHB DMA support

2013-03-29 Thread Kuo-Jung Su
2013/3/29 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Mon, Mar 25, 2013 at 10:09 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The Faraday FTDMAC020 provides eight configurable
 channels for the memory-to-memory, memory-to-peripheral,
 peripheral-to-peripheral, and peripheral-to-memory transfers.

 Each DMA channel supports chain transfer and can be programmed
 to one of the 16 handshaking channels in the hardware handshake mode.

 The main function of the hardware handshake mode is to provide an
 indication of the device status. Users can also disable the hardware
 handshake mode by programming the register when a DMA transfer is not
 necessary of referring to the handshaking channels.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs|2 +-
  hw/arm/ftplat_a369soc.c |   14 ++
  hw/ftdmac020.c  |  599 
 +++
  hw/ftdmac020.h  |  107 +
  4 files changed, 721 insertions(+), 1 deletion(-)
  create mode 100644 hw/ftdmac020.c
  create mode 100644 hw/ftdmac020.h

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index 6a41b21..6510c51 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -25,7 +25,7 @@ obj-y += strongarm.o
  obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
  obj-$(CONFIG_KVM) += kvm/arm_gic.o
  obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 -ftrtc011.o
 +ftrtc011.o ftdmac020.o

  obj-y := $(addprefix ../,$(obj-y))

 diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
 index bd696c4..59e2c61 100644
 --- a/hw/arm/ftplat_a369soc.c
 +++ b/hw/arm/ftplat_a369soc.c
 @@ -168,6 +168,20 @@ static void a369soc_chip_init(FaradaySoCState *s)
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
  /* Hour (Edge) */
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
 +
 +/* ftdmac020 */
 +s-hdma[0] = sysbus_create_varargs(ftdmac020,
 +   0x9030,
 +   s-pic[0],  /* ALL (NC in A369) */
 +   s-pic[15], /* TC */
 +   s-pic[16], /* ERR */
 +   NULL);
 +s-hdma[1] = sysbus_create_varargs(ftdmac020,
 +   0x9610,
 +   s-pic[0],  /* ALL (NC in A369) */
 +   s-pic[17], /* TC */
 +   s-pic[18], /* ERR */
 +   NULL);
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/ftdmac020.c b/hw/ftdmac020.c
 new file mode 100644
 index 000..81b49b2
 --- /dev/null
 +++ b/hw/ftdmac020.c
 @@ -0,0 +1,599 @@
 +/*
 + * QEMU model of the FTDMAC020 DMA Controller
 + *
 + * Copyright (C) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This file is licensed under GNU GPL v2+.
 + *
 + * Note: The FTDMAC020 descending address mode is not implemented.
 + */
 +
 +#include hw/sysbus.h
 +#include sysemu/dma.h
 +#include sysemu/sysemu.h
 +#include sysemu/blockdev.h
 +
 +#include hw/ftdmac020.h
 +
 +#define TYPE_FTDMAC020ftdmac020
 +
 +enum ftdmac020_irqpin {
 +IRQ_ALL = 0,
 +IRQ_TC,
 +IRQ_ERR,
 +};
 +
 +typedef struct Ftdmac020State Ftdmac020State;
 +
 +/**
 + * struct Ftdmac020LLD - hardware link list descriptor.
 + * @src: source physical address
 + * @dst: destination physical addr
 + * @next: phsical address to the next link list descriptor
 + * @ctrl: control field
 + * @size: transfer size
 + *
 + * should be word aligned
 + */
 +typedef struct Ftdmac020LLD {
 +uint32_t src;
 +uint32_t dst;
 +uint32_t next;
 +uint32_t ctrl;
 +uint32_t size;
 +} Ftdmac020LLD;
 +
 +typedef struct Ftdmac020Chan {
 +Ftdmac020State *chip;
 +
 +int id;
 +int burst;
 +int llp_cnt;
 +int src_bw;
 +int src_stride;
 +int dst_bw;
 +int dst_stride;
 +
 +/* HW register cache */
 +uint32_t ccr;
 +uint32_t cfg;
 +uint32_t src;
 +uint32_t dst;
 +uint32_t llp;
 +uint32_t len;
 +} Ftdmac020Chan;
 +
 +typedef struct Ftdmac020State {
 +/* private */
 +SysBusDevice parent;
 +
 +/* public */
 +MemoryRegion iomem;
 +qemu_irq irq[3];
 +
 +Ftdmac020Chan chan[8];
 +qemu_irq  ack[16];
 +uint32_t  req;
 +
 +int busy;/* Busy Channel ID */
 +int bh_owner;
 +QEMUBH *bh;
 +DMAContext *dma;
 +
 +/* HW register cache */
 +uint32_t tcisr;
 +uint32_t eaisr;
 +uint32_t tcsr;
 +uint32_t easr;
 +uint32_t cesr;
 +uint32_t cbsr;
 +uint32_t csr;
 +uint32_t sync;
 +} Ftdmac020State;
 +
 +#define FTDMAC020(obj) \
 +OBJECT_CHECK(Ftdmac020State, obj, TYPE_FTDMAC020)
 +
 +static void

Re: [Qemu-devel] [PATCH v9 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-27 Thread Kuo-Jung Su
2013/3/28 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Mon, Mar 25, 2013 at 10:09 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTDDRII030 is a DDRII SDRAM controller which is responsible for
 SDRAM initialization.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs|2 +-
  hw/arm/ftplat_a369soc.c |8 ++
  hw/ftddrii030.c |  192 
 +++
  3 files changed, 201 insertions(+), 1 deletion(-)
  create mode 100644 hw/ftddrii030.c

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index b2fa20f..e774962 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -24,7 +24,7 @@ obj-y += framebuffer.o
  obj-y += strongarm.o
  obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
  obj-$(CONFIG_KVM) += kvm/arm_gic.o
 -obj-y += ftintc020.o ftahbc020.o
 +obj-y += ftintc020.o ftahbc020.o ftddrii030.o

  obj-y := $(addprefix ../,$(obj-y))

 diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
 index 7f222cb..b2da582 100644
 --- a/hw/arm/ftplat_a369soc.c
 +++ b/hw/arm/ftplat_a369soc.c
 @@ -129,6 +129,14 @@ static void a369soc_chip_init(FaradaySoCState *s)
  fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
  abort();
  }
 +
 +/* ftddrii030 */
 +ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
 +object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
 +if (local_errp) {
 +fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 +abort();
 +}
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/ftddrii030.c b/hw/ftddrii030.c
 new file mode 100644
 index 000..158db1f
 --- /dev/null
 +++ b/hw/ftddrii030.c
 @@ -0,0 +1,192 @@
 +/*
 + * Faraday DDRII controller
 + *
 + * Copyright (c) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This code is licensed under GNU GPL v2+
 + */
 +
 +#include hw/hw.h
 +#include hw/sysbus.h
 +#include hw/devices.h
 +#include sysemu/sysemu.h
 +
 +#include hw/faraday.h
 +
 +#define REG_MCR 0x00/* memory configuration register */
 +#define REG_MSR 0x04/* memory status register */
 +#define REG_REVR0x50/* revision register */
 +
 +#define MSR_INIT_OK BIT(8)  /* initialization finished */
 +#define MSR_CMD_MRS BIT(0)  /* start MRS command (init. seq.) */
 +
 +#define CFG_REGSIZE (REG_REVR / 4)
 +
 +#define TYPE_FTDDRII030 ftddrii030
 +
 +typedef struct Ftddrii030State {
 +/* private */
 +SysBusDevice parent;
 +
 +/* public */
 +MemoryRegion iomem;
 +
 +FaradaySoCState *soc;
 +

 This new implementation still has many of the same encapsulation
 issues discussed in v8. If you go with the suggestion myself and Peter
 came up with you could make this device completely self contained - it
 should have no awareness that it is part of the Faraday SoC. If you
 model as a second MemoryRegion you can push all the Faraday specific
 foo up to the SoC. Interdiff would go something like this:

 -FaradaySoCState *soc;
 +MemoryRegion ram;


Sorry, but I think it might not work in that way.
Because there is an AHB remap function is Faraday SoC,
which would alter the base address of both ROM and RAM.
So the ram instance should never be a local variable to FTDDRII030 only.

The first thing solution spring up in my mind is to add a QOM link in
FTDDRII030, and then pass the ram instance as a QOM link from device model.
However it turns out that it's also not possible, since the ram
instance (MemoryRegion) is not a Object *.

So I turn out to implement both the 'AHB remap' and 'RAM
initialization' as common routines
to Faraday SoC, and also create a remappable memory region for both ROM and RAM.

 +/* HW register cache */
 +uint32_t regs[CFG_REGSIZE];
 +} Ftddrii030State;
 +
 +#define FTDDRII030(obj) \
 +OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
 +
 +#define DDR_REG32(s, off) \
 +((s)-regs[(off) / 4])
 +
 +static uint64_t
 +ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
 +{
 +Ftddrii030State *s = FTDDRII030(opaque);
 +FaradaySoCState *soc = s-soc;
 +uint64_t ret = 0;
 +
 +if (soc-ram_visible) {
 +DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
 +} else {
 +DDR_REG32(s, REG_MSR) = ~MSR_INIT_OK;
 +}
 +
 +switch (addr) {
 +case REG_MCR ... REG_REVR - 4:
 +ret = DDR_REG32(s, addr);
 +break;
 +case REG_REVR:
 +ret = 0x100;/* rev. = 0.1.0 */
 +break;
 +default:
 +qemu_log_mask(LOG_GUEST_ERROR,
 +ftddrii030: undefined memory access@%# HWADDR_PRIx \n, 
 addr);
 +break;
 +}
 +
 +return ret;
 +}
 +
 +static void
 +ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 +{
 +Ftddrii030State *s

Re: [Qemu-devel] [PATCH v9 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-27 Thread Kuo-Jung Su
2013/3/28 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo Jung,

 On Thu, Mar 28, 2013 at 1:24 PM, Kuo-Jung Su dant...@gmail.com wrote:
 2013/3/28 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Mon, Mar 25, 2013 at 10:09 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTDDRII030 is a DDRII SDRAM controller which is responsible for
 SDRAM initialization.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs|2 +-
  hw/arm/ftplat_a369soc.c |8 ++
  hw/ftddrii030.c |  192 
 +++
  3 files changed, 201 insertions(+), 1 deletion(-)
  create mode 100644 hw/ftddrii030.c

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index b2fa20f..e774962 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -24,7 +24,7 @@ obj-y += framebuffer.o
  obj-y += strongarm.o
  obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
  obj-$(CONFIG_KVM) += kvm/arm_gic.o
 -obj-y += ftintc020.o ftahbc020.o
 +obj-y += ftintc020.o ftahbc020.o ftddrii030.o

  obj-y := $(addprefix ../,$(obj-y))

 diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
 index 7f222cb..b2da582 100644
 --- a/hw/arm/ftplat_a369soc.c
 +++ b/hw/arm/ftplat_a369soc.c
 @@ -129,6 +129,14 @@ static void a369soc_chip_init(FaradaySoCState *s)
  fprintf(stderr, a369soc: Unable to set soc link for 
 FTAHBC020\n);
  abort();
  }
 +
 +/* ftddrii030 */
 +ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
 +object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
 +if (local_errp) {
 +fprintf(stderr, a369soc: Unable to set soc link for 
 FTDDRII030\n);
 +abort();
 +}
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/ftddrii030.c b/hw/ftddrii030.c
 new file mode 100644
 index 000..158db1f
 --- /dev/null
 +++ b/hw/ftddrii030.c
 @@ -0,0 +1,192 @@
 +/*
 + * Faraday DDRII controller
 + *
 + * Copyright (c) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This code is licensed under GNU GPL v2+
 + */
 +
 +#include hw/hw.h
 +#include hw/sysbus.h
 +#include hw/devices.h
 +#include sysemu/sysemu.h
 +
 +#include hw/faraday.h
 +
 +#define REG_MCR 0x00/* memory configuration register */
 +#define REG_MSR 0x04/* memory status register */
 +#define REG_REVR0x50/* revision register */
 +
 +#define MSR_INIT_OK BIT(8)  /* initialization finished */
 +#define MSR_CMD_MRS BIT(0)  /* start MRS command (init. seq.) */
 +
 +#define CFG_REGSIZE (REG_REVR / 4)
 +
 +#define TYPE_FTDDRII030 ftddrii030
 +
 +typedef struct Ftddrii030State {
 +/* private */
 +SysBusDevice parent;
 +
 +/* public */
 +MemoryRegion iomem;
 +
 +FaradaySoCState *soc;
 +

 This new implementation still has many of the same encapsulation
 issues discussed in v8. If you go with the suggestion myself and Peter
 came up with you could make this device completely self contained - it
 should have no awareness that it is part of the Faraday SoC. If you
 model as a second MemoryRegion you can push all the Faraday specific
 foo up to the SoC. Interdiff would go something like this:

 -FaradaySoCState *soc;
 +MemoryRegion ram;


 Sorry, but I think it might not work in that way.
 Because there is an AHB remap function is Faraday SoC,
 which would alter the base address of both ROM and RAM.
 So the ram instance should never be a local variable to FTDDRII030 only.


 The new RAM region would have no awareness of its base address. It is
 just a remappable container. The SoC can still do the remapping part.
 This device model is then oblivous to the fact that the SoC and other
 devices are remapping its base address.

 The first thing solution spring up in my mind is to add a QOM link in
 FTDDRII030, and then pass the ram instance as a QOM link from device model.
 However it turns out that it's also not possible, since the ram
 instance (MemoryRegion) is not a Object *.


 calling sysbus_mmio_get_region() on the SoC level should do the trick.
 If you init the container region as proposed, this function can be
 used by the SoC to get a handle to it.


It sounds like pretty good idea to me, I think I know what to do now.
Thanks

 I think we are on similar timezones (+10:00 here) if you want to try
 and clarify on the IRC sometime today as well.


Thanks for the invitation, but the IRQ is banned in my company...

 Regards,
 Peter

 So I turn out to implement both the 'AHB remap' and 'RAM
 initialization' as common routines
 to Faraday SoC, and also create a remappable memory region for both ROM and 
 RAM.

 +/* HW register cache */
 +uint32_t regs[CFG_REGSIZE];
 +} Ftddrii030State;
 +
 +#define FTDDRII030(obj) \
 +OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
 +
 +#define DDR_REG32(s, off

[Qemu-devel] [PATCH v9 01/24] target-arm: add Faraday ARMv5TE processors support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

This patch includes the single core support to FA606TE, FA626TE,
FA616TE and FA726TE with CP15 Faraday extensions (AUX and I/D-Scratchpad).

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 target-arm/cpu.c |   52 +++
 target-arm/cpu.h |6 +++-
 target-arm/helper.c  |   84 ++
 target-arm/machine.c |4 +++
 4 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a1e9093..aed97b0 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -244,6 +244,54 @@ static void arm926_initfn(Object *obj)
 cpu-reset_sctlr = 0x00090078;
 }
 
+static void fa606te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_MPU_FARADAY);
+cpu-midr = 0x66056061; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa616te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66056161; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d152152;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa626te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+set_feature(cpu-env, ARM_FEATURE_AUXCR);
+cpu-midr = 0x66056261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x0f192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa726te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66057261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
 static void arm946_initfn(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -766,6 +814,10 @@ typedef struct ARMCPUInfo {
 
 static const ARMCPUInfo arm_cpus[] = {
 { .name = arm926,  .initfn = arm926_initfn },
+{ .name = fa606te, .initfn = fa606te_initfn },
+{ .name = fa616te, .initfn = fa616te_initfn },
+{ .name = fa626te, .initfn = fa626te_initfn },
+{ .name = fa726te, .initfn = fa726te_initfn },
 { .name = arm946,  .initfn = arm946_initfn },
 { .name = arm1026, .initfn = arm1026_initfn },
 /* What QEMU calls arm1136-r2 is actually the 1136 r0p2, i.e. an
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2b97221..dd27e80 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -152,6 +152,8 @@ typedef struct CPUARMState {
 uint32_t c15_diagnostic; /* diagnostic register */
 uint32_t c15_power_diagnostic;
 uint32_t c15_power_control; /* power control */
+uint32_t c15_tcm_data;  /* Data TCM region register */
+uint32_t c15_tcm_inst;  /* Instruction TCM region register */
 } cp15;
 
 struct {
@@ -392,6 +394,8 @@ enum arm_features {
 ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
 ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
+ARM_FEATURE_TCM_FARADAY, /* Faraday Scratchpad(TCM) */
+ARM_FEATURE_MPU_FARADAY, /* Faraday MPU */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -640,7 +644,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 9
+#define CPU_SAVE_VERSION 10
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fd055e8..337d8b8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1015,6 +1015,84 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+static int faraday_pmsav5_ircfg_read(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+if (ri-crm = 4) {
+return

[Qemu-devel] [PATCH v9 03/24] hw/arm: add FTINTC020 interrupt controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTINTC020 interrupt controller supports both FIQ and IRQ signals
to the microprocessor.
It can handle up to 64 configurable IRQ sources and 64 FIQ sources.
The output signals to the microprocessor can be configured as
level-high/low active or edge-rising/falling triggered.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|1 +
 hw/arm/ftplat_a369soc.c |   11 ++
 hw/ftintc020.c  |  307 +++
 hw/ftintc020.h  |   55 +
 4 files changed, 374 insertions(+)
 create mode 100644 hw/ftintc020.c
 create mode 100644 hw/ftintc020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 09217c6..7cdd831 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,6 +24,7 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
+obj-y += ftintc020.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 624b549..331ec2a 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -51,6 +51,8 @@ static void a369soc_reset(DeviceState *ds)
 
 static void a369soc_chip_init(FaradaySoCState *s)
 {
+int i;
+DeviceState *ds;
 DriveInfo *dinfo;
 
 /* Remappable Memory Region Init */
@@ -84,6 +86,15 @@ static void a369soc_chip_init(FaradaySoCState *s)
 memory_region_add_subregion(s-rmr, s-rom_base,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(s-rom), 0));
 
+/* Interrupt Controller */
+ds = sysbus_create_varargs(ftintc020, 0x9010,
+   s-cpu_pic[ARM_PIC_CPU_IRQ],
+   s-cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+s-pic = g_new0(qemu_irq, 64);
+for (i = 0; i  64; ++i) {
+s-pic[i] = qdev_get_gpio_in(ds, i);
+}
+
 /* Serial (FTUART010 which is 16550A compatible) */
 if (serial_hds[0]) {
 serial_mm_init(s-as,
diff --git a/hw/ftintc020.c b/hw/ftintc020.c
new file mode 100644
index 000..9aaff1d
--- /dev/null
+++ b/hw/ftintc020.c
@@ -0,0 +1,307 @@
+/*
+ * Faraday FTINTC020 Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+
+#include qemu/bitops.h
+#include hw/ftintc020.h
+
+#define TYPE_FTINTC020  ftintc020
+
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftintc020State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+
+qemu_irq irq;
+qemu_irq fiq;
+
+uint32_t irq_ps[2]; /* IRQ pin state */
+uint32_t fiq_ps[2]; /* FIQ pin state */
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftintc020State;
+
+#define FTINTC020(obj) \
+OBJECT_CHECK(Ftintc020State, obj, TYPE_FTINTC020)
+
+#define PIC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+#define IRQ_REG32(s, n, off) \
+((s)-regs[(REG_IRQ(n) + ((off)  REG_MASK)) / 4])
+
+#define FIQ_REG32(s, n, off) \
+((s)-regs[(REG_FIQ(n) + ((off)  REG_MASK)) / 4])
+
+static void
+ftintc020_update_irq(Ftintc020State *s)
+{
+uint32_t mask[2];
+
+/* FIQ */
+mask[0] = PIC_REG32(s, REG_FIQ32SRC)  PIC_REG32(s, REG_FIQ32ENA);
+mask[1] = PIC_REG32(s, REG_FIQ64SRC)  PIC_REG32(s, REG_FIQ64ENA);
+qemu_set_irq(s-fiq, !!(mask[0] || mask[1]));
+
+/* IRQ */
+mask[0] = PIC_REG32(s, REG_IRQ32SRC)  PIC_REG32(s, REG_IRQ32ENA);
+mask[1] = PIC_REG32(s, REG_IRQ64SRC)  PIC_REG32(s, REG_IRQ64ENA);
+qemu_set_irq(s-irq, !!(mask[0] || mask[1]));
+}
+
+/* Note: Here level means state of the signal on a pin */
+static void
+ftintc020_set_irq(void *opaque, int irq, int level)
+{
+Ftintc020State *s = FTINTC020(opaque);
+uint32_t i = irq / 32;
+uint32_t mask = BIT(irq  0x1f);
+
+switch (irq) {
+case 0  ... 63:
+/* IRQ */
+if (IRQ_REG32(s, irq, REG_MDR)  mask) {
+/* Edge Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Falling Active */
+if ((s-irq_ps[i]  mask)  !level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* Rising Active */
+if (!(s-irq_ps[i]  mask)  level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+}
+} else {
+/* Level Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Low Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* High Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC

[Qemu-devel] [PATCH v9 00/24] hw/arm: add Faraday A369 SoC platform support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

These patches introduce Faraday A369 SoC platform support.

Here are some public documents for your reference.

http://www.faraday-tech.com/html/documentation/index.html

The partial version of faraday cpu datasheet with only
the CP15 and MPU description are available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAalh5TkxyZWtlWEE/edit?usp=sharing

The pre-built A369 images are also available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAX2pTTmtUMGFCZW8/edit

Here is the image file list:

1. android-4.0.4/zImage: A369 linux-3.0.31
2. android-4.0.4/romfs-4.0.4.tar.bz2: android-4.0.4
3. nand.img.bz2: A369 nand flash image
4. rom.img.bz2: A369 embedded ROM image
5. u-boot: A369 u-boot-2012.10 ELF file
6. zImage: A369 linux-3.4.12 + initramfs
7. README

If you want to re-build the image from scratch, 
try my Faraday Linux BSP/SDK: falinux.

1. Download the falinux

   $ git clone https://github.com/dantesu1218/falinux.git

2. Download all the required software packages:

   $ cd falinux
   $ make setup

3. Launch the menuconfig of falinux, and enable 'QEMU Support'

   $ make menuconfig

4. Re-build the packages

   $ make

5. Laungh the qemu-1.3.0 with the generated falinux images.

   $ make qemu

Changes for v8 - v9:

1. hw/arm: Update the file directory structure (Addressed by Peter.M)
   hw/arm: top level board models and things directly reference the CPU only
   hw: otherwise
2. hw/arm: Rename SoC platform specific files:
   hw/arm/faraday_a369.c - hw/arm/ftplat_a369.c
   hw/arm/faraday_a369_soc.c - hw/arm/ftplat_a369soc.c
   hw/arm/faraday_a369_scu.c - hw/arm/ftplat_a369scu.c
   hw/arm/faraday_a369_kpd.c - hw/arm/ftplat_a369kpd.c
3. hw: audio_codec.[ch] - audio.[ch]
4. hw/fti2c010: Drop .addr from Fti2c010State. (Addressed by Peter.C)
5. hw/fti2c010: Add qemu_log_mask(LOG_UNIMP, ) to slave mode. (Addressed by 
Peter.C)
6. hw/fti2c010: Update data type of Fti2c010State.recv from 'uint8_t' into 
'bool'.
7. hw/*.c: QOM Coding Conventions (Addressed by Peter.C)
8. hw/*.h: Inlcudes bitops only if they need it. (Addressed by Peter.C)
9. hw/ftplat_a369soc: Add a container memory region for remappable devices. 
(i.e. ROM, RAM)
   (Addressed by Peter.C and Peter.M)
10. hw/faraday.h: Drop cpu, cpu_model, ahb_remapped, ddr_inited, rom_size, 
ram_size 
scu, ahbc, ddrc from FaradaySoCState.
11. hw/faraday.h: Replace FaradaySoCState.bi with FaradaySoCState.ram_boot
12. hw/arm/ftplat_a369soc: Move customized system reset to ftplat_a369.c
13. hw/faraday.h: Add faraday_soc_ahb_remap() and faraday_soc_ram_setup()
for ftddrii030, ftahbc020, ftplat_a369soc and ftplat_a369.
14. hw/ftahbc020, ftapbbrg020, ftddrii030, ftnandc021, ftssp010.c:
Move object_property_add_link() to object::instance_init()

Changes for v7 - v8:
1. [hw/arm/ftintc020.c] (Addressed by Peter)
   'uint32_t mask = BIT(irq % 32);' - 'uint32_t mask = BIT(irq  0x1f);'
2. [hw/arm/*.c] (Addressed by Peter)
   Drop '#include faraday.h', and define DPRINTF() at per-file basis
   exit(1) - abort()
   SysBusDeviceClass::init() - Device::realize()

Changes for v6 - v7:

1. hw/arm/ftwdt010: (Addressed by Paolo)
   Replace 'qemu_system_reset_request()' with 'watchdog_perform_action()'.
2. hw/arm/ftrtc011: (Addressed by Paolo)
   Replace 'get_clock_realtime()' with 'qemu_get_clock_ns(rtc_clock)'.
   Replace 'qemu_new_timer_ms(rt_clock...)' with 
'qemu_new_timer_ms(rtc_clock...)'
   Rename 'ftrtc011_timer_resync' - 'ftrtc011_timer_rebase'
   Add ftrtc011_timer_resche()
   Add QTest support
3. hw/arm/faraday_a369_soc: (Addressed by Paolo)
   Remove redundant device reset from a369soc_system_reset(...)
4. include/qemu/bitops.h: (Addressed by Paolo)
   Update bitrev8() to use a kind of divide and conquer algorithm.
5. hw/arm/ftahb020,ftddrii030,ftapbbrg020,faraday_a369_soc:
   Drop FARADAY_SOC_GET_CORE(), replaced with device to device QOM link.
6. hw/wm8731,wm8750,marvell_88w8618_audio,spitz,z2:
   Add AudioCodecClass for wm87xx audio class abstration.
7. hw/arm/ftnandc021:
   Drop nand_init(), replaced with device to device QOM link.
8. hw/arm/ftsdc010:
   Bug fixed to write operation: remove sd_data_ready() in write path.
9. hw/arm/ftgmac100,ftmac110,ftwdt010:
   rt-clock - vm_clock
   10. hw/nand.c:
   Drop [hw/nand.c: correct the sense of the BUSY/READY], since it's 
already applied.
   Drop [hw/nand.c: bug fix to erase operation], since Peter has a better 
solution.

Changes for v5 - v6:

   1. hw/arm/Makefile.objs: 
   Shift to the next line only after current line length is  80 characters.
   2. hw/arm/faraday.h:
   Update debug macro format per discussions at the link bellow:
   http://thread.gmane.org/gmane.comp.emulators.qemu/195996/focus

[Qemu-devel] [PATCH v9 20/24] hw/arm: add FTTSC010 touchscreen controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTSC010 provides two operation modes to sample
the analog input voltage.

  1. The manual operation mode needs to program
 and control the panel drivers by software
 step-by-step for the x-y position measurement.

  2. The auto-scan mode provides a periodic sampling
 method to convert the analog input.

This patch only implements the auto-scan mode.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |3 +
 hw/fttsc010.c   |  264 +++
 hw/fttsc010.h   |   39 +++
 4 files changed, 307 insertions(+), 1 deletion(-)
 create mode 100644 hw/fttsc010.c
 create mode 100644 hw/fttsc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f6b947e..d163239 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,7 +26,7 @@ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
-ftssp010.o ftgmac100.o ftlcdc200.o
+ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index cdc6d4a..231ea1e 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -238,6 +238,9 @@ static void a369soc_chip_init(FaradaySoCState *s)
   s-pic[23], /* FIFO Under-Run */
   s-pic[22], /* AHB Bus Error */
   NULL);
+
+/* fttsc010 */
+sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/fttsc010.c b/hw/fttsc010.c
new file mode 100644
index 000..02b7ec2
--- /dev/null
+++ b/hw/fttsc010.c
@@ -0,0 +1,264 @@
+/*
+ * Faraday FTTSC010 emulator.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include ui/console.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include hw/fttsc010.h
+
+#define X_AXIS_DMAX 3470
+#define X_AXIS_MIN  290
+#define Y_AXIS_DMAX 3450
+#define Y_AXIS_MIN  200
+
+#define ADS_XPOS(x, y)  \
+(X_AXIS_MIN + ((X_AXIS_DMAX * (x))  15))
+#define ADS_YPOS(x, y)  \
+(Y_AXIS_MIN + ((Y_AXIS_DMAX * (y))  15))
+#define ADS_Z1POS(x, y) \
+(8)
+#define ADS_Z2POS(x, y) \
+((1600 + ADS_XPOS(x, y)) * ADS_Z1POS(x, y) / ADS_XPOS(x, y))
+
+#define TYPE_FTTSC010   fttsc010
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Fttsc010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint64_t interval;
+QEMUTimer *qtimer;
+
+int x, y;
+int z1, z2;
+uint32_t freq;
+
+/* HW registers */
+uint32_t regs[CFG_REGSIZE];
+} Fttsc010State;
+
+#define FTTSC010(obj) \
+OBJECT_CHECK(Fttsc010State, obj, TYPE_FTTSC010)
+
+#define TSC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static void fttsc010_update_irq(Fttsc010State *s)
+{
+qemu_set_irq(s-irq, !!(TSC_REG32(s, REG_IMR)  TSC_REG32(s, REG_ISR)));
+}
+
+static uint64_t
+fttsc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t ret = 0;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR ... REG_DCR:
+ret = s-regs[addr / 4];
+break;
+case REG_XYR:
+ret = deposit32(ret,  0, 12, s-x);
+ret = deposit32(ret, 16, 12, s-y);
+break;
+case REG_ZR:
+ret = deposit32(ret,  0, 12, s-z1);
+ret = deposit32(ret, 16, 12, s-z2);
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fttsc010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fttsc010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+uint32_t dly, sdiv, mdiv;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR:
+TSC_REG32(s, REG_CR) = (uint32_t)val;
+if (TSC_REG32(s, REG_CR)  (CR_AS | CR_RD1)) {
+/* ADC conversion delay with frame number */
+dly = extract32(TSC_REG32(s, REG_DCR), 0, 16);
+/* ADC sample clock divider */
+sdiv = extract32(TSC_REG32(s, REG_CSR), 8, 8);
+/* ADC main clock divider */
+mdiv = extract32(TSC_REG32(s, REG_CSR), 0, 8);
+/* Calculate sample rate/timer interval */
+s-interval = s-freq / ((mdiv + 1) * (sdiv + 1) * (dly + 1) * 64);
+s-interval = MAX(1ULL, s-interval);
+qemu_mod_timer(s-qtimer,
+s-interval + qemu_get_clock_ms(vm_clock

[Qemu-devel] [PATCH v9 07/24] hw/arm: add FTWDT010 watchdog timer support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTWDT010 is used to prevent system from infinite loop
while software gets trapped in the deadlock.

Under the normal operation, users should restart FTWDT010
at the regular intervals before counter counts down to 0.

If the counter does reach 0, FTWDT010 will try to reset
the system by generating one or a combination of signals,
system reset, system interrupt, and external interrupt.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369.c|8 ++
 hw/arm/ftplat_a369soc.c |3 +
 hw/ftwdt010.c   |  213 +++
 hw/ftwdt010.h   |   35 
 5 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftwdt010.c
 create mode 100644 hw/ftwdt010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 4fe0222..22f0c64 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,7 +24,7 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
-obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o
+obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index 6f00c82..45f0846 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -19,6 +19,11 @@
 
 #include hw/faraday.h
 
+static void a369_system_reset(void *opaque)
+{
+cpu_reset(CPU(opaque));
+}
+
 /* Board init.  */
 
 static void a369_board_init(QEMUMachineInitArgs *args)
@@ -57,6 +62,9 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 vmstate_register_ram_global(s-ram);
 qdev_init_nofail(ds);
 
+/* Customized system reset */
+qemu_register_reset(a369_system_reset, cpu);
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 6e2ea65..56f0920 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -147,6 +147,9 @@ static void a369soc_chip_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
+
+/* ftwdt010 */
+sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftwdt010.c b/hw/ftwdt010.c
new file mode 100644
index 000..cdbe2f3
--- /dev/null
+++ b/hw/ftwdt010.c
@@ -0,0 +1,213 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/watchdog.h
+#include sysemu/sysemu.h
+#include qemu/timer.h
+
+#include hw/ftwdt010.h
+
+#define TYPE_FTWDT010   ftwdt010
+
+typedef struct Ftwdt010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+qemu_irq irq;
+
+QEMUTimer *qtimer;
+
+uint64_t timeout;
+uint64_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+bool running;
+
+/* HW register cache */
+uint32_t load;
+uint32_t cr;
+uint32_t sr;
+} Ftwdt010State;
+
+#define FTWDT010(obj) \
+OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
+
+static uint64_t
+ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_COUNTER:
+if (s-cr  CR_EN) {
+ret = s-timeout - qemu_get_clock_ms(rt_clock);
+ret = MIN(s-load, ret * 100ULL / s-step);
+} else {
+ret = s-load;
+}
+break;
+case REG_LOAD:
+return s-load;
+case REG_CR:
+return s-cr;
+case REG_SR:
+return s-sr;
+case REG_REVR:
+return 0x00010601;  /* rev. 1.6.1 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+
+switch (addr) {
+case REG_LOAD:
+s-load = (uint32_t)val;
+break;
+case REG_RESTART:
+if ((s-cr  CR_EN)  (val == WDT_MAGIC)) {
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+}
+break;
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_EN) {
+if (s-running) {
+break;
+}
+s-running = true;
+s-timeout

[Qemu-devel] [PATCH v9 06/24] hw/arm: add FTPWMTMR010 timer support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTPWMTMR010 is an APB device which provides up to 8 independent timers.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |   10 ++
 hw/ftpwmtmr010.c|  261 +++
 hw/ftpwmtmr010.h|   31 ++
 4 files changed, 303 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftpwmtmr010.c
 create mode 100644 hw/ftpwmtmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index e774962..4fe0222 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,7 +24,7 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
-obj-y += ftintc020.o ftahbc020.o ftddrii030.o
+obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index b2da582..6e2ea65 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -137,6 +137,16 @@ static void a369soc_chip_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 abort();
 }
+
+/* Timer */
+ds = qdev_create(NULL, ftpwmtmr010);
+qdev_prop_set_uint32(ds, freq, 66 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9230);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, s-pic[8]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftpwmtmr010.c b/hw/ftpwmtmr010.c
new file mode 100644
index 000..d08eaa6
--- /dev/null
+++ b/hw/ftpwmtmr010.c
@@ -0,0 +1,261 @@
+/*
+ * Faraday FTPWMTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include hw/ftpwmtmr010.h
+
+#define TYPE_FTPWMTMR010ftpwmtmr010
+#define TYPE_FTPWMTMR010_TIMER  ftpwmtmr010_timer
+
+typedef struct Ftpwmtmr010State Ftpwmtmr010State;
+
+typedef struct Ftpwmtmr010Timer {
+uint32_t ctrl;
+uint32_t cntb;
+int id;
+uint64_t timeout;
+uint64_t countdown;
+qemu_irq irq;
+QEMUTimer *qtimer;
+Ftpwmtmr010State *chip;
+} Ftpwmtmr010Timer;
+
+struct Ftpwmtmr010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+Ftpwmtmr010Timer timer[8];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+uint32_t stat;
+};
+
+#define FTPWMTMR010(obj) \
+OBJECT_CHECK(Ftpwmtmr010State, obj, TYPE_FTPWMTMR010)
+
+static uint64_t
+ftpwmtmr010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t ret = 0;
+
+switch (addr) {
+case REG_SR:
+ret = s-stat;
+break;
+case REG_REVR:
+ret = 0x;   /* Rev. 0.0.0 (no rev. id) */
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+return t-ctrl;
+case REG_TIMER_CNTB:
+return t-cntb;
+case REG_TIMER_CNTO:
+if ((t-ctrl  TIMER_CTRL_START)  (t-timeout  now)) {
+ret = (t-timeout - now) / s-step;
+}
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftpwmtmr010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+int i;
+
+switch (addr) {
+case REG_SR:
+s-stat = ~((uint32_t)val);
+for (i = 0; i  8; ++i) {
+if (val  BIT(i)) {
+qemu_irq_lower(s-timer[i].irq);
+}
+}
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+t-ctrl = (uint32_t)val;
+if (t-ctrl  TIMER_CTRL_UPDATE) {
+t-countdown = (uint64_t)t-cntb * s-step;
+}
+if (t-ctrl  TIMER_CTRL_START) {
+t-timeout = t-countdown + qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-timeout);
+}
+break;
+case REG_TIMER_CNTB:
+t-cntb

[Qemu-devel] [PATCH v9 04/24] hw/arm: add FTAHBC020 AHB controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It's used to manage AHB slave devices
and also the AHB remap function for slave4  slave6.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |9 ++
 hw/ftahbc020.c  |  216 +++
 3 files changed, 226 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftahbc020.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 7cdd831..b2fa20f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,7 +24,7 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
-obj-y += ftintc020.o
+obj-y += ftintc020.o ftahbc020.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 331ec2a..7f222cb 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -54,6 +54,7 @@ static void a369soc_chip_init(FaradaySoCState *s)
 int i;
 DeviceState *ds;
 DriveInfo *dinfo;
+Error *local_errp = NULL;
 
 /* Remappable Memory Region Init */
 s-rmr = g_new0(MemoryRegion, 1);
@@ -120,6 +121,14 @@ static void a369soc_chip_init(FaradaySoCState *s)
 
 /* ftkbc010 */
 sysbus_create_simple(a369-kpd, 0x92f0, s-pic[21]);
+
+/* ftahbc020 */
+ds = sysbus_create_simple(ftahbc020, 0x9400, NULL);
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftahbc020.c b/hw/ftahbc020.c
new file mode 100644
index 000..76e8b75
--- /dev/null
+++ b/hw/ftahbc020.c
@@ -0,0 +1,216 @@
+/*
+ * Faraday AHB controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include hw/faraday.h
+
+#define REG_SLAVE(n)((n) * 4)   /* Slave config (base  size) */
+#define REG_PRIR0x80/* Priority register */
+#define REG_IDLECR  0x84/* IDLE count register */
+#define REG_CR  0x88/* Control register */
+#define REG_REVR0x8c/* Revision register */
+
+#define CR_REMAP0x01/* Enable AHB remap for slave 4  6 */
+
+#define TYPE_FTAHBC020  ftahbc020
+
+typedef struct Ftahbc020State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+
+/* HW register cache */
+uint32_t prir;  /* Priority register */
+uint32_t cr;/* Control register */
+} Ftahbc020State;
+
+#define FTAHBC020(obj) \
+OBJECT_CHECK(Ftahbc020State, obj, TYPE_FTAHBC020)
+
+static uint64_t
+ftahbc020_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+FaradaySoCState *soc = s-soc;
+bool remapped = (soc-ram_base != (soc-ahb_slave[6]  0xfff0));
+uint64_t ret = 0;
+
+switch (addr) {
+/* slave address  window configuration */
+case REG_SLAVE(0) ... REG_SLAVE(3):
+/* fall-through - skip slave4 */
+case REG_SLAVE(5):
+/* fall-through - skip slave6 */
+case REG_SLAVE(7) ... REG_SLAVE(31):
+ret = soc-ahb_slave[addr / 4];
+break;
+case REG_SLAVE(4):
+ret = soc-rom_base | (soc-ahb_slave[4]  0x000f);
+break;
+case REG_SLAVE(6):
+ret = soc-ram_base | (soc-ahb_slave[6]  0x000f);
+break;
+/* priority register */
+case REG_PRIR:
+ret = s-prir;
+break;
+/* idle counter register */
+case REG_IDLECR:
+break;
+/* control register */
+case REG_CR:
+if (remapped) {
+s-cr |= CR_REMAP;
+}
+ret = s-cr;
+break;
+/* revision register */
+case REG_REVR:
+ret = 0x00010301;   /* rev. 1.3.1 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftahbc020: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftahbc020_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+FaradaySoCState *soc = s-soc;
+bool remapped = (soc-ram_base != (soc-ahb_slave[6]  0xfff0));
+
+switch (addr) {
+case REG_CR:/* control register */
+s-cr = (uint32_t)val;
+if (remapped  !(s-cr  CR_REMAP)) {
+fprintf(stderr,
+ftahbc020: 
+AHB remap could only be disabled via system reset!\n);
+abort();
+}
+if (!remapped  (s-cr  CR_REMAP)) {
+faraday_soc_ahb_remap(soc, true);
+}
+break;
+case

[Qemu-devel] [PATCH v9 19/24] hw/arm: add FTLCDC200 LCD controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTLCDC200 Color LCD controller performs translation of
pixel-coded data into the required formats and timings to
drive a variety of single/dual mono and color LCDs.

Depending on the LCD type and mode, the unpacked data can represent:
   1. an actual true display gray or color value
   2. an address to a 256 x 16 bit wide palette RAM gray or color value.

The FTLCDC200 generates 4 individual interrupts for:
   1. DMA FIFO underflow
   2. base address update
   3. vertical status
   4. bus error.

There is also a single combined interrupt that is raised when any of
the individual interrupts become active.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |   10 +
 hw/ftlcdc200.c  |  516 +++
 hw/ftlcdc200.h  |  110 ++
 hw/ftlcdc200_template.h |  439 
 5 files changed, 1076 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftlcdc200.c
 create mode 100644 hw/ftlcdc200.h
 create mode 100644 hw/ftlcdc200_template.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 62c823d..f6b947e 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,7 +26,7 @@ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
-ftssp010.o ftgmac100.o
+ftssp010.o ftgmac100.o ftlcdc200.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 622b1db..cdc6d4a 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -228,6 +228,16 @@ static void a369soc_chip_init(FaradaySoCState *s)
 if (nb_nics  0) {
 ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
 }
+
+/* ftlcdc200 */
+sysbus_create_varargs(ftlcdc200,
+  0x94a0,
+  s-pic[0],  /* ALL (NC in A369) */
+  s-pic[25], /* VSTATUS */
+  s-pic[24], /* Base Address Update */
+  s-pic[23], /* FIFO Under-Run */
+  s-pic[22], /* AHB Bus Error */
+  NULL);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftlcdc200.c b/hw/ftlcdc200.c
new file mode 100644
index 000..2e25372
--- /dev/null
+++ b/hw/ftlcdc200.c
@@ -0,0 +1,516 @@
+/*
+ * Faraday FTLCDC200 Color LCD Controller
+ *
+ * base is pl110.c
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under the GNU LGPL
+ */
+
+#include hw/sysbus.h
+#include hw/framebuffer.h
+#include ui/console.h
+#include ui/pixel_ops.h
+
+#include qemu/bitops.h
+#include hw/ftlcdc200.h
+
+enum ftlcdc200_irqpin {
+IRQ_ALL = 0,
+IRQ_VSTATUS,
+IRQ_BASEUPT,
+IRQ_FIFOUR,
+IRQ_BUSERR,
+};
+
+enum ftlcdc200_bppmode {
+BPP_1 = 0,
+BPP_2,
+BPP_4,
+BPP_8,
+BPP_16,
+BPP_32,
+BPP_16_565,
+BPP_12,
+};
+
+#define TYPE_FTLCDC200  ftlcdc200
+
+typedef struct Ftlcdc200State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+QemuConsole *con;
+
+qemu_irq irq[5];
+int cols;
+int rows;
+enum ftlcdc200_bppmode bpp;
+int invalidate;
+uint32_t palette[256];
+uint32_t raw_palette[128];
+
+/* hw register caches */
+uint32_t fer;   /* function enable register */
+uint32_t ppr;   /* panel pixel register */
+uint32_t ier;   /* interrupt enable register */
+uint32_t isr;   /* interrupt status register */
+uint32_t sppr;  /* serail panel pixel register */
+
+uint32_t fb[4]; /* frame buffer base address register */
+uint32_t ht;/* horizontal timing control register */
+uint32_t vt0;   /* vertital timing control register 0 */
+uint32_t vt1;   /* vertital timing control register 1 */
+uint32_t pol;   /* polarity */
+
+} Ftlcdc200State;
+
+#define FTLCDC200(obj) \
+OBJECT_CHECK(Ftlcdc200State, obj, TYPE_FTLCDC200)
+
+static const VMStateDescription vmstate_ftlcdc200 = {
+.name = TYPE_FTLCDC200,
+.version_id = 2,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_INT32(cols, Ftlcdc200State),
+VMSTATE_INT32(rows, Ftlcdc200State),
+VMSTATE_UINT32(bpp, Ftlcdc200State),
+VMSTATE_INT32(invalidate, Ftlcdc200State),
+VMSTATE_UINT32_ARRAY(palette, Ftlcdc200State, 256),
+VMSTATE_UINT32_ARRAY(raw_palette, Ftlcdc200State, 128),
+VMSTATE_UINT32(fer, Ftlcdc200State),
+VMSTATE_UINT32(ppr, Ftlcdc200State),
+VMSTATE_UINT32(ier, Ftlcdc200State),
+VMSTATE_UINT32(isr, Ftlcdc200State),
+VMSTATE_UINT32(sppr, Ftlcdc200State

[Qemu-devel] [PATCH v9 18/24] hw/arm: add FTGMAC100 1Gbps ethernet support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTGMAC100 Ethernet controller has a DMA engine which handles
all data transfers between the system memory and on-chip memories.
Its DMA engine supports both 16-bits and 32-bits alignment,
and thus make it possible to support zero-copy transfer at both
Linux and WINCE.

It also has 802.1Q VLAN tagging support for both insertion and removal.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |5 +
 hw/faraday.h|3 +
 hw/ftgmac100.c  |  712 +++
 hw/ftgmac100.h  |  237 
 5 files changed, 958 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftgmac100.c
 create mode 100644 hw/ftgmac100.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 42c8472..62c823d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,7 +26,7 @@ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
-ftssp010.o
+ftssp010.o ftgmac100.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 9391764..622b1db 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -223,6 +223,11 @@ static void a369soc_chip_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-pdma[0], 8);
 qdev_connect_gpio_out(s-pdma[0], 8, ack);
 qdev_connect_gpio_out(ds, 1, req);
+
+/* ftgmac100 */
+if (nb_nics  0) {
+ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/faraday.h b/hw/faraday.h
index 39a608c..068b799 100644
--- a/hw/faraday.h
+++ b/hw/faraday.h
@@ -124,4 +124,7 @@ static inline void faraday_soc_ahb_remap(FaradaySoCState 
*s, bool active)
 /* ftssp010.c */
 void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 
+/* ftgmac100.c */
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/ftgmac100.c b/hw/ftgmac100.c
new file mode 100644
index 000..45f8a5b
--- /dev/null
+++ b/hw/ftgmac100.c
@@ -0,0 +1,712 @@
+/*
+ * QEMU model of the FTGMAC100 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include hw/faraday.h
+#include hw/ftgmac100.h
+
+#ifndef DEBUG
+#define DEBUG   0
+#endif
+
+#define DPRINTF(fmt, ...) \
+do { \
+if (DEBUG) { \
+fprintf(stderr, fmt , ## __VA_ARGS__); \
+} \
+} while (0)
+
+#define TYPE_FTGMAC100  ftgmac100
+
+#define CFG_MAXFRMLEN   9220/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftgmac100State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t hptx_idx;
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftgmac100State;
+
+#define FTGMAC100(obj) \
+OBJECT_CHECK(Ftgmac100State, obj, TYPE_FTGMAC100)
+
+#define MAC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static int ftgmac100_mcast_hash(Ftgmac100State *s, const uint8_t *data)
+{
+#define CRCPOLY_BE0x04c11db7
+int i, len;
+uint32_t crc = 0x;
+
+len = (MAC_REG32(s, REG_MACCR)  MACCR_GMODE) ? 5 : 6;
+
+while (len--) {
+uint32_t c = *(data++);
+for (i = 0; i  8; ++i) {
+crc = (crc  1) ^ crc  31) ^ c)  0x01) ? CRCPOLY_BE : 0);
+c = 1;
+}
+}
+crc = ~crc;
+
+/* Reverse CRC32 and return MSB 6 bits only */
+return bitrev8(crc  24)  2;
+}
+
+static void
+ftgmac100_read_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+if (addr  0x0f) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: Tx desc is not 16-byte aligned!\n
+ It's fine in QEMU but the real HW would panic.\n);
+}
+
+dma_memory_read(s-dma, addr, desc, sizeof(*desc));
+
+for (i = 0; i  sizeof(*desc); i += 4) {
+*p = le32_to_cpu(*p);
+}
+
+if (desc-buf  0x01) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: tx buffer is not 16-bit aligned!\n);
+}
+}
+
+static void
+ftgmac100_write_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p

[Qemu-devel] [PATCH v9 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTDDRII030 is a DDRII SDRAM controller which is responsible for
SDRAM initialization.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |8 ++
 hw/ftddrii030.c |  192 +++
 3 files changed, 201 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftddrii030.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index b2fa20f..e774962 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,7 +24,7 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
-obj-y += ftintc020.o ftahbc020.o
+obj-y += ftintc020.o ftahbc020.o ftddrii030.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 7f222cb..b2da582 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -129,6 +129,14 @@ static void a369soc_chip_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
 abort();
 }
+
+/* ftddrii030 */
+ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftddrii030.c b/hw/ftddrii030.c
new file mode 100644
index 000..158db1f
--- /dev/null
+++ b/hw/ftddrii030.c
@@ -0,0 +1,192 @@
+/*
+ * Faraday DDRII controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include hw/faraday.h
+
+#define REG_MCR 0x00/* memory configuration register */
+#define REG_MSR 0x04/* memory status register */
+#define REG_REVR0x50/* revision register */
+
+#define MSR_INIT_OK BIT(8)  /* initialization finished */
+#define MSR_CMD_MRS BIT(0)  /* start MRS command (init. seq.) */
+
+#define CFG_REGSIZE (REG_REVR / 4)
+
+#define TYPE_FTDDRII030 ftddrii030
+
+typedef struct Ftddrii030State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftddrii030State;
+
+#define FTDDRII030(obj) \
+OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
+
+#define DDR_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static uint64_t
+ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+FaradaySoCState *soc = s-soc;
+uint64_t ret = 0;
+
+if (soc-ram_visible) {
+DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
+} else {
+DDR_REG32(s, REG_MSR) = ~MSR_INIT_OK;
+}
+
+switch (addr) {
+case REG_MCR ... REG_REVR - 4:
+ret = DDR_REG32(s, addr);
+break;
+case REG_REVR:
+ret = 0x100;/* rev. = 0.1.0 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+FaradaySoCState *soc = s-soc;
+
+switch (addr) {
+case REG_MCR:
+DDR_REG32(s, addr) = (uint32_t)val  0x;
+break;
+case REG_MSR:
+if (!soc-ram_visible  (val  MSR_CMD_MRS)) {
+val = ~MSR_CMD_MRS;
+faraday_soc_ram_setup(soc, true);
+}
+DDR_REG32(s, addr) = (uint32_t)val;
+break;
+/* SDRAM Timing, ECC ...etc. */
+case REG_MSR + 4 ... REG_REVR - 4:
+DDR_REG32(s, addr) = (uint32_t)val;
+break;
+case REG_REVR:
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mmio_ops = {
+.read  = ftddrii030_mem_read,
+.write = ftddrii030_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+}
+};
+
+static void ftddrii030_reset(DeviceState *ds)
+{
+Ftddrii030State *s = FTDDRII030(SYS_BUS_DEVICE(ds));
+Error *local_errp = NULL;
+
+s-soc = FARADAY_SOC(object_property_get_link(OBJECT(s),
+  soc,
+  local_errp));
+if (local_errp) {
+fprintf(stderr, ftahbc020: Unable to get soc link\n);
+abort

[Qemu-devel] [PATCH v9 23/24] hw/arm: add FTTMR010 timer support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTMR010 provides three independent sets of sub-timers.
Two match registers are provided for each sub-timer, whenever
the value of the match registers equals any one value of the
sub-timers, the timer interrupt will be immediately triggered.
And it would also issue an interrupt when an overflow occurs.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs |2 +-
 hw/arm/ftplat_a369.c |8 +
 hw/fttmr010.c|  449 ++
 hw/fttmr010.h|   39 +
 4 files changed, 497 insertions(+), 1 deletion(-)
 create mode 100644 hw/fttmr010.c
 create mode 100644 hw/fttmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 4697a76..bcfb70a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -27,7 +27,7 @@ obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
 ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o \
-ftmac110.o
+ftmac110.o fttmr010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index 1b3e3cd..f22e2ca 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -117,6 +117,14 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
 }
 
+/* Timer: FTTMR010 */
+ds = qdev_create(NULL, fttmr010);
+qdev_prop_set_uint32(ds, freq, 33 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0xC020);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/fttmr010.c b/hw/fttmr010.c
new file mode 100644
index 000..ccb0c6a
--- /dev/null
+++ b/hw/fttmr010.c
@@ -0,0 +1,449 @@
+/*
+ * Faraday FTTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include hw/fttmr010.h
+
+#define TYPE_FTTMR010   fttmr010
+#define TYPE_FTTMR010_TIMER fttmr010_timer
+
+typedef struct Fttmr010State Fttmr010State;
+
+typedef struct Fttmr010Timer {
+int id;
+int up;
+Fttmr010State *chip;
+qemu_irq irq;
+QEMUTimer *qtimer;
+uint64_t start;
+uint32_t intr_match1:1;
+uint32_t intr_match2:1;
+
+/* HW register caches */
+uint64_t counter;
+uint64_t reload;
+uint32_t match1;
+uint32_t match2;
+
+} Fttmr010Timer;
+
+struct Fttmr010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+qemu_irq irq;
+Fttmr010Timer timer[3];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+
+/* HW register caches */
+uint32_t cr;
+uint32_t isr;
+uint32_t imr;
+};
+
+#define FTTMR010(obj) \
+OBJECT_CHECK(Fttmr010State, obj, TYPE_FTTMR010)
+
+static void fttmr010_timer_restart(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t interval;
+int pending = 0;
+
+t-intr_match1 = 0;
+t-intr_match2 = 0;
+
+/* check match1 */
+if (t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (!t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (t-match1 == t-counter) {
+s-isr |= ISR_MATCH1(t-id);
+++pending;
+}
+
+/* check match2 */
+if (t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (!t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (t-match2 == t-counter) {
+s-isr |= ISR_MATCH2(t-id);
+++pending;
+}
+
+/* determine delay interval */
+if (t-up) {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = MIN(t-match1, t-match2) - t-counter;
+} else if (t-match1  t-counter) {
+interval = t-match1 - t-counter;
+} else if (t-match2  t-reload) {
+interval = t-match2 - t-counter;
+} else {
+interval = 0xULL - t-counter;
+}
+} else {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = t-counter - MAX(t-match1, t-match2);
+} else if (t-match1  t-reload) {
+interval = t-counter - t-match1;
+} else if (t-match2  t-reload) {
+interval = t-counter - t-match2;
+} else {
+interval = t-counter;
+}
+}
+
+if (pending) {
+qemu_irq_pulse(s-irq);
+qemu_irq_pulse(t-irq);
+}
+t-start = qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-start

[Qemu-devel] [PATCH v9 24/24] hw/arm: add FTSPI020 SPI flash controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSPI020 is an integrated SPI Flash controller
which supports up to 4 flash chips.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs |2 +-
 hw/arm/ftplat_a369.c |   16 +++
 hw/ftspi020.c|  341 ++
 hw/ftspi020.h|   81 
 4 files changed, 439 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftspi020.c
 create mode 100644 hw/ftspi020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bcfb70a..a34ca41 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -27,7 +27,7 @@ obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
 ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o \
-ftmac110.o fttmr010.o
+ftmac110.o fttmr010.o ftspi020.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index f22e2ca..77cd44d 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -125,6 +125,22 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
 
+/* SPI: FTSPI020 */
+ds = sysbus_create_simple(ftspi020, 0xC000, s-pic[4]);
+s-spi_fl[0] = ds;
+
+/* Attach the spi flash to ftspi020.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi_fl[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi_fl[0]), i + 1, cs_line);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/ftspi020.c b/hw/ftspi020.c
new file mode 100644
index 000..a7253bd
--- /dev/null
+++ b/hw/ftspi020.c
@@ -0,0 +1,341 @@
+/*
+ * Faraday FTSPI020 Flash Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/ssi.h
+#include sysemu/sysemu.h
+
+#include hw/ftspi020.h
+
+#define TYPE_FTSPI020   ftspi020
+
+typedef struct Ftspi020State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+SSIBus *spi;
+qemu_irq *cs_lines;
+
+int wip;/* SPI Flash Status: Write In Progress BIT shift */
+
+/* HW register caches */
+uint32_t cmd[4];
+uint32_t ctrl;
+uint32_t timing;
+uint32_t icr;
+uint32_t isr;
+uint32_t rdsr;
+} Ftspi020State;
+
+#define FTSPI020(obj) \
+OBJECT_CHECK(Ftspi020State, obj, TYPE_FTSPI020)
+
+static void ftspi020_update_irq(Ftspi020State *s)
+{
+qemu_set_irq(s-irq, s-isr ? 1 : 0);
+}
+
+static void ftspi020_handle_ack(void *opaque, int line, int level)
+{
+Ftspi020State *s = FTSPI020(opaque);
+
+if (!(s-icr  ICR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-cmd[2]) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static int ftspi020_do_command(Ftspi020State *s)
+{
+uint32_t cs   = extract32(s-cmd[3],  8, 2);
+uint32_t cmd  = extract32(s-cmd[3], 24, 8);
+uint32_t ilen = extract32(s-cmd[1], 24, 2);
+uint32_t alen = extract32(s-cmd[1],  0, 3);
+uint32_t dcyc = extract32(s-cmd[1], 16, 8);
+
+if (dcyc % 8) {
+fprintf(stderr, ftspi020: bad dummy clock (%u) to QEMU\n, dcyc);
+abort();
+}
+
+/* activate the spi flash */
+qemu_set_irq(s-cs_lines[cs], 0);
+
+/* if it's a SPI flash READ_STATUS command */
+if ((s-cmd[3]  (CMD3_RDSR | CMD3_WRITE)) == CMD3_RDSR) {
+uint32_t rdsr;
+
+ssi_transfer(s-spi, cmd);
+do {
+rdsr = ssi_transfer(s-spi, 0x00);
+if (s-cmd[3]  CMD3_RDSR_SW) {
+break;
+}
+} while (rdsr  (1  s-wip));
+s-rdsr = rdsr;
+} else {
+/* otherwise */
+int i;
+
+ilen = MIN(ilen, 2);
+alen = MIN(alen, 4);
+
+/* command cycles */
+for (i = 0; i  ilen; ++i) {
+ssi_transfer(s-spi, cmd);
+}
+/* address cycles */
+for (i = alen - 1; i = 0; --i) {
+ssi_transfer(s-spi, extract32(s-cmd[0], i * 8, 8));
+}
+/* dummy cycles */
+for (i = 0; i  (dcyc  3); ++i) {
+ssi_transfer(s-spi, 0x00);
+}
+}
+
+if (!s-cmd[2]) {
+qemu_set_irq(s-cs_lines[cs], 1);
+} else if (s-icr  ICR_DMA) {
+qemu_set_irq(s-req, 1);
+}
+
+if (s-cmd[3]  CMD3_INTR) {
+s-isr

[Qemu-devel] [PATCH v9 21/24] hw/arm: add FTSDC010 MMC/SD controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSDC010 is a simple MMC/SD host controller and
many of its registers are similar to Arm PrimeCell PL181.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |7 +
 hw/ftsdc010.c   |  359 +++
 hw/ftsdc010.h   |   88 
 4 files changed, 455 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftsdc010.c
 create mode 100644 hw/ftsdc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index d163239..93e94db 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,7 +26,7 @@ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
-ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o
+ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 231ea1e..21387df 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -241,6 +241,13 @@ static void a369soc_chip_init(FaradaySoCState *s)
 
 /* fttsc010 */
 sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
+
+/* ftsdc010 */
+ds = sysbus_create_simple(ftsdc010, 0x9060, s-pic[39]);
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 13);
+qdev_connect_gpio_out(s-hdma[0], 13, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftsdc010.c b/hw/ftsdc010.c
new file mode 100644
index 000..8b93fa6
--- /dev/null
+++ b/hw/ftsdc010.c
@@ -0,0 +1,359 @@
+/*
+ * QEMU model of the FTSDC010 MMC/SD Host Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/sd.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include qemu/bitops.h
+#include hw/ftsdc010.h
+
+#define TYPE_FTSDC010   ftsdc010
+
+typedef struct Ftsdc010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+SDState *card;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint32_t datacnt;
+
+/* HW register cache */
+uint32_t cmd;
+uint32_t arg;
+uint32_t rsp[4];
+uint32_t rspcmd;
+uint32_t dcr;
+uint32_t dtr;
+uint32_t dlr;
+uint32_t status;
+uint32_t ier;
+uint32_t pwr;
+uint32_t clk;
+} Ftsdc010State;
+
+#define FTSDC010(obj) \
+OBJECT_CHECK(Ftsdc010State, obj, TYPE_FTSDC010)
+
+static void ftsdc010_update_irq(Ftsdc010State *s)
+{
+qemu_set_irq(s-irq, !!(s-ier  s-status));
+}
+
+static void ftsdc010_handle_ack(void *opaque, int line, int level)
+{
+Ftsdc010State *s = FTSDC010(opaque);
+
+if (!(s-dcr  DCR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static void ftsdc010_send_command(Ftsdc010State *s)
+{
+SDRequest request;
+uint8_t response[16];
+int rlen;
+
+request.cmd = s-cmd  CMD_IDX;
+request.arg = s-arg;
+
+rlen = sd_do_command(s-card, request, response);
+if (rlen  0) {
+goto error;
+}
+if (s-cmd  CMD_WAIT_RSP) {
+#define RWORD(n) ((response[n]  24) | (response[n + 1]  16) \
+  | (response[n + 2]  8) | response[n + 3])
+if (rlen == 0 || (rlen == 4  (s-cmd  CMD_LONG_RSP))) {
+goto error;
+}
+if (rlen != 4  rlen != 16) {
+goto error;
+}
+if (rlen == 4) {
+s-rsp[0] = RWORD(0);
+s-rsp[1] = s-rsp[2] = s-rsp[3] = 0;
+} else {
+s-rsp[3] = RWORD(0);
+s-rsp[2] = RWORD(4);
+s-rsp[1] = RWORD(8);
+s-rsp[0] = RWORD(12)  ~1;
+}
+s-rspcmd  = (s-cmd  CMD_IDX);
+s-rspcmd |= (s-cmd  CMD_APP) ? RSP_CMDAPP : 0;
+s-status |= SR_RSP;
+#undef RWORD
+} else {
+s-status |= SR_CMD;
+}
+
+if ((s-dcr  DCR_DMA)  s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+
+return;
+
+error:
+s-status |= SR_RSP_TIMEOUT;
+}
+
+static void ftsdc010_chip_reset(Ftsdc010State *s)
+{
+s-cmd = 0;
+s-arg = 0;
+s-rsp[0] = 0;
+s-rsp[1] = 0;
+s-rsp[2] = 0;
+s-rsp[3] = 0;
+s-rspcmd = 0;
+s-dcr = 0;
+s-dtr = 0;
+s-dlr = 0;
+s-datacnt = 0;
+s-status = ~(SR_CARD_REMOVED | SR_WPROT);
+s-status |= SR_TXRDY | SR_RXRDY;
+s-ier = 0;
+s-pwr = 0;
+s-clk = 0;
+}
+
+static uint64_t ftsdc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftsdc010State *s = FTSDC010(opaque

[Qemu-devel] [PATCH v9 02/24] hw/arm: add Faraday a369 SoC platform support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday A369 EVB is a Faraday SoC platform evalution board used for
Faraday IP functional verification based on the well-known ARM AMBA 2.0
architecture.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +
 hw/arm/ftplat_a369.c|   96 +++
 hw/arm/ftplat_a369kpd.c |  235 +++
 hw/arm/ftplat_a369scu.c |  186 +
 hw/arm/ftplat_a369soc.c |  155 +++
 hw/faraday.h|  124 +
 hw/ftkbc010.h   |   44 +
 7 files changed, 842 insertions(+)
 create mode 100644 hw/arm/ftplat_a369.c
 create mode 100644 hw/arm/ftplat_a369kpd.c
 create mode 100644 hw/arm/ftplat_a369scu.c
 create mode 100644 hw/arm/ftplat_a369soc.c
 create mode 100644 hw/faraday.h
 create mode 100644 hw/ftkbc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f5f7d0e..09217c6 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -34,3 +34,5 @@ obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o
+
+obj-y += ftplat_a369.o ftplat_a369soc.o ftplat_a369scu.o ftplat_a369kpd.o
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
new file mode 100644
index 000..6f00c82
--- /dev/null
+++ b/hw/arm/ftplat_a369.c
@@ -0,0 +1,96 @@
+/*
+ * Faraday A369 Evalution Board
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/arm-misc.h
+#include hw/devices.h
+#include hw/i2c.h
+#include hw/boards.h
+#include hw/ssi.h
+#include net/net.h
+#include sysemu/sysemu.h
+#include exec/address-spaces.h
+
+#include hw/faraday.h
+
+/* Board init.  */
+
+static void a369_board_init(QEMUMachineInitArgs *args)
+{
+ARMCPU *cpu;
+DeviceState *ds;
+FaradaySoCState *s;
+
+if (!args-cpu_model) {
+args-cpu_model = fa626te;
+}
+
+if (!args-ram_size) {
+args-ram_size = 512  20;
+}
+
+/* CPU */
+cpu = cpu_arm_init(args-cpu_model);
+if (!cpu) {
+fprintf(stderr, a369: Unable to find CPU definition\n);
+abort();
+}
+
+/* SoC */
+ds = qdev_create(NULL, TYPE_FARADAY_SOC);
+s = FARADAY_SOC(ds);
+/* Setup QOM path for the SoC object (i.e. /machine/faraday.soc) */
+object_property_add_child(qdev_get_machine(),
+  TYPE_FARADAY_SOC,
+  OBJECT(ds),
+  NULL);
+s-cpu_pic = arm_pic_init_cpu(cpu);
+s-as  = get_system_memory();
+s-ram = g_new0(MemoryRegion, 1);
+memory_region_init_ram(s-ram, TYPE_FARADAY_SOC .ram, args-ram_size);
+vmstate_register_ram_global(s-ram);
+qdev_init_nofail(ds);
+
+/* System start-up */
+
+if (args-kernel_filename) {
+struct arm_boot_info *bi = g_new0(struct arm_boot_info, 1);
+
+s-ram_boot = true;
+
+faraday_soc_ram_setup(s, true);
+
+faraday_soc_ahb_remap(s, true);
+
+/* Boot Info */
+bi-ram_size = args-ram_size;
+bi-kernel_filename = args-kernel_filename;
+bi-kernel_cmdline = args-kernel_cmdline;
+bi-initrd_filename = args-initrd_filename;
+bi-board_id = 0x3369;
+arm_load_kernel(cpu, bi);
+} else if (!drive_get(IF_PFLASH, 0, 0)) {
+fprintf(stderr, a369: Unable to load ROM image!\n);
+abort();
+}
+}
+
+static QEMUMachine a369_machine = {
+.name = a369,
+.desc = Faraday A369 (fa626te),
+.init = a369_board_init,
+DEFAULT_MACHINE_OPTIONS,
+};
+
+static void a369_machine_init(void)
+{
+qemu_register_machine(a369_machine);
+}
+
+machine_init(a369_machine_init);
diff --git a/hw/arm/ftplat_a369kpd.c b/hw/arm/ftplat_a369kpd.c
new file mode 100644
index 000..6d42dfa
--- /dev/null
+++ b/hw/arm/ftplat_a369kpd.c
@@ -0,0 +1,235 @@
+/*
+ * Faraday FTKBC010 emulator for A369.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * In A369 EVB, the FTKBC010 is configured as a keypad controller.
+ * It acts like a group of hard wired buttons on the board, each of them
+ * is monitored by the FTKBC010, and coordinated as (x, y).
+ * However there is a pinmux issue in A369 EVB, the Y-axis usually
+ * malfunctioned, so there are only 3 button emulated here.
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include ui/console.h
+#include sysemu/sysemu.h
+
+#include hw/ftkbc010.h
+
+#define CFG_REGSIZE (0x3c / 4)
+
+/* Key codes */
+#define KEYCODE_ESC 1
+#define KEYCODE_BACKSPACE   14
+#define KEYCODE_ENTER   28
+#define KEYCODE_SPACE   57
+#define KEYCODE_MENU139/* Menu

[Qemu-devel] [PATCH v9 22/24] hw/arm: add FTMAC110 10/100Mbps ethernet support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTMAC110 is an Ethernet controller that provides AHB master capability
and is in full compliance with the IEEE 802.3 10/100 Mbps specifications.
Its DMA controller handles all data transfers between system memory
and on-chip memories.

It supports half-word data transfer for Linux. However it has a weird DMA
alignment issue:

(1) Tx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: O.K

(2) Rx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: Invalid (It means 0x0, 0x4, 0x8, 0xC are invalid)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs |3 +-
 hw/arm/ftplat_a369.c |7 +
 hw/faraday.h |3 +
 hw/ftmac110.c|  665 ++
 hw/ftmac110.h|  166 +
 5 files changed, 843 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftmac110.c
 create mode 100644 hw/ftmac110.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 93e94db..4697a76 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,7 +26,8 @@ obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
 ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
-ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o
+ftssp010.o ftgmac100.o ftlcdc200.o fttsc010.o ftsdc010.o \
+ftmac110.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index 922fb55..1b3e3cd 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -110,6 +110,13 @@ static void a369_board_init(QEMUMachineInitArgs *args)
  s-i2s[0]);
 }
 
+/* External AHB devices */
+
+/* Ethernet: FTMAC110 */
+if (nb_nics  1) {
+ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/faraday.h b/hw/faraday.h
index 068b799..ba7ea0e 100644
--- a/hw/faraday.h
+++ b/hw/faraday.h
@@ -127,4 +127,7 @@ void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 /* ftgmac100.c */
 void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
 
+/* ftmac110.c */
+void ftmac110_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/ftmac110.c b/hw/ftmac110.c
new file mode 100644
index 000..de1164d
--- /dev/null
+++ b/hw/ftmac110.c
@@ -0,0 +1,665 @@
+/*
+ * QEMU model of the FTMAC110 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+/***/
+/*   FTMAC110 DMA design issue */
+/* Dante Su 2010.02.03 */
+/* */
+/* The DMA engine has a weird restriction that its Rx DMA engine   */
+/* accepts only 16-bits aligned address, 32-bits aligned is still  */
+/* invalid. However this restriction does not apply to Tx DMA. */
+/* Conclusion: */
+/* (1) Tx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: O.K (- u-boot ZeroCopy is possible)   */
+/* (2) Rx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: Invalid*/
+/***/
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include hw/faraday.h
+#include hw/ftmac110.h
+
+#ifndef DEBUG
+#define DEBUG   0
+#endif
+
+#define DPRINTF(fmt, ...) \
+do { \
+if (DEBUG) { \
+fprintf(stderr, fmt , ## __VA_ARGS__); \
+} \
+} while (0)
+
+#define TYPE_FTMAC110   ftmac110
+
+#define CFG_MAXFRMLEN   1536/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftmac110State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs

[Qemu-devel] [PATCH v9 17/24] qemu/bitops.h: add the bit ordering reversal functions

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 include/qemu/bitops.h |   59 -
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index affcc96..64cbb04 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2010 Corentin Chary corentin.ch...@gmail.com
  *
- * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
+ * Mostly inspired by (stolen from) linux/bitmap.h, linux/bitops.h
+ * and linux/bitrev.h
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
@@ -273,4 +274,60 @@ static inline uint64_t deposit64(uint64_t value, int 
start, int length,
 return (value  ~mask) | ((fieldval  start)  mask);
 }
 
+/**
+ * bitrev8:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 8 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint8_t bitrev8(uint8_t value)
+{
+value = (value  0xF0)  4 | (value  0x0F)  4;
+value = (value  0xCC)  2 | (value  0x33)  2;
+value = (value  0xAA)  1 | (value  0x55)  1;
+return value;
+}
+
+/**
+ * bitrev16:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 16 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint16_t bitrev16(uint16_t value)
+{
+return (bitrev8(value  0xff)  8) | bitrev8(value  8);
+}
+
+/**
+ * bitrev32:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 32 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint32_t bitrev32(uint32_t value)
+{
+return (bitrev16(value  0x)  16) | bitrev16(value  16);
+}
+
+/**
+ * bitrev64:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 64 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint64_t bitrev64(uint64_t value)
+{
+return ((uint64_t)bitrev32(value  0xULL)  32)
+| (uint64_t)bitrev32(value  32);
+}
+
 #endif
-- 
1.7.9.5




[Qemu-devel] [PATCH v9 10/24] hw/arm: add FTDMAC020 AHB DMA support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday FTDMAC020 provides eight configurable
channels for the memory-to-memory, memory-to-peripheral,
peripheral-to-peripheral, and peripheral-to-memory transfers.

Each DMA channel supports chain transfer and can be programmed
to one of the 16 handshaking channels in the hardware handshake mode.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |   14 ++
 hw/ftdmac020.c  |  599 +++
 hw/ftdmac020.h  |  107 +
 4 files changed, 721 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftdmac020.c
 create mode 100644 hw/ftdmac020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6a41b21..6510c51 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,7 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-ftrtc011.o
+ftrtc011.o ftdmac020.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index bd696c4..59e2c61 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -168,6 +168,20 @@ static void a369soc_chip_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
 /* Hour (Edge) */
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
+
+/* ftdmac020 */
+s-hdma[0] = sysbus_create_varargs(ftdmac020,
+   0x9030,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[15], /* TC */
+   s-pic[16], /* ERR */
+   NULL);
+s-hdma[1] = sysbus_create_varargs(ftdmac020,
+   0x9610,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[17], /* TC */
+   s-pic[18], /* ERR */
+   NULL);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftdmac020.c b/hw/ftdmac020.c
new file mode 100644
index 000..81b49b2
--- /dev/null
+++ b/hw/ftdmac020.c
@@ -0,0 +1,599 @@
+/*
+ * QEMU model of the FTDMAC020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTDMAC020 descending address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include hw/ftdmac020.h
+
+#define TYPE_FTDMAC020ftdmac020
+
+enum ftdmac020_irqpin {
+IRQ_ALL = 0,
+IRQ_TC,
+IRQ_ERR,
+};
+
+typedef struct Ftdmac020State Ftdmac020State;
+
+/**
+ * struct Ftdmac020LLD - hardware link list descriptor.
+ * @src: source physical address
+ * @dst: destination physical addr
+ * @next: phsical address to the next link list descriptor
+ * @ctrl: control field
+ * @size: transfer size
+ *
+ * should be word aligned
+ */
+typedef struct Ftdmac020LLD {
+uint32_t src;
+uint32_t dst;
+uint32_t next;
+uint32_t ctrl;
+uint32_t size;
+} Ftdmac020LLD;
+
+typedef struct Ftdmac020Chan {
+Ftdmac020State *chip;
+
+int id;
+int burst;
+int llp_cnt;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register cache */
+uint32_t ccr;
+uint32_t cfg;
+uint32_t src;
+uint32_t dst;
+uint32_t llp;
+uint32_t len;
+} Ftdmac020Chan;
+
+typedef struct Ftdmac020State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+qemu_irq irq[3];
+
+Ftdmac020Chan chan[8];
+qemu_irq  ack[16];
+uint32_t  req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+
+/* HW register cache */
+uint32_t tcisr;
+uint32_t eaisr;
+uint32_t tcsr;
+uint32_t easr;
+uint32_t cesr;
+uint32_t cbsr;
+uint32_t csr;
+uint32_t sync;
+} Ftdmac020State;
+
+#define FTDMAC020(obj) \
+OBJECT_CHECK(Ftdmac020State, obj, TYPE_FTDMAC020)
+
+static void ftdmac020_update_irq(Ftdmac020State *s)
+{
+uint32_t tc, err;
+
+/* 1. Checking TC interrupts */
+tc = s-tcisr  0xff;
+qemu_set_irq(s-irq[IRQ_TC], tc ? 1 : 0);
+
+/* 2. Checking Error/Abort interrupts */
+err = s-eaisr  0x00ff00ff;
+qemu_set_irq(s-irq[IRQ_ERR], err ? 1 : 0

[Qemu-devel] [PATCH v9 08/24] hw/arm: add FTRTC011 RTC timer support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It provides separate second, minute, hour, and day counters. The second
counter is toggled each second, the minute counter is toggled each minute,
the hour counter is toggled each hour, and the day counter is toggled each day.

The FTRTC011 provides a programmable auto-alarm function. When the second
auto-alarm function is turned on, the RTC will automatically trigger an
interrupt each second. The automatic minute and hour alarms can be turned on
as well.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|3 +-
 hw/arm/ftplat_a369soc.c |   18 +++
 hw/ftrtc011.c   |  387 +++
 hw/ftrtc011.h   |   53 +++
 4 files changed, 460 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftrtc011.c
 create mode 100644 hw/ftrtc011.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 22f0c64..6a41b21 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -24,7 +24,8 @@ obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
-obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o
+obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
+ftrtc011.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 56f0920..bd696c4 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -150,6 +150,24 @@ static void a369soc_chip_init(FaradaySoCState *s)
 
 /* ftwdt010 */
 sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
+
+/* ftrtc011 */
+ds = qdev_create(NULL, ftrtc011);
+/* Setup QOM path for QTest */
+object_property_add_child(OBJECT(s),
+  ftrtc011,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9210);
+/* Alarm (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[42]);
+/* Second (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[43]);
+/* Minute (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
+/* Hour (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftrtc011.c b/hw/ftrtc011.c
new file mode 100644
index 000..79b9021
--- /dev/null
+++ b/hw/ftrtc011.c
@@ -0,0 +1,387 @@
+/*
+ * QEMU model of the FTRTC011 RTC Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include hw/ftrtc011.h
+
+enum ftrtc011_irqpin {
+IRQ_ALARM_LEVEL = 0,
+IRQ_ALARM_EDGE,
+IRQ_SEC,
+IRQ_MIN,
+IRQ_HOUR,
+IRQ_DAY,
+};
+
+#define TYPE_FTRTC011   ftrtc011
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Ftrtc011State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+qemu_irq irq[6];
+
+QEMUTimer *qtimer;
+int64_t rtc_base;
+int64_t rtc_start;
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftrtc011State;
+
+#define FTRTC011(obj) \
+OBJECT_CHECK(Ftrtc011State, obj, TYPE_FTRTC011)
+
+#define RTC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+/* Update interrupts.  */
+static void ftrtc011_update_irq(Ftrtc011State *s)
+{
+uint32_t mask = extract32(RTC_REG32(s, REG_CR), 1, 5)
+   RTC_REG32(s, REG_ISR);
+
+qemu_set_irq(s-irq[IRQ_ALARM_LEVEL], !!(mask  ISR_ALARM));
+
+if (mask) {
+if (mask  ISR_SEC) {
+qemu_irq_pulse(s-irq[IRQ_SEC]);
+}
+if (mask  ISR_MIN) {
+qemu_irq_pulse(s-irq[IRQ_MIN]);
+}
+if (mask  ISR_HOUR) {
+qemu_irq_pulse(s-irq[IRQ_HOUR]);
+}
+if (mask  ISR_DAY) {
+qemu_irq_pulse(s-irq[IRQ_DAY]);
+}
+if (mask  ISR_ALARM) {
+qemu_irq_pulse(s-irq[IRQ_ALARM_EDGE]);
+}
+}
+}
+
+static void ftrtc011_timer_rebase(Ftrtc011State *s)
+{
+int64_t ticks = get_ticks_per_sec();
+int64_t elapsed = RTC_REG32(s, REG_SEC)
++ (60LL * RTC_REG32(s, REG_MIN))
++ (3600LL * RTC_REG32(s, REG_HOUR))
++ (86400LL * RTC_REG32(s, REG_DAY));
+
+s-rtc_base  = elapsed;
+s-rtc_start = qemu_get_clock_ns(rtc_clock);
+/* adjust to the beginning of the current second */
+s-rtc_start = s-rtc_start - (s-rtc_start % ticks);
+}
+
+static void ftrtc011_timer_update(Ftrtc011State *s)
+{
+int64_t elapsed;
+uint8_t sec, min, hr;
+uint32_t day;
+
+/* check if RTC is enabled */
+if (!(RTC_REG32(s, REG_CR)  CR_EN)) {
+return

[Qemu-devel] [PATCH v9 11/24] hw/arm: add FTAPBBRG020 APB DMA support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTAPBBRG020 supports the DMA functions for the AHB-to-AHB,
AHB-to-APB, APB-to-AHB, and APB-to-APB transactions.

The DMA engine can support up to 4 DMA channels (A, B, C, and D)
and 15 handshaking channels. A DMA channel granted by the arbiter
block is the only channel starts transfers. Each DMA channel can
be programmed to one of the 15 handshaking channels in the hardware
handshake mode to act as the source device or act as the destination
device.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |9 +
 hw/ftapbbrg020.c|  478 +++
 hw/ftapbbrg020.h|   44 +
 4 files changed, 532 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftapbbrg020.c
 create mode 100644 hw/ftapbbrg020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6510c51..34e2939 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,7 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-ftrtc011.o ftdmac020.o
+ftrtc011.o ftdmac020.o ftapbbrg020.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 59e2c61..99eb428 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -182,6 +182,15 @@ static void a369soc_chip_init(FaradaySoCState *s)
s-pic[17], /* TC */
s-pic[18], /* ERR */
NULL);
+
+/* ftapbbrg020 */
+ds = sysbus_create_simple(ftapbbrg020, 0x90f0, s-pic[14]);
+s-pdma[0] = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftapbbrg020.c b/hw/ftapbbrg020.c
new file mode 100644
index 000..efc8376
--- /dev/null
+++ b/hw/ftapbbrg020.c
@@ -0,0 +1,478 @@
+/*
+ * QEMU model of the FTAPBBRG020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTAPBBRG020 DMA descending address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include hw/faraday.h
+#include hw/ftapbbrg020.h
+
+#define TYPE_FTAPBBRG020ftapbbrg020
+
+typedef struct Ftapbbrg020State Ftapbbrg020State;
+
+typedef struct Ftapbbrg020Chan {
+Ftapbbrg020State *chip;
+
+int id;
+int burst;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register caches */
+uint32_t src;
+uint32_t dst;
+uint32_t len;
+uint32_t cmd;
+} Ftapbbrg020Chan;
+
+typedef struct Ftapbbrg020State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion iomem;
+qemu_irq irq;
+
+FaradaySoCState *soc;
+Ftapbbrg020Chan chan[4];
+qemu_irq ack[16];
+uint32_t req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+} Ftapbbrg020State;
+
+#define FTAPBBRG020(obj) \
+OBJECT_CHECK(Ftapbbrg020State, obj, TYPE_FTAPBBRG020)
+
+static uint32_t ftapbbrg020_get_isr(Ftapbbrg020State *s)
+{
+int i;
+uint32_t isr = 0;
+Ftapbbrg020Chan *chan;
+
+for (i = 0; i  4; ++i) {
+chan = s-chan + i;
+isr |= (chan-cmd  CMD_INTR_STATUS);
+}
+
+return isr;
+}
+
+static void ftapbbrg020_update_irq(Ftapbbrg020State *s)
+{
+uint32_t isr = ftapbbrg020_get_isr(s);
+
+qemu_set_irq(s-irq, isr ? 1 : 0);
+}
+
+static void ftapbbrg020_chan_cmd_decode(Ftapbbrg020Chan *c)
+{
+uint32_t tmp;
+
+/* 1. decode burst size */
+c-burst = (c-cmd  CMD_BURST4) ? 4 : 1;
+
+/* 2. decode source/destination width */
+tmp = extract32(c-cmd, 20, 2);
+if (tmp  2) {
+tmp = 2;
+}
+c-src_bw = c-dst_bw = 8  (2 - tmp);
+
+/* 3. decode source address stride */
+switch (extract32(c-cmd, 8, 2)) {
+case 0:
+c-src_stride = 0;
+break;
+case 1:
+c-src_stride = c-src_bw  3;
+break;
+case 2:
+c-src_stride = 2 * (c-src_bw  3);
+break;
+case 3:
+c-src_stride = 4 * (c-src_bw  3);
+break;
+}
+
+/* 4. decode destination address stride */
+switch (extract32(c-cmd, 12, 2

[Qemu-devel] [PATCH v9 14/24] hw: Add AudioCodecClass for wm87xx audio class abstration.

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/Makefile.objs   |1 +
 hw/arm/spitz.c |9 +++--
 hw/arm/z2.c|9 +++--
 hw/audio.c |   81 +++
 hw/audio.h |   56 +++
 hw/i2c.h   |9 -
 hw/marvell_88w8618_audio.c |   23 +++
 hw/wm8750.c|   91 ++--
 8 files changed, 211 insertions(+), 68 deletions(-)
 create mode 100644 hw/audio.c
 create mode 100644 hw/audio.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 11812c6..808e2d0 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -168,6 +168,7 @@ common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-y += audio.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index f5832be..a07dfe3 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -24,6 +24,7 @@
 #include ui/console.h
 #include block/block.h
 #include audio/audio.h
+#include hw/audio.h
 #include hw/boards.h
 #include sysemu/blockdev.h
 #include hw/sysbus.h
@@ -739,9 +740,11 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
 qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
 /* .. and to the sound interface.  */
 cpu-i2s-opaque = wm;
-cpu-i2s-codec_out = wm8750_dac_dat;
-cpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, cpu-i2s-data_req, cpu-i2s);
+cpu-i2s-codec_out = audio_codec_dac_dat;
+cpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ cpu-i2s-data_req,
+ cpu-i2s);
 }
 
 static void spitz_akita_i2c_setup(PXA2xxState *cpu)
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index cbb6d80..1fecdc5 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -23,6 +23,7 @@
 #include sysemu/blockdev.h
 #include ui/console.h
 #include audio/audio.h
+#include hw/audio.h
 #include exec/address-spaces.h
 
 #ifdef DEBUG_Z2
@@ -353,9 +354,11 @@ static void z2_init(QEMUMachineInitArgs *args)
 i2c_create_slave(bus, aer915, 0x55);
 wm = i2c_create_slave(bus, wm8750, 0x1b);
 mpu-i2s-opaque = wm;
-mpu-i2s-codec_out = wm8750_dac_dat;
-mpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, mpu-i2s-data_req, mpu-i2s);
+mpu-i2s-codec_out = audio_codec_dac_dat;
+mpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ mpu-i2s-data_req,
+ mpu-i2s);
 
 qdev_connect_gpio_out(mpu-gpio, Z2_GPIO_LCD_CS,
 qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
diff --git a/hw/audio.c b/hw/audio.c
new file mode 100644
index 000..35f99b9
--- /dev/null
+++ b/hw/audio.c
@@ -0,0 +1,81 @@
+/*
+ * Audio Codec Class
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/qdev.h
+#include hw/i2c.h
+#include hw/audio.h
+
+void audio_codec_data_req_set(DeviceState *dev,
+  void (*data_req)(void *, int, int),
+  void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(dev);
+if (k-data_req_set) {
+k-data_req_set(dev, data_req, opaque);
+}
+}
+
+void audio_codec_dac_dat(void *opaque, uint32_t sample)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_dat) {
+k-dac_dat(opaque, sample);
+}
+}
+
+uint32_t audio_codec_adc_dat(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+uint32_t ret = 0;
+if (k-adc_dat) {
+ret = k-adc_dat(opaque);
+}
+return ret;
+}
+
+void *audio_codec_dac_buffer(void *opaque, int samples)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+void *ret = NULL;
+if (k-dac_buffer) {
+ret = k-dac_buffer(opaque, samples);
+}
+return ret;
+}
+
+void audio_codec_dac_commit(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_commit) {
+k-dac_commit(opaque);
+}
+}
+
+void audio_codec_set_bclk_in(void *opaque, int new_hz)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-set_bclk_in) {
+k-set_bclk_in(opaque, new_hz);
+}
+}
+
+static const TypeInfo audio_codec_info = {
+.name  = TYPE_AUDIO_CODEC,
+.parent= TYPE_I2C_SLAVE,
+.instance_size = sizeof(AudioCodecState),
+.abstract  = true,
+.class_size= sizeof(AudioCodecClass),
+};
+
+static void audio_codec_register_types(void)
+{
+type_register_static(audio_codec_info);
+}
+
+type_init(audio_codec_register_types

[Qemu-devel] [PATCH v9 12/24] hw/arm: add FTNANDC021 nand flash controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTNANDC021 is an integrated NAND flash controller which
re-pack the NAND flash command set with a shorter built-in opcode.
It also provides a register base interface for user to easily
access the underlying NAND flash chips, and also supports HW ECC.

However the optional hardware ECC function is not implemented.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369.c|   14 ++
 hw/arm/ftplat_a369soc.c |9 +
 hw/ftnandc021.c |  526 +++
 hw/ftnandc021.h |   84 
 5 files changed, 634 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftnandc021.c
 create mode 100644 hw/ftnandc021.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 34e2939..8fe0f67 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,7 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-ftrtc011.o ftdmac020.o ftapbbrg020.o
+ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index 45f0846..827c58a 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -31,6 +31,8 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 ARMCPU *cpu;
 DeviceState *ds;
 FaradaySoCState *s;
+DriveInfo *dinfo;
+Error *local_errp = NULL;
 
 if (!args-cpu_model) {
 args-cpu_model = fa626te;
@@ -65,6 +67,18 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 /* Customized system reset */
 qemu_register_reset(a369_system_reset, cpu);
 
+/* Attach the nand flash to ftnandc021 */
+dinfo = drive_get_next(IF_MTD);
+ds = nand_init(dinfo ? dinfo-bdrv : NULL, NAND_MFR_SAMSUNG, 0xda);
+object_property_set_link(OBJECT(s-nandc[0]),
+ OBJECT(ds),
+ flash,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set flash link for FTNANDC021\n);
+abort();
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index 99eb428..e057629 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -54,6 +54,7 @@ static void a369soc_chip_init(FaradaySoCState *s)
 int i;
 DeviceState *ds;
 DriveInfo *dinfo;
+qemu_irq ack, req;
 Error *local_errp = NULL;
 
 /* Remappable Memory Region Init */
@@ -191,6 +192,14 @@ static void a369soc_chip_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
 abort();
 }
+
+/* ftnandc021 */
+ds = sysbus_create_simple(ftnandc021, 0x9020, s-pic[30]);
+s-nandc[0] = ds;
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 15);
+qdev_connect_gpio_out(s-hdma[0], 15, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ftnandc021.c b/hw/ftnandc021.c
new file mode 100644
index 000..fef92aa
--- /dev/null
+++ b/hw/ftnandc021.c
@@ -0,0 +1,526 @@
+/*
+ * QEMU model of the FTNANDC021 NAND Flash Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/devices.h
+#include hw/flash.h
+#include sysemu/blockdev.h
+
+#include hw/ftnandc021.h
+
+#define TYPE_FTNANDC021 ftnandc021
+
+typedef struct Ftnandc021State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+qemu_irq irq;
+DeviceState *flash;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint8_t  manf_id, chip_id;
+
+int  cmd;
+int  len;/* buffer length for page read/write */
+int  pi;/* page index */
+int  bw;/* bus width (8-bits, 16-bits) */
+
+uint64_t size;/* flash size (maximum access range) */
+uint32_t pgsz;/* page size (Bytes) */
+uint32_t bksz;/* block size (Bytes) */
+uint32_t alen;/* address length (cycle) */
+
+uint32_t id[2];
+uint8_t  oob[8];/* 5 bytes for 512/2048 page; 7 bytes for 4096 page */
+
+/* HW register caches */
+uint32_t sr;
+uint32_t fcr;
+uint32_t mcr;
+uint32_t ier;
+uint32_t bcr;
+} Ftnandc021State;
+
+#define FTNANDC021(obj) \
+OBJECT_CHECK(Ftnandc021State, obj, TYPE_FTNANDC021)
+
+static void ftnandc021_update_irq(Ftnandc021State *s)
+{
+if (s-ier  IER_ENA) {
+if ((s-ier  0x0f)  (s-sr  2)) {
+qemu_set_irq(s-irq, 1);
+} else {
+qemu_set_irq(s-irq, 0);
+}
+}
+}
+
+static void

[Qemu-devel] [PATCH v9 09/24] tests: add QTest for FTRTC011

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTRTC011 QEMU model is implemented without calender functions.
It acts in counter mode only, all the time  timezone conversion
relies on the c runtime library. (i.e. mktime(), localtime() ...etc)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 tests/Makefile|3 +
 tests/ftrtc011-test.c |  410 +
 2 files changed, 413 insertions(+)
 create mode 100644 tests/ftrtc011-test.c

diff --git a/tests/Makefile b/tests/Makefile
index 567e36e..bc75f2b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -75,6 +75,8 @@ gcov-files-sparc-y += hw/m48t59.c
 gcov-files-sparc64-y += hw/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 gcov-files-arm-y += hw/tmp105.c
+check-qtest-arm-y = tests/ftrtc011-test$(EXESUF)
+gcov-files-arm-y += hw/ftrtc011.c
 
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h 
tests/test-qmp-commands.h
 
@@ -133,6 +135,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o
+tests/ftrtc011-test$(EXESUF): tests/ftrtc011-test.o
 
 # QTest rules
 
diff --git a/tests/ftrtc011-test.c b/tests/ftrtc011-test.c
new file mode 100644
index 000..15b4f0d
--- /dev/null
+++ b/tests/ftrtc011-test.c
@@ -0,0 +1,410 @@
+/*
+ * QTest testcase for the FTRTC011 real-time clock
+ *
+ * Copyright (c) 2013 Kuo-Jung Su
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include libqtest.h
+#include hw/ftrtc011.h
+
+#include glib.h
+#include stdio.h
+#include string.h
+#include stdlib.h
+#include unistd.h
+
+#define A369_FTRTC011_BASE  0x9210
+#define A369_FTRTC011_IRQ_ALARM 42  /* edge triggered */
+#define A369_FTRTC011_IRQ_SEC   43  /* edge triggered */
+#define A369_FTRTC011_IRQ_MIN   44  /* edge triggered */
+#define A369_FTRTC011_IRQ_HOUR  45  /* edge triggered */
+
+#define CFG_BASEYEAR2010
+
+static time_t ts_base;
+
+static uint32_t rtc_read(uint32_t reg)
+{
+return readl(A369_FTRTC011_BASE + reg);
+}
+
+static void rtc_write(uint32_t reg, uint32_t val)
+{
+writel(A369_FTRTC011_BASE + reg, val);
+}
+
+static int rtc_get_irq(int irq)
+{
+#if 0   /* It looks to me that get_irq() doesn't work well
+ * with edge interrupts.
+ */
+return get_irq(irq);
+#else
+switch (irq) {
+case A369_FTRTC011_IRQ_ALARM:
+return !!(rtc_read(REG_ISR)  ISR_ALARM);
+case A369_FTRTC011_IRQ_SEC:
+return !!(rtc_read(REG_ISR)  ISR_SEC);
+case A369_FTRTC011_IRQ_MIN:
+return !!(rtc_read(REG_ISR)  ISR_MIN);
+case A369_FTRTC011_IRQ_HOUR:
+return !!(rtc_read(REG_ISR)  ISR_HOUR);
+default:
+return 0;
+}
+#endif
+}
+
+static int tm_cmp(struct tm *lhs, struct tm *rhs)
+{
+time_t a, b;
+struct tm d1, d2;
+
+memcpy(d1, lhs, sizeof(d1));
+memcpy(d2, rhs, sizeof(d2));
+
+a = mktime(d1);
+b = mktime(d2);
+
+if (a  b) {
+return -1;
+} else if (a  b) {
+return 1;
+}
+
+return 0;
+}
+
+static void rtc_start(void)
+{
+time_t ts;
+struct tm base;
+
+if (!ts_base) {
+base.tm_isdst = -1;
+base.tm_year  = CFG_BASEYEAR - 1900;
+base.tm_mon   = 0;
+base.tm_mday  = 1;
+base.tm_hour  = 0;
+base.tm_min   = 0;
+base.tm_sec   = 0;
+ts_base = mktime(base);
+}
+
+ts = time(NULL) - ts_base;
+rtc_write(REG_WDAY, ts / 86400LL);
+ts %= 86400LL;
+rtc_write(REG_WHOUR, ts / 3600LL);
+ts %= 3600LL;
+rtc_write(REG_WMIN, ts / 60LL);
+ts %= 60LL;
+rtc_write(REG_WSEC, ts);
+
+rtc_write(REG_ISR, ISR_MASK);
+rtc_write(REG_CR, CR_EN | CR_LOAD | CR_INTR_MASK);
+}
+
+static void rtc_get_datetime(struct tm *date)
+{
+time_t ts;
+int64_t sec, min, hour, day;
+
+if (!ts_base) {
+fprintf(stderr, ts_base is not yet initialized!\n);
+exit(1);
+}
+
+sec  = rtc_read(REG_SEC);
+min  = rtc_read(REG_MIN);
+hour = rtc_read(REG_HOUR);
+day  = rtc_read(REG_DAY);
+ts   = ts_base + (86400LL * day) + (hour * 3600LL) + (min * 60LL) + sec;
+
+localtime_r(ts, date);
+}
+
+static void rtc_test_check_time(int wiggle)
+{
+struct tm start, date[4], end;
+struct tm *datep;
+time_t ts;
+
+rtc_start();
+
+/*
+ * This check assumes a few things.
+ * First, we cannot guarantee that we get a consistent reading
+ * from the wall clock because we may hit an edge of the clock
+ * while reading.
+ * To work around this, we read four clock readings such that
+ * at least two of them should match.  We need to assume that one
+ * reading is corrupt so we need four readings to ensure that we have at
+ * least two consecutive identical readings
+ *
+ * It's also

[Qemu-devel] [PATCH v9 15/24] hw: add WM8731 audio codec support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Wolfson WM8731 is a simple audio codec for embedded systems.
It has 2 input and 1 output ports:

** Input **
1. Linue-In
2. Microphone

** Output **
1. Headphone out

BTW it's based on hw/wm8750.c with 16-bit I2S support by default.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 default-configs/arm-softmmu.mak |1 +
 hw/Makefile.objs|1 +
 hw/wm8731.c |  505 +++
 3 files changed, 507 insertions(+)
 create mode 100644 hw/wm8731.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index ab87035..b682c24 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_SD=y
 CONFIG_MAX7310=y
+CONFIG_WM8731=y
 CONFIG_WM8750=y
 CONFIG_TWL92230=y
 CONFIG_TSC2005=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 808e2d0..5b4bf20 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -169,6 +169,7 @@ common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
 common-obj-y += audio.o
+common-obj-$(CONFIG_WM8731) += wm8731.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/wm8731.c b/hw/wm8731.c
new file mode 100644
index 000..820341f
--- /dev/null
+++ b/hw/wm8731.c
@@ -0,0 +1,505 @@
+/*
+ * WM8731 audio codec.
+ *
+ * base is wm8750.c
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/i2c.h
+#include hw/audio.h
+#include audio/audio.h
+
+#define IN_PORT_N   2
+#define OUT_PORT_N  1
+
+#define TYPE_WM8731 wm8731
+
+typedef struct WMRate {
+int adc;
+int adc_hz;
+int dac;
+int dac_hz;
+} WMRate;
+
+typedef struct WM8731State {
+AudioCodecState parent;
+
+uint8_t i2c_data[2];
+int i2c_len;
+QEMUSoundCard card;
+SWVoiceIn *adc_voice[IN_PORT_N];
+SWVoiceOut *dac_voice[OUT_PORT_N];
+void (*data_req)(void *, int, int);
+void *opaque;
+uint8_t data_in[4096];
+uint8_t data_out[4096];
+int idx_in, req_in;
+int idx_out, req_out;
+
+SWVoiceOut **out[2];
+uint8_t outvol[2];
+SWVoiceIn **in[2];
+uint8_t invol[2], inmute[2], mutemic;
+
+uint8_t mute;
+uint8_t power, format, active;
+const WMRate *rate;
+uint8_t rate_vmstate;
+int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
+} WM8731State;
+
+#define WM8731(obj) \
+OBJECT_CHECK(WM8731State, obj, TYPE_WM8731)
+
+#define WM8731_OUTVOL_TRANSFORM(x)  (x  1)
+#define WM8731_INVOL_TRANSFORM(x)   (x  3)
+
+static inline void wm8731_in_load(WM8731State *s)
+{
+if (s-idx_in + s-req_in = sizeof(s-data_in)) {
+return;
+}
+s-idx_in = audio_MAX(0, (int) sizeof(s-data_in) - s-req_in);
+AUD_read(*s-in[0], s-data_in + s-idx_in,
+ sizeof(s-data_in) - s-idx_in);
+}
+
+static inline void wm8731_out_flush(WM8731State *s)
+{
+int sent = 0;
+while (sent  s-idx_out) {
+sent += AUD_write(*s-out[0], s-data_out + sent, s-idx_out - sent)
+? 0 : s-idx_out;
+}
+s-idx_out = 0;
+}
+
+static void wm8731_audio_in_cb(void *opaque, int avail_b)
+{
+WM8731State *s = WM8731(opaque);
+s-req_in = avail_b;
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, avail_b  1);
+}
+
+static void wm8731_audio_out_cb(void *opaque, int free_b)
+{
+WM8731State *s = WM8731(opaque);
+
+if (s-idx_out = free_b) {
+s-idx_out = free_b;
+s-req_out = 0;
+wm8731_out_flush(s);
+} else {
+s-req_out = free_b - s-idx_out;
+}
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, s-req_in  1);
+}
+
+static const WMRate wm_rate_table[] = {
+{  256, 48000,  256, 48000 },/* SR: , BOSR: 0 */
+{  384, 48000,  384, 48000 },/* SR: , BOSR: 1 */
+{  256, 48000,  256,  8000 },/* SR: 0001, BOSR: 0 */
+{  384, 48000,  384,  8000 },/* SR: 0001, BOSR: 1 */
+{  256,  8000,  256, 48000 },/* SR: 0010, BOSR: 0 */
+{  384,  8000,  384, 48000 },/* SR: 0010, BOSR: 1 */
+{  256,  8000,  256,  8000 },/* SR: 0011, BOSR: 0 */
+{  384,  8000,  384,  8000 },/* SR: 0011, BOSR: 1 */
+{  256, 32000,  256, 32000 },/* SR: 0110, BOSR: 0 */
+{  384, 32000,  384, 32000 },/* SR: 0110, BOSR: 1 */
+{  128, 96000,  128, 96000 },/* SR: 0111, BOSR: 0 */
+{  192, 96000,  192, 96000 },/* SR: 0111, BOSR: 1 */
+{  256, 44100,  256, 44100 },/* SR: 1000, BOSR: 0 */
+{  384, 44100,  384, 44100 },/* SR: 1000, BOSR: 1 */
+{  256, 44100,  256,  8000 },/* SR: 1001, BOSR: 0 */
+{  384, 44100,  384,  8000 },/* SR: 1001, BOSR: 1 */
+{  256,  8000,  256, 44100 },/* SR: 1010

[Qemu-devel] [PATCH v9 16/24] The FTSSP010 is a multi-function synchronous serial port interface controller which supports SSP, SPI, I2S, AC97 and SPDIF.

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Only I2S and SPI protocol have been implemented in this patch.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|3 +-
 hw/arm/ftplat_a369.c|   31 +++
 hw/arm/ftplat_a369soc.c |   17 ++
 hw/faraday.h|3 +
 hw/ftssp010.c   |  504 +++
 hw/ftssp010.h   |   96 +
 6 files changed, 653 insertions(+), 1 deletion(-)
 create mode 100644 hw/ftssp010.c
 create mode 100644 hw/ftssp010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2bb67f7..42c8472 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,8 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o
+ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o \
+ftssp010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369.c b/hw/arm/ftplat_a369.c
index 827c58a..922fb55 100644
--- a/hw/arm/ftplat_a369.c
+++ b/hw/arm/ftplat_a369.c
@@ -11,6 +11,7 @@
 #include hw/arm-misc.h
 #include hw/devices.h
 #include hw/i2c.h
+#include hw/audio.h
 #include hw/boards.h
 #include hw/ssi.h
 #include net/net.h
@@ -28,6 +29,7 @@ static void a369_system_reset(void *opaque)
 
 static void a369_board_init(QEMUMachineInitArgs *args)
 {
+int i, nr_flash;
 ARMCPU *cpu;
 DeviceState *ds;
 FaradaySoCState *s;
@@ -79,6 +81,35 @@ static void a369_board_init(QEMUMachineInitArgs *args)
 abort();
 }
 
+/* Attach the spi flash to ftssp010.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi[0]), i + 1, cs_line);
+}
+
+/* Attach the wm8731 to fti2c010.0  ftssp010.0 */
+for (i = 0; i  1; ++i) {
+i2c_bus *i2c = (i2c_bus *)qdev_get_child_bus(s-i2c[0], i2c);
+ds = i2c_create_slave(i2c, wm8731, 0x1B);
+object_property_set_link(OBJECT(s-i2s[0]),
+ OBJECT(ds),
+ codec,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set codec link for FTSSP010\n);
+abort();
+}
+audio_codec_data_req_set(ds,
+ ftssp010_i2s_data_req,
+ s-i2s[0]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index b6e82ad..9391764 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -206,6 +206,23 @@ static void a369soc_chip_init(FaradaySoCState *s)
 s-i2c[0] = ds;
 ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
 s-i2c[1] = ds;
+
+/* ftssp010 */
+ds = sysbus_create_simple(ftssp010, 0x9270, s-pic[49]);
+s-spi[0] = ds;
+s-i2s[0] = ds;
+
+/* ftssp010 - DMA (Tx) */
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-pdma[0], 7);
+qdev_connect_gpio_out(s-pdma[0], 7, ack);
+qdev_connect_gpio_out(ds, 0, req);
+
+/* ftssp010 - DMA (Rx) */
+ack = qdev_get_gpio_in(ds, 1);
+req = qdev_get_gpio_in(s-pdma[0], 8);
+qdev_connect_gpio_out(s-pdma[0], 8, ack);
+qdev_connect_gpio_out(ds, 1, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/faraday.h b/hw/faraday.h
index 7373ba0..39a608c 100644
--- a/hw/faraday.h
+++ b/hw/faraday.h
@@ -121,4 +121,7 @@ static inline void faraday_soc_ahb_remap(FaradaySoCState 
*s, bool active)
 }
 }
 
+/* ftssp010.c */
+void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
+
 #endif
diff --git a/hw/ftssp010.c b/hw/ftssp010.c
new file mode 100644
index 000..fe1ddbb
--- /dev/null
+++ b/hw/ftssp010.c
@@ -0,0 +1,504 @@
+/*
+ * QEMU model of the FTSSP010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/i2c.h
+#include hw/ssi.h
+#include hw/audio.h
+#include sysemu/sysemu.h
+#include qemu/fifo8.h
+
+#include hw/faraday.h
+#include hw/ftssp010.h
+
+#define CFG_FIFO_DEPTH  16
+
+#define TYPE_FTSSP010   ftssp010
+
+typedef struct Ftssp010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+qemu_irq irq;
+SSIBus *spi;
+AudioCodecState *codec;
+
+uint8_t num_cs;
+qemu_irq *cs_lines;
+
+Fifo8 rx_fifo;
+Fifo8 tx_fifo;
+
+uint8_t

[Qemu-devel] [PATCH v9 13/24] hw/arm: add FTI2C010 I2C controller support

2013-03-25 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTI2C010 is a simple I2C master controller.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|2 +-
 hw/arm/ftplat_a369soc.c |6 ++
 hw/fti2c010.c   |  224 +++
 hw/fti2c010.h   |   74 
 4 files changed, 305 insertions(+), 1 deletion(-)
 create mode 100644 hw/fti2c010.c
 create mode 100644 hw/fti2c010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 8fe0f67..2bb67f7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,7 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o
+ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index e057629..b6e82ad 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -200,6 +200,12 @@ static void a369soc_chip_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-hdma[0], 15);
 qdev_connect_gpio_out(s-hdma[0], 15, ack);
 qdev_connect_gpio_out(ds, 0, req);
+
+/* fti2c010 */
+ds = sysbus_create_simple(fti2c010, 0x9290, s-pic[51]);
+s-i2c[0] = ds;
+ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
+s-i2c[1] = ds;
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/fti2c010.c b/hw/fti2c010.c
new file mode 100644
index 000..5b5606b
--- /dev/null
+++ b/hw/fti2c010.c
@@ -0,0 +1,224 @@
+/*
+ * QEMU model of the FTI2C010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/i2c.h
+#include sysemu/sysemu.h
+
+#include hw/fti2c010.h
+
+#define I2C_RD  1
+#define I2C_WR  0
+
+#define TYPE_FTI2C010   fti2c010
+
+typedef struct Fti2c010State {
+/* private */
+SysBusDevice parent;
+
+/* public */
+MemoryRegion mmio;
+
+qemu_irq irq;
+i2c_bus *bus;
+
+bool recv;/* I2C RD = true; I2C WR = false */
+
+/* HW register cache */
+uint32_t cr;
+uint32_t sr;
+uint32_t cdr;
+uint32_t dr;
+uint32_t tgsr;
+} Fti2c010State;
+
+#define FTI2C010(obj) \
+OBJECT_CHECK(Fti2c010State, obj, TYPE_FTI2C010)
+
+static void
+fti2c010_update_irq(Fti2c010State *s)
+{
+uint32_t sr = extract32(s-sr, 4, 8);
+uint32_t cr = extract32(s-cr, 8, 8);
+qemu_set_irq(s-irq, (sr  cr) ? 1 : 0);
+}
+
+static uint64_t
+fti2c010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_CR:
+return s-cr;
+case REG_SR:
+ret = s-sr | (i2c_bus_busy(s-bus) ? SR_BB : 0);
+s-sr = 0xf00f;/* clear RC status bits */
+fti2c010_update_irq(s);
+break;
+case REG_CDR:
+return s-cdr;
+case REG_DR:
+return s-dr;
+case REG_TGSR:
+return s-tgsr;
+case REG_BMR:
+return 0x0003;  /* Slave mode: SCL=1, SDA=1 */
+case REG_REVR:
+return 0x00011000;  /* REV. 1.10.0 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fti2c010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fti2c010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+
+switch (addr) {
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_SLAVE_MASK) {
+qemu_log_mask(LOG_UNIMP,
+fti2c010: slave mask deteced!\n);
+s-cr = ~CR_SLAVE_MASK;
+}
+if (s-cr  CR_I2CRST) {
+s-dr = 0;
+s-sr = 0;
+} else if ((s-cr  CR_MASTER_EN)  (s-cr  CR_TBEN)) {
+s-sr = ~SR_ACK;
+if (s-cr  CR_START) {
+s-recv = !!(s-dr  I2C_RD);
+if (!i2c_start_transfer(s-bus,
+extract32(s-dr, 1, 7),
+s-recv)) {
+s-sr |= SR_DT | SR_ACK;
+} else {
+s-sr = ~SR_DT;
+}
+} else {
+if (s-recv) {
+s-dr = i2c_recv(s-bus);
+s-sr |= SR_DR;
+} else {
+i2c_send(s-bus, (uint8_t)s-dr);
+s-sr |= SR_DT;
+}
+if (s-cr  CR_NACK) {
+i2c_nack(s-bus);
+}
+s-sr |= SR_ACK;
+if (s-cr  CR_STOP) {
+i2c_end_transfer(s-bus

Re: [Qemu-devel] [PATCH v8 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-18 Thread Kuo-Jung Su
2013/3/18 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 On Mon, Mar 18, 2013 at 11:12 AM, Kuo-Jung Su dant...@gmail.com wrote:
 2013/3/16 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Fri, Mar 15, 2013 at 11:13 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTDDRII030 is a DDRII SDRAM controller which is responsible for
 SDRAM initialization.
 In QEMU we emulate only the SDRAM enable function.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs  |1 +
  hw/arm/faraday_a369_soc.c |9 +++
  hw/arm/ftddrii030.c   |  183 
 +
  3 files changed, 193 insertions(+)
  create mode 100644 hw/arm/ftddrii030.c

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index af36b01..0bbf838 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -39,3 +39,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o 
 faraday_a369_scu.o \
  faraday_a369_kpd.o
  obj-y += ftintc020.o
  obj-y += ftahbc020.o
 +obj-y += ftddrii030.o
 diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
 index 01b4395..e8a63bb 100644
 --- a/hw/arm/faraday_a369_soc.c
 +++ b/hw/arm/faraday_a369_soc.c
 @@ -158,6 +158,15 @@ a369soc_device_init(FaradaySoCState *s)
  fprintf(stderr, a369soc: Unable to set soc link for 
 FTAHBC020\n);
  abort();
  }
 +
 +/* ftddrii030 */
 +ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
 +s-ddrc = ds;
 +object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
 +if (local_errp) {
 +fprintf(stderr, a369soc: Unable to set soc link for 
 FTDDRII030\n);
 +abort();
 +}
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
 new file mode 100644
 index 000..90a5842
 --- /dev/null
 +++ b/hw/arm/ftddrii030.c
 @@ -0,0 +1,183 @@
 +/*
 + * Faraday DDRII controller
 + *
 + * Copyright (c) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This code is licensed under GNU GPL v2+
 + */
 +
 +#include hw/hw.h
 +#include hw/sysbus.h
 +#include hw/devices.h
 +#include sysemu/sysemu.h
 +
 +#include faraday.h
 +
 +#define REG_MCR 0x00/* memory configuration register */
 +#define REG_MSR 0x04/* memory status register */
 +#define REG_REVR0x50/* revision register */
 +
 +#define MSR_INIT_OK BIT(8)  /* DDR2 initial is completed */
 +#define MSR_CMD_MRS BIT(0)  /* start MRS command */
 +
 +#define CFG_REGSIZE (0x50 / 4)
 +
 +#define TYPE_FTDDRII030 ftddrii030
 +
 +typedef struct Ftddrii030State {
 +SysBusDevice busdev;
 +MemoryRegion iomem;
 +
 +FaradaySoCState *soc;
 +/* HW register cache */
 +uint32_t regs[CFG_REGSIZE];
 +} Ftddrii030State;
 +
 +#define FTDDRII030(obj) \
 +OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
 +
 +#define DDR_REG32(s, off) \
 +((s)-regs[(off) / 4])
 +
 +static uint64_t
 +ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
 +{
 +Ftddrii030State *s = FTDDRII030(opaque);
 +uint64_t ret = 0;
 +
 +if (s-soc-ddr_inited) {
 +DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
 +}
 +
 +switch (addr) {
 +case REG_MCR ... (CFG_REGSIZE - 1) * 4:
 +ret = s-regs[addr / 4];
 +break;
 +case REG_REVR:
 +ret = 0x100;/* rev. = 0.1.0 */
 +break;
 +default:
 +qemu_log_mask(LOG_GUEST_ERROR,
 +ftddrii030: undefined memory access@%# HWADDR_PRIx \n, 
 addr);
 +break;
 +}
 +
 +return ret;
 +}
 +
 +static void
 +ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned 
 size)
 +{
 +Ftddrii030State *s = FTDDRII030(opaque);
 +
 +switch (addr) {
 +case REG_MCR:
 +DDR_REG32(s, REG_MCR) = (uint32_t)val  0x;
 +break;
 +case REG_MSR:
 +val = (val  0x3f) | (DDR_REG32(s, REG_MSR)  MSR_INIT_OK);
 +if (!s-soc-ddr_inited  (val  MSR_CMD_MRS)) {
 +val = ~MSR_CMD_MRS;
 +val |= MSR_INIT_OK;
 +memory_region_add_subregion(s-soc-as,
 +s-soc-ram_base,
 +s-soc-ram);

 I feel like this is overstepping the bounds of the device. Its
 modifying the internals of the parent device (the SoC itself). AFAICT,
 this device does not need awareness of where the RAM is to live in the
 address map, thats the responsibility of the machine model. It might
 be cleaner to model the actual RAM as a second sysbus memory region
 then leave it up the machine model to decide where in the address map
 it should live. This device just adds/removes the ram from the second
 region without knowing where it lives and the machine model maps the
 RAM to its actual location. Keeps .as .ram_base and .ram private to
 the SoC device.


 Thanks

Re: [Qemu-devel] [PATCH v8 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-18 Thread Kuo-Jung Su
2013/3/18 Peter Maydell peter.mayd...@linaro.org:
 On 18 March 2013 09:56, Kuo-Jung Su dant...@gmail.com wrote:
 The FTDDRII030 is responsible for SDRAM initialization.
 Which means the DDRII SDRAM would not be stabilized until the
 SDRAM is correctly initialized.
 =
 In QEMU, the memory_region_add_subregion() is used to perform this emulation.

 If you want to model sdram doesn't work unless it's inited
 (which is optional, often for qemu it's fine to just have
 the RAM always work), then the right way to do this is
 probably to have this device provide a memory region which
 is a container and which the SoC always maps. Then this device
 just maps the RAM into the container when the guest does the
 DDR init. Having the device mess with its parent's address
 space is a red flag that you're not modelling things right.


Got it, thanks.
It sounds like a good idea to me, I'll try to model the ftddrii030 in that way.

 The FTAHBC030 is responsible for AHB device management (base + window size)
 and also the special case for AHB remap of slave4 and slave6.
 =
 In QEMU,
 1. If SDRAM is initialized before activating AHB remap:
 memory_region_del_subregion() must be called prior to
 memory_region_add_subregion().
 And this is the reason why I need '.ddr_inited' and
 '.ahb_remapped' in SoC struct.
 2. If SDRAM is not yet initialized while activating AHB remap:
 Only memory_region_add_subregion() needs to be invoked.

 If you're handling add/del subregion then you need to model
 this so that the device that does the add/del is working on
 a memory region container that it controls. Then it can have
 a private data structure field which tracks what the state
 of the mapped subregions is. This almost always turns out to
 be the same way the hardware design is structured.

 At the moment you have add/del going on in this device but
 fields relating to what state the subregions are in are
 at the top level soc state.


Got it, thanks

 -- PMM



--
Best wishes,
Kuo-Jung Su



Re: [Qemu-devel] [PATCH v8 00/24] hw/arm: add Faraday A369 SoC platform support

2013-03-17 Thread Kuo-Jung Su
2013/3/15 Peter Maydell peter.mayd...@linaro.org:
 On 15 March 2013 13:15, Kuo-Jung Su dant...@gmail.com wrote:
  default-configs/arm-softmmu.mak |1 +
  hw/Makefile.objs|2 +
  hw/arm/Makefile.objs|   21 ++
  hw/arm/faraday.h|   61 
  hw/arm/faraday_a369.c   |  174 ++
  hw/arm/faraday_a369_kpd.c   |  231 +
  hw/arm/faraday_a369_scu.c   |  182 ++
  hw/arm/faraday_a369_soc.c   |  342 +++
  hw/arm/ftahbc020.c  |  202 +++
  hw/arm/ftapbbrg020.c|  468 ++
  hw/arm/ftapbbrg020.h|   44 +++
  hw/arm/ftddrii030.c |  183 ++
  hw/arm/ftdmac020.c  |  595 
  hw/arm/ftdmac020.h  |  107 ++
  hw/arm/ftgmac100.c  |  708 
 +++
  hw/arm/ftgmac100.h  |  239 +
  hw/arm/fti2c010.c   |  212 
  hw/arm/fti2c010.h   |   71 
  hw/arm/ftintc020.c  |  302 +
  hw/arm/ftintc020.h  |   57 
  hw/arm/ftkbc010.h   |   44 +++
  hw/arm/ftlcdc200.c  |  510 
  hw/arm/ftlcdc200.h  |  112 +++
  hw/arm/ftlcdc200_template.h |  439 
  hw/arm/ftmac110.c   |  661 
  hw/arm/ftmac110.h   |  168 ++
  hw/arm/ftnandc021.c |  516 
  hw/arm/ftnandc021.h |   84 +
  hw/arm/ftpwmtmr010.c|  258 ++
  hw/arm/ftpwmtmr010.h|   31 ++
  hw/arm/ftrtc011.c   |  383 +
  hw/arm/ftrtc011.h   |   53 +++
  hw/arm/ftsdc010.c   |  354 
  hw/arm/ftsdc010.h   |   90 +
  hw/arm/ftspi020.c   |  337 +++
  hw/arm/ftspi020.h   |   81 +
  hw/arm/ftssp010.c   |  494 +++
  hw/arm/ftssp010.h   |   98 ++
  hw/arm/fttmr010.c   |  445 
  hw/arm/fttmr010.h   |   41 +++
  hw/arm/fttsc010.c   |  260 ++
  hw/arm/fttsc010.h   |   39 +++
  hw/arm/ftwdt010.c   |  209 
  hw/arm/ftwdt010.h   |   35 ++

 I don't have time to do a full review right now, but a lot
 of these files are in the wrong place. If it looks like a
 device it doesn't belong in hw/arm (top level board models
 and things that directly reference the CPU only).

 -- PMM

Got it, thanks.

-- 
Best wishes,
Kuo-Jung Su



Re: [Qemu-devel] [PATCH v8 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-17 Thread Kuo-Jung Su
2013/3/16 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 Hi Kuo-Jung,

 On Fri, Mar 15, 2013 at 11:13 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTDDRII030 is a DDRII SDRAM controller which is responsible for
 SDRAM initialization.
 In QEMU we emulate only the SDRAM enable function.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs  |1 +
  hw/arm/faraday_a369_soc.c |9 +++
  hw/arm/ftddrii030.c   |  183 
 +
  3 files changed, 193 insertions(+)
  create mode 100644 hw/arm/ftddrii030.c

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index af36b01..0bbf838 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -39,3 +39,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o 
 faraday_a369_scu.o \
  faraday_a369_kpd.o
  obj-y += ftintc020.o
  obj-y += ftahbc020.o
 +obj-y += ftddrii030.o
 diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
 index 01b4395..e8a63bb 100644
 --- a/hw/arm/faraday_a369_soc.c
 +++ b/hw/arm/faraday_a369_soc.c
 @@ -158,6 +158,15 @@ a369soc_device_init(FaradaySoCState *s)
  fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
  abort();
  }
 +
 +/* ftddrii030 */
 +ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
 +s-ddrc = ds;
 +object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
 +if (local_errp) {
 +fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 +abort();
 +}
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
 new file mode 100644
 index 000..90a5842
 --- /dev/null
 +++ b/hw/arm/ftddrii030.c
 @@ -0,0 +1,183 @@
 +/*
 + * Faraday DDRII controller
 + *
 + * Copyright (c) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This code is licensed under GNU GPL v2+
 + */
 +
 +#include hw/hw.h
 +#include hw/sysbus.h
 +#include hw/devices.h
 +#include sysemu/sysemu.h
 +
 +#include faraday.h
 +
 +#define REG_MCR 0x00/* memory configuration register */
 +#define REG_MSR 0x04/* memory status register */
 +#define REG_REVR0x50/* revision register */
 +
 +#define MSR_INIT_OK BIT(8)  /* DDR2 initial is completed */
 +#define MSR_CMD_MRS BIT(0)  /* start MRS command */
 +
 +#define CFG_REGSIZE (0x50 / 4)
 +
 +#define TYPE_FTDDRII030 ftddrii030
 +
 +typedef struct Ftddrii030State {
 +SysBusDevice busdev;
 +MemoryRegion iomem;
 +
 +FaradaySoCState *soc;
 +/* HW register cache */
 +uint32_t regs[CFG_REGSIZE];
 +} Ftddrii030State;
 +
 +#define FTDDRII030(obj) \
 +OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
 +
 +#define DDR_REG32(s, off) \
 +((s)-regs[(off) / 4])
 +
 +static uint64_t
 +ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
 +{
 +Ftddrii030State *s = FTDDRII030(opaque);
 +uint64_t ret = 0;
 +
 +if (s-soc-ddr_inited) {
 +DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
 +}
 +
 +switch (addr) {
 +case REG_MCR ... (CFG_REGSIZE - 1) * 4:
 +ret = s-regs[addr / 4];
 +break;
 +case REG_REVR:
 +ret = 0x100;/* rev. = 0.1.0 */
 +break;
 +default:
 +qemu_log_mask(LOG_GUEST_ERROR,
 +ftddrii030: undefined memory access@%# HWADDR_PRIx \n, 
 addr);
 +break;
 +}
 +
 +return ret;
 +}
 +
 +static void
 +ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 +{
 +Ftddrii030State *s = FTDDRII030(opaque);
 +
 +switch (addr) {
 +case REG_MCR:
 +DDR_REG32(s, REG_MCR) = (uint32_t)val  0x;
 +break;
 +case REG_MSR:
 +val = (val  0x3f) | (DDR_REG32(s, REG_MSR)  MSR_INIT_OK);
 +if (!s-soc-ddr_inited  (val  MSR_CMD_MRS)) {
 +val = ~MSR_CMD_MRS;
 +val |= MSR_INIT_OK;
 +memory_region_add_subregion(s-soc-as,
 +s-soc-ram_base,
 +s-soc-ram);

 I feel like this is overstepping the bounds of the device. Its
 modifying the internals of the parent device (the SoC itself). AFAICT,
 this device does not need awareness of where the RAM is to live in the
 address map, thats the responsibility of the machine model. It might
 be cleaner to model the actual RAM as a second sysbus memory region
 then leave it up the machine model to decide where in the address map
 it should live. This device just adds/removes the ram from the second
 region without knowing where it lives and the machine model maps the
 RAM to its actual location. Keeps .as .ram_base and .ram private to
 the SoC device.


Thanks for the comments,
I'll try to implement a cleaner model in the way suggested in the
above comments.

 +s-soc-ddr_inited

Re: [Qemu-devel] [PATCH v8 13/24] hw/arm: add FTI2C010 I2C controller support

2013-03-17 Thread Kuo-Jung Su
2013/3/16 Peter Crosthwaite peter.crosthwa...@xilinx.com:
 On Fri, Mar 15, 2013 at 11:15 PM, Kuo-Jung Su dant...@gmail.com wrote:
 From: Kuo-Jung Su dant...@faraday-tech.com

 The FTI2C010 is a simple I2C master controller.

 Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
 ---
  hw/arm/Makefile.objs  |1 +
  hw/arm/faraday_a369_soc.c |6 ++
  hw/arm/fti2c010.c |  212 
 +
  hw/arm/fti2c010.h |   71 +++
  4 files changed, 290 insertions(+)
  create mode 100644 hw/arm/fti2c010.c
  create mode 100644 hw/arm/fti2c010.h

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index 2622f3f..63ba519 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -46,3 +46,4 @@ obj-y += ftrtc011.o
  obj-y += ftdmac020.o
  obj-y += ftapbbrg020.o
  obj-y += ftnandc021.o
 +obj-y += fti2c010.o
 diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
 index 0088915..89610d9 100644
 --- a/hw/arm/faraday_a369_soc.c
 +++ b/hw/arm/faraday_a369_soc.c
 @@ -241,6 +241,12 @@ a369soc_device_init(FaradaySoCState *s)
  req = qdev_get_gpio_in(s-hdma[0], 15);
  qdev_connect_gpio_out(s-hdma[0], 15, ack);
  qdev_connect_gpio_out(ds, 0, req);
 +
 +/* fti2c010 */
 +ds = sysbus_create_simple(fti2c010, 0x9290, s-pic[51]);
 +s-i2c[0] = ds;
 +ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
 +s-i2c[1] = ds;
  }

  static void a369soc_realize(DeviceState *dev, Error **errp)
 diff --git a/hw/arm/fti2c010.c b/hw/arm/fti2c010.c
 new file mode 100644
 index 000..95f6a9d
 --- /dev/null
 +++ b/hw/arm/fti2c010.c
 @@ -0,0 +1,212 @@
 +/*
 + * QEMU model of the FTI2C010 Controller
 + *
 + * Copyright (C) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This file is licensed under GNU GPL v2+.
 + */
 +
 +#include hw/sysbus.h
 +#include hw/i2c.h
 +#include sysemu/sysemu.h
 +
 +#include fti2c010.h
 +
 +#define I2C_RD  1
 +#define I2C_WR  0
 +
 +#define TYPE_FTI2C010   fti2c010
 +
 +typedef struct Fti2c010State {
 +SysBusDevice busdev;
 +MemoryRegion mmio;
 +
 +qemu_irq irq;
 +i2c_bus *bus;
 +
 +uint8_t  recv;/* I2C RD = 1; I2C WR = 0 */
 +uint8_t  addr;/* 7-bits device address */
 +
 +/* HW register cache */
 +uint32_t cr;
 +uint32_t sr;
 +uint32_t cdr;
 +uint32_t dr;
 +uint32_t tgsr;
 +} Fti2c010State;
 +
 +#define FTI2C010(obj) \
 +OBJECT_CHECK(Fti2c010State, obj, TYPE_FTI2C010)
 +
 +static void
 +fti2c010_update_irq(Fti2c010State *s)
 +{
 +uint32_t sr = extract32(s-sr, 4, 8);
 +uint32_t cr = extract32(s-cr, 8, 8);
 +qemu_set_irq(s-irq, (sr  cr) ? 1 : 0);
 +}
 +
 +static uint64_t
 +fti2c010_mem_read(void *opaque, hwaddr addr, unsigned size)
 +{
 +Fti2c010State *s = FTI2C010(opaque);
 +uint32_t ret = 0;
 +
 +switch (addr) {
 +case REG_CR:
 +return s-cr;
 +case REG_SR:
 +ret = s-sr | (i2c_bus_busy(s-bus) ? SR_BB : 0);
 +s-sr = 0xf00f;/* clear RC status bits */
 +fti2c010_update_irq(s);
 +break;
 +case REG_CDR:
 +return s-cdr;
 +case REG_DR:
 +return s-dr;
 +case REG_TGSR:
 +return s-tgsr;
 +case REG_BMR:
 +return 0x0003;  /* Slave mode: SCL=1, SDA=1 */
 +case REG_REVR:
 +return 0x00011000;  /* REV. 1.10.0 */
 +default:
 +qemu_log_mask(LOG_GUEST_ERROR,
 +fti2c010: undefined memory access@%# HWADDR_PRIx \n, addr);
 +break;
 +}
 +
 +return ret;
 +}
 +
 +static void
 +fti2c010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 +{
 +Fti2c010State *s = FTI2C010(opaque);
 +
 +switch (addr) {
 +case REG_CR:
 +s-cr = (uint32_t)val;
 +if (s-cr  CR_I2CRST) {
 +s-dr = 0;
 +s-sr = 0;
 +} else if ((s-cr  CR_MASTER_EN)  (s-cr  CR_TBEN)) {
 +s-sr = ~SR_ACK;
 +if (s-cr  CR_START) {
 +s-recv = (s-dr  I2C_RD) ? 1 : 0;
 +s-addr = extract32(s-dr, 1, 7);
 +if (!i2c_start_transfer(s-bus, s-addr, s-recv)) {

 This is the one and only use or s-addr AFAICT, and its used
 immediately after unconditional assignment. You should drop addr
 completely and just inline to save on redundant device state (the
 desired infomation is in s-dr(8:1).


Got it, thanks.

 +s-sr |= SR_DT | SR_ACK;
 +} else {
 +s-sr = ~SR_DT;
 +}
 +} else {
 +if (s-recv) {
 +s-dr = i2c_recv(s-bus);
 +s-sr |= SR_DR;
 +} else {
 +i2c_send(s-bus, (uint8_t)s-dr);
 +s-sr |= SR_DT;
 +}
 +if (s-cr  CR_NACK) {
 +i2c_nack(s-bus);
 +}
 +s-sr |= SR_ACK;
 +if (s

[Qemu-devel] [PATCH v8 00/24] hw/arm: add Faraday A369 SoC platform support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

These patches introduce Faraday A369 SoC platform support.

Here are some public documents for your reference.

http://www.faraday-tech.com/html/documentation/index.html

The partial version of faraday cpu datasheet with only
the CP15 and MPU description are available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAalh5TkxyZWtlWEE/edit?usp=sharing

The pre-built A369 images are also available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAX2pTTmtUMGFCZW8/edit

Here is the image file list:

1. android-4.0.4/zImage: A369 linux-3.0.31
2. android-4.0.4/romfs-4.0.4.tar.bz2: android-4.0.4
3. nand.img.bz2: A369 nand flash image
4. rom.img.bz2: A369 embedded ROM image
5. u-boot: A369 u-boot-2012.10 ELF file
6. zImage: A369 linux-3.4.12 + initramfs
7. README

If you want to re-build the image from scratch, 
try my Faraday Linux BSP/SDK: falinux.

1. Download the falinux

   $ git clone https://github.com/dantesu1218/falinux.git

2. Download all the required software packages:

   $ cd falinux
   $ make setup

3. Launch the menuconfig of falinux, and enable 'QEMU Support'

   $ make menuconfig

4. Re-build the packages

   $ make

5. Laungh the qemu-1.3.0 with the generated falinux images.

   $ make qemu

Changes for v7 - v8:
1. [hw/arm/ftintc020.c] (Addressed by Peter)
   'uint32_t mask = BIT(irq % 32);' - 'uint32_t mask = BIT(irq  0x1f);'
2. [hw/arm/*.c] (Addressed by Peter)
   Drop '#include faraday.h', and define DPRINTF() at per-file basis
   exit(1) - abort()
   SysBusDeviceClass::init() - Device::realize()

Changes for v6 - v7:

1. hw/arm/ftwdt010: (Addressed by Paolo)
   Replace 'qemu_system_reset_request()' with 'watchdog_perform_action()'.
2. hw/arm/ftrtc011: (Addressed by Paolo)
   Replace 'get_clock_realtime()' with 'qemu_get_clock_ns(rtc_clock)'.
   Replace 'qemu_new_timer_ms(rt_clock...)' with 
'qemu_new_timer_ms(rtc_clock...)'
   Rename 'ftrtc011_timer_resync' - 'ftrtc011_timer_rebase'
   Add ftrtc011_timer_resche()
   Add QTest support
3. hw/arm/faraday_a369_soc: (Addressed by Paolo)
   Remove redundant device reset from a369soc_system_reset(...)
4. include/qemu/bitops.h: (Addressed by Paolo)
   Update bitrev8() to use a kind of divide and conquer algorithm.
5. hw/arm/ftahb020,ftddrii030,ftapbbrg020,faraday_a369_soc:
   Drop FARADAY_SOC_GET_CORE(), replaced with device to device QOM link.
6. hw/wm8731,wm8750,marvell_88w8618_audio,spitz,z2:
   Add AudioCodecClass for wm87xx audio class abstration.
7. hw/arm/ftnandc021:
   Drop nand_init(), replaced with device to device QOM link.
8. hw/arm/ftsdc010:
   Bug fixed to write operation: remove sd_data_ready() in write path.
9. hw/arm/ftgmac100,ftmac110,ftwdt010:
   rt-clock - vm_clock
   10. hw/nand.c:
   Drop [hw/nand.c: correct the sense of the BUSY/READY], since it's 
already applied.
   Drop [hw/nand.c: bug fix to erase operation], since Peter has a better 
solution.

Changes for v5 - v6:

   1. hw/arm/Makefile.objs: 
   Shift to the next line only after current line length is  80 characters.
   2. hw/arm/faraday.h:
   Update debug macro format per discussions at the link bellow:
   http://thread.gmane.org/gmane.comp.emulators.qemu/195996/focus=196975
   3. hw/arm/faraday.h:
   TYPE_FARADAY_SOC: 'faraday/soc' - 'faraday.soc'
   4. hw/arm/*.c:
   Replace '%llx' with '%HWADDR_PRIx'
   5. hw/arm/*.h:
   Add '#include qemu/bitops.h'
   6. hw/arm/faraday_a369_soc.c:
   Typo fix: salve4 - slave4, salve6 - slave6
   7. hw/arm/*.c:
   Drop FROM_SYSBUS().
   8. hw/arm/ftintc020.c:
   Re-write the source file with pl190.c as template.
   9. hw/arm/ftintc020.h:
   Rename the registers to improve readibility.
   10. hw/arm/faraday.h:
   Add dedicated spi flash pointer array (DeviceState *spi_fl[2]).
   11. hw/arm/faraday.h:
   Add 'qemu_irq pic[64]'.
   12. hw/arm/*c:
   Replace the complex conversion in XXX_REG32() with directly array 
indexing.
   13. hw/arm/*c:
   Update the error message output from 'hw_error(...)' into 
'fprintf(stderr, ...)'
   14. hw/arm/faraday_a369.c, hw/arm/faraday_a369_soc.c:
   Move the external AHB device init from faraday_a369_soc.c to 
faraday_a369.c
   15. include/qemu/bitops.h:
   Move bitrev() from bitrev.[ch] into bitops.h
   16. hw/nand.c:
   Remove the clear/set SR[6] code in read/erase/write, because
   it's not possible to be observed by a guest.
   17. hw/arm/faraday_a369_kpd.c:
   Function prefix: 'ftkbc010' - 'a369kpd' 
   Name of struct:  'FTKBC010State' - 'A369KPDState'.
   QOM: 'FTKBC010' - 'A369KPD'
   18. hw/arm/ftddrii030.c:
   'case REG_MCR ... 0x4c' - 'case REG_MCR ... (CFG_REGSIZE - 1) * 4'
   19. hw/arm/ftahbc020.c:
   Add comments to fall-through path. (i.e. /* fall-through - skip slave6 
*/)
   20. hw/arm/faraday_a369

[Qemu-devel] [PATCH v8 03/24] hw/arm: add FTINTC020 interrupt controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTINTC020 interrupt controller supports both FIQ and IRQ signals
to the microprocessor.
It can handle up to 64 configurable IRQ sources and 64 FIQ sources.
The output signals to the microprocessor can be configured as
level-high/low active or edge-rising/falling triggered.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   11 ++
 hw/arm/ftintc020.c|  302 +
 hw/arm/ftintc020.h|   57 +
 4 files changed, 371 insertions(+)
 create mode 100644 hw/arm/ftintc020.c
 create mode 100644 hw/arm/ftintc020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 104e0e7..536d6cf 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -37,3 +37,4 @@ obj-y += omap1.o omap2.o
 
 obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
 faraday_a369_kpd.o
+obj-y += ftintc020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 4e19c7e..eab05dc 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -72,6 +72,8 @@ a369soc_device_init(FaradaySoCState *s)
 {
 DriveInfo *dinfo;
 DeviceState *ds;
+qemu_irq *cpu_pic;
+int i;
 
 s-as = get_system_memory();
 s-ram = g_new(MemoryRegion, 1);
@@ -111,6 +113,15 @@ a369soc_device_init(FaradaySoCState *s)
 abort();
 }
 
+/* Interrupt Controller */
+cpu_pic = arm_pic_init_cpu(s-cpu);
+ds = sysbus_create_varargs(ftintc020, 0x9010,
+   cpu_pic[ARM_PIC_CPU_IRQ],
+   cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+for (i = 0; i  ARRAY_SIZE(s-pic); ++i) {
+s-pic[i] = qdev_get_gpio_in(ds, i);
+}
+
 /* Serial (FTUART010 which is 16550A compatible) */
 if (serial_hds[0]) {
 serial_mm_init(s-as,
diff --git a/hw/arm/ftintc020.c b/hw/arm/ftintc020.c
new file mode 100644
index 000..1a476d3
--- /dev/null
+++ b/hw/arm/ftintc020.c
@@ -0,0 +1,302 @@
+/*
+ * Faraday FTINTC020 Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+
+#include ftintc020.h
+
+#define TYPE_FTINTC020  ftintc020
+
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftintc020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+qemu_irq irq;
+qemu_irq fiq;
+
+uint32_t irq_ps[2]; /* IRQ pin state */
+uint32_t fiq_ps[2]; /* FIQ pin state */
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftintc020State;
+
+#define FTINTC020(obj) \
+OBJECT_CHECK(Ftintc020State, obj, TYPE_FTINTC020)
+
+#define PIC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+#define IRQ_REG32(s, n, off) \
+((s)-regs[(REG_IRQ(n) + ((off)  REG_MASK)) / 4])
+
+#define FIQ_REG32(s, n, off) \
+((s)-regs[(REG_FIQ(n) + ((off)  REG_MASK)) / 4])
+
+static void
+ftintc020_update_irq(Ftintc020State *s)
+{
+uint32_t mask[2];
+
+/* FIQ */
+mask[0] = PIC_REG32(s, REG_FIQ32SRC)  PIC_REG32(s, REG_FIQ32ENA);
+mask[1] = PIC_REG32(s, REG_FIQ64SRC)  PIC_REG32(s, REG_FIQ64ENA);
+qemu_set_irq(s-fiq, !!(mask[0] || mask[1]));
+
+/* IRQ */
+mask[0] = PIC_REG32(s, REG_IRQ32SRC)  PIC_REG32(s, REG_IRQ32ENA);
+mask[1] = PIC_REG32(s, REG_IRQ64SRC)  PIC_REG32(s, REG_IRQ64ENA);
+qemu_set_irq(s-irq, !!(mask[0] || mask[1]));
+}
+
+/* Note: Here level means state of the signal on a pin */
+static void
+ftintc020_set_irq(void *opaque, int irq, int level)
+{
+Ftintc020State *s = FTINTC020(opaque);
+uint32_t i = irq / 32;
+uint32_t mask = BIT(irq  0x1f);
+
+switch (irq) {
+case 0  ... 63:
+/* IRQ */
+if (IRQ_REG32(s, irq, REG_MDR)  mask) {
+/* Edge Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Falling Active */
+if ((s-irq_ps[i]  mask)  !level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* Rising Active */
+if (!(s-irq_ps[i]  mask)  level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+}
+} else {
+/* Level Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Low Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* High Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+}
+}
+}
+
+/* FIQ

[Qemu-devel] [PATCH v8 08/24] hw/arm: add FTRTC011 RTC timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It provides separate second, minute, hour, and day counters. The second
counter is toggled each second, the minute counter is toggled each minute,
the hour counter is toggled each hour, and the day counter is toggled each day.

The FTRTC011 provides a programmable auto-alarm function. When the second
auto-alarm function is turned on, the RTC will automatically trigger an
interrupt each second. The automatic minute and hour alarms can be turned on
as well.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   18 +++
 hw/arm/ftrtc011.c |  383 +
 hw/arm/ftrtc011.h |   53 +++
 4 files changed, 455 insertions(+)
 create mode 100644 hw/arm/ftrtc011.c
 create mode 100644 hw/arm/ftrtc011.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bd330f2..b01da9d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -42,3 +42,4 @@ obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
+obj-y += ftrtc011.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 2ec066d..7d90079 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -191,6 +191,24 @@ a369soc_device_init(FaradaySoCState *s)
 /* ftwdt010 */
 sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
 qemu_register_reset(a369soc_system_reset, s);
+
+/* ftrtc011 */
+ds = qdev_create(NULL, ftrtc011);
+/* Setup QOM path for QTest */
+object_property_add_child(OBJECT(s),
+  ftrtc011,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9210);
+/* Alarm (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[42]);
+/* Second (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[43]);
+/* Minute (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
+/* Hour (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftrtc011.c b/hw/arm/ftrtc011.c
new file mode 100644
index 000..2815f16
--- /dev/null
+++ b/hw/arm/ftrtc011.c
@@ -0,0 +1,383 @@
+/*
+ * QEMU model of the FTRTC011 RTC Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include ftrtc011.h
+
+enum ftrtc011_irqpin {
+IRQ_ALARM_LEVEL = 0,
+IRQ_ALARM_EDGE,
+IRQ_SEC,
+IRQ_MIN,
+IRQ_HOUR,
+IRQ_DAY,
+};
+
+#define TYPE_FTRTC011   ftrtc011
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Ftrtc011State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq[6];
+
+QEMUTimer *qtimer;
+int64_t rtc_base;
+int64_t rtc_start;
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftrtc011State;
+
+#define FTRTC011(obj) \
+OBJECT_CHECK(Ftrtc011State, obj, TYPE_FTRTC011)
+
+#define RTC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+/* Update interrupts.  */
+static void ftrtc011_update_irq(Ftrtc011State *s)
+{
+uint32_t mask = extract32(RTC_REG32(s, REG_CR), 1, 5)
+   RTC_REG32(s, REG_ISR);
+
+qemu_set_irq(s-irq[IRQ_ALARM_LEVEL], !!(mask  ISR_ALARM));
+
+if (mask) {
+if (mask  ISR_SEC) {
+qemu_irq_pulse(s-irq[IRQ_SEC]);
+}
+if (mask  ISR_MIN) {
+qemu_irq_pulse(s-irq[IRQ_MIN]);
+}
+if (mask  ISR_HOUR) {
+qemu_irq_pulse(s-irq[IRQ_HOUR]);
+}
+if (mask  ISR_DAY) {
+qemu_irq_pulse(s-irq[IRQ_DAY]);
+}
+if (mask  ISR_ALARM) {
+qemu_irq_pulse(s-irq[IRQ_ALARM_EDGE]);
+}
+}
+}
+
+static void ftrtc011_timer_rebase(Ftrtc011State *s)
+{
+int64_t ticks = get_ticks_per_sec();
+int64_t elapsed = RTC_REG32(s, REG_SEC)
++ (60LL * RTC_REG32(s, REG_MIN))
++ (3600LL * RTC_REG32(s, REG_HOUR))
++ (86400LL * RTC_REG32(s, REG_DAY));
+
+s-rtc_base  = elapsed;
+s-rtc_start = qemu_get_clock_ns(rtc_clock);
+/* adjust to the beginning of the current second */
+s-rtc_start = s-rtc_start - (s-rtc_start % ticks);
+}
+
+static void ftrtc011_timer_update(Ftrtc011State *s)
+{
+int64_t elapsed;
+uint8_t sec, min, hr;
+uint32_t day;
+
+/* check if RTC is enabled */
+if (!(RTC_REG32(s, REG_CR)  CR_EN)) {
+return;
+}
+
+/*
+ * 2013.03.11 Kuo-Jung Su
+ * Under QTest, in the very beginning of test,
+ * qemu_get_clock_ns(rtc_clock) would somehow jumps
+ * from 0 sec into 436474 sec.
+ * So I have to apply this simple work-aroud to make it work

[Qemu-devel] [PATCH v8 04/24] hw/arm: add FTAHBC020 AHB controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It's used to perform AHB remap and QEMU RAM initialization
when the SDRAM is initialized before AHB remap process activated.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   10 +++
 hw/arm/ftahbc020.c|  202 +
 3 files changed, 213 insertions(+)
 create mode 100644 hw/arm/ftahbc020.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 536d6cf..af36b01 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -38,3 +38,4 @@ obj-y += omap1.o omap2.o
 obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
 faraday_a369_kpd.o
 obj-y += ftintc020.o
+obj-y += ftahbc020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index eab05dc..01b4395 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -70,6 +70,7 @@ static void a369soc_reset(DeviceState *ds)
 static void
 a369soc_device_init(FaradaySoCState *s)
 {
+Error *local_errp = NULL;
 DriveInfo *dinfo;
 DeviceState *ds;
 qemu_irq *cpu_pic;
@@ -148,6 +149,15 @@ a369soc_device_init(FaradaySoCState *s)
 
 /* ftkbc010 */
 ds = sysbus_create_simple(a369.kpd, 0x92f0, s-pic[21]);
+
+/* ftahbc020 */
+ds = sysbus_create_simple(ftahbc020, 0x9400, NULL);
+s-ahbc = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftahbc020.c b/hw/arm/ftahbc020.c
new file mode 100644
index 000..5681906
--- /dev/null
+++ b/hw/arm/ftahbc020.c
@@ -0,0 +1,202 @@
+/*
+ * Faraday AHB controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+#define REG_SLAVE(n)((n) * 4) /* Slave config (base  size) */
+#define REG_PRIR0x80/* Priority register */
+#define REG_IDLECR  0x84/* IDLE count register */
+#define REG_CR  0x88/* Control register */
+#define REG_REVR0x8c/* Revision register */
+
+#define CR_REMAP0x01/* Enable AHB remap for slave 4  6 */
+
+#define TYPE_FTAHBC020  ftahbc020
+
+typedef struct Ftahbc020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+/* HW register cache */
+uint32_t cr;
+} Ftahbc020State;
+
+#define FTAHBC020(obj) \
+OBJECT_CHECK(Ftahbc020State, obj, TYPE_FTAHBC020)
+
+static uint64_t
+ftahbc020_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+uint64_t ret = 0;
+
+switch (addr) {
+/* slave address  window configuration */
+case REG_SLAVE(0) ... REG_SLAVE(3):
+/* fall-through - skip slave4 */
+case REG_SLAVE(5):
+/* fall-through - skip slave6 */
+case REG_SLAVE(7) ... REG_SLAVE(31):
+ret = s-soc-ahb_slave[addr / 4];
+break;
+case REG_SLAVE(4):
+ret = s-soc-rom_base | (s-soc-ahb_slave[4]  0x000f);
+break;
+case REG_SLAVE(6):
+ret = s-soc-ram_base | (s-soc-ahb_slave[6]  0x000f);
+break;
+/* control register */
+case REG_CR:
+if (s-soc-ahb_remapped) {
+s-cr |= CR_REMAP;
+}
+ret = s-cr;
+break;
+case REG_REVR:
+ret = 0x00010301;   /* rev. 1.3.1 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftahbc020: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftahbc020_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+
+switch (addr) {
+case REG_CR:/* control register */
+s-cr = (uint32_t)val;
+if (s-soc-ahb_remapped  !(s-cr  CR_REMAP)) {
+fprintf(stderr, ftahbc020: Once AHB remap is enabled, 
+ it could not be disabled!\n);
+abort();
+}
+if (!s-soc-ahb_remapped  (s-cr  CR_REMAP)) {
+/* Remap AHB slave 4 (ROM)  slave 6 (RAM) */
+/* 1. Remap RAM to base of ROM */
+s-soc-ram_base = s-soc-ahb_slave[4]  0xfff0;
+/* 2. Remap ROM to base of ROM + size of RAM */
+s-soc-rom_base = s-soc-ram_base
++ ((1  extract32(s-soc-ahb_slave[6], 16, 4))  20);
+/* 3. Update ROM memory map */
+sysbus_mmio_map(SYS_BUS_DEVICE(s-soc-rom), 0, s-soc-rom_base);
+/* 4. Update RAM memory map if it has been initialized. */
+if (s-soc-ddr_inited) {
+memory_region_del_subregion(s-soc

[Qemu-devel] [PATCH v8 01/24] target-arm: add Faraday ARMv5TE processors support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

This patch includes the single core support to FA606TE, FA626TE,
FA616TE and FA726TE with CP15 Faraday extensions (AUX and I/D-Scratchpad).

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 target-arm/cpu.c |   52 +++
 target-arm/cpu.h |6 +++-
 target-arm/helper.c  |   84 ++
 target-arm/machine.c |4 +++
 4 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a1e9093..aed97b0 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -244,6 +244,54 @@ static void arm926_initfn(Object *obj)
 cpu-reset_sctlr = 0x00090078;
 }
 
+static void fa606te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_MPU_FARADAY);
+cpu-midr = 0x66056061; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa616te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66056161; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d152152;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa626te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+set_feature(cpu-env, ARM_FEATURE_AUXCR);
+cpu-midr = 0x66056261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x0f192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa726te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66057261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
 static void arm946_initfn(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -766,6 +814,10 @@ typedef struct ARMCPUInfo {
 
 static const ARMCPUInfo arm_cpus[] = {
 { .name = arm926,  .initfn = arm926_initfn },
+{ .name = fa606te, .initfn = fa606te_initfn },
+{ .name = fa616te, .initfn = fa616te_initfn },
+{ .name = fa626te, .initfn = fa626te_initfn },
+{ .name = fa726te, .initfn = fa726te_initfn },
 { .name = arm946,  .initfn = arm946_initfn },
 { .name = arm1026, .initfn = arm1026_initfn },
 /* What QEMU calls arm1136-r2 is actually the 1136 r0p2, i.e. an
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2b97221..dd27e80 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -152,6 +152,8 @@ typedef struct CPUARMState {
 uint32_t c15_diagnostic; /* diagnostic register */
 uint32_t c15_power_diagnostic;
 uint32_t c15_power_control; /* power control */
+uint32_t c15_tcm_data;  /* Data TCM region register */
+uint32_t c15_tcm_inst;  /* Instruction TCM region register */
 } cp15;
 
 struct {
@@ -392,6 +394,8 @@ enum arm_features {
 ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
 ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
+ARM_FEATURE_TCM_FARADAY, /* Faraday Scratchpad(TCM) */
+ARM_FEATURE_MPU_FARADAY, /* Faraday MPU */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -640,7 +644,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 9
+#define CPU_SAVE_VERSION 10
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fd055e8..337d8b8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1015,6 +1015,84 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+static int faraday_pmsav5_ircfg_read(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+if (ri-crm = 4) {
+return

[Qemu-devel] [PATCH v8 06/24] hw/arm: add FTPWMTMR010 timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTPWMTMR010 is an APB device which provides up to 8 independent timers.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   10 ++
 hw/arm/ftpwmtmr010.c  |  258 +
 hw/arm/ftpwmtmr010.h  |   31 ++
 4 files changed, 300 insertions(+)
 create mode 100644 hw/arm/ftpwmtmr010.c
 create mode 100644 hw/arm/ftpwmtmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0bbf838..bc18e22 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -40,3 +40,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
+obj-y += ftpwmtmr010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index e8a63bb..874dc74 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -167,6 +167,16 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 abort();
 }
+
+/* Timer */
+ds = qdev_create(NULL, ftpwmtmr010);
+qdev_prop_set_uint32(ds, freq, 66 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9230);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, s-pic[8]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftpwmtmr010.c b/hw/arm/ftpwmtmr010.c
new file mode 100644
index 000..c212cfe
--- /dev/null
+++ b/hw/arm/ftpwmtmr010.c
@@ -0,0 +1,258 @@
+/*
+ * Faraday FTPWMTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include ftpwmtmr010.h
+
+#define TYPE_FTPWMTMR010ftpwmtmr010
+#define TYPE_FTPWMTMR010_TIMER  ftpwmtmr010_timer
+
+typedef struct Ftpwmtmr010State Ftpwmtmr010State;
+
+typedef struct Ftpwmtmr010Timer {
+uint32_t ctrl;
+uint32_t cntb;
+int id;
+uint64_t timeout;
+uint64_t countdown;
+qemu_irq irq;
+QEMUTimer *qtimer;
+Ftpwmtmr010State *chip;
+} Ftpwmtmr010Timer;
+
+struct Ftpwmtmr010State {
+SysBusDevice busdev;
+
+MemoryRegion iomem;
+Ftpwmtmr010Timer timer[8];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+uint32_t stat;
+};
+
+#define FTPWMTMR010(obj) \
+OBJECT_CHECK(Ftpwmtmr010State, obj, TYPE_FTPWMTMR010)
+
+static uint64_t
+ftpwmtmr010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t ret = 0;
+
+switch (addr) {
+case REG_SR:
+ret = s-stat;
+break;
+case REG_REVR:
+ret = 0x;   /* Rev. 0.0.0 (no rev. id) */
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+return t-ctrl;
+case REG_TIMER_CNTB:
+return t-cntb;
+case REG_TIMER_CNTO:
+if ((t-ctrl  TIMER_CTRL_START)  (t-timeout  now)) {
+ret = (t-timeout - now) / s-step;
+}
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftpwmtmr010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+int i;
+
+switch (addr) {
+case REG_SR:
+s-stat = ~((uint32_t)val);
+for (i = 0; i  8; ++i) {
+if (val  BIT(i)) {
+qemu_irq_lower(s-timer[i].irq);
+}
+}
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+t-ctrl = (uint32_t)val;
+if (t-ctrl  TIMER_CTRL_UPDATE) {
+t-countdown = (uint64_t)t-cntb * s-step;
+}
+if (t-ctrl  TIMER_CTRL_START) {
+t-timeout = t-countdown + qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-timeout);
+}
+break;
+case REG_TIMER_CNTB:
+t-cntb = (uint32_t)val;
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access

[Qemu-devel] [PATCH v8 07/24] hw/arm: add FTWDT010 watchdog timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTWDT010 is used to prevent system from infinite loop
while software gets trapped in the deadlock.

Under the normal operation, users should restart FTWDT010
at the regular intervals before counter counts down to 0.

If the counter does reach 0, FTWDT010 will try to reset
the system by generating one or a combination of signals,
system reset, system interrupt, and external interrupt.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   14 +++
 hw/arm/ftwdt010.c |  209 +
 hw/arm/ftwdt010.h |   35 
 4 files changed, 259 insertions(+)
 create mode 100644 hw/arm/ftwdt010.c
 create mode 100644 hw/arm/ftwdt010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bc18e22..bd330f2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -41,3 +41,4 @@ obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
+obj-y += ftwdt010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 874dc74..2ec066d 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -68,6 +68,16 @@ static void a369soc_reset(DeviceState *ds)
 }
 
 static void
+a369soc_system_reset(void *opaque)
+{
+FaradaySoCState *s = FARADAY_SOC(opaque);
+
+if (s-cpu) {
+cpu_reset(CPU(s-cpu));
+}
+}
+
+static void
 a369soc_device_init(FaradaySoCState *s)
 {
 Error *local_errp = NULL;
@@ -177,6 +187,10 @@ a369soc_device_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
+
+/* ftwdt010 */
+sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
+qemu_register_reset(a369soc_system_reset, s);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftwdt010.c b/hw/arm/ftwdt010.c
new file mode 100644
index 000..d9613ca
--- /dev/null
+++ b/hw/arm/ftwdt010.c
@@ -0,0 +1,209 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/watchdog.h
+#include sysemu/sysemu.h
+#include qemu/timer.h
+
+#include ftwdt010.h
+
+#define TYPE_FTWDT010   ftwdt010
+
+typedef struct Ftwdt010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+
+QEMUTimer *qtimer;
+
+uint64_t timeout;
+uint64_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+bool running;
+
+/* HW register cache */
+uint32_t load;
+uint32_t cr;
+uint32_t sr;
+} Ftwdt010State;
+
+#define FTWDT010(obj) \
+OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
+
+static uint64_t
+ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_COUNTER:
+if (s-cr  CR_EN) {
+ret = s-timeout - qemu_get_clock_ms(rt_clock);
+ret = MIN(s-load, ret * 100ULL / s-step);
+} else {
+ret = s-load;
+}
+break;
+case REG_LOAD:
+return s-load;
+case REG_CR:
+return s-cr;
+case REG_SR:
+return s-sr;
+case REG_REVR:
+return 0x00010601;  /* rev. 1.6.1 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+
+switch (addr) {
+case REG_LOAD:
+s-load = (uint32_t)val;
+break;
+case REG_RESTART:
+if ((s-cr  CR_EN)  (val == WDT_MAGIC)) {
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+}
+break;
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_EN) {
+if (s-running) {
+break;
+}
+s-running = true;
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+} else {
+s-running = false;
+qemu_del_timer(s-qtimer);
+}
+break;
+case REG_SCR:
+s-sr = ~(uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps

[Qemu-devel] [PATCH v8 02/24] hw/arm: add Faraday a369 SoC platform support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday A369 EVB is a Faraday SoC platform evalution board used for
Faraday IP functional verification based on the well-known ARM AMBA 2.0
architecture.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |3 +
 hw/arm/faraday.h  |   52 ++
 hw/arm/faraday_a369.c |   98 +++
 hw/arm/faraday_a369_kpd.c |  231 +
 hw/arm/faraday_a369_scu.c |  182 +++
 hw/arm/faraday_a369_soc.c |  190 +
 hw/arm/ftkbc010.h |   44 +
 7 files changed, 800 insertions(+)
 create mode 100644 hw/arm/faraday.h
 create mode 100644 hw/arm/faraday_a369.c
 create mode 100644 hw/arm/faraday_a369_kpd.c
 create mode 100644 hw/arm/faraday_a369_scu.c
 create mode 100644 hw/arm/faraday_a369_soc.c
 create mode 100644 hw/arm/ftkbc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f5f7d0e..104e0e7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -34,3 +34,6 @@ obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o
+
+obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
+faraday_a369_kpd.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
new file mode 100644
index 000..4a9c2ae
--- /dev/null
+++ b/hw/arm/faraday.h
@@ -0,0 +1,52 @@
+/*
+ * Faraday SoC platform support.
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Kuo-Jung Su dant...@gmail.com
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+#ifndef HW_ARM_FARADAY_H
+#define HW_ARM_FARADAY_H
+
+#include hw/flash.h
+#include qemu/bitops.h
+
+typedef struct FaradaySoCState {
+SysBusDevice busdev;
+hwaddr   rom_base;
+uint64_t rom_size;
+hwaddr   ram_base;
+uint64_t ram_size;
+char *cpu_model;
+ARMCPU   *cpu;
+qemu_irq pic[64];
+DeviceState  *scu;  /* System Control Unit */
+DeviceState  *ahbc; /* AHB controller */
+DeviceState  *ddrc; /* DDR controller */
+DeviceState  *hdma[2];  /* AHB DMA */
+DeviceState  *pdma[1];  /* APB DMA */
+DeviceState  *spi[2];   /* Generic SPI bus */
+DeviceState  *spi_fl[2];/* Dedicated SPI bus for flash memory */
+DeviceState  *i2c[2];   /* Generic I2C bus */
+DeviceState  *i2s[2];   /* Generic I2S bus */
+DeviceState  *nandc[2]; /* NAND flash controller */
+
+MemoryRegion *as;   /* address space */
+MemoryRegion *ram;  /* external sdram */
+pflash_t *rom;  /* on-chip rom */
+MemoryRegion *sram; /* on-chip static ram */
+
+uint32_t ahb_slave[32];
+uint32_t apb_slave[32];
+bool ahb_remapped;
+bool ddr_inited;
+struct arm_boot_info *bi;
+} FaradaySoCState;
+
+/* SoC common APIs */
+#define TYPE_FARADAY_SOCfaraday.soc
+#define FARADAY_SOC(obj) \
+OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
+
+#endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
new file mode 100644
index 000..3a89a04
--- /dev/null
+++ b/hw/arm/faraday_a369.c
@@ -0,0 +1,98 @@
+/*
+ * Faraday A369 Evalution Board
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/arm-misc.h
+#include hw/devices.h
+#include hw/i2c.h
+#include hw/boards.h
+#include hw/ssi.h
+#include net/net.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+/* Board init.  */
+
+static void
+a369_board_init(QEMUMachineInitArgs *args)
+{
+DeviceState *ds;
+FaradaySoCState *s;
+
+if (!args-cpu_model) {
+args-cpu_model = fa626te;
+}
+
+if (!args-ram_size) {
+args-ram_size = 512  20;
+}
+
+ds = qdev_create(NULL, TYPE_FARADAY_SOC);
+qdev_prop_set_string(ds, cpu_model, args-cpu_model);
+qdev_prop_set_uint64(ds, ram_size, args-ram_size);
+/* Setup QOM path for the SoC object (i.e. /machine/faraday.soc) */
+object_property_add_child(qdev_get_machine(),
+  TYPE_FARADAY_SOC,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+
+s = FARADAY_SOC(ds);
+
+/* System start-up */
+
+if (args-kernel_filename) {
+s-bi = g_new0(struct arm_boot_info, 1);
+
+s-ddr_inited = true;
+s-ahb_remapped = true;
+
+/* Remap AHB slave 4 (ROM)  slave 6 (RAM) */
+/* 1. Remap RAM to base of ROM */
+s-ram_base = s-ahb_slave[4]  0xfff0;
+s-ahb_slave[6] = s-ram_base | (s-ahb_slave[6]  0x000f);
+/* 2. Remap ROM to base of ROM + size of RAM */
+s-rom_base = s-ram_base
++ ((1  extract32(s-ahb_slave[6], 16, 4))  20);
+s-ahb_slave[4] = s-rom_base | (s

[Qemu-devel] [PATCH v8 00/24] hw/arm: add Faraday A369 SoC platform support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

These patches introduce Faraday A369 SoC platform support.

Here are some public documents for your reference.

http://www.faraday-tech.com/html/documentation/index.html

The partial version of faraday cpu datasheet with only
the CP15 and MPU description are available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAalh5TkxyZWtlWEE/edit?usp=sharing

The pre-built A369 images are also available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAX2pTTmtUMGFCZW8/edit

Here is the image file list:

1. android-4.0.4/zImage: A369 linux-3.0.31
2. android-4.0.4/romfs-4.0.4.tar.bz2: android-4.0.4
3. nand.img.bz2: A369 nand flash image
4. rom.img.bz2: A369 embedded ROM image
5. u-boot: A369 u-boot-2012.10 ELF file
6. zImage: A369 linux-3.4.12 + initramfs
7. README

If you want to re-build the image from scratch, 
try my Faraday Linux BSP/SDK: falinux.

1. Download the falinux

   $ git clone https://github.com/dantesu1218/falinux.git

2. Download all the required software packages:

   $ cd falinux
   $ make setup

3. Launch the menuconfig of falinux, and enable 'QEMU Support'

   $ make menuconfig

4. Re-build the packages

   $ make

5. Laungh the qemu-1.3.0 with the generated falinux images.

   $ make qemu

Changes for v7 - v8:
1. [hw/arm/ftintc020.c] (Addressed by Peter)
   'uint32_t mask = BIT(irq % 32);' - 'uint32_t mask = BIT(irq  0x1f);'
2. [hw/arm/*.c] (Addressed by Peter)
   Drop '#include faraday.h', and define DPRINTF() at per-file basis
   exit(1) - abort()
   SysBusDeviceClass::init() - Device::realize()

Changes for v6 - v7:

1. hw/arm/ftwdt010: (Addressed by Paolo)
   Replace 'qemu_system_reset_request()' with 'watchdog_perform_action()'.
2. hw/arm/ftrtc011: (Addressed by Paolo)
   Replace 'get_clock_realtime()' with 'qemu_get_clock_ns(rtc_clock)'.
   Replace 'qemu_new_timer_ms(rt_clock...)' with 
'qemu_new_timer_ms(rtc_clock...)'
   Rename 'ftrtc011_timer_resync' - 'ftrtc011_timer_rebase'
   Add ftrtc011_timer_resche()
   Add QTest support
3. hw/arm/faraday_a369_soc: (Addressed by Paolo)
   Remove redundant device reset from a369soc_system_reset(...)
4. include/qemu/bitops.h: (Addressed by Paolo)
   Update bitrev8() to use a kind of divide and conquer algorithm.
5. hw/arm/ftahb020,ftddrii030,ftapbbrg020,faraday_a369_soc:
   Drop FARADAY_SOC_GET_CORE(), replaced with device to device QOM link.
6. hw/wm8731,wm8750,marvell_88w8618_audio,spitz,z2:
   Add AudioCodecClass for wm87xx audio class abstration.
7. hw/arm/ftnandc021:
   Drop nand_init(), replaced with device to device QOM link.
8. hw/arm/ftsdc010:
   Bug fixed to write operation: remove sd_data_ready() in write path.
9. hw/arm/ftgmac100,ftmac110,ftwdt010:
   rt-clock - vm_clock
   10. hw/nand.c:
   Drop [hw/nand.c: correct the sense of the BUSY/READY], since it's 
already applied.
   Drop [hw/nand.c: bug fix to erase operation], since Peter has a better 
solution.

Changes for v5 - v6:

   1. hw/arm/Makefile.objs: 
   Shift to the next line only after current line length is  80 characters.
   2. hw/arm/faraday.h:
   Update debug macro format per discussions at the link bellow:
   http://thread.gmane.org/gmane.comp.emulators.qemu/195996/focus=196975
   3. hw/arm/faraday.h:
   TYPE_FARADAY_SOC: 'faraday/soc' - 'faraday.soc'
   4. hw/arm/*.c:
   Replace '%llx' with '%HWADDR_PRIx'
   5. hw/arm/*.h:
   Add '#include qemu/bitops.h'
   6. hw/arm/faraday_a369_soc.c:
   Typo fix: salve4 - slave4, salve6 - slave6
   7. hw/arm/*.c:
   Drop FROM_SYSBUS().
   8. hw/arm/ftintc020.c:
   Re-write the source file with pl190.c as template.
   9. hw/arm/ftintc020.h:
   Rename the registers to improve readibility.
   10. hw/arm/faraday.h:
   Add dedicated spi flash pointer array (DeviceState *spi_fl[2]).
   11. hw/arm/faraday.h:
   Add 'qemu_irq pic[64]'.
   12. hw/arm/*c:
   Replace the complex conversion in XXX_REG32() with directly array 
indexing.
   13. hw/arm/*c:
   Update the error message output from 'hw_error(...)' into 
'fprintf(stderr, ...)'
   14. hw/arm/faraday_a369.c, hw/arm/faraday_a369_soc.c:
   Move the external AHB device init from faraday_a369_soc.c to 
faraday_a369.c
   15. include/qemu/bitops.h:
   Move bitrev() from bitrev.[ch] into bitops.h
   16. hw/nand.c:
   Remove the clear/set SR[6] code in read/erase/write, because
   it's not possible to be observed by a guest.
   17. hw/arm/faraday_a369_kpd.c:
   Function prefix: 'ftkbc010' - 'a369kpd' 
   Name of struct:  'FTKBC010State' - 'A369KPDState'.
   QOM: 'FTKBC010' - 'A369KPD'
   18. hw/arm/ftddrii030.c:
   'case REG_MCR ... 0x4c' - 'case REG_MCR ... (CFG_REGSIZE - 1) * 4'
   19. hw/arm/ftahbc020.c:
   Add comments to fall-through path. (i.e. /* fall-through - skip slave6 
*/)
   20. hw/arm/faraday_a369

[Qemu-devel] [PATCH v8 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTDDRII030 is a DDRII SDRAM controller which is responsible for
SDRAM initialization.
In QEMU we emulate only the SDRAM enable function.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |9 +++
 hw/arm/ftddrii030.c   |  183 +
 3 files changed, 193 insertions(+)
 create mode 100644 hw/arm/ftddrii030.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index af36b01..0bbf838 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -39,3 +39,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 faraday_a369_kpd.o
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
+obj-y += ftddrii030.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 01b4395..e8a63bb 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -158,6 +158,15 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
 abort();
 }
+
+/* ftddrii030 */
+ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
+s-ddrc = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
new file mode 100644
index 000..90a5842
--- /dev/null
+++ b/hw/arm/ftddrii030.c
@@ -0,0 +1,183 @@
+/*
+ * Faraday DDRII controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+#define REG_MCR 0x00/* memory configuration register */
+#define REG_MSR 0x04/* memory status register */
+#define REG_REVR0x50/* revision register */
+
+#define MSR_INIT_OK BIT(8)  /* DDR2 initial is completed */
+#define MSR_CMD_MRS BIT(0)  /* start MRS command */
+
+#define CFG_REGSIZE (0x50 / 4)
+
+#define TYPE_FTDDRII030 ftddrii030
+
+typedef struct Ftddrii030State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftddrii030State;
+
+#define FTDDRII030(obj) \
+OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
+
+#define DDR_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static uint64_t
+ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+uint64_t ret = 0;
+
+if (s-soc-ddr_inited) {
+DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
+}
+
+switch (addr) {
+case REG_MCR ... (CFG_REGSIZE - 1) * 4:
+ret = s-regs[addr / 4];
+break;
+case REG_REVR:
+ret = 0x100;/* rev. = 0.1.0 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+
+switch (addr) {
+case REG_MCR:
+DDR_REG32(s, REG_MCR) = (uint32_t)val  0x;
+break;
+case REG_MSR:
+val = (val  0x3f) | (DDR_REG32(s, REG_MSR)  MSR_INIT_OK);
+if (!s-soc-ddr_inited  (val  MSR_CMD_MRS)) {
+val = ~MSR_CMD_MRS;
+val |= MSR_INIT_OK;
+memory_region_add_subregion(s-soc-as,
+s-soc-ram_base,
+s-soc-ram);
+s-soc-ddr_inited = true;
+}
+DDR_REG32(s, REG_MSR) = (uint32_t)val;
+break;
+case 0x08 ... (CFG_REGSIZE - 1) * 4: /* DDRII Timing, ECC ...etc. */
+s-regs[addr / 4] = (uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mmio_ops = {
+.read  = ftddrii030_mem_read,
+.write = ftddrii030_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+}
+};
+
+static void ftddrii030_reset(DeviceState *ds)
+{
+Ftddrii030State *s = FTDDRII030(SYS_BUS_DEVICE(ds));
+Error *local_errp = NULL;
+
+s-soc = FARADAY_SOC(object_property_get_link(OBJECT(s),
+  soc,
+  local_errp));
+if (local_errp) {
+fprintf(stderr, ftahbc020: Unable to get soc link\n

[Qemu-devel] [PATCH v8 07/24] hw/arm: add FTWDT010 watchdog timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTWDT010 is used to prevent system from infinite loop
while software gets trapped in the deadlock.

Under the normal operation, users should restart FTWDT010
at the regular intervals before counter counts down to 0.

If the counter does reach 0, FTWDT010 will try to reset
the system by generating one or a combination of signals,
system reset, system interrupt, and external interrupt.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   14 +++
 hw/arm/ftwdt010.c |  209 +
 hw/arm/ftwdt010.h |   35 
 4 files changed, 259 insertions(+)
 create mode 100644 hw/arm/ftwdt010.c
 create mode 100644 hw/arm/ftwdt010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bc18e22..bd330f2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -41,3 +41,4 @@ obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
+obj-y += ftwdt010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 874dc74..2ec066d 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -68,6 +68,16 @@ static void a369soc_reset(DeviceState *ds)
 }
 
 static void
+a369soc_system_reset(void *opaque)
+{
+FaradaySoCState *s = FARADAY_SOC(opaque);
+
+if (s-cpu) {
+cpu_reset(CPU(s-cpu));
+}
+}
+
+static void
 a369soc_device_init(FaradaySoCState *s)
 {
 Error *local_errp = NULL;
@@ -177,6 +187,10 @@ a369soc_device_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
+
+/* ftwdt010 */
+sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
+qemu_register_reset(a369soc_system_reset, s);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftwdt010.c b/hw/arm/ftwdt010.c
new file mode 100644
index 000..d9613ca
--- /dev/null
+++ b/hw/arm/ftwdt010.c
@@ -0,0 +1,209 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/watchdog.h
+#include sysemu/sysemu.h
+#include qemu/timer.h
+
+#include ftwdt010.h
+
+#define TYPE_FTWDT010   ftwdt010
+
+typedef struct Ftwdt010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+
+QEMUTimer *qtimer;
+
+uint64_t timeout;
+uint64_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+bool running;
+
+/* HW register cache */
+uint32_t load;
+uint32_t cr;
+uint32_t sr;
+} Ftwdt010State;
+
+#define FTWDT010(obj) \
+OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
+
+static uint64_t
+ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_COUNTER:
+if (s-cr  CR_EN) {
+ret = s-timeout - qemu_get_clock_ms(rt_clock);
+ret = MIN(s-load, ret * 100ULL / s-step);
+} else {
+ret = s-load;
+}
+break;
+case REG_LOAD:
+return s-load;
+case REG_CR:
+return s-cr;
+case REG_SR:
+return s-sr;
+case REG_REVR:
+return 0x00010601;  /* rev. 1.6.1 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+
+switch (addr) {
+case REG_LOAD:
+s-load = (uint32_t)val;
+break;
+case REG_RESTART:
+if ((s-cr  CR_EN)  (val == WDT_MAGIC)) {
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+}
+break;
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_EN) {
+if (s-running) {
+break;
+}
+s-running = true;
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+} else {
+s-running = false;
+qemu_del_timer(s-qtimer);
+}
+break;
+case REG_SCR:
+s-sr = ~(uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps

[Qemu-devel] [PATCH v8 03/24] hw/arm: add FTINTC020 interrupt controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTINTC020 interrupt controller supports both FIQ and IRQ signals
to the microprocessor.
It can handle up to 64 configurable IRQ sources and 64 FIQ sources.
The output signals to the microprocessor can be configured as
level-high/low active or edge-rising/falling triggered.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   11 ++
 hw/arm/ftintc020.c|  302 +
 hw/arm/ftintc020.h|   57 +
 4 files changed, 371 insertions(+)
 create mode 100644 hw/arm/ftintc020.c
 create mode 100644 hw/arm/ftintc020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 104e0e7..536d6cf 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -37,3 +37,4 @@ obj-y += omap1.o omap2.o
 
 obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
 faraday_a369_kpd.o
+obj-y += ftintc020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 4e19c7e..eab05dc 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -72,6 +72,8 @@ a369soc_device_init(FaradaySoCState *s)
 {
 DriveInfo *dinfo;
 DeviceState *ds;
+qemu_irq *cpu_pic;
+int i;
 
 s-as = get_system_memory();
 s-ram = g_new(MemoryRegion, 1);
@@ -111,6 +113,15 @@ a369soc_device_init(FaradaySoCState *s)
 abort();
 }
 
+/* Interrupt Controller */
+cpu_pic = arm_pic_init_cpu(s-cpu);
+ds = sysbus_create_varargs(ftintc020, 0x9010,
+   cpu_pic[ARM_PIC_CPU_IRQ],
+   cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+for (i = 0; i  ARRAY_SIZE(s-pic); ++i) {
+s-pic[i] = qdev_get_gpio_in(ds, i);
+}
+
 /* Serial (FTUART010 which is 16550A compatible) */
 if (serial_hds[0]) {
 serial_mm_init(s-as,
diff --git a/hw/arm/ftintc020.c b/hw/arm/ftintc020.c
new file mode 100644
index 000..1a476d3
--- /dev/null
+++ b/hw/arm/ftintc020.c
@@ -0,0 +1,302 @@
+/*
+ * Faraday FTINTC020 Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+
+#include ftintc020.h
+
+#define TYPE_FTINTC020  ftintc020
+
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftintc020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+qemu_irq irq;
+qemu_irq fiq;
+
+uint32_t irq_ps[2]; /* IRQ pin state */
+uint32_t fiq_ps[2]; /* FIQ pin state */
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftintc020State;
+
+#define FTINTC020(obj) \
+OBJECT_CHECK(Ftintc020State, obj, TYPE_FTINTC020)
+
+#define PIC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+#define IRQ_REG32(s, n, off) \
+((s)-regs[(REG_IRQ(n) + ((off)  REG_MASK)) / 4])
+
+#define FIQ_REG32(s, n, off) \
+((s)-regs[(REG_FIQ(n) + ((off)  REG_MASK)) / 4])
+
+static void
+ftintc020_update_irq(Ftintc020State *s)
+{
+uint32_t mask[2];
+
+/* FIQ */
+mask[0] = PIC_REG32(s, REG_FIQ32SRC)  PIC_REG32(s, REG_FIQ32ENA);
+mask[1] = PIC_REG32(s, REG_FIQ64SRC)  PIC_REG32(s, REG_FIQ64ENA);
+qemu_set_irq(s-fiq, !!(mask[0] || mask[1]));
+
+/* IRQ */
+mask[0] = PIC_REG32(s, REG_IRQ32SRC)  PIC_REG32(s, REG_IRQ32ENA);
+mask[1] = PIC_REG32(s, REG_IRQ64SRC)  PIC_REG32(s, REG_IRQ64ENA);
+qemu_set_irq(s-irq, !!(mask[0] || mask[1]));
+}
+
+/* Note: Here level means state of the signal on a pin */
+static void
+ftintc020_set_irq(void *opaque, int irq, int level)
+{
+Ftintc020State *s = FTINTC020(opaque);
+uint32_t i = irq / 32;
+uint32_t mask = BIT(irq  0x1f);
+
+switch (irq) {
+case 0  ... 63:
+/* IRQ */
+if (IRQ_REG32(s, irq, REG_MDR)  mask) {
+/* Edge Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Falling Active */
+if ((s-irq_ps[i]  mask)  !level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* Rising Active */
+if (!(s-irq_ps[i]  mask)  level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+}
+} else {
+/* Level Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Low Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* High Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+}
+}
+}
+
+/* FIQ

[Qemu-devel] [PATCH v8 08/24] hw/arm: add FTRTC011 RTC timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It provides separate second, minute, hour, and day counters. The second
counter is toggled each second, the minute counter is toggled each minute,
the hour counter is toggled each hour, and the day counter is toggled each day.

The FTRTC011 provides a programmable auto-alarm function. When the second
auto-alarm function is turned on, the RTC will automatically trigger an
interrupt each second. The automatic minute and hour alarms can be turned on
as well.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   18 +++
 hw/arm/ftrtc011.c |  383 +
 hw/arm/ftrtc011.h |   53 +++
 4 files changed, 455 insertions(+)
 create mode 100644 hw/arm/ftrtc011.c
 create mode 100644 hw/arm/ftrtc011.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bd330f2..b01da9d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -42,3 +42,4 @@ obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
+obj-y += ftrtc011.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 2ec066d..7d90079 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -191,6 +191,24 @@ a369soc_device_init(FaradaySoCState *s)
 /* ftwdt010 */
 sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
 qemu_register_reset(a369soc_system_reset, s);
+
+/* ftrtc011 */
+ds = qdev_create(NULL, ftrtc011);
+/* Setup QOM path for QTest */
+object_property_add_child(OBJECT(s),
+  ftrtc011,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9210);
+/* Alarm (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[42]);
+/* Second (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[43]);
+/* Minute (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
+/* Hour (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftrtc011.c b/hw/arm/ftrtc011.c
new file mode 100644
index 000..2815f16
--- /dev/null
+++ b/hw/arm/ftrtc011.c
@@ -0,0 +1,383 @@
+/*
+ * QEMU model of the FTRTC011 RTC Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include ftrtc011.h
+
+enum ftrtc011_irqpin {
+IRQ_ALARM_LEVEL = 0,
+IRQ_ALARM_EDGE,
+IRQ_SEC,
+IRQ_MIN,
+IRQ_HOUR,
+IRQ_DAY,
+};
+
+#define TYPE_FTRTC011   ftrtc011
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Ftrtc011State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq[6];
+
+QEMUTimer *qtimer;
+int64_t rtc_base;
+int64_t rtc_start;
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftrtc011State;
+
+#define FTRTC011(obj) \
+OBJECT_CHECK(Ftrtc011State, obj, TYPE_FTRTC011)
+
+#define RTC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+/* Update interrupts.  */
+static void ftrtc011_update_irq(Ftrtc011State *s)
+{
+uint32_t mask = extract32(RTC_REG32(s, REG_CR), 1, 5)
+   RTC_REG32(s, REG_ISR);
+
+qemu_set_irq(s-irq[IRQ_ALARM_LEVEL], !!(mask  ISR_ALARM));
+
+if (mask) {
+if (mask  ISR_SEC) {
+qemu_irq_pulse(s-irq[IRQ_SEC]);
+}
+if (mask  ISR_MIN) {
+qemu_irq_pulse(s-irq[IRQ_MIN]);
+}
+if (mask  ISR_HOUR) {
+qemu_irq_pulse(s-irq[IRQ_HOUR]);
+}
+if (mask  ISR_DAY) {
+qemu_irq_pulse(s-irq[IRQ_DAY]);
+}
+if (mask  ISR_ALARM) {
+qemu_irq_pulse(s-irq[IRQ_ALARM_EDGE]);
+}
+}
+}
+
+static void ftrtc011_timer_rebase(Ftrtc011State *s)
+{
+int64_t ticks = get_ticks_per_sec();
+int64_t elapsed = RTC_REG32(s, REG_SEC)
++ (60LL * RTC_REG32(s, REG_MIN))
++ (3600LL * RTC_REG32(s, REG_HOUR))
++ (86400LL * RTC_REG32(s, REG_DAY));
+
+s-rtc_base  = elapsed;
+s-rtc_start = qemu_get_clock_ns(rtc_clock);
+/* adjust to the beginning of the current second */
+s-rtc_start = s-rtc_start - (s-rtc_start % ticks);
+}
+
+static void ftrtc011_timer_update(Ftrtc011State *s)
+{
+int64_t elapsed;
+uint8_t sec, min, hr;
+uint32_t day;
+
+/* check if RTC is enabled */
+if (!(RTC_REG32(s, REG_CR)  CR_EN)) {
+return;
+}
+
+/*
+ * 2013.03.11 Kuo-Jung Su
+ * Under QTest, in the very beginning of test,
+ * qemu_get_clock_ns(rtc_clock) would somehow jumps
+ * from 0 sec into 436474 sec.
+ * So I have to apply this simple work-aroud to make it work

[Qemu-devel] [PATCH v8 15/24] hw: add WM8731 audio codec support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Wolfson WM8731 is a simple audio codec for embedded systems.
It has 2 input and 1 output ports:

** Input **
1. Linue-In
2. Microphone

** Output **
1. Headphone out

BTW it's based on hw/wm8750.c with 16-bit I2S support by default.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 default-configs/arm-softmmu.mak |1 +
 hw/Makefile.objs|1 +
 hw/wm8731.c |  505 +++
 3 files changed, 507 insertions(+)
 create mode 100644 hw/wm8731.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 68b2045..131f85b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_SD=y
 CONFIG_MAX7310=y
+CONFIG_WM8731=y
 CONFIG_WM8750=y
 CONFIG_TWL92230=y
 CONFIG_TSC2005=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index aafcac5..6fdaf41 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -168,6 +168,7 @@ common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
 common-obj-y += audio_codec.o
+common-obj-$(CONFIG_WM8731) += wm8731.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/wm8731.c b/hw/wm8731.c
new file mode 100644
index 000..1696690
--- /dev/null
+++ b/hw/wm8731.c
@@ -0,0 +1,505 @@
+/*
+ * WM8731 audio codec.
+ *
+ * base is wm8750.c
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw.h
+#include i2c.h
+#include audio_codec.h
+#include audio/audio.h
+
+#define IN_PORT_N   2
+#define OUT_PORT_N  1
+
+#define TYPE_WM8731 wm8731
+
+typedef struct WMRate {
+int adc;
+int adc_hz;
+int dac;
+int dac_hz;
+} WMRate;
+
+typedef struct WM8731State {
+AudioCodecState parent;
+
+uint8_t i2c_data[2];
+int i2c_len;
+QEMUSoundCard card;
+SWVoiceIn *adc_voice[IN_PORT_N];
+SWVoiceOut *dac_voice[OUT_PORT_N];
+void (*data_req)(void *, int, int);
+void *opaque;
+uint8_t data_in[4096];
+uint8_t data_out[4096];
+int idx_in, req_in;
+int idx_out, req_out;
+
+SWVoiceOut **out[2];
+uint8_t outvol[2];
+SWVoiceIn **in[2];
+uint8_t invol[2], inmute[2], mutemic;
+
+uint8_t mute;
+uint8_t power, format, active;
+const WMRate *rate;
+uint8_t rate_vmstate;
+int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
+} WM8731State;
+
+#define WM8731(obj) \
+OBJECT_CHECK(WM8731State, obj, TYPE_WM8731)
+
+#define WM8731_OUTVOL_TRANSFORM(x)  (x  1)
+#define WM8731_INVOL_TRANSFORM(x)   (x  3)
+
+static inline void wm8731_in_load(WM8731State *s)
+{
+if (s-idx_in + s-req_in = sizeof(s-data_in)) {
+return;
+}
+s-idx_in = audio_MAX(0, (int) sizeof(s-data_in) - s-req_in);
+AUD_read(*s-in[0], s-data_in + s-idx_in,
+ sizeof(s-data_in) - s-idx_in);
+}
+
+static inline void wm8731_out_flush(WM8731State *s)
+{
+int sent = 0;
+while (sent  s-idx_out) {
+sent += AUD_write(*s-out[0], s-data_out + sent, s-idx_out - sent)
+? 0 : s-idx_out;
+}
+s-idx_out = 0;
+}
+
+static void wm8731_audio_in_cb(void *opaque, int avail_b)
+{
+WM8731State *s = WM8731(opaque);
+s-req_in = avail_b;
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, avail_b  1);
+}
+
+static void wm8731_audio_out_cb(void *opaque, int free_b)
+{
+WM8731State *s = WM8731(opaque);
+
+if (s-idx_out = free_b) {
+s-idx_out = free_b;
+s-req_out = 0;
+wm8731_out_flush(s);
+} else {
+s-req_out = free_b - s-idx_out;
+}
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, s-req_in  1);
+}
+
+static const WMRate wm_rate_table[] = {
+{  256, 48000,  256, 48000 },/* SR: , BOSR: 0 */
+{  384, 48000,  384, 48000 },/* SR: , BOSR: 1 */
+{  256, 48000,  256,  8000 },/* SR: 0001, BOSR: 0 */
+{  384, 48000,  384,  8000 },/* SR: 0001, BOSR: 1 */
+{  256,  8000,  256, 48000 },/* SR: 0010, BOSR: 0 */
+{  384,  8000,  384, 48000 },/* SR: 0010, BOSR: 1 */
+{  256,  8000,  256,  8000 },/* SR: 0011, BOSR: 0 */
+{  384,  8000,  384,  8000 },/* SR: 0011, BOSR: 1 */
+{  256, 32000,  256, 32000 },/* SR: 0110, BOSR: 0 */
+{  384, 32000,  384, 32000 },/* SR: 0110, BOSR: 1 */
+{  128, 96000,  128, 96000 },/* SR: 0111, BOSR: 0 */
+{  192, 96000,  192, 96000 },/* SR: 0111, BOSR: 1 */
+{  256, 44100,  256, 44100 },/* SR: 1000, BOSR: 0 */
+{  384, 44100,  384, 44100 },/* SR: 1000, BOSR: 1 */
+{  256, 44100,  256,  8000 },/* SR: 1001, BOSR: 0 */
+{  384, 44100,  384,  8000 },/* SR: 1001, BOSR: 1 */
+{  256,  8000,  256, 44100 },/* SR

[Qemu-devel] [PATCH v8 06/24] hw/arm: add FTPWMTMR010 timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTPWMTMR010 is an APB device which provides up to 8 independent timers.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   10 ++
 hw/arm/ftpwmtmr010.c  |  258 +
 hw/arm/ftpwmtmr010.h  |   31 ++
 4 files changed, 300 insertions(+)
 create mode 100644 hw/arm/ftpwmtmr010.c
 create mode 100644 hw/arm/ftpwmtmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0bbf838..bc18e22 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -40,3 +40,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
+obj-y += ftpwmtmr010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index e8a63bb..874dc74 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -167,6 +167,16 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 abort();
 }
+
+/* Timer */
+ds = qdev_create(NULL, ftpwmtmr010);
+qdev_prop_set_uint32(ds, freq, 66 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9230);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, s-pic[8]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftpwmtmr010.c b/hw/arm/ftpwmtmr010.c
new file mode 100644
index 000..c212cfe
--- /dev/null
+++ b/hw/arm/ftpwmtmr010.c
@@ -0,0 +1,258 @@
+/*
+ * Faraday FTPWMTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include ftpwmtmr010.h
+
+#define TYPE_FTPWMTMR010ftpwmtmr010
+#define TYPE_FTPWMTMR010_TIMER  ftpwmtmr010_timer
+
+typedef struct Ftpwmtmr010State Ftpwmtmr010State;
+
+typedef struct Ftpwmtmr010Timer {
+uint32_t ctrl;
+uint32_t cntb;
+int id;
+uint64_t timeout;
+uint64_t countdown;
+qemu_irq irq;
+QEMUTimer *qtimer;
+Ftpwmtmr010State *chip;
+} Ftpwmtmr010Timer;
+
+struct Ftpwmtmr010State {
+SysBusDevice busdev;
+
+MemoryRegion iomem;
+Ftpwmtmr010Timer timer[8];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+uint32_t stat;
+};
+
+#define FTPWMTMR010(obj) \
+OBJECT_CHECK(Ftpwmtmr010State, obj, TYPE_FTPWMTMR010)
+
+static uint64_t
+ftpwmtmr010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t ret = 0;
+
+switch (addr) {
+case REG_SR:
+ret = s-stat;
+break;
+case REG_REVR:
+ret = 0x;   /* Rev. 0.0.0 (no rev. id) */
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+return t-ctrl;
+case REG_TIMER_CNTB:
+return t-cntb;
+case REG_TIMER_CNTO:
+if ((t-ctrl  TIMER_CTRL_START)  (t-timeout  now)) {
+ret = (t-timeout - now) / s-step;
+}
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftpwmtmr010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+int i;
+
+switch (addr) {
+case REG_SR:
+s-stat = ~((uint32_t)val);
+for (i = 0; i  8; ++i) {
+if (val  BIT(i)) {
+qemu_irq_lower(s-timer[i].irq);
+}
+}
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+t-ctrl = (uint32_t)val;
+if (t-ctrl  TIMER_CTRL_UPDATE) {
+t-countdown = (uint64_t)t-cntb * s-step;
+}
+if (t-ctrl  TIMER_CTRL_START) {
+t-timeout = t-countdown + qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-timeout);
+}
+break;
+case REG_TIMER_CNTB:
+t-cntb = (uint32_t)val;
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access

[Qemu-devel] [PATCH v8 22/24] hw/arm: add FTMAC110 10/100Mbps ethernet support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTMAC110 is an Ethernet controller that provides AHB master capability
and is in full compliance with the IEEE 802.3 10/100 Mbps specifications.
Its DMA controller handles all data transfers between system memory
and on-chip memories.

It supports half-word data transfer for Linux. However it has a weird DMA
alignment issue:

(1) Tx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: O.K

(2) Rx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: Invalid (It means 0x0, 0x4, 0x8, 0xC are invalid)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369.c |7 +
 hw/arm/ftmac110.c |  661 +
 hw/arm/ftmac110.h |  168 +
 5 files changed, 840 insertions(+)
 create mode 100644 hw/arm/ftmac110.c
 create mode 100644 hw/arm/ftmac110.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0920270..985cb0b 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -52,3 +52,4 @@ obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
 obj-y += fttsc010.o
 obj-y += ftsdc010.o
+obj-y += ftmac110.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 37c6447..3540f57 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -55,4 +55,7 @@ void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 /* ftgmac100.c */
 void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
 
+/* ftmac110.c */
+void ftmac110_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 139a244..c4a9408 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -91,6 +91,13 @@ a369_board_init(QEMUMachineInitArgs *args)
  s-i2s[0]);
 }
 
+/* External AHB devices */
+
+/* Ethernet: FTMAC110 */
+if (nb_nics  1) {
+ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftmac110.c b/hw/arm/ftmac110.c
new file mode 100644
index 000..bc0f656
--- /dev/null
+++ b/hw/arm/ftmac110.c
@@ -0,0 +1,661 @@
+/*
+ * QEMU model of the FTMAC110 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+/***/
+/*   FTMAC110 DMA design issue */
+/* Dante Su 2010.02.03 */
+/* */
+/* The DMA engine has a weird restriction that its Rx DMA engine   */
+/* accepts only 16-bits aligned address, 32-bits aligned is still  */
+/* invalid. However this restriction does not apply to Tx DMA. */
+/* Conclusion: */
+/* (1) Tx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: O.K (- u-boot ZeroCopy is possible)   */
+/* (2) Rx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: Invalid*/
+/***/
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include faraday.h
+#include ftmac110.h
+
+#ifndef DEBUG
+#define DEBUG   0
+#endif
+
+#define DPRINTF(fmt, ...) \
+do { \
+if (DEBUG) { \
+fprintf(stderr, fmt , ## __VA_ARGS__); \
+} \
+} while (0)
+
+#define TYPE_FTMAC110   ftmac110
+
+#define CFG_MAXFRMLEN   1536/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftmac110State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftmac110State;
+
+#define FTMAC110(obj) \
+OBJECT_CHECK(Ftmac110State, obj, TYPE_FTMAC110)
+
+#define MAC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static int ftmac110_mcast_hash(int len, const uint8_t *p)
+{
+#define CRCPOLY_LE 0xedb88320
+int i;
+uint32_t crc = 0x;
+
+while (len--) {
+crc ^= *p++;
+for (i = 0; i  8; i

[Qemu-devel] [PATCH v8 09/24] tests: add QTest for FTRTC011

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTRTC011 QEMU model is implemented without calender functions.
It acts in counter mode only, all the time  timezone conversion
relies on the c runtime library. (i.e. mktime(), localtime() ...etc)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 tests/Makefile|3 +
 tests/ftrtc011-test.c |  410 +
 2 files changed, 413 insertions(+)
 create mode 100644 tests/ftrtc011-test.c

diff --git a/tests/Makefile b/tests/Makefile
index 567e36e..5d0776e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -75,6 +75,8 @@ gcov-files-sparc-y += hw/m48t59.c
 gcov-files-sparc64-y += hw/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 gcov-files-arm-y += hw/tmp105.c
+check-qtest-arm-y = tests/ftrtc011-test$(EXESUF)
+gcov-files-arm-y += hw/arm/ftrtc011.c
 
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h 
tests/test-qmp-commands.h
 
@@ -133,6 +135,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o
+tests/ftrtc011-test$(EXESUF): tests/ftrtc011-test.o
 
 # QTest rules
 
diff --git a/tests/ftrtc011-test.c b/tests/ftrtc011-test.c
new file mode 100644
index 000..e2324fa
--- /dev/null
+++ b/tests/ftrtc011-test.c
@@ -0,0 +1,410 @@
+/*
+ * QTest testcase for the FTRTC011 real-time clock
+ *
+ * Copyright (c) 2013 Kuo-Jung Su
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include libqtest.h
+#include hw/arm/ftrtc011.h
+
+#include glib.h
+#include stdio.h
+#include string.h
+#include stdlib.h
+#include unistd.h
+
+#define A369_FTRTC011_BASE  0x9210
+#define A369_FTRTC011_IRQ_ALARM 42  /* edge triggered */
+#define A369_FTRTC011_IRQ_SEC   43  /* edge triggered */
+#define A369_FTRTC011_IRQ_MIN   44  /* edge triggered */
+#define A369_FTRTC011_IRQ_HOUR  45  /* edge triggered */
+
+#define CFG_BASEYEAR2010
+
+static time_t ts_base;
+
+static uint32_t rtc_read(uint32_t reg)
+{
+return readl(A369_FTRTC011_BASE + reg);
+}
+
+static void rtc_write(uint32_t reg, uint32_t val)
+{
+writel(A369_FTRTC011_BASE + reg, val);
+}
+
+static int rtc_get_irq(int irq)
+{
+#if 0   /* It looks to me that get_irq() doesn't work well
+ * with edge interrupts.
+ */
+return get_irq(irq);
+#else
+switch (irq) {
+case A369_FTRTC011_IRQ_ALARM:
+return !!(rtc_read(REG_ISR)  ISR_ALARM);
+case A369_FTRTC011_IRQ_SEC:
+return !!(rtc_read(REG_ISR)  ISR_SEC);
+case A369_FTRTC011_IRQ_MIN:
+return !!(rtc_read(REG_ISR)  ISR_MIN);
+case A369_FTRTC011_IRQ_HOUR:
+return !!(rtc_read(REG_ISR)  ISR_HOUR);
+default:
+return 0;
+}
+#endif
+}
+
+static int tm_cmp(struct tm *lhs, struct tm *rhs)
+{
+time_t a, b;
+struct tm d1, d2;
+
+memcpy(d1, lhs, sizeof(d1));
+memcpy(d2, rhs, sizeof(d2));
+
+a = mktime(d1);
+b = mktime(d2);
+
+if (a  b) {
+return -1;
+} else if (a  b) {
+return 1;
+}
+
+return 0;
+}
+
+static void rtc_start(void)
+{
+time_t ts;
+struct tm base;
+
+if (!ts_base) {
+base.tm_isdst = -1;
+base.tm_year  = CFG_BASEYEAR - 1900;
+base.tm_mon   = 0;
+base.tm_mday  = 1;
+base.tm_hour  = 0;
+base.tm_min   = 0;
+base.tm_sec   = 0;
+ts_base = mktime(base);
+}
+
+ts = time(NULL) - ts_base;
+rtc_write(REG_WDAY, ts / 86400LL);
+ts %= 86400LL;
+rtc_write(REG_WHOUR, ts / 3600LL);
+ts %= 3600LL;
+rtc_write(REG_WMIN, ts / 60LL);
+ts %= 60LL;
+rtc_write(REG_WSEC, ts);
+
+rtc_write(REG_ISR, ISR_MASK);
+rtc_write(REG_CR, CR_EN | CR_LOAD | CR_INTR_MASK);
+}
+
+static void rtc_get_datetime(struct tm *date)
+{
+time_t ts;
+int64_t sec, min, hour, day;
+
+if (!ts_base) {
+fprintf(stderr, ts_base is not yet initialized!\n);
+exit(1);
+}
+
+sec  = rtc_read(REG_SEC);
+min  = rtc_read(REG_MIN);
+hour = rtc_read(REG_HOUR);
+day  = rtc_read(REG_DAY);
+ts   = ts_base + (86400LL * day) + (hour * 3600LL) + (min * 60LL) + sec;
+
+localtime_r(ts, date);
+}
+
+static void rtc_test_check_time(int wiggle)
+{
+struct tm start, date[4], end;
+struct tm *datep;
+time_t ts;
+
+rtc_start();
+
+/*
+ * This check assumes a few things.
+ * First, we cannot guarantee that we get a consistent reading
+ * from the wall clock because we may hit an edge of the clock
+ * while reading.
+ * To work around this, we read four clock readings such that
+ * at least two of them should match.  We need to assume that one
+ * reading is corrupt so we need four readings to ensure that we have at
+ * least two consecutive identical readings

[Qemu-devel] [PATCH v8 23/24] hw/arm: add FTTMR010 timer support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTMR010 provides three independent sets of sub-timers.
Two match registers are provided for each sub-timer, whenever
the value of the match registers equals any one value of the
sub-timers, the timer interrupt will be immediately triggered.
And it would also issue an interrupt when an overflow occurs.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |8 +
 hw/arm/fttmr010.c |  445 +
 hw/arm/fttmr010.h |   41 +
 4 files changed, 495 insertions(+)
 create mode 100644 hw/arm/fttmr010.c
 create mode 100644 hw/arm/fttmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 985cb0b..d0ce0e2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -53,3 +53,4 @@ obj-y += ftlcdc200.o
 obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
+obj-y += fttmr010.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index c4a9408..a3edacb 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -98,6 +98,14 @@ a369_board_init(QEMUMachineInitArgs *args)
 ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
 }
 
+/* Timer: FTTMR010 */
+ds = qdev_create(NULL, fttmr010);
+qdev_prop_set_uint32(ds, freq, 33 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0xC020);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/fttmr010.c b/hw/arm/fttmr010.c
new file mode 100644
index 000..b6f3b3a
--- /dev/null
+++ b/hw/arm/fttmr010.c
@@ -0,0 +1,445 @@
+/*
+ * Faraday FTTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include fttmr010.h
+
+#define TYPE_FTTMR010   fttmr010
+#define TYPE_FTTMR010_TIMER fttmr010_timer
+
+typedef struct Fttmr010State Fttmr010State;
+
+typedef struct Fttmr010Timer {
+int id;
+int up;
+Fttmr010State *chip;
+qemu_irq irq;
+QEMUTimer *qtimer;
+uint64_t start;
+uint32_t intr_match1:1;
+uint32_t intr_match2:1;
+
+/* HW register caches */
+uint64_t counter;
+uint64_t reload;
+uint32_t match1;
+uint32_t match2;
+
+} Fttmr010Timer;
+
+struct Fttmr010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+Fttmr010Timer timer[3];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+
+/* HW register caches */
+uint32_t cr;
+uint32_t isr;
+uint32_t imr;
+};
+
+#define FTTMR010(obj) \
+OBJECT_CHECK(Fttmr010State, obj, TYPE_FTTMR010)
+
+static void fttmr010_timer_restart(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t interval;
+int pending = 0;
+
+t-intr_match1 = 0;
+t-intr_match2 = 0;
+
+/* check match1 */
+if (t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (!t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (t-match1 == t-counter) {
+s-isr |= ISR_MATCH1(t-id);
+++pending;
+}
+
+/* check match2 */
+if (t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (!t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (t-match2 == t-counter) {
+s-isr |= ISR_MATCH2(t-id);
+++pending;
+}
+
+/* determine delay interval */
+if (t-up) {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = MIN(t-match1, t-match2) - t-counter;
+} else if (t-match1  t-counter) {
+interval = t-match1 - t-counter;
+} else if (t-match2  t-reload) {
+interval = t-match2 - t-counter;
+} else {
+interval = 0xULL - t-counter;
+}
+} else {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = t-counter - MAX(t-match1, t-match2);
+} else if (t-match1  t-reload) {
+interval = t-counter - t-match1;
+} else if (t-match2  t-reload) {
+interval = t-counter - t-match2;
+} else {
+interval = t-counter;
+}
+}
+
+if (pending) {
+qemu_irq_pulse(s-irq);
+qemu_irq_pulse(t-irq);
+}
+t-start = qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-start + interval * s-step);
+}
+
+static uint64_t fttmr010_update_counter(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t elapsed;
+int pending = 0;
+
+if (s-cr  CR_TMR_EN(t-id)) {
+/* get elapsed time */
+elapsed = (now - t-start

[Qemu-devel] [PATCH v8 10/24] hw/arm: add FTDMAC020 AHB DMA support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday FTDMAC020 provides eight configurable
channels for the memory-to-memory, memory-to-peripheral,
peripheral-to-peripheral, and peripheral-to-memory transfers.

Each DMA channel supports chain transfer and can be programmed
to one of the 16 handshaking channels in the hardware handshake mode.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   14 ++
 hw/arm/ftdmac020.c|  595 +
 hw/arm/ftdmac020.h|  107 
 4 files changed, 717 insertions(+)
 create mode 100644 hw/arm/ftdmac020.c
 create mode 100644 hw/arm/ftdmac020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index b01da9d..7a6e94a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -43,3 +43,4 @@ obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
 obj-y += ftrtc011.o
+obj-y += ftdmac020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 7d90079..19b0ad3 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -209,6 +209,20 @@ a369soc_device_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
 /* Hour (Edge) */
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
+
+/* ftdmac020 */
+s-hdma[0] = sysbus_create_varargs(ftdmac020,
+   0x9030,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[15], /* TC */
+   s-pic[16], /* ERR */
+   NULL);
+s-hdma[1] = sysbus_create_varargs(ftdmac020,
+   0x9610,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[17], /* TC */
+   s-pic[18], /* ERR */
+   NULL);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftdmac020.c b/hw/arm/ftdmac020.c
new file mode 100644
index 000..d78ba3c
--- /dev/null
+++ b/hw/arm/ftdmac020.c
@@ -0,0 +1,595 @@
+/*
+ * QEMU model of the FTDMAC020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTDMAC020 decreasing address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include ftdmac020.h
+
+#define TYPE_FTDMAC020ftdmac020
+
+enum ftdmac020_irqpin {
+IRQ_ALL = 0,
+IRQ_TC,
+IRQ_ERR,
+};
+
+typedef struct Ftdmac020State Ftdmac020State;
+
+/**
+ * struct Ftdmac020LLD - hardware link list descriptor.
+ * @src: source physical address
+ * @dst: destination physical addr
+ * @next: phsical address to the next link list descriptor
+ * @ctrl: control field
+ * @size: transfer size
+ *
+ * should be word aligned
+ */
+typedef struct Ftdmac020LLD {
+uint32_t src;
+uint32_t dst;
+uint32_t next;
+uint32_t ctrl;
+uint32_t size;
+} Ftdmac020LLD;
+
+typedef struct Ftdmac020Chan {
+Ftdmac020State *chip;
+
+int id;
+int burst;
+int llp_cnt;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register cache */
+uint32_t ccr;
+uint32_t cfg;
+uint32_t src;
+uint32_t dst;
+uint32_t llp;
+uint32_t len;
+} Ftdmac020Chan;
+
+typedef struct Ftdmac020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq[3];
+
+Ftdmac020Chan chan[8];
+qemu_irq  ack[16];
+uint32_t  req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+
+/* HW register cache */
+uint32_t tcisr;
+uint32_t eaisr;
+uint32_t tcsr;
+uint32_t easr;
+uint32_t cesr;
+uint32_t cbsr;
+uint32_t csr;
+uint32_t sync;
+} Ftdmac020State;
+
+#define FTDMAC020(obj) \
+OBJECT_CHECK(Ftdmac020State, obj, TYPE_FTDMAC020)
+
+static void ftdmac020_update_irq(Ftdmac020State *s)
+{
+uint32_t tc, err;
+
+/* 1. Checking TC interrupts */
+tc = s-tcisr  0xff;
+qemu_set_irq(s-irq[IRQ_TC], tc ? 1 : 0);
+
+/* 2. Checking Error/Abort interrupts */
+err = s-eaisr  0x00ff00ff;
+qemu_set_irq(s-irq[IRQ_ERR], err ? 1 : 0);
+
+/* 3. Checking interrupt summary (TC | Error | Abort) */
+qemu_set_irq(s-irq[IRQ_ALL], (tc || err) ? 1 : 0);
+}
+
+static void ftdmac020_chan_ccr_decode(Ftdmac020Chan *c)
+{
+uint32_t tmp;
+
+/* 1. decode

[Qemu-devel] [PATCH v8 11/24] hw/arm: add FTAPBBRG020 APB DMA support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTAPBBRG020 supports the DMA functions for the AHB-to-AHB,
AHB-to-APB, APB-to-AHB, and APB-to-APB transactions.

The DMA engine can support up to 4 DMA channels (A, B, C, and D)
and 15 handshaking channels. A DMA channel granted by the arbiter
block is the only channel starts transfers. Each DMA channel can
be programmed to one of the 15 handshaking channels in the hardware
handshake mode to act as the source device or act as the destination
device.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |9 +
 hw/arm/ftapbbrg020.c  |  468 +
 hw/arm/ftapbbrg020.h  |   44 +
 4 files changed, 522 insertions(+)
 create mode 100644 hw/arm/ftapbbrg020.c
 create mode 100644 hw/arm/ftapbbrg020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 7a6e94a..cc5e343 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -44,3 +44,4 @@ obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
 obj-y += ftrtc011.o
 obj-y += ftdmac020.o
+obj-y += ftapbbrg020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 19b0ad3..bb80537 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -223,6 +223,15 @@ a369soc_device_init(FaradaySoCState *s)
s-pic[17], /* TC */
s-pic[18], /* ERR */
NULL);
+
+/* ftapbbrg020 */
+ds = sysbus_create_simple(ftapbbrg020, 0x90f0, s-pic[14]);
+s-pdma[0] = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftapbbrg020.c b/hw/arm/ftapbbrg020.c
new file mode 100644
index 000..73c00ae
--- /dev/null
+++ b/hw/arm/ftapbbrg020.c
@@ -0,0 +1,468 @@
+/*
+ * QEMU model of the FTAPBBRG020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTAPBBRG020 DMA decreasing address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include faraday.h
+#include ftapbbrg020.h
+
+#define TYPE_FTAPBBRG020ftapbbrg020
+
+typedef struct Ftapbbrg020State Ftapbbrg020State;
+
+typedef struct Ftapbbrg020Chan {
+Ftapbbrg020State *chip;
+
+int id;
+int burst;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register caches */
+uint32_t src;
+uint32_t dst;
+uint32_t len;
+uint32_t cmd;
+} Ftapbbrg020Chan;
+
+typedef struct Ftapbbrg020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+FaradaySoCState *soc;
+Ftapbbrg020Chan chan[4];
+qemu_irq ack[16];
+uint32_t req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+} Ftapbbrg020State;
+
+#define FTAPBBRG020(obj) \
+OBJECT_CHECK(Ftapbbrg020State, obj, TYPE_FTAPBBRG020)
+
+static uint32_t ftapbbrg020_get_isr(Ftapbbrg020State *s)
+{
+int i;
+uint32_t isr = 0;
+Ftapbbrg020Chan *chan;
+
+for (i = 0; i  4; ++i) {
+chan = s-chan + i;
+isr |= (chan-cmd  CMD_INTR_STATUS);
+}
+
+return isr;
+}
+
+static void ftapbbrg020_update_irq(Ftapbbrg020State *s)
+{
+uint32_t isr = ftapbbrg020_get_isr(s);
+
+qemu_set_irq(s-irq, isr ? 1 : 0);
+}
+
+static void ftapbbrg020_chan_cmd_decode(Ftapbbrg020Chan *c)
+{
+uint32_t tmp;
+
+/* 1. decode burst size */
+c-burst = (c-cmd  CMD_BURST4) ? 4 : 1;
+
+/* 2. decode source/destination width */
+tmp = extract32(c-cmd, 20, 2);
+if (tmp  2) {
+tmp = 2;
+}
+c-src_bw = c-dst_bw = 8  (2 - tmp);
+
+/* 3. decode source address stride */
+switch (extract32(c-cmd, 8, 2)) {
+case 0:
+c-src_stride = 0;
+break;
+case 1:
+c-src_stride = c-src_bw  3;
+break;
+case 2:
+c-src_stride = 2 * (c-src_bw  3);
+break;
+case 3:
+c-src_stride = 4 * (c-src_bw  3);
+break;
+}
+
+/* 4. decode destination address stride */
+switch (extract32(c-cmd, 12, 2)) {
+case 0:
+c-dst_stride = 0;
+break;
+case 1:
+c-dst_stride = c-dst_bw  3;
+break;
+case 2:
+c-dst_stride = 2 * (c-dst_bw  3);
+break;
+case 3:
+c-dst_stride = 4 * (c-dst_bw

[Qemu-devel] [PATCH v8 14/24] hw: Add AudioCodecClass for wm87xx audio class abstration.

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/Makefile.objs   |1 +
 hw/arm/spitz.c |9 +++--
 hw/arm/z2.c|9 +++--
 hw/audio_codec.c   |   81 +++
 hw/audio_codec.h   |   56 +++
 hw/i2c.h   |9 -
 hw/marvell_88w8618_audio.c |   23 +++
 hw/wm8750.c|   91 ++--
 8 files changed, 211 insertions(+), 68 deletions(-)
 create mode 100644 hw/audio_codec.c
 create mode 100644 hw/audio_codec.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index eb7eb31..aafcac5 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -167,6 +167,7 @@ common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-y += audio_codec.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index f5832be..618968b 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -24,6 +24,7 @@
 #include ui/console.h
 #include block/block.h
 #include audio/audio.h
+#include hw/audio_codec.h
 #include hw/boards.h
 #include sysemu/blockdev.h
 #include hw/sysbus.h
@@ -739,9 +740,11 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
 qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
 /* .. and to the sound interface.  */
 cpu-i2s-opaque = wm;
-cpu-i2s-codec_out = wm8750_dac_dat;
-cpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, cpu-i2s-data_req, cpu-i2s);
+cpu-i2s-codec_out = audio_codec_dac_dat;
+cpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ cpu-i2s-data_req,
+ cpu-i2s);
 }
 
 static void spitz_akita_i2c_setup(PXA2xxState *cpu)
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index cbb6d80..bc11309 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -23,6 +23,7 @@
 #include sysemu/blockdev.h
 #include ui/console.h
 #include audio/audio.h
+#include hw/audio_codec.h
 #include exec/address-spaces.h
 
 #ifdef DEBUG_Z2
@@ -353,9 +354,11 @@ static void z2_init(QEMUMachineInitArgs *args)
 i2c_create_slave(bus, aer915, 0x55);
 wm = i2c_create_slave(bus, wm8750, 0x1b);
 mpu-i2s-opaque = wm;
-mpu-i2s-codec_out = wm8750_dac_dat;
-mpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, mpu-i2s-data_req, mpu-i2s);
+mpu-i2s-codec_out = audio_codec_dac_dat;
+mpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ mpu-i2s-data_req,
+ mpu-i2s);
 
 qdev_connect_gpio_out(mpu-gpio, Z2_GPIO_LCD_CS,
 qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
diff --git a/hw/audio_codec.c b/hw/audio_codec.c
new file mode 100644
index 000..c62e51f
--- /dev/null
+++ b/hw/audio_codec.c
@@ -0,0 +1,81 @@
+/*
+ * Audio Codec Class
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include qdev.h
+#include i2c.h
+#include audio_codec.h
+
+void audio_codec_data_req_set(DeviceState *dev,
+  void (*data_req)(void *, int, int),
+  void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(dev);
+if (k-data_req_set) {
+k-data_req_set(dev, data_req, opaque);
+}
+}
+
+void audio_codec_dac_dat(void *opaque, uint32_t sample)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_dat) {
+k-dac_dat(opaque, sample);
+}
+}
+
+uint32_t audio_codec_adc_dat(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+uint32_t ret = 0;
+if (k-adc_dat) {
+ret = k-adc_dat(opaque);
+}
+return ret;
+}
+
+void *audio_codec_dac_buffer(void *opaque, int samples)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+void *ret = NULL;
+if (k-dac_buffer) {
+ret = k-dac_buffer(opaque, samples);
+}
+return ret;
+}
+
+void audio_codec_dac_commit(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_commit) {
+k-dac_commit(opaque);
+}
+}
+
+void audio_codec_set_bclk_in(void *opaque, int new_hz)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-set_bclk_in) {
+k-set_bclk_in(opaque, new_hz);
+}
+}
+
+static const TypeInfo audio_codec_info = {
+.name  = TYPE_AUDIO_CODEC,
+.parent= TYPE_I2C_SLAVE,
+.instance_size = sizeof(AudioCodecState),
+.abstract  = true,
+.class_size= sizeof(AudioCodecClass),
+};
+
+static void audio_codec_register_types(void)
+{
+type_register_static(audio_codec_info

[Qemu-devel] [PATCH v8 13/24] hw/arm: add FTI2C010 I2C controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTI2C010 is a simple I2C master controller.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |6 ++
 hw/arm/fti2c010.c |  212 +
 hw/arm/fti2c010.h |   71 +++
 4 files changed, 290 insertions(+)
 create mode 100644 hw/arm/fti2c010.c
 create mode 100644 hw/arm/fti2c010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2622f3f..63ba519 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -46,3 +46,4 @@ obj-y += ftrtc011.o
 obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
+obj-y += fti2c010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 0088915..89610d9 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -241,6 +241,12 @@ a369soc_device_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-hdma[0], 15);
 qdev_connect_gpio_out(s-hdma[0], 15, ack);
 qdev_connect_gpio_out(ds, 0, req);
+
+/* fti2c010 */
+ds = sysbus_create_simple(fti2c010, 0x9290, s-pic[51]);
+s-i2c[0] = ds;
+ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
+s-i2c[1] = ds;
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/fti2c010.c b/hw/arm/fti2c010.c
new file mode 100644
index 000..95f6a9d
--- /dev/null
+++ b/hw/arm/fti2c010.c
@@ -0,0 +1,212 @@
+/*
+ * QEMU model of the FTI2C010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/i2c.h
+#include sysemu/sysemu.h
+
+#include fti2c010.h
+
+#define I2C_RD  1
+#define I2C_WR  0
+
+#define TYPE_FTI2C010   fti2c010
+
+typedef struct Fti2c010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+i2c_bus *bus;
+
+uint8_t  recv;/* I2C RD = 1; I2C WR = 0 */
+uint8_t  addr;/* 7-bits device address */
+
+/* HW register cache */
+uint32_t cr;
+uint32_t sr;
+uint32_t cdr;
+uint32_t dr;
+uint32_t tgsr;
+} Fti2c010State;
+
+#define FTI2C010(obj) \
+OBJECT_CHECK(Fti2c010State, obj, TYPE_FTI2C010)
+
+static void
+fti2c010_update_irq(Fti2c010State *s)
+{
+uint32_t sr = extract32(s-sr, 4, 8);
+uint32_t cr = extract32(s-cr, 8, 8);
+qemu_set_irq(s-irq, (sr  cr) ? 1 : 0);
+}
+
+static uint64_t
+fti2c010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_CR:
+return s-cr;
+case REG_SR:
+ret = s-sr | (i2c_bus_busy(s-bus) ? SR_BB : 0);
+s-sr = 0xf00f;/* clear RC status bits */
+fti2c010_update_irq(s);
+break;
+case REG_CDR:
+return s-cdr;
+case REG_DR:
+return s-dr;
+case REG_TGSR:
+return s-tgsr;
+case REG_BMR:
+return 0x0003;  /* Slave mode: SCL=1, SDA=1 */
+case REG_REVR:
+return 0x00011000;  /* REV. 1.10.0 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fti2c010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fti2c010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+
+switch (addr) {
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_I2CRST) {
+s-dr = 0;
+s-sr = 0;
+} else if ((s-cr  CR_MASTER_EN)  (s-cr  CR_TBEN)) {
+s-sr = ~SR_ACK;
+if (s-cr  CR_START) {
+s-recv = (s-dr  I2C_RD) ? 1 : 0;
+s-addr = extract32(s-dr, 1, 7);
+if (!i2c_start_transfer(s-bus, s-addr, s-recv)) {
+s-sr |= SR_DT | SR_ACK;
+} else {
+s-sr = ~SR_DT;
+}
+} else {
+if (s-recv) {
+s-dr = i2c_recv(s-bus);
+s-sr |= SR_DR;
+} else {
+i2c_send(s-bus, (uint8_t)s-dr);
+s-sr |= SR_DT;
+}
+if (s-cr  CR_NACK) {
+i2c_nack(s-bus);
+}
+s-sr |= SR_ACK;
+if (s-cr  CR_STOP) {
+i2c_end_transfer(s-bus);
+}
+}
+}
+s-cr = ~(CR_TBEN | CR_I2CRST);
+fti2c010_update_irq(s);
+break;
+case REG_CDR:
+s-cdr = (uint32_t)val  0x3;
+break;
+case REG_DR:
+s-dr  = (uint32_t)val  0xff;
+break;
+case REG_TGSR:
+s-tgsr = (uint32_t)val  0x1fff;
+break;
+/* slave mode is useless to QEMU, ignore it. */
+case REG_SAR:
+default:
+qemu_log_mask

[Qemu-devel] [PATCH v8 12/24] hw/arm: add FTNANDC021 nand flash controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTNANDC021 is an integrated NAND flash controller which
re-pack the NAND flash command set with a shorter built-in opcode.
It also provides a register base interface for user to easily
access the underlying NAND flash chips, and also supports HW ECC.

However the optional hardware ECC function is not implemented.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |   14 ++
 hw/arm/faraday_a369_soc.c |9 +
 hw/arm/ftnandc021.c   |  516 +
 hw/arm/ftnandc021.h   |   84 
 5 files changed, 624 insertions(+)
 create mode 100644 hw/arm/ftnandc021.c
 create mode 100644 hw/arm/ftnandc021.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index cc5e343..2622f3f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -45,3 +45,4 @@ obj-y += ftwdt010.o
 obj-y += ftrtc011.o
 obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
+obj-y += ftnandc021.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 3a89a04..c85de25 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -25,6 +25,8 @@ a369_board_init(QEMUMachineInitArgs *args)
 {
 DeviceState *ds;
 FaradaySoCState *s;
+DriveInfo *dinfo;
+Error *local_errp = NULL;
 
 if (!args-cpu_model) {
 args-cpu_model = fa626te;
@@ -46,6 +48,18 @@ a369_board_init(QEMUMachineInitArgs *args)
 
 s = FARADAY_SOC(ds);
 
+/* Attach the nand flash to ftnandc021 */
+dinfo = drive_get_next(IF_MTD);
+ds = nand_init(dinfo ? dinfo-bdrv : NULL, NAND_MFR_SAMSUNG, 0xda);
+object_property_set_link(OBJECT(s-nandc[0]),
+ OBJECT(ds),
+ flash,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set flash link for FTNANDC021\n);
+abort();
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index bb80537..0088915 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -84,6 +84,7 @@ a369soc_device_init(FaradaySoCState *s)
 DriveInfo *dinfo;
 DeviceState *ds;
 qemu_irq *cpu_pic;
+qemu_irq ack, req;
 int i;
 
 s-as = get_system_memory();
@@ -232,6 +233,14 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
 abort();
 }
+
+/* ftnandc021 */
+ds = sysbus_create_simple(ftnandc021, 0x9020, s-pic[30]);
+s-nandc[0] = ds;
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 15);
+qdev_connect_gpio_out(s-hdma[0], 15, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftnandc021.c b/hw/arm/ftnandc021.c
new file mode 100644
index 000..8b4c84c
--- /dev/null
+++ b/hw/arm/ftnandc021.c
@@ -0,0 +1,516 @@
+/*
+ * QEMU model of the FTNANDC021 NAND Flash Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/devices.h
+#include hw/flash.h
+#include sysemu/blockdev.h
+
+#include ftnandc021.h
+
+#define TYPE_FTNANDC021 ftnandc021
+
+typedef struct Ftnandc021State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+DeviceState *flash;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint8_t  manf_id, chip_id;
+
+int  cmd;
+int  len;/* buffer length for page read/write */
+int  pi;/* page index */
+int  bw;/* bus width (8-bits, 16-bits) */
+
+uint64_t size;/* flash size (maximum access range) */
+uint32_t pgsz;/* page size (Bytes) */
+uint32_t bksz;/* block size (Bytes) */
+uint32_t alen;/* address length (cycle) */
+
+uint32_t id[2];
+uint8_t  oob[8];/* 5 bytes for 512/2048 page; 7 bytes for 4096 page */
+
+/* HW register caches */
+uint32_t sr;
+uint32_t fcr;
+uint32_t mcr;
+uint32_t ier;
+uint32_t bcr;
+} Ftnandc021State;
+
+#define FTNANDC021(obj) \
+OBJECT_CHECK(Ftnandc021State, obj, TYPE_FTNANDC021)
+
+static void ftnandc021_update_irq(Ftnandc021State *s)
+{
+if (s-ier  IER_ENA) {
+if ((s-ier  0x0f)  (s-sr  2)) {
+qemu_set_irq(s-irq, 1);
+} else {
+qemu_set_irq(s-irq, 0);
+}
+}
+}
+
+static void ftnandc021_set_idle(Ftnandc021State *s)
+{
+/* CLE=0, ALE=0, CS=1 */
+nand_setpins(s-flash, 0, 0, 1, 1, 0);
+
+/* Set command compelete */
+s-sr |= SR_CMD;
+
+/* Update IRQ signal */
+ftnandc021_update_irq(s);
+}
+
+static void ftnandc021_set_cmd(Ftnandc021State *s, uint8_t cmd)
+{
+/* CLE=1, ALE=0, CS=0 */
+nand_setpins(s-flash, 1, 0, 0, 1, 0

[Qemu-devel] [PATCH v8 16/24] hw/arm: add FTSSP010 multi-function controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSSP010 is a multi-function synchronous serial port interface
controller which supports SSP, SPI, I2S, AC97 and SPDIF.

Only I2S and SPI protocol have been implemented in this patch.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369.c |   31 +++
 hw/arm/faraday_a369_soc.c |   17 ++
 hw/arm/ftssp010.c |  494 +
 hw/arm/ftssp010.h |   98 +
 6 files changed, 644 insertions(+)
 create mode 100644 hw/arm/ftssp010.c
 create mode 100644 hw/arm/ftssp010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 63ba519..9cb135a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -47,3 +47,4 @@ obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
 obj-y += fti2c010.o
+obj-y += ftssp010.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 4a9c2ae..6da9f42 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -49,4 +49,7 @@ typedef struct FaradaySoCState {
 #define FARADAY_SOC(obj) \
 OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
 
+/* ftssp010.c */
+void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
+
 #endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index c85de25..139a244 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -11,6 +11,7 @@
 #include hw/arm-misc.h
 #include hw/devices.h
 #include hw/i2c.h
+#include hw/audio_codec.h
 #include hw/boards.h
 #include hw/ssi.h
 #include net/net.h
@@ -23,6 +24,7 @@
 static void
 a369_board_init(QEMUMachineInitArgs *args)
 {
+int i, nr_flash;
 DeviceState *ds;
 FaradaySoCState *s;
 DriveInfo *dinfo;
@@ -60,6 +62,35 @@ a369_board_init(QEMUMachineInitArgs *args)
 abort();
 }
 
+/* Attach the spi flash to ftssp010.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi[0]), i + 1, cs_line);
+}
+
+/* Attach the wm8731 to fti2c010.0  ftssp010.0 */
+for (i = 0; i  1; ++i) {
+i2c_bus *i2c = (i2c_bus *)qdev_get_child_bus(s-i2c[0], i2c);
+ds = i2c_create_slave(i2c, wm8731, 0x1B);
+object_property_set_link(OBJECT(s-i2s[0]),
+ OBJECT(ds),
+ codec,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set codec link for FTSSP010\n);
+abort();
+}
+audio_codec_data_req_set(ds,
+ ftssp010_i2s_data_req,
+ s-i2s[0]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 89610d9..839b782 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -247,6 +247,23 @@ a369soc_device_init(FaradaySoCState *s)
 s-i2c[0] = ds;
 ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
 s-i2c[1] = ds;
+
+/* ftssp010 */
+ds = sysbus_create_simple(ftssp010, 0x9270, s-pic[49]);
+s-spi[0] = ds;
+s-i2s[0] = ds;
+
+/* ftssp010 - DMA (Tx) */
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-pdma[0], 7);
+qdev_connect_gpio_out(s-pdma[0], 7, ack);
+qdev_connect_gpio_out(ds, 0, req);
+
+/* ftssp010 - DMA (Rx) */
+ack = qdev_get_gpio_in(ds, 1);
+req = qdev_get_gpio_in(s-pdma[0], 8);
+qdev_connect_gpio_out(s-pdma[0], 8, ack);
+qdev_connect_gpio_out(ds, 1, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftssp010.c b/hw/arm/ftssp010.c
new file mode 100644
index 000..f01a385
--- /dev/null
+++ b/hw/arm/ftssp010.c
@@ -0,0 +1,494 @@
+/*
+ * QEMU model of the FTSSP010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include sysemu/sysemu.h
+#include qemu/fifo8.h
+#include hw/i2c.h
+#include hw/audio_codec.h
+#include hw/ssi.h
+
+#include faraday.h
+#include ftssp010.h
+
+#define CFG_FIFO_DEPTH  16
+
+#define TYPE_FTSSP010   ftssp010
+
+typedef struct Ftssp010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+SSIBus *spi;
+AudioCodecState *codec;
+
+uint8_t num_cs;
+qemu_irq *cs_lines;
+
+Fifo8 rx_fifo;
+Fifo8 tx_fifo;
+
+uint8_t tx_thres;
+uint8_t rx_thres;
+
+int busy;
+uint8_t bw;
+
+/* DMA hardware handshake */
+qemu_irq req[2];/* 0 - Tx, 1 - Rx */
+
+/* HW register caches */
+
+uint32_t cr0

[Qemu-devel] [PATCH v8 17/24] qemu/bitops.h: add the bit ordering reversal functions

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 include/qemu/bitops.h |   59 -
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index affcc96..64cbb04 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2010 Corentin Chary corentin.ch...@gmail.com
  *
- * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
+ * Mostly inspired by (stolen from) linux/bitmap.h, linux/bitops.h
+ * and linux/bitrev.h
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
@@ -273,4 +274,60 @@ static inline uint64_t deposit64(uint64_t value, int 
start, int length,
 return (value  ~mask) | ((fieldval  start)  mask);
 }
 
+/**
+ * bitrev8:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 8 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint8_t bitrev8(uint8_t value)
+{
+value = (value  0xF0)  4 | (value  0x0F)  4;
+value = (value  0xCC)  2 | (value  0x33)  2;
+value = (value  0xAA)  1 | (value  0x55)  1;
+return value;
+}
+
+/**
+ * bitrev16:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 16 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint16_t bitrev16(uint16_t value)
+{
+return (bitrev8(value  0xff)  8) | bitrev8(value  8);
+}
+
+/**
+ * bitrev32:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 32 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint32_t bitrev32(uint32_t value)
+{
+return (bitrev16(value  0x)  16) | bitrev16(value  16);
+}
+
+/**
+ * bitrev64:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 64 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint64_t bitrev64(uint64_t value)
+{
+return ((uint64_t)bitrev32(value  0xULL)  32)
+| (uint64_t)bitrev32(value  32);
+}
+
 #endif
-- 
1.7.9.5




[Qemu-devel] [PATCH v8 19/24] hw/arm: add FTLCDC200 LCD controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTLCDC200 Color LCD controller performs translation of
pixel-coded data into the required formats and timings to
drive a variety of single/dual mono and color LCDs.

Depending on the LCD type and mode, the unpacked data can represent:
   1. an actual true display gray or color value
   2. an address to a 256 x 16 bit wide palette RAM gray or color value.

The FTLCDC200 generates 4 individual interrupts for:
   1. DMA FIFO underflow
   2. base address update
   3. vertical status
   4. bus error.

There is also a single combined interrupt that is raised when any of
the individual interrupts become active.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|1 +
 hw/arm/faraday_a369_soc.c   |   10 +
 hw/arm/ftlcdc200.c  |  510 +++
 hw/arm/ftlcdc200.h  |  112 ++
 hw/arm/ftlcdc200_template.h |  439 +
 5 files changed, 1072 insertions(+)
 create mode 100644 hw/arm/ftlcdc200.c
 create mode 100644 hw/arm/ftlcdc200.h
 create mode 100644 hw/arm/ftlcdc200_template.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index a6a9a0f..6f3bf2d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -49,3 +49,4 @@ obj-y += ftnandc021.o
 obj-y += fti2c010.o
 obj-y += ftssp010.o
 obj-y += ftgmac100.o
+obj-y += ftlcdc200.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 9872d5b..a6a65da 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -269,6 +269,16 @@ a369soc_device_init(FaradaySoCState *s)
 if (nb_nics  0) {
 ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
 }
+
+/* ftlcdc200 */
+sysbus_create_varargs(ftlcdc200,
+  0x94a0,
+  s-pic[0],  /* ALL (NC in A369) */
+  s-pic[25], /* VSTATUS */
+  s-pic[24], /* Base Address Update */
+  s-pic[23], /* FIFO Under-Run */
+  s-pic[22], /* AHB Bus Error */
+  NULL);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftlcdc200.c b/hw/arm/ftlcdc200.c
new file mode 100644
index 000..330068a
--- /dev/null
+++ b/hw/arm/ftlcdc200.c
@@ -0,0 +1,510 @@
+/*
+ * Faraday FTLCDC200 Color LCD Controller
+ *
+ * base is pl110.c
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under the GNU LGPL
+ */
+
+#include hw/sysbus.h
+#include hw/framebuffer.h
+#include ui/console.h
+#include ui/pixel_ops.h
+
+#include ftlcdc200.h
+
+enum ftlcdc200_irqpin {
+IRQ_ALL = 0,
+IRQ_VSTATUS,
+IRQ_BASEUPT,
+IRQ_FIFOUR,
+IRQ_BUSERR,
+};
+
+enum ftlcdc200_bppmode {
+BPP_1 = 0,
+BPP_2,
+BPP_4,
+BPP_8,
+BPP_16,
+BPP_32,
+BPP_16_565,
+BPP_12,
+};
+
+#define TYPE_FTLCDC200  ftlcdc200
+
+typedef struct Ftlcdc200State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+DisplayState *ds;
+qemu_irq irq[5];
+int cols;
+int rows;
+enum ftlcdc200_bppmode bpp;
+int invalidate;
+uint32_t palette[256];
+uint32_t raw_palette[128];
+
+/* hw register caches */
+uint32_t fer;   /* function enable register */
+uint32_t ppr;   /* panel pixel register */
+uint32_t ier;   /* interrupt enable register */
+uint32_t isr;   /* interrupt status register */
+uint32_t sppr;  /* serail panel pixel register */
+
+uint32_t fb[4]; /* frame buffer base address register */
+uint32_t ht;/* horizontal timing control register */
+uint32_t vt0;   /* vertital timing control register 0 */
+uint32_t vt1;   /* vertital timing control register 1 */
+uint32_t pol;   /* polarity */
+
+} Ftlcdc200State;
+
+#define FTLCDC200(obj) \
+OBJECT_CHECK(Ftlcdc200State, obj, TYPE_FTLCDC200)
+
+static const VMStateDescription vmstate_ftlcdc200 = {
+.name = TYPE_FTLCDC200,
+.version_id = 2,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_INT32(cols, Ftlcdc200State),
+VMSTATE_INT32(rows, Ftlcdc200State),
+VMSTATE_UINT32(bpp, Ftlcdc200State),
+VMSTATE_INT32(invalidate, Ftlcdc200State),
+VMSTATE_UINT32_ARRAY(palette, Ftlcdc200State, 256),
+VMSTATE_UINT32_ARRAY(raw_palette, Ftlcdc200State, 128),
+VMSTATE_UINT32(fer, Ftlcdc200State),
+VMSTATE_UINT32(ppr, Ftlcdc200State),
+VMSTATE_UINT32(ier, Ftlcdc200State),
+VMSTATE_UINT32(isr, Ftlcdc200State),
+VMSTATE_UINT32(sppr, Ftlcdc200State),
+VMSTATE_UINT32_ARRAY(fb, Ftlcdc200State, 4),
+VMSTATE_UINT32(ht, Ftlcdc200State),
+VMSTATE_UINT32(vt0, Ftlcdc200State),
+VMSTATE_UINT32(vt1, Ftlcdc200State),
+VMSTATE_UINT32(pol, Ftlcdc200State),
+VMSTATE_END_OF_LIST()
+}
+};
+
+#define BITS 8

[Qemu-devel] [PATCH v8 20/24] hw/arm: add FTTSC010 touchscreen controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTSC010 provides two operation modes to sample
the analog input voltage.

  1. The manual operation mode needs to program
 and control the panel drivers by software
 step-by-step for the x-y position measurement.

  2. The auto-scan mode provides a periodic sampling
 method to convert the analog input.

This patch only implements the auto-scan mode.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |3 +
 hw/arm/fttsc010.c |  260 +
 hw/arm/fttsc010.h |   39 +++
 4 files changed, 303 insertions(+)
 create mode 100644 hw/arm/fttsc010.c
 create mode 100644 hw/arm/fttsc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6f3bf2d..9fdefc8 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -50,3 +50,4 @@ obj-y += fti2c010.o
 obj-y += ftssp010.o
 obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
+obj-y += fttsc010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index a6a65da..2177616 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -279,6 +279,9 @@ a369soc_device_init(FaradaySoCState *s)
   s-pic[23], /* FIFO Under-Run */
   s-pic[22], /* AHB Bus Error */
   NULL);
+
+/* fttsc010 */
+sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/fttsc010.c b/hw/arm/fttsc010.c
new file mode 100644
index 000..fd12d9c
--- /dev/null
+++ b/hw/arm/fttsc010.c
@@ -0,0 +1,260 @@
+/*
+ * Faraday FTTSC010 emulator.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include ui/console.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include fttsc010.h
+
+#define X_AXIS_DMAX 3470
+#define X_AXIS_MIN  290
+#define Y_AXIS_DMAX 3450
+#define Y_AXIS_MIN  200
+
+#define ADS_XPOS(x, y)  \
+(X_AXIS_MIN + ((X_AXIS_DMAX * (x))  15))
+#define ADS_YPOS(x, y)  \
+(Y_AXIS_MIN + ((Y_AXIS_DMAX * (y))  15))
+#define ADS_Z1POS(x, y) \
+(8)
+#define ADS_Z2POS(x, y) \
+((1600 + ADS_XPOS(x, y)) * ADS_Z1POS(x, y) / ADS_XPOS(x, y))
+
+#define TYPE_FTTSC010   fttsc010
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Fttsc010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint64_t interval;
+QEMUTimer *qtimer;
+
+int x, y;
+int z1, z2;
+uint32_t freq;
+
+/* HW registers */
+uint32_t regs[CFG_REGSIZE];
+} Fttsc010State;
+
+#define FTTSC010(obj) \
+OBJECT_CHECK(Fttsc010State, obj, TYPE_FTTSC010)
+
+#define TSC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static void fttsc010_update_irq(Fttsc010State *s)
+{
+qemu_set_irq(s-irq, !!(TSC_REG32(s, REG_IMR)  TSC_REG32(s, REG_ISR)));
+}
+
+static uint64_t
+fttsc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t ret = 0;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR ... REG_DCR:
+ret = s-regs[addr / 4];
+break;
+case REG_XYR:
+ret = deposit32(ret,  0, 12, s-x);
+ret = deposit32(ret, 16, 12, s-y);
+break;
+case REG_ZR:
+ret = deposit32(ret,  0, 12, s-z1);
+ret = deposit32(ret, 16, 12, s-z2);
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fttsc010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fttsc010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+uint32_t dly, sdiv, mdiv;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR:
+TSC_REG32(s, REG_CR) = (uint32_t)val;
+if (TSC_REG32(s, REG_CR)  (CR_AS | CR_RD1)) {
+/* ADC conversion delay with frame number */
+dly = extract32(TSC_REG32(s, REG_DCR), 0, 16);
+/* ADC sample clock divider */
+sdiv = extract32(TSC_REG32(s, REG_CSR), 8, 8);
+/* ADC main clock divider */
+mdiv = extract32(TSC_REG32(s, REG_CSR), 0, 8);
+/* Calculate sample rate/timer interval */
+s-interval = s-freq / ((mdiv + 1) * (sdiv + 1) * (dly + 1) * 64);
+s-interval = MAX(1ULL, s-interval);
+qemu_mod_timer(s-qtimer,
+s-interval + qemu_get_clock_ms(vm_clock));
+} else {
+qemu_del_timer(s-qtimer);
+}
+break;
+case REG_ISR:
+TSC_REG32(s, REG_ISR) = ~((uint32_t)val);
+fttsc010_update_irq(s);
+break;
+case REG_IMR:
+TSC_REG32(s, REG_IMR) = (uint32_t)val;
+fttsc010_update_irq(s);
+break

[Qemu-devel] [PATCH v8 21/24] hw/arm: add FTSDC010 MMC/SD controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSDC010 is a simple MMC/SD host controller and
many of its registers are similar to Arm PrimeCell PL181.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |7 +
 hw/arm/ftsdc010.c |  354 +
 hw/arm/ftsdc010.h |   90 
 4 files changed, 452 insertions(+)
 create mode 100644 hw/arm/ftsdc010.c
 create mode 100644 hw/arm/ftsdc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9fdefc8..0920270 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -51,3 +51,4 @@ obj-y += ftssp010.o
 obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
 obj-y += fttsc010.o
+obj-y += ftsdc010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 2177616..9b4eb7a 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -282,6 +282,13 @@ a369soc_device_init(FaradaySoCState *s)
 
 /* fttsc010 */
 sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
+
+/* ftsdc010 */
+ds = sysbus_create_simple(ftsdc010, 0x9060, s-pic[39]);
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 13);
+qdev_connect_gpio_out(s-hdma[0], 13, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftsdc010.c b/hw/arm/ftsdc010.c
new file mode 100644
index 000..e60e384
--- /dev/null
+++ b/hw/arm/ftsdc010.c
@@ -0,0 +1,354 @@
+/*
+ * QEMU model of the FTSDC010 MMC/SD Host Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/sd.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include ftsdc010.h
+
+#define TYPE_FTSDC010   ftsdc010
+
+typedef struct Ftsdc010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+SDState *card;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint32_t datacnt;
+
+/* HW register cache */
+uint32_t cmd;
+uint32_t arg;
+uint32_t rsp[4];
+uint32_t rspcmd;
+uint32_t dcr;
+uint32_t dtr;
+uint32_t dlr;
+uint32_t status;
+uint32_t ier;
+uint32_t pwr;
+uint32_t clk;
+} Ftsdc010State;
+
+#define FTSDC010(obj) \
+OBJECT_CHECK(Ftsdc010State, obj, TYPE_FTSDC010)
+
+static void ftsdc010_update_irq(Ftsdc010State *s)
+{
+qemu_set_irq(s-irq, !!(s-ier  s-status));
+}
+
+static void ftsdc010_handle_ack(void *opaque, int line, int level)
+{
+Ftsdc010State *s = FTSDC010(opaque);
+
+if (!(s-dcr  DCR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static void ftsdc010_send_command(Ftsdc010State *s)
+{
+SDRequest request;
+uint8_t response[16];
+int rlen;
+
+request.cmd = s-cmd  CMD_IDX;
+request.arg = s-arg;
+
+rlen = sd_do_command(s-card, request, response);
+if (rlen  0) {
+goto error;
+}
+if (s-cmd  CMD_WAIT_RSP) {
+#define RWORD(n) ((response[n]  24) | (response[n + 1]  16) \
+  | (response[n + 2]  8) | response[n + 3])
+if (rlen == 0 || (rlen == 4  (s-cmd  CMD_LONG_RSP))) {
+goto error;
+}
+if (rlen != 4  rlen != 16) {
+goto error;
+}
+if (rlen == 4) {
+s-rsp[0] = RWORD(0);
+s-rsp[1] = s-rsp[2] = s-rsp[3] = 0;
+} else {
+s-rsp[3] = RWORD(0);
+s-rsp[2] = RWORD(4);
+s-rsp[1] = RWORD(8);
+s-rsp[0] = RWORD(12)  ~1;
+}
+s-rspcmd  = (s-cmd  CMD_IDX);
+s-rspcmd |= (s-cmd  CMD_APP) ? RSP_CMDAPP : 0;
+s-status |= SR_RSP;
+#undef RWORD
+} else {
+s-status |= SR_CMD;
+}
+
+if ((s-dcr  DCR_DMA)  s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+
+return;
+
+error:
+s-status |= SR_RSP_TIMEOUT;
+}
+
+static void ftsdc010_chip_reset(Ftsdc010State *s)
+{
+s-cmd = 0;
+s-arg = 0;
+s-rsp[0] = 0;
+s-rsp[1] = 0;
+s-rsp[2] = 0;
+s-rsp[3] = 0;
+s-rspcmd = 0;
+s-dcr = 0;
+s-dtr = 0;
+s-dlr = 0;
+s-datacnt = 0;
+s-status = ~(SR_CARD_REMOVED | SR_WPROT);
+s-status |= SR_TXRDY | SR_RXRDY;
+s-ier = 0;
+s-pwr = 0;
+s-clk = 0;
+}
+
+static uint64_t ftsdc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftsdc010State *s = FTSDC010(opaque);
+uint32_t i, ret = 0;
+
+switch (addr) {
+case REG_SR:
+return s-status;
+case REG_DR:
+if (!(s-dcr  DCR_WR)  s-datacnt  sd_data_ready(s-card)) {
+for (i = 0; i  4  s-datacnt; i++, s-datacnt--) {
+ret = deposit32(ret, i * 8, 8, sd_read_data(s-card));
+}
+if (!s-datacnt) {
+s

[Qemu-devel] [PATCH v8 18/24] hw/arm: add FTGMAC100 1Gbps ethernet support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTGMAC100 Ethernet controller has a DMA engine which handles
all data transfers between the system memory and on-chip memories.
Its DMA engine supports both 16-bits and 32-bits alignment,
and thus make it possible to support zero-copy transfer at both
Linux and WINCE.

It also has 802.1Q VLAN tagging support for both insertion and removal.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369_soc.c |5 +
 hw/arm/ftgmac100.c|  708 +
 hw/arm/ftgmac100.h|  239 +++
 5 files changed, 956 insertions(+)
 create mode 100644 hw/arm/ftgmac100.c
 create mode 100644 hw/arm/ftgmac100.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9cb135a..a6a9a0f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -48,3 +48,4 @@ obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
 obj-y += fti2c010.o
 obj-y += ftssp010.o
+obj-y += ftgmac100.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 6da9f42..37c6447 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -52,4 +52,7 @@ typedef struct FaradaySoCState {
 /* ftssp010.c */
 void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 
+/* ftgmac100.c */
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 839b782..9872d5b 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -264,6 +264,11 @@ a369soc_device_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-pdma[0], 8);
 qdev_connect_gpio_out(s-pdma[0], 8, ack);
 qdev_connect_gpio_out(ds, 1, req);
+
+/* ftgmac100 */
+if (nb_nics  0) {
+ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftgmac100.c b/hw/arm/ftgmac100.c
new file mode 100644
index 000..d1b05fd
--- /dev/null
+++ b/hw/arm/ftgmac100.c
@@ -0,0 +1,708 @@
+/*
+ * QEMU model of the FTGMAC100 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include faraday.h
+#include ftgmac100.h
+
+#ifndef DEBUG
+#define DEBUG   0
+#endif
+
+#define DPRINTF(fmt, ...) \
+do { \
+if (DEBUG) { \
+fprintf(stderr, fmt , ## __VA_ARGS__); \
+} \
+} while (0)
+
+#define TYPE_FTGMAC100  ftgmac100
+
+#define CFG_MAXFRMLEN   9220/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftgmac100State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t hptx_idx;
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftgmac100State;
+
+#define FTGMAC100(obj) \
+OBJECT_CHECK(Ftgmac100State, obj, TYPE_FTGMAC100)
+
+#define MAC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static int ftgmac100_mcast_hash(Ftgmac100State *s, const uint8_t *data)
+{
+#define CRCPOLY_BE0x04c11db7
+int i, len;
+uint32_t crc = 0x;
+
+len = (MAC_REG32(s, REG_MACCR)  MACCR_GMODE) ? 5 : 6;
+
+while (len--) {
+uint32_t c = *(data++);
+for (i = 0; i  8; ++i) {
+crc = (crc  1) ^ crc  31) ^ c)  0x01) ? CRCPOLY_BE : 0);
+c = 1;
+}
+}
+crc = ~crc;
+
+/* Reverse CRC32 and return MSB 6 bits only */
+return bitrev8(crc  24)  2;
+}
+
+static void
+ftgmac100_read_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+if (addr  0x0f) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: Tx desc is not 16-byte aligned!\n
+ It's fine in QEMU but the real HW would panic.\n);
+}
+
+dma_memory_read(s-dma, addr, desc, sizeof(*desc));
+
+for (i = 0; i  sizeof(*desc); i += 4) {
+*p = le32_to_cpu(*p);
+}
+
+if (desc-buf  0x01) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: tx buffer is not 16-bit aligned!\n);
+}
+}
+
+static void
+ftgmac100_write_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+for (i = 0; i  sizeof(*desc); i += 4) {
+*p = cpu_to_le32(*p);
+}
+
+dma_memory_write(s-dma, addr, desc, sizeof(*desc));
+}
+
+static void
+ftgmac100_read_rxdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100RXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc

[Qemu-devel] [PATCH v8 02/24] hw/arm: add Faraday a369 SoC platform support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday A369 EVB is a Faraday SoC platform evalution board used for
Faraday IP functional verification based on the well-known ARM AMBA 2.0
architecture.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |3 +
 hw/arm/faraday.h  |   52 ++
 hw/arm/faraday_a369.c |   98 +++
 hw/arm/faraday_a369_kpd.c |  231 +
 hw/arm/faraday_a369_scu.c |  182 +++
 hw/arm/faraday_a369_soc.c |  190 +
 hw/arm/ftkbc010.h |   44 +
 7 files changed, 800 insertions(+)
 create mode 100644 hw/arm/faraday.h
 create mode 100644 hw/arm/faraday_a369.c
 create mode 100644 hw/arm/faraday_a369_kpd.c
 create mode 100644 hw/arm/faraday_a369_scu.c
 create mode 100644 hw/arm/faraday_a369_soc.c
 create mode 100644 hw/arm/ftkbc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f5f7d0e..104e0e7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -34,3 +34,6 @@ obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o
+
+obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
+faraday_a369_kpd.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
new file mode 100644
index 000..4a9c2ae
--- /dev/null
+++ b/hw/arm/faraday.h
@@ -0,0 +1,52 @@
+/*
+ * Faraday SoC platform support.
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Kuo-Jung Su dant...@gmail.com
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+#ifndef HW_ARM_FARADAY_H
+#define HW_ARM_FARADAY_H
+
+#include hw/flash.h
+#include qemu/bitops.h
+
+typedef struct FaradaySoCState {
+SysBusDevice busdev;
+hwaddr   rom_base;
+uint64_t rom_size;
+hwaddr   ram_base;
+uint64_t ram_size;
+char *cpu_model;
+ARMCPU   *cpu;
+qemu_irq pic[64];
+DeviceState  *scu;  /* System Control Unit */
+DeviceState  *ahbc; /* AHB controller */
+DeviceState  *ddrc; /* DDR controller */
+DeviceState  *hdma[2];  /* AHB DMA */
+DeviceState  *pdma[1];  /* APB DMA */
+DeviceState  *spi[2];   /* Generic SPI bus */
+DeviceState  *spi_fl[2];/* Dedicated SPI bus for flash memory */
+DeviceState  *i2c[2];   /* Generic I2C bus */
+DeviceState  *i2s[2];   /* Generic I2S bus */
+DeviceState  *nandc[2]; /* NAND flash controller */
+
+MemoryRegion *as;   /* address space */
+MemoryRegion *ram;  /* external sdram */
+pflash_t *rom;  /* on-chip rom */
+MemoryRegion *sram; /* on-chip static ram */
+
+uint32_t ahb_slave[32];
+uint32_t apb_slave[32];
+bool ahb_remapped;
+bool ddr_inited;
+struct arm_boot_info *bi;
+} FaradaySoCState;
+
+/* SoC common APIs */
+#define TYPE_FARADAY_SOCfaraday.soc
+#define FARADAY_SOC(obj) \
+OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
+
+#endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
new file mode 100644
index 000..3a89a04
--- /dev/null
+++ b/hw/arm/faraday_a369.c
@@ -0,0 +1,98 @@
+/*
+ * Faraday A369 Evalution Board
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/arm-misc.h
+#include hw/devices.h
+#include hw/i2c.h
+#include hw/boards.h
+#include hw/ssi.h
+#include net/net.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+/* Board init.  */
+
+static void
+a369_board_init(QEMUMachineInitArgs *args)
+{
+DeviceState *ds;
+FaradaySoCState *s;
+
+if (!args-cpu_model) {
+args-cpu_model = fa626te;
+}
+
+if (!args-ram_size) {
+args-ram_size = 512  20;
+}
+
+ds = qdev_create(NULL, TYPE_FARADAY_SOC);
+qdev_prop_set_string(ds, cpu_model, args-cpu_model);
+qdev_prop_set_uint64(ds, ram_size, args-ram_size);
+/* Setup QOM path for the SoC object (i.e. /machine/faraday.soc) */
+object_property_add_child(qdev_get_machine(),
+  TYPE_FARADAY_SOC,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+
+s = FARADAY_SOC(ds);
+
+/* System start-up */
+
+if (args-kernel_filename) {
+s-bi = g_new0(struct arm_boot_info, 1);
+
+s-ddr_inited = true;
+s-ahb_remapped = true;
+
+/* Remap AHB slave 4 (ROM)  slave 6 (RAM) */
+/* 1. Remap RAM to base of ROM */
+s-ram_base = s-ahb_slave[4]  0xfff0;
+s-ahb_slave[6] = s-ram_base | (s-ahb_slave[6]  0x000f);
+/* 2. Remap ROM to base of ROM + size of RAM */
+s-rom_base = s-ram_base
++ ((1  extract32(s-ahb_slave[6], 16, 4))  20);
+s-ahb_slave[4] = s-rom_base | (s

[Qemu-devel] [PATCH v8 24/24] hw/arm: add FTSPI020 SPI flash controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSPI020 is an integrated SPI Flash controller
which supports up to 4 flash chips.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |   16 +++
 hw/arm/ftspi020.c |  337 +
 hw/arm/ftspi020.h |   81 
 4 files changed, 435 insertions(+)
 create mode 100644 hw/arm/ftspi020.c
 create mode 100644 hw/arm/ftspi020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index d0ce0e2..996c606 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -54,3 +54,4 @@ obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
 obj-y += fttmr010.o
+obj-y += ftspi020.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index a3edacb..bd88623 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -106,6 +106,22 @@ a369_board_init(QEMUMachineInitArgs *args)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
 
+/* SPI: FTSPI020 */
+ds = sysbus_create_simple(ftspi020, 0xC000, s-pic[4]);
+s-spi_fl[0] = ds;
+
+/* Attach the spi flash to ftspi020.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi_fl[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi_fl[0]), i + 1, cs_line);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftspi020.c b/hw/arm/ftspi020.c
new file mode 100644
index 000..b3c1bc6
--- /dev/null
+++ b/hw/arm/ftspi020.c
@@ -0,0 +1,337 @@
+/*
+ * Faraday FTSPI020 Flash Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include sysemu/sysemu.h
+#include hw/sysbus.h
+#include hw/ssi.h
+
+#include ftspi020.h
+
+#define TYPE_FTSPI020   ftspi020
+
+typedef struct Ftspi020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+SSIBus *spi;
+qemu_irq *cs_lines;
+
+int wip;/* SPI Flash Status: Write In Progress BIT shift */
+
+/* HW register caches */
+uint32_t cmd[4];
+uint32_t ctrl;
+uint32_t timing;
+uint32_t icr;
+uint32_t isr;
+uint32_t rdsr;
+} Ftspi020State;
+
+#define FTSPI020(obj) \
+OBJECT_CHECK(Ftspi020State, obj, TYPE_FTSPI020)
+
+static void ftspi020_update_irq(Ftspi020State *s)
+{
+qemu_set_irq(s-irq, s-isr ? 1 : 0);
+}
+
+static void ftspi020_handle_ack(void *opaque, int line, int level)
+{
+Ftspi020State *s = FTSPI020(opaque);
+
+if (!(s-icr  ICR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-cmd[2]) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static int ftspi020_do_command(Ftspi020State *s)
+{
+uint32_t cs   = extract32(s-cmd[3],  8, 2);
+uint32_t cmd  = extract32(s-cmd[3], 24, 8);
+uint32_t ilen = extract32(s-cmd[1], 24, 2);
+uint32_t alen = extract32(s-cmd[1],  0, 3);
+uint32_t dcyc = extract32(s-cmd[1], 16, 8);
+
+if (dcyc % 8) {
+fprintf(stderr, ftspi020: bad dummy clock (%u) to QEMU\n, dcyc);
+abort();
+}
+
+/* activate the spi flash */
+qemu_set_irq(s-cs_lines[cs], 0);
+
+/* if it's a SPI flash READ_STATUS command */
+if ((s-cmd[3]  (CMD3_RDSR | CMD3_WRITE)) == CMD3_RDSR) {
+uint32_t rdsr;
+
+ssi_transfer(s-spi, cmd);
+do {
+rdsr = ssi_transfer(s-spi, 0x00);
+if (s-cmd[3]  CMD3_RDSR_SW) {
+break;
+}
+} while (rdsr  (1  s-wip));
+s-rdsr = rdsr;
+} else {
+/* otherwise */
+int i;
+
+ilen = MIN(ilen, 2);
+alen = MIN(alen, 4);
+
+/* command cycles */
+for (i = 0; i  ilen; ++i) {
+ssi_transfer(s-spi, cmd);
+}
+/* address cycles */
+for (i = alen - 1; i = 0; --i) {
+ssi_transfer(s-spi, extract32(s-cmd[0], i * 8, 8));
+}
+/* dummy cycles */
+for (i = 0; i  (dcyc  3); ++i) {
+ssi_transfer(s-spi, 0x00);
+}
+}
+
+if (!s-cmd[2]) {
+qemu_set_irq(s-cs_lines[cs], 1);
+} else if (s-icr  ICR_DMA) {
+qemu_set_irq(s-req, 1);
+}
+
+if (s-cmd[3]  CMD3_INTR) {
+s-isr |= ISR_CMDFIN;
+}
+ftspi020_update_irq(s);
+
+return 0;
+}
+
+static void ftspi020_chip_reset(Ftspi020State *s)
+{
+int i;
+
+for (i = 0; i  4; ++i) {
+s-cmd[i] = 0;
+}
+s-wip = 0;
+s-ctrl = 0;
+s-timing = 0;
+s-icr = 0;
+s-isr = 0;
+s-rdsr = 0;
+
+qemu_set_irq(s-irq, 0

[Qemu-devel] [PATCH v8 01/24] target-arm: add Faraday ARMv5TE processors support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

This patch includes the single core support to FA606TE, FA626TE,
FA616TE and FA726TE with CP15 Faraday extensions (AUX and I/D-Scratchpad).

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 target-arm/cpu.c |   52 +++
 target-arm/cpu.h |6 +++-
 target-arm/helper.c  |   84 ++
 target-arm/machine.c |4 +++
 4 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index a1e9093..aed97b0 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -244,6 +244,54 @@ static void arm926_initfn(Object *obj)
 cpu-reset_sctlr = 0x00090078;
 }
 
+static void fa606te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_MPU_FARADAY);
+cpu-midr = 0x66056061; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa616te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66056161; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d152152;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa626te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+set_feature(cpu-env, ARM_FEATURE_AUXCR);
+cpu-midr = 0x66056261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x0f192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa726te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66057261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
 static void arm946_initfn(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -766,6 +814,10 @@ typedef struct ARMCPUInfo {
 
 static const ARMCPUInfo arm_cpus[] = {
 { .name = arm926,  .initfn = arm926_initfn },
+{ .name = fa606te, .initfn = fa606te_initfn },
+{ .name = fa616te, .initfn = fa616te_initfn },
+{ .name = fa626te, .initfn = fa626te_initfn },
+{ .name = fa726te, .initfn = fa726te_initfn },
 { .name = arm946,  .initfn = arm946_initfn },
 { .name = arm1026, .initfn = arm1026_initfn },
 /* What QEMU calls arm1136-r2 is actually the 1136 r0p2, i.e. an
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2b97221..dd27e80 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -152,6 +152,8 @@ typedef struct CPUARMState {
 uint32_t c15_diagnostic; /* diagnostic register */
 uint32_t c15_power_diagnostic;
 uint32_t c15_power_control; /* power control */
+uint32_t c15_tcm_data;  /* Data TCM region register */
+uint32_t c15_tcm_inst;  /* Instruction TCM region register */
 } cp15;
 
 struct {
@@ -392,6 +394,8 @@ enum arm_features {
 ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
 ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
+ARM_FEATURE_TCM_FARADAY, /* Faraday Scratchpad(TCM) */
+ARM_FEATURE_MPU_FARADAY, /* Faraday MPU */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -640,7 +644,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 9
+#define CPU_SAVE_VERSION 10
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fd055e8..337d8b8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1015,6 +1015,84 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+static int faraday_pmsav5_ircfg_read(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+if (ri-crm = 4) {
+return

[Qemu-devel] [PATCH v8 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-15 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTDDRII030 is a DDRII SDRAM controller which is responsible for
SDRAM initialization.
In QEMU we emulate only the SDRAM enable function.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |9 +++
 hw/arm/ftddrii030.c   |  183 +
 3 files changed, 193 insertions(+)
 create mode 100644 hw/arm/ftddrii030.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index af36b01..0bbf838 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -39,3 +39,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 faraday_a369_kpd.o
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
+obj-y += ftddrii030.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 01b4395..e8a63bb 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -158,6 +158,15 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
 abort();
 }
+
+/* ftddrii030 */
+ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
+s-ddrc = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
+abort();
+}
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
new file mode 100644
index 000..90a5842
--- /dev/null
+++ b/hw/arm/ftddrii030.c
@@ -0,0 +1,183 @@
+/*
+ * Faraday DDRII controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+#define REG_MCR 0x00/* memory configuration register */
+#define REG_MSR 0x04/* memory status register */
+#define REG_REVR0x50/* revision register */
+
+#define MSR_INIT_OK BIT(8)  /* DDR2 initial is completed */
+#define MSR_CMD_MRS BIT(0)  /* start MRS command */
+
+#define CFG_REGSIZE (0x50 / 4)
+
+#define TYPE_FTDDRII030 ftddrii030
+
+typedef struct Ftddrii030State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftddrii030State;
+
+#define FTDDRII030(obj) \
+OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
+
+#define DDR_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static uint64_t
+ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+uint64_t ret = 0;
+
+if (s-soc-ddr_inited) {
+DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
+}
+
+switch (addr) {
+case REG_MCR ... (CFG_REGSIZE - 1) * 4:
+ret = s-regs[addr / 4];
+break;
+case REG_REVR:
+ret = 0x100;/* rev. = 0.1.0 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+
+switch (addr) {
+case REG_MCR:
+DDR_REG32(s, REG_MCR) = (uint32_t)val  0x;
+break;
+case REG_MSR:
+val = (val  0x3f) | (DDR_REG32(s, REG_MSR)  MSR_INIT_OK);
+if (!s-soc-ddr_inited  (val  MSR_CMD_MRS)) {
+val = ~MSR_CMD_MRS;
+val |= MSR_INIT_OK;
+memory_region_add_subregion(s-soc-as,
+s-soc-ram_base,
+s-soc-ram);
+s-soc-ddr_inited = true;
+}
+DDR_REG32(s, REG_MSR) = (uint32_t)val;
+break;
+case 0x08 ... (CFG_REGSIZE - 1) * 4: /* DDRII Timing, ECC ...etc. */
+s-regs[addr / 4] = (uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mmio_ops = {
+.read  = ftddrii030_mem_read,
+.write = ftddrii030_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+}
+};
+
+static void ftddrii030_reset(DeviceState *ds)
+{
+Ftddrii030State *s = FTDDRII030(SYS_BUS_DEVICE(ds));
+Error *local_errp = NULL;
+
+s-soc = FARADAY_SOC(object_property_get_link(OBJECT(s),
+  soc,
+  local_errp));
+if (local_errp) {
+fprintf(stderr, ftahbc020: Unable to get soc link\n

[Qemu-devel] [PATCH v7 00/24] hw/arm: add Faraday A369 SoC platform support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

These patches introduce Faraday A369 SoC platform support.

Here are some public documents for your reference.

http://www.faraday-tech.com/html/documentation/index.html

The partial version of faraday cpu datasheet with only
the CP15 and MPU description are available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAalh5TkxyZWtlWEE/edit?usp=sharing

The pre-built A369 images are also available at my Google Drive:

https://docs.google.com/folder/d/0BwfiewvSmUgAX2pTTmtUMGFCZW8/edit

Here is the image file list:

1. android-4.0.4/zImage: A369 linux-3.0.31
2. android-4.0.4/romfs-4.0.4.tar.bz2: android-4.0.4
3. nand.img.bz2: A369 nand flash image
4. rom.img.bz2: A369 embedded ROM image
5. u-boot: A369 u-boot-2012.10 ELF file
6. zImage: A369 linux-3.4.12 + initramfs
7. README

If you want to re-build the image from scratch, 
try my Faraday Linux BSP/SDK: falinux.

1. Download the falinux

   $ git clone https://github.com/dantesu1218/falinux.git

2. Download all the required software packages:

   $ cd falinux
   $ make setup

3. Launch the menuconfig of falinux, and enable 'QEMU Support'

   $ make menuconfig

4. Re-build the packages

   $ make

5. Laungh the qemu-1.3.0 with the generated falinux images.

   $ make qemu

Changes for v6 - v7:

1. hw/arm/ftwdt010:
   Replace 'qemu_system_reset_request()' with 'watchdog_perform_action()'.
2. hw/arm/ftrtc011:
   Replace 'get_clock_realtime()' with 'qemu_get_clock_ns(rtc_clock)'.
   Replace 'qemu_new_timer_ms(rt_clock...)' with 
'qemu_new_timer_ms(rtc_clock...)'
   Rename 'ftrtc011_timer_resync' - 'ftrtc011_timer_rebase'
   Add ftrtc011_timer_resche()
   Add QTest support
3. hw/arm/faraday_a369_soc:
   Remove redundant device reset from a369soc_system_reset(...)
4. include/qemu/bitops.h:
   Update bitrev8() to use a kind of divide and conquer algorithm.
5. hw/arm/ftahb020,ftddrii030,ftapbbrg020,faraday_a369_soc:
   Drop FARADAY_SOC_GET_CORE(), replaced with device to device QOM link.
6. hw/wm8731,wm8750,marvell_88w8618_audio,spitz,z2:
   Add AudioCodecClass for wm87xx audio class abstration.
7. hw/arm/ftnandc021:
   Drop nand_init(), replaced with device to device QOM link.
8. hw/arm/ftsdc010:
   Bug fixed to write operation: remove sd_data_ready() in write path.
9. hw/arm/ftgmac100,ftmac110,ftwdt010:
   rt-clock - vm_clock
   10. hw/nand.c:
   Drop [hw/nand.c: correct the sense of the BUSY/READY], since it's 
already applied.
   Drop [hw/nand.c: bug fix to erase operation], since Peter has a better 
solution.

Changes for v5 - v6:

   1. hw/arm/Makefile.objs: 
   Shift to the next line only after current line length is  80 characters.
   2. hw/arm/faraday.h:
   Update debug macro format per discussions at the link bellow:
   http://thread.gmane.org/gmane.comp.emulators.qemu/195996/focus=196975
   3. hw/arm/faraday.h:
   TYPE_FARADAY_SOC: 'faraday/soc' - 'faraday.soc'
   4. hw/arm/*.c:
   Replace '%llx' with '%HWADDR_PRIx'
   5. hw/arm/*.h:
   Add '#include qemu/bitops.h'
   6. hw/arm/faraday_a369_soc.c:
   Typo fix: salve4 - slave4, salve6 - slave6
   7. hw/arm/*.c:
   Drop FROM_SYSBUS().
   8. hw/arm/ftintc020.c:
   Re-write the source file with pl190.c as template.
   9. hw/arm/ftintc020.h:
   Rename the registers to improve readibility.
   10. hw/arm/faraday.h:
   Add dedicated spi flash pointer array (DeviceState *spi_fl[2]).
   11. hw/arm/faraday.h:
   Add 'qemu_irq pic[64]'.
   12. hw/arm/*c:
   Replace the complex conversion in XXX_REG32() with directly array 
indexing.
   13. hw/arm/*c:
   Update the error message output from 'hw_error(...)' into 
'fprintf(stderr, ...)'
   14. hw/arm/faraday_a369.c, hw/arm/faraday_a369_soc.c:
   Move the external AHB device init from faraday_a369_soc.c to 
faraday_a369.c
   15. include/qemu/bitops.h:
   Move bitrev() from bitrev.[ch] into bitops.h
   16. hw/nand.c:
   Remove the clear/set SR[6] code in read/erase/write, because
   it's not possible to be observed by a guest.
   17. hw/arm/faraday_a369_kpd.c:
   Function prefix: 'ftkbc010' - 'a369kpd' 
   Name of struct:  'FTKBC010State' - 'A369KPDState'.
   QOM: 'FTKBC010' - 'A369KPD'
   18. hw/arm/ftddrii030.c:
   'case REG_MCR ... 0x4c' - 'case REG_MCR ... (CFG_REGSIZE - 1) * 4'
   19. hw/arm/ftahbc020.c:
   Add comments to fall-through path. (i.e. /* fall-through - skip slave6 
*/)
   20. hw/arm/faraday_a369.c:
   Update spi flash init code to use the new QOM classes of m25p80.

Changes for v3 - v5:

   1. [cpu] Add the unapplied patches for faraday ARMv5TE cores.
   2. [nand] Add the unapplied patches for hw/nand.c.
   3. [audio] Add the unapplied patches for wm8731.
   4. [Global] Replace redundant statement in xxx_update_irq() with
qemu_set_irq(s-irq, !!());
   5. [Global] Introduce 'case xxx ... xxx

[Qemu-devel] [PATCH v7 03/24] hw/arm: add FTINTC020 interrupt controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTINTC020 interrupt controller supports both FIQ and IRQ signals
to the microprocessor.
It can handle up to 64 configurable IRQ sources and 64 FIQ sources.
The output signals to the microprocessor can be configured as
level-high/low active or edge-rising/falling triggered.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   11 ++
 hw/arm/ftintc020.c|  306 +
 hw/arm/ftintc020.h|   57 +
 4 files changed, 375 insertions(+)
 create mode 100644 hw/arm/ftintc020.c
 create mode 100644 hw/arm/ftintc020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 104e0e7..536d6cf 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -37,3 +37,4 @@ obj-y += omap1.o omap2.o
 
 obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
 faraday_a369_kpd.o
+obj-y += ftintc020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index c0309e3..d3187b2 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -72,6 +72,8 @@ a369soc_device_init(FaradaySoCState *s)
 {
 DriveInfo *dinfo;
 DeviceState *ds;
+qemu_irq *cpu_pic;
+int i;
 
 s-as = get_system_memory();
 s-ram = g_new(MemoryRegion, 1);
@@ -111,6 +113,15 @@ a369soc_device_init(FaradaySoCState *s)
 exit(1);
 }
 
+/* Interrupt Controller */
+cpu_pic = arm_pic_init_cpu(s-cpu);
+ds = sysbus_create_varargs(ftintc020, 0x9010,
+   cpu_pic[ARM_PIC_CPU_IRQ],
+   cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+for (i = 0; i  ARRAY_SIZE(s-pic); ++i) {
+s-pic[i] = qdev_get_gpio_in(ds, i);
+}
+
 /* Serial (FTUART010 which is 16550A compatible) */
 if (serial_hds[0]) {
 serial_mm_init(s-as,
diff --git a/hw/arm/ftintc020.c b/hw/arm/ftintc020.c
new file mode 100644
index 000..3ee26b9
--- /dev/null
+++ b/hw/arm/ftintc020.c
@@ -0,0 +1,306 @@
+/*
+ * Faraday FTINTC020 Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+
+#include faraday.h
+#include ftintc020.h
+
+#define TYPE_FTINTC020  ftintc020
+
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftintc020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+qemu_irq irq;
+qemu_irq fiq;
+
+uint32_t irq_ps[2]; /* IRQ pin state */
+uint32_t fiq_ps[2]; /* FIQ pin state */
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftintc020State;
+
+#define FTINTC020(obj) \
+OBJECT_CHECK(Ftintc020State, obj, TYPE_FTINTC020)
+
+#define PIC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+#define IRQ_REG32(s, n, off) \
+((s)-regs[(REG_IRQ(n) + ((off)  REG_MASK)) / 4])
+
+#define FIQ_REG32(s, n, off) \
+((s)-regs[(REG_FIQ(n) + ((off)  REG_MASK)) / 4])
+
+static void
+ftintc020_update_irq(Ftintc020State *s)
+{
+uint32_t mask[2];
+
+/* FIQ */
+mask[0] = PIC_REG32(s, REG_FIQ32SRC)  PIC_REG32(s, REG_FIQ32ENA);
+mask[1] = PIC_REG32(s, REG_FIQ64SRC)  PIC_REG32(s, REG_FIQ64ENA);
+qemu_set_irq(s-fiq, !!(mask[0] || mask[1]));
+
+/* IRQ */
+mask[0] = PIC_REG32(s, REG_IRQ32SRC)  PIC_REG32(s, REG_IRQ32ENA);
+mask[1] = PIC_REG32(s, REG_IRQ64SRC)  PIC_REG32(s, REG_IRQ64ENA);
+qemu_set_irq(s-irq, !!(mask[0] || mask[1]));
+}
+
+/* Note: Here level means state of the signal on a pin */
+static void
+ftintc020_set_irq(void *opaque, int irq, int level)
+{
+Ftintc020State *s = FTINTC020(opaque);
+uint32_t i = irq / 32;
+uint32_t mask = BIT(irq % 32);
+
+switch (irq) {
+case 0  ... 63:
+/* IRQ */
+if (IRQ_REG32(s, irq, REG_MDR)  mask) {
+/* Edge Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Falling Active */
+if ((s-irq_ps[i]  mask)  !level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* Rising Active */
+if (!(s-irq_ps[i]  mask)  level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+}
+} else {
+/* Level Triggered */
+if (IRQ_REG32(s, irq, REG_LVR)  mask) {
+/* Low Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+}
+} else {
+/* High Active */
+if (level) {
+IRQ_REG32(s, irq, REG_SRC) |= mask;
+} else {
+IRQ_REG32(s, irq, REG_SRC) = ~mask;
+}
+}
+}
+
+/* FIQ

[Qemu-devel] [PATCH v7 02/24] hw/arm: add Faraday a369 SoC platform support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday A369 EVB is a Faraday SoC platform evalution board used for
Faraday IP functional verification based on the well-known ARM AMBA 2.0
architecture.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |3 +
 hw/arm/faraday.h  |   59 
 hw/arm/faraday_a369.c |   98 +++
 hw/arm/faraday_a369_kpd.c |  235 +
 hw/arm/faraday_a369_scu.c |  186 +++
 hw/arm/faraday_a369_soc.c |  193 +
 hw/arm/ftkbc010.h |   44 +
 7 files changed, 818 insertions(+)
 create mode 100644 hw/arm/faraday.h
 create mode 100644 hw/arm/faraday_a369.c
 create mode 100644 hw/arm/faraday_a369_kpd.c
 create mode 100644 hw/arm/faraday_a369_scu.c
 create mode 100644 hw/arm/faraday_a369_soc.c
 create mode 100644 hw/arm/ftkbc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f5f7d0e..104e0e7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -34,3 +34,6 @@ obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-y += omap1.o omap2.o
+
+obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
+faraday_a369_kpd.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
new file mode 100644
index 000..86cc1ff
--- /dev/null
+++ b/hw/arm/faraday.h
@@ -0,0 +1,59 @@
+/*
+ * Faraday SoC platform support.
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Kuo-Jung Su dant...@gmail.com
+ *
+ * This code is licensed under the GNU GPL v2.
+ */
+#ifndef HW_ARM_FARADAY_H
+#define HW_ARM_FARADAY_H
+
+#include hw/flash.h
+#include qemu/bitops.h
+
+#ifndef DEBUG
+#define DEBUG   0
+#endif
+
+#define DPRINTF(fmt, ...) \
+do { if (DEBUG) { printf(faraday:  fmt , ## __VA_ARGS__); } } while (0)
+
+typedef struct FaradaySoCState {
+SysBusDevice busdev;
+hwaddr   rom_base;
+uint64_t rom_size;
+hwaddr   ram_base;
+uint64_t ram_size;
+char *cpu_model;
+ARMCPU   *cpu;
+qemu_irq pic[64];
+DeviceState  *scu;  /* System Control Unit */
+DeviceState  *ahbc; /* AHB controller */
+DeviceState  *ddrc; /* DDR controller */
+DeviceState  *hdma[2];  /* AHB DMA */
+DeviceState  *pdma[1];  /* APB DMA */
+DeviceState  *spi[2];   /* Generic SPI bus */
+DeviceState  *spi_fl[2];/* Dedicated SPI bus for flash memory */
+DeviceState  *i2c[2];   /* Generic I2C bus */
+DeviceState  *i2s[2];   /* Generic I2S bus */
+DeviceState  *nandc[2]; /* NAND flash controller */
+
+MemoryRegion *as;   /* address space */
+MemoryRegion *ram;  /* external sdram */
+pflash_t *rom;  /* on-chip rom */
+MemoryRegion *sram; /* on-chip static ram */
+
+uint32_t ahb_slave[32];
+uint32_t apb_slave[32];
+bool ahb_remapped;
+bool ddr_inited;
+struct arm_boot_info *bi;
+} FaradaySoCState;
+
+/* SoC common APIs */
+#define TYPE_FARADAY_SOCfaraday.soc
+#define FARADAY_SOC(obj) \
+OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
+
+#endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
new file mode 100644
index 000..8f8ea4f
--- /dev/null
+++ b/hw/arm/faraday_a369.c
@@ -0,0 +1,98 @@
+/*
+ * Faraday A369 Evalution Board
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/arm-misc.h
+#include hw/devices.h
+#include hw/i2c.h
+#include hw/boards.h
+#include hw/ssi.h
+#include net/net.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+/* Board init.  */
+
+static void
+a369_board_init(QEMUMachineInitArgs *args)
+{
+DeviceState *ds;
+FaradaySoCState *s;
+
+if (!args-cpu_model) {
+args-cpu_model = fa626te;
+}
+
+if (!args-ram_size) {
+args-ram_size = 512  20;
+}
+
+ds = qdev_create(NULL, TYPE_FARADAY_SOC);
+qdev_prop_set_string(ds, cpu_model, args-cpu_model);
+qdev_prop_set_uint64(ds, ram_size, args-ram_size);
+/* Setup QOM path for the SoC object (i.e. /machine/faraday.soc) */
+object_property_add_child(qdev_get_machine(),
+  TYPE_FARADAY_SOC,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+
+s = FARADAY_SOC(ds);
+
+/* System start-up */
+
+if (args-kernel_filename) {
+s-bi = g_new0(struct arm_boot_info, 1);
+
+s-ddr_inited = true;
+s-ahb_remapped = true;
+
+/* Remap AHB slave 4 (ROM)  slave 6 (RAM) */
+/* 1. Remap RAM to base of ROM */
+s-ram_base = s-ahb_slave[4]  0xfff0;
+s-ahb_slave[6] = s-ram_base | (s-ahb_slave[6]  0x000f);
+/* 2. Remap ROM to base of ROM + size of RAM

[Qemu-devel] [PATCH v7 11/24] hw/arm: add FTAPBBRG020 APB DMA support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTAPBBRG020 supports the DMA functions for the AHB-to-AHB,
AHB-to-APB, APB-to-AHB, and APB-to-APB transactions.

The DMA engine can support up to 4 DMA channels (A, B, C, and D)
and 15 handshaking channels. A DMA channel granted by the arbiter
block is the only channel starts transfers. Each DMA channel can
be programmed to one of the 15 handshaking channels in the hardware
handshake mode to act as the source device or act as the destination
device.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |9 +
 hw/arm/ftapbbrg020.c  |  475 +
 hw/arm/ftapbbrg020.h  |   44 +
 4 files changed, 529 insertions(+)
 create mode 100644 hw/arm/ftapbbrg020.c
 create mode 100644 hw/arm/ftapbbrg020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 7a6e94a..cc5e343 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -44,3 +44,4 @@ obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
 obj-y += ftrtc011.o
 obj-y += ftdmac020.o
+obj-y += ftapbbrg020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index b0d0ff6..ab13f70 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -223,6 +223,15 @@ a369soc_device_init(FaradaySoCState *s)
s-pic[17], /* TC */
s-pic[18], /* ERR */
NULL);
+
+/* ftapbbrg020 */
+ds = sysbus_create_simple(ftapbbrg020, 0x90f0, s-pic[14]);
+s-pdma[0] = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
+exit(1);
+}
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftapbbrg020.c b/hw/arm/ftapbbrg020.c
new file mode 100644
index 000..c3cbe65
--- /dev/null
+++ b/hw/arm/ftapbbrg020.c
@@ -0,0 +1,475 @@
+/*
+ * QEMU model of the FTAPBBRG020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTAPBBRG020 DMA decreasing address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include faraday.h
+#include ftapbbrg020.h
+
+#define TYPE_FTAPBBRG020ftapbbrg020
+
+typedef struct Ftapbbrg020State Ftapbbrg020State;
+
+typedef struct Ftapbbrg020Chan {
+Ftapbbrg020State *chip;
+
+int id;
+int burst;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register caches */
+uint32_t src;
+uint32_t dst;
+uint32_t len;
+uint32_t cmd;
+} Ftapbbrg020Chan;
+
+typedef struct Ftapbbrg020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+FaradaySoCState *soc;
+Ftapbbrg020Chan chan[4];
+qemu_irq ack[16];
+uint32_t req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+} Ftapbbrg020State;
+
+#define FTAPBBRG020(obj) \
+OBJECT_CHECK(Ftapbbrg020State, obj, TYPE_FTAPBBRG020)
+
+static uint32_t ftapbbrg020_get_isr(Ftapbbrg020State *s)
+{
+int i;
+uint32_t isr = 0;
+Ftapbbrg020Chan *chan;
+
+for (i = 0; i  4; ++i) {
+chan = s-chan + i;
+isr |= (chan-cmd  CMD_INTR_STATUS);
+}
+
+return isr;
+}
+
+static void ftapbbrg020_update_irq(Ftapbbrg020State *s)
+{
+uint32_t isr = ftapbbrg020_get_isr(s);
+
+qemu_set_irq(s-irq, isr ? 1 : 0);
+}
+
+static void ftapbbrg020_chan_cmd_decode(Ftapbbrg020Chan *c)
+{
+uint32_t tmp;
+
+/* 1. decode burst size */
+c-burst = (c-cmd  CMD_BURST4) ? 4 : 1;
+
+/* 2. decode source/destination width */
+tmp = extract32(c-cmd, 20, 2);
+if (tmp  2) {
+tmp = 2;
+}
+c-src_bw = c-dst_bw = 8  (2 - tmp);
+
+/* 3. decode source address stride */
+switch (extract32(c-cmd, 8, 2)) {
+case 0:
+c-src_stride = 0;
+break;
+case 1:
+c-src_stride = c-src_bw  3;
+break;
+case 2:
+c-src_stride = 2 * (c-src_bw  3);
+break;
+case 3:
+c-src_stride = 4 * (c-src_bw  3);
+break;
+}
+
+/* 4. decode destination address stride */
+switch (extract32(c-cmd, 12, 2)) {
+case 0:
+c-dst_stride = 0;
+break;
+case 1:
+c-dst_stride = c-dst_bw  3;
+break;
+case 2:
+c-dst_stride = 2 * (c-dst_bw  3);
+break;
+case 3:
+c-dst_stride = 4 * (c-dst_bw  3

[Qemu-devel] [PATCH v7 01/24] target-arm: add Faraday ARMv5TE processors support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

This patch includes the single core support to FA606TE, FA626TE,
FA616TE and FA726TE with CP15 Faraday extensions (AUX and I/D-Scratchpad).

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 target-arm/cpu.c |   52 +++
 target-arm/cpu.h |6 +++-
 target-arm/helper.c  |   84 ++
 target-arm/machine.c |4 +++
 4 files changed, 145 insertions(+), 1 deletion(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 5dfcb74..99b7244 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -244,6 +244,54 @@ static void arm926_initfn(Object *obj)
 cpu-reset_sctlr = 0x00090078;
 }
 
+static void fa606te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_MPU_FARADAY);
+cpu-midr = 0x66056061; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa616te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66056161; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d152152;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa626te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+set_feature(cpu-env, ARM_FEATURE_AUXCR);
+cpu-midr = 0x66056261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x0f192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x0078;  /* CR1-0 Configuration Register (CFG) */
+}
+
+static void fa726te_initfn(Object *obj)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+set_feature(cpu-env, ARM_FEATURE_V5);
+set_feature(cpu-env, ARM_FEATURE_DUMMY_C15_REGS);
+set_feature(cpu-env, ARM_FEATURE_CACHE_TEST_CLEAN);
+set_feature(cpu-env, ARM_FEATURE_TCM_FARADAY);
+cpu-midr = 0x66057261; /* CR0-0 Identification Code Register (ID) */
+cpu-ctr = 0x1d192192;  /* CR0-1 Cache Type Register (CTR) */
+cpu-reset_sctlr = 0x00050078;  /* CR1-0 Configuration Register (CFG) */
+}
+
 static void arm946_initfn(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -756,6 +804,10 @@ typedef struct ARMCPUInfo {
 
 static const ARMCPUInfo arm_cpus[] = {
 { .name = arm926,  .initfn = arm926_initfn },
+{ .name = fa606te, .initfn = fa606te_initfn },
+{ .name = fa616te, .initfn = fa616te_initfn },
+{ .name = fa626te, .initfn = fa626te_initfn },
+{ .name = fa726te, .initfn = fa726te_initfn },
 { .name = arm946,  .initfn = arm946_initfn },
 { .name = arm1026, .initfn = arm1026_initfn },
 /* What QEMU calls arm1136-r2 is actually the 1136 r0p2, i.e. an
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c28a0d9..e4c43ef 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -152,6 +152,8 @@ typedef struct CPUARMState {
 uint32_t c15_diagnostic; /* diagnostic register */
 uint32_t c15_power_diagnostic;
 uint32_t c15_power_control; /* power control */
+uint32_t c15_tcm_data;  /* Data TCM region register */
+uint32_t c15_tcm_inst;  /* Instruction TCM region register */
 } cp15;
 
 struct {
@@ -393,6 +395,8 @@ enum arm_features {
 ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
 ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
+ARM_FEATURE_TCM_FARADAY, /* Faraday Scratchpad(TCM) */
+ARM_FEATURE_MPU_FARADAY, /* Faraday MPU */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -641,7 +645,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 9
+#define CPU_SAVE_VERSION 10
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6cad936..7182559 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1015,6 +1015,84 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
 REGINFO_SENTINEL
 };
 
+static int faraday_pmsav5_ircfg_read(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+if (ri-crm = 4) {
+return

[Qemu-devel] [PATCH v7 05/24] hw/arm: add FTDDRII030 DDRII controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTDDRII030 is a DDRII SDRAM controller which is responsible for
SDRAM initialization.
In QEMU we emulate only the SDRAM enable function.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |9 +++
 hw/arm/ftddrii030.c   |  190 +
 3 files changed, 200 insertions(+)
 create mode 100644 hw/arm/ftddrii030.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index af36b01..0bbf838 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -39,3 +39,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 faraday_a369_kpd.o
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
+obj-y += ftddrii030.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 6de2f4f..46600d7 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -158,6 +158,15 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
 exit(1);
 }
+
+/* ftddrii030 */
+ds = sysbus_create_simple(ftddrii030, 0x9310, NULL);
+s-ddrc = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
+exit(1);
+}
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
new file mode 100644
index 000..9ab49c8
--- /dev/null
+++ b/hw/arm/ftddrii030.c
@@ -0,0 +1,190 @@
+/*
+ * Faraday DDRII controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+#define REG_MCR 0x00/* memory configuration register */
+#define REG_MSR 0x04/* memory status register */
+#define REG_REVR0x50/* revision register */
+
+#define MSR_INIT_OK BIT(8)  /* DDR2 initial is completed */
+#define MSR_CMD_MRS BIT(0)  /* start MRS command */
+
+#define CFG_REGSIZE (0x50 / 4)
+
+#define TYPE_FTDDRII030 ftddrii030
+
+typedef struct Ftddrii030State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftddrii030State;
+
+#define FTDDRII030(obj) \
+OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
+
+#define DDR_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static uint64_t
+ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+uint64_t ret = 0;
+
+if (s-soc-ddr_inited) {
+DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
+}
+
+switch (addr) {
+case REG_MCR ... (CFG_REGSIZE - 1) * 4:
+ret = s-regs[addr / 4];
+break;
+case REG_REVR:
+ret = 0x100;/* rev. = 0.1.0 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftddrii030State *s = FTDDRII030(opaque);
+
+switch (addr) {
+case REG_MCR:
+DDR_REG32(s, REG_MCR) = (uint32_t)val  0x;
+break;
+case REG_MSR:
+val = (val  0x3f) | (DDR_REG32(s, REG_MSR)  MSR_INIT_OK);
+if (!s-soc-ddr_inited  (val  MSR_CMD_MRS)) {
+val = ~MSR_CMD_MRS;
+val |= MSR_INIT_OK;
+memory_region_add_subregion(s-soc-as,
+s-soc-ram_base,
+s-soc-ram);
+s-soc-ddr_inited = true;
+}
+DDR_REG32(s, REG_MSR) = (uint32_t)val;
+break;
+case 0x08 ... (CFG_REGSIZE - 1) * 4: /* DDRII Timing, ECC ...etc. */
+s-regs[addr / 4] = (uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftddrii030: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mmio_ops = {
+.read  = ftddrii030_mem_read,
+.write = ftddrii030_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+}
+};
+
+static void ftddrii030_reset(DeviceState *ds)
+{
+Ftddrii030State *s = FTDDRII030(SYS_BUS_DEVICE(ds));
+Error *local_errp = NULL;
+
+s-soc = FARADAY_SOC(object_property_get_link(OBJECT(s),
+  soc,
+  local_errp));
+if (local_errp) {
+fprintf(stderr, ftahbc020: Unable to get soc link\n);
+exit(1

[Qemu-devel] [PATCH v7 09/24] tests: add QTest for FTRTC011

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTRTC011 QEMU model is implemented without calender functions.
It acts in counter mode only, all the time  timezone conversion
relies on the c runtime library. (i.e. mktime(), localtime() ...etc)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 tests/Makefile|3 +
 tests/ftrtc011-test.c |  410 +
 2 files changed, 413 insertions(+)
 create mode 100644 tests/ftrtc011-test.c

diff --git a/tests/Makefile b/tests/Makefile
index 567e36e..5d0776e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -75,6 +75,8 @@ gcov-files-sparc-y += hw/m48t59.c
 gcov-files-sparc64-y += hw/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 gcov-files-arm-y += hw/tmp105.c
+check-qtest-arm-y = tests/ftrtc011-test$(EXESUF)
+gcov-files-arm-y += hw/arm/ftrtc011.c
 
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h 
tests/test-qmp-commands.h
 
@@ -133,6 +135,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o
+tests/ftrtc011-test$(EXESUF): tests/ftrtc011-test.o
 
 # QTest rules
 
diff --git a/tests/ftrtc011-test.c b/tests/ftrtc011-test.c
new file mode 100644
index 000..e2324fa
--- /dev/null
+++ b/tests/ftrtc011-test.c
@@ -0,0 +1,410 @@
+/*
+ * QTest testcase for the FTRTC011 real-time clock
+ *
+ * Copyright (c) 2013 Kuo-Jung Su
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include libqtest.h
+#include hw/arm/ftrtc011.h
+
+#include glib.h
+#include stdio.h
+#include string.h
+#include stdlib.h
+#include unistd.h
+
+#define A369_FTRTC011_BASE  0x9210
+#define A369_FTRTC011_IRQ_ALARM 42  /* edge triggered */
+#define A369_FTRTC011_IRQ_SEC   43  /* edge triggered */
+#define A369_FTRTC011_IRQ_MIN   44  /* edge triggered */
+#define A369_FTRTC011_IRQ_HOUR  45  /* edge triggered */
+
+#define CFG_BASEYEAR2010
+
+static time_t ts_base;
+
+static uint32_t rtc_read(uint32_t reg)
+{
+return readl(A369_FTRTC011_BASE + reg);
+}
+
+static void rtc_write(uint32_t reg, uint32_t val)
+{
+writel(A369_FTRTC011_BASE + reg, val);
+}
+
+static int rtc_get_irq(int irq)
+{
+#if 0   /* It looks to me that get_irq() doesn't work well
+ * with edge interrupts.
+ */
+return get_irq(irq);
+#else
+switch (irq) {
+case A369_FTRTC011_IRQ_ALARM:
+return !!(rtc_read(REG_ISR)  ISR_ALARM);
+case A369_FTRTC011_IRQ_SEC:
+return !!(rtc_read(REG_ISR)  ISR_SEC);
+case A369_FTRTC011_IRQ_MIN:
+return !!(rtc_read(REG_ISR)  ISR_MIN);
+case A369_FTRTC011_IRQ_HOUR:
+return !!(rtc_read(REG_ISR)  ISR_HOUR);
+default:
+return 0;
+}
+#endif
+}
+
+static int tm_cmp(struct tm *lhs, struct tm *rhs)
+{
+time_t a, b;
+struct tm d1, d2;
+
+memcpy(d1, lhs, sizeof(d1));
+memcpy(d2, rhs, sizeof(d2));
+
+a = mktime(d1);
+b = mktime(d2);
+
+if (a  b) {
+return -1;
+} else if (a  b) {
+return 1;
+}
+
+return 0;
+}
+
+static void rtc_start(void)
+{
+time_t ts;
+struct tm base;
+
+if (!ts_base) {
+base.tm_isdst = -1;
+base.tm_year  = CFG_BASEYEAR - 1900;
+base.tm_mon   = 0;
+base.tm_mday  = 1;
+base.tm_hour  = 0;
+base.tm_min   = 0;
+base.tm_sec   = 0;
+ts_base = mktime(base);
+}
+
+ts = time(NULL) - ts_base;
+rtc_write(REG_WDAY, ts / 86400LL);
+ts %= 86400LL;
+rtc_write(REG_WHOUR, ts / 3600LL);
+ts %= 3600LL;
+rtc_write(REG_WMIN, ts / 60LL);
+ts %= 60LL;
+rtc_write(REG_WSEC, ts);
+
+rtc_write(REG_ISR, ISR_MASK);
+rtc_write(REG_CR, CR_EN | CR_LOAD | CR_INTR_MASK);
+}
+
+static void rtc_get_datetime(struct tm *date)
+{
+time_t ts;
+int64_t sec, min, hour, day;
+
+if (!ts_base) {
+fprintf(stderr, ts_base is not yet initialized!\n);
+exit(1);
+}
+
+sec  = rtc_read(REG_SEC);
+min  = rtc_read(REG_MIN);
+hour = rtc_read(REG_HOUR);
+day  = rtc_read(REG_DAY);
+ts   = ts_base + (86400LL * day) + (hour * 3600LL) + (min * 60LL) + sec;
+
+localtime_r(ts, date);
+}
+
+static void rtc_test_check_time(int wiggle)
+{
+struct tm start, date[4], end;
+struct tm *datep;
+time_t ts;
+
+rtc_start();
+
+/*
+ * This check assumes a few things.
+ * First, we cannot guarantee that we get a consistent reading
+ * from the wall clock because we may hit an edge of the clock
+ * while reading.
+ * To work around this, we read four clock readings such that
+ * at least two of them should match.  We need to assume that one
+ * reading is corrupt so we need four readings to ensure that we have at
+ * least two consecutive identical readings

[Qemu-devel] [PATCH v7 13/24] hw/arm: add FTI2C010 I2C controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTI2C010 is a simple I2C master controller.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |6 ++
 hw/arm/fti2c010.c |  216 +
 hw/arm/fti2c010.h |   71 +++
 4 files changed, 294 insertions(+)
 create mode 100644 hw/arm/fti2c010.c
 create mode 100644 hw/arm/fti2c010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2622f3f..63ba519 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -46,3 +46,4 @@ obj-y += ftrtc011.o
 obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
+obj-y += fti2c010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index a211c90..07fe41d 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -241,6 +241,12 @@ a369soc_device_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-hdma[0], 15);
 qdev_connect_gpio_out(s-hdma[0], 15, ack);
 qdev_connect_gpio_out(ds, 0, req);
+
+/* fti2c010 */
+ds = sysbus_create_simple(fti2c010, 0x9290, s-pic[51]);
+s-i2c[0] = ds;
+ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
+s-i2c[1] = ds;
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/fti2c010.c b/hw/arm/fti2c010.c
new file mode 100644
index 000..206f480
--- /dev/null
+++ b/hw/arm/fti2c010.c
@@ -0,0 +1,216 @@
+/*
+ * QEMU model of the FTI2C010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/i2c.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include fti2c010.h
+
+#define I2C_RD  1
+#define I2C_WR  0
+
+#define TYPE_FTI2C010   fti2c010
+
+typedef struct Fti2c010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+i2c_bus *bus;
+
+uint8_t  recv;/* I2C RD = 1; I2C WR = 0 */
+uint8_t  addr;/* 7-bits device address */
+
+/* HW register cache */
+uint32_t cr;
+uint32_t sr;
+uint32_t cdr;
+uint32_t dr;
+uint32_t tgsr;
+} Fti2c010State;
+
+#define FTI2C010(obj) \
+OBJECT_CHECK(Fti2c010State, obj, TYPE_FTI2C010)
+
+static void
+fti2c010_update_irq(Fti2c010State *s)
+{
+uint32_t sr = extract32(s-sr, 4, 8);
+uint32_t cr = extract32(s-cr, 8, 8);
+qemu_set_irq(s-irq, (sr  cr) ? 1 : 0);
+}
+
+static uint64_t
+fti2c010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_CR:
+return s-cr;
+case REG_SR:
+ret = s-sr | (i2c_bus_busy(s-bus) ? SR_BB : 0);
+s-sr = 0xf00f;/* clear RC status bits */
+fti2c010_update_irq(s);
+break;
+case REG_CDR:
+return s-cdr;
+case REG_DR:
+return s-dr;
+case REG_TGSR:
+return s-tgsr;
+case REG_BMR:
+return 0x0003;  /* Slave mode: SCL=1, SDA=1 */
+case REG_REVR:
+return 0x00011000;  /* REV. 1.10.0 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fti2c010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fti2c010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Fti2c010State *s = FTI2C010(opaque);
+
+switch (addr) {
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_I2CRST) {
+s-dr = 0;
+s-sr = 0;
+} else if ((s-cr  CR_MASTER_EN)  (s-cr  CR_TBEN)) {
+s-sr = ~SR_ACK;
+if (s-cr  CR_START) {
+s-recv = (s-dr  I2C_RD) ? 1 : 0;
+s-addr = extract32(s-dr, 1, 7);
+if (!i2c_start_transfer(s-bus, s-addr, s-recv)) {
+s-sr |= SR_DT | SR_ACK;
+} else {
+s-sr = ~SR_DT;
+}
+} else {
+if (s-recv) {
+s-dr = i2c_recv(s-bus);
+s-sr |= SR_DR;
+} else {
+i2c_send(s-bus, (uint8_t)s-dr);
+s-sr |= SR_DT;
+}
+if (s-cr  CR_NACK) {
+i2c_nack(s-bus);
+}
+s-sr |= SR_ACK;
+if (s-cr  CR_STOP) {
+i2c_end_transfer(s-bus);
+}
+}
+}
+s-cr = ~(CR_TBEN | CR_I2CRST);
+fti2c010_update_irq(s);
+break;
+case REG_CDR:
+s-cdr = (uint32_t)val  0x3;
+break;
+case REG_DR:
+s-dr  = (uint32_t)val  0xff;
+break;
+case REG_TGSR:
+s-tgsr = (uint32_t)val  0x1fff;
+break;
+/* slave mode is useless to QEMU, ignore it. */
+case REG_SAR:
+default:
+qemu_log_mask

[Qemu-devel] [PATCH v7 04/24] hw/arm: add FTAHBC020 AHB controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It's used to perform AHB remap and QEMU RAM initialization
when the SDRAM is initialized before AHB remap process activated.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   10 +++
 hw/arm/ftahbc020.c|  209 +
 3 files changed, 220 insertions(+)
 create mode 100644 hw/arm/ftahbc020.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 536d6cf..af36b01 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -38,3 +38,4 @@ obj-y += omap1.o omap2.o
 obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o \
 faraday_a369_kpd.o
 obj-y += ftintc020.o
+obj-y += ftahbc020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index d3187b2..6de2f4f 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -70,6 +70,7 @@ static void a369soc_reset(DeviceState *ds)
 static void
 a369soc_device_init(FaradaySoCState *s)
 {
+Error *local_errp = NULL;
 DriveInfo *dinfo;
 DeviceState *ds;
 qemu_irq *cpu_pic;
@@ -148,6 +149,15 @@ a369soc_device_init(FaradaySoCState *s)
 
 /* ftkbc010 */
 ds = sysbus_create_simple(a369.kpd, 0x92f0, s-pic[21]);
+
+/* ftahbc020 */
+ds = sysbus_create_simple(ftahbc020, 0x9400, NULL);
+s-ahbc = ds;
+object_property_set_link(OBJECT(ds), OBJECT(s), soc, local_errp);
+if (local_errp) {
+fprintf(stderr, a369soc: Unable to set soc link for FTAHBC020\n);
+exit(1);
+}
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftahbc020.c b/hw/arm/ftahbc020.c
new file mode 100644
index 000..65f388f
--- /dev/null
+++ b/hw/arm/ftahbc020.c
@@ -0,0 +1,209 @@
+/*
+ * Faraday AHB controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+
+#define REG_SLAVE(n)((n) * 4) /* Slave config (base  size) */
+#define REG_PRIR0x80/* Priority register */
+#define REG_IDLECR  0x84/* IDLE count register */
+#define REG_CR  0x88/* Control register */
+#define REG_REVR0x8c/* Revision register */
+
+#define CR_REMAP0x01/* Enable AHB remap for slave 4  6 */
+
+#define TYPE_FTAHBC020  ftahbc020
+
+typedef struct Ftahbc020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+
+FaradaySoCState *soc;
+/* HW register cache */
+uint32_t cr;
+} Ftahbc020State;
+
+#define FTAHBC020(obj) \
+OBJECT_CHECK(Ftahbc020State, obj, TYPE_FTAHBC020)
+
+static uint64_t
+ftahbc020_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+uint64_t ret = 0;
+
+switch (addr) {
+/* slave address  window configuration */
+case REG_SLAVE(0) ... REG_SLAVE(3):
+/* fall-through - skip slave4 */
+case REG_SLAVE(5):
+/* fall-through - skip slave6 */
+case REG_SLAVE(7) ... REG_SLAVE(31):
+ret = s-soc-ahb_slave[addr / 4];
+break;
+case REG_SLAVE(4):
+ret = s-soc-rom_base | (s-soc-ahb_slave[4]  0x000f);
+break;
+case REG_SLAVE(6):
+ret = s-soc-ram_base | (s-soc-ahb_slave[6]  0x000f);
+break;
+/* control register */
+case REG_CR:
+if (s-soc-ahb_remapped) {
+s-cr |= CR_REMAP;
+}
+ret = s-cr;
+break;
+case REG_REVR:
+ret = 0x00010301;   /* rev. 1.3.1 */
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftahbc020: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftahbc020_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftahbc020State *s = FTAHBC020(opaque);
+
+switch (addr) {
+case REG_CR:/* control register */
+s-cr = (uint32_t)val;
+if (s-soc-ahb_remapped  !(s-cr  CR_REMAP)) {
+fprintf(stderr, ftahbc020: Once AHB remap is enabled, 
+ it could not be disabled!\n);
+exit(1);
+}
+if (!s-soc-ahb_remapped  (s-cr  CR_REMAP)) {
+/* Remap AHB slave 4 (ROM)  slave 6 (RAM) */
+/* 1. Remap RAM to base of ROM */
+s-soc-ram_base = s-soc-ahb_slave[4]  0xfff0;
+/* 2. Remap ROM to base of ROM + size of RAM */
+s-soc-rom_base = s-soc-ram_base
++ ((1  extract32(s-soc-ahb_slave[6], 16, 4))  20);
+/* 3. Update ROM memory map */
+sysbus_mmio_map(SYS_BUS_DEVICE(s-soc-rom), 0, s-soc-rom_base);
+/* 4. Update RAM memory map if it has been initialized. */
+if (s-soc-ddr_inited) {
+memory_region_del_subregion(s-soc-as, s-soc-ram

[Qemu-devel] [PATCH v7 10/24] hw/arm: add FTDMAC020 AHB DMA support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The Faraday FTDMAC020 provides eight configurable
channels for the memory-to-memory, memory-to-peripheral,
peripheral-to-peripheral, and peripheral-to-memory transfers.

Each DMA channel supports chain transfer and can be programmed
to one of the 16 handshaking channels in the hardware handshake mode.

The main function of the hardware handshake mode is to provide an
indication of the device status. Users can also disable the hardware
handshake mode by programming the register when a DMA transfer is not
necessary of referring to the handshaking channels.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   14 ++
 hw/arm/ftdmac020.c|  599 +
 hw/arm/ftdmac020.h|  107 
 4 files changed, 721 insertions(+)
 create mode 100644 hw/arm/ftdmac020.c
 create mode 100644 hw/arm/ftdmac020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index b01da9d..7a6e94a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -43,3 +43,4 @@ obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
 obj-y += ftrtc011.o
+obj-y += ftdmac020.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 0c15e7d..b0d0ff6 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -209,6 +209,20 @@ a369soc_device_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
 /* Hour (Edge) */
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
+
+/* ftdmac020 */
+s-hdma[0] = sysbus_create_varargs(ftdmac020,
+   0x9030,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[15], /* TC */
+   s-pic[16], /* ERR */
+   NULL);
+s-hdma[1] = sysbus_create_varargs(ftdmac020,
+   0x9610,
+   s-pic[0],  /* ALL (NC in A369) */
+   s-pic[17], /* TC */
+   s-pic[18], /* ERR */
+   NULL);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftdmac020.c b/hw/arm/ftdmac020.c
new file mode 100644
index 000..1330d50
--- /dev/null
+++ b/hw/arm/ftdmac020.c
@@ -0,0 +1,599 @@
+/*
+ * QEMU model of the FTDMAC020 DMA Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ *
+ * Note: The FTDMAC020 decreasing address mode is not implemented.
+ */
+
+#include hw/sysbus.h
+#include sysemu/dma.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include faraday.h
+#include ftdmac020.h
+
+#define TYPE_FTDMAC020ftdmac020
+
+enum ftdmac020_irqpin {
+IRQ_ALL = 0,
+IRQ_TC,
+IRQ_ERR,
+};
+
+typedef struct Ftdmac020State Ftdmac020State;
+
+/**
+ * struct Ftdmac020LLD - hardware link list descriptor.
+ * @src: source physical address
+ * @dst: destination physical addr
+ * @next: phsical address to the next link list descriptor
+ * @ctrl: control field
+ * @size: transfer size
+ *
+ * should be word aligned
+ */
+typedef struct Ftdmac020LLD {
+uint32_t src;
+uint32_t dst;
+uint32_t next;
+uint32_t ctrl;
+uint32_t size;
+} Ftdmac020LLD;
+
+typedef struct Ftdmac020Chan {
+Ftdmac020State *chip;
+
+int id;
+int burst;
+int llp_cnt;
+int src_bw;
+int src_stride;
+int dst_bw;
+int dst_stride;
+
+/* HW register cache */
+uint32_t ccr;
+uint32_t cfg;
+uint32_t src;
+uint32_t dst;
+uint32_t llp;
+uint32_t len;
+} Ftdmac020Chan;
+
+typedef struct Ftdmac020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq[3];
+
+Ftdmac020Chan chan[8];
+qemu_irq  ack[16];
+uint32_t  req;
+
+int busy;/* Busy Channel ID */
+int bh_owner;
+QEMUBH *bh;
+DMAContext *dma;
+
+/* HW register cache */
+uint32_t tcisr;
+uint32_t eaisr;
+uint32_t tcsr;
+uint32_t easr;
+uint32_t cesr;
+uint32_t cbsr;
+uint32_t csr;
+uint32_t sync;
+} Ftdmac020State;
+
+#define FTDMAC020(obj) \
+OBJECT_CHECK(Ftdmac020State, obj, TYPE_FTDMAC020)
+
+static void ftdmac020_update_irq(Ftdmac020State *s)
+{
+uint32_t tc, err;
+
+/* 1. Checking TC interrupts */
+tc = s-tcisr  0xff;
+qemu_set_irq(s-irq[IRQ_TC], tc ? 1 : 0);
+
+/* 2. Checking Error/Abort interrupts */
+err = s-eaisr  0x00ff00ff;
+qemu_set_irq(s-irq[IRQ_ERR], err ? 1 : 0);
+
+/* 3. Checking interrupt summary (TC | Error | Abort) */
+qemu_set_irq(s-irq[IRQ_ALL], (tc || err) ? 1 : 0);
+}
+
+static void ftdmac020_chan_ccr_decode(Ftdmac020Chan *c)
+{
+uint32_t tmp;
+
+/* 1

[Qemu-devel] [PATCH v7 06/24] hw/arm: add FTPWMTMR010 timer support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTPWMTMR010 is an APB device which provides up to 8 independent timers.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   10 ++
 hw/arm/ftpwmtmr010.c  |  264 +
 hw/arm/ftpwmtmr010.h  |   31 ++
 4 files changed, 306 insertions(+)
 create mode 100644 hw/arm/ftpwmtmr010.c
 create mode 100644 hw/arm/ftpwmtmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0bbf838..bc18e22 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -40,3 +40,4 @@ obj-y += faraday_a369.o faraday_a369_soc.o faraday_a369_scu.o 
\
 obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
+obj-y += ftpwmtmr010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 46600d7..4ded777 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -167,6 +167,16 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTDDRII030\n);
 exit(1);
 }
+
+/* Timer */
+ds = qdev_create(NULL, ftpwmtmr010);
+qdev_prop_set_uint32(ds, freq, 66 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9230);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, s-pic[8]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftpwmtmr010.c b/hw/arm/ftpwmtmr010.c
new file mode 100644
index 000..cea7e76
--- /dev/null
+++ b/hw/arm/ftpwmtmr010.c
@@ -0,0 +1,264 @@
+/*
+ * Faraday FTPWMTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include ftpwmtmr010.h
+
+#define TYPE_FTPWMTMR010ftpwmtmr010
+#define TYPE_FTPWMTMR010_TIMER  ftpwmtmr010_timer
+
+typedef struct Ftpwmtmr010State Ftpwmtmr010State;
+
+typedef struct Ftpwmtmr010Timer {
+uint32_t ctrl;
+uint32_t cntb;
+int id;
+uint64_t timeout;
+uint64_t countdown;
+qemu_irq irq;
+QEMUTimer *qtimer;
+Ftpwmtmr010State *chip;
+} Ftpwmtmr010Timer;
+
+struct Ftpwmtmr010State {
+SysBusDevice busdev;
+
+MemoryRegion iomem;
+Ftpwmtmr010Timer timer[8];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+uint32_t stat;
+};
+
+#define FTPWMTMR010(obj) \
+OBJECT_CHECK(Ftpwmtmr010State, obj, TYPE_FTPWMTMR010)
+
+static uint64_t
+ftpwmtmr010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t ret = 0;
+
+switch (addr) {
+case REG_SR:
+ret = s-stat;
+break;
+case REG_REVR:
+ret = 0x;   /* Rev. 0.0.0 (no rev. id) */
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+return t-ctrl;
+case REG_TIMER_CNTB:
+return t-cntb;
+case REG_TIMER_CNTO:
+if ((t-ctrl  TIMER_CTRL_START)  (t-timeout  now)) {
+ret = (t-timeout - now) / s-step;
+}
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftpwmtmr010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftpwmtmr010State *s = FTPWMTMR010(opaque);
+Ftpwmtmr010Timer *t;
+int i;
+
+switch (addr) {
+case REG_SR:
+s-stat = ~((uint32_t)val);
+for (i = 0; i  8; ++i) {
+if (val  BIT(i)) {
+qemu_irq_lower(s-timer[i].irq);
+}
+}
+break;
+case REG_TIMER_BASE(1) ... REG_TIMER_BASE(8) + 0x0C:
+t = s-timer + (addr  4) - 1;
+switch (addr  0x0f) {
+case REG_TIMER_CTRL:
+t-ctrl = (uint32_t)val;
+if (t-ctrl  TIMER_CTRL_UPDATE) {
+t-countdown = (uint64_t)t-cntb * s-step;
+}
+if (t-ctrl  TIMER_CTRL_START) {
+t-timeout = t-countdown + qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-timeout);
+}
+break;
+case REG_TIMER_CNTB:
+t-cntb = (uint32_t)val;
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftpwmtmr010: undefined memory access

[Qemu-devel] [PATCH v7 15/24] hw: add WM8731 audio codec support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Wolfson WM8731 is a simple audio codec for embedded systems.
It has 2 input and 1 output ports:

** Input **
1. Linue-In
2. Microphone

** Output **
1. Headphone out

BTW it's based on hw/wm8750.c with 16-bit I2S support by default.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 default-configs/arm-softmmu.mak |1 +
 hw/Makefile.objs|1 +
 hw/wm8731.c |  505 +++
 3 files changed, 507 insertions(+)
 create mode 100644 hw/wm8731.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 68b2045..131f85b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_SD=y
 CONFIG_MAX7310=y
+CONFIG_WM8731=y
 CONFIG_WM8750=y
 CONFIG_TWL92230=y
 CONFIG_TSC2005=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index aafcac5..6fdaf41 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -168,6 +168,7 @@ common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
 common-obj-y += audio_codec.o
+common-obj-$(CONFIG_WM8731) += wm8731.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/wm8731.c b/hw/wm8731.c
new file mode 100644
index 000..1696690
--- /dev/null
+++ b/hw/wm8731.c
@@ -0,0 +1,505 @@
+/*
+ * WM8731 audio codec.
+ *
+ * base is wm8750.c
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw.h
+#include i2c.h
+#include audio_codec.h
+#include audio/audio.h
+
+#define IN_PORT_N   2
+#define OUT_PORT_N  1
+
+#define TYPE_WM8731 wm8731
+
+typedef struct WMRate {
+int adc;
+int adc_hz;
+int dac;
+int dac_hz;
+} WMRate;
+
+typedef struct WM8731State {
+AudioCodecState parent;
+
+uint8_t i2c_data[2];
+int i2c_len;
+QEMUSoundCard card;
+SWVoiceIn *adc_voice[IN_PORT_N];
+SWVoiceOut *dac_voice[OUT_PORT_N];
+void (*data_req)(void *, int, int);
+void *opaque;
+uint8_t data_in[4096];
+uint8_t data_out[4096];
+int idx_in, req_in;
+int idx_out, req_out;
+
+SWVoiceOut **out[2];
+uint8_t outvol[2];
+SWVoiceIn **in[2];
+uint8_t invol[2], inmute[2], mutemic;
+
+uint8_t mute;
+uint8_t power, format, active;
+const WMRate *rate;
+uint8_t rate_vmstate;
+int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
+} WM8731State;
+
+#define WM8731(obj) \
+OBJECT_CHECK(WM8731State, obj, TYPE_WM8731)
+
+#define WM8731_OUTVOL_TRANSFORM(x)  (x  1)
+#define WM8731_INVOL_TRANSFORM(x)   (x  3)
+
+static inline void wm8731_in_load(WM8731State *s)
+{
+if (s-idx_in + s-req_in = sizeof(s-data_in)) {
+return;
+}
+s-idx_in = audio_MAX(0, (int) sizeof(s-data_in) - s-req_in);
+AUD_read(*s-in[0], s-data_in + s-idx_in,
+ sizeof(s-data_in) - s-idx_in);
+}
+
+static inline void wm8731_out_flush(WM8731State *s)
+{
+int sent = 0;
+while (sent  s-idx_out) {
+sent += AUD_write(*s-out[0], s-data_out + sent, s-idx_out - sent)
+? 0 : s-idx_out;
+}
+s-idx_out = 0;
+}
+
+static void wm8731_audio_in_cb(void *opaque, int avail_b)
+{
+WM8731State *s = WM8731(opaque);
+s-req_in = avail_b;
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, avail_b  1);
+}
+
+static void wm8731_audio_out_cb(void *opaque, int free_b)
+{
+WM8731State *s = WM8731(opaque);
+
+if (s-idx_out = free_b) {
+s-idx_out = free_b;
+s-req_out = 0;
+wm8731_out_flush(s);
+} else {
+s-req_out = free_b - s-idx_out;
+}
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, s-req_in  1);
+}
+
+static const WMRate wm_rate_table[] = {
+{  256, 48000,  256, 48000 },/* SR: , BOSR: 0 */
+{  384, 48000,  384, 48000 },/* SR: , BOSR: 1 */
+{  256, 48000,  256,  8000 },/* SR: 0001, BOSR: 0 */
+{  384, 48000,  384,  8000 },/* SR: 0001, BOSR: 1 */
+{  256,  8000,  256, 48000 },/* SR: 0010, BOSR: 0 */
+{  384,  8000,  384, 48000 },/* SR: 0010, BOSR: 1 */
+{  256,  8000,  256,  8000 },/* SR: 0011, BOSR: 0 */
+{  384,  8000,  384,  8000 },/* SR: 0011, BOSR: 1 */
+{  256, 32000,  256, 32000 },/* SR: 0110, BOSR: 0 */
+{  384, 32000,  384, 32000 },/* SR: 0110, BOSR: 1 */
+{  128, 96000,  128, 96000 },/* SR: 0111, BOSR: 0 */
+{  192, 96000,  192, 96000 },/* SR: 0111, BOSR: 1 */
+{  256, 44100,  256, 44100 },/* SR: 1000, BOSR: 0 */
+{  384, 44100,  384, 44100 },/* SR: 1000, BOSR: 1 */
+{  256, 44100,  256,  8000 },/* SR: 1001, BOSR: 0 */
+{  384, 44100,  384,  8000 },/* SR: 1001, BOSR: 1 */
+{  256,  8000,  256, 44100 },/* SR

[Qemu-devel] [PATCH v7 07/24] hw/arm: add FTWDT010 watchdog timer support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTWDT010 is used to prevent system from infinite loop
while software gets trapped in the deadlock.

Under the normal operation, users should restart FTWDT010
at the regular intervals before counter counts down to 0.

If the counter does reach 0, FTWDT010 will try to reset
the system by generating one or a combination of signals,
system reset, system interrupt, and external interrupt.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   14 +++
 hw/arm/ftwdt010.c |  213 +
 hw/arm/ftwdt010.h |   35 
 4 files changed, 263 insertions(+)
 create mode 100644 hw/arm/ftwdt010.c
 create mode 100644 hw/arm/ftwdt010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bc18e22..bd330f2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -41,3 +41,4 @@ obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
+obj-y += ftwdt010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 4ded777..35549d8 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -68,6 +68,16 @@ static void a369soc_reset(DeviceState *ds)
 }
 
 static void
+a369soc_system_reset(void *opaque)
+{
+FaradaySoCState *s = FARADAY_SOC(opaque);
+
+if (s-cpu) {
+cpu_reset(CPU(s-cpu));
+}
+}
+
+static void
 a369soc_device_init(FaradaySoCState *s)
 {
 Error *local_errp = NULL;
@@ -177,6 +187,10 @@ a369soc_device_init(FaradaySoCState *s)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
+
+/* ftwdt010 */
+sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
+qemu_register_reset(a369soc_system_reset, s);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftwdt010.c b/hw/arm/ftwdt010.c
new file mode 100644
index 000..78245c7
--- /dev/null
+++ b/hw/arm/ftwdt010.c
@@ -0,0 +1,213 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/watchdog.h
+#include sysemu/sysemu.h
+#include qemu/timer.h
+
+#include faraday.h
+#include ftwdt010.h
+
+#define TYPE_FTWDT010   ftwdt010
+
+typedef struct Ftwdt010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+
+QEMUTimer *qtimer;
+
+uint64_t timeout;
+uint64_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+bool running;
+
+/* HW register cache */
+uint32_t load;
+uint32_t cr;
+uint32_t sr;
+} Ftwdt010State;
+
+#define FTWDT010(obj) \
+OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
+
+static uint64_t
+ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+uint32_t ret = 0;
+
+switch (addr) {
+case REG_COUNTER:
+if (s-cr  CR_EN) {
+ret = s-timeout - qemu_get_clock_ms(rt_clock);
+ret = MIN(s-load, ret * 100ULL / s-step);
+} else {
+ret = s-load;
+}
+break;
+case REG_LOAD:
+return s-load;
+case REG_CR:
+return s-cr;
+case REG_SR:
+return s-sr;
+case REG_REVR:
+return 0x00010601;  /* rev. 1.6.1 */
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+Ftwdt010State *s = FTWDT010(opaque);
+
+switch (addr) {
+case REG_LOAD:
+s-load = (uint32_t)val;
+break;
+case REG_RESTART:
+if ((s-cr  CR_EN)  (val == WDT_MAGIC)) {
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+}
+break;
+case REG_CR:
+s-cr = (uint32_t)val;
+if (s-cr  CR_EN) {
+if (s-running) {
+break;
+}
+s-running = true;
+s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
+s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
+qemu_mod_timer(s-qtimer, s-timeout);
+} else {
+s-running = false;
+qemu_del_timer(s-qtimer);
+}
+break;
+case REG_SCR:
+s-sr = ~(uint32_t)val;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+}
+
+static const

[Qemu-devel] [PATCH v7 22/24] hw/arm: add FTMAC110 10/100Mbps ethernet support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTMAC110 is an Ethernet controller that provides AHB master capability
and is in full compliance with the IEEE 802.3 10/100 Mbps specifications.
Its DMA controller handles all data transfers between system memory
and on-chip memories.

It supports half-word data transfer for Linux. However it has a weird DMA
alignment issue:

(1) Tx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: O.K

(2) Rx DMA Buffer Address:
1 bytes aligned: Invalid
2 bytes aligned: O.K
4 bytes aligned: Invalid (It means 0x0, 0x4, 0x8, 0xC are invalid)

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369.c |7 +
 hw/arm/ftmac110.c |  649 +
 hw/arm/ftmac110.h |  168 +
 5 files changed, 828 insertions(+)
 create mode 100644 hw/arm/ftmac110.c
 create mode 100644 hw/arm/ftmac110.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0920270..985cb0b 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -52,3 +52,4 @@ obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
 obj-y += fttsc010.o
 obj-y += ftsdc010.o
+obj-y += ftmac110.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 158fffc..85db025 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -62,4 +62,7 @@ void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 /* ftgmac100.c */
 void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
 
+/* ftmac110.c */
+void ftmac110_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index ef84a8f..05f4066 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -91,6 +91,13 @@ a369_board_init(QEMUMachineInitArgs *args)
  s-i2s[0]);
 }
 
+/* External AHB devices */
+
+/* Ethernet: FTMAC110 */
+if (nb_nics  1) {
+ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftmac110.c b/hw/arm/ftmac110.c
new file mode 100644
index 000..471c82c
--- /dev/null
+++ b/hw/arm/ftmac110.c
@@ -0,0 +1,649 @@
+/*
+ * QEMU model of the FTMAC110 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+/***/
+/*   FTMAC110 DMA design issue */
+/* Dante Su 2010.02.03 */
+/* */
+/* The DMA engine has a weird restriction that its Rx DMA engine   */
+/* accepts only 16-bits aligned address, 32-bits aligned is still  */
+/* invalid. However this restriction does not apply to Tx DMA. */
+/* Conclusion: */
+/* (1) Tx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: O.K (- u-boot ZeroCopy is possible)   */
+/* (2) Rx DMA Buffer Address:  */
+/* 1 bytes aligned: Invalid*/
+/* 2 bytes aligned: O.K*/
+/* 4 bytes aligned: Invalid*/
+/***/
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include faraday.h
+#include ftmac110.h
+
+#define TYPE_FTMAC110   ftmac110
+
+#define CFG_MAXFRMLEN   1536/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftmac110State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftmac110State;
+
+#define FTMAC110(obj) \
+OBJECT_CHECK(Ftmac110State, obj, TYPE_FTMAC110)
+
+#define MAC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static int ftmac110_mcast_hash(int len, const uint8_t *p)
+{
+#define CRCPOLY_LE 0xedb88320
+int i;
+uint32_t crc = 0x;
+
+while (len--) {
+crc ^= *p++;
+for (i = 0; i  8; i++) {
+crc = (crc  1) ^ ((crc  1) ? CRCPOLY_LE : 0);
+}
+}
+
+/* Reverse CRC32 and return MSB 6 bits only */
+return bitrev8(crc  24)  2;
+}
+
+static void
+ftmac110_read_rxdesc

[Qemu-devel] [PATCH v7 14/24] hw: add AudioCodecClass for wm87xx audio class abstration.

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/Makefile.objs   |1 +
 hw/arm/spitz.c |9 +++--
 hw/arm/z2.c|9 +++--
 hw/audio_codec.c   |   81 +++
 hw/audio_codec.h   |   56 +++
 hw/i2c.h   |9 -
 hw/marvell_88w8618_audio.c |   23 +++
 hw/wm8750.c|   91 ++--
 8 files changed, 211 insertions(+), 68 deletions(-)
 create mode 100644 hw/audio_codec.c
 create mode 100644 hw/audio_codec.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index eb7eb31..aafcac5 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -167,6 +167,7 @@ common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-y += audio_codec.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index f5832be..618968b 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -24,6 +24,7 @@
 #include ui/console.h
 #include block/block.h
 #include audio/audio.h
+#include hw/audio_codec.h
 #include hw/boards.h
 #include sysemu/blockdev.h
 #include hw/sysbus.h
@@ -739,9 +740,11 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
 qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
 /* .. and to the sound interface.  */
 cpu-i2s-opaque = wm;
-cpu-i2s-codec_out = wm8750_dac_dat;
-cpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, cpu-i2s-data_req, cpu-i2s);
+cpu-i2s-codec_out = audio_codec_dac_dat;
+cpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ cpu-i2s-data_req,
+ cpu-i2s);
 }
 
 static void spitz_akita_i2c_setup(PXA2xxState *cpu)
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index cbb6d80..bc11309 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -23,6 +23,7 @@
 #include sysemu/blockdev.h
 #include ui/console.h
 #include audio/audio.h
+#include hw/audio_codec.h
 #include exec/address-spaces.h
 
 #ifdef DEBUG_Z2
@@ -353,9 +354,11 @@ static void z2_init(QEMUMachineInitArgs *args)
 i2c_create_slave(bus, aer915, 0x55);
 wm = i2c_create_slave(bus, wm8750, 0x1b);
 mpu-i2s-opaque = wm;
-mpu-i2s-codec_out = wm8750_dac_dat;
-mpu-i2s-codec_in = wm8750_adc_dat;
-wm8750_data_req_set(wm, mpu-i2s-data_req, mpu-i2s);
+mpu-i2s-codec_out = audio_codec_dac_dat;
+mpu-i2s-codec_in = audio_codec_adc_dat;
+audio_codec_data_req_set(DEVICE(wm),
+ mpu-i2s-data_req,
+ mpu-i2s);
 
 qdev_connect_gpio_out(mpu-gpio, Z2_GPIO_LCD_CS,
 qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
diff --git a/hw/audio_codec.c b/hw/audio_codec.c
new file mode 100644
index 000..c62e51f
--- /dev/null
+++ b/hw/audio_codec.c
@@ -0,0 +1,81 @@
+/*
+ * Audio Codec Class
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include qdev.h
+#include i2c.h
+#include audio_codec.h
+
+void audio_codec_data_req_set(DeviceState *dev,
+  void (*data_req)(void *, int, int),
+  void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(dev);
+if (k-data_req_set) {
+k-data_req_set(dev, data_req, opaque);
+}
+}
+
+void audio_codec_dac_dat(void *opaque, uint32_t sample)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_dat) {
+k-dac_dat(opaque, sample);
+}
+}
+
+uint32_t audio_codec_adc_dat(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+uint32_t ret = 0;
+if (k-adc_dat) {
+ret = k-adc_dat(opaque);
+}
+return ret;
+}
+
+void *audio_codec_dac_buffer(void *opaque, int samples)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+void *ret = NULL;
+if (k-dac_buffer) {
+ret = k-dac_buffer(opaque, samples);
+}
+return ret;
+}
+
+void audio_codec_dac_commit(void *opaque)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-dac_commit) {
+k-dac_commit(opaque);
+}
+}
+
+void audio_codec_set_bclk_in(void *opaque, int new_hz)
+{
+AudioCodecClass *k = AUDIO_CODEC_GET_CLASS(opaque);
+if (k-set_bclk_in) {
+k-set_bclk_in(opaque, new_hz);
+}
+}
+
+static const TypeInfo audio_codec_info = {
+.name  = TYPE_AUDIO_CODEC,
+.parent= TYPE_I2C_SLAVE,
+.instance_size = sizeof(AudioCodecState),
+.abstract  = true,
+.class_size= sizeof(AudioCodecClass),
+};
+
+static void audio_codec_register_types(void)
+{
+type_register_static(audio_codec_info

[Qemu-devel] [PATCH v7 08/24] hw/arm: add FTRTC011 RTC timer support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

It provides separate second, minute, hour, and day counters. The second
counter is toggled each second, the minute counter is toggled each minute,
the hour counter is toggled each hour, and the day counter is toggled each day.

The FTRTC011 provides a programmable auto-alarm function. When the second
auto-alarm function is turned on, the RTC will automatically trigger an
interrupt each second. The automatic minute and hour alarms can be turned on
as well.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |   18 +++
 hw/arm/ftrtc011.c |  392 +
 hw/arm/ftrtc011.h |   53 ++
 4 files changed, 464 insertions(+)
 create mode 100644 hw/arm/ftrtc011.c
 create mode 100644 hw/arm/ftrtc011.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index bd330f2..b01da9d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -42,3 +42,4 @@ obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
 obj-y += ftwdt010.o
+obj-y += ftrtc011.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 35549d8..0c15e7d 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -191,6 +191,24 @@ a369soc_device_init(FaradaySoCState *s)
 /* ftwdt010 */
 sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
 qemu_register_reset(a369soc_system_reset, s);
+
+/* ftrtc011 */
+ds = qdev_create(NULL, ftrtc011);
+/* Setup QOM path for QTest */
+object_property_add_child(OBJECT(s),
+  ftrtc011,
+  OBJECT(ds),
+  NULL);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x9210);
+/* Alarm (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[42]);
+/* Second (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[43]);
+/* Minute (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[44]);
+/* Hour (Edge) */
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 4, s-pic[45]);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftrtc011.c b/hw/arm/ftrtc011.c
new file mode 100644
index 000..3c39c61
--- /dev/null
+++ b/hw/arm/ftrtc011.c
@@ -0,0 +1,392 @@
+/*
+ * QEMU model of the FTRTC011 RTC Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include ftrtc011.h
+
+enum ftrtc011_irqpin {
+IRQ_ALARM_LEVEL = 0,
+IRQ_ALARM_EDGE,
+IRQ_SEC,
+IRQ_MIN,
+IRQ_HOUR,
+IRQ_DAY,
+};
+
+#define TYPE_FTRTC011   ftrtc011
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Ftrtc011State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq[6];
+
+QEMUTimer *qtimer;
+int64_t rtc_base;
+int64_t rtc_start;
+
+/* HW register caches */
+uint32_t regs[CFG_REGSIZE];
+} Ftrtc011State;
+
+#define FTRTC011(obj) \
+OBJECT_CHECK(Ftrtc011State, obj, TYPE_FTRTC011)
+
+#define RTC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+/* Update interrupts.  */
+static void ftrtc011_update_irq(Ftrtc011State *s)
+{
+uint32_t mask = extract32(RTC_REG32(s, REG_CR), 1, 5)
+   RTC_REG32(s, REG_ISR);
+
+qemu_set_irq(s-irq[IRQ_ALARM_LEVEL], !!(mask  ISR_ALARM));
+
+if (mask) {
+if (mask  ISR_SEC) {
+qemu_irq_pulse(s-irq[IRQ_SEC]);
+}
+if (mask  ISR_MIN) {
+qemu_irq_pulse(s-irq[IRQ_MIN]);
+}
+if (mask  ISR_HOUR) {
+qemu_irq_pulse(s-irq[IRQ_HOUR]);
+}
+if (mask  ISR_DAY) {
+qemu_irq_pulse(s-irq[IRQ_DAY]);
+}
+if (mask  ISR_ALARM) {
+qemu_irq_pulse(s-irq[IRQ_ALARM_EDGE]);
+}
+}
+}
+
+static void ftrtc011_timer_rebase(Ftrtc011State *s)
+{
+int64_t ticks = get_ticks_per_sec();
+int64_t elapsed = RTC_REG32(s, REG_SEC)
++ (60LL * RTC_REG32(s, REG_MIN))
++ (3600LL * RTC_REG32(s, REG_HOUR))
++ (86400LL * RTC_REG32(s, REG_DAY));
+
+DPRINTF(rebase: now=%lld\n,
+qemu_get_clock_ns(rtc_clock) / 10LL);
+
+s-rtc_base  = elapsed;
+s-rtc_start = qemu_get_clock_ns(rtc_clock);
+/* adjust to the beginning of the current second */
+s-rtc_start = s-rtc_start - (s-rtc_start % ticks);
+}
+
+static void ftrtc011_timer_update(Ftrtc011State *s)
+{
+int64_t elapsed;
+uint8_t sec, min, hr;
+uint32_t day;
+
+/* check if RTC is enabled */
+if (!(RTC_REG32(s, REG_CR)  CR_EN)) {
+return;
+}
+
+DPRINTF(update: now=%lld\n,
+qemu_get_clock_ns(rtc_clock) / 10LL);
+/*
+ * 2013.03.11 Kuo-Jung Su
+ * Under QTest

[Qemu-devel] [PATCH v7 17/24] qemu/bitops.h: add the bit ordering reversal functions

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 include/qemu/bitops.h |   59 -
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index affcc96..64cbb04 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2010 Corentin Chary corentin.ch...@gmail.com
  *
- * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
+ * Mostly inspired by (stolen from) linux/bitmap.h, linux/bitops.h
+ * and linux/bitrev.h
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  * See the COPYING.LIB file in the top-level directory.
@@ -273,4 +274,60 @@ static inline uint64_t deposit64(uint64_t value, int 
start, int length,
 return (value  ~mask) | ((fieldval  start)  mask);
 }
 
+/**
+ * bitrev8:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 8 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint8_t bitrev8(uint8_t value)
+{
+value = (value  0xF0)  4 | (value  0x0F)  4;
+value = (value  0xCC)  2 | (value  0x33)  2;
+value = (value  0xAA)  1 | (value  0x55)  1;
+return value;
+}
+
+/**
+ * bitrev16:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 16 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint16_t bitrev16(uint16_t value)
+{
+return (bitrev8(value  0xff)  8) | bitrev8(value  8);
+}
+
+/**
+ * bitrev32:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 32 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint32_t bitrev32(uint32_t value)
+{
+return (bitrev16(value  0x)  16) | bitrev16(value  16);
+}
+
+/**
+ * bitrev64:
+ * @value: the value to reverse bit ordering from
+ *
+ * Reverse the 64 bit input @value
+ *
+ * Returns: the input @value with reversed bit ordering
+ */
+static inline uint64_t bitrev64(uint64_t value)
+{
+return ((uint64_t)bitrev32(value  0xULL)  32)
+| (uint64_t)bitrev32(value  32);
+}
+
 #endif
-- 
1.7.9.5




[Qemu-devel] [PATCH v7 24/24] hw/arm: add FTSPI020 SPI flash controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSPI020 is an integrated SPI Flash controller
which supports up to 4 flash chips.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |   16 +++
 hw/arm/ftspi020.c |  340 +
 hw/arm/ftspi020.h |   81 
 4 files changed, 438 insertions(+)
 create mode 100644 hw/arm/ftspi020.c
 create mode 100644 hw/arm/ftspi020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index d0ce0e2..996c606 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -54,3 +54,4 @@ obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
 obj-y += fttmr010.o
+obj-y += ftspi020.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 751a5e4..52e8e84 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -106,6 +106,22 @@ a369_board_init(QEMUMachineInitArgs *args)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
 
+/* SPI: FTSPI020 */
+ds = sysbus_create_simple(ftspi020, 0xC000, s-pic[4]);
+s-spi_fl[0] = ds;
+
+/* Attach the spi flash to ftspi020.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi_fl[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi_fl[0]), i + 1, cs_line);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftspi020.c b/hw/arm/ftspi020.c
new file mode 100644
index 000..d61cca7
--- /dev/null
+++ b/hw/arm/ftspi020.c
@@ -0,0 +1,340 @@
+/*
+ * Faraday FTSPI020 Flash Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include sysemu/sysemu.h
+#include hw/sysbus.h
+#include hw/ssi.h
+
+#include ftspi020.h
+
+#define TYPE_FTSPI020   ftspi020
+
+typedef struct Ftspi020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+SSIBus *spi;
+qemu_irq *cs_lines;
+
+int wip;/* SPI Flash Status: Write In Progress BIT shift */
+
+/* HW register caches */
+uint32_t cmd[4];
+uint32_t ctrl;
+uint32_t timing;
+uint32_t icr;
+uint32_t isr;
+uint32_t rdsr;
+} Ftspi020State;
+
+#define FTSPI020(obj) \
+OBJECT_CHECK(Ftspi020State, obj, TYPE_FTSPI020)
+
+static void ftspi020_update_irq(Ftspi020State *s)
+{
+qemu_set_irq(s-irq, s-isr ? 1 : 0);
+}
+
+static void ftspi020_handle_ack(void *opaque, int line, int level)
+{
+Ftspi020State *s = FTSPI020(opaque);
+
+if (!(s-icr  ICR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-cmd[2]) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static int ftspi020_do_command(Ftspi020State *s)
+{
+uint32_t cs   = extract32(s-cmd[3],  8, 2);
+uint32_t cmd  = extract32(s-cmd[3], 24, 8);
+uint32_t ilen = extract32(s-cmd[1], 24, 2);
+uint32_t alen = extract32(s-cmd[1],  0, 3);
+uint32_t dcyc = extract32(s-cmd[1], 16, 8);
+
+if (dcyc % 8) {
+fprintf(stderr, ftspi020: bad dummy clock (%u) to QEMU\n, dcyc);
+exit(1);
+}
+
+/* activate the spi flash */
+qemu_set_irq(s-cs_lines[cs], 0);
+
+/* if it's a SPI flash READ_STATUS command */
+if ((s-cmd[3]  (CMD3_RDSR | CMD3_WRITE)) == CMD3_RDSR) {
+uint32_t rdsr;
+
+ssi_transfer(s-spi, cmd);
+do {
+rdsr = ssi_transfer(s-spi, 0x00);
+if (s-cmd[3]  CMD3_RDSR_SW) {
+break;
+}
+} while (rdsr  (1  s-wip));
+s-rdsr = rdsr;
+} else {
+/* otherwise */
+int i;
+
+ilen = MIN(ilen, 2);
+alen = MIN(alen, 4);
+
+/* command cycles */
+for (i = 0; i  ilen; ++i) {
+ssi_transfer(s-spi, cmd);
+}
+/* address cycles */
+for (i = alen - 1; i = 0; --i) {
+ssi_transfer(s-spi, extract32(s-cmd[0], i * 8, 8));
+}
+/* dummy cycles */
+for (i = 0; i  (dcyc  3); ++i) {
+ssi_transfer(s-spi, 0x00);
+}
+}
+
+if (!s-cmd[2]) {
+qemu_set_irq(s-cs_lines[cs], 1);
+} else if (s-icr  ICR_DMA) {
+qemu_set_irq(s-req, 1);
+}
+
+if (s-cmd[3]  CMD3_INTR) {
+s-isr |= ISR_CMDFIN;
+}
+ftspi020_update_irq(s);
+
+return 0;
+}
+
+static void ftspi020_chip_reset(Ftspi020State *s)
+{
+int i;
+
+for (i = 0; i  4; ++i) {
+s-cmd[i] = 0;
+}
+s-wip = 0;
+s-ctrl = 0;
+s-timing = 0;
+s-icr = 0;
+s-isr = 0;
+s-rdsr = 0;
+
+qemu_set_irq(s-irq, 0

[Qemu-devel] [PATCH v7 16/24] hw/arm: add FTSSP010 multi-function controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSSP010 is a multi-function synchronous serial port interface
controller which supports SSP, SPI, I2S, AC97 and SPDIF.

Only I2S and SPI protocol have been implemented in this patch.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369.c |   31 +++
 hw/arm/faraday_a369_soc.c |   17 ++
 hw/arm/ftssp010.c |  501 +
 hw/arm/ftssp010.h |   98 +
 6 files changed, 651 insertions(+)
 create mode 100644 hw/arm/ftssp010.c
 create mode 100644 hw/arm/ftssp010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 63ba519..9cb135a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -47,3 +47,4 @@ obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
 obj-y += fti2c010.o
+obj-y += ftssp010.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 86cc1ff..6ca88e4 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -56,4 +56,7 @@ typedef struct FaradaySoCState {
 #define FARADAY_SOC(obj) \
 OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
 
+/* ftssp010.c */
+void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
+
 #endif
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index a13e946..ef84a8f 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -11,6 +11,7 @@
 #include hw/arm-misc.h
 #include hw/devices.h
 #include hw/i2c.h
+#include hw/audio_codec.h
 #include hw/boards.h
 #include hw/ssi.h
 #include net/net.h
@@ -23,6 +24,7 @@
 static void
 a369_board_init(QEMUMachineInitArgs *args)
 {
+int i, nr_flash;
 DeviceState *ds;
 FaradaySoCState *s;
 DriveInfo *dinfo;
@@ -60,6 +62,35 @@ a369_board_init(QEMUMachineInitArgs *args)
 exit(1);
 }
 
+/* Attach the spi flash to ftssp010.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi[0]), i + 1, cs_line);
+}
+
+/* Attach the wm8731 to fti2c010.0  ftssp010.0 */
+for (i = 0; i  1; ++i) {
+i2c_bus *i2c = (i2c_bus *)qdev_get_child_bus(s-i2c[0], i2c);
+ds = i2c_create_slave(i2c, wm8731, 0x1B);
+object_property_set_link(OBJECT(s-i2s[0]),
+ OBJECT(ds),
+ codec,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set codec link for FTSSP010\n);
+exit(1);
+}
+audio_codec_data_req_set(ds,
+ ftssp010_i2s_data_req,
+ s-i2s[0]);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 07fe41d..16fa1e3 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -247,6 +247,23 @@ a369soc_device_init(FaradaySoCState *s)
 s-i2c[0] = ds;
 ds = sysbus_create_simple(fti2c010, 0x92A0, s-pic[52]);
 s-i2c[1] = ds;
+
+/* ftssp010 */
+ds = sysbus_create_simple(ftssp010, 0x9270, s-pic[49]);
+s-spi[0] = ds;
+s-i2s[0] = ds;
+
+/* ftssp010 - DMA (Tx) */
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-pdma[0], 7);
+qdev_connect_gpio_out(s-pdma[0], 7, ack);
+qdev_connect_gpio_out(ds, 0, req);
+
+/* ftssp010 - DMA (Rx) */
+ack = qdev_get_gpio_in(ds, 1);
+req = qdev_get_gpio_in(s-pdma[0], 8);
+qdev_connect_gpio_out(s-pdma[0], 8, ack);
+qdev_connect_gpio_out(ds, 1, req);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftssp010.c b/hw/arm/ftssp010.c
new file mode 100644
index 000..51b43e8
--- /dev/null
+++ b/hw/arm/ftssp010.c
@@ -0,0 +1,501 @@
+/*
+ * QEMU model of the FTSSP010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include sysemu/sysemu.h
+#include qemu/fifo8.h
+#include hw/i2c.h
+#include hw/audio_codec.h
+#include hw/ssi.h
+
+#include faraday.h
+#include ftssp010.h
+
+#define CFG_FIFO_DEPTH  16
+
+#define TYPE_FTSSP010   ftssp010
+
+typedef struct Ftssp010State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+SSIBus *spi;
+AudioCodecState *codec;
+
+uint8_t num_cs;
+qemu_irq *cs_lines;
+
+Fifo8 rx_fifo;
+Fifo8 tx_fifo;
+
+uint8_t tx_thres;
+uint8_t rx_thres;
+
+int busy;
+uint8_t bw;
+
+/* DMA hardware handshake */
+qemu_irq req[2];/* 0 - Tx, 1 - Rx */
+
+/* HW register caches */
+
+uint32_t cr0;
+uint32_t

[Qemu-devel] [PATCH v7 18/24] hw/arm: add FTGMAC100 1Gbps ethernet support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTGMAC100 Ethernet controller has a DMA engine which handles
all data transfers between the system memory and on-chip memories.
Its DMA engine supports both 16-bits and 32-bits alignment,
and thus make it possible to support zero-copy transfer at both
Linux and WINCE.

It also has 802.1Q VLAN tagging support for both insertion and removal.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday.h  |3 +
 hw/arm/faraday_a369_soc.c |5 +
 hw/arm/ftgmac100.c|  696 +
 hw/arm/ftgmac100.h|  239 
 5 files changed, 944 insertions(+)
 create mode 100644 hw/arm/ftgmac100.c
 create mode 100644 hw/arm/ftgmac100.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9cb135a..a6a9a0f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -48,3 +48,4 @@ obj-y += ftapbbrg020.o
 obj-y += ftnandc021.o
 obj-y += fti2c010.o
 obj-y += ftssp010.o
+obj-y += ftgmac100.o
diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
index 6ca88e4..158fffc 100644
--- a/hw/arm/faraday.h
+++ b/hw/arm/faraday.h
@@ -59,4 +59,7 @@ typedef struct FaradaySoCState {
 /* ftssp010.c */
 void ftssp010_i2s_data_req(void *opaque, int tx, int rx);
 
+/* ftgmac100.c */
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
 #endif
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 16fa1e3..ea97e19 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -264,6 +264,11 @@ a369soc_device_init(FaradaySoCState *s)
 req = qdev_get_gpio_in(s-pdma[0], 8);
 qdev_connect_gpio_out(s-pdma[0], 8, ack);
 qdev_connect_gpio_out(ds, 1, req);
+
+/* ftgmac100 */
+if (nb_nics  0) {
+ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
+}
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftgmac100.c b/hw/arm/ftgmac100.c
new file mode 100644
index 000..80fdb0d
--- /dev/null
+++ b/hw/arm/ftgmac100.c
@@ -0,0 +1,696 @@
+/*
+ * QEMU model of the FTGMAC100 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+#include sysemu/dma.h
+#include net/net.h
+
+#include faraday.h
+#include ftgmac100.h
+
+#define TYPE_FTGMAC100  ftgmac100
+
+#define CFG_MAXFRMLEN   9220/* Max. frame length */
+#define CFG_REGSIZE (0x100 / 4)
+
+typedef struct Ftgmac100State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+QEMUBH *bh;
+qemu_irq irq;
+NICState *nic;
+NICConf conf;
+DMAContext *dma;
+QEMUTimer *qtimer;
+
+bool phycr_rd;
+
+struct {
+uint8_t  buf[CFG_MAXFRMLEN];
+uint32_t len;
+} txbuff;
+
+uint32_t hptx_idx;
+uint32_t tx_idx;
+uint32_t rx_idx;
+
+/* HW register cache */
+uint32_t regs[CFG_REGSIZE];
+} Ftgmac100State;
+
+#define FTGMAC100(obj) \
+OBJECT_CHECK(Ftgmac100State, obj, TYPE_FTGMAC100)
+
+#define MAC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static int ftgmac100_mcast_hash(Ftgmac100State *s, const uint8_t *data)
+{
+#define CRCPOLY_BE0x04c11db7
+int i, len;
+uint32_t crc = 0x;
+
+len = (MAC_REG32(s, REG_MACCR)  MACCR_GMODE) ? 5 : 6;
+
+while (len--) {
+uint32_t c = *(data++);
+for (i = 0; i  8; ++i) {
+crc = (crc  1) ^ crc  31) ^ c)  0x01) ? CRCPOLY_BE : 0);
+c = 1;
+}
+}
+crc = ~crc;
+
+/* Reverse CRC32 and return MSB 6 bits only */
+return bitrev8(crc  24)  2;
+}
+
+static void
+ftgmac100_read_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+if (addr  0x0f) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: Tx desc is not 16-byte aligned!\n
+ It's fine in QEMU but the real HW would panic.\n);
+}
+
+dma_memory_read(s-dma, addr, desc, sizeof(*desc));
+
+for (i = 0; i  sizeof(*desc); i += 4) {
+*p = le32_to_cpu(*p);
+}
+
+if (desc-buf  0x01) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: tx buffer is not 16-bit aligned!\n);
+}
+}
+
+static void
+ftgmac100_write_txdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100TXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+for (i = 0; i  sizeof(*desc); i += 4) {
+*p = cpu_to_le32(*p);
+}
+
+dma_memory_write(s-dma, addr, desc, sizeof(*desc));
+}
+
+static void
+ftgmac100_read_rxdesc(Ftgmac100State *s, hwaddr addr, Ftgmac100RXD *desc)
+{
+int i;
+uint32_t *p = (uint32_t *)desc;
+
+if (addr  0x0f) {
+qemu_log_mask(LOG_GUEST_ERROR,
+ ftgmac100: Rx desc is not 16-byte aligned!\n
+ It's fine in QEMU but the real HW would panic.\n

[Qemu-devel] [PATCH v7 21/24] hw/arm: add FTSDC010 MMC/SD controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTSDC010 is a simple MMC/SD host controller and
many of its registers are similar to Arm PrimeCell PL181.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |7 +
 hw/arm/ftsdc010.c |  358 +
 hw/arm/ftsdc010.h |   90 
 4 files changed, 456 insertions(+)
 create mode 100644 hw/arm/ftsdc010.c
 create mode 100644 hw/arm/ftsdc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9fdefc8..0920270 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -51,3 +51,4 @@ obj-y += ftssp010.o
 obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
 obj-y += fttsc010.o
+obj-y += ftsdc010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 386a1a8..1240ff1 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -282,6 +282,13 @@ a369soc_device_init(FaradaySoCState *s)
 
 /* fttsc010 */
 sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
+
+/* ftsdc010 */
+ds = sysbus_create_simple(ftsdc010, 0x9060, s-pic[39]);
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 13);
+qdev_connect_gpio_out(s-hdma[0], 13, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftsdc010.c b/hw/arm/ftsdc010.c
new file mode 100644
index 000..40dff64
--- /dev/null
+++ b/hw/arm/ftsdc010.c
@@ -0,0 +1,358 @@
+/*
+ * QEMU model of the FTSDC010 MMC/SD Host Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/sd.h
+#include sysemu/sysemu.h
+#include sysemu/blockdev.h
+
+#include faraday.h
+#include ftsdc010.h
+
+#define TYPE_FTSDC010   ftsdc010
+
+typedef struct Ftsdc010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+SDState *card;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint32_t datacnt;
+
+/* HW register cache */
+uint32_t cmd;
+uint32_t arg;
+uint32_t rsp[4];
+uint32_t rspcmd;
+uint32_t dcr;
+uint32_t dtr;
+uint32_t dlr;
+uint32_t status;
+uint32_t ier;
+uint32_t pwr;
+uint32_t clk;
+} Ftsdc010State;
+
+#define FTSDC010(obj) \
+OBJECT_CHECK(Ftsdc010State, obj, TYPE_FTSDC010)
+
+static void ftsdc010_update_irq(Ftsdc010State *s)
+{
+qemu_set_irq(s-irq, !!(s-ier  s-status));
+}
+
+static void ftsdc010_handle_ack(void *opaque, int line, int level)
+{
+Ftsdc010State *s = FTSDC010(opaque);
+
+if (!(s-dcr  DCR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static void ftsdc010_send_command(Ftsdc010State *s)
+{
+SDRequest request;
+uint8_t response[16];
+int rlen;
+
+request.cmd = s-cmd  CMD_IDX;
+request.arg = s-arg;
+
+rlen = sd_do_command(s-card, request, response);
+if (rlen  0) {
+goto error;
+}
+if (s-cmd  CMD_WAIT_RSP) {
+#define RWORD(n) ((response[n]  24) | (response[n + 1]  16) \
+  | (response[n + 2]  8) | response[n + 3])
+if (rlen == 0 || (rlen == 4  (s-cmd  CMD_LONG_RSP))) {
+goto error;
+}
+if (rlen != 4  rlen != 16) {
+goto error;
+}
+if (rlen == 4) {
+s-rsp[0] = RWORD(0);
+s-rsp[1] = s-rsp[2] = s-rsp[3] = 0;
+} else {
+s-rsp[3] = RWORD(0);
+s-rsp[2] = RWORD(4);
+s-rsp[1] = RWORD(8);
+s-rsp[0] = RWORD(12)  ~1;
+}
+s-rspcmd  = (s-cmd  CMD_IDX);
+s-rspcmd |= (s-cmd  CMD_APP) ? RSP_CMDAPP : 0;
+s-status |= SR_RSP;
+#undef RWORD
+} else {
+s-status |= SR_CMD;
+}
+
+if ((s-dcr  DCR_DMA)  s-datacnt) {
+qemu_set_irq(s-req, 1);
+}
+
+return;
+
+error:
+s-status |= SR_RSP_TIMEOUT;
+}
+
+static void ftsdc010_chip_reset(Ftsdc010State *s)
+{
+s-cmd = 0;
+s-arg = 0;
+s-rsp[0] = 0;
+s-rsp[1] = 0;
+s-rsp[2] = 0;
+s-rsp[3] = 0;
+s-rspcmd = 0;
+s-dcr = 0;
+s-dtr = 0;
+s-dlr = 0;
+s-datacnt = 0;
+s-status = ~(SR_CARD_REMOVED | SR_WPROT);
+s-status |= SR_TXRDY | SR_RXRDY;
+s-ier = 0;
+s-pwr = 0;
+s-clk = 0;
+}
+
+static uint64_t ftsdc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+Ftsdc010State *s = FTSDC010(opaque);
+uint32_t i, ret = 0;
+
+switch (addr) {
+case REG_SR:
+return s-status;
+case REG_DR:
+if (!(s-dcr  DCR_WR)  s-datacnt  sd_data_ready(s-card)) {
+for (i = 0; i  4  s-datacnt; i++, s-datacnt--) {
+ret = deposit32(ret, i * 8, 8, sd_read_data(s-card));
+}
+if (!s-datacnt

[Qemu-devel] [PATCH v7 19/24] hw/arm: add FTLCDC200 LCD controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTLCDC200 Color LCD controller performs translation of
pixel-coded data into the required formats and timings to
drive a variety of single/dual mono and color LCDs.

Depending on the LCD type and mode, the unpacked data can represent:
   1. an actual true display gray or color value
   2. an address to a 256 x 16 bit wide palette RAM gray or color value.

The FTLCDC200 generates 4 individual interrupts for:
   1. DMA FIFO underflow
   2. base address update
   3. vertical status
   4. bus error.

There is also a single combined interrupt that is raised when any of
the individual interrupts become active.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs|1 +
 hw/arm/faraday_a369_soc.c   |   10 +
 hw/arm/ftlcdc200.c  |  513 +++
 hw/arm/ftlcdc200.h  |  112 ++
 hw/arm/ftlcdc200_template.h |  439 
 5 files changed, 1075 insertions(+)
 create mode 100644 hw/arm/ftlcdc200.c
 create mode 100644 hw/arm/ftlcdc200.h
 create mode 100644 hw/arm/ftlcdc200_template.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index a6a9a0f..6f3bf2d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -49,3 +49,4 @@ obj-y += ftnandc021.o
 obj-y += fti2c010.o
 obj-y += ftssp010.o
 obj-y += ftgmac100.o
+obj-y += ftlcdc200.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index ea97e19..da89dfa 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -269,6 +269,16 @@ a369soc_device_init(FaradaySoCState *s)
 if (nb_nics  0) {
 ftgmac100_init(nd_table[0], 0x90c0, s-pic[32]);
 }
+
+/* ftlcdc200 */
+sysbus_create_varargs(ftlcdc200,
+  0x94a0,
+  s-pic[0],  /* ALL (NC in A369) */
+  s-pic[25], /* VSTATUS */
+  s-pic[24], /* Base Address Update */
+  s-pic[23], /* FIFO Under-Run */
+  s-pic[22], /* AHB Bus Error */
+  NULL);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftlcdc200.c b/hw/arm/ftlcdc200.c
new file mode 100644
index 000..17d79d1
--- /dev/null
+++ b/hw/arm/ftlcdc200.c
@@ -0,0 +1,513 @@
+/*
+ * Faraday FTLCDC200 Color LCD Controller
+ *
+ * base is pl110.c
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under the GNU LGPL
+ */
+
+#include hw/sysbus.h
+#include hw/framebuffer.h
+#include ui/console.h
+#include ui/pixel_ops.h
+
+#include faraday.h
+#include ftlcdc200.h
+
+enum ftlcdc200_irqpin {
+IRQ_ALL = 0,
+IRQ_VSTATUS,
+IRQ_BASEUPT,
+IRQ_FIFOUR,
+IRQ_BUSERR,
+};
+
+enum ftlcdc200_bppmode {
+BPP_1 = 0,
+BPP_2,
+BPP_4,
+BPP_8,
+BPP_16,
+BPP_32,
+BPP_16_565,
+BPP_12,
+};
+
+#define TYPE_FTLCDC200  ftlcdc200
+
+typedef struct Ftlcdc200State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+DisplayState *ds;
+qemu_irq irq[5];
+int cols;
+int rows;
+enum ftlcdc200_bppmode bpp;
+int invalidate;
+uint32_t palette[256];
+uint32_t raw_palette[128];
+
+/* hw register caches */
+uint32_t fer;   /* function enable register */
+uint32_t ppr;   /* panel pixel register */
+uint32_t ier;   /* interrupt enable register */
+uint32_t isr;   /* interrupt status register */
+uint32_t sppr;  /* serail panel pixel register */
+
+uint32_t fb[4]; /* frame buffer base address register */
+uint32_t ht;/* horizontal timing control register */
+uint32_t vt0;   /* vertital timing control register 0 */
+uint32_t vt1;   /* vertital timing control register 1 */
+uint32_t pol;   /* polarity */
+
+} Ftlcdc200State;
+
+#define FTLCDC200(obj) \
+OBJECT_CHECK(Ftlcdc200State, obj, TYPE_FTLCDC200)
+
+static const VMStateDescription vmstate_ftlcdc200 = {
+.name = TYPE_FTLCDC200,
+.version_id = 2,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_INT32(cols, Ftlcdc200State),
+VMSTATE_INT32(rows, Ftlcdc200State),
+VMSTATE_UINT32(bpp, Ftlcdc200State),
+VMSTATE_INT32(invalidate, Ftlcdc200State),
+VMSTATE_UINT32_ARRAY(palette, Ftlcdc200State, 256),
+VMSTATE_UINT32_ARRAY(raw_palette, Ftlcdc200State, 128),
+VMSTATE_UINT32(fer, Ftlcdc200State),
+VMSTATE_UINT32(ppr, Ftlcdc200State),
+VMSTATE_UINT32(ier, Ftlcdc200State),
+VMSTATE_UINT32(isr, Ftlcdc200State),
+VMSTATE_UINT32(sppr, Ftlcdc200State),
+VMSTATE_UINT32_ARRAY(fb, Ftlcdc200State, 4),
+VMSTATE_UINT32(ht, Ftlcdc200State),
+VMSTATE_UINT32(vt0, Ftlcdc200State),
+VMSTATE_UINT32(vt1, Ftlcdc200State),
+VMSTATE_UINT32(pol, Ftlcdc200State),
+VMSTATE_END_OF_LIST()
+}
+};
+
+#define BITS

[Qemu-devel] [PATCH v7 23/24] hw/arm: add FTTMR010 timer support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTMR010 provides three independent sets of sub-timers.
Two match registers are provided for each sub-timer, whenever
the value of the match registers equals any one value of the
sub-timers, the timer interrupt will be immediately triggered.
And it would also issue an interrupt when an overflow occurs.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |8 +
 hw/arm/fttmr010.c |  451 +
 hw/arm/fttmr010.h |   41 +
 4 files changed, 501 insertions(+)
 create mode 100644 hw/arm/fttmr010.c
 create mode 100644 hw/arm/fttmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 985cb0b..d0ce0e2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -53,3 +53,4 @@ obj-y += ftlcdc200.o
 obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
+obj-y += fttmr010.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 05f4066..751a5e4 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -98,6 +98,14 @@ a369_board_init(QEMUMachineInitArgs *args)
 ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
 }
 
+/* Timer: FTTMR010 */
+ds = qdev_create(NULL, fttmr010);
+qdev_prop_set_uint32(ds, freq, 33 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0xC020);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/fttmr010.c b/hw/arm/fttmr010.c
new file mode 100644
index 000..f72a1b9
--- /dev/null
+++ b/hw/arm/fttmr010.c
@@ -0,0 +1,451 @@
+/*
+ * Faraday FTTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include fttmr010.h
+
+#define TYPE_FTTMR010   fttmr010
+#define TYPE_FTTMR010_TIMER fttmr010_timer
+
+typedef struct Fttmr010State Fttmr010State;
+
+typedef struct Fttmr010Timer {
+int id;
+int up;
+Fttmr010State *chip;
+qemu_irq irq;
+QEMUTimer *qtimer;
+uint64_t start;
+uint32_t intr_match1:1;
+uint32_t intr_match2:1;
+
+/* HW register caches */
+uint64_t counter;
+uint64_t reload;
+uint32_t match1;
+uint32_t match2;
+
+} Fttmr010Timer;
+
+struct Fttmr010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+Fttmr010Timer timer[3];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+
+/* HW register caches */
+uint32_t cr;
+uint32_t isr;
+uint32_t imr;
+};
+
+#define FTTMR010(obj) \
+OBJECT_CHECK(Fttmr010State, obj, TYPE_FTTMR010)
+
+static void fttmr010_timer_restart(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t interval;
+int pending = 0;
+
+t-intr_match1 = 0;
+t-intr_match2 = 0;
+
+/* check match1 */
+if (t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (!t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (t-match1 == t-counter) {
+s-isr |= ISR_MATCH1(t-id);
+++pending;
+}
+
+/* check match2 */
+if (t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (!t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (t-match2 == t-counter) {
+s-isr |= ISR_MATCH2(t-id);
+++pending;
+}
+
+/* determine delay interval */
+if (t-up) {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = MIN(t-match1, t-match2) - t-counter;
+} else if (t-match1  t-counter) {
+interval = t-match1 - t-counter;
+} else if (t-match2  t-reload) {
+interval = t-match2 - t-counter;
+} else {
+interval = 0xULL - t-counter;
+}
+} else {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = t-counter - MAX(t-match1, t-match2);
+} else if (t-match1  t-reload) {
+interval = t-counter - t-match1;
+} else if (t-match2  t-reload) {
+interval = t-counter - t-match2;
+} else {
+interval = t-counter;
+}
+}
+
+if (pending) {
+qemu_irq_pulse(s-irq);
+qemu_irq_pulse(t-irq);
+}
+t-start = qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-start + interval * s-step);
+}
+
+static uint64_t fttmr010_update_counter(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t elapsed;
+int pending = 0;
+
+if (s-cr  CR_TMR_EN(t-id)) {
+/* get elapsed time

[Qemu-devel] [PATCH v7 20/24] hw/arm: add FTTSC010 touchscreen controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTTSC010 provides two operation modes to sample
the analog input voltage.

  1. The manual operation mode needs to program
 and control the panel drivers by software
 step-by-step for the x-y position measurement.

  2. The auto-scan mode provides a periodic sampling
 method to convert the analog input.

This patch only implements the auto-scan mode.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369_soc.c |3 +
 hw/arm/fttsc010.c |  264 +
 hw/arm/fttsc010.h |   39 +++
 4 files changed, 307 insertions(+)
 create mode 100644 hw/arm/fttsc010.c
 create mode 100644 hw/arm/fttsc010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6f3bf2d..9fdefc8 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -50,3 +50,4 @@ obj-y += fti2c010.o
 obj-y += ftssp010.o
 obj-y += ftgmac100.o
 obj-y += ftlcdc200.o
+obj-y += fttsc010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index da89dfa..386a1a8 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -279,6 +279,9 @@ a369soc_device_init(FaradaySoCState *s)
   s-pic[23], /* FIFO Under-Run */
   s-pic[22], /* AHB Bus Error */
   NULL);
+
+/* fttsc010 */
+sysbus_create_simple(fttsc010, 0x9240, s-pic[19]);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/fttsc010.c b/hw/arm/fttsc010.c
new file mode 100644
index 000..44c43e0
--- /dev/null
+++ b/hw/arm/fttsc010.c
@@ -0,0 +1,264 @@
+/*
+ * Faraday FTTSC010 emulator.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include hw/devices.h
+#include ui/console.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include fttsc010.h
+
+#define X_AXIS_DMAX 3470
+#define X_AXIS_MIN  290
+#define Y_AXIS_DMAX 3450
+#define Y_AXIS_MIN  200
+
+#define ADS_XPOS(x, y)  \
+(X_AXIS_MIN + ((X_AXIS_DMAX * (x))  15))
+#define ADS_YPOS(x, y)  \
+(Y_AXIS_MIN + ((Y_AXIS_DMAX * (y))  15))
+#define ADS_Z1POS(x, y) \
+(8)
+#define ADS_Z2POS(x, y) \
+((1600 + ADS_XPOS(x, y)) * ADS_Z1POS(x, y) / ADS_XPOS(x, y))
+
+#define TYPE_FTTSC010   fttsc010
+
+#define CFG_REGSIZE (0x3c / 4)
+
+typedef struct Fttsc010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+uint64_t interval;
+QEMUTimer *qtimer;
+
+int x, y;
+int z1, z2;
+uint32_t freq;
+
+/* HW registers */
+uint32_t regs[CFG_REGSIZE];
+} Fttsc010State;
+
+#define FTTSC010(obj) \
+OBJECT_CHECK(Fttsc010State, obj, TYPE_FTTSC010)
+
+#define TSC_REG32(s, off) \
+((s)-regs[(off) / 4])
+
+static void fttsc010_update_irq(Fttsc010State *s)
+{
+qemu_set_irq(s-irq, !!(TSC_REG32(s, REG_IMR)  TSC_REG32(s, REG_ISR)));
+}
+
+static uint64_t
+fttsc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+uint32_t ret = 0;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR ... REG_DCR:
+ret = s-regs[addr / 4];
+break;
+case REG_XYR:
+ret = deposit32(ret,  0, 12, s-x);
+ret = deposit32(ret, 16, 12, s-y);
+break;
+case REG_ZR:
+ret = deposit32(ret,  0, 12, s-z1);
+ret = deposit32(ret, 16, 12, s-z2);
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+fttsc010: undefined memory access@%# HWADDR_PRIx \n, addr);
+break;
+}
+
+return ret;
+}
+
+static void
+fttsc010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+uint32_t dly, sdiv, mdiv;
+Fttsc010State *s = FTTSC010(opaque);
+
+switch (addr) {
+case REG_CR:
+TSC_REG32(s, REG_CR) = (uint32_t)val;
+if (TSC_REG32(s, REG_CR)  (CR_AS | CR_RD1)) {
+/* ADC conversion delay with frame number */
+dly = extract32(TSC_REG32(s, REG_DCR), 0, 16);
+/* ADC sample clock divider */
+sdiv = extract32(TSC_REG32(s, REG_CSR), 8, 8);
+/* ADC main clock divider */
+mdiv = extract32(TSC_REG32(s, REG_CSR), 0, 8);
+/* Calculate sample rate/timer interval */
+s-interval = s-freq / ((mdiv + 1) * (sdiv + 1) * (dly + 1) * 64);
+s-interval = MAX(1ULL, s-interval);
+qemu_mod_timer(s-qtimer,
+s-interval + qemu_get_clock_ms(vm_clock));
+} else {
+qemu_del_timer(s-qtimer);
+}
+break;
+case REG_ISR:
+TSC_REG32(s, REG_ISR) = ~((uint32_t)val);
+fttsc010_update_irq(s);
+break;
+case REG_IMR:
+TSC_REG32(s, REG_IMR) = (uint32_t)val;
+fttsc010_update_irq(s);
+break

[Qemu-devel] [PATCH v7 12/24] hw/arm: add FTNANDC021 nand flash controller support

2013-03-12 Thread Kuo-Jung Su
From: Kuo-Jung Su dant...@faraday-tech.com

The FTNANDC021 is an integrated NAND flash controller which
re-pack the NAND flash command set with a shorter built-in opcode.
It also provides a register base interface for user to easily
access the underlying NAND flash chips, and also supports HW ECC.

However the optional hardware ECC function is not implemented.

Signed-off-by: Kuo-Jung Su dant...@faraday-tech.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |   14 ++
 hw/arm/faraday_a369_soc.c |9 +
 hw/arm/ftnandc021.c   |  523 +
 hw/arm/ftnandc021.h   |   84 
 5 files changed, 631 insertions(+)
 create mode 100644 hw/arm/ftnandc021.c
 create mode 100644 hw/arm/ftnandc021.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index cc5e343..2622f3f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -45,3 +45,4 @@ obj-y += ftwdt010.o
 obj-y += ftrtc011.o
 obj-y += ftdmac020.o
 obj-y += ftapbbrg020.o
+obj-y += ftnandc021.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 8f8ea4f..a13e946 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -25,6 +25,8 @@ a369_board_init(QEMUMachineInitArgs *args)
 {
 DeviceState *ds;
 FaradaySoCState *s;
+DriveInfo *dinfo;
+Error *local_errp = NULL;
 
 if (!args-cpu_model) {
 args-cpu_model = fa626te;
@@ -46,6 +48,18 @@ a369_board_init(QEMUMachineInitArgs *args)
 
 s = FARADAY_SOC(ds);
 
+/* Attach the nand flash to ftnandc021 */
+dinfo = drive_get_next(IF_MTD);
+ds = nand_init(dinfo ? dinfo-bdrv : NULL, NAND_MFR_SAMSUNG, 0xda);
+object_property_set_link(OBJECT(s-nandc[0]),
+ OBJECT(ds),
+ flash,
+ local_errp);
+if (local_errp) {
+fprintf(stderr, a369: Unable to set flash link for FTNANDC021\n);
+exit(1);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index ab13f70..a211c90 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -84,6 +84,7 @@ a369soc_device_init(FaradaySoCState *s)
 DriveInfo *dinfo;
 DeviceState *ds;
 qemu_irq *cpu_pic;
+qemu_irq ack, req;
 int i;
 
 s-as = get_system_memory();
@@ -232,6 +233,14 @@ a369soc_device_init(FaradaySoCState *s)
 fprintf(stderr, a369soc: Unable to set soc link for FTAPBBRG020\n);
 exit(1);
 }
+
+/* ftnandc021 */
+ds = sysbus_create_simple(ftnandc021, 0x9020, s-pic[30]);
+s-nandc[0] = ds;
+ack = qdev_get_gpio_in(ds, 0);
+req = qdev_get_gpio_in(s-hdma[0], 15);
+qdev_connect_gpio_out(s-hdma[0], 15, ack);
+qdev_connect_gpio_out(ds, 0, req);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftnandc021.c b/hw/arm/ftnandc021.c
new file mode 100644
index 000..3c5adaa
--- /dev/null
+++ b/hw/arm/ftnandc021.c
@@ -0,0 +1,523 @@
+/*
+ * QEMU model of the FTNANDC021 NAND Flash Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw/sysbus.h
+#include hw/devices.h
+#include hw/flash.h
+#include sysemu/blockdev.h
+
+#include faraday.h
+#include ftnandc021.h
+
+#define TYPE_FTNANDC021 ftnandc021
+
+typedef struct Ftnandc021State {
+SysBusDevice busdev;
+MemoryRegion mmio;
+
+qemu_irq irq;
+DeviceState *flash;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+uint8_t  manf_id, chip_id;
+
+int  cmd;
+int  len;/* buffer length for page read/write */
+int  pi;/* page index */
+int  bw;/* bus width (8-bits, 16-bits) */
+
+uint64_t size;/* flash size (maximum access range) */
+uint32_t pgsz;/* page size (Bytes) */
+uint32_t bksz;/* block size (Bytes) */
+uint32_t alen;/* address length (cycle) */
+
+uint32_t id[2];
+uint8_t  oob[8];/* 5 bytes for 512/2048 page; 7 bytes for 4096 page */
+
+/* HW register caches */
+uint32_t sr;
+uint32_t fcr;
+uint32_t mcr;
+uint32_t ier;
+uint32_t bcr;
+} Ftnandc021State;
+
+#define FTNANDC021(obj) \
+OBJECT_CHECK(Ftnandc021State, obj, TYPE_FTNANDC021)
+
+static void ftnandc021_update_irq(Ftnandc021State *s)
+{
+if (s-ier  IER_ENA) {
+if ((s-ier  0x0f)  (s-sr  2)) {
+qemu_set_irq(s-irq, 1);
+} else {
+qemu_set_irq(s-irq, 0);
+}
+}
+}
+
+static void ftnandc021_set_idle(Ftnandc021State *s)
+{
+/* CLE=0, ALE=0, CS=1 */
+nand_setpins(s-flash, 0, 0, 1, 1, 0);
+
+/* Set command compelete */
+s-sr |= SR_CMD;
+
+/* Update IRQ signal */
+ftnandc021_update_irq(s);
+}
+
+static void ftnandc021_set_cmd(Ftnandc021State *s, uint8_t cmd)
+{
+/* CLE=1, ALE=0, CS=0 */
+nand_setpins(s-flash, 1, 0, 0, 1, 0

Re: [Qemu-devel] [PATCH v6 08/24] hw/arm: add Faraday FTRTC011 RTC timer support

2013-03-07 Thread Kuo-Jung Su
2013/3/7 Paolo Bonzini pbonz...@redhat.com:

   From Makefile.target, qtest is built when you build softmmu target.
 I guess there is no need to add --enable-qtest option. However, I
 don't know how to run qtest...

 make check-qtest-arm

 Paolo

Got it, thanks.


-- 
Best wishes,
Kuo-Jung Su



[Qemu-devel] [PATCH v6 24/24] hw/arm: add Faraday FTSPI020 SPI flash controller support

2013-03-06 Thread Kuo-Jung Su
The FTSPI020 is an integrated SPI Flash controller
which supports up to 4 flash chips.

Signed-off-by: Kuo-Jung Su dant...@gmail.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |   16 +++
 hw/arm/ftspi020.c |  340 +
 hw/arm/ftspi020.h |   81 
 4 files changed, 438 insertions(+)
 create mode 100644 hw/arm/ftspi020.c
 create mode 100644 hw/arm/ftspi020.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 1cbb58f..9bb3076 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -54,3 +54,4 @@ obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
 obj-y += fttmr010.o
+obj-y += ftspi020.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 0e75b02..5d66b31 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -83,6 +83,22 @@ a369_board_init(QEMUMachineInitArgs *args)
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
 sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
 
+/* SPI: FTSPI020 */
+ds = sysbus_create_simple(ftspi020, 0xC000, s-pic[4]);
+s-spi_fl[0] = ds;
+
+/* Attach the spi flash to ftspi020.0 */
+nr_flash = 1;
+for (i = 0; i  nr_flash; i++) {
+SSIBus *ssi = (SSIBus *)qdev_get_child_bus(s-spi_fl[0], spi);
+DeviceState *fl = ssi_create_slave_no_init(ssi, w25q64);
+qemu_irq cs_line;
+
+qdev_init_nofail(fl);
+cs_line = qdev_get_gpio_in(fl, 0);
+sysbus_connect_irq(SYS_BUS_DEVICE(s-spi_fl[0]), i + 1, cs_line);
+}
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/ftspi020.c b/hw/arm/ftspi020.c
new file mode 100644
index 000..d61cca7
--- /dev/null
+++ b/hw/arm/ftspi020.c
@@ -0,0 +1,340 @@
+/*
+ * Faraday FTSPI020 Flash Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include sysemu/sysemu.h
+#include hw/sysbus.h
+#include hw/ssi.h
+
+#include ftspi020.h
+
+#define TYPE_FTSPI020   ftspi020
+
+typedef struct Ftspi020State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+
+/* DMA hardware handshake */
+qemu_irq req;
+
+SSIBus *spi;
+qemu_irq *cs_lines;
+
+int wip;/* SPI Flash Status: Write In Progress BIT shift */
+
+/* HW register caches */
+uint32_t cmd[4];
+uint32_t ctrl;
+uint32_t timing;
+uint32_t icr;
+uint32_t isr;
+uint32_t rdsr;
+} Ftspi020State;
+
+#define FTSPI020(obj) \
+OBJECT_CHECK(Ftspi020State, obj, TYPE_FTSPI020)
+
+static void ftspi020_update_irq(Ftspi020State *s)
+{
+qemu_set_irq(s-irq, s-isr ? 1 : 0);
+}
+
+static void ftspi020_handle_ack(void *opaque, int line, int level)
+{
+Ftspi020State *s = FTSPI020(opaque);
+
+if (!(s-icr  ICR_DMA)) {
+return;
+}
+
+if (level) {
+qemu_set_irq(s-req, 0);
+} else if (s-cmd[2]) {
+qemu_set_irq(s-req, 1);
+}
+}
+
+static int ftspi020_do_command(Ftspi020State *s)
+{
+uint32_t cs   = extract32(s-cmd[3],  8, 2);
+uint32_t cmd  = extract32(s-cmd[3], 24, 8);
+uint32_t ilen = extract32(s-cmd[1], 24, 2);
+uint32_t alen = extract32(s-cmd[1],  0, 3);
+uint32_t dcyc = extract32(s-cmd[1], 16, 8);
+
+if (dcyc % 8) {
+fprintf(stderr, ftspi020: bad dummy clock (%u) to QEMU\n, dcyc);
+exit(1);
+}
+
+/* activate the spi flash */
+qemu_set_irq(s-cs_lines[cs], 0);
+
+/* if it's a SPI flash READ_STATUS command */
+if ((s-cmd[3]  (CMD3_RDSR | CMD3_WRITE)) == CMD3_RDSR) {
+uint32_t rdsr;
+
+ssi_transfer(s-spi, cmd);
+do {
+rdsr = ssi_transfer(s-spi, 0x00);
+if (s-cmd[3]  CMD3_RDSR_SW) {
+break;
+}
+} while (rdsr  (1  s-wip));
+s-rdsr = rdsr;
+} else {
+/* otherwise */
+int i;
+
+ilen = MIN(ilen, 2);
+alen = MIN(alen, 4);
+
+/* command cycles */
+for (i = 0; i  ilen; ++i) {
+ssi_transfer(s-spi, cmd);
+}
+/* address cycles */
+for (i = alen - 1; i = 0; --i) {
+ssi_transfer(s-spi, extract32(s-cmd[0], i * 8, 8));
+}
+/* dummy cycles */
+for (i = 0; i  (dcyc  3); ++i) {
+ssi_transfer(s-spi, 0x00);
+}
+}
+
+if (!s-cmd[2]) {
+qemu_set_irq(s-cs_lines[cs], 1);
+} else if (s-icr  ICR_DMA) {
+qemu_set_irq(s-req, 1);
+}
+
+if (s-cmd[3]  CMD3_INTR) {
+s-isr |= ISR_CMDFIN;
+}
+ftspi020_update_irq(s);
+
+return 0;
+}
+
+static void ftspi020_chip_reset(Ftspi020State *s)
+{
+int i;
+
+for (i = 0; i  4; ++i) {
+s-cmd[i] = 0;
+}
+s-wip = 0;
+s-ctrl = 0;
+s-timing = 0;
+s-icr = 0;
+s-isr = 0;
+s-rdsr = 0;
+
+qemu_set_irq(s-irq, 0);
+
+for (i = 0; i  CFG_NR_CSLINES; ++i

[Qemu-devel] [PATCH v6 15/24] hw: add WM8731 codec support

2013-03-06 Thread Kuo-Jung Su
Wolfson WM8731 is a simple audio codec for embedded systems.
It has 2 input and 1 output ports:

** Input **
1. Linue-In
2. Microphone

** Output **
1. Headphone out

BTW it's based on hw/wm8750.c with 16-bit I2S support by default.

Signed-off-by: Kuo-Jung Su dant...@gmail.com
---
 default-configs/arm-softmmu.mak |1 +
 hw/Makefile.objs|1 +
 hw/i2c.h|6 +
 hw/wm8731.c |  499 +++
 4 files changed, 507 insertions(+)
 create mode 100644 hw/wm8731.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 68b2045..131f85b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_SD=y
 CONFIG_MAX7310=y
+CONFIG_WM8731=y
 CONFIG_WM8750=y
 CONFIG_TWL92230=y
 CONFIG_TSC2005=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 40ebe46..33c128d 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -168,6 +168,7 @@ common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 common-obj-y += usb/
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
+common-obj-$(CONFIG_WM8731) += wm8731.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_TWL92230) += twl92230.o
 common-obj-$(CONFIG_TSC2005) += tsc2005.o
diff --git a/hw/i2c.h b/hw/i2c.h
index 0e80d5a..f03edc5 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -63,6 +63,12 @@ int i2c_recv(i2c_bus *bus);
 
 DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr);
 
+/* wm8731.c */
+void wm8731_data_req_set(DeviceState *dev,
+void (*data_req)(void *, int, int), void *opaque);
+void wm8731_dac_dat(void *opaque, uint32_t sample);
+uint32_t wm8731_adc_dat(void *opaque);
+
 /* wm8750.c */
 void wm8750_data_req_set(DeviceState *dev,
 void (*data_req)(void *, int, int), void *opaque);
diff --git a/hw/wm8731.c b/hw/wm8731.c
new file mode 100644
index 000..51560a3
--- /dev/null
+++ b/hw/wm8731.c
@@ -0,0 +1,499 @@
+/*
+ * WM8731 audio codec.
+ *
+ * base is wm8750.c
+ *
+ * Copyright (c) 2013 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include hw.h
+#include i2c.h
+#include audio/audio.h
+
+#define IN_PORT_N   2
+#define OUT_PORT_N  1
+
+#define TYPE_WM8731 wm8731
+
+typedef struct WMRate {
+int adc;
+int adc_hz;
+int dac;
+int dac_hz;
+} WMRate;
+
+typedef struct WM8731State {
+I2CSlave i2c;
+uint8_t i2c_data[2];
+int i2c_len;
+QEMUSoundCard card;
+SWVoiceIn *adc_voice[IN_PORT_N];
+SWVoiceOut *dac_voice[OUT_PORT_N];
+void (*data_req)(void *, int, int);
+void *opaque;
+uint8_t data_in[4096];
+uint8_t data_out[4096];
+int idx_in, req_in;
+int idx_out, req_out;
+
+SWVoiceOut **out[2];
+uint8_t outvol[2];
+SWVoiceIn **in[2];
+uint8_t invol[2], inmute[2], mutemic;
+
+uint8_t mute;
+uint8_t power, format, active;
+const WMRate *rate;
+uint8_t rate_vmstate;
+int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
+} WM8731State;
+
+#define WM8731(obj) \
+OBJECT_CHECK(WM8731State, obj, TYPE_WM8731)
+
+#define WM8731_OUTVOL_TRANSFORM(x)  (x  1)
+#define WM8731_INVOL_TRANSFORM(x)   (x  3)
+
+static inline void wm8731_in_load(WM8731State *s)
+{
+if (s-idx_in + s-req_in = sizeof(s-data_in)) {
+return;
+}
+s-idx_in = audio_MAX(0, (int) sizeof(s-data_in) - s-req_in);
+AUD_read(*s-in[0], s-data_in + s-idx_in,
+ sizeof(s-data_in) - s-idx_in);
+}
+
+static inline void wm8731_out_flush(WM8731State *s)
+{
+int sent = 0;
+while (sent  s-idx_out) {
+sent += AUD_write(*s-out[0], s-data_out + sent, s-idx_out - sent)
+? 0 : s-idx_out;
+}
+s-idx_out = 0;
+}
+
+static void wm8731_audio_in_cb(void *opaque, int avail_b)
+{
+WM8731State *s = WM8731(opaque);
+s-req_in = avail_b;
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, avail_b  1);
+}
+
+static void wm8731_audio_out_cb(void *opaque, int free_b)
+{
+WM8731State *s = WM8731(opaque);
+
+if (s-idx_out = free_b) {
+s-idx_out = free_b;
+s-req_out = 0;
+wm8731_out_flush(s);
+} else {
+s-req_out = free_b - s-idx_out;
+}
+/* 16 bit samples */
+s-data_req(s-opaque, s-req_out  1, s-req_in  1);
+}
+
+static const WMRate wm_rate_table[] = {
+{  256, 48000,  256, 48000 },/* SR: , BOSR: 0 */
+{  384, 48000,  384, 48000 },/* SR: , BOSR: 1 */
+{  256, 48000,  256,  8000 },/* SR: 0001, BOSR: 0 */
+{  384, 48000,  384,  8000 },/* SR: 0001, BOSR: 1 */
+{  256,  8000,  256, 48000 },/* SR: 0010, BOSR: 0 */
+{  384,  8000,  384, 48000 },/* SR: 0010, BOSR: 1 */
+{  256,  8000,  256,  8000 },/* SR: 0011, BOSR: 0 */
+{  384,  8000,  384,  8000 },/* SR: 0011, BOSR: 1

[Qemu-devel] [PATCH v6 23/24] hw/arm: add Faraday FTTMR010 timer support

2013-03-06 Thread Kuo-Jung Su
The FTTMR010 provides three independent sets of sub-timers.
Two match registers are provided for each sub-timer, whenever
the value of the match registers equals any one value of the
sub-timers, the timer interrupt will be immediately triggered.
And it would also issue an interrupt when an overflow occurs.

Signed-off-by: Kuo-Jung Su dant...@gmail.com
---
 hw/arm/Makefile.objs  |1 +
 hw/arm/faraday_a369.c |8 +
 hw/arm/fttmr010.c |  451 +
 hw/arm/fttmr010.h |   41 +
 4 files changed, 501 insertions(+)
 create mode 100644 hw/arm/fttmr010.c
 create mode 100644 hw/arm/fttmr010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2560b3c..1cbb58f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -53,3 +53,4 @@ obj-y += ftlcdc200.o
 obj-y += fttsc010.o
 obj-y += ftsdc010.o
 obj-y += ftmac110.o
+obj-y += fttmr010.o
diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
index 71e4233..0e75b02 100644
--- a/hw/arm/faraday_a369.c
+++ b/hw/arm/faraday_a369.c
@@ -75,6 +75,14 @@ a369_board_init(QEMUMachineInitArgs *args)
 ftmac110_init(nd_table[1], 0xC010, s-pic[5]);
 }
 
+/* Timer: FTTMR010 */
+ds = qdev_create(NULL, fttmr010);
+qdev_prop_set_uint32(ds, freq, 33 * 100);
+qdev_init_nofail(ds);
+sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0xC020);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[6]);
+sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[7]);
+
 /* System start-up */
 
 if (args-kernel_filename) {
diff --git a/hw/arm/fttmr010.c b/hw/arm/fttmr010.c
new file mode 100644
index 000..f72a1b9
--- /dev/null
+++ b/hw/arm/fttmr010.c
@@ -0,0 +1,451 @@
+/*
+ * Faraday FTTMR010 Timer.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su dant...@faraday-tech.com
+ *
+ * This code is licensed under GNU GPL v2+.
+ */
+
+#include hw/hw.h
+#include hw/sysbus.h
+#include qemu/timer.h
+#include sysemu/sysemu.h
+
+#include faraday.h
+#include fttmr010.h
+
+#define TYPE_FTTMR010   fttmr010
+#define TYPE_FTTMR010_TIMER fttmr010_timer
+
+typedef struct Fttmr010State Fttmr010State;
+
+typedef struct Fttmr010Timer {
+int id;
+int up;
+Fttmr010State *chip;
+qemu_irq irq;
+QEMUTimer *qtimer;
+uint64_t start;
+uint32_t intr_match1:1;
+uint32_t intr_match2:1;
+
+/* HW register caches */
+uint64_t counter;
+uint64_t reload;
+uint32_t match1;
+uint32_t match2;
+
+} Fttmr010Timer;
+
+struct Fttmr010State {
+SysBusDevice busdev;
+MemoryRegion iomem;
+qemu_irq irq;
+Fttmr010Timer timer[3];
+uint32_t freq;/* desired source clock */
+uint64_t step;/* get_ticks_per_sec() / freq */
+
+/* HW register caches */
+uint32_t cr;
+uint32_t isr;
+uint32_t imr;
+};
+
+#define FTTMR010(obj) \
+OBJECT_CHECK(Fttmr010State, obj, TYPE_FTTMR010)
+
+static void fttmr010_timer_restart(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t interval;
+int pending = 0;
+
+t-intr_match1 = 0;
+t-intr_match2 = 0;
+
+/* check match1 */
+if (t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (!t-up  t-match1 = t-counter) {
+t-intr_match1 = 1;
+}
+if (t-match1 == t-counter) {
+s-isr |= ISR_MATCH1(t-id);
+++pending;
+}
+
+/* check match2 */
+if (t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (!t-up  t-match2 = t-counter) {
+t-intr_match2 = 1;
+}
+if (t-match2 == t-counter) {
+s-isr |= ISR_MATCH2(t-id);
+++pending;
+}
+
+/* determine delay interval */
+if (t-up) {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = MIN(t-match1, t-match2) - t-counter;
+} else if (t-match1  t-counter) {
+interval = t-match1 - t-counter;
+} else if (t-match2  t-reload) {
+interval = t-match2 - t-counter;
+} else {
+interval = 0xULL - t-counter;
+}
+} else {
+if ((t-match1  t-counter)  (t-match2  t-counter)) {
+interval = t-counter - MAX(t-match1, t-match2);
+} else if (t-match1  t-reload) {
+interval = t-counter - t-match1;
+} else if (t-match2  t-reload) {
+interval = t-counter - t-match2;
+} else {
+interval = t-counter;
+}
+}
+
+if (pending) {
+qemu_irq_pulse(s-irq);
+qemu_irq_pulse(t-irq);
+}
+t-start = qemu_get_clock_ns(vm_clock);
+qemu_mod_timer(t-qtimer, t-start + interval * s-step);
+}
+
+static uint64_t fttmr010_update_counter(Fttmr010Timer *t)
+{
+Fttmr010State *s = t-chip;
+uint64_t now = qemu_get_clock_ns(vm_clock);
+uint64_t elapsed;
+int pending = 0;
+
+if (s-cr  CR_TMR_EN(t-id)) {
+/* get elapsed time */
+elapsed = (now - t-start) / s-step

Re: [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer support

2013-03-06 Thread Kuo-Jung Su
2013/3/6 Paolo Bonzini pbonz...@redhat.com:
 Il 06/03/2013 08:27, Kuo-Jung Su ha scritto:
 The FTWDT010 is used to prevent system from infinite loop
 while software gets trapped in the deadlock.

 Under the normal operation, users should restart FTWDT010
 at the regular intervals before counter counts down to 0.

 If the counter does reach 0, FTWDT010 will try to reset
 the system by generating one or a combination of signals,
 system reset, system interrupt, and external interrupt.

 Signed-off-by: Kuo-Jung Su dant...@gmail.com
 ---
  hw/arm/Makefile.objs  |1 +
  hw/arm/faraday_a369_soc.c |   23 +
  hw/arm/ftwdt010.c |  212 
 +
  hw/arm/ftwdt010.h |   35 
  4 files changed, 271 insertions(+)
  create mode 100644 hw/arm/ftwdt010.c
  create mode 100644 hw/arm/ftwdt010.h

 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
 index 2190edd..bc8e2de 100644
 --- a/hw/arm/Makefile.objs
 +++ b/hw/arm/Makefile.objs
 @@ -41,3 +41,4 @@ obj-y += ftintc020.o
  obj-y += ftahbc020.o
  obj-y += ftddrii030.o
  obj-y += ftpwmtmr010.o
 +obj-y += ftwdt010.o
 diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
 index 66d9891..1bf64d4 100644
 --- a/hw/arm/faraday_a369_soc.c
 +++ b/hw/arm/faraday_a369_soc.c
 @@ -68,6 +68,25 @@ static void a369soc_reset(DeviceState *ds)
  }

  static void
 +a369soc_system_reset(void *opaque)
 +{
 +FaradaySoCState *s = FARADAY_SOC(opaque);
 +
 +if (s-scu) {
 +device_reset(s-scu);
 +}
 +if (s-ddrc) {
 +device_reset(s-ddrc);
 +}
 +if (s-ahbc) {
 +device_reset(s-ahbc);
 +}
 +if (s-cpu) {
 +cpu_reset(CPU(s-cpu));
 +}
 +}

 Why is this needed?  Aren't they called already by

 qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());

 ?


It doesn't work while running under ROM mode. ( no -kernel )
Because Faraday SoC Platform usually designed to boot from ROM and
followed by an AHB remapping process (i.e. remap ROM/RAM address).

  a369soc_device_init(FaradaySoCState *s)
  {
  DriveInfo *dinfo;
 @@ -166,6 +185,10 @@ a369soc_device_init(FaradaySoCState *s)
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s-pic[9]);
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s-pic[10]);
  sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s-pic[11]);
 +
 +/* ftwdt010 */
 +sysbus_create_simple(ftwdt010, 0x9220, s-pic[46]);
 +qemu_register_reset(a369soc_system_reset, s);
  }

  static int a369soc_init(SysBusDevice *dev)
 diff --git a/hw/arm/ftwdt010.c b/hw/arm/ftwdt010.c
 new file mode 100644
 index 000..361f16e
 --- /dev/null
 +++ b/hw/arm/ftwdt010.c
 @@ -0,0 +1,212 @@
 +/*
 + * QEMU model of the FTWDT010 WatchDog Timer
 + *
 + * Copyright (C) 2012 Faraday Technology
 + * Written by Dante Su dant...@faraday-tech.com
 + *
 + * This file is licensed under GNU GPL v2+.
 + */
 +
 +#include hw/sysbus.h
 +#include sysemu/sysemu.h
 +#include qemu/timer.h
 +
 +#include faraday.h
 +#include ftwdt010.h
 +
 +#define TYPE_FTWDT010   ftwdt010
 +
 +typedef struct Ftwdt010State {
 +SysBusDevice busdev;
 +MemoryRegion mmio;
 +
 +qemu_irq irq;
 +
 +QEMUTimer *qtimer;
 +
 +uint64_t timeout;
 +uint64_t freq;/* desired source clock */
 +uint64_t step;/* get_ticks_per_sec() / freq */
 +bool running;
 +
 +/* HW register cache */
 +uint32_t load;
 +uint32_t cr;
 +uint32_t sr;
 +} Ftwdt010State;
 +
 +#define FTWDT010(obj) \
 +OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
 +
 +static uint64_t
 +ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
 +{
 +Ftwdt010State *s = FTWDT010(opaque);
 +uint32_t ret = 0;
 +
 +switch (addr) {
 +case REG_COUNTER:
 +if (s-cr  CR_EN) {
 +ret = s-timeout - qemu_get_clock_ms(rt_clock);
 +ret = MIN(s-load, ret * 100ULL / s-step);
 +} else {
 +ret = s-load;
 +}
 +break;
 +case REG_LOAD:
 +return s-load;
 +case REG_CR:
 +return s-cr;
 +case REG_SR:
 +return s-sr;
 +case REG_REVR:
 +return 0x00010601;  /* rev. 1.6.1 */
 +default:
 +qemu_log_mask(LOG_GUEST_ERROR,
 +ftwdt010: undefined memory access@%# HWADDR_PRIx \n, addr);
 +break;
 +}
 +
 +return ret;
 +}
 +
 +static void
 +ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 +{
 +Ftwdt010State *s = FTWDT010(opaque);
 +
 +switch (addr) {
 +case REG_LOAD:
 +s-load = (uint32_t)val;
 +break;
 +case REG_RESTART:
 +if ((s-cr  CR_EN)  (val == WDT_MAGIC)) {
 +s-timeout = (s-step * (uint64_t)s-load) / 100ULL;
 +s-timeout = qemu_get_clock_ms(rt_clock) + MAX(s-timeout, 1);
 +qemu_mod_timer(s-qtimer, s-timeout);
 +}
 +break;
 +case REG_CR:
 +s-cr = (uint32_t)val;
 +if (s-cr  CR_EN

Re: [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer support

2013-03-06 Thread Kuo-Jung Su
2013/3/6 Paolo Bonzini pbonz...@redhat.com:
   It doesn't work while running under ROM mode. ( no -kernel )
   Because Faraday SoC Platform usually designed to boot from ROM and
   followed by an AHB remapping process (i.e. remap ROM/RAM address).
 
  What doesn't work exactly?  Why aren't these called?  Or are
  you forcing a particular reset order?
 
  Paolo

 While booting from ROM, the faraday soc usually remap the ROM / RAM
 before jumping into linux.

 In other words,  the system mapping is:

 1. Power-On:

 ROM: 0x
 RAM: N/A
 SRAM: 0xA000

 2. AHB Remap (u-boot/linux)

 ROM: 0x2000
 RAM: 0x

 So I have to register my own reset handler to

 1. Undo the ROM/RAM remap (i.e. device_reset(s-ahbc))
 2. Reset CPU

 - Messaggio originale -
 Da: Kuo-Jung Su dant...@gmail.com
 A: Paolo Bonzini pbonz...@redhat.com
 Inviato: Mercoledì, 6 marzo 2013 11:00:49
 Oggetto: Re: [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer 
 support

 2013/3/6 Paolo Bonzini pbonz...@redhat.com:
 
  2013/3/6 Paolo Bonzini pbonz...@redhat.com:
   Il 06/03/2013 08:27, Kuo-Jung Su ha scritto:
   The FTWDT010 is used to prevent system from infinite loop
   while software gets trapped in the deadlock.
  
   Under the normal operation, users should restart FTWDT010
   at the regular intervals before counter counts down to 0.
  
   If the counter does reach 0, FTWDT010 will try to reset
   the system by generating one or a combination of signals,
   system reset, system interrupt, and external interrupt.
  
   Signed-off-by: Kuo-Jung Su dant...@gmail.com
   ---
hw/arm/Makefile.objs  |1 +
hw/arm/faraday_a369_soc.c |   23 +
hw/arm/ftwdt010.c |  212
+
hw/arm/ftwdt010.h |   35 
4 files changed, 271 insertions(+)
create mode 100644 hw/arm/ftwdt010.c
create mode 100644 hw/arm/ftwdt010.h
  
   diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
   index 2190edd..bc8e2de 100644
   --- a/hw/arm/Makefile.objs
   +++ b/hw/arm/Makefile.objs
   @@ -41,3 +41,4 @@ obj-y += ftintc020.o
obj-y += ftahbc020.o
obj-y += ftddrii030.o
obj-y += ftpwmtmr010.o
   +obj-y += ftwdt010.o
   diff --git a/hw/arm/faraday_a369_soc.c
   b/hw/arm/faraday_a369_soc.c
   index 66d9891..1bf64d4 100644
   --- a/hw/arm/faraday_a369_soc.c
   +++ b/hw/arm/faraday_a369_soc.c
   @@ -68,6 +68,25 @@ static void a369soc_reset(DeviceState *ds)
}
  
static void
   +a369soc_system_reset(void *opaque)
   +{
   +FaradaySoCState *s = FARADAY_SOC(opaque);
   +
   +if (s-scu) {
   +device_reset(s-scu);
   +}
   +if (s-ddrc) {
   +device_reset(s-ddrc);
   +}
   +if (s-ahbc) {
   +device_reset(s-ahbc);
   +}
   +if (s-cpu) {
   +cpu_reset(CPU(s-cpu));
   +}
   +}
  
   Why is this needed?  Aren't they called already by
  
   qemu_register_reset(qbus_reset_all_fn,
   sysbus_get_default());
  
   ?
  
 
  It doesn't work while running under ROM mode. ( no -kernel )
  Because Faraday SoC Platform usually designed to boot from ROM and
  followed by an AHB remapping process (i.e. remap ROM/RAM address).
 
  What doesn't work exactly?  Why aren't these called?  Or are
  you forcing a particular reset order?
 
  Paolo

 While booting from ROM, the faraday soc usually remap the ROM / RAM
 before jumping into linux.

 In other words,  the system mapping is:

 1. Power-On:

 ROM: 0x
 RAM: N/A
 SRAM: 0xA000

 2. AHB Remap (u-boot/linux)

 ROM: 0x2000
 RAM: 0x

 So I have to register my own reset handler to

 1. Undo the ROM/RAM remap (i.e. device_reset(s-ahbc))
 2. Reset CPU

 I understand that.  What I'm missing is, why these reset handlers aren't
 called anyway when QEMU does qemu_devices_reset(), for example from
 qemu_system_reset().


1. arm_cpu_reset() is never be invoked from the default reset handler.

2. Undo ROM/RAM remap would make bus become unstable there is no
guaranty when the bus would be stabilized.
(It looks to me that it's true for both QEMU and real hardware)

3. In QEMU, my guess is without arm_cpu_reset(), when the AHB remap process
activated upon watchdog counts down to zero.
The PC (r15) could be anywhere, and so does the stack  bss.
Which means the CPU would likely suffers from UNKNOWN INSTRUCTION,
DATA ABORT... etc.

 Also, I do not understand who performs this again:


It's performed at my ROM code:

https://github.com/dantesu1218/virgil/blob/master/arch/mach-a369/board.c

line 200 ~ 220

#ifndef CONFIG_SKIP_SYSINIT
/* Skip AHB remap if the jump address is not inside SDRAM address space */
ldr r4, =0x1000\n
cmp %2, r4\n
movhs pc, %2\n /* jump without AHB remapped */
/* AHB remap
* REG32(CONFIG_IOBASE_DDR + 0x10) = 0x00FF
* REG32(CONFIG_IOBASE_AHB + 0x88)  = 0x00100F01
*/
ldr r4, [%0, #0x10]\n
bic r4, #0xff00\n
ldr r5, =0x00100f01

Re: [Qemu-devel] [PATCH v6 17/24] qemu/bitops.h: add the bit ordering reversal functions stolen from linux

2013-03-06 Thread Kuo-Jung Su
2013/3/6 Paolo Bonzini pbonz...@redhat.com:
 Il 06/03/2013 08:27, Kuo-Jung Su ha scritto:
 Signed-off-by: Kuo-Jung Su dant...@gmail.com
 ---
  include/qemu/bitops.h |   63 
 -
  1 file changed, 62 insertions(+), 1 deletion(-)

 diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
 index affcc96..920d028 100644
 --- a/include/qemu/bitops.h
 +++ b/include/qemu/bitops.h
 @@ -3,7 +3,8 @@
   *
   * Copyright (C) 2010 Corentin Chary corentin.ch...@gmail.com
   *
 - * Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
 + * Mostly inspired by (stolen from) linux/bitmap.h, linux/bitops.h
 + * and linux/bitrev.h
   *
   * This work is licensed under the terms of the GNU LGPL, version 2.1 or 
 later.
   * See the COPYING.LIB file in the top-level directory.
 @@ -273,4 +274,64 @@ static inline uint64_t deposit64(uint64_t value, int 
 start, int length,
  return (value  ~mask) | ((fieldval  start)  mask);
  }

 +/**
 + * bitrev8:
 + * @value: the value to reverse bit ordering from
 + *
 + * Reverse the 8 bit input @value
 + *
 + * Returns: the input @value with reversed bit ordering
 + */
 +static inline uint8_t bitrev8(uint8_t value)
 +{
 +int i;
 +uint8_t ret = 0;
 +for (i = 0; i  8; ++i) {
 +if (value  BIT(i)) {
 +ret |= BIT(7 - i);
 +}
 +}

 Please use instead

value = ((value  0xAA)  1) | ((value  0x55)  1);
value = ((value  0xCC)  2) | ((value  0x33)  2);
value = ((value  0xF0)  4) | ((value  0x0F)  4);
return value;

 Paolo


Got it, thanks

 +return ret;
 +}
 +
 +/**
 + * bitrev16:
 + * @value: the value to reverse bit ordering from
 + *
 + * Reverse the 16 bit input @value
 + *
 + * Returns: the input @value with reversed bit ordering
 + */
 +static inline uint16_t bitrev16(uint16_t value)
 +{
 +return (bitrev8(value  0xff)  8) | bitrev8(value  8);
 +}
 +
 +/**
 + * bitrev32:
 + * @value: the value to reverse bit ordering from
 + *
 + * Reverse the 32 bit input @value
 + *
 + * Returns: the input @value with reversed bit ordering
 + */
 +static inline uint32_t bitrev32(uint32_t value)
 +{
 +return (bitrev16(value  0x)  16) | bitrev16(value  16);
 +}
 +
 +/**
 + * bitrev64:
 + * @value: the value to reverse bit ordering from
 + *
 + * Reverse the 64 bit input @value
 + *
 + * Returns: the input @value with reversed bit ordering
 + */
 +static inline uint64_t bitrev64(uint64_t value)
 +{
 +return ((uint64_t)bitrev32(value  0xULL)  32)
 +| (uint64_t)bitrev32(value  32);
 +}
 +
  #endif





-- 
Best wishes,
Kuo-Jung Su



  1   2   3   >