[{"id":1763830,"web_url":"http://patchwork.ozlabs.org/comment/1763830/","msgid":"<CALHRZurCYW+B2e+Ru62VH2VJJQfL1gNkz+OF=G9YD+VptDXhtw@mail.gmail.com>","list_archive_url":null,"date":"2017-09-06T06:11:00","subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","submitter":{"id":64324,"url":"http://patchwork.ozlabs.org/api/people/64324/","name":"sundeep subbaraya","email":"sundeep.lkml@gmail.com"},"content":"Ping.\n\nThanks,\nSundeep\n\nOn Mon, Aug 28, 2017 at 10:08 PM, Subbaraya Sundeep <sundeep.lkml@gmail.com>\nwrote:\n\n> Modelled Microsemi's Smartfusion2 SPI controller.\n>\n> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> ---\n>  hw/ssi/Makefile.objs     |   1 +\n>  hw/ssi/mss-spi.c         | 409 ++++++++++++++++++++++++++++++\n> +++++++++++++++++\n>  include/hw/ssi/mss-spi.h |  58 +++++++\n>  3 files changed, 468 insertions(+)\n>  create mode 100644 hw/ssi/mss-spi.c\n>  create mode 100644 include/hw/ssi/mss-spi.h\n>\n> diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs\n> index 487add2..f5bcc65 100644\n> --- a/hw/ssi/Makefile.objs\n> +++ b/hw/ssi/Makefile.objs\n> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o\n>  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o\n>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o\n>  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o\n> +common-obj-$(CONFIG_MSF2) += mss-spi.o\n>\n>  obj-$(CONFIG_OMAP) += omap_spi.o\n>  obj-$(CONFIG_IMX) += imx_spi.o\n> diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c\n> new file mode 100644\n> index 0000000..7209363\n> --- /dev/null\n> +++ b/hw/ssi/mss-spi.c\n> @@ -0,0 +1,409 @@\n> +/*\n> + * Block model of SPI controller present in\n> + * Microsemi's SmartFusion2 and SmartFusion SoCs.\n> + *\n> + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> + *\n> + * Permission is hereby granted, free of charge, to any person obtaining\n> a copy\n> + * of this software and associated documentation files (the \"Software\"),\n> to deal\n> + * in the Software without restriction, including without limitation the\n> rights\n> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or\n> sell\n> + * copies of the Software, and to permit persons to whom the Software is\n> + * furnished to do so, subject to the following conditions:\n> + *\n> + * The above copyright notice and this permission notice shall be\n> included in\n> + * all copies or substantial portions of the Software.\n> + *\n> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR\n> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY,\n> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n> OTHER\n> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n> ARISING FROM,\n> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n> IN\n> + * THE SOFTWARE.\n> + */\n> +\n> +#include \"qemu/osdep.h\"\n> +#include \"hw/ssi/mss-spi.h\"\n> +#include \"qemu/log.h\"\n> +\n> +#ifndef MSS_SPI_ERR_DEBUG\n> +#define MSS_SPI_ERR_DEBUG   0\n> +#endif\n> +\n> +#define DB_PRINT_L(lvl, fmt, args...) do { \\\n> +    if (MSS_SPI_ERR_DEBUG >= lvl) { \\\n> +        qemu_log(\"%s: \" fmt \"\\n\", __func__, ## args); \\\n> +    } \\\n> +} while (0);\n> +\n> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)\n> +\n> +#define FIFO_CAPACITY         32\n> +#define FIFO_CAPACITY         32\n> +\n> +#define R_SPI_CONTROL         0\n> +#define R_SPI_DFSIZE          1\n> +#define R_SPI_STATUS          2\n> +#define R_SPI_INTCLR          3\n> +#define R_SPI_RX              4\n> +#define R_SPI_TX              5\n> +#define R_SPI_CLKGEN          6\n> +#define R_SPI_SS              7\n> +#define R_SPI_MIS             8\n> +#define R_SPI_RIS             9\n> +\n> +#define S_TXDONE             (1 << 0)\n> +#define S_RXRDY              (1 << 1)\n> +#define S_RXCHOVRF           (1 << 2)\n> +#define S_RXFIFOFUL          (1 << 4)\n> +#define S_RXFIFOFULNXT       (1 << 5)\n> +#define S_RXFIFOEMP          (1 << 6)\n> +#define S_RXFIFOEMPNXT       (1 << 7)\n> +#define S_TXFIFOFUL          (1 << 8)\n> +#define S_TXFIFOFULNXT       (1 << 9)\n> +#define S_TXFIFOEMP          (1 << 10)\n> +#define S_TXFIFOEMPNXT       (1 << 11)\n> +#define S_FRAMESTART         (1 << 12)\n> +#define S_SSEL               (1 << 13)\n> +#define S_ACTIVE             (1 << 14)\n> +\n> +#define C_ENABLE             (1 << 0)\n> +#define C_MODE               (1 << 1)\n> +#define C_INTRXDATA          (1 << 4)\n> +#define C_INTTXDATA          (1 << 5)\n> +#define C_INTRXOVRFLO        (1 << 6)\n> +#define C_SPS                (1 << 26)\n> +#define C_BIGFIFO            (1 << 29)\n> +#define C_RESET              (1 << 31)\n> +\n> +#define FRAMESZ_MASK         0x1F\n> +#define FMCOUNT_MASK         0x00FFFF00\n> +#define FMCOUNT_SHIFT        8\n> +\n> +static void txfifo_reset(MSSSpiState *s)\n> +{\n> +    fifo32_reset(&s->tx_fifo);\n> +\n> +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;\n> +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;\n> +}\n> +\n> +static void rxfifo_reset(MSSSpiState *s)\n> +{\n> +    fifo32_reset(&s->rx_fifo);\n> +\n> +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> +}\n> +\n> +static void set_fifodepth(MSSSpiState *s)\n> +{\n> +    unsigned int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;\n> +\n> +    if (size <= 8) {\n> +        s->fifo_depth = 32;\n> +    } else if (size <= 16) {\n> +        s->fifo_depth = 16;\n> +    } else if (size <= 32) {\n> +        s->fifo_depth = 8;\n> +    } else {\n> +        s->fifo_depth = 4;\n> +    }\n> +}\n> +\n> +static void mss_spi_do_reset(MSSSpiState *s)\n> +{\n> +    memset(s->regs, 0, sizeof s->regs);\n> +    s->regs[R_SPI_CONTROL] = 0x80000102;\n> +    s->regs[R_SPI_DFSIZE] = 0x4;\n> +    s->regs[R_SPI_STATUS] = S_SSEL | S_TXFIFOEMP | S_RXFIFOEMP;\n> +    s->regs[R_SPI_CLKGEN] = 0x7;\n> +    s->regs[R_SPI_RIS] = 0x0;\n> +\n> +    s->fifo_depth = 4;\n> +    s->frame_count = 1;\n> +    s->enabled = false;\n> +\n> +    rxfifo_reset(s);\n> +    txfifo_reset(s);\n> +}\n> +\n> +static void update_mis(MSSSpiState *s)\n> +{\n> +    uint32_t reg = s->regs[R_SPI_CONTROL];\n> +    uint32_t tmp;\n> +\n> +    /*\n> +     * form the Control register interrupt enable bits\n> +     * same as RIS, MIS and Interrupt clear registers for simplicity\n> +     */\n> +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |\n> +           ((reg & C_INTTXDATA) >> 5);\n> +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];\n> +}\n> +\n> +static void spi_update_irq(MSSSpiState *s)\n> +{\n> +    int irq;\n> +\n> +    update_mis(s);\n> +    irq = !!(s->regs[R_SPI_MIS]);\n> +\n> +    qemu_set_irq(s->irq, irq);\n> +}\n> +\n> +static void mss_spi_reset(DeviceState *d)\n> +{\n> +    mss_spi_do_reset(MSS_SPI(d));\n> +}\n> +\n> +static uint64_t\n> +spi_read(void *opaque, hwaddr addr, unsigned int size)\n> +{\n> +    MSSSpiState *s = opaque;\n> +    uint32_t ret = 0;\n> +\n> +    addr >>= 2;\n> +    switch (addr) {\n> +    case R_SPI_RX:\n> +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> +        s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;\n> +        ret = fifo32_pop(&s->rx_fifo);\n> +        if (fifo32_is_empty(&s->rx_fifo)) {\n> +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> +        }\n> +        break;\n> +\n> +    case R_SPI_MIS:\n> +        update_mis(s);\n> +        ret = s->regs[R_SPI_MIS];\n> +        break;\n> +\n> +    default:\n> +        if (addr < ARRAY_SIZE(s->regs)) {\n> +            ret = s->regs[addr];\n> +        } else {\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\", __func__,\n> +                         addr * 4);\n> +        }\n> +        break;\n> +    }\n> +\n> +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" = 0x%\" PRIx32, addr * 4, ret);\n> +    spi_update_irq(s);\n> +    return ret;\n> +}\n> +\n> +static void assert_cs(MSSSpiState *s)\n> +{\n> +    qemu_set_irq(s->cs_line, 0);\n> +}\n> +\n> +static void deassert_cs(MSSSpiState *s)\n> +{\n> +    qemu_set_irq(s->cs_line, 1);\n> +}\n> +\n> +static void spi_flush_txfifo(MSSSpiState *s)\n> +{\n> +    uint32_t tx;\n> +    uint32_t rx;\n> +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);\n> +\n> +    /*\n> +     * Chip Select(CS) is automatically controlled by this controller.\n> +     * If SPS bit is set in Control register then CS is asserted\n> +     * until all the frames set in frame count of Control register are\n> +     * transferred. If SPS is not set then CS pulses between frames.\n> +     * Note that Slave Select register specifies which of the CS line\n> +     * has to be controlled automatically by controller. Bits SS[7:1] are\n> for\n> +     * masters in FPGA fabric since we model only Microcontroller\n> subsystem\n> +     * of Smartfusion2 we control only one CS(SS[0]) line.\n> +     */\n> +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {\n> +        assert_cs(s);\n> +\n> +        s->regs[R_SPI_STATUS] &= ~(S_TXDONE | S_RXRDY);\n> +\n> +        tx = fifo32_pop(&s->tx_fifo);\n> +        DB_PRINT(\"data tx:0x%\" PRIx32, tx);\n> +        rx = ssi_transfer(s->spi, tx);\n> +        DB_PRINT(\"data rx:0x%\" PRIx32, rx);\n> +\n> +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> +            s->regs[R_SPI_STATUS] |= S_RXCHOVRF;\n> +            s->regs[R_SPI_RIS] |= S_RXCHOVRF;\n> +        } else {\n> +            fifo32_push(&s->rx_fifo, rx);\n> +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;\n> +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {\n> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;\n> +            } else if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;\n> +            }\n> +        }\n> +        s->frame_count--;\n> +        if (!sps) {\n> +            deassert_cs(s);\n> +        }\n> +    }\n> +\n> +    if (!s->frame_count) {\n> +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>\n> +                            FMCOUNT_SHIFT;\n> +        if (sps) {\n> +            deassert_cs(s);\n> +        }\n> +        s->regs[R_SPI_RIS] |= S_TXDONE | S_RXRDY;\n> +        s->regs[R_SPI_STATUS] |= S_TXDONE | S_RXRDY;\n> +   }\n> +}\n> +\n> +static void spi_write(void *opaque, hwaddr addr,\n> +            uint64_t val64, unsigned int size)\n> +{\n> +    MSSSpiState *s = opaque;\n> +    uint32_t value = val64;\n> +\n> +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" =0x%\" PRIx32, addr, value);\n> +    addr >>= 2;\n> +\n> +    switch (addr) {\n> +    case R_SPI_TX:\n> +        /* adding to already full FIFO */\n> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> +            break;\n> +        }\n> +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;\n> +        fifo32_push(&s->tx_fifo, value);\n> +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {\n> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;\n> +        } else if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;\n> +        }\n> +        if (s->enabled) {\n> +            spi_flush_txfifo(s);\n> +        }\n> +        break;\n> +\n> +    case R_SPI_CONTROL:\n> +        s->regs[R_SPI_CONTROL] = value;\n> +        if (value & C_BIGFIFO) {\n> +            set_fifodepth(s);\n> +        } else {\n> +            s->fifo_depth = 4;\n> +        }\n> +        s->enabled = value & C_ENABLE;\n> +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;\n> +        if (value & C_RESET) {\n> +            mss_spi_do_reset(s);\n> +        }\n> +        break;\n> +\n> +    case R_SPI_DFSIZE:\n> +        if (s->enabled) {\n> +            break;\n> +        }\n> +        s->regs[R_SPI_DFSIZE] = value;\n> +        break;\n> +\n> +    case R_SPI_INTCLR:\n> +        s->regs[R_SPI_INTCLR] = value;\n> +        if (value & S_TXDONE) {\n> +            s->regs[R_SPI_RIS] &= ~S_TXDONE;\n> +        }\n> +        if (value & S_RXRDY) {\n> +            s->regs[R_SPI_RIS] &= ~S_RXRDY;\n> +        }\n> +        if (value & S_RXCHOVRF) {\n> +            s->regs[R_SPI_RIS] &= ~S_RXCHOVRF;\n> +        }\n> +        break;\n> +\n> +    case R_SPI_MIS:\n> +    case R_SPI_STATUS:\n> +    case R_SPI_RIS:\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Write to read only register 0x%\"\n> HWADDR_PRIx \"\\n\",\n> +                         __func__, addr * 4);\n> +        break;\n> +\n> +    default:\n> +        if (addr < ARRAY_SIZE(s->regs)) {\n> +            s->regs[addr] = value;\n> +        } else {\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\", __func__,\n> +                         addr * 4);\n> +        }\n> +        break;\n> +    }\n> +\n> +    spi_update_irq(s);\n> +}\n> +\n> +static const MemoryRegionOps spi_ops = {\n> +    .read = spi_read,\n> +    .write = spi_write,\n> +    .endianness = DEVICE_NATIVE_ENDIAN,\n> +    .valid = {\n> +        .min_access_size = 1,\n> +        .max_access_size = 4\n> +    }\n> +};\n> +\n> +static void mss_spi_realize(DeviceState *dev, Error **errp)\n> +{\n> +    MSSSpiState *s = MSS_SPI(dev);\n> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);\n> +\n> +    s->spi = ssi_create_bus(dev, \"spi\");\n> +\n> +    sysbus_init_irq(sbd, &s->irq);\n> +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);\n> +    sysbus_init_irq(sbd, &s->cs_line);\n> +\n> +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,\n> +                          TYPE_MSS_SPI, R_SPI_MAX * 4);\n> +    sysbus_init_mmio(sbd, &s->mmio);\n> +\n> +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);\n> +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);\n> +}\n> +\n> +static const VMStateDescription vmstate_mss_spi = {\n> +    .name = TYPE_MSS_SPI,\n> +    .version_id = 1,\n> +    .minimum_version_id = 1,\n> +    .fields = (VMStateField[]) {\n> +        VMSTATE_FIFO32(tx_fifo, MSSSpiState),\n> +        VMSTATE_FIFO32(rx_fifo, MSSSpiState),\n> +        VMSTATE_UINT32_ARRAY(regs, MSSSpiState, R_SPI_MAX),\n> +        VMSTATE_END_OF_LIST()\n> +    }\n> +};\n> +\n> +static void mss_spi_class_init(ObjectClass *klass, void *data)\n> +{\n> +    DeviceClass *dc = DEVICE_CLASS(klass);\n> +\n> +    dc->realize = mss_spi_realize;\n> +    dc->reset = mss_spi_reset;\n> +    dc->vmsd = &vmstate_mss_spi;\n> +}\n> +\n> +static const TypeInfo mss_spi_info = {\n> +    .name           = TYPE_MSS_SPI,\n> +    .parent         = TYPE_SYS_BUS_DEVICE,\n> +    .instance_size  = sizeof(MSSSpiState),\n> +    .class_init     = mss_spi_class_init,\n> +};\n> +\n> +static void mss_spi_register_types(void)\n> +{\n> +    type_register_static(&mss_spi_info);\n> +}\n> +\n> +type_init(mss_spi_register_types)\n> diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h\n> new file mode 100644\n> index 0000000..f0cf324\n> --- /dev/null\n> +++ b/include/hw/ssi/mss-spi.h\n> @@ -0,0 +1,58 @@\n> +/*\n> + * Microsemi SmartFusion2 SPI\n> + *\n> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> + *\n> + * Permission is hereby granted, free of charge, to any person obtaining\n> a copy\n> + * of this software and associated documentation files (the \"Software\"),\n> to deal\n> + * in the Software without restriction, including without limitation the\n> rights\n> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or\n> sell\n> + * copies of the Software, and to permit persons to whom the Software is\n> + * furnished to do so, subject to the following conditions:\n> + *\n> + * The above copyright notice and this permission notice shall be\n> included in\n> + * all copies or substantial portions of the Software.\n> + *\n> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR\n> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY,\n> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n> OTHER\n> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n> ARISING FROM,\n> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n> IN\n> + * THE SOFTWARE.\n> + */\n> +\n> +#ifndef HW_MSS_SPI_H\n> +#define HW_MSS_SPI_H\n> +\n> +#include \"hw/sysbus.h\"\n> +#include \"hw/ssi/ssi.h\"\n> +#include \"qemu/fifo32.h\"\n> +\n> +#define TYPE_MSS_SPI   \"mss-spi\"\n> +#define MSS_SPI(obj)   OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI)\n> +\n> +#define R_SPI_MAX             16\n> +\n> +typedef struct MSSSpiState {\n> +    SysBusDevice parent_obj;\n> +\n> +    MemoryRegion mmio;\n> +\n> +    qemu_irq irq;\n> +\n> +    qemu_irq cs_line;\n> +\n> +    SSIBus *spi;\n> +\n> +    Fifo32 rx_fifo;\n> +    Fifo32 tx_fifo;\n> +\n> +    int fifo_depth;\n> +    uint32_t frame_count;\n> +    bool enabled;\n> +\n> +    uint32_t regs[R_SPI_MAX];\n> +} MSSSpiState;\n> +\n> +#endif /* HW_MSS_SPI_H */\n> --\n> 2.5.0\n>\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"P8BFLn+W\"; dkim-atps=neutral"],"Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xnCsd0dmXz9s2G\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed,  6 Sep 2017 16:12:05 +1000 (AEST)","from localhost ([::1]:34337 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dpTZD-0003Y7-7X\n\tfor incoming@patchwork.ozlabs.org; Wed, 06 Sep 2017 02:12:03 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:60012)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <sundeep.lkml@gmail.com>) id 1dpTYI-0003CL-KJ\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 02:11:10 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <sundeep.lkml@gmail.com>) id 1dpTYF-0001gW-7Q\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 02:11:06 -0400","from mail-vk0-x231.google.com ([2607:f8b0:400c:c05::231]:35350)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <sundeep.lkml@gmail.com>)\n\tid 1dpTYE-0001fr-Vq; Wed, 06 Sep 2017 02:11:03 -0400","by mail-vk0-x231.google.com with SMTP id m142so2884610vkf.2;\n\tTue, 05 Sep 2017 23:11:01 -0700 (PDT)","by 10.176.75.196 with HTTP; Tue, 5 Sep 2017 23:11:00 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=mime-version:in-reply-to:references:from:date:message-id:subject:to\n\t:cc; bh=hNGAXDSNnhXCNjSo4A5OecgYwdfATkJqD41vmn4Q4Ag=;\n\tb=P8BFLn+WynjSkkicxSM/Jj9L8kcHHn3rGIe2LQC2NcD0Z8p5mAVLBVFpmLJpDGklIv\n\tbNTeR1Ftal7khMJSn3wzSgj8nRUlr35KxydBPrH5FRwwRnAk/RgJOOdOVM3crpc5Eb9O\n\tUyBJmwekXeb39dHiLdnarQCZmTOknYZmldmMXQCSAl25vUMSW6MsHuSUffV+jCQh7L35\n\tZx255sF342pL10uHZd/8wFzT7N1G0YlsgfsoL2TLXcJwEWZcUzP7AUsUT0ZYIa+hwuz3\n\t2GWPiZSQNfgwu4QrP5g+KDZOFqSqon8flKC4agn76iQK6Pf7ABH9QbCS5gmiaKpN0evt\n\t7GlQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:in-reply-to:references:from:date\n\t:message-id:subject:to:cc;\n\tbh=hNGAXDSNnhXCNjSo4A5OecgYwdfATkJqD41vmn4Q4Ag=;\n\tb=FTQDTTzwhUdPGvdPXy13xr3CAxHX3kqx1ljUrVYS005ea+wUXX5sJEEs2PzuqMsgPf\n\tQ0F8CV7CE3j7CUCszG0Ydbo5Utat5SyS4Ih7vQdAoDQu21Il7oPY4Pc7U59PKTyTBes8\n\tcMIQ/RtpzkNt6ljGaWCnE6nHuQ4FKtp0J0Y85QrpDbpE4ly9hNgmOXOaAO83M0inBUnM\n\tnYcjbQm5ga62GeQeYWjf2g28Ti1glG0BXS1ZItZJiQoyRMNMLegxrw4z7KRXLJwV0wnz\n\tKrLlnN7n4XNM7s+syIBVJpEAN9UeCiXPz1TLfZNQYqTJy+cYcBZL8o2rYeEr1+cTkzGM\n\t2e8A==","X-Gm-Message-State":"AHPjjUhzWOuMJ5lvHaGUR5tfRRfBdZ0+CnFtHU5OpyXTKhpGqt6XBwNC\n\tJIOOGjtxntCHg77FhUyFl/Re+AHJHA==","X-Google-Smtp-Source":"ADKCNb53zW0ayX3oWXueRyH8qWn1jLX4vkvVwrwe2VWDsVvZEdwI85UfyviYgLerfKrw8OYU+eS6Qvj6njZ83qBtPhk=","X-Received":"by 10.31.181.208 with SMTP id e199mr868337vkf.55.1504678260920; \n\tTue, 05 Sep 2017 23:11:00 -0700 (PDT)","MIME-Version":"1.0","In-Reply-To":"<1503938283-12404-4-git-send-email-sundeep.lkml@gmail.com>","References":"<1503938283-12404-1-git-send-email-sundeep.lkml@gmail.com>\n\t<1503938283-12404-4-git-send-email-sundeep.lkml@gmail.com>","From":"sundeep subbaraya <sundeep.lkml@gmail.com>","Date":"Wed, 6 Sep 2017 11:41:00 +0530","Message-ID":"<CALHRZurCYW+B2e+Ru62VH2VJJQfL1gNkz+OF=G9YD+VptDXhtw@mail.gmail.com>","To":"QEMU Developers <qemu-devel@nongnu.org>, qemu-arm <qemu-arm@nongnu.org>","X-detected-operating-system":"by eggs.gnu.org: Genre and OS details not\n\trecognized.","X-Received-From":"2607:f8b0:400c:c05::231","Content-Type":"text/plain; charset=\"UTF-8\"","X-Content-Filtered-By":"Mailman/MimeDel 2.1.21","Subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"Peter Maydell <peter.maydell@linaro.org>, Subbaraya Sundeep\n\t<sundeep.lkml@gmail.com>, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?=\n\t<f4bug@amsat.org>, \tAlistair Francis <alistair23@gmail.com>,\n\tPeter Crosthwaite <crosthwaite.peter@gmail.com>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"}},{"id":1764351,"web_url":"http://patchwork.ozlabs.org/comment/1764351/","msgid":"<CAKmqyKPTENTDXp=jEiaecC3RqnBb6jUHKCPkyXi6gnsVYoqrqA@mail.gmail.com>","list_archive_url":null,"date":"2017-09-06T20:29:13","subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","submitter":{"id":64571,"url":"http://patchwork.ozlabs.org/api/people/64571/","name":"Alistair Francis","email":"alistair23@gmail.com"},"content":"On Mon, Aug 28, 2017 at 9:38 AM, Subbaraya Sundeep\n<sundeep.lkml@gmail.com> wrote:\n> Modelled Microsemi's Smartfusion2 SPI controller.\n>\n> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> ---\n>  hw/ssi/Makefile.objs     |   1 +\n>  hw/ssi/mss-spi.c         | 409 +++++++++++++++++++++++++++++++++++++++++++++++\n>  include/hw/ssi/mss-spi.h |  58 +++++++\n>  3 files changed, 468 insertions(+)\n>  create mode 100644 hw/ssi/mss-spi.c\n>  create mode 100644 include/hw/ssi/mss-spi.h\n>\n> diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs\n> index 487add2..f5bcc65 100644\n> --- a/hw/ssi/Makefile.objs\n> +++ b/hw/ssi/Makefile.objs\n> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o\n>  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o\n>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o\n>  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o\n> +common-obj-$(CONFIG_MSF2) += mss-spi.o\n>\n>  obj-$(CONFIG_OMAP) += omap_spi.o\n>  obj-$(CONFIG_IMX) += imx_spi.o\n> diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c\n> new file mode 100644\n> index 0000000..7209363\n> --- /dev/null\n> +++ b/hw/ssi/mss-spi.c\n> @@ -0,0 +1,409 @@\n> +/*\n> + * Block model of SPI controller present in\n> + * Microsemi's SmartFusion2 and SmartFusion SoCs.\n> + *\n> + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> + *\n> + * Permission is hereby granted, free of charge, to any person obtaining a copy\n> + * of this software and associated documentation files (the \"Software\"), to deal\n> + * in the Software without restriction, including without limitation the rights\n> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> + * copies of the Software, and to permit persons to whom the Software is\n> + * furnished to do so, subject to the following conditions:\n> + *\n> + * The above copyright notice and this permission notice shall be included in\n> + * all copies or substantial portions of the Software.\n> + *\n> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> + * THE SOFTWARE.\n> + */\n> +\n> +#include \"qemu/osdep.h\"\n> +#include \"hw/ssi/mss-spi.h\"\n> +#include \"qemu/log.h\"\n> +\n> +#ifndef MSS_SPI_ERR_DEBUG\n> +#define MSS_SPI_ERR_DEBUG   0\n> +#endif\n> +\n> +#define DB_PRINT_L(lvl, fmt, args...) do { \\\n> +    if (MSS_SPI_ERR_DEBUG >= lvl) { \\\n> +        qemu_log(\"%s: \" fmt \"\\n\", __func__, ## args); \\\n> +    } \\\n> +} while (0);\n> +\n> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)\n> +\n> +#define FIFO_CAPACITY         32\n> +#define FIFO_CAPACITY         32\n\nDouble define?\n\n> +\n> +#define R_SPI_CONTROL         0\n> +#define R_SPI_DFSIZE          1\n> +#define R_SPI_STATUS          2\n> +#define R_SPI_INTCLR          3\n> +#define R_SPI_RX              4\n> +#define R_SPI_TX              5\n> +#define R_SPI_CLKGEN          6\n> +#define R_SPI_SS              7\n> +#define R_SPI_MIS             8\n> +#define R_SPI_RIS             9\n> +\n> +#define S_TXDONE             (1 << 0)\n> +#define S_RXRDY              (1 << 1)\n> +#define S_RXCHOVRF           (1 << 2)\n> +#define S_RXFIFOFUL          (1 << 4)\n> +#define S_RXFIFOFULNXT       (1 << 5)\n> +#define S_RXFIFOEMP          (1 << 6)\n> +#define S_RXFIFOEMPNXT       (1 << 7)\n> +#define S_TXFIFOFUL          (1 << 8)\n> +#define S_TXFIFOFULNXT       (1 << 9)\n> +#define S_TXFIFOEMP          (1 << 10)\n> +#define S_TXFIFOEMPNXT       (1 << 11)\n> +#define S_FRAMESTART         (1 << 12)\n> +#define S_SSEL               (1 << 13)\n> +#define S_ACTIVE             (1 << 14)\n> +\n> +#define C_ENABLE             (1 << 0)\n> +#define C_MODE               (1 << 1)\n> +#define C_INTRXDATA          (1 << 4)\n> +#define C_INTTXDATA          (1 << 5)\n> +#define C_INTRXOVRFLO        (1 << 6)\n> +#define C_SPS                (1 << 26)\n> +#define C_BIGFIFO            (1 << 29)\n> +#define C_RESET              (1 << 31)\n> +\n> +#define FRAMESZ_MASK         0x1F\n> +#define FMCOUNT_MASK         0x00FFFF00\n> +#define FMCOUNT_SHIFT        8\n> +\n> +static void txfifo_reset(MSSSpiState *s)\n> +{\n> +    fifo32_reset(&s->tx_fifo);\n> +\n> +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;\n> +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;\n> +}\n> +\n> +static void rxfifo_reset(MSSSpiState *s)\n> +{\n> +    fifo32_reset(&s->rx_fifo);\n> +\n> +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> +}\n> +\n> +static void set_fifodepth(MSSSpiState *s)\n> +{\n> +    unsigned int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;\n> +\n> +    if (size <= 8) {\n> +        s->fifo_depth = 32;\n> +    } else if (size <= 16) {\n> +        s->fifo_depth = 16;\n> +    } else if (size <= 32) {\n> +        s->fifo_depth = 8;\n> +    } else {\n> +        s->fifo_depth = 4;\n> +    }\n> +}\n> +\n> +static void mss_spi_do_reset(MSSSpiState *s)\n> +{\n> +    memset(s->regs, 0, sizeof s->regs);\n> +    s->regs[R_SPI_CONTROL] = 0x80000102;\n> +    s->regs[R_SPI_DFSIZE] = 0x4;\n> +    s->regs[R_SPI_STATUS] = S_SSEL | S_TXFIFOEMP | S_RXFIFOEMP;\n> +    s->regs[R_SPI_CLKGEN] = 0x7;\n> +    s->regs[R_SPI_RIS] = 0x0;\n> +\n> +    s->fifo_depth = 4;\n> +    s->frame_count = 1;\n> +    s->enabled = false;\n> +\n> +    rxfifo_reset(s);\n> +    txfifo_reset(s);\n> +}\n> +\n> +static void update_mis(MSSSpiState *s)\n> +{\n> +    uint32_t reg = s->regs[R_SPI_CONTROL];\n> +    uint32_t tmp;\n> +\n> +    /*\n> +     * form the Control register interrupt enable bits\n> +     * same as RIS, MIS and Interrupt clear registers for simplicity\n> +     */\n> +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |\n> +           ((reg & C_INTTXDATA) >> 5);\n> +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];\n> +}\n> +\n> +static void spi_update_irq(MSSSpiState *s)\n> +{\n> +    int irq;\n> +\n> +    update_mis(s);\n> +    irq = !!(s->regs[R_SPI_MIS]);\n> +\n> +    qemu_set_irq(s->irq, irq);\n> +}\n> +\n> +static void mss_spi_reset(DeviceState *d)\n> +{\n> +    mss_spi_do_reset(MSS_SPI(d));\n> +}\n\nJust combine these two together.\n\n> +\n> +static uint64_t\n> +spi_read(void *opaque, hwaddr addr, unsigned int size)\n> +{\n> +    MSSSpiState *s = opaque;\n> +    uint32_t ret = 0;\n> +\n> +    addr >>= 2;\n> +    switch (addr) {\n> +    case R_SPI_RX:\n> +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> +        s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;\n> +        ret = fifo32_pop(&s->rx_fifo);\n> +        if (fifo32_is_empty(&s->rx_fifo)) {\n> +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> +        }\n> +        break;\n> +\n> +    case R_SPI_MIS:\n> +        update_mis(s);\n> +        ret = s->regs[R_SPI_MIS];\n> +        break;\n> +\n> +    default:\n> +        if (addr < ARRAY_SIZE(s->regs)) {\n> +            ret = s->regs[addr];\n> +        } else {\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\", __func__,\n> +                         addr * 4);\n\nI'd return here do you don't hit the read print below.\n\n> +        }\n> +        break;\n> +    }\n> +\n> +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" = 0x%\" PRIx32, addr * 4, ret);\n> +    spi_update_irq(s);\n> +    return ret;\n> +}\n> +\n> +static void assert_cs(MSSSpiState *s)\n> +{\n> +    qemu_set_irq(s->cs_line, 0);\n> +}\n> +\n> +static void deassert_cs(MSSSpiState *s)\n> +{\n> +    qemu_set_irq(s->cs_line, 1);\n> +}\n> +\n> +static void spi_flush_txfifo(MSSSpiState *s)\n> +{\n> +    uint32_t tx;\n> +    uint32_t rx;\n> +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);\n> +\n> +    /*\n> +     * Chip Select(CS) is automatically controlled by this controller.\n> +     * If SPS bit is set in Control register then CS is asserted\n> +     * until all the frames set in frame count of Control register are\n> +     * transferred. If SPS is not set then CS pulses between frames.\n> +     * Note that Slave Select register specifies which of the CS line\n> +     * has to be controlled automatically by controller. Bits SS[7:1] are for\n> +     * masters in FPGA fabric since we model only Microcontroller subsystem\n> +     * of Smartfusion2 we control only one CS(SS[0]) line.\n> +     */\n> +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {\n> +        assert_cs(s);\n> +\n> +        s->regs[R_SPI_STATUS] &= ~(S_TXDONE | S_RXRDY);\n> +\n> +        tx = fifo32_pop(&s->tx_fifo);\n> +        DB_PRINT(\"data tx:0x%\" PRIx32, tx);\n> +        rx = ssi_transfer(s->spi, tx);\n> +        DB_PRINT(\"data rx:0x%\" PRIx32, rx);\n> +\n> +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> +            s->regs[R_SPI_STATUS] |= S_RXCHOVRF;\n> +            s->regs[R_SPI_RIS] |= S_RXCHOVRF;\n> +        } else {\n> +            fifo32_push(&s->rx_fifo, rx);\n> +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;\n> +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {\n> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;\n> +            } else if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;\n> +            }\n> +        }\n> +        s->frame_count--;\n> +        if (!sps) {\n> +            deassert_cs(s);\n> +        }\n> +    }\n> +\n> +    if (!s->frame_count) {\n> +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>\n> +                            FMCOUNT_SHIFT;\n> +        if (sps) {\n> +            deassert_cs(s);\n> +        }\n\nShouldn't this be lowered no matter what?\n\nThanks,\nAlistair\n\n> +        s->regs[R_SPI_RIS] |= S_TXDONE | S_RXRDY;\n> +        s->regs[R_SPI_STATUS] |= S_TXDONE | S_RXRDY;\n> +   }\n> +}\n> +\n> +static void spi_write(void *opaque, hwaddr addr,\n> +            uint64_t val64, unsigned int size)\n> +{\n> +    MSSSpiState *s = opaque;\n> +    uint32_t value = val64;\n> +\n> +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" =0x%\" PRIx32, addr, value);\n> +    addr >>= 2;\n> +\n> +    switch (addr) {\n> +    case R_SPI_TX:\n> +        /* adding to already full FIFO */\n> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> +            break;\n> +        }\n> +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;\n> +        fifo32_push(&s->tx_fifo, value);\n> +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {\n> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;\n> +        } else if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;\n> +        }\n> +        if (s->enabled) {\n> +            spi_flush_txfifo(s);\n> +        }\n> +        break;\n> +\n> +    case R_SPI_CONTROL:\n> +        s->regs[R_SPI_CONTROL] = value;\n> +        if (value & C_BIGFIFO) {\n> +            set_fifodepth(s);\n> +        } else {\n> +            s->fifo_depth = 4;\n> +        }\n> +        s->enabled = value & C_ENABLE;\n> +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;\n> +        if (value & C_RESET) {\n> +            mss_spi_do_reset(s);\n> +        }\n> +        break;\n> +\n> +    case R_SPI_DFSIZE:\n> +        if (s->enabled) {\n> +            break;\n> +        }\n> +        s->regs[R_SPI_DFSIZE] = value;\n> +        break;\n> +\n> +    case R_SPI_INTCLR:\n> +        s->regs[R_SPI_INTCLR] = value;\n> +        if (value & S_TXDONE) {\n> +            s->regs[R_SPI_RIS] &= ~S_TXDONE;\n> +        }\n> +        if (value & S_RXRDY) {\n> +            s->regs[R_SPI_RIS] &= ~S_RXRDY;\n> +        }\n> +        if (value & S_RXCHOVRF) {\n> +            s->regs[R_SPI_RIS] &= ~S_RXCHOVRF;\n> +        }\n> +        break;\n> +\n> +    case R_SPI_MIS:\n> +    case R_SPI_STATUS:\n> +    case R_SPI_RIS:\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Write to read only register 0x%\" HWADDR_PRIx \"\\n\",\n> +                         __func__, addr * 4);\n> +        break;\n> +\n> +    default:\n> +        if (addr < ARRAY_SIZE(s->regs)) {\n> +            s->regs[addr] = value;\n> +        } else {\n> +            qemu_log_mask(LOG_GUEST_ERROR,\n> +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\", __func__,\n> +                         addr * 4);\n> +        }\n> +        break;\n> +    }\n> +\n> +    spi_update_irq(s);\n> +}\n> +\n> +static const MemoryRegionOps spi_ops = {\n> +    .read = spi_read,\n> +    .write = spi_write,\n> +    .endianness = DEVICE_NATIVE_ENDIAN,\n> +    .valid = {\n> +        .min_access_size = 1,\n> +        .max_access_size = 4\n> +    }\n> +};\n> +\n> +static void mss_spi_realize(DeviceState *dev, Error **errp)\n> +{\n> +    MSSSpiState *s = MSS_SPI(dev);\n> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);\n> +\n> +    s->spi = ssi_create_bus(dev, \"spi\");\n> +\n> +    sysbus_init_irq(sbd, &s->irq);\n> +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);\n> +    sysbus_init_irq(sbd, &s->cs_line);\n> +\n> +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,\n> +                          TYPE_MSS_SPI, R_SPI_MAX * 4);\n> +    sysbus_init_mmio(sbd, &s->mmio);\n> +\n> +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);\n> +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);\n> +}\n> +\n> +static const VMStateDescription vmstate_mss_spi = {\n> +    .name = TYPE_MSS_SPI,\n> +    .version_id = 1,\n> +    .minimum_version_id = 1,\n> +    .fields = (VMStateField[]) {\n> +        VMSTATE_FIFO32(tx_fifo, MSSSpiState),\n> +        VMSTATE_FIFO32(rx_fifo, MSSSpiState),\n> +        VMSTATE_UINT32_ARRAY(regs, MSSSpiState, R_SPI_MAX),\n> +        VMSTATE_END_OF_LIST()\n> +    }\n> +};\n> +\n> +static void mss_spi_class_init(ObjectClass *klass, void *data)\n> +{\n> +    DeviceClass *dc = DEVICE_CLASS(klass);\n> +\n> +    dc->realize = mss_spi_realize;\n> +    dc->reset = mss_spi_reset;\n> +    dc->vmsd = &vmstate_mss_spi;\n> +}\n> +\n> +static const TypeInfo mss_spi_info = {\n> +    .name           = TYPE_MSS_SPI,\n> +    .parent         = TYPE_SYS_BUS_DEVICE,\n> +    .instance_size  = sizeof(MSSSpiState),\n> +    .class_init     = mss_spi_class_init,\n> +};\n> +\n> +static void mss_spi_register_types(void)\n> +{\n> +    type_register_static(&mss_spi_info);\n> +}\n> +\n> +type_init(mss_spi_register_types)\n> diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h\n> new file mode 100644\n> index 0000000..f0cf324\n> --- /dev/null\n> +++ b/include/hw/ssi/mss-spi.h\n> @@ -0,0 +1,58 @@\n> +/*\n> + * Microsemi SmartFusion2 SPI\n> + *\n> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> + *\n> + * Permission is hereby granted, free of charge, to any person obtaining a copy\n> + * of this software and associated documentation files (the \"Software\"), to deal\n> + * in the Software without restriction, including without limitation the rights\n> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> + * copies of the Software, and to permit persons to whom the Software is\n> + * furnished to do so, subject to the following conditions:\n> + *\n> + * The above copyright notice and this permission notice shall be included in\n> + * all copies or substantial portions of the Software.\n> + *\n> + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> + * THE SOFTWARE.\n> + */\n> +\n> +#ifndef HW_MSS_SPI_H\n> +#define HW_MSS_SPI_H\n> +\n> +#include \"hw/sysbus.h\"\n> +#include \"hw/ssi/ssi.h\"\n> +#include \"qemu/fifo32.h\"\n> +\n> +#define TYPE_MSS_SPI   \"mss-spi\"\n> +#define MSS_SPI(obj)   OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI)\n> +\n> +#define R_SPI_MAX             16\n> +\n> +typedef struct MSSSpiState {\n> +    SysBusDevice parent_obj;\n> +\n> +    MemoryRegion mmio;\n> +\n> +    qemu_irq irq;\n> +\n> +    qemu_irq cs_line;\n> +\n> +    SSIBus *spi;\n> +\n> +    Fifo32 rx_fifo;\n> +    Fifo32 tx_fifo;\n> +\n> +    int fifo_depth;\n> +    uint32_t frame_count;\n> +    bool enabled;\n> +\n> +    uint32_t regs[R_SPI_MAX];\n> +} MSSSpiState;\n> +\n> +#endif /* HW_MSS_SPI_H */\n> --\n> 2.5.0\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"rQMyeM5h\"; dkim-atps=neutral"],"Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xnZwR5d06z9t2r\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu,  7 Sep 2017 06:30:46 +1000 (AEST)","from localhost ([::1]:37672 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dpgyB-0002a0-N6\n\tfor incoming@patchwork.ozlabs.org; Wed, 06 Sep 2017 16:30:43 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:53429)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <alistair23@gmail.com>) id 1dpgxN-0002ZX-Hn\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:59 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <alistair23@gmail.com>) id 1dpgxH-0000wF-MY\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:53 -0400","from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:34546)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <alistair23@gmail.com>)\n\tid 1dpgxH-0000uY-Bo; Wed, 06 Sep 2017 16:29:47 -0400","by mail-wm0-x243.google.com with SMTP id l19so3063wmi.1;\n\tWed, 06 Sep 2017 13:29:45 -0700 (PDT)","by 10.28.191.130 with HTTP; Wed, 6 Sep 2017 13:29:13 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=mime-version:in-reply-to:references:from:date:message-id:subject:to\n\t:cc; bh=b/Z1V34gSQMKKM/z9qXCOuwQM/srwxYs9fEarPZksiY=;\n\tb=rQMyeM5hU4g5NIMQ85KcoerJ5g2CEeOU8AgEHnIOvxmCALbqKwTdIZ9JRUPIJP9GL8\n\tevobooxp38W5Qhnfj9OVus7t16y9LHRx+wCpUqYeULl/mSK5mHIJeDJLKUCrxjfaK0Yr\n\tZZIi3lD1dFcuJncIduxe75Do5Kr/iN8b7Cg01tce/gX6beSRvhSq5uVq2SfVkVKVdVdv\n\tTvlJpyo9I+NDOjQNDGWLGf1Ad82g11o+VJvGhAjSWxcEjBulA411T42enDIpBYOhA6mQ\n\tgyhvT585xa1Z/gWH0Xe6YiuZPuB8AsyeWCvsyVDq/8Z/LQDczMznwLOz0PAm2j+ROm5F\n\tG/VQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:in-reply-to:references:from:date\n\t:message-id:subject:to:cc;\n\tbh=b/Z1V34gSQMKKM/z9qXCOuwQM/srwxYs9fEarPZksiY=;\n\tb=gjWA/LvShEKGTXrwawrfjT1Mnl3c7658KiSlbgoVQu5mvZOspN4rXNx5AranSweuLJ\n\tU8Pm6g2HHodHe+RtNMx+jwVEHFhxFoft3PnXWeeE9wUoziuZfQSa1k2e6A0lSMa1nAcO\n\t2c2rWI1cIjwLKZ+ov5RXQFitR8PatRCkals5BGQxmVJINfpfjS4tD+gnxG1KAAk/YUgD\n\tA/eN/GzUWeex0r9xWIwklElGyAJnTbPKE1odFav9zgL67N6sgR/FhBcIVSfFfXNeiEs6\n\tHH57IHsY6a8Rd90ILeqht4qEeqZzb/UMSdddAtLPNN1O3TIsFSc1IVQsRcvEcZ5MpfCz\n\tr5Xg==","X-Gm-Message-State":"AHPjjUhxUsR/BWEYMYpvEdOSW6S3fbuoCh/ptNG3BaexR/LvjMTEwzDq\n\tmq9/eMHMt8qLD9Cv8NbmhmOg9V4k/g==","X-Google-Smtp-Source":"ADKCNb4cYJbJFmvMrW6iTcVUR/toreZe9r3IohpRCA16pvobttXAheBYiv8FIfWsHvLIgGe7sKuAgeYnIRMdBqIveIM=","X-Received":"by 10.28.125.205 with SMTP id y196mr662678wmc.128.1504729784267; \n\tWed, 06 Sep 2017 13:29:44 -0700 (PDT)","MIME-Version":"1.0","In-Reply-To":"<1503938283-12404-4-git-send-email-sundeep.lkml@gmail.com>","References":"<1503938283-12404-1-git-send-email-sundeep.lkml@gmail.com>\n\t<1503938283-12404-4-git-send-email-sundeep.lkml@gmail.com>","From":"Alistair Francis <alistair23@gmail.com>","Date":"Wed, 6 Sep 2017 13:29:13 -0700","Message-ID":"<CAKmqyKPTENTDXp=jEiaecC3RqnBb6jUHKCPkyXi6gnsVYoqrqA@mail.gmail.com>","To":"Subbaraya Sundeep <sundeep.lkml@gmail.com>","Content-Type":"text/plain; charset=\"UTF-8\"","X-detected-operating-system":"by eggs.gnu.org: Genre and OS details not\n\trecognized.","X-Received-From":"2a00:1450:400c:c09::243","Subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"Peter Maydell <peter.maydell@linaro.org>, =?utf-8?q?Philippe_Mathieu-D?=\n\t=?utf-8?b?YXVkw6k=?= <f4bug@amsat.org>, \tqemu-arm <qemu-arm@nongnu.org>,\n\t\"qemu-devel@nongnu.org Developers\" <qemu-devel@nongnu.org>, \n\tPeter Crosthwaite <crosthwaite.peter@gmail.com>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"}},{"id":1764474,"web_url":"http://patchwork.ozlabs.org/comment/1764474/","msgid":"<CALHRZupCUR_7qZJ+eFfGe2yE3vWj-5SXJ5dP=fTW77V3Np+DAg@mail.gmail.com>","list_archive_url":null,"date":"2017-09-07T02:01:45","subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","submitter":{"id":64324,"url":"http://patchwork.ozlabs.org/api/people/64324/","name":"sundeep subbaraya","email":"sundeep.lkml@gmail.com"},"content":"Hi Alistair,\n\nOn Thu, Sep 7, 2017 at 1:59 AM, Alistair Francis <alistair23@gmail.com>\nwrote:\n\n> On Mon, Aug 28, 2017 at 9:38 AM, Subbaraya Sundeep\n> <sundeep.lkml@gmail.com> wrote:\n> > Modelled Microsemi's Smartfusion2 SPI controller.\n> >\n> > Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> > ---\n> >  hw/ssi/Makefile.objs     |   1 +\n> >  hw/ssi/mss-spi.c         | 409 ++++++++++++++++++++++++++++++\n> +++++++++++++++++\n> >  include/hw/ssi/mss-spi.h |  58 +++++++\n> >  3 files changed, 468 insertions(+)\n> >  create mode 100644 hw/ssi/mss-spi.c\n> >  create mode 100644 include/hw/ssi/mss-spi.h\n> >\n> > diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs\n> > index 487add2..f5bcc65 100644\n> > --- a/hw/ssi/Makefile.objs\n> > +++ b/hw/ssi/Makefile.objs\n> > @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o\n> >  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o\n> >  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o\n> >  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o\n> > +common-obj-$(CONFIG_MSF2) += mss-spi.o\n> >\n> >  obj-$(CONFIG_OMAP) += omap_spi.o\n> >  obj-$(CONFIG_IMX) += imx_spi.o\n> > diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c\n> > new file mode 100644\n> > index 0000000..7209363\n> > --- /dev/null\n> > +++ b/hw/ssi/mss-spi.c\n> > @@ -0,0 +1,409 @@\n> > +/*\n> > + * Block model of SPI controller present in\n> > + * Microsemi's SmartFusion2 and SmartFusion SoCs.\n> > + *\n> > + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> > + *\n> > + * Permission is hereby granted, free of charge, to any person\n> obtaining a copy\n> > + * of this software and associated documentation files (the\n> \"Software\"), to deal\n> > + * in the Software without restriction, including without limitation\n> the rights\n> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or\n> sell\n> > + * copies of the Software, and to permit persons to whom the Software is\n> > + * furnished to do so, subject to the following conditions:\n> > + *\n> > + * The above copyright notice and this permission notice shall be\n> included in\n> > + * all copies or substantial portions of the Software.\n> > + *\n> > + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR\n> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY,\n> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n> SHALL\n> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n> OTHER\n> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n> ARISING FROM,\n> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n> DEALINGS IN\n> > + * THE SOFTWARE.\n> > + */\n> > +\n> > +#include \"qemu/osdep.h\"\n> > +#include \"hw/ssi/mss-spi.h\"\n> > +#include \"qemu/log.h\"\n> > +\n> > +#ifndef MSS_SPI_ERR_DEBUG\n> > +#define MSS_SPI_ERR_DEBUG   0\n> > +#endif\n> > +\n> > +#define DB_PRINT_L(lvl, fmt, args...) do { \\\n> > +    if (MSS_SPI_ERR_DEBUG >= lvl) { \\\n> > +        qemu_log(\"%s: \" fmt \"\\n\", __func__, ## args); \\\n> > +    } \\\n> > +} while (0);\n> > +\n> > +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)\n> > +\n> > +#define FIFO_CAPACITY         32\n> > +#define FIFO_CAPACITY         32\n>\n> Double define?\n>\n\nWrong will remove it.\n\n>\n> > +\n> > +#define R_SPI_CONTROL         0\n> > +#define R_SPI_DFSIZE          1\n> > +#define R_SPI_STATUS          2\n> > +#define R_SPI_INTCLR          3\n> > +#define R_SPI_RX              4\n> > +#define R_SPI_TX              5\n> > +#define R_SPI_CLKGEN          6\n> > +#define R_SPI_SS              7\n> > +#define R_SPI_MIS             8\n> > +#define R_SPI_RIS             9\n> > +\n> > +#define S_TXDONE             (1 << 0)\n> > +#define S_RXRDY              (1 << 1)\n> > +#define S_RXCHOVRF           (1 << 2)\n> > +#define S_RXFIFOFUL          (1 << 4)\n> > +#define S_RXFIFOFULNXT       (1 << 5)\n> > +#define S_RXFIFOEMP          (1 << 6)\n> > +#define S_RXFIFOEMPNXT       (1 << 7)\n> > +#define S_TXFIFOFUL          (1 << 8)\n> > +#define S_TXFIFOFULNXT       (1 << 9)\n> > +#define S_TXFIFOEMP          (1 << 10)\n> > +#define S_TXFIFOEMPNXT       (1 << 11)\n> > +#define S_FRAMESTART         (1 << 12)\n> > +#define S_SSEL               (1 << 13)\n> > +#define S_ACTIVE             (1 << 14)\n> > +\n> > +#define C_ENABLE             (1 << 0)\n> > +#define C_MODE               (1 << 1)\n> > +#define C_INTRXDATA          (1 << 4)\n> > +#define C_INTTXDATA          (1 << 5)\n> > +#define C_INTRXOVRFLO        (1 << 6)\n> > +#define C_SPS                (1 << 26)\n> > +#define C_BIGFIFO            (1 << 29)\n> > +#define C_RESET              (1 << 31)\n> > +\n> > +#define FRAMESZ_MASK         0x1F\n> > +#define FMCOUNT_MASK         0x00FFFF00\n> > +#define FMCOUNT_SHIFT        8\n> > +\n> > +static void txfifo_reset(MSSSpiState *s)\n> > +{\n> > +    fifo32_reset(&s->tx_fifo);\n> > +\n> > +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;\n> > +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;\n> > +}\n> > +\n> > +static void rxfifo_reset(MSSSpiState *s)\n> > +{\n> > +    fifo32_reset(&s->rx_fifo);\n> > +\n> > +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> > +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> > +}\n> > +\n> > +static void set_fifodepth(MSSSpiState *s)\n> > +{\n> > +    unsigned int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;\n> > +\n> > +    if (size <= 8) {\n> > +        s->fifo_depth = 32;\n> > +    } else if (size <= 16) {\n> > +        s->fifo_depth = 16;\n> > +    } else if (size <= 32) {\n> > +        s->fifo_depth = 8;\n> > +    } else {\n> > +        s->fifo_depth = 4;\n> > +    }\n> > +}\n> > +\n> > +static void mss_spi_do_reset(MSSSpiState *s)\n> > +{\n> > +    memset(s->regs, 0, sizeof s->regs);\n> > +    s->regs[R_SPI_CONTROL] = 0x80000102;\n> > +    s->regs[R_SPI_DFSIZE] = 0x4;\n> > +    s->regs[R_SPI_STATUS] = S_SSEL | S_TXFIFOEMP | S_RXFIFOEMP;\n> > +    s->regs[R_SPI_CLKGEN] = 0x7;\n> > +    s->regs[R_SPI_RIS] = 0x0;\n> > +\n> > +    s->fifo_depth = 4;\n> > +    s->frame_count = 1;\n> > +    s->enabled = false;\n> > +\n> > +    rxfifo_reset(s);\n> > +    txfifo_reset(s);\n> > +}\n> > +\n> > +static void update_mis(MSSSpiState *s)\n> > +{\n> > +    uint32_t reg = s->regs[R_SPI_CONTROL];\n> > +    uint32_t tmp;\n> > +\n> > +    /*\n> > +     * form the Control register interrupt enable bits\n> > +     * same as RIS, MIS and Interrupt clear registers for simplicity\n> > +     */\n> > +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |\n> > +           ((reg & C_INTTXDATA) >> 5);\n> > +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];\n> > +}\n> > +\n> > +static void spi_update_irq(MSSSpiState *s)\n> > +{\n> > +    int irq;\n> > +\n> > +    update_mis(s);\n> > +    irq = !!(s->regs[R_SPI_MIS]);\n> > +\n> > +    qemu_set_irq(s->irq, irq);\n> > +}\n> > +\n> > +static void mss_spi_reset(DeviceState *d)\n> > +{\n> > +    mss_spi_do_reset(MSS_SPI(d));\n> > +}\n>\n> Just combine these two together.\n>\n> Ok\n\n> > +\n> > +static uint64_t\n> > +spi_read(void *opaque, hwaddr addr, unsigned int size)\n> > +{\n> > +    MSSSpiState *s = opaque;\n> > +    uint32_t ret = 0;\n> > +\n> > +    addr >>= 2;\n> > +    switch (addr) {\n> > +    case R_SPI_RX:\n> > +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;\n> > +        s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;\n> > +        ret = fifo32_pop(&s->rx_fifo);\n> > +        if (fifo32_is_empty(&s->rx_fifo)) {\n> > +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;\n> > +        }\n> > +        break;\n> > +\n> > +    case R_SPI_MIS:\n> > +        update_mis(s);\n> > +        ret = s->regs[R_SPI_MIS];\n> > +        break;\n> > +\n> > +    default:\n> > +        if (addr < ARRAY_SIZE(s->regs)) {\n> > +            ret = s->regs[addr];\n> > +        } else {\n> > +            qemu_log_mask(LOG_GUEST_ERROR,\n> > +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\",\n> __func__,\n> > +                         addr * 4);\n>\n> I'd return here do you don't hit the read print below.\n>\n> Ok\n\n> > +        }\n> > +        break;\n> > +    }\n> > +\n> > +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" = 0x%\" PRIx32, addr * 4, ret);\n> > +    spi_update_irq(s);\n> > +    return ret;\n> > +}\n> > +\n> > +static void assert_cs(MSSSpiState *s)\n> > +{\n> > +    qemu_set_irq(s->cs_line, 0);\n> > +}\n> > +\n> > +static void deassert_cs(MSSSpiState *s)\n> > +{\n> > +    qemu_set_irq(s->cs_line, 1);\n> > +}\n> > +\n> > +static void spi_flush_txfifo(MSSSpiState *s)\n> > +{\n> > +    uint32_t tx;\n> > +    uint32_t rx;\n> > +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);\n> > +\n> > +    /*\n> > +     * Chip Select(CS) is automatically controlled by this controller.\n> > +     * If SPS bit is set in Control register then CS is asserted\n> > +     * until all the frames set in frame count of Control register are\n> > +     * transferred. If SPS is not set then CS pulses between frames.\n> > +     * Note that Slave Select register specifies which of the CS line\n> > +     * has to be controlled automatically by controller. Bits SS[7:1]\n> are for\n> > +     * masters in FPGA fabric since we model only Microcontroller\n> subsystem\n> > +     * of Smartfusion2 we control only one CS(SS[0]) line.\n> > +     */\n> > +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {\n> > +        assert_cs(s);\n> > +\n> > +        s->regs[R_SPI_STATUS] &= ~(S_TXDONE | S_RXRDY);\n> > +\n> > +        tx = fifo32_pop(&s->tx_fifo);\n> > +        DB_PRINT(\"data tx:0x%\" PRIx32, tx);\n> > +        rx = ssi_transfer(s->spi, tx);\n> > +        DB_PRINT(\"data rx:0x%\" PRIx32, rx);\n> > +\n> > +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> > +            s->regs[R_SPI_STATUS] |= S_RXCHOVRF;\n> > +            s->regs[R_SPI_RIS] |= S_RXCHOVRF;\n> > +        } else {\n> > +            fifo32_push(&s->rx_fifo, rx);\n> > +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;\n> > +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {\n> > +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;\n> > +            } else if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {\n> > +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;\n> > +            }\n> > +        }\n> > +        s->frame_count--;\n> > +        if (!sps) {\n> > +            deassert_cs(s);\n> > +        }\n> > +    }\n> > +\n> > +    if (!s->frame_count) {\n> > +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>\n> > +                            FMCOUNT_SHIFT;\n> > +        if (sps) {\n> > +            deassert_cs(s);\n> > +        }\n>\n> Shouldn't this be lowered no matter what?\n>\n> Yes you are right :).\n\nThanks\nSundeep\n\n\n\n> Thanks,\n> Alistair\n>\n> > +        s->regs[R_SPI_RIS] |= S_TXDONE | S_RXRDY;\n> > +        s->regs[R_SPI_STATUS] |= S_TXDONE | S_RXRDY;\n> > +   }\n> > +}\n> > +\n> > +static void spi_write(void *opaque, hwaddr addr,\n> > +            uint64_t val64, unsigned int size)\n> > +{\n> > +    MSSSpiState *s = opaque;\n> > +    uint32_t value = val64;\n> > +\n> > +    DB_PRINT(\"addr=0x%\" HWADDR_PRIx \" =0x%\" PRIx32, addr, value);\n> > +    addr >>= 2;\n> > +\n> > +    switch (addr) {\n> > +    case R_SPI_TX:\n> > +        /* adding to already full FIFO */\n> > +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> > +            break;\n> > +        }\n> > +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;\n> > +        fifo32_push(&s->tx_fifo, value);\n> > +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {\n> > +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;\n> > +        } else if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {\n> > +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;\n> > +        }\n> > +        if (s->enabled) {\n> > +            spi_flush_txfifo(s);\n> > +        }\n> > +        break;\n> > +\n> > +    case R_SPI_CONTROL:\n> > +        s->regs[R_SPI_CONTROL] = value;\n> > +        if (value & C_BIGFIFO) {\n> > +            set_fifodepth(s);\n> > +        } else {\n> > +            s->fifo_depth = 4;\n> > +        }\n> > +        s->enabled = value & C_ENABLE;\n> > +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;\n> > +        if (value & C_RESET) {\n> > +            mss_spi_do_reset(s);\n> > +        }\n> > +        break;\n> > +\n> > +    case R_SPI_DFSIZE:\n> > +        if (s->enabled) {\n> > +            break;\n> > +        }\n> > +        s->regs[R_SPI_DFSIZE] = value;\n> > +        break;\n> > +\n> > +    case R_SPI_INTCLR:\n> > +        s->regs[R_SPI_INTCLR] = value;\n> > +        if (value & S_TXDONE) {\n> > +            s->regs[R_SPI_RIS] &= ~S_TXDONE;\n> > +        }\n> > +        if (value & S_RXRDY) {\n> > +            s->regs[R_SPI_RIS] &= ~S_RXRDY;\n> > +        }\n> > +        if (value & S_RXCHOVRF) {\n> > +            s->regs[R_SPI_RIS] &= ~S_RXCHOVRF;\n> > +        }\n> > +        break;\n> > +\n> > +    case R_SPI_MIS:\n> > +    case R_SPI_STATUS:\n> > +    case R_SPI_RIS:\n> > +            qemu_log_mask(LOG_GUEST_ERROR,\n> > +                         \"%s: Write to read only register 0x%\"\n> HWADDR_PRIx \"\\n\",\n> > +                         __func__, addr * 4);\n> > +        break;\n> > +\n> > +    default:\n> > +        if (addr < ARRAY_SIZE(s->regs)) {\n> > +            s->regs[addr] = value;\n> > +        } else {\n> > +            qemu_log_mask(LOG_GUEST_ERROR,\n> > +                         \"%s: Bad offset 0x%\" HWADDR_PRIx \"\\n\",\n> __func__,\n> > +                         addr * 4);\n> > +        }\n> > +        break;\n> > +    }\n> > +\n> > +    spi_update_irq(s);\n> > +}\n> > +\n> > +static const MemoryRegionOps spi_ops = {\n> > +    .read = spi_read,\n> > +    .write = spi_write,\n> > +    .endianness = DEVICE_NATIVE_ENDIAN,\n> > +    .valid = {\n> > +        .min_access_size = 1,\n> > +        .max_access_size = 4\n> > +    }\n> > +};\n> > +\n> > +static void mss_spi_realize(DeviceState *dev, Error **errp)\n> > +{\n> > +    MSSSpiState *s = MSS_SPI(dev);\n> > +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);\n> > +\n> > +    s->spi = ssi_create_bus(dev, \"spi\");\n> > +\n> > +    sysbus_init_irq(sbd, &s->irq);\n> > +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);\n> > +    sysbus_init_irq(sbd, &s->cs_line);\n> > +\n> > +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,\n> > +                          TYPE_MSS_SPI, R_SPI_MAX * 4);\n> > +    sysbus_init_mmio(sbd, &s->mmio);\n> > +\n> > +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);\n> > +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);\n> > +}\n> > +\n> > +static const VMStateDescription vmstate_mss_spi = {\n> > +    .name = TYPE_MSS_SPI,\n> > +    .version_id = 1,\n> > +    .minimum_version_id = 1,\n> > +    .fields = (VMStateField[]) {\n> > +        VMSTATE_FIFO32(tx_fifo, MSSSpiState),\n> > +        VMSTATE_FIFO32(rx_fifo, MSSSpiState),\n> > +        VMSTATE_UINT32_ARRAY(regs, MSSSpiState, R_SPI_MAX),\n> > +        VMSTATE_END_OF_LIST()\n> > +    }\n> > +};\n> > +\n> > +static void mss_spi_class_init(ObjectClass *klass, void *data)\n> > +{\n> > +    DeviceClass *dc = DEVICE_CLASS(klass);\n> > +\n> > +    dc->realize = mss_spi_realize;\n> > +    dc->reset = mss_spi_reset;\n> > +    dc->vmsd = &vmstate_mss_spi;\n> > +}\n> > +\n> > +static const TypeInfo mss_spi_info = {\n> > +    .name           = TYPE_MSS_SPI,\n> > +    .parent         = TYPE_SYS_BUS_DEVICE,\n> > +    .instance_size  = sizeof(MSSSpiState),\n> > +    .class_init     = mss_spi_class_init,\n> > +};\n> > +\n> > +static void mss_spi_register_types(void)\n> > +{\n> > +    type_register_static(&mss_spi_info);\n> > +}\n> > +\n> > +type_init(mss_spi_register_types)\n> > diff --git a/include/hw/ssi/mss-spi.h b/include/hw/ssi/mss-spi.h\n> > new file mode 100644\n> > index 0000000..f0cf324\n> > --- /dev/null\n> > +++ b/include/hw/ssi/mss-spi.h\n> > @@ -0,0 +1,58 @@\n> > +/*\n> > + * Microsemi SmartFusion2 SPI\n> > + *\n> > + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>\n> > + *\n> > + * Permission is hereby granted, free of charge, to any person\n> obtaining a copy\n> > + * of this software and associated documentation files (the\n> \"Software\"), to deal\n> > + * in the Software without restriction, including without limitation\n> the rights\n> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or\n> sell\n> > + * copies of the Software, and to permit persons to whom the Software is\n> > + * furnished to do so, subject to the following conditions:\n> > + *\n> > + * The above copyright notice and this permission notice shall be\n> included in\n> > + * all copies or substantial portions of the Software.\n> > + *\n> > + * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR\n> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY,\n> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n> SHALL\n> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n> OTHER\n> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n> ARISING FROM,\n> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n> DEALINGS IN\n> > + * THE SOFTWARE.\n> > + */\n> > +\n> > +#ifndef HW_MSS_SPI_H\n> > +#define HW_MSS_SPI_H\n> > +\n> > +#include \"hw/sysbus.h\"\n> > +#include \"hw/ssi/ssi.h\"\n> > +#include \"qemu/fifo32.h\"\n> > +\n> > +#define TYPE_MSS_SPI   \"mss-spi\"\n> > +#define MSS_SPI(obj)   OBJECT_CHECK(MSSSpiState, (obj), TYPE_MSS_SPI)\n> > +\n> > +#define R_SPI_MAX             16\n> > +\n> > +typedef struct MSSSpiState {\n> > +    SysBusDevice parent_obj;\n> > +\n> > +    MemoryRegion mmio;\n> > +\n> > +    qemu_irq irq;\n> > +\n> > +    qemu_irq cs_line;\n> > +\n> > +    SSIBus *spi;\n> > +\n> > +    Fifo32 rx_fifo;\n> > +    Fifo32 tx_fifo;\n> > +\n> > +    int fifo_depth;\n> > +    uint32_t frame_count;\n> > +    bool enabled;\n> > +\n> > +    uint32_t regs[R_SPI_MAX];\n> > +} MSSSpiState;\n> > +\n> > +#endif /* HW_MSS_SPI_H */\n> > --\n> > 2.5.0\n> >\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"RPpr8I3+\"; dkim-atps=neutral"],"Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xnkH53Dr4z9s4s\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu,  7 Sep 2017 12:02:23 +1000 (AEST)","from localhost ([::1]:38589 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dpm96-00059O-3P\n\tfor incoming@patchwork.ozlabs.org; Wed, 06 Sep 2017 22:02:20 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:40031)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <sundeep.lkml@gmail.com>) id 1dpm8g-000597-0I\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 22:01:57 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <sundeep.lkml@gmail.com>) id 1dpm8Y-0002oc-Uy\n\tfor qemu-devel@nongnu.org; Wed, 06 Sep 2017 22:01:54 -0400","from mail-ua0-x236.google.com ([2607:f8b0:400c:c08::236]:36436)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <sundeep.lkml@gmail.com>)\n\tid 1dpm8Y-0002oO-Mw; Wed, 06 Sep 2017 22:01:46 -0400","by mail-ua0-x236.google.com with SMTP id q29so14049896uaf.3;\n\tWed, 06 Sep 2017 19:01:46 -0700 (PDT)","by 10.176.75.196 with HTTP; Wed, 6 Sep 2017 19:01:45 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=mime-version:in-reply-to:references:from:date:message-id:subject:to\n\t:cc; bh=QzYd/GRndLWB36pxw5s1O0TBgfLkQH4Btqh03ueJYTU=;\n\tb=RPpr8I3+Q3ThEtra172FI70fZ39Js1LFNUew5/GzngVQGTsik2wmL82KosIohDB3U9\n\tr1s9DFYL/D8fWGkVWlZokR2pvbhEKd62hqTSHnjwg2Tz80F+8xrHcbwr964pCeTCTpuf\n\tM6cfeljO9+3xJjzVOyckr8WuvJ7mC9gKXS4OOvGTjyyf77wEVJ4bkvwr1AhyyueCG7h6\n\tjFFso3zhsbX3ivYlWcTWCq0VOeJu/hgVtdXzYDpHJz/neunVS+aAQx5QeLob3S5JkX3t\n\tRK/5twC/ymjVEMYF3U4inMx2lEDXglH2PgVH2eYL6J8DN0gFmTK8jejpEWrBzHMhUzJp\n\tGRkQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:in-reply-to:references:from:date\n\t:message-id:subject:to:cc;\n\tbh=QzYd/GRndLWB36pxw5s1O0TBgfLkQH4Btqh03ueJYTU=;\n\tb=aRh7MCGZcPNGdIy+9WLaShwXTpfQyOEgjC5oV39PHQlgFZjigjbqR27F4EsNyhnkbN\n\tG1fFs/U9EEExdCrSU8H14efODIdzPu9egYHmkSWWHdudFycNQe6mh0f2NhLNHe5Yqast\n\tL6gnzxiYwWRd5ckZsb2O0ZnL8fCsMFvvaOsVPaJ6Egp6SdF5R1L7ZBCIwsleAx1EorPc\n\tK+Hptrm0rDq1SdsNXTAqaNTDJ/5+cin8cy4qQj3W44IawYoqOi/jS2NsMlwQsvorSkFW\n\t0CxptwfMwK3fDVSwibcwoY0kYQC6T9+Vh3vKwi7vyrxoBam0NYPenQANyPecn6mK1bmx\n\tthMQ==","X-Gm-Message-State":"AHPjjUhBvJIGT38KtyV/8SIV2UrvWhjM6vQNoVmTom0qqtKTM5zqbp/W\n\tkDatMuamnieHPQThxa+9S2oVSMXMfA==","X-Google-Smtp-Source":"ADKCNb6hl/VCa5VK2/x4AJMU9I+JgulNrMjlzWwOp8QmfShyHJ5yuoiw+76lyRCIIgQptNrCwO0rTJjCtL2r1m+0JDA=","X-Received":"by 10.176.2.51 with SMTP id 48mr763315uas.158.1504749705948; Wed,\n\t06 Sep 2017 19:01:45 -0700 (PDT)","MIME-Version":"1.0","In-Reply-To":"<CAKmqyKPTENTDXp=jEiaecC3RqnBb6jUHKCPkyXi6gnsVYoqrqA@mail.gmail.com>","References":"<1503938283-12404-1-git-send-email-sundeep.lkml@gmail.com>\n\t<1503938283-12404-4-git-send-email-sundeep.lkml@gmail.com>\n\t<CAKmqyKPTENTDXp=jEiaecC3RqnBb6jUHKCPkyXi6gnsVYoqrqA@mail.gmail.com>","From":"sundeep subbaraya <sundeep.lkml@gmail.com>","Date":"Thu, 7 Sep 2017 07:31:45 +0530","Message-ID":"<CALHRZupCUR_7qZJ+eFfGe2yE3vWj-5SXJ5dP=fTW77V3Np+DAg@mail.gmail.com>","To":"Alistair Francis <alistair23@gmail.com>","X-detected-operating-system":"by eggs.gnu.org: Genre and OS details not\n\trecognized.","X-Received-From":"2607:f8b0:400c:c08::236","Content-Type":"text/plain; charset=\"UTF-8\"","X-Content-Filtered-By":"Mailman/MimeDel 2.1.21","Subject":"Re: [Qemu-devel] [Qemu devel v7 PATCH 3/5] msf2: Add Smartfusion2\n\tSPI controller","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"Peter Maydell <peter.maydell@linaro.org>, =?utf-8?q?Philippe_Mathieu-D?=\n\t=?utf-8?b?YXVkw6k=?= <f4bug@amsat.org>, \tqemu-arm <qemu-arm@nongnu.org>,\n\t\"qemu-devel@nongnu.org Developers\" <qemu-devel@nongnu.org>, \n\tPeter Crosthwaite <crosthwaite.peter@gmail.com>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"}}]