Refactored NAND/NAND ECC into separate files

This commit is contained in:
Martijn de Vos committed 2021-12-26 13:28:12 +01:00
1 parent df09005a18
commit 7475713599
7 files changed
+249 -147

No files matched your search

+9 -109
View File
@@ -302,105 +302,6 @@ static const MemoryRegionOps sysic_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
/*
NAND
*/
static int nand_read_cnt = 0;
static uint64_t s5l8900_nand_read(void *opaque, hwaddr addr, unsigned size)
{
s5l8900_nand_s *s = (s5l8900_nand_s *) opaque;
//fprintf(stderr, "%s: reading from 0x%08x\n", __func__, addr);
switch (addr) {
case NAND_FMCTRL0:
return s->fmctrl0;
case NAND_FMFIFO:
if(s->cmd == NAND_CMD_ID) {
return 0xA514D3AD;
}
else if(s->cmd == NAND_CMD_READSTATUS) {
return (1 << 6);
}
else {
nand_read_cnt++;
return 0x43303032;
}
case NAND_FMCSTAT:
return (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12); // this indicates that everything is ready, including our eight banks
case NAND_RSCTRL:
return s->rsctrl;
default:
break;
}
return 0;
}
static void s5l8900_nand_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
s5l8900_nand_s *s = (s5l8900_nand_s *) opaque;
switch(addr) {
case NAND_FMCTRL0:
s->fmctrl0 = val;
break;
case NAND_CMD:
s->cmd = val;
break;
case NAND_RSCTRL:
s->rsctrl = val;
break;
default:
break;
}
}
static const MemoryRegionOps nand_ops = {
.read = s5l8900_nand_read,
.write = s5l8900_nand_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
/*
NAND ECC
*/
static uint64_t s5l8900_nand_ecc_read(void *opaque, hwaddr addr, unsigned size)
{
s5l8900_nand_ecc_s *s = (s5l8900_nand_ecc_s *) opaque;
//fprintf(stderr, "%s: reading from 0x%08x\n", __func__, addr);
switch (addr) {
case NANDECC_STATUS:
return 0; // TODO: for now, we assume that all ECC operations are successful
default:
break;
}
return 0;
}
static void s5l8900_nand_ecc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
s5l8900_nand_ecc_s *s = (s5l8900_nand_ecc_s *) opaque;
switch(addr) {
case NANDECC_START:
qemu_irq_raise(s->irq);
break;
case NANDECC_CLEARINT:
qemu_irq_lower(s->irq);
break;
default:
break;
}
}
static const MemoryRegionOps nand_ecc_ops = {
.read = s5l8900_nand_ecc_read,
.write = s5l8900_nand_ecc_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
/*
USB PHYS
*/
@@ -928,19 +829,18 @@ static void ipod_touch_machine_init(MachineState *machine)
memory_region_add_subregion(sysmem, ENGINE_8900_MEM_BASE, iomem);
// init NAND flash
s5l8900_nand_s *nand_state = malloc(sizeof(s5l8900_nand_s));
dev = qdev_new("itnand");
ITNandState *nand_state = ITNAND(dev);
nms->nand_state = nand_state;
iomem = g_new(MemoryRegion, 1);
memory_region_init_io(iomem, OBJECT(s), &nand_ops, s, "nand", 0x1000);
memory_region_add_subregion(sysmem, NAND_MEM_BASE, iomem);
memory_region_add_subregion(sysmem, NAND_MEM_BASE, &nand_state->iomem);
// init NAND ECC module
s5l8900_nand_ecc_s *nand_ecc_state = malloc(sizeof(s5l8900_nand_ecc_s));
dev = qdev_new("itnand_ecc");
ITNandECCState *nand_ecc_state = ITNANDECC(dev);
nms->nand_ecc_state = nand_ecc_state;
nand_ecc_state->irq = s5l8900_get_irq(nms, S5L8900_NAND_ECC_IRQ);
iomem = g_new(MemoryRegion, 1);
memory_region_init_io(iomem, OBJECT(s), &nand_ecc_ops, nand_ecc_state, "nandecc", 0x100);
memory_region_add_subregion(sysmem, NAND_ECC_MEM_BASE, iomem);
SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8900_NAND_ECC_IRQ));
memory_region_add_subregion(sysmem, NAND_ECC_MEM_BASE, &nand_ecc_state->iomem);
// init USB OTG
dev = ipod_touch_init_usb_otg(nms->irq[0][13], s5l8900_usb_hwcfg);
@@ -986,7 +886,7 @@ static void ipod_touch_machine_init(MachineState *machine)
PL080State *pl080_1 = PL080(dev);
object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem), &error_fatal);
memory_region_add_subregion(sysmem, DMAC0_MEM_BASE, &pl080_1->iomem);
SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8900_DMAC0_IRQ));
+97
View File
@@ -0,0 +1,97 @@
#include "hw/arm/ipod_touch_nand.h"
static int nand_read_cnt = 0;
static uint64_t itnand_read(void *opaque, hwaddr addr, unsigned size)
{
ITNandState *s = (ITNandState *) opaque;
//fprintf(stderr, "%s: reading from 0x%08x\n", __func__, addr);
switch (addr) {
case NAND_FMCTRL0:
return s->fmctrl0;
case NAND_FMFIFO:
if(s->cmd == NAND_CMD_ID) {
return 0xA514D3AD;
}
else if(s->cmd == NAND_CMD_READSTATUS) {
return (1 << 6);
}
else {
nand_read_cnt++;
return 0x43303032;
}
case NAND_FMCSTAT:
return (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12); // this indicates that everything is ready, including our eight banks
case NAND_RSCTRL:
return s->rsctrl;
default:
break;
}
return 0;
}
static void itnand_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
ITNandState *s = (ITNandState *) opaque;
switch(addr) {
case NAND_FMCTRL0:
s->fmctrl0 = val;
break;
case NAND_CMD:
s->cmd = val;
break;
case NAND_RSCTRL:
s->rsctrl = val;
break;
default:
break;
}
}
static const MemoryRegionOps nand_ops = {
.read = itnand_read,
.write = itnand_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void itnand_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ITNandState *s = ITNAND(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &nand_ops, s, "nand", 0x1000);
sysbus_init_irq(sbd, &s->irq);
}
static void itnand_reset(DeviceState *d)
{
ITNandState *s = (ITNandState *) d;
s->fmctrl0 = 0;
s->rsctrl = 0;
s->cmd = 0;
}
static void itnand_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->reset = itnand_reset;
}
static const TypeInfo itnand_info = {
.name = TYPE_ITNAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ITNandState),
.instance_init = itnand_init,
.class_init = itnand_class_init,
};
static void itnand_register_types(void)
{
type_register_static(&itnand_info);
}
type_init(itnand_register_types)
+77
View File
@@ -0,0 +1,77 @@
#include "hw/arm/ipod_touch_nand_ecc.h"
static uint64_t itnand_ecc_read(void *opaque, hwaddr addr, unsigned size)
{
ITNandECCState *s = (ITNandECCState *) opaque;
//fprintf(stderr, "%s: reading from 0x%08x\n", __func__, addr);
switch (addr) {
case NANDECC_STATUS:
return 0; // TODO: for now, we assume that all ECC operations are successful
default:
break;
}
return 0;
}
static void itnand_ecc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
ITNandECCState *s = (ITNandECCState *) opaque;
switch(addr) {
case NANDECC_START:
qemu_irq_raise(s->irq);
break;
case NANDECC_CLEARINT:
qemu_irq_lower(s->irq);
break;
default:
break;
}
}
static const MemoryRegionOps nand_ecc_ops = {
.read = itnand_ecc_read,
.write = itnand_ecc_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void itnand_ecc_init(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
ITNandECCState *s = ITNANDECC(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &nand_ecc_ops, s, "nandecc", 0x100);
sysbus_init_irq(sbd, &s->irq);
}
static void itnand_ecc_reset(DeviceState *d)
{
ITNandECCState *s = (ITNandECCState *) d;
s->data_addr = 0;
s->ecc_addr = 0;
s->status = 0;
s->setup = 0;
}
static void itnand_ecc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->reset = itnand_ecc_reset;
}
static const TypeInfo itnand_ecc_info = {
.name = TYPE_ITNANDECC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ITNandECCState),
.instance_init = itnand_ecc_init,
.class_init = itnand_ecc_class_init,
};
static void itnand_ecc_register_types(void)
{
type_register_static(&itnand_ecc_info);
}
type_init(itnand_ecc_register_types)
+1 -1
View File
@@ -58,6 +58,6 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c', '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_IPOD_TOUCH', if_true: files('ipod_touch.c', 'xnu.c', 'xnu_mem.c', 'xnu_dtb.c', 'ipod_touch_spi.c', 'ipod_touch_aes.c', 'ipod_touch_sha1.c', 'ipod_touch_usb_otg.c', 'ipod_touch_8900_engine.c'))
arm_ss.add(when: 'CONFIG_IPOD_TOUCH', if_true: files('ipod_touch.c', 'xnu.c', 'xnu_mem.c', 'xnu_dtb.c', 'ipod_touch_spi.c', 'ipod_touch_aes.c', 'ipod_touch_sha1.c', 'ipod_touch_usb_otg.c', 'ipod_touch_8900_engine.c', 'ipod_touch_nand.c', 'ipod_touch_nand_ecc.c'))
hw_arch += {'arm': arm_ss}
+4 -37
View File
@@ -11,6 +11,8 @@
#include "hw/arm/ipod_touch_sha1.h"
#include "hw/arm/ipod_touch_8900_engine.h"
#include "hw/arm/ipod_touch_usb_otg.h"
#include "hw/arm/ipod_touch_nand.h"
#include "hw/arm/ipod_touch_nand_ecc.h"
#include "cpu.h"
#define TYPE_IPOD_TOUCH "iPod-Touch"
@@ -66,24 +68,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(s5l8900_lcd_state, IPOD_TOUCH_LCD)
#define S5L8900_NAND_ECC_IRQ 0x2B
// NAND
#define NAND_FMCTRL0 0x0
#define NAND_CMD 0x8
#define NAND_FMCSTAT 0x48
#define NAND_FMFIFO 0x80
#define NAND_RSCTRL 0x100
#define NAND_CMD_ID 0x90
#define NAND_CMD_READSTATUS 0x70
// NAND ECC
#define NANDECC_DATA 0x4
#define NANDECC_ECC 0x8
#define NANDECC_START 0xC
#define NANDECC_STATUS 0x10
#define NANDECC_SETUP 0x14
#define NANDECC_CLEARINT 0x40
typedef struct {
MachineClass parent;
} IPodTouchMachineClass;
@@ -131,22 +115,6 @@ typedef struct s5l8900_timer_s
} s5l8900_timer_s;
typedef struct s5l8900_nand_s
{
uint32_t fmctrl0;
uint32_t rsctrl;
uint32_t cmd;
} s5l8900_nand_s;
typedef struct s5l8900_nand_ecc_s
{
uint32_t data_addr;
uint32_t ecc_addr;
uint32_t status;
uint32_t setup;
qemu_irq irq;
} s5l8900_nand_ecc_s;
typedef struct s5l8900_sysic_s
{
uint32_t power_state;
@@ -178,8 +146,8 @@ typedef struct {
s5l8900_usb_phys_s *usb_phys;
S5L8900AESState *aes_state;
S5L8900SHA1State *sha1_state;
s5l8900_nand_s *nand_state;
s5l8900_nand_ecc_s *nand_ecc_state;
ITNandState *nand_state;
ITNandECCState *nand_ecc_state;
Clock *sysclk;
uint32_t kpc_pa;
uint32_t kbootargs_pa;
@@ -188,7 +156,6 @@ typedef struct {
char kernel_filename[1024];
char dtb_filename[1024];
char kern_args[256];
uint64_t printf_buffer[256];
} IPodTouchMachineState;
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef HW_ARM_IPOD_TOUCH_NAND_H
#define HW_ARM_IPOD_TOUCH_NAND_H
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/platform-bus.h"
#include "hw/hw.h"
#include "hw/irq.h"
#define NAND_FMCTRL0 0x0
#define NAND_CMD 0x8
#define NAND_FMCSTAT 0x48
#define NAND_FMFIFO 0x80
#define NAND_RSCTRL 0x100
#define NAND_CMD_ID 0x90
#define NAND_CMD_READSTATUS 0x70
#define TYPE_ITNAND "itnand"
OBJECT_DECLARE_SIMPLE_TYPE(ITNandState, ITNAND)
typedef struct ITNandState {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t fmctrl0;
uint32_t rsctrl;
uint32_t cmd;
qemu_irq irq;
} ITNandState;
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef HW_ARM_IPOD_TOUCH_NAND_ECC_H
#define HW_ARM_IPOD_TOUCH_NAND_ECC_H
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/platform-bus.h"
#include "hw/hw.h"
#include "hw/irq.h"
#define NANDECC_DATA 0x4
#define NANDECC_ECC 0x8
#define NANDECC_START 0xC
#define NANDECC_STATUS 0x10
#define NANDECC_SETUP 0x14
#define NANDECC_CLEARINT 0x40
#define TYPE_ITNANDECC "itnand_ecc"
OBJECT_DECLARE_SIMPLE_TYPE(ITNandECCState, ITNANDECC)
typedef struct ITNandECCState {
SysBusDevice busdev;
MemoryRegion iomem;
uint32_t data_addr;
uint32_t ecc_addr;
uint32_t status;
uint32_t setup;
qemu_irq irq;
} ITNandECCState;
#endif