Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,6 @@ trace-dtrace-root.dtrace
trace-ust-all.h
trace-ust-all.c
/target/arm/decode-sve.inc.c
storage-daemon/
qemu-storage-daemon
roms
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.3)
project(qemu_dev)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

file(GLOB_RECURSE src "*.c" "*.h")

set(SOURCES ${src})
add_library(qemu_dev ${SOURCES})
target_include_directories(qemu_dev PUBLIC "include" "target/arm" "")
4 changes: 4 additions & 0 deletions hw/arm/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
obj-$(CONFIG_NRF51_SOC) += nrf51_soc.o
obj-y += amazfit.o
obj-y += da1469x/soc.o
obj-y += da1469x/qspi.o
obj-y += da1469x/timer.o
48 changes: 48 additions & 0 deletions hw/arm/amazfit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "qemu/osdep.h"
#include "hw/misc/unimp.h"
#include "hw/sysbus.h"
#include "hw/arm/armv7m.h"
#include "qapi/error.h"
#include "hw/boards.h"
#include "hw/arm/boot.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
#include "hw/loader.h"
#include "hw/arm/da1469x/soc.h"
#include "qemu/log.h"
#include "hw/ssi/ssi.h"

static void bip_s_init(MachineState *machine) {
DeviceState *dev;
dev = qdev_create(NULL, TYPE_DA1469X_SOC);
object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);

DA1469xState *soc = DA1469X_SOC(dev);

/* --- QSPI Flash --------------------------------------------- */
SSIBus *qspi = (SSIBus *) qdev_get_child_bus(DEVICE(&soc->qspi), "spi");
DeviceState *qspi_flash = ssi_create_slave_no_init(qspi, "GD25LQ64C");
DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
if (dinfo) {
qdev_prop_set_drive(qspi_flash, "drive", blk_by_legacy_dinfo(dinfo), &error_fatal);
}
qdev_init_nofail(qspi_flash);

qemu_irq cs_line = qdev_get_gpio_in_named(qspi_flash, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&soc->qspi), 1, cs_line);

load_image_targphys("/Users/Marijn/Downloads/tonlesap_202006191826_2.1.1.16_tonlesap.img", 0x0, 0x8192 * 1024);
load_image_targphys("otp.bin", 0x10080000, 64 * 1024);

armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
0x8192 * 1024);
}

static void bip_s_machine_class_init(MachineClass *mc)
{
mc->desc = "Amazfit Bip S";
mc->init = bip_s_init;
mc->ignore_memory_transaction_failures = true;
}

DEFINE_MACHINE("bip-s", bip_s_machine_class_init)
214 changes: 214 additions & 0 deletions hw/arm/da1469x/qspi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/qdev-properties.h"
#include "qspi.h"
#include "qemu/log.h"
#include "hw/ssi/ssi.h"
#include "hw/irq.h"

static const int QSPIC_CTRLBUS_REG = 0x00;
static const int QSPIC_CTRLMODE_REG = 0x04;
static const int QSPIC_BURSTCMDA_REG = 0x0C;
static const int QSPIC_BURSTCMDB_REG = 0x10;
static const int QSPIC_WRITEDATA_REG = 0x18;
static const int QSPIC_READDATA_REG = 0x1C;
static const int QSPIC_ERASECMDA_REG = 0x28;
static const int QSPIC_ERASECMDB_REG = 0x2C;
static const int QSPIC_BURSTBRK_REG = 0x30;
static const int QSPIC_STATUSCMD_REG = 0x34;

static void da1469x_qspi_set_cs(DA1469xQspiState *s, bool low) {
qemu_set_irq(s->cs_line, !low);
}

static uint64_t da1469x_qspic_read(void *opaque, hwaddr addr, unsigned size) {
DA1469xQspiState *s = opaque;

if (addr == QSPIC_READDATA_REG && size == 1) {
uint32_t ret = ssi_transfer(s->spi, 0);
printf("[QSPI] - read -> 0x%X\n", ret);
return ret;
}

switch (addr) {
case QSPIC_CTRLMODE_REG: {
int out = 0;
out |= s->AUTO_MD << 0;
out |= s->CLK_MD << 1;
out |= s->IO2_OEN << 2;
out |= s->IO3_OEN << 3;
out |= s->IO2_DAT << 4;
out |= s->IO3_DAT << 5;
out |= s->HRDY_MD << 6;
out |= s->RXD_NEG << 7;
out |= s->RPIPE_EN << 8;
out |= s->PCLK_MD << 9;

out |= s->BUF_LIM_EN << 12;
out |= s->USE_32BA << 13;
return out;
}
case QSPIC_BURSTCMDA_REG:
case QSPIC_BURSTCMDB_REG:
case QSPIC_READDATA_REG:
case QSPIC_ERASECMDB_REG:
case QSPIC_BURSTBRK_REG:
case QSPIC_STATUSCMD_REG:
break;

// For write
case QSPIC_WRITEDATA_REG:
break;

default:
printf("READ case 0x%X:\n", addr);
}
return 0;
}

static void da1469x_qspic_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) {

DA1469xQspiState *s = DA1469XQSPI(opaque);

if (addr == QSPIC_WRITEDATA_REG) {
for (int i = 0; i < size; i++) {
uint8_t byte = (value >> (8 * i)) & 0xff;
uint32_t ret = ssi_transfer(s->spi, byte);
printf("[QSPI] - write 0x%X -> 0x%X\n", byte, ret);
}
return;
}

switch (addr) {
case QSPIC_CTRLBUS_REG:
if (value & (1 << 0))
qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_SINGLE\n");
if (value & (1 << 1))
qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_DUAL\n");
if (value & (1 << 2))
qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_QUAD\n");
if (value & (1 << 3)) {
// QSPIC_EN_CS
printf("[QSPI] CS_LOW\n");
da1469x_qspi_set_cs(opaque, true);
}
if (value & (1 << 4)) {
// QSPIC_DIS_CS
printf("[QSPI] CS_HIGH\n");
da1469x_qspi_set_cs(opaque, false);
}
break;

case QSPIC_STATUSCMD_REG:
case QSPIC_CTRLMODE_REG:
case QSPIC_ERASECMDB_REG:
case QSPIC_WRITEDATA_REG:
case QSPIC_BURSTCMDB_REG:
case QSPIC_ERASECMDA_REG:
case QSPIC_BURSTBRK_REG:
case QSPIC_BURSTCMDA_REG: {
uint64_t old = da1469x_qspic_read(opaque, addr, size);
qemu_log_mask(LOG_GUEST_ERROR,
"%"HWADDR_PRIx": 0x%X -> 0x%X (size: %d)\n", addr, old, value, size);

}

break;

default:
printf("WRITE case 0x%X:\n", addr);
}
}

static const MemoryRegionOps da1469x_qspic_ops = {
.read = da1469x_qspic_read,
.write = da1469x_qspic_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};

#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
static uint64_t da1469x_qspi_read(void *opaque, hwaddr addr, unsigned size) {
DA1469xQspiState *s = DA1469XQSPI(opaque);

da1469x_qspi_set_cs(opaque, true);

ssi_transfer(s->spi, SPI_OP_READ);
ssi_transfer(s->spi, (addr >> 16) & 0xff);
ssi_transfer(s->spi, (addr >> 8) & 0xff);
ssi_transfer(s->spi, (addr & 0xff));

uint64_t ret = 0;
for (int i = 0; i < size; i++) {
ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
}

da1469x_qspi_set_cs(opaque, false);
return ret;
}
static void da1469x_qspi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) {

}

static const MemoryRegionOps da1469x_qspi_ops = {
.read = da1469x_qspi_read,
.write = da1469x_qspi_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};

static void da1469x_qspi_reset(DeviceState *dev) {
DA1469xQspiState *s = DA1469XQSPI(dev);

s->AUTO_MD = 0;
s->CLK_MD = 0;
s->IO2_OEN = 0;
s->IO3_OEN = 0;
s->IO2_DAT = 0;
s->IO3_DAT = 0;
s->HRDY_MD = 0;
s->RXD_NEG = 0;
s->RPIPE_EN = 0;
s->PCLK_MD = 0;
s->BUF_LIM_EN = 0;
s->USE_32BA = 0;
}

static void da1469x_qspi_init(Object *obj) {
}

static void da1469x_qspi_realize(DeviceState *dev, Error **errp) {
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
DA1469xQspiState *s = DA1469XQSPI(dev);

memory_region_init_io(&s->control, dev, &da1469x_qspic_ops, s, "QSPIC", 0x100);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->control);

memory_region_init_io(&s->iomem, dev, &da1469x_qspi_ops, s, "QSPI", 0x2000000);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);

s->spi = ssi_create_bus(DEVICE(dev), "spi");

sysbus_init_irq(sbd, &s->_irq);
ssi_auto_connect_slaves(DEVICE(dev), &s->cs_line, s->spi);
sysbus_init_irq(sbd, &s->cs_line);
}

static void da1469x_qspi_class_init(ObjectClass *klass, void *data) {
DeviceClass *dc = DEVICE_CLASS(klass);

dc->reset = da1469x_qspi_reset;
dc->realize = da1469x_qspi_realize;
}

static const TypeInfo da1469x_qspi_info = {
.name = TYPE_DA1469X_QSPI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(DA1469xQspiState),
.class_init = da1469x_qspi_class_init,
.instance_init = da1469x_qspi_init,
};

static void da1469x_qspi_register_types(void) {
type_register_static(&da1469x_qspi_info);
}

type_init(da1469x_qspi_register_types)
32 changes: 32 additions & 0 deletions hw/arm/da1469x/qspi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/qdev-properties.h"

#define TYPE_DA1469X_QSPI "da1469x.qspi"
#define DA1469XQSPI(obj) OBJECT_CHECK(DA1469xQspiState, \
(obj), TYPE_DA1469X_QSPI)

typedef struct {
SysBusDevice parent_obj;
MemoryRegion control;
MemoryRegion iomem;
SSIBus *spi;
qemu_irq _irq;

int AUTO_MD;
int CLK_MD;
int IO2_OEN;
int IO3_OEN;
int IO2_DAT;
int IO3_DAT;
int HRDY_MD;

int RPIPE_EN;
int RXD_NEG;
int PCLK_MD;
int BUF_LIM_EN;
int USE_32BA;

bool cs;
qemu_irq cs_line;
} DA1469xQspiState;
Loading