Progress on some components
This commit is contained in:
1 parent
29e927ab33
commit
8fae8122ad
11 files changed
+626
-13
No files matched your search
+29
-1
@@ -66,7 +66,7 @@ static void atv4_cpu_reset(void *opaque)
|
||||
static void atv4_memory_setup(MachineState *machine, MemoryRegion *sysmem, AddressSpace *nsas)
|
||||
{
|
||||
// ATV4MachineState *nms = ATV4_MACHINE(machine);
|
||||
allocate_ram(sysmem, "unknown1", UNKNOWN1_MEM_BASE, 0x200000);
|
||||
allocate_ram(sysmem, "sram", SRAM_MEM_BASE, SRAM_LENGTH);
|
||||
allocate_ram(sysmem, "unknown2", UNKNOWN2_MEM_BASE, 0x1000);
|
||||
allocate_ram(sysmem, "unknown3", UNKNOWN3_MEM_BASE, 0x20);
|
||||
|
||||
@@ -135,6 +135,34 @@ static void atv4_machine_init(MachineState *machine)
|
||||
nms->ausb_state = ausb_state;
|
||||
memory_region_add_subregion(sysmem, AUSB_MEM_BASE, &ausb_state->iomem);
|
||||
|
||||
// init the AUSB Widget
|
||||
dev = qdev_new("atv4.ausbwidget");
|
||||
ATV4AUSBWidgetState *ausb_widget_state = ATV4_AUSB_WIDGET(dev);
|
||||
nms->ausb_widget_state = ausb_widget_state;
|
||||
memory_region_add_subregion(sysmem, AUSB_WIDGET_MEM_BASE, &ausb_widget_state->iomem);
|
||||
|
||||
// init the ANCs
|
||||
dev = qdev_new("atv4.anc");
|
||||
ATV4ANCState *anc0_state = ATV4_ANC(dev);
|
||||
nms->anc0_state = anc0_state;
|
||||
memory_region_add_subregion(sysmem, PPNNPL_MEM_BASE, &anc0_state->ppnnpl_iomem);
|
||||
memory_region_add_subregion(sysmem, ANC0_MEM_BASE, &anc0_state->anc_iomem);
|
||||
|
||||
dev = qdev_new("atv4.anc");
|
||||
ATV4ANCState *anc1_state = ATV4_ANC(dev);
|
||||
nms->anc1_state = anc1_state;
|
||||
memory_region_add_subregion(sysmem, PPNNPL_MEM_BASE, &anc1_state->ppnnpl_iomem);
|
||||
memory_region_add_subregion(sysmem, ANC1_MEM_BASE, &anc1_state->anc_iomem);
|
||||
|
||||
// init spis
|
||||
uint64_t spi_bases[] = { SPI0_MEM_BASE, SPI1_MEM_BASE, SPI2_MEM_BASE, SPI3_MEM_BASE };
|
||||
for(int i = 0; i < 4; i++) {
|
||||
set_spi_base(i);
|
||||
dev = sysbus_create_simple("atv4.spi", spi_bases[i], 0); // TODO set the right IRQ!
|
||||
ATV4SPIState *spi_state = ATV4_SPI(dev);
|
||||
nms->spi_state[i] = spi_state;
|
||||
}
|
||||
|
||||
qemu_register_reset(atv4_cpu_reset, nms);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "hw/arm/atv4_anc.h"
|
||||
|
||||
static uint64_t atv4_anc_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
ATV4ANCState *s = (ATV4ANCState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
static void atv4_anc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
ATV4ANCState *s = (ATV4ANCState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps atv4_anc_ops = {
|
||||
.read = atv4_anc_read,
|
||||
.write = atv4_anc_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_anc_init(Object *obj)
|
||||
{
|
||||
ATV4ANCState *s = ATV4_ANC(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->ppnnpl_iomem, obj, &atv4_anc_ops, s, TYPE_ATV4_ANC, 0x100); // TODO hard-coded anc_ops call, should change
|
||||
sysbus_init_mmio(sbd, &s->ppnnpl_iomem);
|
||||
|
||||
memory_region_init_io(&s->anc_iomem, obj, &atv4_anc_ops, s, TYPE_ATV4_ANC, 0x3000);
|
||||
sysbus_init_mmio(sbd, &s->anc_iomem);
|
||||
}
|
||||
|
||||
static void atv4_anc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo atv4_anc_type_info = {
|
||||
.name = TYPE_ATV4_ANC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ATV4ANCState),
|
||||
.instance_init = atv4_anc_init,
|
||||
.class_init = atv4_anc_class_init,
|
||||
};
|
||||
|
||||
static void atv4_anc_register_types(void)
|
||||
{
|
||||
type_register_static(&atv4_anc_type_info);
|
||||
}
|
||||
|
||||
type_init(atv4_anc_register_types)
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "hw/arm/atv4_ausb_widget.h"
|
||||
|
||||
static uint64_t atv4_ausb_widget_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
ATV4AUSBWidgetState *s = (ATV4AUSBWidgetState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
static void atv4_ausb_widget_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
ATV4AUSBWidgetState *s = (ATV4AUSBWidgetState *) opaque;
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps atv4_ausb_widget_ops = {
|
||||
.read = atv4_ausb_widget_read,
|
||||
.write = atv4_ausb_widget_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_ausb_widget_init(Object *obj)
|
||||
{
|
||||
ATV4AUSBWidgetState *s = ATV4_AUSB_WIDGET(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &atv4_ausb_widget_ops, s, TYPE_ATV4_AUSB_WIDGET, 0x100);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void atv4_ausb_widget_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo atv4_ausb_widget_type_info = {
|
||||
.name = TYPE_ATV4_AUSB_WIDGET,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ATV4AUSBWidgetState),
|
||||
.instance_init = atv4_ausb_widget_init,
|
||||
.class_init = atv4_ausb_widget_class_init,
|
||||
};
|
||||
|
||||
static void atv4_ausb_widget_register_types(void)
|
||||
{
|
||||
type_register_static(&atv4_ausb_widget_type_info);
|
||||
}
|
||||
|
||||
type_init(atv4_ausb_widget_register_types)
|
||||
+9
-9
@@ -214,21 +214,21 @@ static void atv4_pmgr_soc_write(void *opaque, hwaddr addr, uint64_t value, unsig
|
||||
{
|
||||
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
ATV4PMGRState *s = (struct ATV4PMGRState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
s->scratch[addr] = value;
|
||||
}
|
||||
|
||||
static uint64_t atv4_pmgr_scratch_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
printf("%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
ATV4PMGRState *s = (struct ATV4PMGRState *) opaque;
|
||||
|
||||
switch (addr) {
|
||||
case 0x0 ... 0x60:
|
||||
// TODO return the right scratch configuration
|
||||
case 0x0:
|
||||
return s->scratch[0] | (BOOT_DEVICE_NAND << 8);
|
||||
break;
|
||||
case 0x4 ... 0xC:
|
||||
return s->scratch[addr];
|
||||
default:
|
||||
hw_error("%s: reading from unknown PMGR SCRATCH register 0x%08x\n", __func__, addr);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ static uint64_t atv4_pmgr_scratch_read(void *opaque, hwaddr addr, unsigned size)
|
||||
|
||||
static void atv4_pmgr_scratch_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
printf("%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
ATV4PMGRState *s = (struct ATV4PMGRState *) opaque;
|
||||
|
||||
switch(addr) {
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* S5L8900 SPI Emulation
|
||||
*
|
||||
* by cmw
|
||||
*/
|
||||
|
||||
#include "hw/arm/atv4_spi.h"
|
||||
|
||||
static int apple_spi_word_size(ATV4SPIState *s)
|
||||
{
|
||||
switch (R_CFG_WORD_SIZE(REG(s, R_CFG))) {
|
||||
case R_CFG_WORD_SIZE_8B:
|
||||
return 1;
|
||||
case R_CFG_WORD_SIZE_16B:
|
||||
return 2;
|
||||
case R_CFG_WORD_SIZE_32B:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void apple_spi_update_xfer_tx(ATV4SPIState *s)
|
||||
{
|
||||
if (fifo8_is_empty(&s->tx_fifo)) {
|
||||
REG(s, R_STATUS) |= R_STATUS_TXEMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_spi_update_xfer_rx(ATV4SPIState *s)
|
||||
{
|
||||
if (!fifo8_is_empty(&s->rx_fifo)) {
|
||||
REG(s, R_STATUS) |= R_STATUS_RXREADY;
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_spi_update_irq(ATV4SPIState *s)
|
||||
{
|
||||
uint32_t irq = 0;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (REG(s, R_CFG) & R_CFG_IE_RXREADY) {
|
||||
mask |= R_STATUS_RXREADY;
|
||||
}
|
||||
if (REG(s, R_CFG) & R_CFG_IE_TXEMPTY) {
|
||||
mask |= R_STATUS_TXEMPTY;
|
||||
}
|
||||
if (REG(s, R_CFG) & R_CFG_IE_COMPLETE) {
|
||||
mask |= R_STATUS_COMPLETE;
|
||||
}
|
||||
|
||||
if (REG(s, R_STATUS) & mask) {
|
||||
irq = 1;
|
||||
}
|
||||
if (irq != s->last_irq) {
|
||||
s->last_irq = irq;
|
||||
qemu_set_irq(s->irq, irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_spi_update_cs(ATV4SPIState *s)
|
||||
{
|
||||
BusState *b = BUS(s->spi);
|
||||
BusChild *kid = QTAILQ_FIRST(&b->children);
|
||||
if (kid) {
|
||||
// TODO GPIO not properly setup yet
|
||||
//qemu_set_irq(qdev_get_gpio_in_named(kid->child, SSI_GPIO_CS, 0), (REG(s, R_PIN) & R_PIN_CS) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_spi_cs_set(void *opaque, int pin, int level)
|
||||
{
|
||||
ATV4SPIState *s = ATV4_SPI(opaque);
|
||||
if (level) {
|
||||
REG(s, R_PIN) |= R_PIN_CS;
|
||||
} else {
|
||||
REG(s, R_PIN) &= ~R_PIN_CS;
|
||||
}
|
||||
apple_spi_update_cs(s);
|
||||
}
|
||||
|
||||
static void apple_spi_run(ATV4SPIState *s)
|
||||
{
|
||||
uint32_t tx;
|
||||
uint32_t rx;
|
||||
|
||||
if (!(REG(s, R_CTRL) & R_CTRL_RUN)) {
|
||||
return;
|
||||
}
|
||||
if (REG(s, R_RXCNT) == 0 && REG(s, R_TXCNT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
apple_spi_update_xfer_tx(s);
|
||||
|
||||
//printf("TX queue: %d, RX queue: %d\n", REG(s, R_TXCNT), REG(s, R_RXCNT));
|
||||
//printf("TX buffer size: %d, RX buffer size: %d\n", fifo8_num_used(&s->tx_fifo), fifo8_num_used(&s->rx_fifo));
|
||||
|
||||
while (REG(s, R_TXCNT) && !fifo8_is_empty(&s->tx_fifo)) {
|
||||
tx = (uint32_t)fifo8_pop(&s->tx_fifo);
|
||||
rx = ssi_transfer(s->spi, tx);
|
||||
REG(s, R_TXCNT)--;
|
||||
apple_spi_update_xfer_tx(s);
|
||||
if (REG(s, R_RXCNT) > 0) {
|
||||
if (fifo8_is_full(&s->rx_fifo)) {
|
||||
hw_error("Rx buffer overflow: %d\n", fifo8_num_free(&s->rx_fifo));
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: rx overflow\n", __func__);
|
||||
REG(s, R_STATUS) |= R_STATUS_RXOVERFLOW;
|
||||
} else {
|
||||
fifo8_push(&s->rx_fifo, (uint8_t)rx);
|
||||
REG(s, R_RXCNT)--;
|
||||
apple_spi_update_xfer_rx(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fetch the remaining bytes by sending sentinel bytes.
|
||||
while (!fifo8_is_full(&s->rx_fifo) && (REG(s, R_RXCNT) > 0) && (REG(s, R_CFG) & R_CFG_AGD)) {
|
||||
rx = ssi_transfer(s->spi, 0xff);
|
||||
if (fifo8_is_full(&s->rx_fifo)) {
|
||||
hw_error("Rx buffer overflow: %d\n", fifo8_num_free(&s->rx_fifo));
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: rx overflow\n", __func__);
|
||||
REG(s, R_STATUS) |= R_STATUS_RXOVERFLOW;
|
||||
break;
|
||||
} else {
|
||||
fifo8_push(&s->rx_fifo, (uint8_t)rx);
|
||||
REG(s, R_RXCNT)--;
|
||||
apple_spi_update_xfer_rx(s);
|
||||
}
|
||||
}
|
||||
if (REG(s, R_RXCNT) == 0 && REG(s, R_TXCNT) == 0) {
|
||||
REG(s, R_STATUS) |= R_STATUS_COMPLETE;
|
||||
}
|
||||
|
||||
//printf("<after> TX buffer size: %d, RX buffer size: %d\n", fifo8_num_used(&s->tx_fifo), fifo8_num_used(&s->rx_fifo));
|
||||
}
|
||||
|
||||
static uint64_t atv4_spi_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
ATV4SPIState *s = ATV4_SPI(opaque);
|
||||
//printf("%s (base %d): read from location 0x%08x\n", __func__, s->base, addr);
|
||||
|
||||
uint32_t r;
|
||||
bool run = false;
|
||||
|
||||
r = s->regs[addr >> 2];
|
||||
switch (addr) {
|
||||
case R_RXDATA: {
|
||||
const uint8_t *buf = NULL;
|
||||
int word_size = apple_spi_word_size(s);
|
||||
uint32_t num = 0;
|
||||
if (fifo8_is_empty(&s->rx_fifo)) {
|
||||
hw_error("Rx buffer underflow\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: rx underflow\n", __func__);
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
buf = fifo8_pop_buf(&s->rx_fifo, word_size, &num);
|
||||
memcpy(&r, buf, num);
|
||||
|
||||
if (fifo8_is_empty(&s->rx_fifo)) {
|
||||
run = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_STATUS: {
|
||||
int val = 0;
|
||||
val |= (fifo8_num_used(&s->tx_fifo) << R_STATUS_TXFIFO_SHIFT);
|
||||
val |= (fifo8_num_used(&s->rx_fifo) << R_STATUS_RXFIFO_SHIFT);
|
||||
r |= val;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (run) {
|
||||
apple_spi_run(s);
|
||||
}
|
||||
apple_spi_update_irq(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void atv4_spi_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
|
||||
{
|
||||
ATV4SPIState *s = ATV4_SPI(opaque);
|
||||
//printf("%s (base %d): writing 0x%08x to 0x%08x\n", __func__, s->base, data, addr);
|
||||
|
||||
uint32_t r = data;
|
||||
uint32_t *mmio = ®(s, addr);
|
||||
uint32_t old = *mmio;
|
||||
bool cs_flg = false;
|
||||
bool run = false;
|
||||
|
||||
switch (addr) {
|
||||
case R_CTRL:
|
||||
if (r & R_CTRL_TX_RESET) {
|
||||
fifo8_reset(&s->tx_fifo);
|
||||
}
|
||||
if (r & R_CTRL_RX_RESET) {
|
||||
fifo8_reset(&s->rx_fifo);
|
||||
}
|
||||
if (r & R_CTRL_RUN && !fifo8_is_empty(&s->tx_fifo)) {
|
||||
run = true;
|
||||
}
|
||||
break;
|
||||
case R_STATUS:
|
||||
run = true;
|
||||
r = old & (~r);
|
||||
break;
|
||||
case R_PIN:
|
||||
cs_flg = true;
|
||||
break;
|
||||
case R_TXDATA ... R_TXDATA + 3: {
|
||||
int word_size = apple_spi_word_size(s);
|
||||
if (fifo8_is_full(&s->tx_fifo) || fifo8_num_free(&s->tx_fifo) < word_size) {
|
||||
hw_error("Tx buffer overflow: %d\n", fifo8_num_free(&s->tx_fifo));
|
||||
}
|
||||
fifo8_push_all(&s->tx_fifo, (uint8_t *)&r, word_size);
|
||||
break;
|
||||
case R_CFG:
|
||||
run = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*mmio = r;
|
||||
if (cs_flg) {
|
||||
apple_spi_update_cs(s);
|
||||
}
|
||||
if (run) {
|
||||
apple_spi_run(s);
|
||||
}
|
||||
|
||||
if(addr == R_STATUS) {
|
||||
apple_spi_update_xfer_tx(s);
|
||||
apple_spi_update_xfer_rx(s);
|
||||
}
|
||||
|
||||
apple_spi_update_irq(s);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps spi_ops = {
|
||||
.read = atv4_spi_read,
|
||||
.write = atv4_spi_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void atv4_spi_reset(DeviceState *d)
|
||||
{
|
||||
ATV4SPIState *s = (ATV4SPIState *)d;
|
||||
memset(s->regs, 0, sizeof(s->regs));
|
||||
fifo8_reset(&s->tx_fifo);
|
||||
fifo8_reset(&s->rx_fifo);
|
||||
}
|
||||
|
||||
static uint32_t base_addr = 0;
|
||||
|
||||
void set_spi_base(uint32_t base)
|
||||
{
|
||||
base_addr = base;
|
||||
}
|
||||
|
||||
static void atv4_spi_realize(DeviceState *dev, struct Error **errp)
|
||||
{
|
||||
ATV4SPIState *s = ATV4_SPI(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
char bus_name[32] = { 0 };
|
||||
snprintf(bus_name, sizeof(bus_name), "%s.bus", dev->id);
|
||||
s->spi = ssi_create_bus(dev, (const char *)bus_name);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
sysbus_init_irq(sbd, &s->cs_line);
|
||||
qdev_init_gpio_in_named(dev, apple_spi_cs_set, SSI_GPIO_CS, 1);
|
||||
char name[5];
|
||||
snprintf(name, 5, "spi%d", base_addr);
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &spi_ops, s, name, 0x100);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
s->base = base_addr;
|
||||
|
||||
fifo8_create(&s->tx_fifo, R_FIFO_TX_DEPTH);
|
||||
fifo8_create(&s->rx_fifo, R_FIFO_RX_DEPTH);
|
||||
|
||||
// // create the peripheral
|
||||
// switch(s->base) {
|
||||
// case 0:
|
||||
// {
|
||||
// DeviceState *dev = ssi_create_peripheral(s->spi, TYPE_IPOD_TOUCH_NOR_SPI);
|
||||
// IPodTouchNORSPIState *nor = IPOD_TOUCH_NOR_SPI(dev);
|
||||
// s->nor = nor;
|
||||
// break;
|
||||
// }
|
||||
// case 1:
|
||||
// break;
|
||||
// case 4:
|
||||
// {
|
||||
// DeviceState *dev = ssi_create_peripheral(s->spi, TYPE_IPOD_TOUCH_MULTITOUCH);
|
||||
// IPodTouchMultitouchState *mt = IPOD_TOUCH_MULTITOUCH(dev);
|
||||
// s->mt = mt;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static void atv4_spi_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
dc->realize = atv4_spi_realize;
|
||||
dc->reset = atv4_spi_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo atv4_spi_info = {
|
||||
.name = TYPE_ATV4_SPI,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ATV4SPIState),
|
||||
.class_init = atv4_spi_class_init,
|
||||
};
|
||||
|
||||
static void atv4_spi_register_types(void)
|
||||
{
|
||||
type_register_static(&atv4_spi_info);
|
||||
}
|
||||
|
||||
type_init(atv4_spi_register_types)
|
||||
+1
-1
@@ -65,7 +65,7 @@ arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
|
||||
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
|
||||
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
|
||||
arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
|
||||
arm_ss.add(when: 'CONFIG_ATV4', if_true: files('atv4.c', 'atv4_chipid.c', 'atv4_pmgr.c', 'atv4_gpio.c', 'atv4_ausb.c'))
|
||||
arm_ss.add(when: 'CONFIG_ATV4', if_true: files('atv4.c', 'atv4_chipid.c', 'atv4_pmgr.c', 'atv4_gpio.c', 'atv4_ausb.c', 'atv4_ausb_widget.c', 'atv4_spi.c', 'atv4_anc.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
|
||||
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
|
||||
|
||||
+20
-2
@@ -10,6 +10,9 @@
|
||||
#include "hw/arm/atv4_pmgr.h"
|
||||
#include "hw/arm/atv4_gpio.h"
|
||||
#include "hw/arm/atv4_ausb.h"
|
||||
#include "hw/arm/atv4_ausb_widget.h"
|
||||
#include "hw/arm/atv4_spi.h"
|
||||
#include "hw/arm/atv4_anc.h"
|
||||
|
||||
#define TYPE_ATV4 "ATV4"
|
||||
|
||||
@@ -20,12 +23,23 @@
|
||||
#define ATV4_MACHINE(obj) \
|
||||
OBJECT_CHECK(ATV4MachineState, (obj), TYPE_ATV4_MACHINE)
|
||||
|
||||
#define NUM_SPI_PORTS 4
|
||||
#define SRAM_LENGTH 0x400000 // 4MB
|
||||
|
||||
// memory addresses
|
||||
#define VROM_MEM_BASE 0x100000000
|
||||
#define UNKNOWN1_MEM_BASE 0x180000000
|
||||
#define SRAM_MEM_BASE 0x180000000
|
||||
#define UNKNOWN2_MEM_BASE 0x202220000
|
||||
#define UNKNOWN3_MEM_BASE 0x202240000
|
||||
#define AUSB_MEM_BASE 0x20c900000
|
||||
#define PPNNPL_MEM_BASE 0x208081000
|
||||
#define ANC0_MEM_BASE 0x208800000
|
||||
#define ANC1_MEM_BASE 0x208900000
|
||||
#define SPI0_MEM_BASE 0x20a080000
|
||||
#define SPI1_MEM_BASE 0x20a084000
|
||||
#define SPI2_MEM_BASE 0x20a088000
|
||||
#define SPI3_MEM_BASE 0x20a08C000
|
||||
#define AUSB_MEM_BASE 0x20c000000
|
||||
#define AUSB_WIDGET_MEM_BASE 0x20c900000
|
||||
#define PMGR_MEM_BASE 0x20e000000
|
||||
#define AIC_MEM_BASE 0x20e100000
|
||||
#define GPIO_MEM_BASE 0x20e300000
|
||||
@@ -55,6 +69,10 @@ typedef struct {
|
||||
ATV4PMGRState *pmgr_state;
|
||||
ATV4GPIOState *gpio_state;
|
||||
ATV4AUSBState *ausb_state;
|
||||
ATV4AUSBWidgetState *ausb_widget_state;
|
||||
ATV4SPIState *spi_state[4];
|
||||
ATV4ANCState *anc0_state;
|
||||
ATV4ANCState *anc1_state;
|
||||
ATV4_CPREG_VAR_DEF(REG0);
|
||||
ATV4_CPREG_VAR_DEF(REG1);
|
||||
ATV4_CPREG_VAR_DEF(REG2);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef HW_ARM_ATV4_ANC_H
|
||||
#define HW_ARM_ATV4_ANC_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ATV4_ANC "atv4.anc"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4ANCState, ATV4_ANC)
|
||||
|
||||
typedef struct ATV4ANCState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion ppnnpl_iomem;
|
||||
MemoryRegion anc_iomem;
|
||||
} ATV4ANCState;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef HW_ARM_ATV4_AUSB_WIDGET_H
|
||||
#define HW_ARM_ATV4_AUSB_WIDGET_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ATV4_AUSB_WIDGET "atv4.ausbwidget"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4AUSBWidgetState, ATV4_AUSB_WIDGET)
|
||||
|
||||
typedef struct ATV4AUSBWidgetState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem;
|
||||
} ATV4AUSBWidgetState;
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,16 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
enum boot_device {
|
||||
BOOT_DEVICE_NOR = 0,
|
||||
BOOT_DEVICE_SPI,
|
||||
BOOT_DEVICE_NAND,
|
||||
BOOT_DEVICE_NVME,
|
||||
BOOT_DEVICE_USBDFU,
|
||||
BOOT_DEVICE_TBTDFU,
|
||||
BOOT_DEVICE_XMODEM,
|
||||
};
|
||||
|
||||
#define TYPE_ATV4_PMGR "atv4.pmgr"
|
||||
#define TYPE_ATV4_PMGR_VOLMAN "atv4.pmgr.volman"
|
||||
#define TYPE_ATV4_PMGR_PS "atv4.pmgr.ps"
|
||||
@@ -173,6 +183,7 @@ typedef struct ATV4PMGRState {
|
||||
MemoryRegion scratch_iomem;
|
||||
MemoryRegion pwrgate_iomem;
|
||||
uint64_t pll_bypass_cfg[6];
|
||||
uint64_t scratch[0x4];
|
||||
} ATV4PMGRState;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef HW_ARM_ATV4_SPI_H
|
||||
#define HW_ARM_ATV4_SPI_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/fifo8.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/platform-bus.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/ssi/ssi.h"
|
||||
|
||||
#define TYPE_ATV4_SPI "atv4.spi"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ATV4SPIState, ATV4_SPI)
|
||||
|
||||
#define R_CTRL 0x000
|
||||
#define R_CTRL_RUN (1 << 0)
|
||||
#define R_CTRL_TX_RESET (1 << 2)
|
||||
#define R_CTRL_RX_RESET (1 << 3)
|
||||
|
||||
#define R_CFG 0x004
|
||||
#define R_CFG_AGD (1 << 0)
|
||||
#define R_CFG_CPHA (1 << 1)
|
||||
#define R_CFG_CPOL (1 << 2)
|
||||
#define R_CFG_IE_RXREADY (1 << 7)
|
||||
#define R_CFG_IE_TXEMPTY (1 << 8)
|
||||
#define R_CFG_WORD_SIZE(_x) (((_x) >> 15) & 0x3)
|
||||
#define R_CFG_WORD_SIZE_8B 0
|
||||
#define R_CFG_WORD_SIZE_16B 1
|
||||
#define R_CFG_WORD_SIZE_32B 2
|
||||
#define R_CFG_IE_COMPLETE (1 << 21)
|
||||
|
||||
#define R_STATUS 0x008
|
||||
#define R_STATUS_RXREADY (1 << 0)
|
||||
#define R_STATUS_TXEMPTY (1 << 1)
|
||||
#define R_STATUS_RXOVERFLOW (1 << 3)
|
||||
#define R_STATUS_COMPLETE (1 << 22)
|
||||
#define R_STATUS_TXFIFO_SHIFT (6)
|
||||
#define R_STATUS_RXFIFO_SHIFT (11)
|
||||
|
||||
#define R_PIN 0x00c
|
||||
#define R_PIN_CS (1 << 1)
|
||||
|
||||
#define R_TXDATA 0x010
|
||||
#define R_RXDATA 0x020
|
||||
#define R_CLKDIV 0x030
|
||||
#define R_CLKDIV_MAX 0x7ff
|
||||
#define R_RXCNT 0x034
|
||||
#define R_WORD_DELAY 0x038
|
||||
#define R_TXCNT 0x04c
|
||||
|
||||
#define R_FIFO_TX_DEPTH 50000
|
||||
#define R_FIFO_RX_DEPTH 16
|
||||
|
||||
#define REG(_s,_v) ((_s)->regs[(_v)>>2])
|
||||
#define MMIO_SIZE (0x4000)
|
||||
|
||||
|
||||
typedef struct ATV4SPIState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
SSIBus *spi;
|
||||
|
||||
qemu_irq irq;
|
||||
uint32_t last_irq;
|
||||
qemu_irq cs_line;
|
||||
|
||||
uint32_t regs[MMIO_SIZE >> 2];
|
||||
uint8_t base;
|
||||
Fifo8 rx_fifo;
|
||||
Fifo8 tx_fifo;
|
||||
} ATV4SPIState;
|
||||
|
||||
void set_spi_base(uint32_t base);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user