Message ID | CAEgOgz6WUQ1KuBq1MykKzp2xFOwz_oQVg+KUkt=HXh9Ury3xMg@mail.gmail.com |
---|---|
State | New |
Headers | show |
2013/2/27 Peter Crosthwaite <peter.crosthwaite@xilinx.com>: > Hi Kuo-Jung, > > On Wed, Feb 27, 2013 at 12:08 PM, Kuo-Jung Su <dantesu@gmail.com> wrote: >> 2013/2/26 Peter Crosthwaite <peter.crosthwaite@xilinx.com>: >>> Hi Kuo-Jung, >>> >>> On Tue, Feb 26, 2013 at 7:14 PM, Kuo-Jung Su <dantesu@gmail.com> wrote: >>>> From: Kuo-Jung Su <dantesu@faraday-tech.com> >>>> >>>> The FTSPI020 is an integrated SPI Flash controller >>>> which supports upto 4 flash chips. >>>> >>>> Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com> >>>> --- >>> >>> Please provide change logs below the line as per the patch submission process. >>> >>>> hw/arm/Makefile.objs | 1 + >>>> hw/arm/faraday_a369.c | 13 ++ >>>> hw/arm/faraday_a369_soc.c | 4 + >>>> hw/arm/ftspi020.c | 333 +++++++++++++++++++++++++++++++++++++++++++++ >>>> hw/arm/ftspi020.h | 81 +++++++++++ >>>> 5 files changed, 432 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 c25eba2..2ed1c7c 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 += ftspi020.o >>>> diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c >>>> index 46fc570..ace0784 100644 >>>> --- a/hw/arm/faraday_a369.c >>>> +++ b/hw/arm/faraday_a369.c >>>> @@ -67,6 +67,19 @@ a369_board_init(QEMUMachineInitArgs *args) >>>> wm8731_data_req_set(s->codec, ftssp010_i2s_data_req, s->i2s[0]); >>>> } >>>> >>>> + /* 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[1], "spi"); >>>> + DeviceState *fl = ssi_create_slave_no_init(ssi, "m25p80"); >>>> + qemu_irq cs_line; >>>> + >>>> + qdev_prop_set_string(fl, "partname", "w25q64"); >>>> + qdev_init_nofail(fl); >>>> + cs_line = qdev_get_gpio_in(fl, 0); >>>> + sysbus_connect_irq(SYS_BUS_DEVICE(s->spi[1]), i + 1, cs_line); >>>> + } >>>> + >>>> if (args->kernel_filename) { >>>> s->bi = g_new0(struct arm_boot_info, 1); >>>> >>>> diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c >>>> index eb9dd2f..8b07689 100644 >>>> --- a/hw/arm/faraday_a369_soc.c >>>> +++ b/hw/arm/faraday_a369_soc.c >>>> @@ -272,6 +272,10 @@ a369soc_device_init(FaradaySoCState *s) >>>> 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); >>>> + >>>> + /* ftspi020: as an external AHB device */ >>>> + ds = sysbus_create_simple("ftspi020", 0xC0000000, pic[4]); >>>> + s->spi[1] = ds; >>>> } >>>> >>>> static int a369soc_init(SysBusDevice *busdev) >>>> diff --git a/hw/arm/ftspi020.c b/hw/arm/ftspi020.c >>>> new file mode 100644 >>>> index 0000000..fb8a510 >>>> --- /dev/null >>>> +++ b/hw/arm/ftspi020.c >>>> @@ -0,0 +1,333 @@ >>>> +/* >>>> + * Faraday FTSPI020 Flash Controller >>>> + * >>>> + * Copyright (c) 2012 Faraday Technology >>>> + * Written by Dante Su <dantesu@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) { >>>> + hw_error("ftspi020: bad dummy clock (%u) to QEMU\n", dcyc); >>>> + exit(1); >>>> + } >>>> + >>>> + /* make sure the spi flash is de-activated */ >>>> + qemu_set_irq(s->cs_lines[cs], 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); >>>> + >>>> + /* DO NOT reset cs lines here, or the QEMU would crash */ >>> >>> More information please. This should work. What happened? >>> >> >> If there is no spi flash connected with the specific cs_line, >> de-activate the cs_line >> in the ftspi020_chip_reset() would crash the QEMU without any error message. >> I've checked qemu_set_irq() and ssi_cs_default(), but no luck. >> > > It might be a case of un-initialised irqs. See my comment further below. > >>>> +} >>>> + >>>> +static uint64_t >>>> +ftspi020_mem_read(void *opaque, hwaddr addr, unsigned size) >>>> +{ >>>> + Ftspi020State *s = FTSPI020(opaque); >>>> + uint64_t ret = 0; >>>> + >>>> + switch (addr) { >>>> + case REG_CMD0 ... REG_CMD3: >>>> + return s->cmd[(addr - REG_CMD0) / 4]; >>>> + case REG_CR: >>>> + return s->ctrl; >>>> + case REG_TR: >>>> + return s->timing; >>>> + case REG_SR: >>>> + /* In QEMU, the data fifo is always ready for read/write */ >>>> + return SR_RX_READY | SR_TX_READY; >>>> + case REG_ISR: >>>> + return s->isr; >>>> + case REG_ICR: >>>> + return s->icr; >>>> + case REG_RDSR: >>>> + return s->rdsr; >>>> + case REG_REVR: >>>> + return 0x00010001; /* rev. 1.0.1 */ >>>> + case REG_FEAR: >>>> + return FEAR_CLKM_SYNC >>>> + | FEAR_CMDQ(2) | FEAR_RXFIFO(32) | FEAR_TXFIFO(32); >>>> + case REG_DR: >>>> + if (!(s->cmd[3] & CMD3_WRITE)) { >>>> + int i; >>>> + uint32_t cs = extract32(s->cmd[3], 8, 2); >>>> + for (i = 0; i < 4 && s->cmd[2]; i++, s->cmd[2]--) { >>>> + ret = deposit32(ret, i * 8, 8, >>>> + ssi_transfer(s->spi, 0x00) & 0xff); >>>> + } >>>> + if (!s->cmd[2]) { >>>> + qemu_set_irq(s->cs_lines[cs], 1); >>>> + if (s->cmd[3] & CMD3_INTR) { >>>> + s->isr |= ISR_CMDFIN; >>>> + } >>>> + ftspi020_update_irq(s); >>>> + } >>>> + } >>>> + break; >>>> + /* we don't care */ >>>> + default: >>> >>> You could qemu_log_mask(LOG_GUEST_ERROR on undefined memory accesses. >>> >> >> Got it, thanks. >> >>>> + break; >>>> + } >>>> + >>>> + return ret; >>>> +} >>>> + >>>> +static void >>>> +ftspi020_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) >>>> +{ >>>> + Ftspi020State *s = FTSPI020(opaque); >>>> + >>>> + switch (addr) { >>>> + case REG_CMD0 ... REG_CMD2: >>>> + s->cmd[(addr - REG_CMD0) / 4] = (uint32_t)val; >>>> + break; >>>> + case REG_CMD3: >>>> + s->cmd[3] = (uint32_t)val; >>>> + ftspi020_do_command(s); >>>> + break; >>>> + case REG_CR: >>>> + if (val & CR_ABORT) { >>>> + ftspi020_chip_reset(s); >>>> + val &= ~CR_ABORT; >>>> + } >>>> + s->ctrl = (uint32_t)val; >>>> + s->wip = extract32(val, 16, 3); >>>> + break; >>>> + case REG_TR: >>>> + s->timing = (uint32_t)val; >>>> + break; >>>> + case REG_DR: >>>> + if (s->cmd[3] & CMD3_WRITE) { >>>> + int i; >>>> + uint32_t cs = extract32(s->cmd[3], 8, 2); >>>> + for (i = 0; i < 4 && s->cmd[2]; i++, s->cmd[2]--) { >>>> + ssi_transfer(s->spi, extract32((uint32_t)val, i * 8, 8)); >>>> + } >>>> + if (!s->cmd[2]) { >>>> + qemu_set_irq(s->cs_lines[cs], 1); >>>> + if (s->cmd[3] & CMD3_INTR) { >>>> + s->isr |= ISR_CMDFIN; >>>> + } >>>> + ftspi020_update_irq(s); >>>> + } >>>> + } >>>> + break; >>>> + case REG_ISR: >>>> + s->isr &= ~((uint32_t)val); >>>> + ftspi020_update_irq(s); >>>> + break; >>>> + case REG_ICR: >>>> + s->icr = (uint32_t)val; >>>> + break; >>>> + /* we don't care */ >>>> + default: >>>> + break; >>>> + } >>>> +} >>>> + >>>> +static const MemoryRegionOps ftspi020_ops = { >>>> + .read = ftspi020_mem_read, >>>> + .write = ftspi020_mem_write, >>> >>> Your REG_FOO macros are jumping in fours, and the case statement in >>> your read/write handlers only handles those values, leading me to >>> believe your device only supports full word access. You should enforce >>> this by setting min/max_access size to 4 here. >>> >> >> Got it, thanks. >> >>> Regards, >>> Peter >>> >>>> + .endianness = DEVICE_LITTLE_ENDIAN, >>>> +}; >>>> + >>>> +static void ftspi020_reset(DeviceState *ds) >>>> +{ >>>> + SysBusDevice *busdev = SYS_BUS_DEVICE(ds); >>>> + Ftspi020State *s = FTSPI020(FROM_SYSBUS(Ftspi020State, busdev)); >>>> + >>>> + ftspi020_chip_reset(s); >>>> +} >>>> + >>>> +static int ftspi020_init(SysBusDevice *dev) >>>> +{ >>>> + Ftspi020State *s = FTSPI020(FROM_SYSBUS(Ftspi020State, dev)); >>>> + int i; >>>> + >>>> + memory_region_init_io(&s->iomem, >>>> + &ftspi020_ops, >>>> + s, >>>> + TYPE_FTSPI020, >>>> + 0x1000); >>>> + sysbus_init_mmio(dev, &s->iomem); >>>> + sysbus_init_irq(dev, &s->irq); >>>> + >>>> + s->spi = ssi_create_bus(&dev->qdev, "spi"); >>>> + s->cs_lines = g_new(qemu_irq, CFG_NR_CSLINES); > > s/g_new/g_new0. That will knock out your un-attached IRQ lines. You > may have contagiously contracted this bug from xilinx_spips I think. > My fix to spips is currently on list: > > commit d474fc0447fabaeb5f51ccbd88973c7f85ea1abe > Author: Peter Crosthwaite <peter.crosthwaite@xilinx.com> > Date: Thu Nov 29 14:39:56 2012 +1000 > > xilinx_spips: Set unused IRQs to NULL > > Unused CS lines should init to 0 to avoid segfaulting when accessing an > unattached QSPI controller. > > Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> > > diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c > index 42e019d..3eee828 100644 > --- a/hw/xilinx_spips.c > +++ b/hw/xilinx_spips.c > @@ -497,7 +497,7 @@ static int xilinx_spips_init(SysBusDevice *dev) > s->spi[i] = ssi_create_bus(&dev->qdev, bus_name); > } > > - s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses); > + s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); > ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); > ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); > sysbus_init_irq(dev, &s->irq); > > Regards, > Peter > You're absolutely right, after replacing 'g_new' with 'g_new0' for s->cs_lines, the FTSPI020 now works gracefully with de-activating the cs lines in its own reset functions. >>>> + ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi); >>>> + for (i = 0; i < CFG_NR_CSLINES; ++i) { >>>> + sysbus_init_irq(dev, &s->cs_lines[i]); >>>> + } >>>> + >>>> + qdev_init_gpio_in(&s->busdev.qdev, ftspi020_handle_ack, 1); >>>> + qdev_init_gpio_out(&s->busdev.qdev, &s->req, 1); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +static const VMStateDescription vmstate_ftspi020 = { >>>> + .name = TYPE_FTSPI020, >>>> + .version_id = 1, >>>> + .minimum_version_id = 1, >>>> + .minimum_version_id_old = 1, >>>> + .fields = (VMStateField[]) { >>>> + VMSTATE_UINT32_ARRAY(cmd, Ftspi020State, 4), >>>> + VMSTATE_UINT32(ctrl, Ftspi020State), >>>> + VMSTATE_UINT32(timing, Ftspi020State), >>>> + VMSTATE_UINT32(icr, Ftspi020State), >>>> + VMSTATE_UINT32(isr, Ftspi020State), >>>> + VMSTATE_UINT32(rdsr, Ftspi020State), >>>> + VMSTATE_END_OF_LIST(), >>>> + } >>>> +}; >>>> + >>>> +static void ftspi020_class_init(ObjectClass *klass, void *data) >>>> +{ >>>> + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); >>>> + DeviceClass *dc = DEVICE_CLASS(klass); >>>> + >>>> + k->init = ftspi020_init; >>>> + dc->vmsd = &vmstate_ftspi020; >>>> + dc->reset = ftspi020_reset; >>>> + dc->no_user = 1; >>>> +} >>>> + >>>> +static const TypeInfo ftspi020_info = { >>>> + .name = TYPE_FTSPI020, >>>> + .parent = TYPE_SYS_BUS_DEVICE, >>>> + .instance_size = sizeof(Ftspi020State), >>>> + .class_init = ftspi020_class_init, >>>> +}; >>>> + >>>> +static void ftspi020_register_types(void) >>>> +{ >>>> + type_register_static(&ftspi020_info); >>>> +} >>>> + >>>> +type_init(ftspi020_register_types) >>>> diff --git a/hw/arm/ftspi020.h b/hw/arm/ftspi020.h >>>> new file mode 100644 >>>> index 0000000..47b5d2e >>>> --- /dev/null >>>> +++ b/hw/arm/ftspi020.h >>>> @@ -0,0 +1,81 @@ >>>> +/* >>>> + * Faraday FTSPI020 Flash Controller >>>> + * >>>> + * Copyright (c) 2012 Faraday Technology >>>> + * Written by Dante Su <dantesu@faraday-tech.com> >>>> + * >>>> + * This code is licensed under GNU GPL v2+. >>>> + */ >>>> + >>>> +#ifndef HW_ARM_FTSPI020_H >>>> +#define HW_ARM_FTSPI020_H >>>> + >>>> +#include "qemu/bitops.h" >>>> + >>>> +/* Number of CS lines */ >>>> +#define CFG_NR_CSLINES 4 >>>> + >>>> +/****************************************************************************** >>>> + * FTSPI020 registers >>>> + *****************************************************************************/ >>>> +#define REG_CMD0 0x00 /* Flash address */ >>>> +#define REG_CMD1 0x04 >>>> +#define REG_CMD2 0x08 /* Flash data counter */ >>>> +#define REG_CMD3 0x0c >>>> +#define REG_CR 0x10 /* Control Register */ >>>> +#define REG_TR 0x14 /* AC Timing Register */ >>>> +#define REG_SR 0x18 /* Status Register */ >>>> +#define REG_ICR 0x20 /* Interrupt Control Register */ >>>> +#define REG_ISR 0x24 /* Interrupt Status Register */ >>>> +#define REG_RDSR 0x28 /* Read Status Register */ >>>> +#define REG_REVR 0x50 /* Revision Register */ >>>> +#define REG_FEAR 0x54 /* Feature Register */ >>>> +#define REG_DR 0x100 /* Data Register */ >>>> + >>>> +#define CMD1_CTRD BIT(28) /* Enable 1 byte continuous read */ >>>> +#define CMD1_INST_LEN(x) (((x) & 0x03) << 24)/* instruction length */ >>>> +#define CMD1_DCLK_LEN(x) (((x) & 0xff) << 16)/* dummy clock length */ >>>> +#define CMD1_ADDR_LEN(x) (((x) & 0x07) << 0) /* address length */ >>>> + >>>> +#define CMD3_INST_OPC(x) (((x) & 0xff) << 24)/* instruction op code */ >>>> +#define CMD3_CTRD_OPC(x) (((x) & 0xff) << 16)/* cont. read op code */ >>>> +#define CMD3_CS(x) (((x) & 0x0f) << 8) /* chip select */ >>>> +#define CMD3_OPM_STD (0) /* standard 1-bit serial mode */ >>>> +#define CMD3_OPM_DUAL (1 << 5) /* fast read dual */ >>>> +#define CMD3_OPM_QUAD (2 << 5) /* fast read quad */ >>>> +#define CMD3_OPM_DUALIO (3 << 5) /* fast read dual io */ >>>> +#define CMD3_OPM_QUADIO (4 << 5) /* fast read quad io */ >>>> +#define CMD3_DTR BIT(4) /* Enable double transfer rate */ >>>> +#define CMD3_RDSR_HW (0) /* Enable HW polling RDSR */ >>>> +#define CMD3_RDSR_SW BIT(3) /* Disable HW polling RDSR */ >>>> +#define CMD3_RDSR BIT(2) /* Indicate it's a RDSR command */ >>>> +#define CMD3_READ 0 /* Indicate it's a read command */ >>>> +#define CMD3_WRITE BIT(1) /* Indicate it's a write command */ >>>> +#define CMD3_INTR BIT(0) /* Enable interrupt and status update */ >>>> + >>>> +#define CR_BUSYBIT(x) (((x) & 0x07) << 16) /* Busy bit in the RDSR */ >>>> +#define CR_ABORT BIT(8) >>>> +#define CR_MODE0 0 /* SPI MODE0 */ >>>> +#define CR_MODE3 BIT(4) /* SPI MODE3 */ >>>> +#define CR_CLKDIV(n) ((n) & 0x03) /* Clock divider = 2 * (n + 1) */ >>>> + >>>> +#define TR_TRACE(x) (((x) & 0x0f) << 4) /* trace delay */ >>>> +#define TR_CS(x) (((x) & 0x0f) << 0) /* cs delay */ >>>> + >>>> +#define SR_RX_READY BIT(1) /* Rx Ready */ >>>> +#define SR_TX_READY BIT(0) /* Tx Ready */ >>>> + >>>> +#define ICR_RX_THRES(x) (((x) & 0x03) << 12)/* rx interrupt threshold */ >>>> +#define ICR_TX_THRES(x) (((x) & 0x03) << 8) /* tx interrupt threshold */ >>>> +#define ICR_DMA BIT(0) /* Enable DMA HW handshake */ >>>> + >>>> +#define ISR_CMDFIN BIT(0) /* Command finished interrupt */ >>>> + >>>> +#define FEAR_CLKM_BYPORT 0 /* clock mode = byport */ >>>> +#define FEAR_CLKM_SYNC BIT(25) /* clock mode = sync */ >>>> +#define FEAR_SUPP_DTR BIT(24) /* support double transfer rate */ >>>> +#define FEAR_CMDQ(x) (((x) & 0x07) << 16) /* cmd queue depth */ >>>> +#define FEAR_RXFIFO(x) (((x) & 0xff) << 8) /* rx fifo depth */ >>>> +#define FEAR_TXFIFO(x) (((x) & 0xff) << 0) /* tx fifo depth */ >>>> + >>>> +#endif /* HW_ARM_FTSPI020_H */ >>>> -- >>>> 1.7.9.5 >>>> >>>> >> >> >> >> -- >> Best wishes, >> Kuo-Jung Su >> -- Best wishes, Kuo-Jung Su
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c index 42e019d..3eee828 100644 --- a/hw/xilinx_spips.c +++ b/hw/xilinx_spips.c @@ -497,7 +497,7 @@ static int xilinx_spips_init(SysBusDevice *dev) s->spi[i] = ssi_create_bus(&dev->qdev, bus_name); } - s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses); + s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]); ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]); sysbus_init_irq(dev, &s->irq);