All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC
@ 2017-05-09 16:44 Subbaraya Sundeep
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer Subbaraya Sundeep
                   ` (5 more replies)
  0 siblings, 6 replies; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Hi Qemu-devel,

I am trying to add Smartfusion2 SoC.
SoC is from Microsemi and System on Module(SOM)
board is from Emcraft systems. Smartfusion2 has hardened
Microcontroller(Cortex-M3)based Sub System and FPGA fabric.
At the moment only system timer, sysreg and SPI
controller are modelled.

Testing:
./arm-softmmu/qemu-system-arm -M smartfusion2-som -serial mon:stdio \
-kernel u-boot.bin -display none -drive file=spi.bin,if=mtd,format=raw

U-boot is from Emcraft with modified SPI driver not to use PDMA.
Linux is 4.5 linux with Smartfusion2 SoC dts and clocksource 
driver added by myself @
https://github.com/Subbaraya-Sundeep/linux.git

Baremetal elfs from Microsemi Softconsole IDE are also working.

Thanks,
Sundeep

Subbaraya Sundeep (5):
  msf2: Add Smartfusion2 System timer
  msf2: Microsemi Smartfusion2 System Register block.
  msf2: Add Smartfusion2 SPI controller
  msf2: Add Smartfusion2 SoC.
  msf2: Add Emcraft's Smartfusion2 SOM kit.

 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs            |   3 +-
 hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++
 hw/arm/msf2-som.c               |  67 +++++++
 hw/misc/Makefile.objs           |   1 +
 hw/misc/msf2-sysreg.c           | 131 ++++++++++++++
 hw/ssi/Makefile.objs            |   1 +
 hw/ssi/msf2-spi.c               | 378 ++++++++++++++++++++++++++++++++++++++++
 hw/timer/Makefile.objs          |   1 +
 hw/timer/msf2-timer.c           | 252 +++++++++++++++++++++++++++
 include/hw/arm/msf2-soc.h       |  60 +++++++
 include/hw/misc/msf2-sysreg.h   |  80 +++++++++
 include/hw/ssi/msf2-spi.h       | 105 +++++++++++
 include/hw/timer/msf2-timer.h   |  85 +++++++++
 14 files changed, 1352 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/msf2-soc.c
 create mode 100644 hw/arm/msf2-som.c
 create mode 100644 hw/misc/msf2-sysreg.c
 create mode 100644 hw/ssi/msf2-spi.c
 create mode 100644 hw/timer/msf2-timer.c
 create mode 100644 include/hw/arm/msf2-soc.h
 create mode 100644 include/hw/misc/msf2-sysreg.h
 create mode 100644 include/hw/ssi/msf2-spi.h
 create mode 100644 include/hw/timer/msf2-timer.h

-- 
2.5.0

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

* [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
@ 2017-05-09 16:44 ` Subbaraya Sundeep
  2017-05-10  9:41   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block Subbaraya Sundeep
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Modelled System Timer in Microsemi's Smartfusion2 Soc.
Timer has two 32bit down counters and two interrupts.

Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
---
 hw/timer/Makefile.objs        |   1 +
 hw/timer/msf2-timer.c         | 252 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/timer/msf2-timer.h |  85 ++++++++++++++
 3 files changed, 338 insertions(+)
 create mode 100644 hw/timer/msf2-timer.c
 create mode 100644 include/hw/timer/msf2-timer.h

diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index dd6f27e..bd1ff15 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -41,3 +41,4 @@ common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
 
 common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
+common-obj-$(CONFIG_MSF2) += msf2-timer.o
diff --git a/hw/timer/msf2-timer.c b/hw/timer/msf2-timer.c
new file mode 100644
index 0000000..466faa6
--- /dev/null
+++ b/hw/timer/msf2-timer.c
@@ -0,0 +1,252 @@
+/*
+ * Timer block model of Microsemi SmartFusion2.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/timer/msf2-timer.h"
+
+#ifndef MSF2_TIMER_ERR_DEBUG
+#define MSF2_TIMER_ERR_DEBUG  0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (MSF2_TIMER_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void timer_update_irq(struct Msf2Timer *st)
+{
+    bool isr, ier;
+
+    isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
+    ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
+
+    qemu_set_irq(st->irq, (ier && isr));
+}
+
+static void timer_update(struct Msf2Timer *st)
+{
+    uint64_t count;
+
+    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL)) {
+        ptimer_stop(st->ptimer);
+        return;
+    }
+
+    count = st->regs[R_TIM_LOADVAL];
+    ptimer_set_limit(st->ptimer, count, 1);
+    ptimer_run(st->ptimer, 1);
+}
+
+static uint64_t
+timer_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    MSF2TimerState *t = opaque;
+    struct Msf2Timer *st;
+    uint32_t ret = 0;
+    int timer = 0;
+    int isr;
+    int ier;
+
+    addr >>= 2;
+    /*
+     * Two independent timers has same base address.
+     * Based on addr passed figure out which timer is being used.
+     */
+    if (addr >= R_TIM1_MAX) {
+        timer = 1;
+        addr -= R_TIM1_MAX;
+    }
+
+    st = &t->timers[timer];
+
+    switch (addr) {
+    case R_TIM_VAL:
+        ret = ptimer_get_count(st->ptimer);
+        break;
+
+    case R_TIM_MIS:
+        isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
+        ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
+        ret = ier & isr;
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(st->regs)) {
+            ret = st->regs[addr];
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
+                         addr * 4);
+        }
+        break;
+    }
+
+    DB_PRINT("timer=%d 0x%" HWADDR_PRIx "=0x%" PRIx32 "\n", timer, addr * 4,
+            ret);
+    return ret;
+}
+
+static void
+timer_write(void *opaque, hwaddr addr,
+            uint64_t val64, unsigned int size)
+{
+    MSF2TimerState *t = opaque;
+    struct Msf2Timer *st;
+    int timer = 0;
+    uint32_t value = val64;
+
+    addr >>= 2;
+    /*
+     * Two independent timers has same base address.
+     * Based on addr passed figure out which timer is being used.
+     */
+    if (addr >= R_TIM1_MAX) {
+        timer = 1;
+        addr -= R_TIM1_MAX;
+    }
+
+    st = &t->timers[timer];
+
+    DB_PRINT("addr=0x%" HWADDR_PRIx " val=0x%" PRIx32 " (timer=%d)\n", addr * 4,
+            value, timer);
+
+    switch (addr) {
+    case R_TIM_CTRL:
+        st->regs[R_TIM_CTRL] = value;
+        timer_update(st);
+        break;
+
+    case R_TIM_RIS:
+        if (value & TIMER_RIS_ACK) {
+            st->regs[R_TIM_RIS] &= ~TIMER_RIS_ACK;
+        }
+        break;
+
+    case R_TIM_LOADVAL:
+        st->regs[R_TIM_LOADVAL] = value;
+        if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
+            timer_update(st);
+        }
+        break;
+
+    case R_TIM_BGLOADVAL:
+        st->regs[R_TIM_BGLOADVAL] = value;
+        st->regs[R_TIM_LOADVAL] = value;
+        break;
+
+    case R_TIM_VAL:
+    case R_TIM_MIS:
+        break;
+
+    case R_TIM_MODE:
+        if (value & TIMER_MODE) {
+            qemu_log_mask(LOG_UNIMP, "64-bit mode not supported\n");
+        }
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(st->regs)) {
+            st->regs[addr] = value;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
+                         addr * 4);
+        }
+        break;
+    }
+    timer_update_irq(st);
+}
+
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void timer_hit(void *opaque)
+{
+    struct Msf2Timer *st = opaque;
+
+    st->regs[R_TIM_RIS] |= TIMER_RIS_ACK;
+
+    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ONESHOT)) {
+        timer_update(st);
+    }
+    timer_update_irq(st);
+}
+
+static void msf2_timer_init(Object *obj)
+{
+    MSF2TimerState *t = MSF2_TIMER(obj);
+    int i;
+
+    /* Init all the ptimers.  */
+    t->timers = g_malloc0((sizeof t->timers[0]) * NUM_TIMERS);
+    for (i = 0; i < NUM_TIMERS; i++) {
+        struct Msf2Timer *st = &t->timers[i];
+
+        st->bh = qemu_bh_new(timer_hit, st);
+        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
+        ptimer_set_freq(st->ptimer, t->freq_hz);
+        sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
+    }
+
+    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, TYPE_MSF2_TIMER,
+                          R_TIM_MAX * 4);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio);
+}
+
+static Property msf2_timer_properties[] = {
+    DEFINE_PROP_UINT32("clock-frequency", MSF2TimerState, freq_hz,
+                       MSF2_TIMER_FREQ),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void msf2_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = msf2_timer_properties;
+}
+
+static const TypeInfo msf2_timer_info = {
+    .name          = TYPE_MSF2_TIMER,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MSF2TimerState),
+    .instance_init = msf2_timer_init,
+    .class_init    = msf2_timer_class_init,
+};
+
+static void msf2_timer_register_types(void)
+{
+    type_register_static(&msf2_timer_info);
+}
+
+type_init(msf2_timer_register_types)
diff --git a/include/hw/timer/msf2-timer.h b/include/hw/timer/msf2-timer.h
new file mode 100644
index 0000000..10eb2f8
--- /dev/null
+++ b/include/hw/timer/msf2-timer.h
@@ -0,0 +1,85 @@
+/*
+ * Microsemi SmartFusion2 Timer.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_MSF2_TIMER_H
+#define HW_MSF2_TIMER_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+
+#define TYPE_MSF2_TIMER     "msf2-timer"
+#define MSF2_TIMER(obj)     OBJECT_CHECK(MSF2TimerState, \
+                              (obj), TYPE_MSF2_TIMER)
+
+/*
+ * There are two 32-bit down counting timers.
+ * Timers 1 and 2 can be concatenated into a single 64-bit Timer
+ * that operates either in Periodic mode or in One-shot mode.
+ * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit mode.
+ * In 64-bit mode, writing to the 32-bit registers has no effect.
+ * Similarly, in 32-bit mode, writing to the 64-bit mode registers
+ * has no effect. Only two 32-bit timers are supported currently.
+ */
+#define NUM_TIMERS        2
+
+#define MSF2_TIMER_FREQ   (83 * 1000000)
+
+#define R_TIM_VAL         0
+#define R_TIM_LOADVAL     1
+#define R_TIM_BGLOADVAL   2
+#define R_TIM_CTRL        3
+#define R_TIM_RIS         4
+#define R_TIM_MIS         5
+#define R_TIM1_MAX        6
+
+#define R_TIM_MODE       21
+#define R_TIM_MAX        22 /* including 64-bit timer registers */
+
+#define TIMER_CTRL_ENBL     (1 << 0)
+#define TIMER_CTRL_ONESHOT  (1 << 1)
+#define TIMER_CTRL_INTR     (1 << 2)
+#define TIMER_RIS_ACK       (1 << 0)
+#define TIMER_RST_CLR       (1 << 6)
+#define TIMER_MODE          (1 << 0)
+
+struct Msf2Timer {
+    QEMUBH *bh;
+    ptimer_state *ptimer;
+
+    uint32_t regs[R_TIM_MAX];
+    qemu_irq irq;
+};
+
+typedef struct MSF2TimerState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+    uint32_t freq_hz;
+    struct Msf2Timer *timers;
+} MSF2TimerState;
+
+#endif /* HW_MSF2_TIMER_H */
-- 
2.5.0

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

* [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block.
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer Subbaraya Sundeep
@ 2017-05-09 16:44 ` Subbaraya Sundeep
  2017-05-10 10:34   ` Philippe Mathieu-Daudé
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller Subbaraya Sundeep
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Added Sytem register block of Smartfusion2.
This block has PLL registers which are accessed by guest.

Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
---
 hw/misc/Makefile.objs         |   1 +
 hw/misc/msf2-sysreg.c         | 131 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/misc/msf2-sysreg.h |  80 ++++++++++++++++++++++++++
 3 files changed, 212 insertions(+)
 create mode 100644 hw/misc/msf2-sysreg.c
 create mode 100644 include/hw/misc/msf2-sysreg.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c8b4893..0f52354 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -56,3 +56,4 @@ obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
+obj-$(CONFIG_MSF2) += msf2-sysreg.o
diff --git a/hw/misc/msf2-sysreg.c b/hw/misc/msf2-sysreg.c
new file mode 100644
index 0000000..53e9cba
--- /dev/null
+++ b/hw/misc/msf2-sysreg.c
@@ -0,0 +1,131 @@
+/*
+ * System Register block model of Microsemi SmartFusion2.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/misc/msf2-sysreg.h"
+
+#ifndef MSF2_SYSREG_ERR_DEBUG
+#define MSF2_SYSREG_ERR_DEBUG  0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (MSF2_SYSREG_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void msf2_sysreg_reset(DeviceState *d)
+{
+    MSF2SysregState *s = MSF2_SYSREG(d);
+
+    DB_PRINT("RESET\n");
+
+    s->regs[MSSDDR_PLL_STATUS_LOW_CR] = 0x02420041;
+    s->regs[MSSDDR_FACC1_CR] = 0x0A482124;
+    s->regs[MSSDDR_PLL_STATUS] = 0x3;
+}
+
+static uint64_t msf2_sysreg_read(void *opaque, hwaddr offset,
+    unsigned size)
+{
+    MSF2SysregState *s = opaque;
+    offset /= 4;
+    uint32_t ret = 0;
+
+    if (offset < ARRAY_SIZE(s->regs)) {
+        ret = s->regs[offset];
+        DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx32 "\n",
+                    offset * 4, ret);
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                    "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
+                    offset * 4);
+    }
+
+    return ret;
+}
+
+static void msf2_sysreg_write(void *opaque, hwaddr offset,
+                          uint64_t val, unsigned size)
+{
+    MSF2SysregState *s = (MSF2SysregState *)opaque;
+    offset /= 4;
+
+    DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx64 "\n",
+            offset * 4, val);
+
+    switch (offset) {
+    case MSSDDR_PLL_STATUS:
+        break;
+
+    default:
+        if (offset < ARRAY_SIZE(s->regs)) {
+            s->regs[offset] = val;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                        "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
+                        offset * 4);
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps sysreg_ops = {
+    .read = msf2_sysreg_read,
+    .write = msf2_sysreg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void msf2_sysreg_init(Object *obj)
+{
+    MSF2SysregState *s = MSF2_SYSREG(obj);
+
+    memory_region_init_io(&s->iomem, obj, &sysreg_ops, s, TYPE_MSF2_SYSREG,
+                          MSF2_SYSREG_MMIO_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static const VMStateDescription vmstate_msf2_sysreg = {
+    .name = TYPE_MSF2_SYSREG,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MSF2SysregState, MSF2_SYSREG_NUM_REGS),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void msf2_sysreg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_msf2_sysreg;
+    dc->reset = msf2_sysreg_reset;
+}
+
+static const TypeInfo msf2_sysreg_info = {
+    .name  = TYPE_MSF2_SYSREG,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .class_init = msf2_sysreg_class_init,
+    .instance_size  = sizeof(MSF2SysregState),
+    .instance_init = msf2_sysreg_init,
+};
+
+static void msf2_sysreg_register_types(void)
+{
+    type_register_static(&msf2_sysreg_info);
+}
+
+type_init(msf2_sysreg_register_types)
diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.h
new file mode 100644
index 0000000..a485ed6
--- /dev/null
+++ b/include/hw/misc/msf2-sysreg.h
@@ -0,0 +1,80 @@
+/*
+ * Microsemi SmartFusion2 SYSREG
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_MSF2_SYSREG_H
+#define HW_MSF2_SYSREG_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+
+enum {
+    ESRAM_CR        = 0x00 / 4,
+    ESRAM_MAX_LAT,
+    DDR_CR,
+    ENVM_CR,
+    ENVM_REMAP_BASE_CR,
+    ENVM_REMAP_FAB_CR,
+    CC_CR,
+    CC_REGION_CR,
+    CC_LOCK_BASE_ADDR_CR,
+    CC_FLUSH_INDX_CR,
+    DDRB_BUF_TIMER_CR,
+    DDRB_NB_ADDR_CR,
+    DDRB_NB_SIZE_CR,
+    DDRB_CR,
+
+    SOFT_RESET_CR  = 0x48 / 4,
+    M3_CR,
+
+    GPIO_SYSRESET_SEL_CR = 0x58 / 4,
+
+    MDDR_CR = 0x60 / 4,
+
+    MSSDDR_PLL_STATUS_LOW_CR = 0x90 / 4,
+    MSSDDR_PLL_STATUS_HIGH_CR,
+    MSSDDR_FACC1_CR,
+    MSSDDR_FACC2_CR,
+
+    MSSDDR_PLL_STATUS = 0x150 / 4,
+
+};
+
+#define MSF2_SYSREG_MMIO_SIZE     0x300
+#define MSF2_SYSREG_NUM_REGS      (MSF2_SYSREG_MMIO_SIZE / 4)
+
+#define TYPE_MSF2_SYSREG          "msf2-sysreg"
+#define MSF2_SYSREG(obj)  OBJECT_CHECK(MSF2SysregState, (obj), TYPE_MSF2_SYSREG)
+
+typedef struct MSF2SysregState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+
+    uint32_t regs[MSF2_SYSREG_NUM_REGS];
+} MSF2SysregState;
+
+#endif /* HW_MSF2_SYSREG_H */
-- 
2.5.0

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

* [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer Subbaraya Sundeep
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block Subbaraya Sundeep
@ 2017-05-09 16:44 ` Subbaraya Sundeep
  2017-05-10 12:12   ` Philippe Mathieu-Daudé
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC Subbaraya Sundeep
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Modelled Microsemi's Smartfusion2 SPI controller.

Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
---
 hw/ssi/Makefile.objs      |   1 +
 hw/ssi/msf2-spi.c         | 378 ++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/ssi/msf2-spi.h | 105 +++++++++++++
 3 files changed, 484 insertions(+)
 create mode 100644 hw/ssi/msf2-spi.c
 create mode 100644 include/hw/ssi/msf2-spi.h

diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 487add2..3105c4b 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
 common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
+common-obj-$(CONFIG_MSF2) += msf2-spi.o
 
 obj-$(CONFIG_OMAP) += omap_spi.o
 obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/msf2-spi.c b/hw/ssi/msf2-spi.c
new file mode 100644
index 0000000..2059ed9
--- /dev/null
+++ b/hw/ssi/msf2-spi.c
@@ -0,0 +1,378 @@
+/*
+ * SPI controller model of Microsemi SmartFusion2.
+ *
+ * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/ssi/msf2-spi.h"
+
+#ifndef MSF2_SPI_ERR_DEBUG
+#define MSF2_SPI_ERR_DEBUG   0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (MSF2_SPI_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void txfifo_reset(MSF2SpiState *s)
+{
+    fifo32_reset(&s->tx_fifo);
+
+    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;
+    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;
+}
+
+static void rxfifo_reset(MSF2SpiState *s)
+{
+    fifo32_reset(&s->rx_fifo);
+
+    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
+    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
+}
+
+static void set_fifodepth(MSF2SpiState *s)
+{
+    int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;
+
+    if (0 <= size && size <= 8) {
+        s->fifo_depth = 32;
+    }
+    if (9 <= size && size <= 16) {
+        s->fifo_depth = 16;
+    }
+    if (17 <= size && size <= 32) {
+        s->fifo_depth = 8;
+    }
+}
+
+static void msf2_spi_do_reset(MSF2SpiState *s)
+{
+    memset(s->regs, 0, sizeof s->regs);
+    s->regs[R_SPI_CONTROL] = 0x80000102;
+    s->regs[R_SPI_DFSIZE] = 0x4;
+    s->regs[R_SPI_STATUS] = 0x2440;
+    s->regs[R_SPI_CLKGEN] = 0x7;
+    s->regs[R_SPI_STAT8] = 0x7;
+    s->regs[R_SPI_RIS] = 0x0;
+
+    s->fifo_depth = 4;
+    s->frame_count = 1;
+    s->enabled = false;
+
+    rxfifo_reset(s);
+    txfifo_reset(s);
+}
+
+static void update_mis(MSF2SpiState *s)
+{
+    uint32_t reg = s->regs[R_SPI_CONTROL];
+    uint32_t tmp;
+
+    /*
+     * form the Control register interrupt enable bits
+     * same as RIS, MIS and Interrupt clear registers for simplicity
+     */
+    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |
+           ((reg & C_INTTXDATA) >> 5);
+    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];
+}
+
+static void spi_update_irq(MSF2SpiState *s)
+{
+    int irq;
+
+    update_mis(s);
+    irq = !!(s->regs[R_SPI_MIS]);
+
+    qemu_set_irq(s->irq, irq);
+}
+
+static void msf2_spi_reset(DeviceState *d)
+{
+    msf2_spi_do_reset(MSF2_SPI(d));
+}
+
+static uint64_t
+spi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    MSF2SpiState *s = opaque;
+    uint32_t ret = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_SPI_RX:
+        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
+        s->regs[R_SPI_STATUS] &= ~RXCHOVRF;
+        ret = fifo32_pop(&s->rx_fifo);
+        if (fifo32_is_empty(&s->rx_fifo)) {
+            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
+        }
+        break;
+
+    case R_SPI_MIS:
+        update_mis(s);
+        ret = s->regs[R_SPI_MIS];
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            ret = s->regs[addr];
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
+                         addr * 4);
+        }
+        break;
+    }
+
+    DB_PRINT("addr=0x%" HWADDR_PRIx " = 0x%" PRIx32 "\n", addr * 4, ret);
+    spi_update_irq(s);
+    return ret;
+}
+
+static void assert_cs(MSF2SpiState *s)
+{
+    qemu_set_irq(s->cs_line, 0);
+}
+
+static void deassert_cs(MSF2SpiState *s)
+{
+    qemu_set_irq(s->cs_line, 1);
+}
+
+static void spi_flush_txfifo(MSF2SpiState *s)
+{
+    uint32_t tx;
+    uint32_t rx;
+    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);
+
+    /*
+     * Chip Select(CS) is automatically controlled by this controller.
+     * If SPS bit is set in Control register then CS is asserted
+     * until all the frames set in frame count of Control register are
+     * transferred. If SPS is not set then CS pulses between frames.
+     * Note that Slave Select register specifies which of the CS line
+     * has to be controlled automatically by controller. Bits SS[7:1] are for
+     * masters in FPGA fabric since we model only Microcontroller subsystem
+     * of Smartfusion2 we control only one CS(SS[0]) line.
+     */
+    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {
+        assert_cs(s);
+
+        s->regs[R_SPI_STATUS] &= ~TXDONE;
+        s->regs[R_SPI_STATUS] &= ~RXRDY;
+
+        tx = fifo32_pop(&s->tx_fifo);
+        DB_PRINT("data tx:0x%" PRIx32 "\n", tx);
+        rx = ssi_transfer(s->spi, tx);
+        DB_PRINT("data rx:0x%" PRIx32 "\n", rx);
+
+        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
+            s->regs[R_SPI_STATUS] |= RXCHOVRF;
+            s->regs[R_SPI_RIS] |= RXCHOVRF;
+        } else {
+            fifo32_push(&s->rx_fifo, rx);
+            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;
+            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {
+                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;
+            }
+            if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
+                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;
+            }
+        }
+        s->frame_count--;
+        if (!sps) {
+            deassert_cs(s);
+            assert_cs(s);
+        }
+    }
+
+    if (!sps) {
+        deassert_cs(s);
+    }
+
+    if (!s->frame_count) {
+        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>
+                            FMCOUNT_SHIFT;
+        if (sps) {
+            deassert_cs(s);
+        }
+        s->regs[R_SPI_RIS] |= TXDONE;
+        s->regs[R_SPI_RIS] |= RXRDY;
+        s->regs[R_SPI_STATUS] |= TXDONE;
+        s->regs[R_SPI_STATUS] |= RXRDY;
+   }
+}
+
+static void spi_write(void *opaque, hwaddr addr,
+            uint64_t val64, unsigned int size)
+{
+    MSF2SpiState *s = opaque;
+    uint32_t value = val64;
+
+    DB_PRINT("addr=0x%" HWADDR_PRIx " =0x%" PRIx32 "\n", addr, value);
+    addr >>= 2;
+
+    switch (addr) {
+    case R_SPI_TX:
+        /* adding to already full FIFO */
+        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
+            break;
+        }
+        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;
+        fifo32_push(&s->tx_fifo, value);
+        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {
+            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;
+        }
+        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
+            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;
+        }
+        if (s->enabled) {
+            spi_flush_txfifo(s);
+        }
+        break;
+
+    case R_SPI_CONTROL:
+        s->regs[R_SPI_CONTROL] = value;
+        if (value & C_BIGFIFO) {
+            set_fifodepth(s);
+        } else {
+            s->fifo_depth = 4;
+        }
+        if (value & C_ENABLE) {
+            s->enabled = true;
+        } else {
+            s->enabled = false;
+        }
+        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;
+        if (value & C_RESET) {
+            msf2_spi_do_reset(s);
+        }
+        break;
+
+    case R_SPI_DFSIZE:
+        if (s->enabled) {
+            break;
+        }
+        s->regs[R_SPI_DFSIZE] = value;
+        break;
+
+    case R_SPI_INTCLR:
+        s->regs[R_SPI_INTCLR] = value;
+        if (value & TXDONE) {
+            s->regs[R_SPI_RIS] &= ~TXDONE;
+        }
+        if (value & RXRDY) {
+            s->regs[R_SPI_RIS] &= ~RXRDY;
+        }
+        if (value & RXCHOVRF) {
+            s->regs[R_SPI_RIS] &= ~RXCHOVRF;
+        }
+        break;
+
+    case R_SPI_MIS:
+    case R_SPI_STATUS:
+    case R_SPI_RIS:
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
+                         addr * 4);
+        }
+        break;
+    }
+
+    spi_update_irq(s);
+}
+
+static const MemoryRegionOps spi_ops = {
+    .read = spi_read,
+    .write = spi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void msf2_spi_realize(DeviceState *dev, Error **errp)
+{
+    MSF2SpiState *s = MSF2_SPI(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    DB_PRINT("\n");
+
+    s->spi = ssi_create_bus(dev, "spi0");
+
+    sysbus_init_irq(sbd, &s->irq);
+    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);
+    sysbus_init_irq(sbd, &s->cs_line);
+
+    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
+                          TYPE_MSF2_SPI, R_SPI_MAX * 4);
+    sysbus_init_mmio(sbd, &s->mmio);
+
+    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);
+    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);
+}
+
+static const VMStateDescription vmstate_msf2_spi = {
+    .name = TYPE_MSF2_SPI,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_FIFO32(tx_fifo, MSF2SpiState),
+        VMSTATE_FIFO32(rx_fifo, MSF2SpiState),
+        VMSTATE_UINT32_ARRAY(regs, MSF2SpiState, R_SPI_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void msf2_spi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = msf2_spi_realize;
+    dc->reset = msf2_spi_reset;
+    dc->vmsd = &vmstate_msf2_spi;
+}
+
+static const TypeInfo msf2_spi_info = {
+    .name           = TYPE_MSF2_SPI,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(MSF2SpiState),
+    .class_init     = msf2_spi_class_init,
+};
+
+static void msf2_spi_register_types(void)
+{
+    type_register_static(&msf2_spi_info);
+}
+
+type_init(msf2_spi_register_types)
diff --git a/include/hw/ssi/msf2-spi.h b/include/hw/ssi/msf2-spi.h
new file mode 100644
index 0000000..585edde
--- /dev/null
+++ b/include/hw/ssi/msf2-spi.h
@@ -0,0 +1,105 @@
+/*
+ * Microsemi SmartFusion2 SPI
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_MSF2_SPI_H
+#define HW_MSF2_SPI_H
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/ssi/ssi.h"
+#include "qemu/fifo32.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+
+#define FIFO_CAPACITY     32
+#define FIFO_CAPACITY     32
+
+#define R_SPI_CONTROL         0
+#define R_SPI_DFSIZE          1
+#define R_SPI_STATUS          2
+#define R_SPI_INTCLR          3
+#define R_SPI_RX              4
+#define R_SPI_TX              5
+#define R_SPI_CLKGEN          6
+#define R_SPI_SS              7
+#define R_SPI_MIS             8
+#define R_SPI_RIS             9
+#define R_SPI_STAT8           15
+#define R_SPI_MAX             16
+
+#define S_RXFIFOFUL       (1 << 4)
+#define S_RXFIFOFULNXT    (1 << 5)
+#define S_RXFIFOEMP       (1 << 6)
+#define S_RXFIFOEMPNXT    (1 << 7)
+#define S_TXFIFOFUL       (1 << 8)
+#define S_TXFIFOFULNXT    (1 << 9)
+#define S_TXFIFOEMP       (1 << 10)
+#define S_TXFIFOEMPNXT    (1 << 11)
+#define S_FRAMESTART      (1 << 12)
+#define S_SSEL            (1 << 13)
+#define S_ACTIVE          (1 << 14)
+
+#define C_ENABLE          (1 << 0)
+#define C_MODE            (1 << 1)
+#define C_INTRXDATA       (1 << 4)
+#define C_INTTXDATA       (1 << 5)
+#define C_INTRXOVRFLO     (1 << 6)
+#define C_SPS             (1 << 26)
+#define C_BIGFIFO         (1 << 29)
+#define C_RESET           (1 << 31)
+
+#define FRAMESZ_MASK      0x1F
+#define FMCOUNT_MASK      0x00FFFF00
+#define FMCOUNT_SHIFT     8
+
+#define TXDONE            (1 << 0)
+#define RXRDY             (1 << 1)
+#define RXCHOVRF          (1 << 2)
+
+#define TYPE_MSF2_SPI   "msf2-spi"
+#define MSF2_SPI(obj)   OBJECT_CHECK(MSF2SpiState, (obj), TYPE_MSF2_SPI)
+
+typedef struct MSF2SpiState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    qemu_irq irq;
+
+    qemu_irq cs_line;
+
+    SSIBus *spi;
+
+    Fifo32 rx_fifo;
+    Fifo32 tx_fifo;
+
+    int fifo_depth;
+    uint32_t frame_count;
+    bool enabled;
+
+    uint32_t regs[R_SPI_MAX];
+} MSF2SpiState;
+
+#endif /* HW_MSF2_SPI_H */
-- 
2.5.0

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

* [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
                   ` (2 preceding siblings ...)
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller Subbaraya Sundeep
@ 2017-05-09 16:44 ` Subbaraya Sundeep
  2017-05-10 11:50   ` Philippe Mathieu-Daudé
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit Subbaraya Sundeep
  2017-05-10  9:44 ` [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Philippe Mathieu-Daudé
  5 siblings, 1 reply; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Smartfusion2 SoC has hardened Microcontroller subsystem
and flash based FPGA fabric. This patch adds support for
Microcontroller subsystem in the SoC.

Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
---
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs            |   2 +-
 hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/msf2-soc.h       |  60 +++++++++++++
 4 files changed, 250 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/msf2-soc.c
 create mode 100644 include/hw/arm/msf2-soc.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 78d7af0..7062512 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -122,3 +122,4 @@ CONFIG_ACPI=y
 CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
+CONFIG_MSF2=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 4c5c4ee..ae5e4a3 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,7 +1,7 @@
 obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
 obj-$(CONFIG_DIGIC) += digic_boards.o
 obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
-obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
+obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
 obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
 obj-y += netduino2.o
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
new file mode 100644
index 0000000..d6341a2
--- /dev/null
+++ b/hw/arm/msf2-soc.c
@@ -0,0 +1,188 @@
+/*
+ * SmartFusion2 SoC emulation.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/arm.h"
+#include "exec/address-spaces.h"
+#include "hw/char/serial.h"
+#include "hw/boards.h"
+#include "sysemu/block-backend.h"
+#include "hw/arm/msf2-soc.h"
+
+#define MSF2_TIMER_BASE       0x40004000
+#define MSF2_SYSREG_BASE      0x40038000
+
+#define MSF2_TIMER_IRQ0       14
+#define MSF2_TIMER_IRQ1       15
+
+static const uint32_t spi_addr[MSF2_NUM_SPIS] = { 0x40001000 , 0x40011000 };
+static const uint32_t uart_addr[MSF2_NUM_UARTS] = { 0x40000000 , 0x40010000 };
+
+static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 };
+static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 };
+
+static void msf2_soc_initfn(Object *obj)
+{
+    MSF2State *s = MSF2_SOC(obj);
+    int i;
+
+    object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
+    qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
+
+    object_initialize(&s->sysreg, sizeof(s->sysreg), TYPE_MSF2_SYSREG);
+    qdev_set_parent_bus(DEVICE(&s->sysreg), sysbus_get_default());
+
+    object_initialize(&s->timer, sizeof(s->timer), TYPE_MSF2_TIMER);
+    qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default());
+
+    for (i = 0; i < MSF2_NUM_SPIS; i++) {
+        object_initialize(&s->spi[i], sizeof(s->spi[i]),
+                          TYPE_MSF2_SPI);
+        qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
+    }
+}
+
+static void msf2_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+    MSF2State *s = MSF2_SOC(dev_soc);
+    DeviceState *dev, *armv7m;
+    SysBusDevice *busdev;
+    Error *err = NULL;
+    int i;
+
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *nvm = g_new(MemoryRegion, 1);
+    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *ddr = g_new(MemoryRegion, 1);
+
+    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
+                           &error_fatal);
+    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
+                             nvm, 0, ENVM_SIZE);
+    vmstate_register_ram_global(nvm);
+
+    memory_region_set_readonly(nvm, true);
+    memory_region_set_readonly(nvm_alias, true);
+
+    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
+    memory_region_add_subregion(system_memory, 0, nvm_alias);
+
+    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
+                           &error_fatal);
+    vmstate_register_ram_global(ddr);
+    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS, ddr);
+
+    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
+                           &error_fatal);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
+
+    armv7m = DEVICE(&s->armv7m);
+    qdev_prop_set_uint32(armv7m, "num-irq", 96);
+    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
+    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
+                                     "memory", &error_abort);
+    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    for (i = 0; i < MSF2_NUM_UARTS; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(get_system_memory(), uart_addr[i], 2,
+                           qdev_get_gpio_in(armv7m, uart_irq[i]),
+                           115200, serial_hds[i], DEVICE_NATIVE_ENDIAN);
+        }
+    }
+
+    dev = DEVICE(&s->timer);
+    qdev_prop_set_uint32(dev, "clock-frequency", MSF2_TIMER_FREQ);
+    object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, MSF2_TIMER_BASE);
+    sysbus_connect_irq(busdev, 0,
+                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ0));
+    sysbus_connect_irq(busdev, 1,
+                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ1));
+
+    dev = DEVICE(&s->sysreg);
+    object_property_set_bool(OBJECT(&s->sysreg), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, MSF2_SYSREG_BASE);
+
+    for (i = 0; i < MSF2_NUM_SPIS; i++) {
+        gchar *bus_name = g_strdup_printf("spi%d", i);
+
+        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
+        if (err != NULL) {
+            g_free(bus_name);
+            error_propagate(errp, err);
+            return;
+        }
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_addr[i]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
+                           qdev_get_gpio_in(armv7m, spi_irq[i]));
+
+        /* Alias controller SPI bus to the SoC itself */
+        object_property_add_alias(OBJECT(s), bus_name,
+                                  OBJECT(&s->spi[i]), "spi0",
+                                  &error_abort);
+        g_free(bus_name);
+    }
+}
+
+static void msf2_soc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = msf2_soc_realize;
+}
+
+static const TypeInfo msf2_soc_info = {
+    .name          = TYPE_MSF2_SOC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MSF2State),
+    .instance_init = msf2_soc_initfn,
+    .class_init    = msf2_soc_class_init,
+};
+
+static void msf2_soc_types(void)
+{
+    type_register_static(&msf2_soc_info);
+}
+
+type_init(msf2_soc_types)
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
new file mode 100644
index 0000000..29a8ff8
--- /dev/null
+++ b/include/hw/arm/msf2-soc.h
@@ -0,0 +1,60 @@
+/*
+ * Microsemi Smartfusion2 SoC
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_MSF2_SOC_H
+#define HW_ARM_MSF2_SOC_H
+
+#include "hw/misc/msf2-sysreg.h"
+#include "hw/timer/msf2-timer.h"
+#include "hw/ssi/msf2-spi.h"
+#include "hw/arm/armv7m.h"
+
+#define TYPE_MSF2_SOC     "msf2-soc"
+#define MSF2_SOC(obj)     OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
+
+#define MSF2_NUM_SPIS         2
+#define MSF2_NUM_UARTS        2
+
+#define ENVM_BASE_ADDRESS     0x60000000
+#define ENVM_SIZE             (128 * 1024)
+
+#define DDR_BASE_ADDRESS      0xA0000000
+#define DDR_SIZE              (64 * 1024 * 1024)
+
+#define SRAM_BASE_ADDRESS     0x20000000
+#define SRAM_SIZE             (64 * 1024)
+
+typedef struct MSF2State {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    ARMv7MState armv7m;
+
+    MSF2SysregState sysreg;
+    MSF2TimerState timer;
+    MSF2SpiState spi[MSF2_NUM_SPIS];
+} MSF2State;
+
+#endif
-- 
2.5.0

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

* [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit.
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
                   ` (3 preceding siblings ...)
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC Subbaraya Sundeep
@ 2017-05-09 16:44 ` Subbaraya Sundeep
  2017-05-10 11:16   ` Philippe Mathieu-Daudé
  2017-05-10  9:44 ` [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Philippe Mathieu-Daudé
  5 siblings, 1 reply; 26+ messages in thread
From: Subbaraya Sundeep @ 2017-05-09 16:44 UTC (permalink / raw)
  To: qemu-devel, qemu-arm
  Cc: peter.maydell, crosthwaite.peter, alistair23, Subbaraya Sundeep

Emulated Emcraft's Smartfusion2 System On Module starter
kit.

Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
---
 hw/arm/Makefile.objs |  1 +
 hw/arm/msf2-som.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 hw/arm/msf2-som.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index ae5e4a3..b626a43 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -5,6 +5,7 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
 obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
 obj-y += netduino2.o
+obj-y += msf2-som.o
 obj-y += sysbus-fdt.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
new file mode 100644
index 0000000..bc44169
--- /dev/null
+++ b/hw/arm/msf2-som.c
@@ -0,0 +1,67 @@
+/*
+ * SmartFusion2 SOM starter kit(from Emcraft) emulation.
+ *
+ * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/arm/msf2-soc.h"
+#include "hw/arm/arm.h"
+
+static void msf2_init(MachineState *machine)
+{
+    DeviceState *dev;
+    DeviceState *spi_flash;
+    MSF2State *soc;
+    DriveInfo *dinfo = drive_get_next(IF_MTD);
+    qemu_irq cs_line;
+    SSIBus *spi_bus;
+
+    dev = qdev_create(NULL, TYPE_MSF2_SOC);
+    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
+
+    soc = MSF2_SOC(dev);
+
+    /* Attach SPI flash to SPI0 controller */
+    spi_bus = (SSIBus *)qdev_get_child_bus(dev, "spi0");
+    spi_flash = ssi_create_slave_no_init(spi_bus, "s25sl12801");
+    qdev_prop_set_uint8(spi_flash, "spansion-cr2nv", 1);
+    if (dinfo) {
+        qdev_prop_set_drive(spi_flash, "drive", blk_by_legacy_dinfo(dinfo),
+                                    &error_fatal);
+    }
+    qdev_init_nofail(spi_flash);
+    cs_line = qdev_get_gpio_in_named(spi_flash, SSI_GPIO_CS, 0);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
+
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
+                       ENVM_SIZE);
+}
+
+static void msf2_machine_init(MachineClass *mc)
+{
+    mc->desc = "SmartFusion2 SOM kit from Emcraft";
+    mc->init = msf2_init;
+}
+
+DEFINE_MACHINE("smartfusion2-som", msf2_machine_init)
-- 
2.5.0

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer Subbaraya Sundeep
@ 2017-05-10  9:41   ` Philippe Mathieu-Daudé
  2017-05-10 12:37     ` sundeep subbaraya
  2017-05-15 11:52     ` Philippe Mathieu-Daudé
  0 siblings, 2 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10  9:41 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm; +Cc: peter.maydell, alistair23

Hi Subbaraya, nice work!

The timer you are modeling is the mss_timer, which is in particular used 
in the smartfusion2, I'd rather name it mss_timer.c so it can be reused 
by other SoC models.

I added few comments.

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Modelled System Timer in Microsemi's Smartfusion2 Soc.
> Timer has two 32bit down counters and two interrupts.
>
> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> ---
>  hw/timer/Makefile.objs        |   1 +
>  hw/timer/msf2-timer.c         | 252 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/timer/msf2-timer.h |  85 ++++++++++++++
>  3 files changed, 338 insertions(+)
>  create mode 100644 hw/timer/msf2-timer.c
>  create mode 100644 include/hw/timer/msf2-timer.h
>
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index dd6f27e..bd1ff15 100644
> --- a/hw/timer/Makefile.objs
> +++ b/hw/timer/Makefile.objs
> @@ -41,3 +41,4 @@ common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
>
>  common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
> +common-obj-$(CONFIG_MSF2) += msf2-timer.o
> diff --git a/hw/timer/msf2-timer.c b/hw/timer/msf2-timer.c
> new file mode 100644
> index 0000000..466faa6
> --- /dev/null
> +++ b/hw/timer/msf2-timer.c
> @@ -0,0 +1,252 @@
> +/*
> + * Timer block model of Microsemi SmartFusion2.
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "hw/timer/msf2-timer.h"
> +
> +#ifndef MSF2_TIMER_ERR_DEBUG
> +#define MSF2_TIMER_ERR_DEBUG  0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (MSF2_TIMER_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0);
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
> +
> +static void timer_update_irq(struct Msf2Timer *st)
> +{
> +    bool isr, ier;
> +
> +    isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
> +    ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
> +
> +    qemu_set_irq(st->irq, (ier && isr));
> +}
> +
> +static void timer_update(struct Msf2Timer *st)
> +{
> +    uint64_t count;
> +
> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL)) {
> +        ptimer_stop(st->ptimer);
> +        return;
> +    }
> +
> +    count = st->regs[R_TIM_LOADVAL];
> +    ptimer_set_limit(st->ptimer, count, 1);
> +    ptimer_run(st->ptimer, 1);
> +}
> +
> +static uint64_t
> +timer_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> +    MSF2TimerState *t = opaque;
> +    struct Msf2Timer *st;
> +    uint32_t ret = 0;
> +    int timer = 0;
> +    int isr;
> +    int ier;
> +
> +    addr >>= 2;
> +    /*
> +     * Two independent timers has same base address.
> +     * Based on addr passed figure out which timer is being used.
> +     */
> +    if (addr >= R_TIM1_MAX) {
> +        timer = 1;
> +        addr -= R_TIM1_MAX;
> +    }
> +
> +    st = &t->timers[timer];
> +
> +    switch (addr) {
> +    case R_TIM_VAL:
> +        ret = ptimer_get_count(st->ptimer);
> +        break;
> +
> +    case R_TIM_MIS:
> +        isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
> +        ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
> +        ret = ier & isr;
> +        break;
> +
> +    default:
> +        if (addr < ARRAY_SIZE(st->regs)) {
> +            ret = st->regs[addr];
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
> +                         addr * 4);
> +        }
> +        break;
> +    }
> +
> +    DB_PRINT("timer=%d 0x%" HWADDR_PRIx "=0x%" PRIx32 "\n", timer, addr * 4,
> +            ret);
> +    return ret;
> +}
> +
> +static void
> +timer_write(void *opaque, hwaddr addr,
> +            uint64_t val64, unsigned int size)
> +{
> +    MSF2TimerState *t = opaque;
> +    struct Msf2Timer *st;
> +    int timer = 0;
> +    uint32_t value = val64;
> +
> +    addr >>= 2;
> +    /*
> +     * Two independent timers has same base address.
> +     * Based on addr passed figure out which timer is being used.
> +     */
> +    if (addr >= R_TIM1_MAX) {
> +        timer = 1;
> +        addr -= R_TIM1_MAX;

This is only valid if addr < (NUM_TIMERS * R_TIM1_MAX).

> +    }
> +
> +    st = &t->timers[timer];
> +
> +    DB_PRINT("addr=0x%" HWADDR_PRIx " val=0x%" PRIx32 " (timer=%d)\n", addr * 4,
> +            value, timer);
> +
> +    switch (addr) {
> +    case R_TIM_CTRL:
> +        st->regs[R_TIM_CTRL] = value;
> +        timer_update(st);
> +        break;
> +
> +    case R_TIM_RIS:
> +        if (value & TIMER_RIS_ACK) {
> +            st->regs[R_TIM_RIS] &= ~TIMER_RIS_ACK;
> +        }
> +        break;
> +
> +    case R_TIM_LOADVAL:
> +        st->regs[R_TIM_LOADVAL] = value;
> +        if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
> +            timer_update(st);
> +        }
> +        break;
> +
> +    case R_TIM_BGLOADVAL:
> +        st->regs[R_TIM_BGLOADVAL] = value;
> +        st->regs[R_TIM_LOADVAL] = value;
> +        break;
> +
> +    case R_TIM_VAL:
> +    case R_TIM_MIS:
> +        break;
> +
> +    case R_TIM_MODE:

This case is never reached, if the guest wanted to access register 21, 
since 21 >= R_TIM1_MAX you have now addr = 21 - R_TIM1_MAX = 15.

> +        if (value & TIMER_MODE) {
> +            qemu_log_mask(LOG_UNIMP, "64-bit mode not supported\n");

No need of trailing '\n', be more specific, something like:

     qemu_log_mask(LOG_UNIMP, TYPE_MSF2_TIMER ": 64-bit mode not 
supported");

> +        }
> +        break;
> +
> +    default:

Once the issue "addr -= R_TIM1_MAX" is fixed, this default will catch 
registers 12 .. 20 silently while there are unimplemented!
I'd rather catch them altogether and log some "64-bit mode not supported".

> +        if (addr < ARRAY_SIZE(st->regs)) {
> +            st->regs[addr] = value;
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
> +                         addr * 4);
> +        }
> +        break;
> +    }
> +    timer_update_irq(st);

Here if addr >= (NUM_TIMERS * R_TIM1_MAX) you still update Timer1 IRQ, 
while this is unharmful right now this is likely to be break later.

> +}
> +
> +static const MemoryRegionOps timer_ops = {
> +    .read = timer_read,
> +    .write = timer_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 4,

I believe min_access_size = 1 is valid for any APB device.

> +        .max_access_size = 4
> +    }
> +};
> +
> +static void timer_hit(void *opaque)
> +{
> +    struct Msf2Timer *st = opaque;
> +
> +    st->regs[R_TIM_RIS] |= TIMER_RIS_ACK;
> +
> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ONESHOT)) {
> +        timer_update(st);
> +    }
> +    timer_update_irq(st);
> +}
> +
> +static void msf2_timer_init(Object *obj)
> +{
> +    MSF2TimerState *t = MSF2_TIMER(obj);
> +    int i;
> +
> +    /* Init all the ptimers.  */
> +    t->timers = g_malloc0((sizeof t->timers[0]) * NUM_TIMERS);
> +    for (i = 0; i < NUM_TIMERS; i++) {
> +        struct Msf2Timer *st = &t->timers[i];
> +
> +        st->bh = qemu_bh_new(timer_hit, st);
> +        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
> +        ptimer_set_freq(st->ptimer, t->freq_hz);
> +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
> +    }
> +
> +    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, TYPE_MSF2_TIMER,
> +                          R_TIM_MAX * 4);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio);
> +}
> +
> +static Property msf2_timer_properties[] = {
> +    DEFINE_PROP_UINT32("clock-frequency", MSF2TimerState, freq_hz,
> +                       MSF2_TIMER_FREQ),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void msf2_timer_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->props = msf2_timer_properties;
> +}
> +
> +static const TypeInfo msf2_timer_info = {
> +    .name          = TYPE_MSF2_TIMER,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(MSF2TimerState),
> +    .instance_init = msf2_timer_init,
> +    .class_init    = msf2_timer_class_init,
> +};
> +
> +static void msf2_timer_register_types(void)
> +{
> +    type_register_static(&msf2_timer_info);
> +}
> +
> +type_init(msf2_timer_register_types)
> diff --git a/include/hw/timer/msf2-timer.h b/include/hw/timer/msf2-timer.h
> new file mode 100644
> index 0000000..10eb2f8
> --- /dev/null
> +++ b/include/hw/timer/msf2-timer.h
> @@ -0,0 +1,85 @@
> +/*
> + * Microsemi SmartFusion2 Timer.
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_MSF2_TIMER_H
> +#define HW_MSF2_TIMER_H
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/ptimer.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/log.h"
> +
> +#define TYPE_MSF2_TIMER     "msf2-timer"
> +#define MSF2_TIMER(obj)     OBJECT_CHECK(MSF2TimerState, \
> +                              (obj), TYPE_MSF2_TIMER)
> +
> +/*
> + * There are two 32-bit down counting timers.
> + * Timers 1 and 2 can be concatenated into a single 64-bit Timer
> + * that operates either in Periodic mode or in One-shot mode.
> + * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit mode.
> + * In 64-bit mode, writing to the 32-bit registers has no effect.
> + * Similarly, in 32-bit mode, writing to the 64-bit mode registers
> + * has no effect. Only two 32-bit timers are supported currently.
> + */
> +#define NUM_TIMERS        2
> +
> +#define MSF2_TIMER_FREQ   (83 * 1000000)

I can not find this value, can you point me to the datasheet? It seems 
SoC specific to me.

> +
> +#define R_TIM_VAL         0
> +#define R_TIM_LOADVAL     1
> +#define R_TIM_BGLOADVAL   2
> +#define R_TIM_CTRL        3
> +#define R_TIM_RIS         4
> +#define R_TIM_MIS         5
> +#define R_TIM1_MAX        6
> +
> +#define R_TIM_MODE       21
> +#define R_TIM_MAX        22 /* including 64-bit timer registers */
> +
> +#define TIMER_CTRL_ENBL     (1 << 0)
> +#define TIMER_CTRL_ONESHOT  (1 << 1)
> +#define TIMER_CTRL_INTR     (1 << 2)
> +#define TIMER_RIS_ACK       (1 << 0)
> +#define TIMER_RST_CLR       (1 << 6)
> +#define TIMER_MODE          (1 << 0)
> +
> +struct Msf2Timer {
> +    QEMUBH *bh;
> +    ptimer_state *ptimer;
> +
> +    uint32_t regs[R_TIM_MAX];
> +    qemu_irq irq;
> +};
> +
> +typedef struct MSF2TimerState {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion mmio;
> +    uint32_t freq_hz;
> +    struct Msf2Timer *timers;
> +} MSF2TimerState;
> +
> +#endif /* HW_MSF2_TIMER_H */

Regards,

Phil.

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC
  2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
                   ` (4 preceding siblings ...)
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit Subbaraya Sundeep
@ 2017-05-10  9:44 ` Philippe Mathieu-Daudé
  2017-05-10 15:24   ` sundeep subbaraya
  5 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10  9:44 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm; +Cc: peter.maydell, alistair23

Hi Subbaraya,

This is your v4 of this patch set, please don't forget to include the 
version in your next set.

Please also include changes between versions in your cover letter, it 
eases the review.

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Hi Qemu-devel,
>
> I am trying to add Smartfusion2 SoC.
> SoC is from Microsemi and System on Module(SOM)
> board is from Emcraft systems. Smartfusion2 has hardened
> Microcontroller(Cortex-M3)based Sub System and FPGA fabric.
> At the moment only system timer, sysreg and SPI
> controller are modelled.
>
> Testing:
> ./arm-softmmu/qemu-system-arm -M smartfusion2-som -serial mon:stdio \
> -kernel u-boot.bin -display none -drive file=spi.bin,if=mtd,format=raw
>
> U-boot is from Emcraft with modified SPI driver not to use PDMA.
> Linux is 4.5 linux with Smartfusion2 SoC dts and clocksource
> driver added by myself @
> https://github.com/Subbaraya-Sundeep/linux.git
>
> Baremetal elfs from Microsemi Softconsole IDE are also working.
>
> Thanks,
> Sundeep
>
> Subbaraya Sundeep (5):
>   msf2: Add Smartfusion2 System timer
>   msf2: Microsemi Smartfusion2 System Register block.
>   msf2: Add Smartfusion2 SPI controller
>   msf2: Add Smartfusion2 SoC.
>   msf2: Add Emcraft's Smartfusion2 SOM kit.
>
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Makefile.objs            |   3 +-
>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++
>  hw/arm/msf2-som.c               |  67 +++++++
>  hw/misc/Makefile.objs           |   1 +
>  hw/misc/msf2-sysreg.c           | 131 ++++++++++++++
>  hw/ssi/Makefile.objs            |   1 +
>  hw/ssi/msf2-spi.c               | 378 ++++++++++++++++++++++++++++++++++++++++
>  hw/timer/Makefile.objs          |   1 +
>  hw/timer/msf2-timer.c           | 252 +++++++++++++++++++++++++++
>  include/hw/arm/msf2-soc.h       |  60 +++++++
>  include/hw/misc/msf2-sysreg.h   |  80 +++++++++
>  include/hw/ssi/msf2-spi.h       | 105 +++++++++++
>  include/hw/timer/msf2-timer.h   |  85 +++++++++
>  14 files changed, 1352 insertions(+), 1 deletion(-)
>  create mode 100644 hw/arm/msf2-soc.c
>  create mode 100644 hw/arm/msf2-som.c
>  create mode 100644 hw/misc/msf2-sysreg.c
>  create mode 100644 hw/ssi/msf2-spi.c
>  create mode 100644 hw/timer/msf2-timer.c
>  create mode 100644 include/hw/arm/msf2-soc.h
>  create mode 100644 include/hw/misc/msf2-sysreg.h
>  create mode 100644 include/hw/ssi/msf2-spi.h
>  create mode 100644 include/hw/timer/msf2-timer.h
>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block.
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block Subbaraya Sundeep
@ 2017-05-10 10:34   ` Philippe Mathieu-Daudé
  2017-05-12  3:48     ` sundeep subbaraya
  0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10 10:34 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm
  Cc: peter.maydell, alistair23, crosthwaite.peter

Hi Subbaraya,

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Added Sytem register block of Smartfusion2.
> This block has PLL registers which are accessed by guest.
>
> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> ---
>  hw/misc/Makefile.objs         |   1 +
>  hw/misc/msf2-sysreg.c         | 131 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/misc/msf2-sysreg.h |  80 ++++++++++++++++++++++++++
>  3 files changed, 212 insertions(+)
>  create mode 100644 hw/misc/msf2-sysreg.c
>  create mode 100644 include/hw/misc/msf2-sysreg.h
>
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index c8b4893..0f52354 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -56,3 +56,4 @@ obj-$(CONFIG_EDU) += edu.o
>  obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
>  obj-$(CONFIG_AUX) += auxbus.o
>  obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
> +obj-$(CONFIG_MSF2) += msf2-sysreg.o
> diff --git a/hw/misc/msf2-sysreg.c b/hw/misc/msf2-sysreg.c
> new file mode 100644
> index 0000000..53e9cba
> --- /dev/null
> +++ b/hw/misc/msf2-sysreg.c
> @@ -0,0 +1,131 @@
> +/*
> + * System Register block model of Microsemi SmartFusion2.
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/misc/msf2-sysreg.h"
> +
> +#ifndef MSF2_SYSREG_ERR_DEBUG
> +#define MSF2_SYSREG_ERR_DEBUG  0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (MSF2_SYSREG_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0);
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
> +
> +static void msf2_sysreg_reset(DeviceState *d)
> +{
> +    MSF2SysregState *s = MSF2_SYSREG(d);
> +
> +    DB_PRINT("RESET\n");
> +
> +    s->regs[MSSDDR_PLL_STATUS_LOW_CR] = 0x02420041;
> +    s->regs[MSSDDR_FACC1_CR] = 0x0A482124;
> +    s->regs[MSSDDR_PLL_STATUS] = 0x3;
> +}
> +
> +static uint64_t msf2_sysreg_read(void *opaque, hwaddr offset,
> +    unsigned size)
> +{
> +    MSF2SysregState *s = opaque;
> +    offset /= 4;
> +    uint32_t ret = 0;
> +
> +    if (offset < ARRAY_SIZE(s->regs)) {
> +        ret = s->regs[offset];
> +        DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx32 "\n",
> +                    offset * 4, ret);
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                    "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
> +                    offset * 4);
> +    }
> +
> +    return ret;
> +}
> +
> +static void msf2_sysreg_write(void *opaque, hwaddr offset,
> +                          uint64_t val, unsigned size)
> +{
> +    MSF2SysregState *s = (MSF2SysregState *)opaque;
> +    offset /= 4;
> +
> +    DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx64 "\n",
> +            offset * 4, val);
> +
> +    switch (offset) {
> +    case MSSDDR_PLL_STATUS:
> +        break;
> +
> +    default:
> +        if (offset < ARRAY_SIZE(s->regs)) {
> +            s->regs[offset] = val;

I think this is pretty unsafe for the guest to continue if those 
registers are accessed in your current implementation.

I'd at least somehow abort for few of them (RESET, REMAP*), what do you 
think?

> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                        "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
> +                        offset * 4);
> +        }
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps sysreg_ops = {
> +    .read = msf2_sysreg_read,
> +    .write = msf2_sysreg_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void msf2_sysreg_init(Object *obj)
> +{
> +    MSF2SysregState *s = MSF2_SYSREG(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &sysreg_ops, s, TYPE_MSF2_SYSREG,
> +                          MSF2_SYSREG_MMIO_SIZE);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
> +}
> +
> +static const VMStateDescription vmstate_msf2_sysreg = {
> +    .name = TYPE_MSF2_SYSREG,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(regs, MSF2SysregState, MSF2_SYSREG_NUM_REGS),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void msf2_sysreg_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_msf2_sysreg;
> +    dc->reset = msf2_sysreg_reset;
> +}
> +
> +static const TypeInfo msf2_sysreg_info = {
> +    .name  = TYPE_MSF2_SYSREG,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .class_init = msf2_sysreg_class_init,
> +    .instance_size  = sizeof(MSF2SysregState),
> +    .instance_init = msf2_sysreg_init,
> +};
> +
> +static void msf2_sysreg_register_types(void)
> +{
> +    type_register_static(&msf2_sysreg_info);
> +}
> +
> +type_init(msf2_sysreg_register_types)
> diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.h
> new file mode 100644
> index 0000000..a485ed6
> --- /dev/null
> +++ b/include/hw/misc/msf2-sysreg.h
> @@ -0,0 +1,80 @@
> +/*
> + * Microsemi SmartFusion2 SYSREG
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_MSF2_SYSREG_H
> +#define HW_MSF2_SYSREG_H
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/log.h"
> +
> +enum {
> +    ESRAM_CR        = 0x00 / 4,
> +    ESRAM_MAX_LAT,
> +    DDR_CR,
> +    ENVM_CR,
> +    ENVM_REMAP_BASE_CR,
> +    ENVM_REMAP_FAB_CR,
> +    CC_CR,
> +    CC_REGION_CR,
> +    CC_LOCK_BASE_ADDR_CR,
> +    CC_FLUSH_INDX_CR,
> +    DDRB_BUF_TIMER_CR,
> +    DDRB_NB_ADDR_CR,
> +    DDRB_NB_SIZE_CR,
> +    DDRB_CR,
> +
> +    SOFT_RESET_CR  = 0x48 / 4,
> +    M3_CR,
> +
> +    GPIO_SYSRESET_SEL_CR = 0x58 / 4,
> +
> +    MDDR_CR = 0x60 / 4,
> +
> +    MSSDDR_PLL_STATUS_LOW_CR = 0x90 / 4,
> +    MSSDDR_PLL_STATUS_HIGH_CR,
> +    MSSDDR_FACC1_CR,
> +    MSSDDR_FACC2_CR,
> +
> +    MSSDDR_PLL_STATUS = 0x150 / 4,
> +
> +};
> +
> +#define MSF2_SYSREG_MMIO_SIZE     0x300
> +#define MSF2_SYSREG_NUM_REGS      (MSF2_SYSREG_MMIO_SIZE / 4)
> +
> +#define TYPE_MSF2_SYSREG          "msf2-sysreg"
> +#define MSF2_SYSREG(obj)  OBJECT_CHECK(MSF2SysregState, (obj), TYPE_MSF2_SYSREG)
> +
> +typedef struct MSF2SysregState {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion iomem;
> +
> +    uint32_t regs[MSF2_SYSREG_NUM_REGS];
> +} MSF2SysregState;
> +
> +#endif /* HW_MSF2_SYSREG_H */
>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit.
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit Subbaraya Sundeep
@ 2017-05-10 11:16   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10 11:16 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm
  Cc: peter.maydell, alistair23, crosthwaite.peter

Hi Subbaraya,

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Emulated Emcraft's Smartfusion2 System On Module starter
> kit.
>
> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> ---
>  hw/arm/Makefile.objs |  1 +
>  hw/arm/msf2-som.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 68 insertions(+)
>  create mode 100644 hw/arm/msf2-som.c
>
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index ae5e4a3..b626a43 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -5,6 +5,7 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
>  obj-y += netduino2.o
> +obj-y += msf2-som.o
>  obj-y += sysbus-fdt.o
>
>  obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
> diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
> new file mode 100644
> index 0000000..bc44169
> --- /dev/null
> +++ b/hw/arm/msf2-som.c
> @@ -0,0 +1,67 @@
> +/*
> + * SmartFusion2 SOM starter kit(from Emcraft) emulation.
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/boards.h"
> +#include "hw/arm/msf2-soc.h"
> +#include "hw/arm/arm.h"
> +
> +static void msf2_init(MachineState *machine)
> +{
> +    DeviceState *dev;
> +    DeviceState *spi_flash;
> +    MSF2State *soc;
> +    DriveInfo *dinfo = drive_get_next(IF_MTD);
> +    qemu_irq cs_line;
> +    SSIBus *spi_bus;
> +
> +    dev = qdev_create(NULL, TYPE_MSF2_SOC);
> +    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> +
> +    soc = MSF2_SOC(dev);
> +
> +    /* Attach SPI flash to SPI0 controller */
> +    spi_bus = (SSIBus *)qdev_get_child_bus(dev, "spi0");
> +    spi_flash = ssi_create_slave_no_init(spi_bus, "s25sl12801");
> +    qdev_prop_set_uint8(spi_flash, "spansion-cr2nv", 1);
> +    if (dinfo) {
> +        qdev_prop_set_drive(spi_flash, "drive", blk_by_legacy_dinfo(dinfo),
> +                                    &error_fatal);
> +    }
> +    qdev_init_nofail(spi_flash);
> +    cs_line = qdev_get_gpio_in_named(spi_flash, SSI_GPIO_CS, 0);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
> +
> +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> +                       ENVM_SIZE);
> +}
> +
> +static void msf2_machine_init(MachineClass *mc)
> +{
> +    mc->desc = "SmartFusion2 SOM kit from Emcraft";
> +    mc->init = msf2_init;
> +}
> +
> +DEFINE_MACHINE("smartfusion2-som", msf2_machine_init)

This is not the only SoM existing using a SF2, what about beeing more 
specific, like "emcraft-sf2"?
Likewise I'd rename the functions with a pattern such 'emcraft_sf2_*()' 
although the filename is correct.

Regards,

Phil.

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

* Re: [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC Subbaraya Sundeep
@ 2017-05-10 11:50   ` Philippe Mathieu-Daudé
  2017-05-12  3:17     ` sundeep subbaraya
  0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10 11:50 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm
  Cc: peter.maydell, alistair23, crosthwaite.peter

Hi Subbaraya,

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Smartfusion2 SoC has hardened Microcontroller subsystem
> and flash based FPGA fabric. This patch adds support for
> Microcontroller subsystem in the SoC.
>
> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> ---
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Makefile.objs            |   2 +-
>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/arm/msf2-soc.h       |  60 +++++++++++++
>  4 files changed, 250 insertions(+), 1 deletion(-)
>  create mode 100644 hw/arm/msf2-soc.c
>  create mode 100644 include/hw/arm/msf2-soc.h
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 78d7af0..7062512 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -122,3 +122,4 @@ CONFIG_ACPI=y
>  CONFIG_SMBIOS=y
>  CONFIG_ASPEED_SOC=y
>  CONFIG_GPIO_KEY=y
> +CONFIG_MSF2=y
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index 4c5c4ee..ae5e4a3 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -1,7 +1,7 @@
>  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
>  obj-$(CONFIG_DIGIC) += digic_boards.o
>  obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
> -obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
> +obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o

Not a big deal, but since you added CONFIG_MSF2 why not using it here 
and the Makefiles you touched (misc/ssi/timer)?

obj-$(CONFIG_MSF2) += msf2-soc.o

>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
>  obj-y += netduino2.o
> diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
> new file mode 100644
> index 0000000..d6341a2
> --- /dev/null
> +++ b/hw/arm/msf2-soc.c
> @@ -0,0 +1,188 @@
> +/*
> + * SmartFusion2 SoC emulation.
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "hw/arm/arm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/char/serial.h"
> +#include "hw/boards.h"
> +#include "sysemu/block-backend.h"
> +#include "hw/arm/msf2-soc.h"
> +
> +#define MSF2_TIMER_BASE       0x40004000
> +#define MSF2_SYSREG_BASE      0x40038000
> +
> +#define MSF2_TIMER_IRQ0       14
> +#define MSF2_TIMER_IRQ1       15
> +
> +static const uint32_t spi_addr[MSF2_NUM_SPIS] = { 0x40001000 , 0x40011000 };
> +static const uint32_t uart_addr[MSF2_NUM_UARTS] = { 0x40000000 , 0x40010000 };
> +
> +static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 };
> +static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 };
> +
> +static void msf2_soc_initfn(Object *obj)
> +{
> +    MSF2State *s = MSF2_SOC(obj);
> +    int i;
> +
> +    object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
> +    qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
> +
> +    object_initialize(&s->sysreg, sizeof(s->sysreg), TYPE_MSF2_SYSREG);
> +    qdev_set_parent_bus(DEVICE(&s->sysreg), sysbus_get_default());
> +
> +    object_initialize(&s->timer, sizeof(s->timer), TYPE_MSF2_TIMER);
> +    qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default());
> +
> +    for (i = 0; i < MSF2_NUM_SPIS; i++) {
> +        object_initialize(&s->spi[i], sizeof(s->spi[i]),
> +                          TYPE_MSF2_SPI);
> +        qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
> +    }
> +}
> +
> +static void msf2_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    MSF2State *s = MSF2_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *nvm = g_new(MemoryRegion, 1);
> +    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *ddr = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
> +                           &error_fatal);

Maybe you can name it "eNVM" to match the documentation.

Also envm_size should be a per-model property.

> +    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
> +                             nvm, 0, ENVM_SIZE);

Hmmm well this would be the "Cache Matrix Remap" which happens to be 
mapped by default to eNVM on cold reset.
Naming it "MSF2.flash.alias" is pretty confusing.

> +    vmstate_register_ram_global(nvm);
> +
> +    memory_region_set_readonly(nvm, true);
> +    memory_region_set_readonly(nvm_alias, true);
> +
> +    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
> +    memory_region_add_subregion(system_memory, 0, nvm_alias);
> +
> +    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
> +                           &error_fatal);

Wrong, there is no DDR on this SoC.

> +    vmstate_register_ram_global(ddr);
> +    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS, ddr);
> +
> +    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
> +                           &error_fatal);

I'd rather like to see it named "eSRAM" somehow, so there is no 
confusion possible with external SRAM a SoM/board can map at 0x60000000.

Same comment than envm_size, sram_size should be a per-model property.

> +    vmstate_register_ram_global(sram);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);

Can you point me to your datasheet? I thought the SF2 had 240 IRQs.

> +    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> +                                     "memory", &error_abort);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    for (i = 0; i < MSF2_NUM_UARTS; i++) {
> +        if (serial_hds[i]) {
> +            serial_mm_init(get_system_memory(), uart_addr[i], 2,
> +                           qdev_get_gpio_in(armv7m, uart_irq[i]),
> +                           115200, serial_hds[i], DEVICE_NATIVE_ENDIAN);
> +        }
> +    }
> +
> +    dev = DEVICE(&s->timer);
> +    qdev_prop_set_uint32(dev, "clock-frequency", MSF2_TIMER_FREQ);
> +    object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, MSF2_TIMER_BASE);
> +    sysbus_connect_irq(busdev, 0,
> +                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ0));
> +    sysbus_connect_irq(busdev, 1,
> +                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ1));
> +
> +    dev = DEVICE(&s->sysreg);
> +    object_property_set_bool(OBJECT(&s->sysreg), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, MSF2_SYSREG_BASE);
> +
> +    for (i = 0; i < MSF2_NUM_SPIS; i++) {
> +        gchar *bus_name = g_strdup_printf("spi%d", i);
> +
> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            g_free(bus_name);
> +            error_propagate(errp, err);
> +            return;
> +        }
> +
> +        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_addr[i]);
> +        sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
> +                           qdev_get_gpio_in(armv7m, spi_irq[i]));
> +
> +        /* Alias controller SPI bus to the SoC itself */
> +        object_property_add_alias(OBJECT(s), bus_name,
> +                                  OBJECT(&s->spi[i]), "spi0",
> +                                  &error_abort);
> +        g_free(bus_name);
> +    }
> +}
> +
> +static void msf2_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = msf2_soc_realize;
> +}
> +
> +static const TypeInfo msf2_soc_info = {
> +    .name          = TYPE_MSF2_SOC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(MSF2State),
> +    .instance_init = msf2_soc_initfn,
> +    .class_init    = msf2_soc_class_init,
> +};
> +
> +static void msf2_soc_types(void)
> +{
> +    type_register_static(&msf2_soc_info);
> +}
> +
> +type_init(msf2_soc_types)
> diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
> new file mode 100644
> index 0000000..29a8ff8
> --- /dev/null
> +++ b/include/hw/arm/msf2-soc.h
> @@ -0,0 +1,60 @@
> +/*
> + * Microsemi Smartfusion2 SoC
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_ARM_MSF2_SOC_H
> +#define HW_ARM_MSF2_SOC_H
> +
> +#include "hw/misc/msf2-sysreg.h"
> +#include "hw/timer/msf2-timer.h"
> +#include "hw/ssi/msf2-spi.h"
> +#include "hw/arm/armv7m.h"
> +
> +#define TYPE_MSF2_SOC     "msf2-soc"
> +#define MSF2_SOC(obj)     OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
> +
> +#define MSF2_NUM_SPIS         2
> +#define MSF2_NUM_UARTS        2
> +
> +#define ENVM_BASE_ADDRESS     0x60000000
> +#define ENVM_SIZE             (128 * 1024)

The SoC design ENVM_SIZE is 1MB, 128K seems your particular model.

> +
> +#define DDR_BASE_ADDRESS      0xA0000000
> +#define DDR_SIZE              (64 * 1024 * 1024)

This belongs to the SoM.

> +
> +#define SRAM_BASE_ADDRESS     0x20000000
> +#define SRAM_SIZE             (64 * 1024)

Indeed this SoC is designed to have up to 64K of SRAM.
Luckily your model provides 64K.

> +
> +typedef struct MSF2State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    ARMv7MState armv7m;
> +
> +    MSF2SysregState sysreg;
> +    MSF2TimerState timer;
> +    MSF2SpiState spi[MSF2_NUM_SPIS];
> +} MSF2State;
> +
> +#endif
>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller
  2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller Subbaraya Sundeep
@ 2017-05-10 12:12   ` Philippe Mathieu-Daudé
  2017-05-12  3:31     ` sundeep subbaraya
  0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-10 12:12 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm
  Cc: peter.maydell, alistair23, crosthwaite.peter

Hi Subbaraya,

Like my comment for the timer model, I'd name this model "mss_spi".
The only difference I see in the SF2 is the STAT8 register.
No need to register both devices now but maybe you can add a comment 
about it?

On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> Modelled Microsemi's Smartfusion2 SPI controller.
>
> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> ---
>  hw/ssi/Makefile.objs      |   1 +
>  hw/ssi/msf2-spi.c         | 378 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/ssi/msf2-spi.h | 105 +++++++++++++
>  3 files changed, 484 insertions(+)
>  create mode 100644 hw/ssi/msf2-spi.c
>  create mode 100644 include/hw/ssi/msf2-spi.h
>
> diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
> index 487add2..3105c4b 100644
> --- a/hw/ssi/Makefile.objs
> +++ b/hw/ssi/Makefile.objs
> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
>  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
>  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
> +common-obj-$(CONFIG_MSF2) += msf2-spi.o

Not a big deal but his define only appears after applying the next patch.

>
>  obj-$(CONFIG_OMAP) += omap_spi.o
>  obj-$(CONFIG_IMX) += imx_spi.o
> diff --git a/hw/ssi/msf2-spi.c b/hw/ssi/msf2-spi.c
> new file mode 100644
> index 0000000..2059ed9
> --- /dev/null
> +++ b/hw/ssi/msf2-spi.c
> @@ -0,0 +1,378 @@
> +/*
> + * SPI controller model of Microsemi SmartFusion2.
> + *
> + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "hw/ssi/msf2-spi.h"
> +
> +#ifndef MSF2_SPI_ERR_DEBUG
> +#define MSF2_SPI_ERR_DEBUG   0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (MSF2_SPI_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0);
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
> +
> +static void txfifo_reset(MSF2SpiState *s)
> +{
> +    fifo32_reset(&s->tx_fifo);
> +
> +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;
> +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;
> +}
> +
> +static void rxfifo_reset(MSF2SpiState *s)
> +{
> +    fifo32_reset(&s->rx_fifo);
> +
> +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
> +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
> +}
> +
> +static void set_fifodepth(MSF2SpiState *s)
> +{
> +    int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;
> +
> +    if (0 <= size && size <= 8) {
> +        s->fifo_depth = 32;
> +    }
> +    if (9 <= size && size <= 16) {
> +        s->fifo_depth = 16;
> +    }
> +    if (17 <= size && size <= 32) {
> +        s->fifo_depth = 8;
> +    }
> +}
> +
> +static void msf2_spi_do_reset(MSF2SpiState *s)
> +{
> +    memset(s->regs, 0, sizeof s->regs);
> +    s->regs[R_SPI_CONTROL] = 0x80000102;
> +    s->regs[R_SPI_DFSIZE] = 0x4;
> +    s->regs[R_SPI_STATUS] = 0x2440;
> +    s->regs[R_SPI_CLKGEN] = 0x7;
> +    s->regs[R_SPI_STAT8] = 0x7;
> +    s->regs[R_SPI_RIS] = 0x0;
> +
> +    s->fifo_depth = 4;
> +    s->frame_count = 1;
> +    s->enabled = false;
> +
> +    rxfifo_reset(s);
> +    txfifo_reset(s);
> +}
> +
> +static void update_mis(MSF2SpiState *s)
> +{
> +    uint32_t reg = s->regs[R_SPI_CONTROL];
> +    uint32_t tmp;
> +
> +    /*
> +     * form the Control register interrupt enable bits
> +     * same as RIS, MIS and Interrupt clear registers for simplicity
> +     */
> +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |
> +           ((reg & C_INTTXDATA) >> 5);
> +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];
> +}
> +
> +static void spi_update_irq(MSF2SpiState *s)
> +{
> +    int irq;
> +
> +    update_mis(s);
> +    irq = !!(s->regs[R_SPI_MIS]);
> +
> +    qemu_set_irq(s->irq, irq);
> +}
> +
> +static void msf2_spi_reset(DeviceState *d)
> +{
> +    msf2_spi_do_reset(MSF2_SPI(d));
> +}
> +
> +static uint64_t
> +spi_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> +    MSF2SpiState *s = opaque;
> +    uint32_t ret = 0;
> +
> +    addr >>= 2;
> +    switch (addr) {
> +    case R_SPI_RX:
> +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
> +        s->regs[R_SPI_STATUS] &= ~RXCHOVRF;
> +        ret = fifo32_pop(&s->rx_fifo);
> +        if (fifo32_is_empty(&s->rx_fifo)) {
> +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
> +        }
> +        break;
> +
> +    case R_SPI_MIS:
> +        update_mis(s);
> +        ret = s->regs[R_SPI_MIS];
> +        break;
> +
> +    default:
> +        if (addr < ARRAY_SIZE(s->regs)) {
> +            ret = s->regs[addr];
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
> +                         addr * 4);

Drop '\n' while calling qemu_log_mask().

> +        }
> +        break;
> +    }
> +
> +    DB_PRINT("addr=0x%" HWADDR_PRIx " = 0x%" PRIx32 "\n", addr * 4, ret);
> +    spi_update_irq(s);
> +    return ret;
> +}
> +
> +static void assert_cs(MSF2SpiState *s)
> +{
> +    qemu_set_irq(s->cs_line, 0);
> +}
> +
> +static void deassert_cs(MSF2SpiState *s)
> +{
> +    qemu_set_irq(s->cs_line, 1);
> +}
> +
> +static void spi_flush_txfifo(MSF2SpiState *s)
> +{
> +    uint32_t tx;
> +    uint32_t rx;
> +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);
> +
> +    /*
> +     * Chip Select(CS) is automatically controlled by this controller.
> +     * If SPS bit is set in Control register then CS is asserted
> +     * until all the frames set in frame count of Control register are
> +     * transferred. If SPS is not set then CS pulses between frames.
> +     * Note that Slave Select register specifies which of the CS line
> +     * has to be controlled automatically by controller. Bits SS[7:1] are for
> +     * masters in FPGA fabric since we model only Microcontroller subsystem
> +     * of Smartfusion2 we control only one CS(SS[0]) line.
> +     */
> +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {
> +        assert_cs(s);
> +
> +        s->regs[R_SPI_STATUS] &= ~TXDONE;
> +        s->regs[R_SPI_STATUS] &= ~RXRDY;
> +
> +        tx = fifo32_pop(&s->tx_fifo);
> +        DB_PRINT("data tx:0x%" PRIx32 "\n", tx);
> +        rx = ssi_transfer(s->spi, tx);
> +        DB_PRINT("data rx:0x%" PRIx32 "\n", rx);
> +
> +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
> +            s->regs[R_SPI_STATUS] |= RXCHOVRF;
> +            s->regs[R_SPI_RIS] |= RXCHOVRF;
> +        } else {
> +            fifo32_push(&s->rx_fifo, rx);
> +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;
> +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {
> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;
> +            }
> +            if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;
> +            }
> +        }
> +        s->frame_count--;
> +        if (!sps) {
> +            deassert_cs(s);
> +            assert_cs(s);
> +        }
> +    }
> +
> +    if (!sps) {
> +        deassert_cs(s);
> +    }
> +
> +    if (!s->frame_count) {
> +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>
> +                            FMCOUNT_SHIFT;
> +        if (sps) {
> +            deassert_cs(s);
> +        }
> +        s->regs[R_SPI_RIS] |= TXDONE;
> +        s->regs[R_SPI_RIS] |= RXRDY;
> +        s->regs[R_SPI_STATUS] |= TXDONE;
> +        s->regs[R_SPI_STATUS] |= RXRDY;
> +   }
> +}
> +
> +static void spi_write(void *opaque, hwaddr addr,
> +            uint64_t val64, unsigned int size)
> +{
> +    MSF2SpiState *s = opaque;
> +    uint32_t value = val64;
> +
> +    DB_PRINT("addr=0x%" HWADDR_PRIx " =0x%" PRIx32 "\n", addr, value);
> +    addr >>= 2;
> +
> +    switch (addr) {
> +    case R_SPI_TX:
> +        /* adding to already full FIFO */
> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
> +            break;
> +        }
> +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;
> +        fifo32_push(&s->tx_fifo, value);
> +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {
> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;
> +        }
> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;
> +        }
> +        if (s->enabled) {
> +            spi_flush_txfifo(s);
> +        }
> +        break;
> +
> +    case R_SPI_CONTROL:
> +        s->regs[R_SPI_CONTROL] = value;
> +        if (value & C_BIGFIFO) {
> +            set_fifodepth(s);
> +        } else {
> +            s->fifo_depth = 4;
> +        }
> +        if (value & C_ENABLE) {
> +            s->enabled = true;
> +        } else {
> +            s->enabled = false;
> +        }
> +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;
> +        if (value & C_RESET) {
> +            msf2_spi_do_reset(s);
> +        }
> +        break;
> +
> +    case R_SPI_DFSIZE:
> +        if (s->enabled) {
> +            break;
> +        }
> +        s->regs[R_SPI_DFSIZE] = value;
> +        break;
> +
> +    case R_SPI_INTCLR:
> +        s->regs[R_SPI_INTCLR] = value;
> +        if (value & TXDONE) {
> +            s->regs[R_SPI_RIS] &= ~TXDONE;
> +        }
> +        if (value & RXRDY) {
> +            s->regs[R_SPI_RIS] &= ~RXRDY;
> +        }
> +        if (value & RXCHOVRF) {
> +            s->regs[R_SPI_RIS] &= ~RXCHOVRF;
> +        }
> +        break;
> +
> +    case R_SPI_MIS:
> +    case R_SPI_STATUS:
> +    case R_SPI_RIS:
> +        break;
> +
> +    default:
> +        if (addr < ARRAY_SIZE(s->regs)) {
> +            s->regs[addr] = value;
> +        } else {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
> +                         addr * 4);
> +        }
> +        break;
> +    }
> +
> +    spi_update_irq(s);
> +}
> +
> +static const MemoryRegionOps spi_ops = {
> +    .read = spi_read,
> +    .write = spi_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4
> +    }
> +};
> +
> +static void msf2_spi_realize(DeviceState *dev, Error **errp)
> +{
> +    MSF2SpiState *s = MSF2_SPI(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> +    DB_PRINT("\n");
> +
> +    s->spi = ssi_create_bus(dev, "spi0");
> +
> +    sysbus_init_irq(sbd, &s->irq);
> +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);
> +    sysbus_init_irq(sbd, &s->cs_line);
> +
> +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
> +                          TYPE_MSF2_SPI, R_SPI_MAX * 4);
> +    sysbus_init_mmio(sbd, &s->mmio);
> +
> +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);
> +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);
> +}
> +
> +static const VMStateDescription vmstate_msf2_spi = {
> +    .name = TYPE_MSF2_SPI,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_FIFO32(tx_fifo, MSF2SpiState),
> +        VMSTATE_FIFO32(rx_fifo, MSF2SpiState),
> +        VMSTATE_UINT32_ARRAY(regs, MSF2SpiState, R_SPI_MAX),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void msf2_spi_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = msf2_spi_realize;
> +    dc->reset = msf2_spi_reset;
> +    dc->vmsd = &vmstate_msf2_spi;
> +}
> +
> +static const TypeInfo msf2_spi_info = {
> +    .name           = TYPE_MSF2_SPI,
> +    .parent         = TYPE_SYS_BUS_DEVICE,
> +    .instance_size  = sizeof(MSF2SpiState),
> +    .class_init     = msf2_spi_class_init,
> +};
> +
> +static void msf2_spi_register_types(void)
> +{
> +    type_register_static(&msf2_spi_info);
> +}
> +
> +type_init(msf2_spi_register_types)
> diff --git a/include/hw/ssi/msf2-spi.h b/include/hw/ssi/msf2-spi.h
> new file mode 100644
> index 0000000..585edde
> --- /dev/null
> +++ b/include/hw/ssi/msf2-spi.h
> @@ -0,0 +1,105 @@
> +/*
> + * Microsemi SmartFusion2 SPI
> + *
> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_MSF2_SPI_H
> +#define HW_MSF2_SPI_H
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +#include "hw/ssi/ssi.h"
> +#include "qemu/fifo32.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/log.h"
> +
> +#define FIFO_CAPACITY     32
> +#define FIFO_CAPACITY     32
> +
> +#define R_SPI_CONTROL         0
> +#define R_SPI_DFSIZE          1
> +#define R_SPI_STATUS          2
> +#define R_SPI_INTCLR          3
> +#define R_SPI_RX              4
> +#define R_SPI_TX              5
> +#define R_SPI_CLKGEN          6
> +#define R_SPI_SS              7
> +#define R_SPI_MIS             8
> +#define R_SPI_RIS             9
> +#define R_SPI_STAT8           15
> +#define R_SPI_MAX             16
> +
> +#define S_RXFIFOFUL       (1 << 4)
> +#define S_RXFIFOFULNXT    (1 << 5)
> +#define S_RXFIFOEMP       (1 << 6)
> +#define S_RXFIFOEMPNXT    (1 << 7)
> +#define S_TXFIFOFUL       (1 << 8)
> +#define S_TXFIFOFULNXT    (1 << 9)
> +#define S_TXFIFOEMP       (1 << 10)
> +#define S_TXFIFOEMPNXT    (1 << 11)
> +#define S_FRAMESTART      (1 << 12)
> +#define S_SSEL            (1 << 13)
> +#define S_ACTIVE          (1 << 14)
> +
> +#define C_ENABLE          (1 << 0)
> +#define C_MODE            (1 << 1)
> +#define C_INTRXDATA       (1 << 4)
> +#define C_INTTXDATA       (1 << 5)
> +#define C_INTRXOVRFLO     (1 << 6)
> +#define C_SPS             (1 << 26)
> +#define C_BIGFIFO         (1 << 29)
> +#define C_RESET           (1 << 31)
> +
> +#define FRAMESZ_MASK      0x1F
> +#define FMCOUNT_MASK      0x00FFFF00
> +#define FMCOUNT_SHIFT     8
> +
> +#define TXDONE            (1 << 0)
> +#define RXRDY             (1 << 1)
> +#define RXCHOVRF          (1 << 2)
> +
> +#define TYPE_MSF2_SPI   "msf2-spi"
> +#define MSF2_SPI(obj)   OBJECT_CHECK(MSF2SpiState, (obj), TYPE_MSF2_SPI)
> +
> +typedef struct MSF2SpiState {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion mmio;
> +
> +    qemu_irq irq;
> +
> +    qemu_irq cs_line;
> +
> +    SSIBus *spi;
> +
> +    Fifo32 rx_fifo;
> +    Fifo32 tx_fifo;
> +
> +    int fifo_depth;
> +    uint32_t frame_count;
> +    bool enabled;
> +
> +    uint32_t regs[R_SPI_MAX];
> +} MSF2SpiState;
> +
> +#endif /* HW_MSF2_SPI_H */
>

Regards,

Phil.

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-10  9:41   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
@ 2017-05-10 12:37     ` sundeep subbaraya
  2017-05-12  4:38       ` Philippe Mathieu-Daudé
  2017-05-15 11:52     ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-10 12:37 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis

Hi Phil,

On Wed, May 10, 2017 at 3:11 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:
> Hi Subbaraya, nice work!
>
> The timer you are modeling is the mss_timer, which is in particular used
in
> the smartfusion2, I'd rather name it mss_timer.c so it can be reused by
> other SoC models.
>
Ok I will change all other file names also to mss. Do I need to change type
names
also to mss?

> I added few comments.
>
>
> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>
>> Modelled System Timer in Microsemi's Smartfusion2 Soc.
>> Timer has two 32bit down counters and two interrupts.
>>
>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> ---
>>  hw/timer/Makefile.objs        |   1 +
>>  hw/timer/msf2-timer.c         | 252
>> ++++++++++++++++++++++++++++++++++++++++++
>>  include/hw/timer/msf2-timer.h |  85 ++++++++++++++
>>  3 files changed, 338 insertions(+)
>>  create mode 100644 hw/timer/msf2-timer.c
>>  create mode 100644 include/hw/timer/msf2-timer.h
>>
>> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
>> index dd6f27e..bd1ff15 100644
>> --- a/hw/timer/Makefile.objs
>> +++ b/hw/timer/Makefile.objs
>> @@ -41,3 +41,4 @@ common-obj-$(CONFIG_STM32F2XX_TIMER) +=
>> stm32f2xx_timer.o
>>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
>>
>>  common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
>> +common-obj-$(CONFIG_MSF2) += msf2-timer.o
>> diff --git a/hw/timer/msf2-timer.c b/hw/timer/msf2-timer.c
>> new file mode 100644
>> index 0000000..466faa6
>> --- /dev/null
>> +++ b/hw/timer/msf2-timer.c
>> @@ -0,0 +1,252 @@
>> +/*
>> + * Timer block model of Microsemi SmartFusion2.
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS
>> IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#include "hw/timer/msf2-timer.h"
>> +
>> +#ifndef MSF2_TIMER_ERR_DEBUG
>> +#define MSF2_TIMER_ERR_DEBUG  0
>> +#endif
>> +
>> +#define DB_PRINT_L(lvl, fmt, args...) do { \
>> +    if (MSF2_TIMER_ERR_DEBUG >= lvl) { \
>> +        qemu_log("%s: " fmt, __func__, ## args); \
>> +    } \
>> +} while (0);
>> +
>> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>> +
>> +static void timer_update_irq(struct Msf2Timer *st)
>> +{
>> +    bool isr, ier;
>> +
>> +    isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
>> +    ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
>> +
>> +    qemu_set_irq(st->irq, (ier && isr));
>> +}
>> +
>> +static void timer_update(struct Msf2Timer *st)
>> +{
>> +    uint64_t count;
>> +
>> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL)) {
>> +        ptimer_stop(st->ptimer);
>> +        return;
>> +    }
>> +
>> +    count = st->regs[R_TIM_LOADVAL];
>> +    ptimer_set_limit(st->ptimer, count, 1);
>> +    ptimer_run(st->ptimer, 1);
>> +}
>> +
>> +static uint64_t
>> +timer_read(void *opaque, hwaddr addr, unsigned int size)
>> +{
>> +    MSF2TimerState *t = opaque;
>> +    struct Msf2Timer *st;
>> +    uint32_t ret = 0;
>> +    int timer = 0;
>> +    int isr;
>> +    int ier;
>> +
>> +    addr >>= 2;
>> +    /*
>> +     * Two independent timers has same base address.
>> +     * Based on addr passed figure out which timer is being used.
>> +     */
>> +    if (addr >= R_TIM1_MAX) {
>> +        timer = 1;
>> +        addr -= R_TIM1_MAX;
>> +    }
>> +
>> +    st = &t->timers[timer];
>> +
>> +    switch (addr) {
>> +    case R_TIM_VAL:
>> +        ret = ptimer_get_count(st->ptimer);
>> +        break;
>> +
>> +    case R_TIM_MIS:
>> +        isr = !!(st->regs[R_TIM_RIS] & TIMER_RIS_ACK);
>> +        ier = !!(st->regs[R_TIM_CTRL] & TIMER_CTRL_INTR);
>> +        ret = ier & isr;
>> +        break;
>> +
>> +    default:
>> +        if (addr < ARRAY_SIZE(st->regs)) {
>> +            ret = st->regs[addr];
>> +        } else {
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__,
>> +                         addr * 4);
>> +        }
>> +        break;
>> +    }
>> +
>> +    DB_PRINT("timer=%d 0x%" HWADDR_PRIx "=0x%" PRIx32 "\n", timer, addr
*
>> 4,
>> +            ret);
>> +    return ret;
>> +}
>> +
>> +static void
>> +timer_write(void *opaque, hwaddr addr,
>> +            uint64_t val64, unsigned int size)
>> +{
>> +    MSF2TimerState *t = opaque;
>> +    struct Msf2Timer *st;
>> +    int timer = 0;
>> +    uint32_t value = val64;
>> +
>> +    addr >>= 2;
>> +    /*
>> +     * Two independent timers has same base address.
>> +     * Based on addr passed figure out which timer is being used.
>> +     */
>> +    if (addr >= R_TIM1_MAX) {
>> +        timer = 1;
>> +        addr -= R_TIM1_MAX;
>
>
> This is only valid if addr < (NUM_TIMERS * R_TIM1_MAX).
>
>
Yes you are right. My intention was to treat any address greater than
R_TIM1_MAX as timer 2 and below default case in switch would take care of
addresses which are greater than 2 *  R_TIM1_MAX. As you mentioned there
is problem with 12..20. If guest sends more than 20 say 24 then 24 - 6 = 18
which will be treated as valid but it is not. Thanks for pointing it.

>> +    }
>> +
>> +    st = &t->timers[timer];
>> +
>> +    DB_PRINT("addr=0x%" HWADDR_PRIx " val=0x%" PRIx32 " (timer=%d)\n",
>> addr * 4,
>> +            value, timer);
>> +
>> +    switch (addr) {
>> +    case R_TIM_CTRL:
>> +        st->regs[R_TIM_CTRL] = value;
>> +        timer_update(st);
>> +        break;
>> +
>> +    case R_TIM_RIS:
>> +        if (value & TIMER_RIS_ACK) {
>> +            st->regs[R_TIM_RIS] &= ~TIMER_RIS_ACK;
>> +        }
>> +        break;
>> +
>> +    case R_TIM_LOADVAL:
>> +        st->regs[R_TIM_LOADVAL] = value;
>> +        if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
>> +            timer_update(st);
>> +        }
>> +        break;
>> +
>> +    case R_TIM_BGLOADVAL:
>> +        st->regs[R_TIM_BGLOADVAL] = value;
>> +        st->regs[R_TIM_LOADVAL] = value;
>> +        break;
>> +
>> +    case R_TIM_VAL:
>> +    case R_TIM_MIS:
>> +        break;
>> +
>> +    case R_TIM_MODE:
>
>
> This case is never reached, if the guest wanted to access register 21,
since
> 21 >= R_TIM1_MAX you have now addr = 21 - R_TIM1_MAX = 15.
>
Yes. I overlooked it. Will change it.

>> +        if (value & TIMER_MODE) {
>> +            qemu_log_mask(LOG_UNIMP, "64-bit mode not supported\n");
>
>
> No need of trailing '\n', be more specific, something like:
>
>     qemu_log_mask(LOG_UNIMP, TYPE_MSF2_TIMER ": 64-bit mode not
supported");
>
Ok. Will change it.
>> +        }
>> +        break;
>> +
>> +    default:
>
>
> Once the issue "addr -= R_TIM1_MAX" is fixed, this default will catch
> registers 12 .. 20 silently while there are unimplemented!
> I'd rather catch them altogether and log some "64-bit mode not supported".
>
Ok. I will change it.

>> +        if (addr < ARRAY_SIZE(st->regs)) {
>> +            st->regs[addr] = value;
>> +        } else {
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__,
>> +                         addr * 4);
>> +        }
>> +        break;
>> +    }
>> +    timer_update_irq(st);
>
>
> Here if addr >= (NUM_TIMERS * R_TIM1_MAX) you still update Timer1 IRQ,
while
> this is unharmful right now this is likely to be break later.
>
As long as Interrupt status register and Interrupt enable register are not
modified calling timer_update_irq will not harm. Am I missing something
here?
>> +}
>> +
>> +static const MemoryRegionOps timer_ops = {
>> +    .read = timer_read,
>> +    .write = timer_write,
>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>> +    .valid = {
>> +        .min_access_size = 4,
>
>
> I believe min_access_size = 1 is valid for any APB device.
>
>
Ok. I followed Xilinx soft IP models while writing this. I am really not
sure it is mandatory to put access_size. Can i remove it?

>> +        .max_access_size = 4
>> +    }
>> +};
>> +
>> +static void timer_hit(void *opaque)
>> +{
>> +    struct Msf2Timer *st = opaque;
>> +
>> +    st->regs[R_TIM_RIS] |= TIMER_RIS_ACK;
>> +
>> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ONESHOT)) {
>> +        timer_update(st);
>> +    }
>> +    timer_update_irq(st);
>> +}
>> +
>> +static void msf2_timer_init(Object *obj)
>> +{
>> +    MSF2TimerState *t = MSF2_TIMER(obj);
>> +    int i;
>> +
>> +    /* Init all the ptimers.  */
>> +    t->timers = g_malloc0((sizeof t->timers[0]) * NUM_TIMERS);
>> +    for (i = 0; i < NUM_TIMERS; i++) {
>> +        struct Msf2Timer *st = &t->timers[i];
>> +
>> +        st->bh = qemu_bh_new(timer_hit, st);
>> +        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
>> +        ptimer_set_freq(st->ptimer, t->freq_hz);
>> +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
>> +    }
>> +
>> +    memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
>> TYPE_MSF2_TIMER,
>> +                          R_TIM_MAX * 4);
>> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &t->mmio);
>> +}
>> +
>> +static Property msf2_timer_properties[] = {
>> +    DEFINE_PROP_UINT32("clock-frequency", MSF2TimerState, freq_hz,
>> +                       MSF2_TIMER_FREQ),
>> +    DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void msf2_timer_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->props = msf2_timer_properties;
>> +}
>> +
>> +static const TypeInfo msf2_timer_info = {
>> +    .name          = TYPE_MSF2_TIMER,
>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size = sizeof(MSF2TimerState),
>> +    .instance_init = msf2_timer_init,
>> +    .class_init    = msf2_timer_class_init,
>> +};
>> +
>> +static void msf2_timer_register_types(void)
>> +{
>> +    type_register_static(&msf2_timer_info);
>> +}
>> +
>> +type_init(msf2_timer_register_types)
>> diff --git a/include/hw/timer/msf2-timer.h
b/include/hw/timer/msf2-timer.h
>> new file mode 100644
>> index 0000000..10eb2f8
>> --- /dev/null
>> +++ b/include/hw/timer/msf2-timer.h
>> @@ -0,0 +1,85 @@
>> +/*
>> + * Microsemi SmartFusion2 Timer.
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS
>> IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#ifndef HW_MSF2_TIMER_H
>> +#define HW_MSF2_TIMER_H
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/ptimer.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/log.h"
>> +
>> +#define TYPE_MSF2_TIMER     "msf2-timer"
>> +#define MSF2_TIMER(obj)     OBJECT_CHECK(MSF2TimerState, \
>> +                              (obj), TYPE_MSF2_TIMER)
>> +
>> +/*
>> + * There are two 32-bit down counting timers.
>> + * Timers 1 and 2 can be concatenated into a single 64-bit Timer
>> + * that operates either in Periodic mode or in One-shot mode.
>> + * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit
>> mode.
>> + * In 64-bit mode, writing to the 32-bit registers has no effect.
>> + * Similarly, in 32-bit mode, writing to the 64-bit mode registers
>> + * has no effect. Only two 32-bit timers are supported currently.
>> + */
>> +#define NUM_TIMERS        2
>> +
>> +#define MSF2_TIMER_FREQ   (83 * 1000000)
>
>
> I can not find this value, can you point me to the datasheet? It seems SoC
> specific to me.
>
It is configured in Microsemi Libero. The SOM kit from Emcraft comes with
this default setting.
I guess this property should be set and passed from board file and not from
SoC.
Am I correct?
Can I attach the datasheet to this thread?

Thank you,
Sundeep
>
>> +
>> +#define R_TIM_VAL         0
>> +#define R_TIM_LOADVAL     1
>> +#define R_TIM_BGLOADVAL   2
>> +#define R_TIM_CTRL        3
>> +#define R_TIM_RIS         4
>> +#define R_TIM_MIS         5
>> +#define R_TIM1_MAX        6
>> +
>> +#define R_TIM_MODE       21
>> +#define R_TIM_MAX        22 /* including 64-bit timer registers */
>> +
>> +#define TIMER_CTRL_ENBL     (1 << 0)
>> +#define TIMER_CTRL_ONESHOT  (1 << 1)
>> +#define TIMER_CTRL_INTR     (1 << 2)
>> +#define TIMER_RIS_ACK       (1 << 0)
>> +#define TIMER_RST_CLR       (1 << 6)
>> +#define TIMER_MODE          (1 << 0)
>> +
>> +struct Msf2Timer {
>> +    QEMUBH *bh;
>> +    ptimer_state *ptimer;
>> +
>> +    uint32_t regs[R_TIM_MAX];
>> +    qemu_irq irq;
>> +};
>> +
>> +typedef struct MSF2TimerState {
>> +    SysBusDevice parent_obj;
>> +
>> +    MemoryRegion mmio;
>> +    uint32_t freq_hz;
>> +    struct Msf2Timer *timers;
>> +} MSF2TimerState;
>> +
>> +#endif /* HW_MSF2_TIMER_H */
>
>
> Regards,
>
> Phil.

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC
  2017-05-10  9:44 ` [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Philippe Mathieu-Daudé
@ 2017-05-10 15:24   ` sundeep subbaraya
  0 siblings, 0 replies; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-10 15:24 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis

Hi Philippe,


On Wed, May 10, 2017 at 3:14 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> Hi Subbaraya,
>
> This is your v4 of this patch set, please don't forget to include the
> version in your next set.
>
> Please also include changes between versions in your cover letter, it
> eases the review.


Sure. Sorry since this is not RFC i did not include versions. I will add
versions from next iteration.

Thanks,
Sundeep

>
>
> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>
>> Hi Qemu-devel,
>>
>> I am trying to add Smartfusion2 SoC.
>> SoC is from Microsemi and System on Module(SOM)
>> board is from Emcraft systems. Smartfusion2 has hardened
>> Microcontroller(Cortex-M3)based Sub System and FPGA fabric.
>> At the moment only system timer, sysreg and SPI
>> controller are modelled.
>>
>> Testing:
>> ./arm-softmmu/qemu-system-arm -M smartfusion2-som -serial mon:stdio \
>> -kernel u-boot.bin -display none -drive file=spi.bin,if=mtd,format=raw
>>
>> U-boot is from Emcraft with modified SPI driver not to use PDMA.
>> Linux is 4.5 linux with Smartfusion2 SoC dts and clocksource
>> driver added by myself @
>> https://github.com/Subbaraya-Sundeep/linux.git
>>
>> Baremetal elfs from Microsemi Softconsole IDE are also working.
>>
>> Thanks,
>> Sundeep
>>
>> Subbaraya Sundeep (5):
>>   msf2: Add Smartfusion2 System timer
>>   msf2: Microsemi Smartfusion2 System Register block.
>>   msf2: Add Smartfusion2 SPI controller
>>   msf2: Add Smartfusion2 SoC.
>>   msf2: Add Emcraft's Smartfusion2 SOM kit.
>>
>>  default-configs/arm-softmmu.mak |   1 +
>>  hw/arm/Makefile.objs            |   3 +-
>>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++
>>  hw/arm/msf2-som.c               |  67 +++++++
>>  hw/misc/Makefile.objs           |   1 +
>>  hw/misc/msf2-sysreg.c           | 131 ++++++++++++++
>>  hw/ssi/Makefile.objs            |   1 +
>>  hw/ssi/msf2-spi.c               | 378 ++++++++++++++++++++++++++++++
>> ++++++++++
>>  hw/timer/Makefile.objs          |   1 +
>>  hw/timer/msf2-timer.c           | 252 +++++++++++++++++++++++++++
>>  include/hw/arm/msf2-soc.h       |  60 +++++++
>>  include/hw/misc/msf2-sysreg.h   |  80 +++++++++
>>  include/hw/ssi/msf2-spi.h       | 105 +++++++++++
>>  include/hw/timer/msf2-timer.h   |  85 +++++++++
>>  14 files changed, 1352 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/arm/msf2-soc.c
>>  create mode 100644 hw/arm/msf2-som.c
>>  create mode 100644 hw/misc/msf2-sysreg.c
>>  create mode 100644 hw/ssi/msf2-spi.c
>>  create mode 100644 hw/timer/msf2-timer.c
>>  create mode 100644 include/hw/arm/msf2-soc.h
>>  create mode 100644 include/hw/misc/msf2-sysreg.h
>>  create mode 100644 include/hw/ssi/msf2-spi.h
>>  create mode 100644 include/hw/timer/msf2-timer.h
>>
>>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-10 11:50   ` Philippe Mathieu-Daudé
@ 2017-05-12  3:17     ` sundeep subbaraya
  2017-05-12  5:02       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-12  3:17 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis,
	Peter Crosthwaite

Hi Philippe,

On Wed, May 10, 2017 at 5:20 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> Hi Subbaraya,
>
>
> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>
>> Smartfusion2 SoC has hardened Microcontroller subsystem
>> and flash based FPGA fabric. This patch adds support for
>> Microcontroller subsystem in the SoC.
>>
>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> ---
>>  default-configs/arm-softmmu.mak |   1 +
>>  hw/arm/Makefile.objs            |   2 +-
>>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++
>> ++++++++++
>>  include/hw/arm/msf2-soc.h       |  60 +++++++++++++
>>  4 files changed, 250 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/arm/msf2-soc.c
>>  create mode 100644 include/hw/arm/msf2-soc.h
>>
>> diff --git a/default-configs/arm-softmmu.mak
>> b/default-configs/arm-softmmu.mak
>> index 78d7af0..7062512 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -122,3 +122,4 @@ CONFIG_ACPI=y
>>  CONFIG_SMBIOS=y
>>  CONFIG_ASPEED_SOC=y
>>  CONFIG_GPIO_KEY=y
>> +CONFIG_MSF2=y
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index 4c5c4ee..ae5e4a3 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -1,7 +1,7 @@
>>  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
>>  obj-$(CONFIG_DIGIC) += digic_boards.o
>>  obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
>> -obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
>> +obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
>>
>
> Not a big deal, but since you added CONFIG_MSF2 why not using it here and
> the Makefiles you touched (misc/ssi/timer)?
>
> obj-$(CONFIG_MSF2) += msf2-soc.o
>
>   OK. Will change it.

>
>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
>>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
>>  obj-y += netduino2.o
>> diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
>> new file mode 100644
>> index 0000000..d6341a2
>> --- /dev/null
>> +++ b/hw/arm/msf2-soc.c
>> @@ -0,0 +1,188 @@
>> +/*
>> + * SmartFusion2 SoC emulation.
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu-common.h"
>> +#include "hw/arm/arm.h"
>> +#include "exec/address-spaces.h"
>> +#include "hw/char/serial.h"
>> +#include "hw/boards.h"
>> +#include "sysemu/block-backend.h"
>> +#include "hw/arm/msf2-soc.h"
>> +
>> +#define MSF2_TIMER_BASE       0x40004000
>> +#define MSF2_SYSREG_BASE      0x40038000
>> +
>> +#define MSF2_TIMER_IRQ0       14
>> +#define MSF2_TIMER_IRQ1       15
>> +
>> +static const uint32_t spi_addr[MSF2_NUM_SPIS] = { 0x40001000 ,
>> 0x40011000 };
>> +static const uint32_t uart_addr[MSF2_NUM_UARTS] = { 0x40000000 ,
>> 0x40010000 };
>> +
>> +static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 };
>> +static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 };
>> +
>> +static void msf2_soc_initfn(Object *obj)
>> +{
>> +    MSF2State *s = MSF2_SOC(obj);
>> +    int i;
>> +
>> +    object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
>> +    qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
>> +
>> +    object_initialize(&s->sysreg, sizeof(s->sysreg), TYPE_MSF2_SYSREG);
>> +    qdev_set_parent_bus(DEVICE(&s->sysreg), sysbus_get_default());
>> +
>> +    object_initialize(&s->timer, sizeof(s->timer), TYPE_MSF2_TIMER);
>> +    qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default());
>> +
>> +    for (i = 0; i < MSF2_NUM_SPIS; i++) {
>> +        object_initialize(&s->spi[i], sizeof(s->spi[i]),
>> +                          TYPE_MSF2_SPI);
>> +        qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
>> +    }
>> +}
>> +
>> +static void msf2_soc_realize(DeviceState *dev_soc, Error **errp)
>> +{
>> +    MSF2State *s = MSF2_SOC(dev_soc);
>> +    DeviceState *dev, *armv7m;
>> +    SysBusDevice *busdev;
>> +    Error *err = NULL;
>> +    int i;
>> +
>> +    MemoryRegion *system_memory = get_system_memory();
>> +    MemoryRegion *nvm = g_new(MemoryRegion, 1);
>> +    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
>> +    MemoryRegion *ddr = g_new(MemoryRegion, 1);
>> +
>> +    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
>> +                           &error_fatal);
>>
>
> Maybe you can name it "eNVM" to match the documentation.
>
> Also envm_size should be a per-model property.
>

Ok.

>
> +    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
>> +                             nvm, 0, ENVM_SIZE);
>>
>
> Hmmm well this would be the "Cache Matrix Remap" which happens to be
> mapped by default to eNVM on cold reset.
> Naming it "MSF2.flash.alias" is pretty confusing.
>

Exactly it is Cache Matrix Remap.
AFAIK currently we cannot remap memory during runtime in Qemu.
So I handled default remap with alias.
Please suggest the name. MSF2.eNVM.alias sounds fine?

>
> +    vmstate_register_ram_global(nvm);
>> +
>> +    memory_region_set_readonly(nvm, true);
>> +    memory_region_set_readonly(nvm_alias, true);
>> +
>> +    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
>> +    memory_region_add_subregion(system_memory, 0, nvm_alias);
>> +
>> +    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
>> +                           &error_fatal);
>>
>
> Wrong, there is no DDR on this SoC.
>
DDR controller is there in Smartfusion2 (different from Smartfusion). As
you said below this
should be in board file.

>
> +    vmstate_register_ram_global(ddr);
>> +    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS, ddr);
>> +
>> +    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
>> +                           &error_fatal);
>>
>
> I'd rather like to see it named "eSRAM" somehow, so there is no confusion
> possible with external SRAM a SoM/board can map at 0x60000000.
>
> Same comment than envm_size, sram_size should be a per-model property.
>
> OK

> +    vmstate_register_ram_global(sram);
>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
>> +
>> +    armv7m = DEVICE(&s->armv7m);
>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
>>
>
> Can you point me to your datasheet? I thought the SF2 had 240 IRQs.


Please go to link:
https://www.microsemi.com/document-portal/search_form
and provide search keyword as "UG0331". You can the download the spec.
It has 81 irqs I remember when I have given 81 qemu complained not multiple
of 4.
I checked again with 81 and it is fine. I will change it to 81.

+    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
>> +    object_property_set_link(OBJECT(&s->armv7m),
>> OBJECT(get_system_memory()),
>> +                                     "memory", &error_abort);
>> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized",
>> &err);
>> +    if (err != NULL) {
>> +        error_propagate(errp, err);
>> +        return;
>> +    }
>> +
>> +    for (i = 0; i < MSF2_NUM_UARTS; i++) {
>> +        if (serial_hds[i]) {
>> +            serial_mm_init(get_system_memory(), uart_addr[i], 2,
>> +                           qdev_get_gpio_in(armv7m, uart_irq[i]),
>> +                           115200, serial_hds[i], DEVICE_NATIVE_ENDIAN);
>> +        }
>> +    }
>> +
>> +    dev = DEVICE(&s->timer);
>> +    qdev_prop_set_uint32(dev, "clock-frequency", MSF2_TIMER_FREQ);
>> +    object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
>> +    if (err != NULL) {
>> +        error_propagate(errp, err);
>> +        return;
>> +    }
>> +    busdev = SYS_BUS_DEVICE(dev);
>> +    sysbus_mmio_map(busdev, 0, MSF2_TIMER_BASE);
>> +    sysbus_connect_irq(busdev, 0,
>> +                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ0));
>> +    sysbus_connect_irq(busdev, 1,
>> +                           qdev_get_gpio_in(armv7m, MSF2_TIMER_IRQ1));
>> +
>> +    dev = DEVICE(&s->sysreg);
>> +    object_property_set_bool(OBJECT(&s->sysreg), true, "realized",
>> &err);
>> +    if (err != NULL) {
>> +        error_propagate(errp, err);
>> +        return;
>> +    }
>> +    busdev = SYS_BUS_DEVICE(dev);
>> +    sysbus_mmio_map(busdev, 0, MSF2_SYSREG_BASE);
>> +
>> +    for (i = 0; i < MSF2_NUM_SPIS; i++) {
>> +        gchar *bus_name = g_strdup_printf("spi%d", i);
>> +
>> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
>> &err);
>> +        if (err != NULL) {
>> +            g_free(bus_name);
>> +            error_propagate(errp, err);
>> +            return;
>> +        }
>> +
>> +        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_addr[i]);
>> +        sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
>> +                           qdev_get_gpio_in(armv7m, spi_irq[i]));
>> +
>> +        /* Alias controller SPI bus to the SoC itself */
>> +        object_property_add_alias(OBJECT(s), bus_name,
>> +                                  OBJECT(&s->spi[i]), "spi0",
>> +                                  &error_abort);
>> +        g_free(bus_name);
>> +    }
>> +}
>> +
>> +static void msf2_soc_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->realize = msf2_soc_realize;
>> +}
>> +
>> +static const TypeInfo msf2_soc_info = {
>> +    .name          = TYPE_MSF2_SOC,
>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size = sizeof(MSF2State),
>> +    .instance_init = msf2_soc_initfn,
>> +    .class_init    = msf2_soc_class_init,
>> +};
>> +
>> +static void msf2_soc_types(void)
>> +{
>> +    type_register_static(&msf2_soc_info);
>> +}
>> +
>> +type_init(msf2_soc_types)
>> diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
>> new file mode 100644
>> index 0000000..29a8ff8
>> --- /dev/null
>> +++ b/include/hw/arm/msf2-soc.h
>> @@ -0,0 +1,60 @@
>> +/*
>> + * Microsemi Smartfusion2 SoC
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#ifndef HW_ARM_MSF2_SOC_H
>> +#define HW_ARM_MSF2_SOC_H
>> +
>> +#include "hw/misc/msf2-sysreg.h"
>> +#include "hw/timer/msf2-timer.h"
>> +#include "hw/ssi/msf2-spi.h"
>> +#include "hw/arm/armv7m.h"
>> +
>> +#define TYPE_MSF2_SOC     "msf2-soc"
>> +#define MSF2_SOC(obj)     OBJECT_CHECK(MSF2State, (obj), TYPE_MSF2_SOC)
>> +
>> +#define MSF2_NUM_SPIS         2
>> +#define MSF2_NUM_UARTS        2
>> +
>> +#define ENVM_BASE_ADDRESS     0x60000000
>> +#define ENVM_SIZE             (128 * 1024)
>>
>
> The SoC design ENVM_SIZE is 1MB, 128K seems your particular model.
>

 M2S010 SoC device has 256K eNMV. My bad it should be 256 instead of 128.
 The board I have contains M2S010 device in SOM.

> +
>> +#define DDR_BASE_ADDRESS      0xA0000000
>> +#define DDR_SIZE              (64 * 1024 * 1024)
>>
>
> This belongs to the SoM.
> Yes will change it.
>
>> +
>> +#define SRAM_BASE_ADDRESS     0x20000000
>> +#define SRAM_SIZE             (64 * 1024)
>>
>
> Indeed this SoC is designed to have up to 64K of SRAM.
> Luckily your model provides 64K.
>


Yes it is 64k :)

>
>
+
>> +typedef struct MSF2State {
>> +    /*< private >*/
>> +    SysBusDevice parent_obj;
>> +    /*< public >*/
>> +
>> +    ARMv7MState armv7m;
>> +
>> +    MSF2SysregState sysreg;
>> +    MSF2TimerState timer;
>> +    MSF2SpiState spi[MSF2_NUM_SPIS];
>> +} MSF2State;
>> +
>> +#endif
>>
>>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller
  2017-05-10 12:12   ` Philippe Mathieu-Daudé
@ 2017-05-12  3:31     ` sundeep subbaraya
  2017-05-12  3:54       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-12  3:31 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis,
	Peter Crosthwaite

Hi Philippe,

On Wed, May 10, 2017 at 5:42 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> Hi Subbaraya,
>
> Like my comment for the timer model, I'd name this model "mss_spi".
> The only difference I see in the SF2 is the STAT8 register.
> No need to register both devices now but maybe you can add a comment about
> it?
>

Ok I will register only SPI0 in SoC file as of now and will add comment.

>
> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>
>> Modelled Microsemi's Smartfusion2 SPI controller.
>>
>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> ---
>>  hw/ssi/Makefile.objs      |   1 +
>>  hw/ssi/msf2-spi.c         | 378 ++++++++++++++++++++++++++++++
>> ++++++++++++++++
>>  include/hw/ssi/msf2-spi.h | 105 +++++++++++++
>>  3 files changed, 484 insertions(+)
>>  create mode 100644 hw/ssi/msf2-spi.c
>>  create mode 100644 include/hw/ssi/msf2-spi.h
>>
>> diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
>> index 487add2..3105c4b 100644
>> --- a/hw/ssi/Makefile.objs
>> +++ b/hw/ssi/Makefile.objs
>> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
>>  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
>>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
>>  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
>> +common-obj-$(CONFIG_MSF2) += msf2-spi.o
>>
>
> Not a big deal but his define only appears after applying the next patch.

Do I need to reorder the patches?

>
>>  obj-$(CONFIG_OMAP) += omap_spi.o
>>  obj-$(CONFIG_IMX) += imx_spi.o
>> diff --git a/hw/ssi/msf2-spi.c b/hw/ssi/msf2-spi.c
>> new file mode 100644
>> index 0000000..2059ed9
>> --- /dev/null
>> +++ b/hw/ssi/msf2-spi.c
>> @@ -0,0 +1,378 @@
>> +/*
>> + * SPI controller model of Microsemi SmartFusion2.
>> + *
>> + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#include "hw/ssi/msf2-spi.h"
>> +
>> +#ifndef MSF2_SPI_ERR_DEBUG
>> +#define MSF2_SPI_ERR_DEBUG   0
>> +#endif
>> +
>> +#define DB_PRINT_L(lvl, fmt, args...) do { \
>> +    if (MSF2_SPI_ERR_DEBUG >= lvl) { \
>> +        qemu_log("%s: " fmt, __func__, ## args); \
>> +    } \
>> +} while (0);
>> +
>> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>> +
>> +static void txfifo_reset(MSF2SpiState *s)
>> +{
>> +    fifo32_reset(&s->tx_fifo);
>> +
>> +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;
>> +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;
>> +}
>> +
>> +static void rxfifo_reset(MSF2SpiState *s)
>> +{
>> +    fifo32_reset(&s->rx_fifo);
>> +
>> +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
>> +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
>> +}
>> +
>> +static void set_fifodepth(MSF2SpiState *s)
>> +{
>> +    int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;
>> +
>> +    if (0 <= size && size <= 8) {
>> +        s->fifo_depth = 32;
>> +    }
>> +    if (9 <= size && size <= 16) {
>> +        s->fifo_depth = 16;
>> +    }
>> +    if (17 <= size && size <= 32) {
>> +        s->fifo_depth = 8;
>> +    }
>> +}
>> +
>> +static void msf2_spi_do_reset(MSF2SpiState *s)
>> +{
>> +    memset(s->regs, 0, sizeof s->regs);
>> +    s->regs[R_SPI_CONTROL] = 0x80000102;
>> +    s->regs[R_SPI_DFSIZE] = 0x4;
>> +    s->regs[R_SPI_STATUS] = 0x2440;
>> +    s->regs[R_SPI_CLKGEN] = 0x7;
>> +    s->regs[R_SPI_STAT8] = 0x7;
>> +    s->regs[R_SPI_RIS] = 0x0;
>> +
>> +    s->fifo_depth = 4;
>> +    s->frame_count = 1;
>> +    s->enabled = false;
>> +
>> +    rxfifo_reset(s);
>> +    txfifo_reset(s);
>> +}
>> +
>> +static void update_mis(MSF2SpiState *s)
>> +{
>> +    uint32_t reg = s->regs[R_SPI_CONTROL];
>> +    uint32_t tmp;
>> +
>> +    /*
>> +     * form the Control register interrupt enable bits
>> +     * same as RIS, MIS and Interrupt clear registers for simplicity
>> +     */
>> +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |
>> +           ((reg & C_INTTXDATA) >> 5);
>> +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];
>> +}
>> +
>> +static void spi_update_irq(MSF2SpiState *s)
>> +{
>> +    int irq;
>> +
>> +    update_mis(s);
>> +    irq = !!(s->regs[R_SPI_MIS]);
>> +
>> +    qemu_set_irq(s->irq, irq);
>> +}
>> +
>> +static void msf2_spi_reset(DeviceState *d)
>> +{
>> +    msf2_spi_do_reset(MSF2_SPI(d));
>> +}
>> +
>> +static uint64_t
>> +spi_read(void *opaque, hwaddr addr, unsigned int size)
>> +{
>> +    MSF2SpiState *s = opaque;
>> +    uint32_t ret = 0;
>> +
>> +    addr >>= 2;
>> +    switch (addr) {
>> +    case R_SPI_RX:
>> +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
>> +        s->regs[R_SPI_STATUS] &= ~RXCHOVRF;
>> +        ret = fifo32_pop(&s->rx_fifo);
>> +        if (fifo32_is_empty(&s->rx_fifo)) {
>> +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
>> +        }
>> +        break;
>> +
>> +    case R_SPI_MIS:
>> +        update_mis(s);
>> +        ret = s->regs[R_SPI_MIS];
>> +        break;
>> +
>> +    default:
>> +        if (addr < ARRAY_SIZE(s->regs)) {
>> +            ret = s->regs[addr];
>> +        } else {
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
>> +                         addr * 4);
>>
>
> Drop '\n' while calling qemu_log_mask().

Ok.

>
>
> +        }
>> +        break;
>> +    }
>> +
>> +    DB_PRINT("addr=0x%" HWADDR_PRIx " = 0x%" PRIx32 "\n", addr * 4, ret);
>> +    spi_update_irq(s);
>> +    return ret;
>> +}
>> +
>> +static void assert_cs(MSF2SpiState *s)
>> +{
>> +    qemu_set_irq(s->cs_line, 0);
>> +}
>> +
>> +static void deassert_cs(MSF2SpiState *s)
>> +{
>> +    qemu_set_irq(s->cs_line, 1);
>> +}
>> +
>> +static void spi_flush_txfifo(MSF2SpiState *s)
>> +{
>> +    uint32_t tx;
>> +    uint32_t rx;
>> +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);
>> +
>> +    /*
>> +     * Chip Select(CS) is automatically controlled by this controller.
>> +     * If SPS bit is set in Control register then CS is asserted
>> +     * until all the frames set in frame count of Control register are
>> +     * transferred. If SPS is not set then CS pulses between frames.
>> +     * Note that Slave Select register specifies which of the CS line
>> +     * has to be controlled automatically by controller. Bits SS[7:1]
>> are for
>> +     * masters in FPGA fabric since we model only Microcontroller
>> subsystem
>> +     * of Smartfusion2 we control only one CS(SS[0]) line.
>> +     */
>> +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {
>> +        assert_cs(s);
>> +
>> +        s->regs[R_SPI_STATUS] &= ~TXDONE;
>> +        s->regs[R_SPI_STATUS] &= ~RXRDY;
>> +
>> +        tx = fifo32_pop(&s->tx_fifo);
>> +        DB_PRINT("data tx:0x%" PRIx32 "\n", tx);
>> +        rx = ssi_transfer(s->spi, tx);
>> +        DB_PRINT("data rx:0x%" PRIx32 "\n", rx);
>> +
>> +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
>> +            s->regs[R_SPI_STATUS] |= RXCHOVRF;
>> +            s->regs[R_SPI_RIS] |= RXCHOVRF;
>> +        } else {
>> +            fifo32_push(&s->rx_fifo, rx);
>> +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;
>> +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {
>> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;
>> +            }
>> +            if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
>> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;
>> +            }
>> +        }
>> +        s->frame_count--;
>> +        if (!sps) {
>> +            deassert_cs(s);
>> +            assert_cs(s);
>> +        }
>> +    }
>> +
>> +    if (!sps) {
>> +        deassert_cs(s);
>> +    }
>> +
>> +    if (!s->frame_count) {
>> +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>
>> +                            FMCOUNT_SHIFT;
>> +        if (sps) {
>> +            deassert_cs(s);
>> +        }
>> +        s->regs[R_SPI_RIS] |= TXDONE;
>> +        s->regs[R_SPI_RIS] |= RXRDY;
>> +        s->regs[R_SPI_STATUS] |= TXDONE;
>> +        s->regs[R_SPI_STATUS] |= RXRDY;
>> +   }
>> +}
>> +
>> +static void spi_write(void *opaque, hwaddr addr,
>> +            uint64_t val64, unsigned int size)
>> +{
>> +    MSF2SpiState *s = opaque;
>> +    uint32_t value = val64;
>> +
>> +    DB_PRINT("addr=0x%" HWADDR_PRIx " =0x%" PRIx32 "\n", addr, value);
>> +    addr >>= 2;
>> +
>> +    switch (addr) {
>> +    case R_SPI_TX:
>> +        /* adding to already full FIFO */
>> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
>> +            break;
>> +        }
>> +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;
>> +        fifo32_push(&s->tx_fifo, value);
>> +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {
>> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;
>> +        }
>> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
>> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;
>> +        }
>> +        if (s->enabled) {
>> +            spi_flush_txfifo(s);
>> +        }
>> +        break;
>> +
>> +    case R_SPI_CONTROL:
>> +        s->regs[R_SPI_CONTROL] = value;
>> +        if (value & C_BIGFIFO) {
>> +            set_fifodepth(s);
>> +        } else {
>> +            s->fifo_depth = 4;
>> +        }
>> +        if (value & C_ENABLE) {
>> +            s->enabled = true;
>> +        } else {
>> +            s->enabled = false;
>> +        }
>> +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;
>> +        if (value & C_RESET) {
>> +            msf2_spi_do_reset(s);
>> +        }
>> +        break;
>> +
>> +    case R_SPI_DFSIZE:
>> +        if (s->enabled) {
>> +            break;
>> +        }
>> +        s->regs[R_SPI_DFSIZE] = value;
>> +        break;
>> +
>> +    case R_SPI_INTCLR:
>> +        s->regs[R_SPI_INTCLR] = value;
>> +        if (value & TXDONE) {
>> +            s->regs[R_SPI_RIS] &= ~TXDONE;
>> +        }
>> +        if (value & RXRDY) {
>> +            s->regs[R_SPI_RIS] &= ~RXRDY;
>> +        }
>> +        if (value & RXCHOVRF) {
>> +            s->regs[R_SPI_RIS] &= ~RXCHOVRF;
>> +        }
>> +        break;
>> +
>> +    case R_SPI_MIS:
>> +    case R_SPI_STATUS:
>> +    case R_SPI_RIS:
>> +        break;
>> +
>> +    default:
>> +        if (addr < ARRAY_SIZE(s->regs)) {
>> +            s->regs[addr] = value;
>> +        } else {
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
>> +                         addr * 4);
>> +        }
>> +        break;
>> +    }
>> +
>> +    spi_update_irq(s);
>> +}
>> +
>> +static const MemoryRegionOps spi_ops = {
>> +    .read = spi_read,
>> +    .write = spi_write,
>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>> +    .valid = {
>> +        .min_access_size = 4,
>> +        .max_access_size = 4
>> +    }
>> +};
>> +
>> +static void msf2_spi_realize(DeviceState *dev, Error **errp)
>> +{
>> +    MSF2SpiState *s = MSF2_SPI(dev);
>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> +
>> +    DB_PRINT("\n");
>> +
>> +    s->spi = ssi_create_bus(dev, "spi0");
>> +
>> +    sysbus_init_irq(sbd, &s->irq);
>> +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);
>> +    sysbus_init_irq(sbd, &s->cs_line);
>> +
>> +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
>> +                          TYPE_MSF2_SPI, R_SPI_MAX * 4);
>> +    sysbus_init_mmio(sbd, &s->mmio);
>> +
>> +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);
>> +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);
>> +}
>> +
>> +static const VMStateDescription vmstate_msf2_spi = {
>> +    .name = TYPE_MSF2_SPI,
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_FIFO32(tx_fifo, MSF2SpiState),
>> +        VMSTATE_FIFO32(rx_fifo, MSF2SpiState),
>> +        VMSTATE_UINT32_ARRAY(regs, MSF2SpiState, R_SPI_MAX),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void msf2_spi_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->realize = msf2_spi_realize;
>> +    dc->reset = msf2_spi_reset;
>> +    dc->vmsd = &vmstate_msf2_spi;
>> +}
>> +
>> +static const TypeInfo msf2_spi_info = {
>> +    .name           = TYPE_MSF2_SPI,
>> +    .parent         = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size  = sizeof(MSF2SpiState),
>> +    .class_init     = msf2_spi_class_init,
>> +};
>> +
>> +static void msf2_spi_register_types(void)
>> +{
>> +    type_register_static(&msf2_spi_info);
>> +}
>> +
>> +type_init(msf2_spi_register_types)
>> diff --git a/include/hw/ssi/msf2-spi.h b/include/hw/ssi/msf2-spi.h
>> new file mode 100644
>> index 0000000..585edde
>> --- /dev/null
>> +++ b/include/hw/ssi/msf2-spi.h
>> @@ -0,0 +1,105 @@
>> +/*
>> + * Microsemi SmartFusion2 SPI
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#ifndef HW_MSF2_SPI_H
>> +#define HW_MSF2_SPI_H
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/hw.h"
>> +#include "hw/ssi/ssi.h"
>> +#include "qemu/fifo32.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/log.h"
>> +
>> +#define FIFO_CAPACITY     32
>> +#define FIFO_CAPACITY     32
>> +
>> +#define R_SPI_CONTROL         0
>> +#define R_SPI_DFSIZE          1
>> +#define R_SPI_STATUS          2
>> +#define R_SPI_INTCLR          3
>> +#define R_SPI_RX              4
>> +#define R_SPI_TX              5
>> +#define R_SPI_CLKGEN          6
>> +#define R_SPI_SS              7
>> +#define R_SPI_MIS             8
>> +#define R_SPI_RIS             9
>> +#define R_SPI_STAT8           15
>> +#define R_SPI_MAX             16
>> +
>> +#define S_RXFIFOFUL       (1 << 4)
>> +#define S_RXFIFOFULNXT    (1 << 5)
>> +#define S_RXFIFOEMP       (1 << 6)
>> +#define S_RXFIFOEMPNXT    (1 << 7)
>> +#define S_TXFIFOFUL       (1 << 8)
>> +#define S_TXFIFOFULNXT    (1 << 9)
>> +#define S_TXFIFOEMP       (1 << 10)
>> +#define S_TXFIFOEMPNXT    (1 << 11)
>> +#define S_FRAMESTART      (1 << 12)
>> +#define S_SSEL            (1 << 13)
>> +#define S_ACTIVE          (1 << 14)
>> +
>> +#define C_ENABLE          (1 << 0)
>> +#define C_MODE            (1 << 1)
>> +#define C_INTRXDATA       (1 << 4)
>> +#define C_INTTXDATA       (1 << 5)
>> +#define C_INTRXOVRFLO     (1 << 6)
>> +#define C_SPS             (1 << 26)
>> +#define C_BIGFIFO         (1 << 29)
>> +#define C_RESET           (1 << 31)
>> +
>> +#define FRAMESZ_MASK      0x1F
>> +#define FMCOUNT_MASK      0x00FFFF00
>> +#define FMCOUNT_SHIFT     8
>> +
>> +#define TXDONE            (1 << 0)
>> +#define RXRDY             (1 << 1)
>> +#define RXCHOVRF          (1 << 2)
>> +
>> +#define TYPE_MSF2_SPI   "msf2-spi"
>> +#define MSF2_SPI(obj)   OBJECT_CHECK(MSF2SpiState, (obj), TYPE_MSF2_SPI)
>> +
>> +typedef struct MSF2SpiState {
>> +    SysBusDevice parent_obj;
>> +
>> +    MemoryRegion mmio;
>> +
>> +    qemu_irq irq;
>> +
>> +    qemu_irq cs_line;
>> +
>> +    SSIBus *spi;
>> +
>> +    Fifo32 rx_fifo;
>> +    Fifo32 tx_fifo;
>> +
>> +    int fifo_depth;
>> +    uint32_t frame_count;
>> +    bool enabled;
>> +
>> +    uint32_t regs[R_SPI_MAX];
>> +} MSF2SpiState;
>> +
>> +#endif /* HW_MSF2_SPI_H */
>>
>>
> Regards,
>
> Phil.
>
Thanks,
Sundeep

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

* Re: [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block.
  2017-05-10 10:34   ` Philippe Mathieu-Daudé
@ 2017-05-12  3:48     ` sundeep subbaraya
  2017-05-12  4:12       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-12  3:48 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis,
	Peter Crosthwaite

Hi Phiilippe,

On Wed, May 10, 2017 at 4:04 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> Hi Subbaraya,
>
>
> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>
>> Added Sytem register block of Smartfusion2.
>> This block has PLL registers which are accessed by guest.
>>
>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> ---
>>  hw/misc/Makefile.objs         |   1 +
>>  hw/misc/msf2-sysreg.c         | 131 ++++++++++++++++++++++++++++++
>> ++++++++++++
>>  include/hw/misc/msf2-sysreg.h |  80 ++++++++++++++++++++++++++
>>  3 files changed, 212 insertions(+)
>>  create mode 100644 hw/misc/msf2-sysreg.c
>>  create mode 100644 include/hw/misc/msf2-sysreg.h
>>
>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>> index c8b4893..0f52354 100644
>> --- a/hw/misc/Makefile.objs
>> +++ b/hw/misc/Makefile.objs
>> @@ -56,3 +56,4 @@ obj-$(CONFIG_EDU) += edu.o
>>  obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
>>  obj-$(CONFIG_AUX) += auxbus.o
>>  obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
>> +obj-$(CONFIG_MSF2) += msf2-sysreg.o
>> diff --git a/hw/misc/msf2-sysreg.c b/hw/misc/msf2-sysreg.c
>> new file mode 100644
>> index 0000000..53e9cba
>> --- /dev/null
>> +++ b/hw/misc/msf2-sysreg.c
>> @@ -0,0 +1,131 @@
>> +/*
>> + * System Register block model of Microsemi SmartFusion2.
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version
>> + * 2 of the License, or (at your option) any later version.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "hw/misc/msf2-sysreg.h"
>> +
>> +#ifndef MSF2_SYSREG_ERR_DEBUG
>> +#define MSF2_SYSREG_ERR_DEBUG  0
>> +#endif
>> +
>> +#define DB_PRINT_L(lvl, fmt, args...) do { \
>> +    if (MSF2_SYSREG_ERR_DEBUG >= lvl) { \
>> +        qemu_log("%s: " fmt, __func__, ## args); \
>> +    } \
>> +} while (0);
>> +
>> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>> +
>> +static void msf2_sysreg_reset(DeviceState *d)
>> +{
>> +    MSF2SysregState *s = MSF2_SYSREG(d);
>> +
>> +    DB_PRINT("RESET\n");
>> +
>> +    s->regs[MSSDDR_PLL_STATUS_LOW_CR] = 0x02420041;
>> +    s->regs[MSSDDR_FACC1_CR] = 0x0A482124;
>> +    s->regs[MSSDDR_PLL_STATUS] = 0x3;
>> +}
>> +
>> +static uint64_t msf2_sysreg_read(void *opaque, hwaddr offset,
>> +    unsigned size)
>> +{
>> +    MSF2SysregState *s = opaque;
>> +    offset /= 4;
>> +    uint32_t ret = 0;
>> +
>> +    if (offset < ARRAY_SIZE(s->regs)) {
>> +        ret = s->regs[offset];
>> +        DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx32 "\n",
>> +                    offset * 4, ret);
>> +    } else {
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                    "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
>> +                    offset * 4);
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +static void msf2_sysreg_write(void *opaque, hwaddr offset,
>> +                          uint64_t val, unsigned size)
>> +{
>> +    MSF2SysregState *s = (MSF2SysregState *)opaque;
>> +    offset /= 4;
>> +
>> +    DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx64 "\n",
>> +            offset * 4, val);
>> +
>> +    switch (offset) {
>> +    case MSSDDR_PLL_STATUS:
>> +        break;
>> +
>> +    default:
>> +        if (offset < ARRAY_SIZE(s->regs)) {
>> +            s->regs[offset] = val;
>>
>
> I think this is pretty unsafe for the guest to continue if those registers
> are accessed in your current implementation.
>
> I'd at least somehow abort for few of them (RESET, REMAP*), what do you
> think?


Ok. We can abort for REMAP. All the peripherals need to be released from
reset by writing to Sysreg.
Can we handle that case where if guest writes to Sysreg to reset SPI(say)
then we can reset SPI
model from here? I am very new here and I did not come across this case in
the models I have referred.
Please let me know if that is possible. If not possible I would simply log
messages like released
from reset/put in reset.

Thanks,
Sundeep

>
>
> +        } else {
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                        "%s: Bad offset 0x%08" HWADDR_PRIx "\n",
>> __func__,
>> +                        offset * 4);
>> +        }
>> +        break;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps sysreg_ops = {
>> +    .read = msf2_sysreg_read,
>> +    .write = msf2_sysreg_write,
>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>> +};
>> +
>> +static void msf2_sysreg_init(Object *obj)
>> +{
>> +    MSF2SysregState *s = MSF2_SYSREG(obj);
>> +
>> +    memory_region_init_io(&s->iomem, obj, &sysreg_ops, s,
>> TYPE_MSF2_SYSREG,
>> +                          MSF2_SYSREG_MMIO_SIZE);
>> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
>> +}
>> +
>> +static const VMStateDescription vmstate_msf2_sysreg = {
>> +    .name = TYPE_MSF2_SYSREG,
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT32_ARRAY(regs, MSF2SysregState,
>> MSF2_SYSREG_NUM_REGS),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void msf2_sysreg_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    dc->vmsd = &vmstate_msf2_sysreg;
>> +    dc->reset = msf2_sysreg_reset;
>> +}
>> +
>> +static const TypeInfo msf2_sysreg_info = {
>> +    .name  = TYPE_MSF2_SYSREG,
>> +    .parent = TYPE_SYS_BUS_DEVICE,
>> +    .class_init = msf2_sysreg_class_init,
>> +    .instance_size  = sizeof(MSF2SysregState),
>> +    .instance_init = msf2_sysreg_init,
>> +};
>> +
>> +static void msf2_sysreg_register_types(void)
>> +{
>> +    type_register_static(&msf2_sysreg_info);
>> +}
>> +
>> +type_init(msf2_sysreg_register_types)
>> diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.
>> h
>> new file mode 100644
>> index 0000000..a485ed6
>> --- /dev/null
>> +++ b/include/hw/misc/msf2-sysreg.h
>> @@ -0,0 +1,80 @@
>> +/*
>> + * Microsemi SmartFusion2 SYSREG
>> + *
>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +#ifndef HW_MSF2_SYSREG_H
>> +#define HW_MSF2_SYSREG_H
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/hw.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/log.h"
>> +
>> +enum {
>> +    ESRAM_CR        = 0x00 / 4,
>> +    ESRAM_MAX_LAT,
>> +    DDR_CR,
>> +    ENVM_CR,
>> +    ENVM_REMAP_BASE_CR,
>> +    ENVM_REMAP_FAB_CR,
>> +    CC_CR,
>> +    CC_REGION_CR,
>> +    CC_LOCK_BASE_ADDR_CR,
>> +    CC_FLUSH_INDX_CR,
>> +    DDRB_BUF_TIMER_CR,
>> +    DDRB_NB_ADDR_CR,
>> +    DDRB_NB_SIZE_CR,
>> +    DDRB_CR,
>> +
>> +    SOFT_RESET_CR  = 0x48 / 4,
>> +    M3_CR,
>> +
>> +    GPIO_SYSRESET_SEL_CR = 0x58 / 4,
>> +
>> +    MDDR_CR = 0x60 / 4,
>> +
>> +    MSSDDR_PLL_STATUS_LOW_CR = 0x90 / 4,
>> +    MSSDDR_PLL_STATUS_HIGH_CR,
>> +    MSSDDR_FACC1_CR,
>> +    MSSDDR_FACC2_CR,
>> +
>> +    MSSDDR_PLL_STATUS = 0x150 / 4,
>> +
>> +};
>> +
>> +#define MSF2_SYSREG_MMIO_SIZE     0x300
>> +#define MSF2_SYSREG_NUM_REGS      (MSF2_SYSREG_MMIO_SIZE / 4)
>> +
>> +#define TYPE_MSF2_SYSREG          "msf2-sysreg"
>> +#define MSF2_SYSREG(obj)  OBJECT_CHECK(MSF2SysregState, (obj),
>> TYPE_MSF2_SYSREG)
>> +
>> +typedef struct MSF2SysregState {
>> +    SysBusDevice parent_obj;
>> +
>> +    MemoryRegion iomem;
>> +
>> +    uint32_t regs[MSF2_SYSREG_NUM_REGS];
>> +} MSF2SysregState;
>> +
>> +#endif /* HW_MSF2_SYSREG_H */
>>
>>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller
  2017-05-12  3:31     ` sundeep subbaraya
@ 2017-05-12  3:54       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-12  3:54 UTC (permalink / raw)
  To: sundeep subbaraya
  Cc: Peter Maydell, Peter Crosthwaite, qemu-arm, QEMU Developers,
	Alistair Francis

Hi Subbaraya,

On 05/12/2017 12:31 AM, sundeep subbaraya wrote:
> Hi Philippe,
>
> On Wed, May 10, 2017 at 5:42 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
> wrote:
>
>> Hi Subbaraya,
>>
>> Like my comment for the timer model, I'd name this model "mss_spi".
>> The only difference I see in the SF2 is the STAT8 register.
>> No need to register both devices now but maybe you can add a comment about
>> it?
>>
>
> Ok I will register only SPI0 in SoC file as of now and will add comment.
>

What I mean is the difference I know between mss_spi from SmartFusion 
versus mss_spi from the SmartFusion2 is the STAT8 register.
Your file is SmartFusion2-specific just because of this unused register.

Now since you have the mss_spi modeled and you want to model the SF2 
SoC, you should register both SPI_0 and SPI_1, my comment was not about 
that.

Well forget about this comment about STAT8 difference :) This is not a 
problem and can be improved in the future.

>>
>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>
>>> Modelled Microsemi's Smartfusion2 SPI controller.
>>>
>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> ---
>>>  hw/ssi/Makefile.objs      |   1 +
>>>  hw/ssi/msf2-spi.c         | 378 ++++++++++++++++++++++++++++++
>>> ++++++++++++++++
>>>  include/hw/ssi/msf2-spi.h | 105 +++++++++++++
>>>  3 files changed, 484 insertions(+)
>>>  create mode 100644 hw/ssi/msf2-spi.c
>>>  create mode 100644 include/hw/ssi/msf2-spi.h
>>>
>>> diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
>>> index 487add2..3105c4b 100644
>>> --- a/hw/ssi/Makefile.objs
>>> +++ b/hw/ssi/Makefile.objs
>>> @@ -4,6 +4,7 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
>>>  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
>>>  common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
>>>  common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
>>> +common-obj-$(CONFIG_MSF2) += msf2-spi.o
>>>
>>
>> Not a big deal but his define only appears after applying the next patch.
>
> Do I need to reorder the patches?
>

It is probably not important, but for what it's worth if you checkout 
your tree at this patch 3/5 and build, the msf2-spi.o is not compiled.

Although I'm not sure it could bother bissecting an issue in your code.

>>
>>>  obj-$(CONFIG_OMAP) += omap_spi.o
>>>  obj-$(CONFIG_IMX) += imx_spi.o
>>> diff --git a/hw/ssi/msf2-spi.c b/hw/ssi/msf2-spi.c
>>> new file mode 100644
>>> index 0000000..2059ed9
>>> --- /dev/null
>>> +++ b/hw/ssi/msf2-spi.c
>>> @@ -0,0 +1,378 @@
>>> +/*
>>> + * SPI controller model of Microsemi SmartFusion2.
>>> + *
>>> + * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining
>>> a copy
>>> + * of this software and associated documentation files (the "Software"),
>>> to deal
>>> + * in the Software without restriction, including without limitation the
>>> rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>>> sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be
>>> included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>>> EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>>> MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>>> SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>>> OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>>> ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>>> DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#include "hw/ssi/msf2-spi.h"
>>> +
>>> +#ifndef MSF2_SPI_ERR_DEBUG
>>> +#define MSF2_SPI_ERR_DEBUG   0
>>> +#endif
>>> +
>>> +#define DB_PRINT_L(lvl, fmt, args...) do { \
>>> +    if (MSF2_SPI_ERR_DEBUG >= lvl) { \
>>> +        qemu_log("%s: " fmt, __func__, ## args); \
>>> +    } \
>>> +} while (0);
>>> +
>>> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>>> +
>>> +static void txfifo_reset(MSF2SpiState *s)
>>> +{
>>> +    fifo32_reset(&s->tx_fifo);
>>> +
>>> +    s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL;
>>> +    s->regs[R_SPI_STATUS] |= S_TXFIFOEMP;
>>> +}
>>> +
>>> +static void rxfifo_reset(MSF2SpiState *s)
>>> +{
>>> +    fifo32_reset(&s->rx_fifo);
>>> +
>>> +    s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
>>> +    s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
>>> +}
>>> +
>>> +static void set_fifodepth(MSF2SpiState *s)
>>> +{
>>> +    int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK;
>>> +
>>> +    if (0 <= size && size <= 8) {
>>> +        s->fifo_depth = 32;
>>> +    }
>>> +    if (9 <= size && size <= 16) {
>>> +        s->fifo_depth = 16;
>>> +    }
>>> +    if (17 <= size && size <= 32) {
>>> +        s->fifo_depth = 8;
>>> +    }
>>> +}
>>> +
>>> +static void msf2_spi_do_reset(MSF2SpiState *s)
>>> +{
>>> +    memset(s->regs, 0, sizeof s->regs);
>>> +    s->regs[R_SPI_CONTROL] = 0x80000102;
>>> +    s->regs[R_SPI_DFSIZE] = 0x4;
>>> +    s->regs[R_SPI_STATUS] = 0x2440;
>>> +    s->regs[R_SPI_CLKGEN] = 0x7;
>>> +    s->regs[R_SPI_STAT8] = 0x7;
>>> +    s->regs[R_SPI_RIS] = 0x0;
>>> +
>>> +    s->fifo_depth = 4;
>>> +    s->frame_count = 1;
>>> +    s->enabled = false;
>>> +
>>> +    rxfifo_reset(s);
>>> +    txfifo_reset(s);
>>> +}
>>> +
>>> +static void update_mis(MSF2SpiState *s)
>>> +{
>>> +    uint32_t reg = s->regs[R_SPI_CONTROL];
>>> +    uint32_t tmp;
>>> +
>>> +    /*
>>> +     * form the Control register interrupt enable bits
>>> +     * same as RIS, MIS and Interrupt clear registers for simplicity
>>> +     */
>>> +    tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) |
>>> +           ((reg & C_INTTXDATA) >> 5);
>>> +    s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS];
>>> +}
>>> +
>>> +static void spi_update_irq(MSF2SpiState *s)
>>> +{
>>> +    int irq;
>>> +
>>> +    update_mis(s);
>>> +    irq = !!(s->regs[R_SPI_MIS]);
>>> +
>>> +    qemu_set_irq(s->irq, irq);
>>> +}
>>> +
>>> +static void msf2_spi_reset(DeviceState *d)
>>> +{
>>> +    msf2_spi_do_reset(MSF2_SPI(d));
>>> +}
>>> +
>>> +static uint64_t
>>> +spi_read(void *opaque, hwaddr addr, unsigned int size)
>>> +{
>>> +    MSF2SpiState *s = opaque;
>>> +    uint32_t ret = 0;
>>> +
>>> +    addr >>= 2;
>>> +    switch (addr) {
>>> +    case R_SPI_RX:
>>> +        s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
>>> +        s->regs[R_SPI_STATUS] &= ~RXCHOVRF;
>>> +        ret = fifo32_pop(&s->rx_fifo);
>>> +        if (fifo32_is_empty(&s->rx_fifo)) {
>>> +            s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
>>> +        }
>>> +        break;
>>> +
>>> +    case R_SPI_MIS:
>>> +        update_mis(s);
>>> +        ret = s->regs[R_SPI_MIS];
>>> +        break;
>>> +
>>> +    default:
>>> +        if (addr < ARRAY_SIZE(s->regs)) {
>>> +            ret = s->regs[addr];
>>> +        } else {
>>> +            qemu_log_mask(LOG_GUEST_ERROR,
>>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
>>> +                         addr * 4);
>>>
>>
>> Drop '\n' while calling qemu_log_mask().
>
> Ok.
>
>>
>>
>> +        }
>>> +        break;
>>> +    }
>>> +
>>> +    DB_PRINT("addr=0x%" HWADDR_PRIx " = 0x%" PRIx32 "\n", addr * 4, ret);
>>> +    spi_update_irq(s);
>>> +    return ret;
>>> +}
>>> +
>>> +static void assert_cs(MSF2SpiState *s)
>>> +{
>>> +    qemu_set_irq(s->cs_line, 0);
>>> +}
>>> +
>>> +static void deassert_cs(MSF2SpiState *s)
>>> +{
>>> +    qemu_set_irq(s->cs_line, 1);
>>> +}
>>> +
>>> +static void spi_flush_txfifo(MSF2SpiState *s)
>>> +{
>>> +    uint32_t tx;
>>> +    uint32_t rx;
>>> +    bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS);
>>> +
>>> +    /*
>>> +     * Chip Select(CS) is automatically controlled by this controller.
>>> +     * If SPS bit is set in Control register then CS is asserted
>>> +     * until all the frames set in frame count of Control register are
>>> +     * transferred. If SPS is not set then CS pulses between frames.
>>> +     * Note that Slave Select register specifies which of the CS line
>>> +     * has to be controlled automatically by controller. Bits SS[7:1]
>>> are for
>>> +     * masters in FPGA fabric since we model only Microcontroller
>>> subsystem
>>> +     * of Smartfusion2 we control only one CS(SS[0]) line.
>>> +     */
>>> +    while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) {
>>> +        assert_cs(s);
>>> +
>>> +        s->regs[R_SPI_STATUS] &= ~TXDONE;
>>> +        s->regs[R_SPI_STATUS] &= ~RXRDY;
>>> +
>>> +        tx = fifo32_pop(&s->tx_fifo);
>>> +        DB_PRINT("data tx:0x%" PRIx32 "\n", tx);
>>> +        rx = ssi_transfer(s->spi, tx);
>>> +        DB_PRINT("data rx:0x%" PRIx32 "\n", rx);
>>> +
>>> +        if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
>>> +            s->regs[R_SPI_STATUS] |= RXCHOVRF;
>>> +            s->regs[R_SPI_RIS] |= RXCHOVRF;
>>> +        } else {
>>> +            fifo32_push(&s->rx_fifo, rx);
>>> +            s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP;
>>> +            if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) {
>>> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT;
>>> +            }
>>> +            if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) {
>>> +                s->regs[R_SPI_STATUS] |= S_RXFIFOFUL;
>>> +            }
>>> +        }
>>> +        s->frame_count--;
>>> +        if (!sps) {
>>> +            deassert_cs(s);
>>> +            assert_cs(s);
>>> +        }
>>> +    }
>>> +
>>> +    if (!sps) {
>>> +        deassert_cs(s);
>>> +    }
>>> +
>>> +    if (!s->frame_count) {
>>> +        s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >>
>>> +                            FMCOUNT_SHIFT;
>>> +        if (sps) {
>>> +            deassert_cs(s);
>>> +        }
>>> +        s->regs[R_SPI_RIS] |= TXDONE;
>>> +        s->regs[R_SPI_RIS] |= RXRDY;
>>> +        s->regs[R_SPI_STATUS] |= TXDONE;
>>> +        s->regs[R_SPI_STATUS] |= RXRDY;
>>> +   }
>>> +}
>>> +
>>> +static void spi_write(void *opaque, hwaddr addr,
>>> +            uint64_t val64, unsigned int size)
>>> +{
>>> +    MSF2SpiState *s = opaque;
>>> +    uint32_t value = val64;
>>> +
>>> +    DB_PRINT("addr=0x%" HWADDR_PRIx " =0x%" PRIx32 "\n", addr, value);
>>> +    addr >>= 2;
>>> +
>>> +    switch (addr) {
>>> +    case R_SPI_TX:
>>> +        /* adding to already full FIFO */
>>> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
>>> +            break;
>>> +        }
>>> +        s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP;
>>> +        fifo32_push(&s->tx_fifo, value);
>>> +        if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) {
>>> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT;
>>> +        }
>>> +        if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) {
>>> +            s->regs[R_SPI_STATUS] |= S_TXFIFOFUL;
>>> +        }
>>> +        if (s->enabled) {
>>> +            spi_flush_txfifo(s);
>>> +        }
>>> +        break;
>>> +
>>> +    case R_SPI_CONTROL:
>>> +        s->regs[R_SPI_CONTROL] = value;
>>> +        if (value & C_BIGFIFO) {
>>> +            set_fifodepth(s);
>>> +        } else {
>>> +            s->fifo_depth = 4;
>>> +        }
>>> +        if (value & C_ENABLE) {
>>> +            s->enabled = true;
>>> +        } else {
>>> +            s->enabled = false;
>>> +        }
>>> +        s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT;
>>> +        if (value & C_RESET) {
>>> +            msf2_spi_do_reset(s);
>>> +        }
>>> +        break;
>>> +
>>> +    case R_SPI_DFSIZE:
>>> +        if (s->enabled) {
>>> +            break;
>>> +        }
>>> +        s->regs[R_SPI_DFSIZE] = value;
>>> +        break;
>>> +
>>> +    case R_SPI_INTCLR:
>>> +        s->regs[R_SPI_INTCLR] = value;
>>> +        if (value & TXDONE) {
>>> +            s->regs[R_SPI_RIS] &= ~TXDONE;
>>> +        }
>>> +        if (value & RXRDY) {
>>> +            s->regs[R_SPI_RIS] &= ~RXRDY;
>>> +        }
>>> +        if (value & RXCHOVRF) {
>>> +            s->regs[R_SPI_RIS] &= ~RXCHOVRF;
>>> +        }
>>> +        break;
>>> +
>>> +    case R_SPI_MIS:
>>> +    case R_SPI_STATUS:
>>> +    case R_SPI_RIS:
>>> +        break;
>>> +
>>> +    default:
>>> +        if (addr < ARRAY_SIZE(s->regs)) {
>>> +            s->regs[addr] = value;
>>> +        } else {
>>> +            qemu_log_mask(LOG_GUEST_ERROR,
>>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__,
>>> +                         addr * 4);
>>> +        }
>>> +        break;
>>> +    }
>>> +
>>> +    spi_update_irq(s);
>>> +}
>>> +
>>> +static const MemoryRegionOps spi_ops = {
>>> +    .read = spi_read,
>>> +    .write = spi_write,
>>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>>> +    .valid = {
>>> +        .min_access_size = 4,
>>> +        .max_access_size = 4
>>> +    }
>>> +};
>>> +
>>> +static void msf2_spi_realize(DeviceState *dev, Error **errp)
>>> +{
>>> +    MSF2SpiState *s = MSF2_SPI(dev);
>>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>> +
>>> +    DB_PRINT("\n");
>>> +
>>> +    s->spi = ssi_create_bus(dev, "spi0");
>>> +
>>> +    sysbus_init_irq(sbd, &s->irq);
>>> +    ssi_auto_connect_slaves(dev, &s->cs_line, s->spi);
>>> +    sysbus_init_irq(sbd, &s->cs_line);
>>> +
>>> +    memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
>>> +                          TYPE_MSF2_SPI, R_SPI_MAX * 4);
>>> +    sysbus_init_mmio(sbd, &s->mmio);
>>> +
>>> +    fifo32_create(&s->tx_fifo, FIFO_CAPACITY);
>>> +    fifo32_create(&s->rx_fifo, FIFO_CAPACITY);
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_msf2_spi = {
>>> +    .name = TYPE_MSF2_SPI,
>>> +    .version_id = 1,
>>> +    .minimum_version_id = 1,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_FIFO32(tx_fifo, MSF2SpiState),
>>> +        VMSTATE_FIFO32(rx_fifo, MSF2SpiState),
>>> +        VMSTATE_UINT32_ARRAY(regs, MSF2SpiState, R_SPI_MAX),
>>> +        VMSTATE_END_OF_LIST()
>>> +    }
>>> +};
>>> +
>>> +static void msf2_spi_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +
>>> +    dc->realize = msf2_spi_realize;
>>> +    dc->reset = msf2_spi_reset;
>>> +    dc->vmsd = &vmstate_msf2_spi;
>>> +}
>>> +
>>> +static const TypeInfo msf2_spi_info = {
>>> +    .name           = TYPE_MSF2_SPI,
>>> +    .parent         = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size  = sizeof(MSF2SpiState),
>>> +    .class_init     = msf2_spi_class_init,
>>> +};
>>> +
>>> +static void msf2_spi_register_types(void)
>>> +{
>>> +    type_register_static(&msf2_spi_info);
>>> +}
>>> +
>>> +type_init(msf2_spi_register_types)
>>> diff --git a/include/hw/ssi/msf2-spi.h b/include/hw/ssi/msf2-spi.h
>>> new file mode 100644
>>> index 0000000..585edde
>>> --- /dev/null
>>> +++ b/include/hw/ssi/msf2-spi.h
>>> @@ -0,0 +1,105 @@
>>> +/*
>>> + * Microsemi SmartFusion2 SPI
>>> + *
>>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining
>>> a copy
>>> + * of this software and associated documentation files (the "Software"),
>>> to deal
>>> + * in the Software without restriction, including without limitation the
>>> rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>>> sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be
>>> included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>>> EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>>> MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>>> SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>>> OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>>> ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>>> DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#ifndef HW_MSF2_SPI_H
>>> +#define HW_MSF2_SPI_H
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "hw/sysbus.h"
>>> +#include "hw/hw.h"
>>> +#include "hw/ssi/ssi.h"
>>> +#include "qemu/fifo32.h"
>>> +#include "sysemu/sysemu.h"
>>> +#include "qemu/log.h"
>>> +
>>> +#define FIFO_CAPACITY     32
>>> +#define FIFO_CAPACITY     32
>>> +
>>> +#define R_SPI_CONTROL         0
>>> +#define R_SPI_DFSIZE          1
>>> +#define R_SPI_STATUS          2
>>> +#define R_SPI_INTCLR          3
>>> +#define R_SPI_RX              4
>>> +#define R_SPI_TX              5
>>> +#define R_SPI_CLKGEN          6
>>> +#define R_SPI_SS              7
>>> +#define R_SPI_MIS             8
>>> +#define R_SPI_RIS             9
>>> +#define R_SPI_STAT8           15
>>> +#define R_SPI_MAX             16
>>> +
>>> +#define S_RXFIFOFUL       (1 << 4)
>>> +#define S_RXFIFOFULNXT    (1 << 5)
>>> +#define S_RXFIFOEMP       (1 << 6)
>>> +#define S_RXFIFOEMPNXT    (1 << 7)
>>> +#define S_TXFIFOFUL       (1 << 8)
>>> +#define S_TXFIFOFULNXT    (1 << 9)
>>> +#define S_TXFIFOEMP       (1 << 10)
>>> +#define S_TXFIFOEMPNXT    (1 << 11)
>>> +#define S_FRAMESTART      (1 << 12)
>>> +#define S_SSEL            (1 << 13)
>>> +#define S_ACTIVE          (1 << 14)
>>> +
>>> +#define C_ENABLE          (1 << 0)
>>> +#define C_MODE            (1 << 1)
>>> +#define C_INTRXDATA       (1 << 4)
>>> +#define C_INTTXDATA       (1 << 5)
>>> +#define C_INTRXOVRFLO     (1 << 6)
>>> +#define C_SPS             (1 << 26)
>>> +#define C_BIGFIFO         (1 << 29)
>>> +#define C_RESET           (1 << 31)
>>> +
>>> +#define FRAMESZ_MASK      0x1F
>>> +#define FMCOUNT_MASK      0x00FFFF00
>>> +#define FMCOUNT_SHIFT     8
>>> +
>>> +#define TXDONE            (1 << 0)
>>> +#define RXRDY             (1 << 1)
>>> +#define RXCHOVRF          (1 << 2)
>>> +
>>> +#define TYPE_MSF2_SPI   "msf2-spi"
>>> +#define MSF2_SPI(obj)   OBJECT_CHECK(MSF2SpiState, (obj), TYPE_MSF2_SPI)
>>> +
>>> +typedef struct MSF2SpiState {
>>> +    SysBusDevice parent_obj;
>>> +
>>> +    MemoryRegion mmio;
>>> +
>>> +    qemu_irq irq;
>>> +
>>> +    qemu_irq cs_line;
>>> +
>>> +    SSIBus *spi;
>>> +
>>> +    Fifo32 rx_fifo;
>>> +    Fifo32 tx_fifo;
>>> +
>>> +    int fifo_depth;
>>> +    uint32_t frame_count;
>>> +    bool enabled;
>>> +
>>> +    uint32_t regs[R_SPI_MAX];
>>> +} MSF2SpiState;
>>> +
>>> +#endif /* HW_MSF2_SPI_H */
>>>
>>>
>> Regards,
>>
>> Phil.
>>
> Thanks,
> Sundeep
>

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

* Re: [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block.
  2017-05-12  3:48     ` sundeep subbaraya
@ 2017-05-12  4:12       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-12  4:12 UTC (permalink / raw)
  To: sundeep subbaraya
  Cc: Peter Maydell, Peter Crosthwaite, qemu-arm, QEMU Developers,
	Alistair Francis

On 05/12/2017 12:48 AM, sundeep subbaraya wrote:
> Hi Phiilippe,
>
> On Wed, May 10, 2017 at 4:04 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
> wrote:
>
>> Hi Subbaraya,
>>
>>
>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>
>>> Added Sytem register block of Smartfusion2.
>>> This block has PLL registers which are accessed by guest.
>>>
>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> ---
>>>  hw/misc/Makefile.objs         |   1 +
>>>  hw/misc/msf2-sysreg.c         | 131 ++++++++++++++++++++++++++++++
>>> ++++++++++++
>>>  include/hw/misc/msf2-sysreg.h |  80 ++++++++++++++++++++++++++
>>>  3 files changed, 212 insertions(+)
>>>  create mode 100644 hw/misc/msf2-sysreg.c
>>>  create mode 100644 include/hw/misc/msf2-sysreg.h
>>>
>>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>>> index c8b4893..0f52354 100644
>>> --- a/hw/misc/Makefile.objs
>>> +++ b/hw/misc/Makefile.objs
>>> @@ -56,3 +56,4 @@ obj-$(CONFIG_EDU) += edu.o
>>>  obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
>>>  obj-$(CONFIG_AUX) += auxbus.o
>>>  obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
>>> +obj-$(CONFIG_MSF2) += msf2-sysreg.o
>>> diff --git a/hw/misc/msf2-sysreg.c b/hw/misc/msf2-sysreg.c
>>> new file mode 100644
>>> index 0000000..53e9cba
>>> --- /dev/null
>>> +++ b/hw/misc/msf2-sysreg.c
>>> @@ -0,0 +1,131 @@
>>> +/*
>>> + * System Register block model of Microsemi SmartFusion2.
>>> + *
>>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License
>>> + * as published by the Free Software Foundation; either version
>>> + * 2 of the License, or (at your option) any later version.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> along
>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include "hw/misc/msf2-sysreg.h"
>>> +
>>> +#ifndef MSF2_SYSREG_ERR_DEBUG
>>> +#define MSF2_SYSREG_ERR_DEBUG  0
>>> +#endif
>>> +
>>> +#define DB_PRINT_L(lvl, fmt, args...) do { \
>>> +    if (MSF2_SYSREG_ERR_DEBUG >= lvl) { \
>>> +        qemu_log("%s: " fmt, __func__, ## args); \
>>> +    } \
>>> +} while (0);
>>> +
>>> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>>> +
>>> +static void msf2_sysreg_reset(DeviceState *d)
>>> +{
>>> +    MSF2SysregState *s = MSF2_SYSREG(d);
>>> +
>>> +    DB_PRINT("RESET\n");
>>> +
>>> +    s->regs[MSSDDR_PLL_STATUS_LOW_CR] = 0x02420041;
>>> +    s->regs[MSSDDR_FACC1_CR] = 0x0A482124;
>>> +    s->regs[MSSDDR_PLL_STATUS] = 0x3;
>>> +}
>>> +
>>> +static uint64_t msf2_sysreg_read(void *opaque, hwaddr offset,
>>> +    unsigned size)
>>> +{
>>> +    MSF2SysregState *s = opaque;
>>> +    offset /= 4;
>>> +    uint32_t ret = 0;
>>> +
>>> +    if (offset < ARRAY_SIZE(s->regs)) {
>>> +        ret = s->regs[offset];
>>> +        DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx32 "\n",
>>> +                    offset * 4, ret);
>>> +    } else {
>>> +        qemu_log_mask(LOG_GUEST_ERROR,
>>> +                    "%s: Bad offset 0x%08" HWADDR_PRIx "\n", __func__,
>>> +                    offset * 4);
>>> +    }
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static void msf2_sysreg_write(void *opaque, hwaddr offset,
>>> +                          uint64_t val, unsigned size)
>>> +{
>>> +    MSF2SysregState *s = (MSF2SysregState *)opaque;
>>> +    offset /= 4;
>>> +
>>> +    DB_PRINT("addr: 0x%08" HWADDR_PRIx " data: 0x%08" PRIx64 "\n",
>>> +            offset * 4, val);
>>> +
>>> +    switch (offset) {
>>> +    case MSSDDR_PLL_STATUS:
>>> +        break;
>>> +
>>> +    default:
>>> +        if (offset < ARRAY_SIZE(s->regs)) {
>>> +            s->regs[offset] = val;
>>>
>>
>> I think this is pretty unsafe for the guest to continue if those registers
>> are accessed in your current implementation.
>>
>> I'd at least somehow abort for few of them (RESET, REMAP*), what do you
>> think?
>
>
> Ok. We can abort for REMAP. All the peripherals need to be released from
> reset by writing to Sysreg.
> Can we handle that case where if guest writes to Sysreg to reset SPI(say)
> then we can reset SPI
> model from here? I am very new here and I did not come across this case in
> the models I have referred.
> Please let me know if that is possible. If not possible I would simply log
> messages like released
> from reset/put in reset.

You are lucky if you didn't have to use the remap register :)
This can be implemented later if needed, don't get lost there now!

On Cold Reset the SF2 starts with the Cache Matrix mapping the CM3 code 
region (anything below 0x2000.0000) to the eNVM (which is physically 
mapped at 0x6000.0000). Now if you write to the REMAP reg you can 
instead map the eSRAM or the DDR space to the CM3 code, and the eNVM 
will only be accessible at 0x6000.0000. For the cpu the execution 
depends of the code stored at the mapped region.

If there is enough space to run your code in the eNVM, don't worry about 
modeling a remap. But now anyone can try your model, and if their 
firmware do a remap, the code flow will be completely wrong.
I think just reporting a GUEST_ERROR here is not enough since code flow 
continuing would be pretty hard to understand/debug. That's why I 
suggest to report an error and abort for now.

>
> Thanks,
> Sundeep
>
>>
>>
>> +        } else {
>>> +            qemu_log_mask(LOG_GUEST_ERROR,
>>> +                        "%s: Bad offset 0x%08" HWADDR_PRIx "\n",
>>> __func__,
>>> +                        offset * 4);
>>> +        }
>>> +        break;
>>> +    }
>>> +}
>>> +
>>> +static const MemoryRegionOps sysreg_ops = {
>>> +    .read = msf2_sysreg_read,
>>> +    .write = msf2_sysreg_write,
>>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>>> +};
>>> +
>>> +static void msf2_sysreg_init(Object *obj)
>>> +{
>>> +    MSF2SysregState *s = MSF2_SYSREG(obj);
>>> +
>>> +    memory_region_init_io(&s->iomem, obj, &sysreg_ops, s,
>>> TYPE_MSF2_SYSREG,
>>> +                          MSF2_SYSREG_MMIO_SIZE);
>>> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_msf2_sysreg = {
>>> +    .name = TYPE_MSF2_SYSREG,
>>> +    .version_id = 1,
>>> +    .minimum_version_id = 1,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_UINT32_ARRAY(regs, MSF2SysregState,
>>> MSF2_SYSREG_NUM_REGS),
>>> +        VMSTATE_END_OF_LIST()
>>> +    }
>>> +};
>>> +
>>> +static void msf2_sysreg_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +
>>> +    dc->vmsd = &vmstate_msf2_sysreg;
>>> +    dc->reset = msf2_sysreg_reset;
>>> +}
>>> +
>>> +static const TypeInfo msf2_sysreg_info = {
>>> +    .name  = TYPE_MSF2_SYSREG,
>>> +    .parent = TYPE_SYS_BUS_DEVICE,
>>> +    .class_init = msf2_sysreg_class_init,
>>> +    .instance_size  = sizeof(MSF2SysregState),
>>> +    .instance_init = msf2_sysreg_init,
>>> +};
>>> +
>>> +static void msf2_sysreg_register_types(void)
>>> +{
>>> +    type_register_static(&msf2_sysreg_info);
>>> +}
>>> +
>>> +type_init(msf2_sysreg_register_types)
>>> diff --git a/include/hw/misc/msf2-sysreg.h b/include/hw/misc/msf2-sysreg.
>>> h
>>> new file mode 100644
>>> index 0000000..a485ed6
>>> --- /dev/null
>>> +++ b/include/hw/misc/msf2-sysreg.h
>>> @@ -0,0 +1,80 @@
>>> +/*
>>> + * Microsemi SmartFusion2 SYSREG
>>> + *
>>> + * Copyright (c) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining
>>> a copy
>>> + * of this software and associated documentation files (the "Software"),
>>> to deal
>>> + * in the Software without restriction, including without limitation the
>>> rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>>> sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be
>>> included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>>> EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>>> MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>>> SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>>> OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>>> ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>>> DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#ifndef HW_MSF2_SYSREG_H
>>> +#define HW_MSF2_SYSREG_H
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "hw/sysbus.h"
>>> +#include "hw/hw.h"
>>> +#include "sysemu/sysemu.h"
>>> +#include "qemu/log.h"
>>> +
>>> +enum {
>>> +    ESRAM_CR        = 0x00 / 4,
>>> +    ESRAM_MAX_LAT,
>>> +    DDR_CR,
>>> +    ENVM_CR,
>>> +    ENVM_REMAP_BASE_CR,
>>> +    ENVM_REMAP_FAB_CR,
>>> +    CC_CR,
>>> +    CC_REGION_CR,
>>> +    CC_LOCK_BASE_ADDR_CR,
>>> +    CC_FLUSH_INDX_CR,
>>> +    DDRB_BUF_TIMER_CR,
>>> +    DDRB_NB_ADDR_CR,
>>> +    DDRB_NB_SIZE_CR,
>>> +    DDRB_CR,
>>> +
>>> +    SOFT_RESET_CR  = 0x48 / 4,
>>> +    M3_CR,
>>> +
>>> +    GPIO_SYSRESET_SEL_CR = 0x58 / 4,
>>> +
>>> +    MDDR_CR = 0x60 / 4,
>>> +
>>> +    MSSDDR_PLL_STATUS_LOW_CR = 0x90 / 4,
>>> +    MSSDDR_PLL_STATUS_HIGH_CR,
>>> +    MSSDDR_FACC1_CR,
>>> +    MSSDDR_FACC2_CR,
>>> +
>>> +    MSSDDR_PLL_STATUS = 0x150 / 4,
>>> +
>>> +};
>>> +
>>> +#define MSF2_SYSREG_MMIO_SIZE     0x300
>>> +#define MSF2_SYSREG_NUM_REGS      (MSF2_SYSREG_MMIO_SIZE / 4)
>>> +
>>> +#define TYPE_MSF2_SYSREG          "msf2-sysreg"
>>> +#define MSF2_SYSREG(obj)  OBJECT_CHECK(MSF2SysregState, (obj),
>>> TYPE_MSF2_SYSREG)
>>> +
>>> +typedef struct MSF2SysregState {
>>> +    SysBusDevice parent_obj;
>>> +
>>> +    MemoryRegion iomem;
>>> +
>>> +    uint32_t regs[MSF2_SYSREG_NUM_REGS];
>>> +} MSF2SysregState;
>>> +
>>> +#endif /* HW_MSF2_SYSREG_H */
>>>
>>>

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-10 12:37     ` sundeep subbaraya
@ 2017-05-12  4:38       ` Philippe Mathieu-Daudé
  2017-05-12  5:16         ` sundeep subbaraya
  0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-12  4:38 UTC (permalink / raw)
  To: sundeep subbaraya
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis

On 05/10/2017 09:37 AM, sundeep subbaraya wrote:
> Hi Phil,
>
> On Wed, May 10, 2017 at 3:11 PM, Philippe Mathieu-Daudé <f4bug@amsat.org
> <mailto:f4bug@amsat.org>> wrote:
>> Hi Subbaraya, nice work!
>>
>> The timer you are modeling is the mss_timer, which is in particular
> used in
>> the smartfusion2, I'd rather name it mss_timer.c so it can be reused by
>> other SoC models.
>>
> Ok I will change all other file names also to mss. Do I need to change
> type names
> also to mss?

As you wish :) Actel/Microsemi keep changing how they name it, MSS, 
M2S... What I mean is this timer is valid for a Actel SmartFusion and 
for the MicroSemi SmartFusion2, naming it "msf2-timer" seems to restrict 
it to the SF2 only.

>> I added few comments.
>>
>>
>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>>
>>> Modelled System Timer in Microsemi's Smartfusion2 Soc.
>>> Timer has two 32bit down counters and two interrupts.
>>>
>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com
> <mailto:sundeep.lkml@gmail.com>>
>>> ---
>>>  hw/timer/Makefile.objs        |   1 +
>>>  hw/timer/msf2-timer.c         | 252
>>> ++++++++++++++++++++++++++++++++++++++++++
>>>  include/hw/timer/msf2-timer.h |  85 ++++++++++++++
>>>  3 files changed, 338 insertions(+)
>>>  create mode 100644 hw/timer/msf2-timer.c
>>>  create mode 100644 include/hw/timer/msf2-timer.h
>>>
[...]
>>> +        if (addr < ARRAY_SIZE(st->regs)) {
>>> +            st->regs[addr] = value;
>>> +        } else {
>>> +            qemu_log_mask(LOG_GUEST_ERROR,
>>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n",
> __func__,
>>> +                         addr * 4);
>>> +        }
>>> +        break;
>>> +    }
>>> +    timer_update_irq(st);
>>
>>
>> Here if addr >= (NUM_TIMERS * R_TIM1_MAX) you still update Timer1 IRQ,
> while
>> this is unharmful right now this is likely to be break later.
>>
> As long as Interrupt status register and Interrupt enable register are not
> modified calling timer_update_irq will not harm. Am I missing something
> here?

Indeed, this is unharmful. It just surprised me when I follow the 
control flow.

>>> +}
>>> +
>>> +static const MemoryRegionOps timer_ops = {
>>> +    .read = timer_read,
>>> +    .write = timer_write,
>>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>>> +    .valid = {
>>> +        .min_access_size = 4,
>>
>>
>> I believe min_access_size = 1 is valid for any APB device.
>>
>>
> Ok. I followed Xilinx soft IP models while writing this. I am really not
> sure it is mandatory to put access_size. Can i remove it?

checking the datasheet "UG0331: SmartFusion2 Microcontroller Subsystem":

'''
CMSIS Data types:

The [Cortex-M3] processor:
* supports the following data types:
- 32-bit words
- 16-bit halfwords
- 8-bit bytes.
* manages all data memory accesses as little-endian or big-endian. 
Instruction memory and Private Peripheral Bus (PPB) accesses are always 
performed as little-endian. The Cortex-M3 processor configured for 
SmartFusion2 SoC FPGA MSS uses only little-endian.
'''

So Yes, ".min_access_size = 1" is correct for this Cortex-M3.

If you remove it memory_region_access_valid() will do:

     access_size_min = mr->ops->valid.min_access_size;
     if (!mr->ops->valid.min_access_size) {
         access_size_min = 1;
     }

So that is the same, personally I prefer it to be explicit (not removed).

>>> +        .max_access_size = 4
>>> +    }
>>> +};
>>> +
>>> +static void timer_hit(void *opaque)
>>> +{
>>> +    struct Msf2Timer *st = opaque;
>>> +
>>> +    st->regs[R_TIM_RIS] |= TIMER_RIS_ACK;
>>> +
>>> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ONESHOT)) {
>>> +        timer_update(st);
>>> +    }
>>> +    timer_update_irq(st);
>>> +}
[...]
>>> +/*
>>> + * There are two 32-bit down counting timers.
>>> + * Timers 1 and 2 can be concatenated into a single 64-bit Timer
>>> + * that operates either in Periodic mode or in One-shot mode.
>>> + * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit
>>> mode.
>>> + * In 64-bit mode, writing to the 32-bit registers has no effect.
>>> + * Similarly, in 32-bit mode, writing to the 64-bit mode registers
>>> + * has no effect. Only two 32-bit timers are supported currently.
>>> + */
>>> +#define NUM_TIMERS        2
>>> +
>>> +#define MSF2_TIMER_FREQ   (83 * 1000000)
>>
>>
>> I can not find this value, can you point me to the datasheet? It seems SoC
>> specific to me.
>>
> It is configured in Microsemi Libero. The SOM kit from Emcraft comes
> with this default setting.
> I guess this property should be set and passed from board file and not
> from SoC.
> Am I correct?

It seems an option configurable in Libero before synthesizing, so that 
would be SoM/bitfile specific?

What I mean here is I don't think this is a fixed value for a mss_timer 
and I'd rather have it configurable (but ok to default 83MHz in your SoM).

 > Can I attach the datasheet to this thread?

Isn't this datasheet publicly available?

Eventually can you upload a binary (like your Linux patches) somewhere? 
So it would be easier to test this patchset.

> Thank you,
> Sundeep

Good luck!

Phil.

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

* Re: [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-12  3:17     ` sundeep subbaraya
@ 2017-05-12  5:02       ` Philippe Mathieu-Daudé
  2017-05-15 16:54         ` Alistair Francis
  0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-12  5:02 UTC (permalink / raw)
  To: sundeep subbaraya, Peter Maydell, QEMU Developers, Alistair Francis
  Cc: Peter Crosthwaite, qemu-arm

On 05/12/2017 12:17 AM, sundeep subbaraya wrote:
> Hi Philippe,
>
> On Wed, May 10, 2017 at 5:20 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
> wrote:
>
>> Hi Subbaraya,
>>
>>
>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>
>>> Smartfusion2 SoC has hardened Microcontroller subsystem
>>> and flash based FPGA fabric. This patch adds support for
>>> Microcontroller subsystem in the SoC.
>>>
>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>> ---
>>>  default-configs/arm-softmmu.mak |   1 +
>>>  hw/arm/Makefile.objs            |   2 +-
>>>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++
>>> ++++++++++
>>>  include/hw/arm/msf2-soc.h       |  60 +++++++++++++
>>>  4 files changed, 250 insertions(+), 1 deletion(-)
>>>  create mode 100644 hw/arm/msf2-soc.c
>>>  create mode 100644 include/hw/arm/msf2-soc.h
>>>
>>> diff --git a/default-configs/arm-softmmu.mak
>>> b/default-configs/arm-softmmu.mak
>>> index 78d7af0..7062512 100644
>>> --- a/default-configs/arm-softmmu.mak
>>> +++ b/default-configs/arm-softmmu.mak
>>> @@ -122,3 +122,4 @@ CONFIG_ACPI=y
>>>  CONFIG_SMBIOS=y
>>>  CONFIG_ASPEED_SOC=y
>>>  CONFIG_GPIO_KEY=y
>>> +CONFIG_MSF2=y
>>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>>> index 4c5c4ee..ae5e4a3 100644
>>> --- a/hw/arm/Makefile.objs
>>> +++ b/hw/arm/Makefile.objs
>>> @@ -1,7 +1,7 @@
>>>  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
>>>  obj-$(CONFIG_DIGIC) += digic_boards.o
>>>  obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
>>> -obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
>>> +obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
>>>
>>
>> Not a big deal, but since you added CONFIG_MSF2 why not using it here and
>> the Makefiles you touched (misc/ssi/timer)?
>>
>> obj-$(CONFIG_MSF2) += msf2-soc.o
>>
>>   OK. Will change it.
>
>>
>>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
>>>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
>>>  obj-y += netduino2.o
[...]
>>> +    MemoryRegion *system_memory = get_system_memory();
>>> +    MemoryRegion *nvm = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *ddr = g_new(MemoryRegion, 1);
>>> +
>>> +    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
>>> +                           &error_fatal);
>>>
>>
>> Maybe you can name it "eNVM" to match the documentation.
>>
>> Also envm_size should be a per-model property.
>>
>
> Ok.
>
>>
>> +    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
>>> +                             nvm, 0, ENVM_SIZE);
>>>
>>
>> Hmmm well this would be the "Cache Matrix Remap" which happens to be
>> mapped by default to eNVM on cold reset.
>> Naming it "MSF2.flash.alias" is pretty confusing.
>>
>
> Exactly it is Cache Matrix Remap.
> AFAIK currently we cannot remap memory during runtime in Qemu.
> So I handled default remap with alias.
> Please suggest the name. MSF2.eNVM.alias sounds fine?

Hmm Peter, Francis?

Personally I prefer "bus_remap.alias" which is explicit.

"eNVM.alias" is only true on Cold Reset.

>>
>> +    vmstate_register_ram_global(nvm);
>>> +
>>> +    memory_region_set_readonly(nvm, true);
>>> +    memory_region_set_readonly(nvm_alias, true);
>>> +
>>> +    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
>>> +    memory_region_add_subregion(system_memory, 0, nvm_alias);
>>> +
>>> +    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
>>> +                           &error_fatal);
>>>
>>
>> Wrong, there is no DDR on this SoC.
>>
> DDR controller is there in Smartfusion2 (different from Smartfusion). As
> you said below this
> should be in board file.

There IS a DDRC in this SoC, but here you are registering a DDR 'ram' 
memory region, not a controller. This SoC can be used without any DDR, 
enough using embedded eNVM and eSRAM.

Now it happens your SoM board provides a DDR chip connected to this SoC.

>>
>> +    vmstate_register_ram_global(ddr);
>>> +    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS, ddr);
>>> +
>>> +    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
>>> +                           &error_fatal);
>>>
>>
>> I'd rather like to see it named "eSRAM" somehow, so there is no confusion
>> possible with external SRAM a SoM/board can map at 0x60000000.
>>
>> Same comment than envm_size, sram_size should be a per-model property.
>>
>> OK
>
>> +    vmstate_register_ram_global(sram);
>>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
>>> +
>>> +    armv7m = DEVICE(&s->armv7m);
>>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
>>>
>>
>> Can you point me to your datasheet? I thought the SF2 had 240 IRQs.
>
>
> Please go to link:
> https://www.microsemi.com/document-portal/search_form
> and provide search keyword as "UG0331". You can the download the spec.
> It has 81 irqs I remember when I have given 81 qemu complained not multiple
> of 4.
> I checked again with 81 and it is fine. I will change it to 81.

Ok :)

> +    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
>>> +    object_property_set_link(OBJECT(&s->armv7m),
>>> OBJECT(get_system_memory()),
>>> +                                     "memory", &error_abort);
[...]
>>> +#define MSF2_NUM_SPIS         2
>>> +#define MSF2_NUM_UARTS        2
>>> +
>>> +#define ENVM_BASE_ADDRESS     0x60000000
>>> +#define ENVM_SIZE             (128 * 1024)
>>>
>>
>> The SoC design ENVM_SIZE is 1MB, 128K seems your particular model.
>>
>
>  M2S010 SoC device has 256K eNMV. My bad it should be 256 instead of 128.
>  The board I have contains M2S010 device in SOM.
>

What I mean here is on the SF2 the eNVM "region size" (as seen by the 
AHB Bus) is 1MB. Now your SoC M2S010 provides 256KB in this dedicated 1M 
region.

I find your #define confusing, what about:

#define ENVM_REGION_SIZE      (1 * M_BYTE)
#define M2S010_ENVM_SIZE      (256 * K_BYTE)

(?_BYTE from "qemu/cutils.h")

I wanted to clarify this because you named your functions as it can 
models any SF2 but actually you restrict it to your M2S010.

Maybe to start you can rename msf2_soc_x() -> m2s010_sf2_soc_x() then if 
needed this can be generalized to other SoCs from SF2 family?

>> +
>>> +#define DDR_BASE_ADDRESS      0xA0000000
>>> +#define DDR_SIZE              (64 * 1024 * 1024)
>>>
>>
>> This belongs to the SoM.
>> Yes will change it.
>>
>>> +
>>> +#define SRAM_BASE_ADDRESS     0x20000000
>>> +#define SRAM_SIZE             (64 * 1024)
>>>
>>
>> Indeed this SoC is designed to have up to 64K of SRAM.
>> Luckily your model provides 64K.
>>
>
>
> Yes it is 64k :)
>

Same here, what you have is:

#define ESRAM_REGION_SIZE     (64 * K_BYTE)
#define M2S010_ESRAM_SIZE     (64 * K_BYTE)

which happens to be equal but does not mean the same, do you see the 
difference?

> +
>>> +typedef struct MSF2State {
>>> +    /*< private >*/
>>> +    SysBusDevice parent_obj;
>>> +    /*< public >*/
>>> +
>>> +    ARMv7MState armv7m;
>>> +
>>> +    MSF2SysregState sysreg;
>>> +    MSF2TimerState timer;
>>> +    MSF2SpiState spi[MSF2_NUM_SPIS];
>>> +} MSF2State;
>>> +
>>> +#endif

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-12  4:38       ` Philippe Mathieu-Daudé
@ 2017-05-12  5:16         ` sundeep subbaraya
  0 siblings, 0 replies; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-12  5:16 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis

Hi Philippe,

On Fri, May 12, 2017 at 10:08 AM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> On 05/10/2017 09:37 AM, sundeep subbaraya wrote:
>
>> Hi Phil,
>>
>> On Wed, May 10, 2017 at 3:11 PM, Philippe Mathieu-Daudé <f4bug@amsat.org
>> <mailto:f4bug@amsat.org>> wrote:
>>
>>> Hi Subbaraya, nice work!
>>>
>>> The timer you are modeling is the mss_timer, which is in particular
>>>
>> used in
>>
>>> the smartfusion2, I'd rather name it mss_timer.c so it can be reused by
>>> other SoC models.
>>>
>>> Ok I will change all other file names also to mss. Do I need to change
>> type names
>> also to mss?
>>
>
> As you wish :) Actel/Microsemi keep changing how they name it, MSS, M2S...
> What I mean is this timer is valid for a Actel SmartFusion and for the
> MicroSemi SmartFusion2, naming it "msf2-timer" seems to restrict it to the
> SF2 only.
>
> Hmm. OK I will change to mss except for SoC model,file and SOM file.

> I added few comments.
>>>
>>>
>>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>>
>>>>
>>>> Modelled System Timer in Microsemi's Smartfusion2 Soc.
>>>> Timer has two 32bit down counters and two interrupts.
>>>>
>>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com
>>>>
>>> <mailto:sundeep.lkml@gmail.com>>
>>
>>> ---
>>>>  hw/timer/Makefile.objs        |   1 +
>>>>  hw/timer/msf2-timer.c         | 252
>>>> ++++++++++++++++++++++++++++++++++++++++++
>>>>  include/hw/timer/msf2-timer.h |  85 ++++++++++++++
>>>>  3 files changed, 338 insertions(+)
>>>>  create mode 100644 hw/timer/msf2-timer.c
>>>>  create mode 100644 include/hw/timer/msf2-timer.h
>>>>
>>>> [...]
>
>> +        if (addr < ARRAY_SIZE(st->regs)) {
>>>> +            st->regs[addr] = value;
>>>> +        } else {
>>>> +            qemu_log_mask(LOG_GUEST_ERROR,
>>>> +                         "%s: Bad offset 0x%" HWADDR_PRIx "\n",
>>>>
>>> __func__,
>>
>>> +                         addr * 4);
>>>> +        }
>>>> +        break;
>>>> +    }
>>>> +    timer_update_irq(st);
>>>>
>>>
>>>
>>> Here if addr >= (NUM_TIMERS * R_TIM1_MAX) you still update Timer1 IRQ,
>>>
>> while
>>
>>> this is unharmful right now this is likely to be break later.
>>>
>>> As long as Interrupt status register and Interrupt enable register are
>> not
>> modified calling timer_update_irq will not harm. Am I missing something
>> here?
>>
>
> Indeed, this is unharmful. It just surprised me when I follow the control
> flow.

Ok I will change it.

>
>
> +}
>>>> +
>>>> +static const MemoryRegionOps timer_ops = {
>>>> +    .read = timer_read,
>>>> +    .write = timer_write,
>>>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>>>> +    .valid = {
>>>> +        .min_access_size = 4,
>>>>
>>>
>>>
>>> I believe min_access_size = 1 is valid for any APB device.
>>>
>>>
>>> Ok. I followed Xilinx soft IP models while writing this. I am really not
>> sure it is mandatory to put access_size. Can i remove it?
>>
>
> checking the datasheet "UG0331: SmartFusion2 Microcontroller Subsystem":
>
> '''
> CMSIS Data types:
>
> The [Cortex-M3] processor:
> * supports the following data types:
> - 32-bit words
> - 16-bit halfwords
> - 8-bit bytes.
> * manages all data memory accesses as little-endian or big-endian.
> Instruction memory and Private Peripheral Bus (PPB) accesses are always
> performed as little-endian. The Cortex-M3 processor configured for
> SmartFusion2 SoC FPGA MSS uses only little-endian.
> '''
>
> So Yes, ".min_access_size = 1" is correct for this Cortex-M3.
>
> If you remove it memory_region_access_valid() will do:
>
>     access_size_min = mr->ops->valid.min_access_size;
>     if (!mr->ops->valid.min_access_size) {
>         access_size_min = 1;
>     }
>
> So that is the same, personally I prefer it to be explicit (not removed).
>
> Ok will change to 1.

> +        .max_access_size = 4
>>>> +    }
>>>> +};
>>>> +
>>>> +static void timer_hit(void *opaque)
>>>> +{
>>>> +    struct Msf2Timer *st = opaque;
>>>> +
>>>> +    st->regs[R_TIM_RIS] |= TIMER_RIS_ACK;
>>>> +
>>>> +    if (!(st->regs[R_TIM_CTRL] & TIMER_CTRL_ONESHOT)) {
>>>> +        timer_update(st);
>>>> +    }
>>>> +    timer_update_irq(st);
>>>> +}
>>>>
>>> [...]
>
>> +/*
>>>> + * There are two 32-bit down counting timers.
>>>> + * Timers 1 and 2 can be concatenated into a single 64-bit Timer
>>>> + * that operates either in Periodic mode or in One-shot mode.
>>>> + * Writing 1 to the TIM64_MODE register bit 0 sets the Timers in 64-bit
>>>> mode.
>>>> + * In 64-bit mode, writing to the 32-bit registers has no effect.
>>>> + * Similarly, in 32-bit mode, writing to the 64-bit mode registers
>>>> + * has no effect. Only two 32-bit timers are supported currently.
>>>> + */
>>>> +#define NUM_TIMERS        2
>>>> +
>>>> +#define MSF2_TIMER_FREQ   (83 * 1000000)
>>>>
>>>
>>>
>>> I can not find this value, can you point me to the datasheet? It seems
>>> SoC
>>> specific to me.
>>>
>>> It is configured in Microsemi Libero. The SOM kit from Emcraft comes
>> with this default setting.
>> I guess this property should be set and passed from board file and not
>> from SoC.
>> Am I correct?
>>
>
> It seems an option configurable in Libero before synthesizing, so that
> would be SoM/bitfile specific?
>
> What I mean here is I don't think this is a fixed value for a mss_timer
> and I'd rather have it configurable (but ok to default 83MHz in your SoM).
>
> Yeah. Same like hw/microblaze/petalogix_ml605_mmu.c where one design was
chosen for FPGA.
I have chosen the one which comes preloaded with Emcraft SOM kit.

> > Can I attach the datasheet to this thread?
>
> Isn't this datasheet publicly available?
>
> We need to download instead of direct google link. I dont know why.

Eventually can you upload a binary (like your Linux patches) somewhere? So
> it would be easier to test this patchset.
>

Sure I will put the source code and binaries in github.

>
> Thank you,
>> Sundeep
>>
>
> Good luck!
>
> Phil.
>

Thanks for taking your time to review.

Sundeep

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-10  9:41   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
  2017-05-10 12:37     ` sundeep subbaraya
@ 2017-05-15 11:52     ` Philippe Mathieu-Daudé
  2017-05-16  6:41       ` sundeep subbaraya
  1 sibling, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-15 11:52 UTC (permalink / raw)
  To: Subbaraya Sundeep, qemu-devel, qemu-arm; +Cc: peter.maydell, alistair23

Hi Subbaraya,

>> +        if (value & TIMER_MODE) {
>> +            qemu_log_mask(LOG_UNIMP, "64-bit mode not supported\n");
>
> No need of trailing '\n', be more specific, something like:
>
>     qemu_log_mask(LOG_UNIMP, TYPE_MSF2_TIMER ": 64-bit mode not
> supported");

I mistaken with error_report(), qemu_log_mask() does use trailing 
newline, sorry!

Phil.

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

* Re: [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-12  5:02       ` Philippe Mathieu-Daudé
@ 2017-05-15 16:54         ` Alistair Francis
  2017-05-16  6:40           ` sundeep subbaraya
  0 siblings, 1 reply; 26+ messages in thread
From: Alistair Francis @ 2017-05-15 16:54 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: sundeep subbaraya, Peter Maydell, QEMU Developers,
	Peter Crosthwaite, qemu-arm

 On Thu, May 11, 2017 at 10:02 PM, Philippe Mathieu-Daudé
<f4bug@amsat.org> wrote:
> On 05/12/2017 12:17 AM, sundeep subbaraya wrote:
>>
>> Hi Philippe,
>>
>> On Wed, May 10, 2017 at 5:20 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
>> wrote:
>>
>>> Hi Subbaraya,
>>>
>>>
>>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
>>>
>>>> Smartfusion2 SoC has hardened Microcontroller subsystem
>>>> and flash based FPGA fabric. This patch adds support for
>>>> Microcontroller subsystem in the SoC.
>>>>
>>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
>>>> ---
>>>>  default-configs/arm-softmmu.mak |   1 +
>>>>  hw/arm/Makefile.objs            |   2 +-
>>>>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++
>>>> ++++++++++
>>>>  include/hw/arm/msf2-soc.h       |  60 +++++++++++++
>>>>  4 files changed, 250 insertions(+), 1 deletion(-)
>>>>  create mode 100644 hw/arm/msf2-soc.c
>>>>  create mode 100644 include/hw/arm/msf2-soc.h
>>>>
>>>> diff --git a/default-configs/arm-softmmu.mak
>>>> b/default-configs/arm-softmmu.mak
>>>> index 78d7af0..7062512 100644
>>>> --- a/default-configs/arm-softmmu.mak
>>>> +++ b/default-configs/arm-softmmu.mak
>>>> @@ -122,3 +122,4 @@ CONFIG_ACPI=y
>>>>  CONFIG_SMBIOS=y
>>>>  CONFIG_ASPEED_SOC=y
>>>>  CONFIG_GPIO_KEY=y
>>>> +CONFIG_MSF2=y
>>>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>>>> index 4c5c4ee..ae5e4a3 100644
>>>> --- a/hw/arm/Makefile.objs
>>>> +++ b/hw/arm/Makefile.objs
>>>> @@ -1,7 +1,7 @@
>>>>  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
>>>>  obj-$(CONFIG_DIGIC) += digic_boards.o
>>>>  obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
>>>> -obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
>>>> +obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
>>>>
>>>
>>> Not a big deal, but since you added CONFIG_MSF2 why not using it here and
>>> the Makefiles you touched (misc/ssi/timer)?
>>>
>>> obj-$(CONFIG_MSF2) += msf2-soc.o
>>>
>>>   OK. Will change it.
>>
>>
>>>
>>>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
>>>>
>>>>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
>>>>  obj-y += netduino2.o
>
> [...]
>>>>
>>>> +    MemoryRegion *system_memory = get_system_memory();
>>>> +    MemoryRegion *nvm = g_new(MemoryRegion, 1);
>>>> +    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
>>>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
>>>> +    MemoryRegion *ddr = g_new(MemoryRegion, 1);
>>>> +
>>>> +    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
>>>> +                           &error_fatal);
>>>>
>>>
>>> Maybe you can name it "eNVM" to match the documentation.
>>>
>>> Also envm_size should be a per-model property.
>>>
>>
>> Ok.
>>
>>>
>>> +    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
>>>>
>>>> +                             nvm, 0, ENVM_SIZE);
>>>>
>>>
>>> Hmmm well this would be the "Cache Matrix Remap" which happens to be
>>> mapped by default to eNVM on cold reset.
>>> Naming it "MSF2.flash.alias" is pretty confusing.
>>>
>>
>> Exactly it is Cache Matrix Remap.
>> AFAIK currently we cannot remap memory during runtime in Qemu.
>> So I handled default remap with alias.
>> Please suggest the name. MSF2.eNVM.alias sounds fine?
>
>
> Hmm Peter, Francis?
>
> Personally I prefer "bus_remap.alias" which is explicit.
>
> "eNVM.alias" is only true on Cold Reset.

Yeah, I'm pretty sure you can't remap memory (unless that is some new
feature I missed).

Creating an alias seems like the right idea (you can even
enable/disable it as needed to pretend we have dynamic remapping).

As for names usually just copy the data sheet. MSF2.eNVM.alias sounds
fine to me.

Thanks,

Alistair

>
>>>
>>> +    vmstate_register_ram_global(nvm);
>>>>
>>>> +
>>>> +    memory_region_set_readonly(nvm, true);
>>>> +    memory_region_set_readonly(nvm_alias, true);
>>>> +
>>>> +    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
>>>> +    memory_region_add_subregion(system_memory, 0, nvm_alias);
>>>> +
>>>> +    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
>>>> +                           &error_fatal);
>>>>
>>>
>>> Wrong, there is no DDR on this SoC.
>>>
>> DDR controller is there in Smartfusion2 (different from Smartfusion). As
>> you said below this
>> should be in board file.
>
>
> There IS a DDRC in this SoC, but here you are registering a DDR 'ram' memory
> region, not a controller. This SoC can be used without any DDR, enough using
> embedded eNVM and eSRAM.
>
> Now it happens your SoM board provides a DDR chip connected to this SoC.
>
>>>
>>> +    vmstate_register_ram_global(ddr);
>>>>
>>>> +    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS, ddr);
>>>> +
>>>> +    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
>>>> +                           &error_fatal);
>>>>
>>>
>>> I'd rather like to see it named "eSRAM" somehow, so there is no confusion
>>> possible with external SRAM a SoM/board can map at 0x60000000.
>>>
>>> Same comment than envm_size, sram_size should be a per-model property.
>>>
>>> OK
>>
>>
>>> +    vmstate_register_ram_global(sram);
>>>>
>>>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS,
>>>> sram);
>>>> +
>>>> +    armv7m = DEVICE(&s->armv7m);
>>>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
>>>>
>>>
>>> Can you point me to your datasheet? I thought the SF2 had 240 IRQs.
>>
>>
>>
>> Please go to link:
>> https://www.microsemi.com/document-portal/search_form
>> and provide search keyword as "UG0331". You can the download the spec.
>> It has 81 irqs I remember when I have given 81 qemu complained not
>> multiple
>> of 4.
>> I checked again with 81 and it is fine. I will change it to 81.
>
>
> Ok :)
>
>> +    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
>>>>
>>>> +    object_property_set_link(OBJECT(&s->armv7m),
>>>> OBJECT(get_system_memory()),
>>>> +                                     "memory", &error_abort);
>
> [...]
>>>>
>>>> +#define MSF2_NUM_SPIS         2
>>>> +#define MSF2_NUM_UARTS        2
>>>> +
>>>> +#define ENVM_BASE_ADDRESS     0x60000000
>>>> +#define ENVM_SIZE             (128 * 1024)
>>>>
>>>
>>> The SoC design ENVM_SIZE is 1MB, 128K seems your particular model.
>>>
>>
>>  M2S010 SoC device has 256K eNMV. My bad it should be 256 instead of 128.
>>  The board I have contains M2S010 device in SOM.
>>
>
> What I mean here is on the SF2 the eNVM "region size" (as seen by the AHB
> Bus) is 1MB. Now your SoC M2S010 provides 256KB in this dedicated 1M region.
>
> I find your #define confusing, what about:
>
> #define ENVM_REGION_SIZE      (1 * M_BYTE)
> #define M2S010_ENVM_SIZE      (256 * K_BYTE)
>
> (?_BYTE from "qemu/cutils.h")
>
> I wanted to clarify this because you named your functions as it can models
> any SF2 but actually you restrict it to your M2S010.
>
> Maybe to start you can rename msf2_soc_x() -> m2s010_sf2_soc_x() then if
> needed this can be generalized to other SoCs from SF2 family?
>
>>> +
>>>>
>>>> +#define DDR_BASE_ADDRESS      0xA0000000
>>>> +#define DDR_SIZE              (64 * 1024 * 1024)
>>>>
>>>
>>> This belongs to the SoM.
>>> Yes will change it.
>>>
>>>> +
>>>> +#define SRAM_BASE_ADDRESS     0x20000000
>>>> +#define SRAM_SIZE             (64 * 1024)
>>>>
>>>
>>> Indeed this SoC is designed to have up to 64K of SRAM.
>>> Luckily your model provides 64K.
>>>
>>
>>
>> Yes it is 64k :)
>>
>
> Same here, what you have is:
>
> #define ESRAM_REGION_SIZE     (64 * K_BYTE)
> #define M2S010_ESRAM_SIZE     (64 * K_BYTE)
>
> which happens to be equal but does not mean the same, do you see the
> difference?
>
>
>> +
>>>>
>>>> +typedef struct MSF2State {
>>>> +    /*< private >*/
>>>> +    SysBusDevice parent_obj;
>>>> +    /*< public >*/
>>>> +
>>>> +    ARMv7MState armv7m;
>>>> +
>>>> +    MSF2SysregState sysreg;
>>>> +    MSF2TimerState timer;
>>>> +    MSF2SpiState spi[MSF2_NUM_SPIS];
>>>> +} MSF2State;
>>>> +
>>>> +#endif

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

* Re: [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC.
  2017-05-15 16:54         ` Alistair Francis
@ 2017-05-16  6:40           ` sundeep subbaraya
  0 siblings, 0 replies; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-16  6:40 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Philippe Mathieu-Daudé,
	Peter Maydell, QEMU Developers, Peter Crosthwaite, qemu-arm

Hi Philippe and Alistair,

On Mon, May 15, 2017 at 10:24 PM, Alistair Francis <alistair23@gmail.com>
wrote:

>  On Thu, May 11, 2017 at 10:02 PM, Philippe Mathieu-Daudé
> <f4bug@amsat.org> wrote:
> > On 05/12/2017 12:17 AM, sundeep subbaraya wrote:
> >>
> >> Hi Philippe,
> >>
> >> On Wed, May 10, 2017 at 5:20 PM, Philippe Mathieu-Daudé <
> f4bug@amsat.org>
> >> wrote:
> >>
> >>> Hi Subbaraya,
> >>>
> >>>
> >>> On 05/09/2017 01:44 PM, Subbaraya Sundeep wrote:
> >>>
> >>>> Smartfusion2 SoC has hardened Microcontroller subsystem
> >>>> and flash based FPGA fabric. This patch adds support for
> >>>> Microcontroller subsystem in the SoC.
> >>>>
> >>>> Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com>
> >>>> ---
> >>>>  default-configs/arm-softmmu.mak |   1 +
> >>>>  hw/arm/Makefile.objs            |   2 +-
> >>>>  hw/arm/msf2-soc.c               | 188 ++++++++++++++++++++++++++++++
> >>>> ++++++++++
> >>>>  include/hw/arm/msf2-soc.h       |  60 +++++++++++++
> >>>>  4 files changed, 250 insertions(+), 1 deletion(-)
> >>>>  create mode 100644 hw/arm/msf2-soc.c
> >>>>  create mode 100644 include/hw/arm/msf2-soc.h
> >>>>
> >>>> diff --git a/default-configs/arm-softmmu.mak
> >>>> b/default-configs/arm-softmmu.mak
> >>>> index 78d7af0..7062512 100644
> >>>> --- a/default-configs/arm-softmmu.mak
> >>>> +++ b/default-configs/arm-softmmu.mak
> >>>> @@ -122,3 +122,4 @@ CONFIG_ACPI=y
> >>>>  CONFIG_SMBIOS=y
> >>>>  CONFIG_ASPEED_SOC=y
> >>>>  CONFIG_GPIO_KEY=y
> >>>> +CONFIG_MSF2=y
> >>>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> >>>> index 4c5c4ee..ae5e4a3 100644
> >>>> --- a/hw/arm/Makefile.objs
> >>>> +++ b/hw/arm/Makefile.objs
> >>>> @@ -1,7 +1,7 @@
> >>>>  obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
> >>>>  obj-$(CONFIG_DIGIC) += digic_boards.o
> >>>>  obj-y += integratorcp.o mainstone.o musicpal.o nseries.o
> >>>> -obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
> >>>> +obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o msf2-soc.o
> >>>>
> >>>
> >>> Not a big deal, but since you added CONFIG_MSF2 why not using it here
> and
> >>> the Makefiles you touched (misc/ssi/timer)?
> >>>
> >>> obj-$(CONFIG_MSF2) += msf2-soc.o
> >>>
> >>>   OK. Will change it.
> >>
> >>
> >>>
> >>>  obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
> >>>>
> >>>>  obj-$(CONFIG_ACPI) += virt-acpi-build.o
> >>>>  obj-y += netduino2.o
> >
> > [...]
> >>>>
> >>>> +    MemoryRegion *system_memory = get_system_memory();
> >>>> +    MemoryRegion *nvm = g_new(MemoryRegion, 1);
> >>>> +    MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
> >>>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> >>>> +    MemoryRegion *ddr = g_new(MemoryRegion, 1);
> >>>> +
> >>>> +    memory_region_init_ram(nvm, NULL, "MSF2.envm", ENVM_SIZE,
> >>>> +                           &error_fatal);
> >>>>
> >>>
> >>> Maybe you can name it "eNVM" to match the documentation.
> >>>
> >>> Also envm_size should be a per-model property.
> >>>
> >>
> >> Ok.
> >>
> >>>
> >>> +    memory_region_init_alias(nvm_alias, NULL, "MSF2.flash.alias",
> >>>>
> >>>> +                             nvm, 0, ENVM_SIZE);
> >>>>
> >>>
> >>> Hmmm well this would be the "Cache Matrix Remap" which happens to be
> >>> mapped by default to eNVM on cold reset.
> >>> Naming it "MSF2.flash.alias" is pretty confusing.
> >>>
> >>
> >> Exactly it is Cache Matrix Remap.
> >> AFAIK currently we cannot remap memory during runtime in Qemu.
> >> So I handled default remap with alias.
> >> Please suggest the name. MSF2.eNVM.alias sounds fine?
> >
> >
> > Hmm Peter, Francis?
> >
> > Personally I prefer "bus_remap.alias" which is explicit.
> >
> > "eNVM.alias" is only true on Cold Reset.
>
> Yeah, I'm pretty sure you can't remap memory (unless that is some new
> feature I missed).
>
> Creating an alias seems like the right idea (you can even
> enable/disable it as needed to pretend we have dynamic remapping).
>
> As for names usually just copy the data sheet. MSF2.eNVM.alias sounds
> fine to me.
>

I will let it be MSF2.eNVM.alias and add comment about default remapping on
reset.

Thanks,
Sundeep

>
> Thanks,
>
> Alistair
>
> >
> >>>
> >>> +    vmstate_register_ram_global(nvm);
> >>>>
> >>>> +
> >>>> +    memory_region_set_readonly(nvm, true);
> >>>> +    memory_region_set_readonly(nvm_alias, true);
> >>>> +
> >>>> +    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS,
> nvm);
> >>>> +    memory_region_add_subregion(system_memory, 0, nvm_alias);
> >>>> +
> >>>> +    memory_region_init_ram(ddr, NULL, "MSF2.ddr", DDR_SIZE,
> >>>> +                           &error_fatal);
> >>>>
> >>>
> >>> Wrong, there is no DDR on this SoC.
> >>>
> >> DDR controller is there in Smartfusion2 (different from Smartfusion). As
> >> you said below this
> >> should be in board file.
> >
> >
> > There IS a DDRC in this SoC, but here you are registering a DDR 'ram'
> memory
> > region, not a controller. This SoC can be used without any DDR, enough
> using
> > embedded eNVM and eSRAM.
> >
> > Now it happens your SoM board provides a DDR chip connected to this SoC.
> >
> >>>
> >>> +    vmstate_register_ram_global(ddr);
> >>>>
> >>>> +    memory_region_add_subregion(system_memory, DDR_BASE_ADDRESS,
> ddr);
> >>>> +
> >>>> +    memory_region_init_ram(sram, NULL, "MSF2.sram", SRAM_SIZE,
> >>>> +                           &error_fatal);
> >>>>
> >>>
> >>> I'd rather like to see it named "eSRAM" somehow, so there is no
> confusion
> >>> possible with external SRAM a SoM/board can map at 0x60000000.
> >>>
> >>> Same comment than envm_size, sram_size should be a per-model property.
> >>>
> >>> OK
> >>
> >>
> >>> +    vmstate_register_ram_global(sram);
> >>>>
> >>>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS,
> >>>> sram);
> >>>> +
> >>>> +    armv7m = DEVICE(&s->armv7m);
> >>>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> >>>>
> >>>
> >>> Can you point me to your datasheet? I thought the SF2 had 240 IRQs.
> >>
> >>
> >>
> >> Please go to link:
> >> https://www.microsemi.com/document-portal/search_form
> >> and provide search keyword as "UG0331". You can the download the spec.
> >> It has 81 irqs I remember when I have given 81 qemu complained not
> >> multiple
> >> of 4.
> >> I checked again with 81 and it is fine. I will change it to 81.
> >
> >
> > Ok :)
> >
> >> +    qdev_prop_set_string(armv7m, "cpu-model", "cortex-m3");
> >>>>
> >>>> +    object_property_set_link(OBJECT(&s->armv7m),
> >>>> OBJECT(get_system_memory()),
> >>>> +                                     "memory", &error_abort);
> >
> > [...]
> >>>>
> >>>> +#define MSF2_NUM_SPIS         2
> >>>> +#define MSF2_NUM_UARTS        2
> >>>> +
> >>>> +#define ENVM_BASE_ADDRESS     0x60000000
> >>>> +#define ENVM_SIZE             (128 * 1024)
> >>>>
> >>>
> >>> The SoC design ENVM_SIZE is 1MB, 128K seems your particular model.
> >>>
> >>
> >>  M2S010 SoC device has 256K eNMV. My bad it should be 256 instead of
> 128.
> >>  The board I have contains M2S010 device in SOM.
> >>
> >
> > What I mean here is on the SF2 the eNVM "region size" (as seen by the AHB
> > Bus) is 1MB. Now your SoC M2S010 provides 256KB in this dedicated 1M
> region.
> >
> > I find your #define confusing, what about:
> >
> > #define ENVM_REGION_SIZE      (1 * M_BYTE)
> > #define M2S010_ENVM_SIZE      (256 * K_BYTE)
> >
> > (?_BYTE from "qemu/cutils.h")
> >
> > I wanted to clarify this because you named your functions as it can
> models
> > any SF2 but actually you restrict it to your M2S010.
> >
> > Maybe to start you can rename msf2_soc_x() -> m2s010_sf2_soc_x() then if
> > needed this can be generalized to other SoCs from SF2 family?
> >
> >>> +
> >>>>
> >>>> +#define DDR_BASE_ADDRESS      0xA0000000
> >>>> +#define DDR_SIZE              (64 * 1024 * 1024)
> >>>>
> >>>
> >>> This belongs to the SoM.
> >>> Yes will change it.
> >>>
> >>>> +
> >>>> +#define SRAM_BASE_ADDRESS     0x20000000
> >>>> +#define SRAM_SIZE             (64 * 1024)
> >>>>
> >>>
> >>> Indeed this SoC is designed to have up to 64K of SRAM.
> >>> Luckily your model provides 64K.
> >>>
> >>
> >>
> >> Yes it is 64k :)
> >>
> >
> > Same here, what you have is:
> >
> > #define ESRAM_REGION_SIZE     (64 * K_BYTE)
> > #define M2S010_ESRAM_SIZE     (64 * K_BYTE)
> >
> > which happens to be equal but does not mean the same, do you see the
> > difference?
> >
> >
> >> +
> >>>>
> >>>> +typedef struct MSF2State {
> >>>> +    /*< private >*/
> >>>> +    SysBusDevice parent_obj;
> >>>> +    /*< public >*/
> >>>> +
> >>>> +    ARMv7MState armv7m;
> >>>> +
> >>>> +    MSF2SysregState sysreg;
> >>>> +    MSF2TimerState timer;
> >>>> +    MSF2SpiState spi[MSF2_NUM_SPIS];
> >>>> +} MSF2State;
> >>>> +
> >>>> +#endif
>

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

* Re: [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer
  2017-05-15 11:52     ` Philippe Mathieu-Daudé
@ 2017-05-16  6:41       ` sundeep subbaraya
  0 siblings, 0 replies; 26+ messages in thread
From: sundeep subbaraya @ 2017-05-16  6:41 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: QEMU Developers, qemu-arm, Peter Maydell, Alistair Francis

Hi Philippe,

On Mon, May 15, 2017 at 5:22 PM, Philippe Mathieu-Daudé <f4bug@amsat.org>
wrote:

> Hi Subbaraya,
>
> +        if (value & TIMER_MODE) {
>>> +            qemu_log_mask(LOG_UNIMP, "64-bit mode not supported\n");
>>>
>>
>> No need of trailing '\n', be more specific, something like:
>>
>>     qemu_log_mask(LOG_UNIMP, TYPE_MSF2_TIMER ": 64-bit mode not
>> supported");
>>
>
> I mistaken with error_report(), qemu_log_mask() does use trailing newline,
> sorry!
>

thats ok :)

Thanks,
Sundeep

>
> Phil.
>

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

end of thread, other threads:[~2017-05-16  6:41 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-09 16:44 [Qemu-devel] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Subbaraya Sundeep
2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 1/5] msf2: Add Smartfusion2 System timer Subbaraya Sundeep
2017-05-10  9:41   ` [Qemu-devel] [Qemu-arm] " Philippe Mathieu-Daudé
2017-05-10 12:37     ` sundeep subbaraya
2017-05-12  4:38       ` Philippe Mathieu-Daudé
2017-05-12  5:16         ` sundeep subbaraya
2017-05-15 11:52     ` Philippe Mathieu-Daudé
2017-05-16  6:41       ` sundeep subbaraya
2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 2/5] msf2: Microsemi Smartfusion2 System Register block Subbaraya Sundeep
2017-05-10 10:34   ` Philippe Mathieu-Daudé
2017-05-12  3:48     ` sundeep subbaraya
2017-05-12  4:12       ` Philippe Mathieu-Daudé
2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 3/5] msf2: Add Smartfusion2 SPI controller Subbaraya Sundeep
2017-05-10 12:12   ` Philippe Mathieu-Daudé
2017-05-12  3:31     ` sundeep subbaraya
2017-05-12  3:54       ` Philippe Mathieu-Daudé
2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 4/5] msf2: Add Smartfusion2 SoC Subbaraya Sundeep
2017-05-10 11:50   ` Philippe Mathieu-Daudé
2017-05-12  3:17     ` sundeep subbaraya
2017-05-12  5:02       ` Philippe Mathieu-Daudé
2017-05-15 16:54         ` Alistair Francis
2017-05-16  6:40           ` sundeep subbaraya
2017-05-09 16:44 ` [Qemu-devel] [Qemu-devel PATCH 5/5] msf2: Add Emcraft's Smartfusion2 SOM kit Subbaraya Sundeep
2017-05-10 11:16   ` Philippe Mathieu-Daudé
2017-05-10  9:44 ` [Qemu-devel] [Qemu-arm] [Qemu-devel PATCH 0/5] Add support for Smartfusion2 SoC Philippe Mathieu-Daudé
2017-05-10 15:24   ` sundeep subbaraya

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.