Renesas SH-4 patches queue
Patches from Zoltan: - Various clean up to align the code style with the rest of the code base - QOM'ify the SH_SERIAL device - Modify few memory region size to better match the hardware manual -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmF9ez8ACgkQ4+MsLN6t wN5jIBAAySm8Q7cDR/CVI+ubaAD1dW0sBAH6WVFd+P/pz6XotvLH9qvFjspTrKmw QujMLr/oDP3z/JvVZGpe3ArCkCoqoy9Q+hDFYfwgGmOun0p6bLLw7GC6qoWUwdfE BPVaZIbeW15ujn7Cawul+2rU2TIwcp+rtSg4KnKuLQp+1kKrkVlZDYp4YZeUjpIJ 98KhnLRO38V/VUVvtuJjK/Vksc7mdP2es1kmStq5HKGYXKCTd68JAPi7OCxg4mKj IxGyamy8aK6khW1ccIeaCJv6NStHR1rVlFQDG10HildAcOvrJDUyQjBqYbDfh/Gj zsbpXw0fwz+GWmQlj2d7ndfYNNqr+G6IwBNrzVcnDoJYlVmLrJUOYnY509hcVhVY c33XgXYSurSskG5kSdhpZLIN4inrnRoX410gCi14mqxcjl88DTbeIjqUzizaHzRU xCgIAjNKnryEimGb8cEShftBT/U9t/VeXXxfe+MfoBCG0sKczUp6QVHhkq6dH5qV xFAZOQyxw6lLaTrcQQByCBh+NFyqtrYFsqS1b1Or3z0ZfKF65Y8M5sx1RufhybfV UutGY7JaZU3MJEeT6UY9XHSZXwGLajixjXuYR25Gj/LYgOSMIP0iqsci2V0AfBLQ u1Z54qIllDVAickaHLlBfI2jn6XXfzZ09+POHOsf//b39i1QjIk= =ktI+ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/philmd/tags/renesas-20211030' into staging Renesas SH-4 patches queue Patches from Zoltan: - Various clean up to align the code style with the rest of the code base - QOM'ify the SH_SERIAL device - Modify few memory region size to better match the hardware manual # gpg: Signature made Sat 30 Oct 2021 10:05:03 AM PDT # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] * remotes/philmd/tags/renesas-20211030: (30 commits) hw/timer/sh_timer: Remove use of hw_error hw/timer/sh_timer: Fix timer memory region size hw/timer/sh_timer: Do not wrap lines that are not too long hw/timer/sh_timer: Rename sh_timer_state to SHTimerState hw/intc/sh_intc: Remove unneeded local variable initialisers hw/intc/sh_intc: Simplify allocating sources array hw/intc/sh_intc: Avoid using continue in loops hw/intc/sh_intc: Replace abort() with g_assert_not_reached() hw/intc/sh_intc: Inline and drop sh_intc_source() function hw/intc/sh_intc: Use array index instead of pointer arithmetics hw/intc/sh_intc: Remove excessive parenthesis hw/intc/sh_intc: Move sh_intc_register() closer to its only user hw/intc/sh_intc: Drop another useless macro hw/intc/sh_intc: Rename iomem region hw/intc/sh_intc: Turn some defines into an enum hw/intc/sh_intc: Use existing macro instead of local one hw/char/sh_serial: Add device id to trace output hw/char/sh_serial: QOM-ify hw/char/sh_serial: Split off sh_serial_reset() from sh_serial_init() hw/char/sh_serial: Embed QEMUTimer in state struct ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
af531756d2
@ -26,13 +26,17 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
//#define DEBUG_SERIAL
|
||||
#include "qemu/log.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define SH_SERIAL_FLAG_TEND (1 << 0)
|
||||
#define SH_SERIAL_FLAG_TDE (1 << 1)
|
||||
@ -42,10 +46,10 @@
|
||||
|
||||
#define SH_RX_FIFO_LENGTH (16)
|
||||
|
||||
typedef struct {
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion iomem_p4;
|
||||
MemoryRegion iomem_a7;
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(SHSerialState, SH_SERIAL)
|
||||
|
||||
struct SHSerialState {
|
||||
SysBusDevice parent;
|
||||
uint8_t smr;
|
||||
uint8_t brr;
|
||||
uint8_t scr;
|
||||
@ -59,13 +63,12 @@ typedef struct {
|
||||
uint8_t rx_tail;
|
||||
uint8_t rx_head;
|
||||
|
||||
int freq;
|
||||
int feat;
|
||||
uint8_t feat;
|
||||
int flags;
|
||||
int rtrg;
|
||||
|
||||
CharBackend chr;
|
||||
QEMUTimer *fifo_timeout_timer;
|
||||
QEMUTimer fifo_timeout_timer;
|
||||
uint64_t etu; /* Elementary Time Unit (ns) */
|
||||
|
||||
qemu_irq eri;
|
||||
@ -73,9 +76,13 @@ typedef struct {
|
||||
qemu_irq txi;
|
||||
qemu_irq tei;
|
||||
qemu_irq bri;
|
||||
} sh_serial_state;
|
||||
};
|
||||
|
||||
static void sh_serial_clear_fifo(sh_serial_state * s)
|
||||
typedef struct {} SHSerialStateClass;
|
||||
|
||||
OBJECT_DEFINE_TYPE(SHSerialState, sh_serial, SH_SERIAL, SYS_BUS_DEVICE)
|
||||
|
||||
static void sh_serial_clear_fifo(SHSerialState *s)
|
||||
{
|
||||
memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
|
||||
s->rx_cnt = 0;
|
||||
@ -86,13 +93,11 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
|
||||
static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
SHSerialState *s = opaque;
|
||||
DeviceState *d = DEVICE(s);
|
||||
unsigned char ch;
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
printf("sh_serial: write offs=0x%02x val=0x%02x\n",
|
||||
offs, val);
|
||||
#endif
|
||||
trace_sh_serial_write(d->id, size, offs, val);
|
||||
switch (offs) {
|
||||
case 0x00: /* SMR */
|
||||
s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
|
||||
@ -103,8 +108,9 @@ static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
case 0x08: /* SCR */
|
||||
/* TODO : For SH7751, SCIF mask should be 0xfb. */
|
||||
s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
|
||||
if (!(val & (1 << 5)))
|
||||
if (!(val & (1 << 5))) {
|
||||
s->flags |= SH_SERIAL_FLAG_TEND;
|
||||
}
|
||||
if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
|
||||
qemu_set_irq(s->txi, val & (1 << 7));
|
||||
}
|
||||
@ -115,8 +121,10 @@ static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
case 0x0c: /* FTDR / TDR */
|
||||
if (qemu_chr_fe_backend_connected(&s->chr)) {
|
||||
ch = val;
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
/*
|
||||
* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks
|
||||
*/
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
s->dr = val;
|
||||
@ -131,16 +139,21 @@ static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
if (s->feat & SH_SERIAL_FEAT_SCIF) {
|
||||
switch (offs) {
|
||||
case 0x10: /* FSR */
|
||||
if (!(val & (1 << 6)))
|
||||
if (!(val & (1 << 6))) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_TEND;
|
||||
if (!(val & (1 << 5)))
|
||||
}
|
||||
if (!(val & (1 << 5))) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_TDE;
|
||||
if (!(val & (1 << 4)))
|
||||
}
|
||||
if (!(val & (1 << 4))) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_BRK;
|
||||
if (!(val & (1 << 1)))
|
||||
}
|
||||
if (!(val & (1 << 1))) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_RDF;
|
||||
if (!(val & (1 << 0)))
|
||||
}
|
||||
if (!(val & (1 << 0))) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_DR;
|
||||
}
|
||||
|
||||
if (!(val & (1 << 1)) || !(val & (1 << 0))) {
|
||||
if (s->rxi) {
|
||||
@ -176,8 +189,7 @@ static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
case 0x24: /* LSR */
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
switch (offs) {
|
||||
#if 0
|
||||
case 0x0c:
|
||||
@ -192,17 +204,17 @@ static void sh_serial_write(void *opaque, hwaddr offs,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "sh_serial: unsupported write to 0x%02"
|
||||
HWADDR_PRIx "\n", offs);
|
||||
abort();
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: unsupported write to 0x%02" HWADDR_PRIx "\n",
|
||||
__func__, offs);
|
||||
}
|
||||
|
||||
static uint64_t sh_serial_read(void *opaque, hwaddr offs,
|
||||
unsigned size)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
uint32_t ret = ~0;
|
||||
SHSerialState *s = opaque;
|
||||
DeviceState *d = DEVICE(s);
|
||||
uint32_t ret = UINT32_MAX;
|
||||
|
||||
#if 0
|
||||
switch (offs) {
|
||||
@ -230,30 +242,38 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
|
||||
break;
|
||||
case 0x10: /* FSR */
|
||||
ret = 0;
|
||||
if (s->flags & SH_SERIAL_FLAG_TEND)
|
||||
if (s->flags & SH_SERIAL_FLAG_TEND) {
|
||||
ret |= (1 << 6);
|
||||
if (s->flags & SH_SERIAL_FLAG_TDE)
|
||||
}
|
||||
if (s->flags & SH_SERIAL_FLAG_TDE) {
|
||||
ret |= (1 << 5);
|
||||
if (s->flags & SH_SERIAL_FLAG_BRK)
|
||||
}
|
||||
if (s->flags & SH_SERIAL_FLAG_BRK) {
|
||||
ret |= (1 << 4);
|
||||
if (s->flags & SH_SERIAL_FLAG_RDF)
|
||||
}
|
||||
if (s->flags & SH_SERIAL_FLAG_RDF) {
|
||||
ret |= (1 << 1);
|
||||
if (s->flags & SH_SERIAL_FLAG_DR)
|
||||
}
|
||||
if (s->flags & SH_SERIAL_FLAG_DR) {
|
||||
ret |= (1 << 0);
|
||||
}
|
||||
|
||||
if (s->scr & (1 << 5))
|
||||
if (s->scr & (1 << 5)) {
|
||||
s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x14:
|
||||
if (s->rx_cnt > 0) {
|
||||
ret = s->rx_fifo[s->rx_tail++];
|
||||
s->rx_cnt--;
|
||||
if (s->rx_tail == SH_RX_FIFO_LENGTH)
|
||||
if (s->rx_tail == SH_RX_FIFO_LENGTH) {
|
||||
s->rx_tail = 0;
|
||||
if (s->rx_cnt < s->rtrg)
|
||||
}
|
||||
if (s->rx_cnt < s->rtrg) {
|
||||
s->flags &= ~SH_SERIAL_FLAG_RDF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x18:
|
||||
ret = s->fcr;
|
||||
@ -268,8 +288,7 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
switch (offs) {
|
||||
#if 0
|
||||
case 0x0c:
|
||||
@ -287,40 +306,39 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs,
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_SERIAL
|
||||
printf("sh_serial: read offs=0x%02x val=0x%x\n",
|
||||
offs, ret);
|
||||
#endif
|
||||
trace_sh_serial_read(d->id, size, offs, ret);
|
||||
|
||||
if (ret & ~((1 << 16) - 1)) {
|
||||
fprintf(stderr, "sh_serial: unsupported read from 0x%02"
|
||||
HWADDR_PRIx "\n", offs);
|
||||
abort();
|
||||
if (ret > UINT16_MAX) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: unsupported read from 0x%02" HWADDR_PRIx "\n",
|
||||
__func__, offs);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sh_serial_can_receive(sh_serial_state *s)
|
||||
static int sh_serial_can_receive(SHSerialState *s)
|
||||
{
|
||||
return s->scr & (1 << 4);
|
||||
}
|
||||
|
||||
static void sh_serial_receive_break(sh_serial_state *s)
|
||||
static void sh_serial_receive_break(SHSerialState *s)
|
||||
{
|
||||
if (s->feat & SH_SERIAL_FEAT_SCIF)
|
||||
if (s->feat & SH_SERIAL_FEAT_SCIF) {
|
||||
s->sr |= (1 << 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int sh_serial_can_receive1(void *opaque)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
SHSerialState *s = opaque;
|
||||
return sh_serial_can_receive(s);
|
||||
}
|
||||
|
||||
static void sh_serial_timeout_int(void *opaque)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
SHSerialState *s = opaque;
|
||||
|
||||
s->flags |= SH_SERIAL_FLAG_RDF;
|
||||
if (s->scr & (1 << 6) && s->rxi) {
|
||||
@ -330,7 +348,7 @@ static void sh_serial_timeout_int(void *opaque)
|
||||
|
||||
static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
SHSerialState *s = opaque;
|
||||
|
||||
if (s->feat & SH_SERIAL_FEAT_SCIF) {
|
||||
int i;
|
||||
@ -344,11 +362,11 @@ static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
|
||||
if (s->rx_cnt >= s->rtrg) {
|
||||
s->flags |= SH_SERIAL_FLAG_RDF;
|
||||
if (s->scr & (1 << 6) && s->rxi) {
|
||||
timer_del(s->fifo_timeout_timer);
|
||||
timer_del(&s->fifo_timeout_timer);
|
||||
qemu_set_irq(s->rxi, 1);
|
||||
}
|
||||
} else {
|
||||
timer_mod(s->fifo_timeout_timer,
|
||||
timer_mod(&s->fifo_timeout_timer,
|
||||
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu);
|
||||
}
|
||||
}
|
||||
@ -360,10 +378,11 @@ static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
|
||||
|
||||
static void sh_serial_event(void *opaque, QEMUChrEvent event)
|
||||
{
|
||||
sh_serial_state *s = opaque;
|
||||
if (event == CHR_EVENT_BREAK)
|
||||
SHSerialState *s = opaque;
|
||||
if (event == CHR_EVENT_BREAK) {
|
||||
sh_serial_receive_break(s);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps sh_serial_ops = {
|
||||
.read = sh_serial_read,
|
||||
@ -371,20 +390,10 @@ static const MemoryRegionOps sh_serial_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
void sh_serial_init(MemoryRegion *sysmem,
|
||||
hwaddr base, int feat,
|
||||
uint32_t freq, Chardev *chr,
|
||||
qemu_irq eri_source,
|
||||
qemu_irq rxi_source,
|
||||
qemu_irq txi_source,
|
||||
qemu_irq tei_source,
|
||||
qemu_irq bri_source)
|
||||
static void sh_serial_reset(DeviceState *dev)
|
||||
{
|
||||
sh_serial_state *s;
|
||||
SHSerialState *s = SH_SERIAL(dev);
|
||||
|
||||
s = g_malloc0(sizeof(sh_serial_state));
|
||||
|
||||
s->feat = feat;
|
||||
s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
|
||||
s->rtrg = 1;
|
||||
|
||||
@ -393,39 +402,64 @@ void sh_serial_init(MemoryRegion *sysmem,
|
||||
s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
|
||||
s->sptr = 0;
|
||||
|
||||
if (feat & SH_SERIAL_FEAT_SCIF) {
|
||||
if (s->feat & SH_SERIAL_FEAT_SCIF) {
|
||||
s->fcr = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
s->dr = 0xff;
|
||||
}
|
||||
|
||||
sh_serial_clear_fifo(s);
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
|
||||
"serial", 0x100000000ULL);
|
||||
static void sh_serial_realize(DeviceState *d, Error **errp)
|
||||
{
|
||||
SHSerialState *s = SH_SERIAL(d);
|
||||
MemoryRegion *iomem = g_malloc(sizeof(*iomem));
|
||||
|
||||
memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
|
||||
0, 0x28);
|
||||
memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
|
||||
assert(d->id);
|
||||
memory_region_init_io(iomem, OBJECT(d), &sh_serial_ops, s, d->id, 0x28);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(d), iomem);
|
||||
qdev_init_gpio_out_named(d, &s->eri, "eri", 1);
|
||||
qdev_init_gpio_out_named(d, &s->rxi, "rxi", 1);
|
||||
qdev_init_gpio_out_named(d, &s->txi, "txi", 1);
|
||||
qdev_init_gpio_out_named(d, &s->tei, "tei", 1);
|
||||
qdev_init_gpio_out_named(d, &s->bri, "bri", 1);
|
||||
|
||||
memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
|
||||
0, 0x28);
|
||||
memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
|
||||
|
||||
if (chr) {
|
||||
qemu_chr_fe_init(&s->chr, chr, &error_abort);
|
||||
if (qemu_chr_fe_backend_connected(&s->chr)) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
|
||||
sh_serial_receive1,
|
||||
sh_serial_event, NULL, s, NULL, true);
|
||||
}
|
||||
|
||||
s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
timer_init_ns(&s->fifo_timeout_timer, QEMU_CLOCK_VIRTUAL,
|
||||
sh_serial_timeout_int, s);
|
||||
s->etu = NANOSECONDS_PER_SECOND / 9600;
|
||||
s->eri = eri_source;
|
||||
s->rxi = rxi_source;
|
||||
s->txi = txi_source;
|
||||
s->tei = tei_source;
|
||||
s->bri = bri_source;
|
||||
}
|
||||
|
||||
static void sh_serial_finalize(Object *obj)
|
||||
{
|
||||
SHSerialState *s = SH_SERIAL(obj);
|
||||
|
||||
timer_del(&s->fifo_timeout_timer);
|
||||
}
|
||||
|
||||
static void sh_serial_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static Property sh_serial_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", SHSerialState, chr),
|
||||
DEFINE_PROP_UINT8("features", SHSerialState, feat, 0),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void sh_serial_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
device_class_set_props(dc, sh_serial_properties);
|
||||
dc->realize = sh_serial_realize;
|
||||
dc->reset = sh_serial_reset;
|
||||
/* Reason: part of SuperH CPU/SoC, needs to be wired up */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
@ -101,3 +101,7 @@ exynos_uart_rx_timeout(uint32_t channel, uint32_t stat, uint32_t intsp) "UART%d:
|
||||
|
||||
# cadence_uart.c
|
||||
cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
|
||||
|
||||
# sh_serial.c
|
||||
sh_serial_read(char *id, unsigned size, uint64_t offs, uint64_t val) " %s size %d offs 0x%02" PRIx64 " -> 0x%02" PRIx64
|
||||
sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %d offs 0x%02" PRIx64 " <- 0x%02" PRIx64
|
||||
|
@ -9,15 +9,12 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/sh4/sh_intc.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
|
||||
//#define DEBUG_INTC
|
||||
//#define DEBUG_INTC_SOURCES
|
||||
|
||||
#define INTC_A7(x) ((x) & 0x1fffffff)
|
||||
#include "trace.h"
|
||||
|
||||
void sh_intc_toggle_source(struct intc_source *source,
|
||||
int enable_adj, int assert_adj)
|
||||
@ -26,23 +23,23 @@ void sh_intc_toggle_source(struct intc_source *source,
|
||||
int pending_changed = 0;
|
||||
int old_pending;
|
||||
|
||||
if ((source->enable_count == source->enable_max) && (enable_adj == -1))
|
||||
if (source->enable_count == source->enable_max && enable_adj == -1) {
|
||||
enable_changed = -1;
|
||||
|
||||
}
|
||||
source->enable_count += enable_adj;
|
||||
|
||||
if (source->enable_count == source->enable_max)
|
||||
if (source->enable_count == source->enable_max) {
|
||||
enable_changed = 1;
|
||||
|
||||
}
|
||||
source->asserted += assert_adj;
|
||||
|
||||
old_pending = source->pending;
|
||||
source->pending = source->asserted &&
|
||||
(source->enable_count == source->enable_max);
|
||||
|
||||
if (old_pending != source->pending)
|
||||
if (old_pending != source->pending) {
|
||||
pending_changed = 1;
|
||||
|
||||
}
|
||||
if (pending_changed) {
|
||||
if (source->pending) {
|
||||
source->parent->pending++;
|
||||
@ -58,32 +55,27 @@ void sh_intc_toggle_source(struct intc_source *source,
|
||||
}
|
||||
|
||||
if (enable_changed || assert_adj || pending_changed) {
|
||||
#ifdef DEBUG_INTC_SOURCES
|
||||
printf("sh_intc: (%d/%d/%d/%d) interrupt source 0x%x %s%s%s\n",
|
||||
source->parent->pending,
|
||||
source->asserted,
|
||||
source->enable_count,
|
||||
source->enable_max,
|
||||
source->vect,
|
||||
source->asserted ? "asserted " :
|
||||
trace_sh_intc_sources(source->parent->pending, source->asserted,
|
||||
source->enable_count, source->enable_max,
|
||||
source->vect, source->asserted ? "asserted " :
|
||||
assert_adj ? "deasserted" : "",
|
||||
enable_changed == 1 ? "enabled " :
|
||||
enable_changed == -1 ? "disabled " : "",
|
||||
source->pending ? "pending" : "");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void sh_intc_set_irq(void *opaque, int n, int level)
|
||||
{
|
||||
struct intc_desc *desc = opaque;
|
||||
struct intc_source *source = &(desc->sources[n]);
|
||||
struct intc_source *source = &desc->sources[n];
|
||||
|
||||
if (level && !source->asserted)
|
||||
if (level && !source->asserted) {
|
||||
sh_intc_toggle_source(source, 0, 1);
|
||||
else if (!level && source->asserted)
|
||||
} else if (!level && source->asserted) {
|
||||
sh_intc_toggle_source(source, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int sh_intc_get_pending_vector(struct intc_desc *desc, int imask)
|
||||
{
|
||||
@ -97,45 +89,36 @@ int sh_intc_get_pending_vector(struct intc_desc *desc, int imask)
|
||||
}
|
||||
|
||||
for (i = 0; i < desc->nr_sources; i++) {
|
||||
struct intc_source *source = desc->sources + i;
|
||||
struct intc_source *source = &desc->sources[i];
|
||||
|
||||
if (source->pending) {
|
||||
#ifdef DEBUG_INTC_SOURCES
|
||||
printf("sh_intc: (%d) returning interrupt source 0x%x\n",
|
||||
desc->pending, source->vect);
|
||||
#endif
|
||||
trace_sh_intc_pending(desc->pending, source->vect);
|
||||
return source->vect;
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
#define INTC_MODE_NONE 0
|
||||
#define INTC_MODE_DUAL_SET 1
|
||||
#define INTC_MODE_DUAL_CLR 2
|
||||
#define INTC_MODE_ENABLE_REG 3
|
||||
#define INTC_MODE_MASK_REG 4
|
||||
#define INTC_MODE_IS_PRIO 8
|
||||
typedef enum {
|
||||
INTC_MODE_NONE,
|
||||
INTC_MODE_DUAL_SET,
|
||||
INTC_MODE_DUAL_CLR,
|
||||
INTC_MODE_ENABLE_REG,
|
||||
INTC_MODE_MASK_REG,
|
||||
} SHIntCMode;
|
||||
#define INTC_MODE_IS_PRIO 0x80
|
||||
|
||||
static unsigned int sh_intc_mode(unsigned long address,
|
||||
unsigned long set_reg, unsigned long clr_reg)
|
||||
static SHIntCMode sh_intc_mode(unsigned long address, unsigned long set_reg,
|
||||
unsigned long clr_reg)
|
||||
{
|
||||
if ((address != INTC_A7(set_reg)) &&
|
||||
(address != INTC_A7(clr_reg)))
|
||||
if (address != A7ADDR(set_reg) && address != A7ADDR(clr_reg)) {
|
||||
return INTC_MODE_NONE;
|
||||
|
||||
if (set_reg && clr_reg) {
|
||||
if (address == INTC_A7(set_reg))
|
||||
return INTC_MODE_DUAL_SET;
|
||||
else
|
||||
return INTC_MODE_DUAL_CLR;
|
||||
}
|
||||
|
||||
if (set_reg)
|
||||
return INTC_MODE_ENABLE_REG;
|
||||
else
|
||||
return INTC_MODE_MASK_REG;
|
||||
if (set_reg && clr_reg) {
|
||||
return address == A7ADDR(set_reg) ?
|
||||
INTC_MODE_DUAL_SET : INTC_MODE_DUAL_CLR;
|
||||
}
|
||||
return set_reg ? INTC_MODE_ENABLE_REG : INTC_MODE_MASK_REG;
|
||||
}
|
||||
|
||||
static void sh_intc_locate(struct intc_desc *desc,
|
||||
@ -146,18 +129,17 @@ static void sh_intc_locate(struct intc_desc *desc,
|
||||
unsigned int *width,
|
||||
unsigned int *modep)
|
||||
{
|
||||
unsigned int i, mode;
|
||||
SHIntCMode mode;
|
||||
unsigned int i;
|
||||
|
||||
/* this is slow but works for now */
|
||||
|
||||
if (desc->mask_regs) {
|
||||
for (i = 0; i < desc->nr_mask_regs; i++) {
|
||||
struct intc_mask_reg *mr = desc->mask_regs + i;
|
||||
struct intc_mask_reg *mr = &desc->mask_regs[i];
|
||||
|
||||
mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg);
|
||||
if (mode == INTC_MODE_NONE)
|
||||
continue;
|
||||
|
||||
if (mode != INTC_MODE_NONE) {
|
||||
*modep = mode;
|
||||
*datap = &mr->value;
|
||||
*enums = mr->enum_ids;
|
||||
@ -166,78 +148,65 @@ static void sh_intc_locate(struct intc_desc *desc,
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->prio_regs) {
|
||||
for (i = 0; i < desc->nr_prio_regs; i++) {
|
||||
struct intc_prio_reg *pr = desc->prio_regs + i;
|
||||
struct intc_prio_reg *pr = &desc->prio_regs[i];
|
||||
|
||||
mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg);
|
||||
if (mode == INTC_MODE_NONE)
|
||||
continue;
|
||||
|
||||
if (mode != INTC_MODE_NONE) {
|
||||
*modep = mode | INTC_MODE_IS_PRIO;
|
||||
*datap = &pr->value;
|
||||
*enums = pr->enum_ids;
|
||||
*first = (pr->reg_width / pr->field_width) - 1;
|
||||
*first = pr->reg_width / pr->field_width - 1;
|
||||
*width = pr->field_width;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id,
|
||||
int enable, int is_group)
|
||||
{
|
||||
struct intc_source *source = desc->sources + id;
|
||||
struct intc_source *source = &desc->sources[id];
|
||||
|
||||
if (!id)
|
||||
if (!id) {
|
||||
return;
|
||||
|
||||
}
|
||||
if (!source->next_enum_id && (!source->enable_max || !source->vect)) {
|
||||
#ifdef DEBUG_INTC_SOURCES
|
||||
printf("sh_intc: reserved interrupt source %d modified\n", id);
|
||||
#endif
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"sh_intc: reserved interrupt source %d modified\n", id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (source->vect)
|
||||
if (source->vect) {
|
||||
sh_intc_toggle_source(source, enable ? 1 : -1, 0);
|
||||
|
||||
#ifdef DEBUG_INTC
|
||||
else {
|
||||
printf("setting interrupt group %d to %d\n", id, !!enable);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((is_group || !source->vect) && source->next_enum_id) {
|
||||
sh_intc_toggle_mask(desc, source->next_enum_id, enable, 1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INTC
|
||||
if (!source->vect) {
|
||||
printf("setting interrupt group %d to %d - done\n", id, !!enable);
|
||||
trace_sh_intc_set(id, !!enable);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t sh_intc_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
static uint64_t sh_intc_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
struct intc_desc *desc = opaque;
|
||||
intc_enum *enum_ids = NULL;
|
||||
unsigned int first = 0;
|
||||
unsigned int width = 0;
|
||||
unsigned int mode = 0;
|
||||
intc_enum *enum_ids;
|
||||
unsigned int first;
|
||||
unsigned int width;
|
||||
unsigned int mode;
|
||||
unsigned long *valuep;
|
||||
|
||||
#ifdef DEBUG_INTC
|
||||
printf("sh_intc_read 0x%lx\n", (unsigned long) offset);
|
||||
#endif
|
||||
|
||||
sh_intc_locate(desc, (unsigned long)offset, &valuep,
|
||||
&enum_ids, &first, &width, &mode);
|
||||
trace_sh_intc_read(size, (uint64_t)offset, *valuep);
|
||||
return *valuep;
|
||||
}
|
||||
|
||||
@ -245,45 +214,40 @@ static void sh_intc_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
struct intc_desc *desc = opaque;
|
||||
intc_enum *enum_ids = NULL;
|
||||
unsigned int first = 0;
|
||||
unsigned int width = 0;
|
||||
unsigned int mode = 0;
|
||||
unsigned int k;
|
||||
intc_enum *enum_ids;
|
||||
unsigned int first;
|
||||
unsigned int width;
|
||||
unsigned int mode;
|
||||
unsigned long *valuep;
|
||||
unsigned int k;
|
||||
unsigned long mask;
|
||||
|
||||
#ifdef DEBUG_INTC
|
||||
printf("sh_intc_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
|
||||
#endif
|
||||
|
||||
trace_sh_intc_write(size, (uint64_t)offset, value);
|
||||
sh_intc_locate(desc, (unsigned long)offset, &valuep,
|
||||
&enum_ids, &first, &width, &mode);
|
||||
|
||||
switch (mode) {
|
||||
case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO: break;
|
||||
case INTC_MODE_DUAL_SET: value |= *valuep; break;
|
||||
case INTC_MODE_DUAL_CLR: value = *valuep & ~value; break;
|
||||
default: abort();
|
||||
case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO:
|
||||
break;
|
||||
case INTC_MODE_DUAL_SET:
|
||||
value |= *valuep;
|
||||
break;
|
||||
case INTC_MODE_DUAL_CLR:
|
||||
value = *valuep & ~value;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
for (k = 0; k <= first; k++) {
|
||||
mask = ((1 << width) - 1) << ((first - k) * width);
|
||||
mask = (1 << width) - 1;
|
||||
mask <<= (first - k) * width;
|
||||
|
||||
if ((*valuep & mask) == (value & mask))
|
||||
continue;
|
||||
#if 0
|
||||
printf("k = %d, first = %d, enum = %d, mask = 0x%08x\n",
|
||||
k, first, enum_ids[k], (unsigned int)mask);
|
||||
#endif
|
||||
if ((*valuep & mask) != (value & mask)) {
|
||||
sh_intc_toggle_mask(desc, enum_ids[k], value & mask, 0);
|
||||
}
|
||||
}
|
||||
|
||||
*valuep = value;
|
||||
|
||||
#ifdef DEBUG_INTC
|
||||
printf("sh_intc_write 0x%lx -> 0x%08x\n", (unsigned long) offset, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const MemoryRegionOps sh_intc_ops = {
|
||||
@ -292,12 +256,97 @@ static const MemoryRegionOps sh_intc_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
|
||||
static void sh_intc_register_source(struct intc_desc *desc,
|
||||
intc_enum source,
|
||||
struct intc_group *groups,
|
||||
int nr_groups)
|
||||
{
|
||||
if (id)
|
||||
return desc->sources + id;
|
||||
unsigned int i, k;
|
||||
intc_enum id;
|
||||
|
||||
return NULL;
|
||||
if (desc->mask_regs) {
|
||||
for (i = 0; i < desc->nr_mask_regs; i++) {
|
||||
struct intc_mask_reg *mr = &desc->mask_regs[i];
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(mr->enum_ids); k++) {
|
||||
id = mr->enum_ids[k];
|
||||
if (id && id == source) {
|
||||
desc->sources[id].enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->prio_regs) {
|
||||
for (i = 0; i < desc->nr_prio_regs; i++) {
|
||||
struct intc_prio_reg *pr = &desc->prio_regs[i];
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(pr->enum_ids); k++) {
|
||||
id = pr->enum_ids[k];
|
||||
if (id && id == source) {
|
||||
desc->sources[id].enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; i < nr_groups; i++) {
|
||||
struct intc_group *gr = &groups[i];
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(gr->enum_ids); k++) {
|
||||
id = gr->enum_ids[k];
|
||||
if (id && id == source) {
|
||||
desc->sources[id].enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sh_intc_register_sources(struct intc_desc *desc,
|
||||
struct intc_vect *vectors,
|
||||
int nr_vectors,
|
||||
struct intc_group *groups,
|
||||
int nr_groups)
|
||||
{
|
||||
unsigned int i, k;
|
||||
intc_enum id;
|
||||
struct intc_source *s;
|
||||
|
||||
for (i = 0; i < nr_vectors; i++) {
|
||||
struct intc_vect *vect = &vectors[i];
|
||||
|
||||
sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
|
||||
id = vect->enum_id;
|
||||
if (id) {
|
||||
s = &desc->sources[id];
|
||||
s->vect = vect->vect;
|
||||
trace_sh_intc_register("source", vect->enum_id, s->vect,
|
||||
s->enable_count, s->enable_max);
|
||||
}
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; i < nr_groups; i++) {
|
||||
struct intc_group *gr = &groups[i];
|
||||
|
||||
id = gr->enum_id;
|
||||
s = &desc->sources[id];
|
||||
s->next_enum_id = gr->enum_ids[0];
|
||||
|
||||
for (k = 1; k < ARRAY_SIZE(gr->enum_ids); k++) {
|
||||
if (gr->enum_ids[k]) {
|
||||
id = gr->enum_ids[k - 1];
|
||||
s = &desc->sources[id];
|
||||
s->next_enum_id = gr->enum_ids[k];
|
||||
}
|
||||
}
|
||||
trace_sh_intc_register("group", gr->enum_id, 0xffff,
|
||||
s->enable_count, s->enable_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sh_intc_register(MemoryRegion *sysmem,
|
||||
@ -315,125 +364,21 @@ static unsigned int sh_intc_register(MemoryRegion *sysmem,
|
||||
}
|
||||
|
||||
iomem = &desc->iomem;
|
||||
iomem_p4 = desc->iomem_aliases + index;
|
||||
iomem_p4 = &desc->iomem_aliases[index];
|
||||
iomem_a7 = iomem_p4 + 1;
|
||||
|
||||
#define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s"
|
||||
snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4");
|
||||
memory_region_init_alias(iomem_p4, NULL, name, iomem, INTC_A7(address), 4);
|
||||
snprintf(name, sizeof(name), "intc-%s-%s-%s", type, action, "p4");
|
||||
memory_region_init_alias(iomem_p4, NULL, name, iomem, A7ADDR(address), 4);
|
||||
memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
|
||||
|
||||
snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7");
|
||||
memory_region_init_alias(iomem_a7, NULL, name, iomem, INTC_A7(address), 4);
|
||||
snprintf(name, sizeof(name), "intc-%s-%s-%s", type, action, "a7");
|
||||
memory_region_init_alias(iomem_a7, NULL, name, iomem, A7ADDR(address), 4);
|
||||
memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
|
||||
#undef SH_INTC_IOMEM_FORMAT
|
||||
|
||||
/* used to increment aliases index */
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void sh_intc_register_source(struct intc_desc *desc,
|
||||
intc_enum source,
|
||||
struct intc_group *groups,
|
||||
int nr_groups)
|
||||
{
|
||||
unsigned int i, k;
|
||||
struct intc_source *s;
|
||||
|
||||
if (desc->mask_regs) {
|
||||
for (i = 0; i < desc->nr_mask_regs; i++) {
|
||||
struct intc_mask_reg *mr = desc->mask_regs + i;
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(mr->enum_ids); k++) {
|
||||
if (mr->enum_ids[k] != source)
|
||||
continue;
|
||||
|
||||
s = sh_intc_source(desc, mr->enum_ids[k]);
|
||||
if (s)
|
||||
s->enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->prio_regs) {
|
||||
for (i = 0; i < desc->nr_prio_regs; i++) {
|
||||
struct intc_prio_reg *pr = desc->prio_regs + i;
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(pr->enum_ids); k++) {
|
||||
if (pr->enum_ids[k] != source)
|
||||
continue;
|
||||
|
||||
s = sh_intc_source(desc, pr->enum_ids[k]);
|
||||
if (s)
|
||||
s->enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; i < nr_groups; i++) {
|
||||
struct intc_group *gr = groups + i;
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(gr->enum_ids); k++) {
|
||||
if (gr->enum_ids[k] != source)
|
||||
continue;
|
||||
|
||||
s = sh_intc_source(desc, gr->enum_ids[k]);
|
||||
if (s)
|
||||
s->enable_max++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sh_intc_register_sources(struct intc_desc *desc,
|
||||
struct intc_vect *vectors,
|
||||
int nr_vectors,
|
||||
struct intc_group *groups,
|
||||
int nr_groups)
|
||||
{
|
||||
unsigned int i, k;
|
||||
struct intc_source *s;
|
||||
|
||||
for (i = 0; i < nr_vectors; i++) {
|
||||
struct intc_vect *vect = vectors + i;
|
||||
|
||||
sh_intc_register_source(desc, vect->enum_id, groups, nr_groups);
|
||||
s = sh_intc_source(desc, vect->enum_id);
|
||||
if (s) {
|
||||
s->vect = vect->vect;
|
||||
|
||||
#ifdef DEBUG_INTC_SOURCES
|
||||
printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n",
|
||||
vect->enum_id, s->vect, s->enable_count, s->enable_max);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
for (i = 0; i < nr_groups; i++) {
|
||||
struct intc_group *gr = groups + i;
|
||||
|
||||
s = sh_intc_source(desc, gr->enum_id);
|
||||
s->next_enum_id = gr->enum_ids[0];
|
||||
|
||||
for (k = 1; k < ARRAY_SIZE(gr->enum_ids); k++) {
|
||||
if (!gr->enum_ids[k])
|
||||
continue;
|
||||
|
||||
s = sh_intc_source(desc, gr->enum_ids[k - 1]);
|
||||
s->next_enum_id = gr->enum_ids[k];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INTC_SOURCES
|
||||
printf("sh_intc: registered group %d (%d/%d)\n",
|
||||
gr->enum_id, s->enable_count, s->enable_max);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sh_intc_init(MemoryRegion *sysmem,
|
||||
struct intc_desc *desc,
|
||||
int nr_sources,
|
||||
@ -450,65 +395,55 @@ int sh_intc_init(MemoryRegion *sysmem,
|
||||
desc->nr_mask_regs = nr_mask_regs;
|
||||
desc->prio_regs = prio_regs;
|
||||
desc->nr_prio_regs = nr_prio_regs;
|
||||
/* Allocate 4 MemoryRegions per register (2 actions * 2 aliases).
|
||||
**/
|
||||
/* Allocate 4 MemoryRegions per register (2 actions * 2 aliases) */
|
||||
desc->iomem_aliases = g_new0(MemoryRegion,
|
||||
(nr_mask_regs + nr_prio_regs) * 4);
|
||||
|
||||
j = 0;
|
||||
i = sizeof(struct intc_source) * nr_sources;
|
||||
desc->sources = g_malloc0(i);
|
||||
|
||||
for (i = 0; i < desc->nr_sources; i++) {
|
||||
struct intc_source *source = desc->sources + i;
|
||||
|
||||
source->parent = desc;
|
||||
desc->sources = g_new0(struct intc_source, nr_sources);
|
||||
for (i = 0; i < nr_sources; i++) {
|
||||
desc->sources[i].parent = desc;
|
||||
}
|
||||
|
||||
desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
|
||||
|
||||
memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc,
|
||||
"interrupt-controller", 0x100000000ULL);
|
||||
|
||||
#define INT_REG_PARAMS(reg_struct, type, action, j) \
|
||||
reg_struct->action##_reg, #type, #action, j
|
||||
memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc, "intc",
|
||||
0x100000000ULL);
|
||||
j = 0;
|
||||
if (desc->mask_regs) {
|
||||
for (i = 0; i < desc->nr_mask_regs; i++) {
|
||||
struct intc_mask_reg *mr = desc->mask_regs + i;
|
||||
struct intc_mask_reg *mr = &desc->mask_regs[i];
|
||||
|
||||
j += sh_intc_register(sysmem, desc,
|
||||
INT_REG_PARAMS(mr, mask, set, j));
|
||||
j += sh_intc_register(sysmem, desc,
|
||||
INT_REG_PARAMS(mr, mask, clr, j));
|
||||
j += sh_intc_register(sysmem, desc, mr->set_reg, "mask", "set", j);
|
||||
j += sh_intc_register(sysmem, desc, mr->clr_reg, "mask", "clr", j);
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->prio_regs) {
|
||||
for (i = 0; i < desc->nr_prio_regs; i++) {
|
||||
struct intc_prio_reg *pr = desc->prio_regs + i;
|
||||
struct intc_prio_reg *pr = &desc->prio_regs[i];
|
||||
|
||||
j += sh_intc_register(sysmem, desc,
|
||||
INT_REG_PARAMS(pr, prio, set, j));
|
||||
j += sh_intc_register(sysmem, desc,
|
||||
INT_REG_PARAMS(pr, prio, clr, j));
|
||||
j += sh_intc_register(sysmem, desc, pr->set_reg, "prio", "set", j);
|
||||
j += sh_intc_register(sysmem, desc, pr->clr_reg, "prio", "clr", j);
|
||||
}
|
||||
}
|
||||
#undef INT_REG_PARAMS
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assert level <n> IRL interrupt.
|
||||
0:deassert. 1:lowest priority,... 15:highest priority. */
|
||||
/*
|
||||
* Assert level <n> IRL interrupt.
|
||||
* 0:deassert. 1:lowest priority,... 15:highest priority
|
||||
*/
|
||||
void sh_intc_set_irl(void *opaque, int n, int level)
|
||||
{
|
||||
struct intc_source *s = opaque;
|
||||
int i, irl = level ^ 15;
|
||||
for (i = 0; (s = sh_intc_source(s->parent, s->next_enum_id)); i++) {
|
||||
if (i == irl)
|
||||
sh_intc_toggle_source(s, s->enable_count?0:1, s->asserted?0:1);
|
||||
else
|
||||
if (s->asserted)
|
||||
intc_enum id = s->next_enum_id;
|
||||
|
||||
for (i = 0; id; id = s->next_enum_id, i++) {
|
||||
s = &s->parent->sources[id];
|
||||
if (i == irl) {
|
||||
sh_intc_toggle_source(s, s->enable_count ? 0 : 1,
|
||||
s->asserted ? 0 : 1);
|
||||
} else if (s->asserted) {
|
||||
sh_intc_toggle_source(s, 0, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,3 +238,11 @@ goldfish_pic_write(void *dev, int idx, unsigned int addr, unsigned int size, uin
|
||||
goldfish_pic_reset(void *dev, int idx) "pic: %p goldfish-irq.%d"
|
||||
goldfish_pic_realize(void *dev, int idx) "pic: %p goldfish-irq.%d"
|
||||
goldfish_pic_instance_init(void *dev) "pic: %p goldfish-irq"
|
||||
|
||||
# sh_intc.c
|
||||
sh_intc_sources(int p, int a, int c, int m, unsigned short v, const char *s1, const char *s2, const char *s3) "(%d/%d/%d/%d) interrupt source 0x%x %s%s%s"
|
||||
sh_intc_pending(int p, unsigned short v) "(%d) returning interrupt source 0x%x"
|
||||
sh_intc_register(const char *s, int id, unsigned short v, int c, int m) "%s %u -> 0x%04x (%d/%d)"
|
||||
sh_intc_read(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " -> 0x%lx"
|
||||
sh_intc_write(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " <- 0x%lx"
|
||||
sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
|
||||
|
@ -49,8 +49,7 @@ struct SHPCIState {
|
||||
uint32_t iobr;
|
||||
};
|
||||
|
||||
static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
|
||||
unsigned size)
|
||||
static void sh_pci_reg_write(void *p, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
SHPCIState *pcic = p;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
|
||||
@ -75,8 +74,7 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
|
||||
unsigned size)
|
||||
static uint64_t sh_pci_reg_read(void *p, hwaddr addr, unsigned size)
|
||||
{
|
||||
SHPCIState *pcic = p;
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
|
||||
|
27
hw/sh4/r2d.c
27
hw/sh4/r2d.c
@ -26,6 +26,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
@ -114,20 +115,23 @@ static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
|
||||
static void update_irl(r2d_fpga_t *fpga)
|
||||
{
|
||||
int i, irl = 15;
|
||||
for (i = 0; i < NR_IRQS; i++)
|
||||
if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
|
||||
if (irqtab[i].irl < irl)
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
if ((fpga->irlmon & fpga->irlmsk & irqtab[i].msk) &&
|
||||
irqtab[i].irl < irl) {
|
||||
irl = irqtab[i].irl;
|
||||
}
|
||||
}
|
||||
qemu_set_irq(fpga->irl, irl ^ 15);
|
||||
}
|
||||
|
||||
static void r2d_fpga_irq_set(void *opaque, int n, int level)
|
||||
{
|
||||
r2d_fpga_t *fpga = opaque;
|
||||
if (level)
|
||||
if (level) {
|
||||
fpga->irlmon |= irqtab[n].msk;
|
||||
else
|
||||
} else {
|
||||
fpga->irlmon &= ~irqtab[n].msk;
|
||||
}
|
||||
update_irl(fpga);
|
||||
}
|
||||
|
||||
@ -321,7 +325,7 @@ static void r2d_init(MachineState *machine)
|
||||
SDRAM_BASE + LINUX_LOAD_OFFSET,
|
||||
INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
|
||||
if (kernel_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
|
||||
error_report("qemu: could not load kernel '%s'", kernel_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -330,7 +334,8 @@ static void r2d_init(MachineState *machine)
|
||||
MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */
|
||||
address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),
|
||||
MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */
|
||||
reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
|
||||
/* Start from P2 area */
|
||||
reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
|
||||
}
|
||||
|
||||
if (initrd_filename) {
|
||||
@ -341,7 +346,7 @@ static void r2d_init(MachineState *machine)
|
||||
SDRAM_SIZE - INITRD_LOAD_OFFSET);
|
||||
|
||||
if (initrd_size < 0) {
|
||||
fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
|
||||
error_report("qemu: could not load initrd '%s'", initrd_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -352,8 +357,10 @@ static void r2d_init(MachineState *machine)
|
||||
}
|
||||
|
||||
if (kernel_cmdline) {
|
||||
/* I see no evidence that this .kernel_cmdline buffer requires
|
||||
NUL-termination, so using strncpy should be ok. */
|
||||
/*
|
||||
* I see no evidence that this .kernel_cmdline buffer requires
|
||||
* NUL-termination, so using strncpy should be ok.
|
||||
*/
|
||||
strncpy(boot_params.kernel_cmdline, kernel_cmdline,
|
||||
sizeof(boot_params.kernel_cmdline));
|
||||
}
|
||||
|
117
hw/sh4/sh7750.c
117
hw/sh4/sh7750.c
@ -24,14 +24,19 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "sh7750_regs.h"
|
||||
#include "sh7750_regnames.h"
|
||||
#include "hw/sh4/sh_intc.h"
|
||||
#include "hw/timer/tmu012.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define NB_DEVICES 4
|
||||
|
||||
@ -82,9 +87,10 @@ static inline int has_bcr3_and_bcr4(SH7750State * s)
|
||||
{
|
||||
return s->cpu->env.features & SH_FEATURE_BCR3_AND_BCR4;
|
||||
}
|
||||
/**********************************************************************
|
||||
I/O ports
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
* I/O ports
|
||||
*/
|
||||
|
||||
int sh7750_register_io_device(SH7750State *s, sh7750_io_device *device)
|
||||
{
|
||||
@ -146,14 +152,11 @@ static void porta_changed(SH7750State * s, uint16_t prev)
|
||||
uint16_t currenta, changes;
|
||||
int i, r = 0;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
|
||||
prev, porta_lines(s));
|
||||
fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
|
||||
#endif
|
||||
currenta = porta_lines(s);
|
||||
if (currenta == prev)
|
||||
if (currenta == prev) {
|
||||
return;
|
||||
}
|
||||
trace_sh7750_porta(prev, currenta, s->pdtra, s->pctra);
|
||||
changes = currenta ^ prev;
|
||||
|
||||
for (i = 0; i < NB_DEVICES; i++) {
|
||||
@ -166,9 +169,10 @@ static void porta_changed(SH7750State * s, uint16_t prev)
|
||||
}
|
||||
}
|
||||
|
||||
if (r)
|
||||
if (r) {
|
||||
gen_port_interrupts(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void portb_changed(SH7750State *s, uint16_t prev)
|
||||
{
|
||||
@ -176,8 +180,10 @@ static void portb_changed(SH7750State * s, uint16_t prev)
|
||||
int i, r = 0;
|
||||
|
||||
currentb = portb_lines(s);
|
||||
if (currentb == prev)
|
||||
if (currentb == prev) {
|
||||
return;
|
||||
}
|
||||
trace_sh7750_portb(prev, currentb, s->pdtrb, s->pctrb);
|
||||
changes = currentb ^ prev;
|
||||
|
||||
for (i = 0; i < NB_DEVICES; i++) {
|
||||
@ -190,13 +196,14 @@ static void portb_changed(SH7750State * s, uint16_t prev)
|
||||
}
|
||||
}
|
||||
|
||||
if (r)
|
||||
if (r) {
|
||||
gen_port_interrupts(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Memory
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Memory
|
||||
*/
|
||||
|
||||
static void error_access(const char *kind, hwaddr addr)
|
||||
{
|
||||
@ -227,8 +234,9 @@ static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
|
||||
case SH7750_BCR2_A7:
|
||||
return s->bcr2;
|
||||
case SH7750_BCR3_A7:
|
||||
if(!has_bcr3_and_bcr4(s))
|
||||
if (!has_bcr3_and_bcr4(s)) {
|
||||
error_access("word read", addr);
|
||||
}
|
||||
return s->bcr3;
|
||||
case SH7750_FRQCR_A7:
|
||||
return 0;
|
||||
@ -262,8 +270,9 @@ static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
|
||||
case SH7750_BCR1_A7:
|
||||
return s->bcr1;
|
||||
case SH7750_BCR4_A7:
|
||||
if(!has_bcr3_and_bcr4(s))
|
||||
if (!has_bcr3_and_bcr4(s)) {
|
||||
error_access("long read", addr);
|
||||
}
|
||||
return s->bcr4;
|
||||
case SH7750_WCR1_A7:
|
||||
case SH7750_WCR2_A7:
|
||||
@ -331,8 +340,9 @@ static void sh7750_mem_writew(void *opaque, hwaddr addr,
|
||||
s->bcr2 = mem_value;
|
||||
return;
|
||||
case SH7750_BCR3_A7:
|
||||
if(!has_bcr3_and_bcr4(s))
|
||||
if (!has_bcr3_and_bcr4(s)) {
|
||||
error_access("word write", addr);
|
||||
}
|
||||
s->bcr3 = mem_value;
|
||||
return;
|
||||
case SH7750_PCR_A7:
|
||||
@ -383,8 +393,9 @@ static void sh7750_mem_writel(void *opaque, hwaddr addr,
|
||||
s->bcr1 = mem_value;
|
||||
return;
|
||||
case SH7750_BCR4_A7:
|
||||
if(!has_bcr3_and_bcr4(s))
|
||||
if (!has_bcr3_and_bcr4(s)) {
|
||||
error_access("long write", addr);
|
||||
}
|
||||
s->bcr4 = mem_value;
|
||||
return;
|
||||
case SH7750_WCR1_A7:
|
||||
@ -491,7 +502,8 @@ static const MemoryRegionOps sh7750_mem_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
/* sh775x interrupt controller tables for sh_intc.c
|
||||
/*
|
||||
* sh775x interrupt controller tables for sh_intc.c
|
||||
* stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
|
||||
*/
|
||||
|
||||
@ -550,8 +562,7 @@ static struct intc_prio_reg prio_registers[] = {
|
||||
{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
|
||||
{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
|
||||
{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
|
||||
{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
|
||||
TMU4, TMU3,
|
||||
{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0, TMU4, TMU3,
|
||||
PCIC1, PCIC0_PCISERR } },
|
||||
};
|
||||
|
||||
@ -643,9 +654,9 @@ static struct intc_group groups_irl[] = {
|
||||
IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
Memory mapped cache and TLB
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Memory mapped cache and TLB
|
||||
*/
|
||||
|
||||
#define MM_REGION_MASK 0x07000000
|
||||
#define MM_ICACHE_ADDR (0)
|
||||
@ -755,6 +766,9 @@ static const MemoryRegionOps sh7750_mmct_ops = {
|
||||
SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
|
||||
{
|
||||
SH7750State *s;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sb;
|
||||
MemoryRegion *mr, *alias;
|
||||
|
||||
s = g_malloc0(sizeof(SH7750State));
|
||||
s->cpu = cpu;
|
||||
@ -800,21 +814,40 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
|
||||
|
||||
cpu->env.intc_handle = &s->intc;
|
||||
|
||||
sh_serial_init(sysmem, 0x1fe00000,
|
||||
0, s->periph_freq, serial_hd(0),
|
||||
s->intc.irqs[SCI1_ERI],
|
||||
s->intc.irqs[SCI1_RXI],
|
||||
s->intc.irqs[SCI1_TXI],
|
||||
s->intc.irqs[SCI1_TEI],
|
||||
NULL);
|
||||
sh_serial_init(sysmem, 0x1fe80000,
|
||||
SH_SERIAL_FEAT_SCIF,
|
||||
s->periph_freq, serial_hd(1),
|
||||
s->intc.irqs[SCIF_ERI],
|
||||
s->intc.irqs[SCIF_RXI],
|
||||
s->intc.irqs[SCIF_TXI],
|
||||
NULL,
|
||||
s->intc.irqs[SCIF_BRI]);
|
||||
/* SCI */
|
||||
dev = qdev_new(TYPE_SH_SERIAL);
|
||||
dev->id = g_strdup("sci");
|
||||
qdev_prop_set_chr(dev, "chardev", serial_hd(0));
|
||||
sb = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(sb, &error_fatal);
|
||||
sysbus_mmio_map(sb, 0, 0xffe00000);
|
||||
alias = g_malloc(sizeof(*alias));
|
||||
mr = sysbus_mmio_get_region(sb, 0);
|
||||
memory_region_init_alias(alias, OBJECT(dev), "sci-a7", mr,
|
||||
0, memory_region_size(mr));
|
||||
memory_region_add_subregion(sysmem, A7ADDR(0xffe00000), alias);
|
||||
qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCI1_ERI]);
|
||||
qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCI1_RXI]);
|
||||
qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCI1_TXI]);
|
||||
qdev_connect_gpio_out_named(dev, "tei", 0, s->intc.irqs[SCI1_TEI]);
|
||||
|
||||
/* SCIF */
|
||||
dev = qdev_new(TYPE_SH_SERIAL);
|
||||
dev->id = g_strdup("scif");
|
||||
qdev_prop_set_chr(dev, "chardev", serial_hd(1));
|
||||
qdev_prop_set_uint8(dev, "features", SH_SERIAL_FEAT_SCIF);
|
||||
sb = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(sb, &error_fatal);
|
||||
sysbus_mmio_map(sb, 0, 0xffe80000);
|
||||
alias = g_malloc(sizeof(*alias));
|
||||
mr = sysbus_mmio_get_region(sb, 0);
|
||||
memory_region_init_alias(alias, OBJECT(dev), "scif-a7", mr,
|
||||
0, memory_region_size(mr));
|
||||
memory_region_add_subregion(sysmem, A7ADDR(0xffe80000), alias);
|
||||
qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCIF_ERI]);
|
||||
qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCIF_RXI]);
|
||||
qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCIF_TXI]);
|
||||
qdev_connect_gpio_out_named(dev, "bri", 0, s->intc.irqs[SCIF_BRI]);
|
||||
|
||||
tmu012_init(sysmem, 0x1fd80000,
|
||||
TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
|
||||
@ -866,6 +899,6 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
|
||||
|
||||
qemu_irq sh7750_irl(SH7750State *s)
|
||||
{
|
||||
sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
|
||||
return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), 0);
|
||||
sh_intc_toggle_source(&s->intc.sources[IRL], 1, 0); /* enable */
|
||||
return qemu_allocate_irq(sh_intc_set_irl, &s->intc.sources[IRL], 0);
|
||||
}
|
||||
|
@ -81,7 +81,8 @@ static regname_t regnames[] = {
|
||||
REGNAME(SH7750_BCR3_A7)
|
||||
REGNAME(SH7750_BCR4_A7)
|
||||
REGNAME(SH7750_SDMR2_A7)
|
||||
REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
|
||||
REGNAME(SH7750_SDMR3_A7)
|
||||
{ (uint32_t)-1, NULL }
|
||||
};
|
||||
|
||||
const char *regname(uint32_t addr)
|
||||
@ -89,9 +90,10 @@ const char *regname(uint32_t addr)
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; regnames[i].regaddr != (uint32_t)-1; i++) {
|
||||
if (regnames[i].regaddr == addr)
|
||||
if (regnames[i].regaddr == addr) {
|
||||
return regnames[i].regname;
|
||||
}
|
||||
}
|
||||
|
||||
return "<unknown reg>";
|
||||
}
|
||||
|
@ -43,8 +43,7 @@
|
||||
* All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address) and
|
||||
* in 0x1f000000 - 0x1fffffff (area 7 address)
|
||||
*/
|
||||
#define SH7750_P4_BASE 0xff000000 /* Accessible only in
|
||||
privileged mode */
|
||||
#define SH7750_P4_BASE 0xff000000 /* Accessible only in privileged mode */
|
||||
#define SH7750_A7_BASE 0x1f000000 /* Accessible only using TLB */
|
||||
|
||||
#define SH7750_P4_REG32(ofs) (SH7750_P4_BASE + (ofs))
|
||||
@ -81,24 +80,24 @@
|
||||
#define SH7750_PTEL_PR_RWPO 0x00000020 /* read-write in priv mode */
|
||||
#define SH7750_PTEL_PR_ROPU 0x00000040 /* read-only in priv or user mode */
|
||||
#define SH7750_PTEL_PR_RWPU 0x00000060 /* read-write in priv or user mode */
|
||||
#define SH7750_PTEL_C 0x00000008 /* Cacheability
|
||||
(0 - page not cacheable) */
|
||||
#define SH7750_PTEL_D 0x00000004 /* Dirty bit (1 - write has been
|
||||
performed to a page) */
|
||||
#define SH7750_PTEL_SH 0x00000002 /* Share Status bit (1 - page are
|
||||
shared by processes) */
|
||||
#define SH7750_PTEL_WT 0x00000001 /* Write-through bit, specifies the
|
||||
cache write mode:
|
||||
0 - Copy-back mode
|
||||
1 - Write-through mode */
|
||||
#define SH7750_PTEL_C 0x00000008 /* Cacheability */
|
||||
/* (0 - page not cacheable) */
|
||||
#define SH7750_PTEL_D 0x00000004 /* Dirty bit (1 - write has been */
|
||||
/* performed to a page) */
|
||||
#define SH7750_PTEL_SH 0x00000002 /* Share Status bit (1 - page are */
|
||||
/* shared by processes) */
|
||||
#define SH7750_PTEL_WT 0x00000001 /* Write-through bit, specifies the */
|
||||
/* cache write mode: */
|
||||
/* 0 - Copy-back mode */
|
||||
/* 1 - Write-through mode */
|
||||
|
||||
/* Page Table Entry Assistance register - PTEA */
|
||||
#define SH7750_PTEA_REGOFS 0x000034 /* offset */
|
||||
#define SH7750_PTEA SH7750_P4_REG32(SH7750_PTEA_REGOFS)
|
||||
#define SH7750_PTEA_A7 SH7750_A7_REG32(SH7750_PTEA_REGOFS)
|
||||
#define SH7750_PTEA_TC 0x00000008 /* Timing Control bit
|
||||
0 - use area 5 wait states
|
||||
1 - use area 6 wait states */
|
||||
#define SH7750_PTEA_TC 0x00000008 /* Timing Control bit */
|
||||
/* 0 - use area 5 wait states */
|
||||
/* 1 - use area 6 wait states */
|
||||
#define SH7750_PTEA_SA 0x00000007 /* Space Attribute bits: */
|
||||
#define SH7750_PTEA_SA_UNDEF 0x00000000 /* 0 - undefined */
|
||||
#define SH7750_PTEA_SA_IOVAR 0x00000001 /* 1 - variable-size I/O space */
|
||||
@ -150,13 +149,13 @@
|
||||
#define SH7750_CCR_A7 SH7750_A7_REG32(SH7750_CCR_REGOFS)
|
||||
|
||||
#define SH7750_CCR_IIX 0x00008000 /* IC index enable bit */
|
||||
#define SH7750_CCR_ICI 0x00000800 /* IC invalidation bit:
|
||||
set it to clear IC */
|
||||
#define SH7750_CCR_ICI 0x00000800 /* IC invalidation bit: */
|
||||
/* set it to clear IC */
|
||||
#define SH7750_CCR_ICE 0x00000100 /* IC enable bit */
|
||||
#define SH7750_CCR_OIX 0x00000080 /* OC index enable bit */
|
||||
#define SH7750_CCR_ORA 0x00000020 /* OC RAM enable bit
|
||||
if you set OCE = 0,
|
||||
you should set ORA = 0 */
|
||||
#define SH7750_CCR_ORA 0x00000020 /* OC RAM enable bit */
|
||||
/* if you set OCE = 0, */
|
||||
/* you should set ORA = 0 */
|
||||
#define SH7750_CCR_OCI 0x00000008 /* OC invalidation bit */
|
||||
#define SH7750_CCR_CB 0x00000004 /* Copy-back bit for P1 area */
|
||||
#define SH7750_CCR_WT 0x00000002 /* Write-through bit for P0,U0,P3 area */
|
||||
@ -213,21 +212,22 @@
|
||||
/* General exception category */
|
||||
#define SH7750_EVT_USER_BREAK 0x1E0 /* User break */
|
||||
#define SH7750_EVT_IADDR_ERR 0x0E0 /* Instruction address error */
|
||||
#define SH7750_EVT_TLB_READ_MISS 0x040 /* ITLB miss exception /
|
||||
DTLB miss exception (read) */
|
||||
#define SH7750_EVT_TLB_READ_PROTV 0x0A0 /* ITLB protection violation /
|
||||
DTLB protection violation (read) */
|
||||
#define SH7750_EVT_ILLEGAL_INSTR 0x180 /* General Illegal Instruction
|
||||
exception */
|
||||
#define SH7750_EVT_SLOT_ILLEGAL_INSTR 0x1A0 /* Slot Illegal Instruction
|
||||
exception */
|
||||
#define SH7750_EVT_TLB_READ_MISS 0x040 /* ITLB miss exception / */
|
||||
/* DTLB miss exception (read) */
|
||||
#define SH7750_EVT_TLB_READ_PROTV 0x0A0 /* ITLB protection violation, */
|
||||
/* DTLB protection violation */
|
||||
/* (read) */
|
||||
#define SH7750_EVT_ILLEGAL_INSTR 0x180 /* General Illegal Instruction */
|
||||
/* exception */
|
||||
#define SH7750_EVT_SLOT_ILLEGAL_INSTR 0x1A0 /* Slot Illegal Instruction */
|
||||
/* exception */
|
||||
#define SH7750_EVT_FPU_DISABLE 0x800 /* General FPU disable exception */
|
||||
#define SH7750_EVT_SLOT_FPU_DISABLE 0x820 /* Slot FPU disable exception */
|
||||
#define SH7750_EVT_DATA_READ_ERR 0x0E0 /* Data address error (read) */
|
||||
#define SH7750_EVT_DATA_WRITE_ERR 0x100 /* Data address error (write) */
|
||||
#define SH7750_EVT_DTLB_WRITE_MISS 0x060 /* DTLB miss exception (write) */
|
||||
#define SH7750_EVT_DTLB_WRITE_PROTV 0x0C0 /* DTLB protection violation
|
||||
exception (write) */
|
||||
#define SH7750_EVT_DTLB_WRITE_PROTV 0x0C0 /* DTLB protection violation */
|
||||
/* exception (write) */
|
||||
#define SH7750_EVT_FPU_EXCEPTION 0x120 /* FPU exception */
|
||||
#define SH7750_EVT_INITIAL_PGWRITE 0x080 /* Initial Page Write exception */
|
||||
#define SH7750_EVT_TRAPA 0x160 /* Unconditional trap (TRAPA) */
|
||||
@ -268,14 +268,14 @@
|
||||
#define SH7750_EVT_SCI_TEI 0x540 /* Transmit End */
|
||||
|
||||
/* Peripheral Module Interrupts - Watchdog Timer (WDT) */
|
||||
#define SH7750_EVT_WDT_ITI 0x560 /* Interval Timer Interrupt
|
||||
(used when WDT operates in
|
||||
interval timer mode) */
|
||||
#define SH7750_EVT_WDT_ITI 0x560 /* Interval Timer Interrupt */
|
||||
/* (used when WDT operates in */
|
||||
/* interval timer mode) */
|
||||
|
||||
/* Peripheral Module Interrupts - Memory Refresh Unit (REF) */
|
||||
#define SH7750_EVT_REF_RCMI 0x580 /* Compare-match Interrupt */
|
||||
#define SH7750_EVT_REF_ROVI 0x5A0 /* Refresh Counter Overflow
|
||||
interrupt */
|
||||
#define SH7750_EVT_REF_ROVI 0x5A0 /* Refresh Counter Overflow */
|
||||
/* interrupt */
|
||||
|
||||
/* Peripheral Module Interrupts - Hitachi User Debug Interface (H-UDI) */
|
||||
#define SH7750_EVT_HUDI 0x600 /* UDI interrupt */
|
||||
@ -290,11 +290,10 @@
|
||||
#define SH7750_EVT_DMAC_DMTE3 0x6A0 /* DMAC 3 Transfer End Interrupt */
|
||||
#define SH7750_EVT_DMAC_DMAE 0x6C0 /* DMAC Address Error Interrupt */
|
||||
|
||||
/* Peripheral Module Interrupts - Serial Communication Interface with FIFO */
|
||||
/* (SCIF) */
|
||||
/* Peripheral Module Interrupts Serial Communication Interface w/ FIFO (SCIF) */
|
||||
#define SH7750_EVT_SCIF_ERI 0x700 /* Receive Error */
|
||||
#define SH7750_EVT_SCIF_RXI 0x720 /* Receive FIFO Data Full or
|
||||
Receive Data ready interrupt */
|
||||
#define SH7750_EVT_SCIF_RXI 0x720 /* Receive FIFO Data Full or */
|
||||
/* Receive Data ready interrupt */
|
||||
#define SH7750_EVT_SCIF_BRI 0x740 /* Break or overrun error */
|
||||
#define SH7750_EVT_SCIF_TXI 0x760 /* Transmit FIFO Data Empty */
|
||||
|
||||
@ -305,13 +304,13 @@
|
||||
#define SH7750_STBCR SH7750_P4_REG32(SH7750_STBCR_REGOFS)
|
||||
#define SH7750_STBCR_A7 SH7750_A7_REG32(SH7750_STBCR_REGOFS)
|
||||
|
||||
#define SH7750_STBCR_STBY 0x80 /* Specifies a transition to standby mode:
|
||||
0 - Transition to SLEEP mode on SLEEP
|
||||
1 - Transition to STANDBY mode on SLEEP */
|
||||
#define SH7750_STBCR_PHZ 0x40 /* State of peripheral module pins in
|
||||
standby mode:
|
||||
0 - normal state
|
||||
1 - high-impendance state */
|
||||
#define SH7750_STBCR_STBY 0x80 /* Specifies a transition to standby mode: */
|
||||
/* 0 Transition to SLEEP mode on SLEEP */
|
||||
/* 1 Transition to STANDBY mode on SLEEP */
|
||||
#define SH7750_STBCR_PHZ 0x40 /* State of peripheral module pins in */
|
||||
/* standby mode: */
|
||||
/* 0 normal state */
|
||||
/* 1 high-impendance state */
|
||||
|
||||
#define SH7750_STBCR_PPU 0x20 /* Peripheral module pins pull-up controls */
|
||||
#define SH7750_STBCR_MSTP4 0x10 /* Stopping the clock supply to DMAC */
|
||||
@ -332,16 +331,16 @@
|
||||
#define SH7750_STBCR2 SH7750_P4_REG32(SH7750_STBCR2_REGOFS)
|
||||
#define SH7750_STBCR2_A7 SH7750_A7_REG32(SH7750_STBCR2_REGOFS)
|
||||
|
||||
#define SH7750_STBCR2_DSLP 0x80 /* Specifies transition to deep sleep mode:
|
||||
0 - transition to sleep or standby mode
|
||||
as it is specified in STBY bit
|
||||
1 - transition to deep sleep mode on
|
||||
execution of SLEEP instruction */
|
||||
#define SH7750_STBCR2_MSTP6 0x02 /* Stopping the clock supply to Store Queue
|
||||
in the cache controller */
|
||||
#define SH7750_STBCR2_DSLP 0x80 /* Specifies transition to deep sleep mode */
|
||||
/* 0 transition to sleep or standby mode */
|
||||
/* as it is specified in STBY bit */
|
||||
/* 1 transition to deep sleep mode on */
|
||||
/* execution of SLEEP instruction */
|
||||
#define SH7750_STBCR2_MSTP6 0x02 /* Stopping the clock supply to the */
|
||||
/* Store Queue in the cache controller */
|
||||
#define SH7750_STBCR2_SQ_STP SH7750_STBCR2_MSTP6
|
||||
#define SH7750_STBCR2_MSTP5 0x01 /* Stopping the clock supply to the User
|
||||
Break Controller (UBC) */
|
||||
#define SH7750_STBCR2_MSTP5 0x01 /* Stopping the clock supply to the */
|
||||
/* User Break Controller (UBC) */
|
||||
#define SH7750_STBCR2_UBC_STP SH7750_STBCR2_MSTP5
|
||||
|
||||
/*
|
||||
@ -351,9 +350,9 @@
|
||||
#define SH7750_FRQCR SH7750_P4_REG32(SH7750_FRQCR_REGOFS)
|
||||
#define SH7750_FRQCR_A7 SH7750_A7_REG32(SH7750_FRQCR_REGOFS)
|
||||
|
||||
#define SH7750_FRQCR_CKOEN 0x0800 /* Clock Output Enable
|
||||
0 - CKIO pin goes to HiZ/pullup
|
||||
1 - Clock is output from CKIO */
|
||||
#define SH7750_FRQCR_CKOEN 0x0800 /* Clock Output Enable */
|
||||
/* 0 - CKIO pin goes to HiZ/pullup */
|
||||
/* 1 - Clock is output from CKIO */
|
||||
#define SH7750_FRQCR_PLL1EN 0x0400 /* PLL circuit 1 enable */
|
||||
#define SH7750_FRQCR_PLL2EN 0x0200 /* PLL circuit 2 enable */
|
||||
|
||||
@ -373,8 +372,8 @@
|
||||
#define SH7750_FRQCR_BFCDIV6 0x0020 /* 4 - * 1/6 */
|
||||
#define SH7750_FRQCR_BFCDIV8 0x0028 /* 5 - * 1/8 */
|
||||
|
||||
#define SH7750_FRQCR_PFC 0x0007 /* Peripheral module clock frequency
|
||||
division ratio: */
|
||||
#define SH7750_FRQCR_PFC 0x0007 /* Peripheral module clock frequency */
|
||||
/* division ratio: */
|
||||
#define SH7750_FRQCR_PFCDIV2 0x0000 /* 0 - * 1/2 */
|
||||
#define SH7750_FRQCR_PFCDIV3 0x0001 /* 1 - * 1/3 */
|
||||
#define SH7750_FRQCR_PFCDIV4 0x0002 /* 2 - * 1/4 */
|
||||
@ -389,17 +388,15 @@
|
||||
#define SH7750_WTCNT_REGOFS 0xC00008 /* offset */
|
||||
#define SH7750_WTCNT SH7750_P4_REG32(SH7750_WTCNT_REGOFS)
|
||||
#define SH7750_WTCNT_A7 SH7750_A7_REG32(SH7750_WTCNT_REGOFS)
|
||||
#define SH7750_WTCNT_KEY 0x5A00 /* When WTCNT byte register written,
|
||||
you have to set the upper byte to
|
||||
0x5A */
|
||||
#define SH7750_WTCNT_KEY 0x5A00 /* When WTCNT byte register written, you */
|
||||
/* have to set the upper byte to 0x5A */
|
||||
|
||||
/* Watchdog Timer Control/Status register - WTCSR */
|
||||
#define SH7750_WTCSR_REGOFS 0xC0000C /* offset */
|
||||
#define SH7750_WTCSR SH7750_P4_REG32(SH7750_WTCSR_REGOFS)
|
||||
#define SH7750_WTCSR_A7 SH7750_A7_REG32(SH7750_WTCSR_REGOFS)
|
||||
#define SH7750_WTCSR_KEY 0xA500 /* When WTCSR byte register written,
|
||||
you have to set the upper byte to
|
||||
0xA5 */
|
||||
#define SH7750_WTCSR_KEY 0xA500 /* When WTCSR byte register written, you */
|
||||
/* have to set the upper byte to 0xA5 */
|
||||
#define SH7750_WTCSR_TME 0x80 /* Timer enable (1-upcount start) */
|
||||
#define SH7750_WTCSR_MODE 0x40 /* Timer Mode Select: */
|
||||
#define SH7750_WTCSR_MODE_WT 0x40 /* Watchdog Timer Mode */
|
||||
@ -540,10 +537,10 @@
|
||||
#define SH7750_RCR2_RTCEN 0x08 /* RTC Crystal Oscillator is Operated */
|
||||
#define SH7750_RCR2_ADJ 0x04 /* 30-Second Adjastment */
|
||||
#define SH7750_RCR2_RESET 0x02 /* Frequency divider circuits are reset */
|
||||
#define SH7750_RCR2_START 0x01 /* 0 - sec, min, hr, day-of-week, month,
|
||||
year counters are stopped
|
||||
1 - sec, min, hr, day-of-week, month,
|
||||
year counters operate normally */
|
||||
#define SH7750_RCR2_START 0x01 /* 0 - sec, min, hr, day-of-week, month, */
|
||||
/* year counters are stopped */
|
||||
/* 1 - sec, min, hr, day-of-week, month, */
|
||||
/* year counters operate normally */
|
||||
/*
|
||||
* Bus State Controller - BSC
|
||||
*/
|
||||
@ -554,96 +551,98 @@
|
||||
#define SH7750_BCR1_ENDIAN 0x80000000 /* Endianness (1 - little endian) */
|
||||
#define SH7750_BCR1_MASTER 0x40000000 /* Master/Slave mode (1-master) */
|
||||
#define SH7750_BCR1_A0MPX 0x20000000 /* Area 0 Memory Type (0-SRAM,1-MPX) */
|
||||
#define SH7750_BCR1_IPUP 0x02000000 /* Input Pin Pull-up Control:
|
||||
0 - pull-up resistor is on for
|
||||
control input pins
|
||||
1 - pull-up resistor is off */
|
||||
#define SH7750_BCR1_OPUP 0x01000000 /* Output Pin Pull-up Control:
|
||||
0 - pull-up resistor is on for
|
||||
control output pins
|
||||
1 - pull-up resistor is off */
|
||||
#define SH7750_BCR1_A1MBC 0x00200000 /* Area 1 SRAM Byte Control Mode:
|
||||
0 - Area 1 SRAM is set to
|
||||
normal mode
|
||||
1 - Area 1 SRAM is set to byte
|
||||
control mode */
|
||||
#define SH7750_BCR1_A4MBC 0x00100000 /* Area 4 SRAM Byte Control Mode:
|
||||
0 - Area 4 SRAM is set to
|
||||
normal mode
|
||||
1 - Area 4 SRAM is set to byte
|
||||
control mode */
|
||||
#define SH7750_BCR1_BREQEN 0x00080000 /* BREQ Enable:
|
||||
0 - External requests are not
|
||||
accepted
|
||||
1 - External requests are
|
||||
accepted */
|
||||
#define SH7750_BCR1_PSHR 0x00040000 /* Partial Sharing Bit:
|
||||
0 - Master Mode
|
||||
1 - Partial-sharing Mode */
|
||||
#define SH7750_BCR1_MEMMPX 0x00020000 /* Area 1 to 6 MPX Interface:
|
||||
0 - SRAM/burst ROM interface
|
||||
1 - MPX interface */
|
||||
#define SH7750_BCR1_HIZMEM 0x00008000 /* High Impendance Control. Specifies
|
||||
the state of A[25:0], BS\, CSn\,
|
||||
RD/WR\, CE2A\, CE2B\ in standby
|
||||
mode and when bus is released:
|
||||
0 - signals go to High-Z mode
|
||||
1 - signals driven */
|
||||
#define SH7750_BCR1_HIZCNT 0x00004000 /* High Impendance Control. Specifies
|
||||
the state of the RAS\, RAS2\, WEn\,
|
||||
CASn\, DQMn, RD\, CASS\, FRAME\,
|
||||
RD2\ signals in standby mode and
|
||||
when bus is released:
|
||||
0 - signals go to High-Z mode
|
||||
1 - signals driven */
|
||||
#define SH7750_BCR1_IPUP 0x02000000 /* Input Pin Pull-up Control: */
|
||||
/* 0 - pull-up resistor is on for */
|
||||
/* control input pins */
|
||||
/* 1 - pull-up resistor is off */
|
||||
#define SH7750_BCR1_OPUP 0x01000000 /* Output Pin Pull-up Control: */
|
||||
/* 0 - pull-up resistor is on for */
|
||||
/* control output pins */
|
||||
/* 1 - pull-up resistor is off */
|
||||
#define SH7750_BCR1_A1MBC 0x00200000 /* Area 1 SRAM Byte Control Mode: */
|
||||
/* 0 - Area 1 SRAM is set to */
|
||||
/* normal mode */
|
||||
/* 1 - Area 1 SRAM is set to byte */
|
||||
/* control mode */
|
||||
#define SH7750_BCR1_A4MBC 0x00100000 /* Area 4 SRAM Byte Control Mode: */
|
||||
/* 0 - Area 4 SRAM is set to */
|
||||
/* normal mode */
|
||||
/* 1 - Area 4 SRAM is set to byte */
|
||||
/* control mode */
|
||||
#define SH7750_BCR1_BREQEN 0x00080000 /* BREQ Enable: */
|
||||
/* 0 - External requests are not */
|
||||
/* accepted */
|
||||
/* 1 - External requests are */
|
||||
/* accepted */
|
||||
#define SH7750_BCR1_PSHR 0x00040000 /* Partial Sharing Bit: */
|
||||
/* 0 - Master Mode */
|
||||
/* 1 - Partial-sharing Mode */
|
||||
#define SH7750_BCR1_MEMMPX 0x00020000 /* Area 1 to 6 MPX Interface: */
|
||||
/* 0 - SRAM/burst ROM interface */
|
||||
/* 1 - MPX interface */
|
||||
#define SH7750_BCR1_HIZMEM 0x00008000 /* High Impendance Control. */
|
||||
/* Specifies the state of A[25:0], */
|
||||
/* BS\, CSn\, RD/WR\, CE2A\, CE2B\ */
|
||||
/* in standby mode and when bus is */
|
||||
/* released: */
|
||||
/* 0 - signals go to High-Z mode */
|
||||
/* 1 - signals driven */
|
||||
#define SH7750_BCR1_HIZCNT 0x00004000 /* High Impendance Control. */
|
||||
/* Specifies the state of the */
|
||||
/* RAS\, RAS2\, WEn\, CASn\, DQMn, */
|
||||
/* RD\, CASS\, FRAME\, RD2\ */
|
||||
/* signals in standby mode and */
|
||||
/* when bus is released: */
|
||||
/* 0 - signals go to High-Z mode */
|
||||
/* 1 - signals driven */
|
||||
#define SH7750_BCR1_A0BST 0x00003800 /* Area 0 Burst ROM Control */
|
||||
#define SH7750_BCR1_A0BST_SRAM 0x0000 /* Area 0 accessed as SRAM i/f */
|
||||
#define SH7750_BCR1_A0BST_ROM4 0x0800 /* Area 0 accessed as burst ROM
|
||||
interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM8 0x1000 /* Area 0 accessed as burst ROM
|
||||
interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM16 0x1800 /* Area 0 accessed as burst ROM
|
||||
interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM32 0x2000 /* Area 0 accessed as burst ROM
|
||||
interface, 32 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM4 0x0800 /* Area 0 accessed as burst ROM */
|
||||
/* interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM8 0x1000 /* Area 0 accessed as burst ROM */
|
||||
/* interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM16 0x1800 /* Area 0 accessed as burst ROM */
|
||||
/* interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A0BST_ROM32 0x2000 /* Area 0 accessed as burst ROM */
|
||||
/* interface, 32 cosequtive access */
|
||||
|
||||
#define SH7750_BCR1_A5BST 0x00000700 /* Area 5 Burst ROM Control */
|
||||
#define SH7750_BCR1_A5BST_SRAM 0x0000 /* Area 5 accessed as SRAM i/f */
|
||||
#define SH7750_BCR1_A5BST_ROM4 0x0100 /* Area 5 accessed as burst ROM
|
||||
interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM8 0x0200 /* Area 5 accessed as burst ROM
|
||||
interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM16 0x0300 /* Area 5 accessed as burst ROM
|
||||
interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM32 0x0400 /* Area 5 accessed as burst ROM
|
||||
interface, 32 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM4 0x0100 /* Area 5 accessed as burst ROM */
|
||||
/* interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM8 0x0200 /* Area 5 accessed as burst ROM */
|
||||
/* interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM16 0x0300 /* Area 5 accessed as burst ROM */
|
||||
/* interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A5BST_ROM32 0x0400 /* Area 5 accessed as burst ROM */
|
||||
/* interface, 32 cosequtive access */
|
||||
|
||||
#define SH7750_BCR1_A6BST 0x000000E0 /* Area 6 Burst ROM Control */
|
||||
#define SH7750_BCR1_A6BST_SRAM 0x0000 /* Area 6 accessed as SRAM i/f */
|
||||
#define SH7750_BCR1_A6BST_ROM4 0x0020 /* Area 6 accessed as burst ROM
|
||||
interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM8 0x0040 /* Area 6 accessed as burst ROM
|
||||
interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM16 0x0060 /* Area 6 accessed as burst ROM
|
||||
interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM32 0x0080 /* Area 6 accessed as burst ROM
|
||||
interface, 32 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM4 0x0020 /* Area 6 accessed as burst ROM */
|
||||
/* interface, 4 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM8 0x0040 /* Area 6 accessed as burst ROM */
|
||||
/* interface, 8 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM16 0x0060 /* Area 6 accessed as burst ROM */
|
||||
/* interface, 16 cosequtive access */
|
||||
#define SH7750_BCR1_A6BST_ROM32 0x0080 /* Area 6 accessed as burst ROM */
|
||||
/* interface, 32 cosequtive access */
|
||||
|
||||
#define SH7750_BCR1_DRAMTP 0x001C /* Area 2 and 3 Memory Type */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3SRAM 0x0000 /* Area 2 and 3 are SRAM or MPX
|
||||
interface. */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3SDRAM 0x0008 /* Area 2 - SRAM/MPX, Area 3 -
|
||||
synchronous DRAM */
|
||||
#define SH7750_BCR1_DRAMTP_2SDRAM_3SDRAM 0x000C /* Area 2 and 3 are synchronous
|
||||
DRAM interface */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3DRAM 0x0010 /* Area 2 - SRAM/MPX, Area 3 -
|
||||
DRAM interface */
|
||||
#define SH7750_BCR1_DRAMTP_2DRAM_3DRAM 0x0014 /* Area 2 and 3 are DRAM
|
||||
interface */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3SRAM 0x0000 /* Area 2 and 3 are SRAM or */
|
||||
/* MPX interface. */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3SDRAM 0x0008 /* Area 2 - SRAM/MPX, Area 3 */
|
||||
/* synchronous DRAM */
|
||||
#define SH7750_BCR1_DRAMTP_2SDRAM_3SDRAM 0x000C /* Area 2 and 3 are */
|
||||
/* synchronous DRAM interface */
|
||||
#define SH7750_BCR1_DRAMTP_2SRAM_3DRAM 0x0010 /* Area 2 - SRAM/MPX, Area 3 */
|
||||
/* DRAM interface */
|
||||
#define SH7750_BCR1_DRAMTP_2DRAM_3DRAM 0x0014 /* Area 2 and 3 are DRAM */
|
||||
/* interface */
|
||||
|
||||
#define SH7750_BCR1_A56PCM 0x00000001 /* Area 5 and 6 Bus Type:
|
||||
0 - SRAM interface
|
||||
1 - PCMCIA interface */
|
||||
#define SH7750_BCR1_A56PCM 0x00000001 /* Area 5 and 6 Bus Type: */
|
||||
/* 0 - SRAM interface */
|
||||
/* 1 - PCMCIA interface */
|
||||
|
||||
/* Bus Control Register 2 (half) - BCR2 */
|
||||
#define SH7750_BCR2_REGOFS 0x800004 /* offset */
|
||||
@ -668,16 +667,16 @@
|
||||
#define SH7750_BCR2_SZ_8 1 /* 8 bits */
|
||||
#define SH7750_BCR2_SZ_16 2 /* 16 bits */
|
||||
#define SH7750_BCR2_SZ_32 3 /* 32 bits */
|
||||
#define SH7750_BCR2_PORTEN 0x0001 /* Port Function Enable :
|
||||
0 - D51-D32 are not used as a port
|
||||
1 - D51-D32 are used as a port */
|
||||
#define SH7750_BCR2_PORTEN 0x0001 /* Port Function Enable */
|
||||
/* 0 - D51-D32 are not used as a port */
|
||||
/* 1 - D51-D32 are used as a port */
|
||||
|
||||
/* Wait Control Register 1 - WCR1 */
|
||||
#define SH7750_WCR1_REGOFS 0x800008 /* offset */
|
||||
#define SH7750_WCR1 SH7750_P4_REG32(SH7750_WCR1_REGOFS)
|
||||
#define SH7750_WCR1_A7 SH7750_A7_REG32(SH7750_WCR1_REGOFS)
|
||||
#define SH7750_WCR1_DMAIW 0x70000000 /* DACK Device Inter-Cycle Idle
|
||||
specification */
|
||||
#define SH7750_WCR1_DMAIW 0x70000000 /* DACK Device Inter-Cycle Idle */
|
||||
/* specification */
|
||||
#define SH7750_WCR1_DMAIW_S 28
|
||||
#define SH7750_WCR1_A6IW 0x07000000 /* Area 6 Inter-Cycle Idle spec. */
|
||||
#define SH7750_WCR1_A6IW_S 24
|
||||
@ -794,8 +793,8 @@
|
||||
#define SH7750_MCR_RASD 0x80000000 /* RAS Down mode */
|
||||
#define SH7750_MCR_MRSET 0x40000000 /* SDRAM Mode Register Set */
|
||||
#define SH7750_MCR_PALL 0x00000000 /* SDRAM Precharge All cmd. Mode */
|
||||
#define SH7750_MCR_TRC 0x38000000 /* RAS Precharge Time at End of
|
||||
Refresh: */
|
||||
#define SH7750_MCR_TRC 0x38000000 /* RAS Precharge Time at End of */
|
||||
/* Refresh: */
|
||||
#define SH7750_MCR_TRC_0 0x00000000 /* 0 */
|
||||
#define SH7750_MCR_TRC_3 0x08000000 /* 3 */
|
||||
#define SH7750_MCR_TRC_6 0x10000000 /* 6 */
|
||||
@ -809,10 +808,10 @@
|
||||
#define SH7750_MCR_TCAS_1 0x00000000 /* 1 */
|
||||
#define SH7750_MCR_TCAS_2 0x00800000 /* 2 */
|
||||
|
||||
#define SH7750_MCR_TPC 0x00380000 /* DRAM: RAS Precharge Period
|
||||
SDRAM: minimum number of cycles
|
||||
until the next bank active cmd
|
||||
is output after precharging */
|
||||
#define SH7750_MCR_TPC 0x00380000 /* DRAM: RAS Precharge Period */
|
||||
/* SDRAM: minimum number of cycles */
|
||||
/* until the next bank active cmd */
|
||||
/* is output after precharging */
|
||||
#define SH7750_MCR_TPC_S 19
|
||||
#define SH7750_MCR_TPC_SDRAM_1 0x00000000 /* 1 cycle */
|
||||
#define SH7750_MCR_TPC_SDRAM_2 0x00080000 /* 2 cycles */
|
||||
@ -823,9 +822,10 @@
|
||||
#define SH7750_MCR_TPC_SDRAM_7 0x00300000 /* 7 cycles */
|
||||
#define SH7750_MCR_TPC_SDRAM_8 0x00380000 /* 8 cycles */
|
||||
|
||||
#define SH7750_MCR_RCD 0x00030000 /* DRAM: RAS-CAS Assertion Delay time
|
||||
SDRAM: bank active-read/write cmd
|
||||
delay time */
|
||||
#define SH7750_MCR_RCD 0x00030000 /* DRAM: RAS-CAS Assertion Delay */
|
||||
/* time */
|
||||
/* SDRAM: bank active-read/write */
|
||||
/* command delay time */
|
||||
#define SH7750_MCR_RCD_DRAM_2 0x00000000 /* DRAM delay 2 clocks */
|
||||
#define SH7750_MCR_RCD_DRAM_3 0x00010000 /* DRAM delay 3 clocks */
|
||||
#define SH7750_MCR_RCD_DRAM_4 0x00020000 /* DRAM delay 4 clocks */
|
||||
@ -841,10 +841,10 @@
|
||||
#define SH7750_MCR_TRWL_4 0x00006000 /* 4 */
|
||||
#define SH7750_MCR_TRWL_5 0x00008000 /* 5 */
|
||||
|
||||
#define SH7750_MCR_TRAS 0x00001C00 /* DRAM: CAS-Before-RAS Refresh RAS
|
||||
asserting period
|
||||
SDRAM: Command interval after
|
||||
synchronous DRAM refresh */
|
||||
#define SH7750_MCR_TRAS 0x00001C00 /* DRAM: CAS-Before-RAS Refresh RAS */
|
||||
/* asserting period */
|
||||
/* SDRAM: Command interval after */
|
||||
/* synchronous DRAM refresh */
|
||||
#define SH7750_MCR_TRAS_DRAM_2 0x00000000 /* 2 */
|
||||
#define SH7750_MCR_TRAS_DRAM_3 0x00000400 /* 3 */
|
||||
#define SH7750_MCR_TRAS_DRAM_4 0x00000800 /* 4 */
|
||||
@ -898,30 +898,30 @@
|
||||
#define SH7750_PCR SH7750_P4_REG32(SH7750_PCR_REGOFS)
|
||||
#define SH7750_PCR_A7 SH7750_A7_REG32(SH7750_PCR_REGOFS)
|
||||
|
||||
#define SH7750_PCR_A5PCW 0xC000 /* Area 5 PCMCIA Wait - Number of wait
|
||||
states to be added to the number of
|
||||
waits specified by WCR2 in a low-speed
|
||||
PCMCIA wait cycle */
|
||||
#define SH7750_PCR_A5PCW 0xC000 /* Area 5 PCMCIA Wait - Number of wait */
|
||||
/* states to be added to the number of */
|
||||
/* waits specified by WCR2 in a */
|
||||
/* low-speed PCMCIA wait cycle */
|
||||
#define SH7750_PCR_A5PCW_0 0x0000 /* 0 waits inserted */
|
||||
#define SH7750_PCR_A5PCW_15 0x4000 /* 15 waits inserted */
|
||||
#define SH7750_PCR_A5PCW_30 0x8000 /* 30 waits inserted */
|
||||
#define SH7750_PCR_A5PCW_50 0xC000 /* 50 waits inserted */
|
||||
|
||||
#define SH7750_PCR_A6PCW 0x3000 /* Area 6 PCMCIA Wait - Number of wait
|
||||
states to be added to the number of
|
||||
waits specified by WCR2 in a low-speed
|
||||
PCMCIA wait cycle */
|
||||
#define SH7750_PCR_A6PCW 0x3000 /* Area 6 PCMCIA Wait - Number of wait */
|
||||
/* states to be added to the number of */
|
||||
/* waits specified by WCR2 in a */
|
||||
/* low-speed PCMCIA wait cycle */
|
||||
#define SH7750_PCR_A6PCW_0 0x0000 /* 0 waits inserted */
|
||||
#define SH7750_PCR_A6PCW_15 0x1000 /* 15 waits inserted */
|
||||
#define SH7750_PCR_A6PCW_30 0x2000 /* 30 waits inserted */
|
||||
#define SH7750_PCR_A6PCW_50 0x3000 /* 50 waits inserted */
|
||||
|
||||
#define SH7750_PCR_A5TED 0x0E00 /* Area 5 Address-OE\/WE\ Assertion Delay,
|
||||
delay time from address output to
|
||||
OE\/WE\ assertion on the connected
|
||||
PCMCIA interface */
|
||||
#define SH7750_PCR_A5TED 0x0E00 /* Area 5 Addr-OE\/WE\ Assertion Delay */
|
||||
/* delay time from address output to */
|
||||
/* OE\/WE\ assertion on the connected */
|
||||
/* PCMCIA interface */
|
||||
#define SH7750_PCR_A5TED_S 9
|
||||
#define SH7750_PCR_A6TED 0x01C0 /* Area 6 Address-OE\/WE\ Assertion Delay */
|
||||
#define SH7750_PCR_A6TED 0x01C0 /* Area 6 Addr-OE\/WE\ Assertion Delay */
|
||||
#define SH7750_PCR_A6TED_S 6
|
||||
|
||||
#define SH7750_PCR_TED_0WS 0 /* 0 Waits inserted */
|
||||
@ -933,10 +933,10 @@
|
||||
#define SH7750_PCR_TED_12WS 6 /* 12 Waits inserted */
|
||||
#define SH7750_PCR_TED_15WS 7 /* 15 Waits inserted */
|
||||
|
||||
#define SH7750_PCR_A5TEH 0x0038 /* Area 5 OE\/WE\ Negation Address delay,
|
||||
address hold delay time from OE\/WE\
|
||||
negation in a write on the connected
|
||||
PCMCIA interface */
|
||||
#define SH7750_PCR_A5TEH 0x0038 /* Area 5 OE\/WE\ Negation Addr delay, */
|
||||
/* address hold delay time from OE\/WE\ */
|
||||
/* negation in a write on the connected */
|
||||
/* PCMCIA interface */
|
||||
#define SH7750_PCR_A5TEH_S 3
|
||||
|
||||
#define SH7750_PCR_A6TEH 0x0007 /* Area 6 OE\/WE\ Negation Address delay */
|
||||
@ -957,9 +957,9 @@
|
||||
#define SH7750_RTCSR_A7 SH7750_A7_REG32(SH7750_RTCSR_REGOFS)
|
||||
|
||||
#define SH7750_RTCSR_KEY 0xA500 /* RTCSR write key */
|
||||
#define SH7750_RTCSR_CMF 0x0080 /* Compare-Match Flag (indicates a
|
||||
match between the refresh timer
|
||||
counter and refresh time constant) */
|
||||
#define SH7750_RTCSR_CMF 0x0080 /* Compare-Match Flag (indicates a */
|
||||
/* match between the refresh timer */
|
||||
/* counter and refresh time constant) */
|
||||
#define SH7750_RTCSR_CMIE 0x0040 /* Compare-Match Interrupt Enable */
|
||||
#define SH7750_RTCSR_CKS 0x0038 /* Refresh Counter Clock Selects */
|
||||
#define SH7750_RTCSR_CKS_DIS 0x0000 /* Clock Input Disabled */
|
||||
@ -972,8 +972,8 @@
|
||||
#define SH7750_RTCSR_CKS_CKIO_DIV4096 0x0038 /* Bus Clock / 4096 */
|
||||
|
||||
#define SH7750_RTCSR_OVF 0x0004 /* Refresh Count Overflow Flag */
|
||||
#define SH7750_RTCSR_OVIE 0x0002 /* Refresh Count Overflow Interrupt
|
||||
Enable */
|
||||
#define SH7750_RTCSR_OVIE 0x0002 /* Refresh Count Overflow Interrupt */
|
||||
/* Enable */
|
||||
#define SH7750_RTCSR_LMTS 0x0001 /* Refresh Count Overflow Limit Select */
|
||||
#define SH7750_RTCSR_LMTS_1024 0x0000 /* Count Limit is 1024 */
|
||||
#define SH7750_RTCSR_LMTS_512 0x0001 /* Count Limit is 512 */
|
||||
@ -1076,9 +1076,9 @@
|
||||
#define SH7750_CHCR_SSA_AMEM8 0xC0000000 /* 8-bit attribute memory space */
|
||||
#define SH7750_CHCR_SSA_AMEM16 0xE0000000 /* 16-bit attribute memory space */
|
||||
|
||||
#define SH7750_CHCR_STC 0x10000000 /* Source Address Wait Control Select,
|
||||
specifies CS5 or CS6 space wait
|
||||
control for PCMCIA access */
|
||||
#define SH7750_CHCR_STC 0x10000000 /* Source Addr Wait Control Select */
|
||||
/* specifies CS5 or CS6 space wait */
|
||||
/* control for PCMCIA access */
|
||||
|
||||
#define SH7750_CHCR_DSA 0x0E000000 /* Source Address Space Attribute */
|
||||
#define SH7750_CHCR_DSA_PCMCIA 0x00000000 /* Reserved in PCMCIA access */
|
||||
@ -1090,10 +1090,10 @@
|
||||
#define SH7750_CHCR_DSA_AMEM8 0x0C000000 /* 8-bit attribute memory space */
|
||||
#define SH7750_CHCR_DSA_AMEM16 0x0E000000 /* 16-bit attribute memory space */
|
||||
|
||||
#define SH7750_CHCR_DTC 0x01000000 /* Destination Address Wait Control
|
||||
Select, specifies CS5 or CS6
|
||||
space wait control for PCMCIA
|
||||
access */
|
||||
#define SH7750_CHCR_DTC 0x01000000 /* Destination Address Wait Control */
|
||||
/* Select, specifies CS5 or CS6 */
|
||||
/* space wait control for PCMCIA */
|
||||
/* access */
|
||||
|
||||
#define SH7750_CHCR_DS 0x00080000 /* DREQ\ Select : */
|
||||
#define SH7750_CHCR_DS_LOWLVL 0x00000000 /* Low Level Detection */
|
||||
@ -1122,49 +1122,49 @@
|
||||
#define SH7750_CHCR_SM_DEC 0x00002000 /* Source Addr Decremented */
|
||||
|
||||
#define SH7750_CHCR_RS 0x00000F00 /* Request Source Select: */
|
||||
#define SH7750_CHCR_RS_ER_DA_EA_TO_EA 0x000 /* External Request, Dual Address
|
||||
Mode (External Addr Space->
|
||||
External Addr Space) */
|
||||
#define SH7750_CHCR_RS_ER_SA_EA_TO_ED 0x200 /* External Request, Single
|
||||
Address Mode (External Addr
|
||||
Space -> External Device) */
|
||||
#define SH7750_CHCR_RS_ER_SA_ED_TO_EA 0x300 /* External Request, Single
|
||||
Address Mode, (External
|
||||
Device -> External Addr
|
||||
Space) */
|
||||
#define SH7750_CHCR_RS_AR_EA_TO_EA 0x400 /* Auto-Request (External Addr
|
||||
Space -> External Addr Space) */
|
||||
#define SH7750_CHCR_RS_ER_DA_EA_TO_EA 0x000 /* External Request, Dual Addr */
|
||||
/* Mode, External Addr Space */
|
||||
/* -> External Addr Space) */
|
||||
#define SH7750_CHCR_RS_ER_SA_EA_TO_ED 0x200 /* External Request, Single */
|
||||
/* Address Mode (Ext. Addr */
|
||||
/* Space -> External Device) */
|
||||
#define SH7750_CHCR_RS_ER_SA_ED_TO_EA 0x300 /* External Request, Single */
|
||||
/* Address Mode, (External */
|
||||
/* Device -> External Addr */
|
||||
/* Space) */
|
||||
#define SH7750_CHCR_RS_AR_EA_TO_EA 0x400 /* Auto-Request (External Addr */
|
||||
/* Space -> Ext. Addr Space) */
|
||||
|
||||
#define SH7750_CHCR_RS_AR_EA_TO_OCP 0x500 /* Auto-Request (External Addr
|
||||
Space -> On-chip Peripheral
|
||||
Module) */
|
||||
#define SH7750_CHCR_RS_AR_OCP_TO_EA 0x600 /* Auto-Request (On-chip
|
||||
Peripheral Module ->
|
||||
External Addr Space */
|
||||
#define SH7750_CHCR_RS_SCITX_EA_TO_SC 0x800 /* SCI Transmit-Data-Empty intr
|
||||
transfer request (external
|
||||
address space -> SCTDR1) */
|
||||
#define SH7750_CHCR_RS_SCIRX_SC_TO_EA 0x900 /* SCI Receive-Data-Full intr
|
||||
transfer request (SCRDR1 ->
|
||||
External Addr Space) */
|
||||
#define SH7750_CHCR_RS_SCIFTX_EA_TO_SC 0xA00 /* SCIF Transmit-Data-Empty intr
|
||||
transfer request (external
|
||||
address space -> SCFTDR1) */
|
||||
#define SH7750_CHCR_RS_SCIFRX_SC_TO_EA 0xB00 /* SCIF Receive-Data-Full intr
|
||||
transfer request (SCFRDR2 ->
|
||||
External Addr Space) */
|
||||
#define SH7750_CHCR_RS_TMU2_EA_TO_EA 0xC00 /* TMU Channel 2 (input capture
|
||||
interrupt), (external address
|
||||
space -> external address
|
||||
space) */
|
||||
#define SH7750_CHCR_RS_TMU2_EA_TO_OCP 0xD00 /* TMU Channel 2 (input capture
|
||||
interrupt), (external address
|
||||
space -> on-chip peripheral
|
||||
module) */
|
||||
#define SH7750_CHCR_RS_TMU2_OCP_TO_EA 0xE00 /* TMU Channel 2 (input capture
|
||||
interrupt), (on-chip
|
||||
peripheral module -> external
|
||||
address space) */
|
||||
#define SH7750_CHCR_RS_AR_EA_TO_OCP 0x500 /* Auto-Request (External Addr */
|
||||
/* Space -> On-chip */
|
||||
/* Peripheral Module) */
|
||||
#define SH7750_CHCR_RS_AR_OCP_TO_EA 0x600 /* Auto-Request (On-chip */
|
||||
/* Peripheral Module -> */
|
||||
/* External Addr Space */
|
||||
#define SH7750_CHCR_RS_SCITX_EA_TO_SC 0x800 /* SCI Transmit-Data-Empty intr */
|
||||
/* transfer request (external */
|
||||
/* address space -> SCTDR1) */
|
||||
#define SH7750_CHCR_RS_SCIRX_SC_TO_EA 0x900 /* SCI Receive-Data-Full intr */
|
||||
/* transfer request (SCRDR1 */
|
||||
/* -> External Addr Space) */
|
||||
#define SH7750_CHCR_RS_SCIFTX_EA_TO_SC 0xA00 /* SCIF TX-Data-Empty intr */
|
||||
/* transfer request (external */
|
||||
/* address space -> SCFTDR1) */
|
||||
#define SH7750_CHCR_RS_SCIFRX_SC_TO_EA 0xB00 /* SCIF Receive-Data-Full intr */
|
||||
/* transfer request (SCFRDR2 */
|
||||
/* -> External Addr Space) */
|
||||
#define SH7750_CHCR_RS_TMU2_EA_TO_EA 0xC00 /* TMU Channel 2 (input capture */
|
||||
/* interrupt), (external */
|
||||
/* address space -> external */
|
||||
/* address space) */
|
||||
#define SH7750_CHCR_RS_TMU2_EA_TO_OCP 0xD00 /* TMU Channel 2 (input capture */
|
||||
/* interrupt), (external */
|
||||
/* address space -> on-chip */
|
||||
/* peripheral module) */
|
||||
#define SH7750_CHCR_RS_TMU2_OCP_TO_EA 0xE00 /* TMU Channel 2 (input capture */
|
||||
/* interrupt), (on-chip */
|
||||
/* peripheral module -> */
|
||||
/* external address space) */
|
||||
|
||||
#define SH7750_CHCR_TM 0x00000080 /* Transmit mode: */
|
||||
#define SH7750_CHCR_TM_CSTEAL 0x00000000 /* Cycle Steal Mode */
|
||||
@ -1255,22 +1255,22 @@
|
||||
#define SH7750_ICR_MAI 0x4000 /* NMI Interrupt Mask */
|
||||
|
||||
#define SH7750_ICR_NMIB 0x0200 /* NMI Block Mode: */
|
||||
#define SH7750_ICR_NMIB_BLK 0x0000 /* NMI requests held pending while
|
||||
SR.BL bit is set to 1 */
|
||||
#define SH7750_ICR_NMIB_NBLK 0x0200 /* NMI requests detected when SR.BL bit
|
||||
set to 1 */
|
||||
#define SH7750_ICR_NMIB_BLK 0x0000 /* NMI requests held pending while */
|
||||
/* SR.BL bit is set to 1 */
|
||||
#define SH7750_ICR_NMIB_NBLK 0x0200 /* NMI requests detected when SR.BL */
|
||||
/* bit set to 1 */
|
||||
|
||||
#define SH7750_ICR_NMIE 0x0100 /* NMI Edge Select: */
|
||||
#define SH7750_ICR_NMIE_FALL 0x0000 /* Interrupt request detected on falling
|
||||
edge of NMI input */
|
||||
#define SH7750_ICR_NMIE_RISE 0x0100 /* Interrupt request detected on rising
|
||||
edge of NMI input */
|
||||
#define SH7750_ICR_NMIE_FALL 0x0000 /* Interrupt request detected on */
|
||||
/* falling edge of NMI input */
|
||||
#define SH7750_ICR_NMIE_RISE 0x0100 /* Interrupt request detected on */
|
||||
/* rising edge of NMI input */
|
||||
|
||||
#define SH7750_ICR_IRLM 0x0080 /* IRL Pin Mode: */
|
||||
#define SH7750_ICR_IRLM_ENC 0x0000 /* IRL\ pins used as a level-encoded
|
||||
interrupt requests */
|
||||
#define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four independent
|
||||
interrupt requests */
|
||||
#define SH7750_ICR_IRLM_ENC 0x0000 /* IRL\ pins used as a level-encoded */
|
||||
/* interrupt requests */
|
||||
#define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four */
|
||||
/* independent interrupt requests */
|
||||
|
||||
/*
|
||||
* User Break Controller registers
|
||||
|
@ -22,10 +22,10 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Shix 2.0 board by Alexis Polti, described at
|
||||
https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
|
||||
|
||||
More information in target/sh4/README.sh4
|
||||
* Shix 2.0 board by Alexis Polti, described at
|
||||
* https://web.archive.org/web/20070917001736/perso.enst.fr/~polti/realisations/shix20
|
||||
*
|
||||
* More information in target/sh4/README.sh4
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
|
3
hw/sh4/trace-events
Normal file
3
hw/sh4/trace-events
Normal file
@ -0,0 +1,3 @@
|
||||
# sh7750.c
|
||||
sh7750_porta(uint16_t prev, uint16_t cur, uint16_t pdtr, uint16_t pctr) "porta changed from 0x%04x to 0x%04x\npdtra=0x%04x, pctra=0x%08x"
|
||||
sh7750_portb(uint16_t prev, uint16_t cur, uint16_t pdtr, uint16_t pctr) "portb changed from 0x%04x to 0x%04x\npdtrb=0x%04x, pctrb=0x%08x"
|
1
hw/sh4/trace.h
Normal file
1
hw/sh4/trace.h
Normal file
@ -0,0 +1 @@
|
||||
#include "trace/trace-hw_sh4.h"
|
@ -10,13 +10,12 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/memory.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sh4/sh.h"
|
||||
#include "hw/timer/tmu012.h"
|
||||
#include "hw/ptimer.h"
|
||||
|
||||
//#define DEBUG_TIMER
|
||||
#include "trace.h"
|
||||
|
||||
#define TIMER_TCR_TPSC (7 << 0)
|
||||
#define TIMER_TCR_CKEG (3 << 3)
|
||||
@ -46,24 +45,24 @@ typedef struct {
|
||||
int feat;
|
||||
int enabled;
|
||||
qemu_irq irq;
|
||||
} sh_timer_state;
|
||||
} SHTimerState;
|
||||
|
||||
/* Check all active timers, and schedule the next timer interrupt. */
|
||||
|
||||
static void sh_timer_update(sh_timer_state *s)
|
||||
static void sh_timer_update(SHTimerState *s)
|
||||
{
|
||||
int new_level = s->int_level && (s->tcr & TIMER_TCR_UNIE);
|
||||
|
||||
if (new_level != s->old_level)
|
||||
if (new_level != s->old_level) {
|
||||
qemu_set_irq(s->irq, new_level);
|
||||
|
||||
}
|
||||
s->old_level = s->int_level;
|
||||
s->int_level = new_level;
|
||||
}
|
||||
|
||||
static uint32_t sh_timer_read(void *opaque, hwaddr offset)
|
||||
{
|
||||
sh_timer_state *s = (sh_timer_state *)opaque;
|
||||
SHTimerState *s = opaque;
|
||||
|
||||
switch (offset >> 2) {
|
||||
case OFFSET_TCOR:
|
||||
@ -73,19 +72,18 @@ static uint32_t sh_timer_read(void *opaque, hwaddr offset)
|
||||
case OFFSET_TCR:
|
||||
return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
|
||||
case OFFSET_TCPR:
|
||||
if (s->feat & TIMER_FEAT_CAPT)
|
||||
if (s->feat & TIMER_FEAT_CAPT) {
|
||||
return s->tcpr;
|
||||
/* fall through */
|
||||
default:
|
||||
hw_error("sh_timer_read: Bad offset %x\n", (int)offset);
|
||||
}
|
||||
}
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
uint32_t value)
|
||||
static void sh_timer_write(void *opaque, hwaddr offset, uint32_t value)
|
||||
{
|
||||
sh_timer_state *s = (sh_timer_state *)opaque;
|
||||
SHTimerState *s = opaque;
|
||||
int freq;
|
||||
|
||||
switch (offset >> 2) {
|
||||
@ -104,19 +102,30 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
case OFFSET_TCR:
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (s->enabled) {
|
||||
/* Pause the timer if it is running. This may cause some
|
||||
inaccuracy dure to rounding, but avoids a whole lot of other
|
||||
messyness. */
|
||||
/*
|
||||
* Pause the timer if it is running. This may cause some inaccuracy
|
||||
* due to rounding, but avoids a whole lot of other messiness
|
||||
*/
|
||||
ptimer_stop(s->timer);
|
||||
}
|
||||
freq = s->freq;
|
||||
/* ??? Need to recalculate expiry time after changing divisor. */
|
||||
switch (value & TIMER_TCR_TPSC) {
|
||||
case 0: freq >>= 2; break;
|
||||
case 1: freq >>= 4; break;
|
||||
case 2: freq >>= 6; break;
|
||||
case 3: freq >>= 8; break;
|
||||
case 4: freq >>= 10; break;
|
||||
case 0:
|
||||
freq >>= 2;
|
||||
break;
|
||||
case 1:
|
||||
freq >>= 4;
|
||||
break;
|
||||
case 2:
|
||||
freq >>= 6;
|
||||
break;
|
||||
case 3:
|
||||
freq >>= 8;
|
||||
break;
|
||||
case 4:
|
||||
freq >>= 10;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
if (s->feat & TIMER_FEAT_EXTCLK) {
|
||||
@ -124,7 +133,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
hw_error("sh_timer_write: Reserved TPSC value\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Reserved TPSC value\n", __func__);
|
||||
}
|
||||
switch ((value & TIMER_TCR_CKEG) >> 3) {
|
||||
case 0:
|
||||
@ -137,7 +147,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
hw_error("sh_timer_write: Reserved CKEG value\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Reserved CKEG value\n", __func__);
|
||||
}
|
||||
switch ((value & TIMER_TCR_ICPE) >> 6) {
|
||||
case 0:
|
||||
@ -149,7 +160,8 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
hw_error("sh_timer_write: Reserved ICPE value\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Reserved ICPE value\n", __func__);
|
||||
}
|
||||
if ((value & TIMER_TCR_UNF) == 0) {
|
||||
s->int_level = 0;
|
||||
@ -158,13 +170,15 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
value &= ~TIMER_TCR_UNF;
|
||||
|
||||
if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) {
|
||||
hw_error("sh_timer_write: Reserved ICPF value\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Reserved ICPF value\n", __func__);
|
||||
}
|
||||
|
||||
value &= ~TIMER_TCR_ICPF; /* capture not supported */
|
||||
|
||||
if (value & TIMER_TCR_RESERVED) {
|
||||
hw_error("sh_timer_write: Reserved TCR bits set\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Reserved TCR bits set\n", __func__);
|
||||
}
|
||||
s->tcr = value;
|
||||
ptimer_set_limit(s->timer, s->tcor, 0);
|
||||
@ -182,19 +196,17 @@ static void sh_timer_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
hw_error("sh_timer_write: Bad offset %x\n", (int)offset);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
|
||||
}
|
||||
sh_timer_update(s);
|
||||
}
|
||||
|
||||
static void sh_timer_start_stop(void *opaque, int enable)
|
||||
{
|
||||
sh_timer_state *s = (sh_timer_state *)opaque;
|
||||
|
||||
#ifdef DEBUG_TIMER
|
||||
printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
|
||||
#endif
|
||||
SHTimerState *s = opaque;
|
||||
|
||||
trace_sh_timer_start_stop(enable, s->enabled);
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (s->enabled && !enable) {
|
||||
ptimer_stop(s->timer);
|
||||
@ -204,24 +216,20 @@ static void sh_timer_start_stop(void *opaque, int enable)
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
s->enabled = !!enable;
|
||||
|
||||
#ifdef DEBUG_TIMER
|
||||
printf("sh_timer_start_stop done %d\n", s->enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sh_timer_tick(void *opaque)
|
||||
{
|
||||
sh_timer_state *s = (sh_timer_state *)opaque;
|
||||
SHTimerState *s = opaque;
|
||||
s->int_level = s->enabled;
|
||||
sh_timer_update(s);
|
||||
}
|
||||
|
||||
static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
|
||||
{
|
||||
sh_timer_state *s;
|
||||
SHTimerState *s;
|
||||
|
||||
s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state));
|
||||
s = g_malloc0(sizeof(*s));
|
||||
s->freq = freq;
|
||||
s->feat = feat;
|
||||
s->tcor = 0xffffffff;
|
||||
@ -252,50 +260,49 @@ typedef struct {
|
||||
int feat;
|
||||
} tmu012_state;
|
||||
|
||||
static uint64_t tmu012_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
static uint64_t tmu012_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
tmu012_state *s = (tmu012_state *)opaque;
|
||||
|
||||
#ifdef DEBUG_TIMER
|
||||
printf("tmu012_read 0x%lx\n", (unsigned long) offset);
|
||||
#endif
|
||||
tmu012_state *s = opaque;
|
||||
|
||||
trace_sh_timer_read(offset);
|
||||
if (offset >= 0x20) {
|
||||
if (!(s->feat & TMU012_FEAT_3CHAN)) {
|
||||
hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad channel offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
}
|
||||
return sh_timer_read(s->timer[2], offset - 0x20);
|
||||
}
|
||||
|
||||
if (offset >= 0x14)
|
||||
if (offset >= 0x14) {
|
||||
return sh_timer_read(s->timer[1], offset - 0x14);
|
||||
|
||||
if (offset >= 0x08)
|
||||
}
|
||||
if (offset >= 0x08) {
|
||||
return sh_timer_read(s->timer[0], offset - 0x08);
|
||||
|
||||
if (offset == 4)
|
||||
}
|
||||
if (offset == 4) {
|
||||
return s->tstr;
|
||||
|
||||
if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
|
||||
}
|
||||
if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
|
||||
return s->tocr;
|
||||
}
|
||||
|
||||
hw_error("tmu012_write: Bad offset %x\n", (int)offset);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tmu012_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
tmu012_state *s = (tmu012_state *)opaque;
|
||||
|
||||
#ifdef DEBUG_TIMER
|
||||
printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
|
||||
#endif
|
||||
tmu012_state *s = opaque;
|
||||
|
||||
trace_sh_timer_write(offset, value);
|
||||
if (offset >= 0x20) {
|
||||
if (!(s->feat & TMU012_FEAT_3CHAN)) {
|
||||
hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad channel offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
}
|
||||
sh_timer_write(s->timer[2], offset - 0x20, value);
|
||||
return;
|
||||
@ -318,7 +325,7 @@ static void tmu012_write(void *opaque, hwaddr offset,
|
||||
sh_timer_start_stop(s->timer[2], value & (1 << 2));
|
||||
} else {
|
||||
if (value & (1 << 2)) {
|
||||
hw_error("tmu012_write: Bad channel\n");
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad channel\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,15 +344,14 @@ static const MemoryRegionOps tmu012_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
void tmu012_init(MemoryRegion *sysmem, hwaddr base,
|
||||
int feat, uint32_t freq,
|
||||
void tmu012_init(MemoryRegion *sysmem, hwaddr base, int feat, uint32_t freq,
|
||||
qemu_irq ch0_irq, qemu_irq ch1_irq,
|
||||
qemu_irq ch2_irq0, qemu_irq ch2_irq1)
|
||||
{
|
||||
tmu012_state *s;
|
||||
int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
|
||||
|
||||
s = (tmu012_state *)g_malloc0(sizeof(tmu012_state));
|
||||
s = g_malloc0(sizeof(*s));
|
||||
s->feat = feat;
|
||||
s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq);
|
||||
s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq);
|
||||
@ -354,15 +360,14 @@ void tmu012_init(MemoryRegion *sysmem, hwaddr base,
|
||||
ch2_irq0); /* ch2_irq1 not supported */
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s,
|
||||
"timer", 0x100000000ULL);
|
||||
memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s, "timer", 0x30);
|
||||
|
||||
memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4",
|
||||
&s->iomem, 0, 0x1000);
|
||||
&s->iomem, 0, memory_region_size(&s->iomem));
|
||||
memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
|
||||
|
||||
memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7",
|
||||
&s->iomem, 0, 0x1000);
|
||||
&s->iomem, 0, memory_region_size(&s->iomem));
|
||||
memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
|
||||
/* ??? Save/restore. */
|
||||
}
|
||||
|
@ -94,3 +94,8 @@ sifive_pwm_set_alarm(uint64_t alarm, uint64_t now) "Setting alarm to: 0x%" PRIx6
|
||||
sifive_pwm_interrupt(int num) "Interrupt %d"
|
||||
sifive_pwm_read(uint64_t offset) "Read at address: 0x%" PRIx64
|
||||
sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address: 0x%" PRIx64
|
||||
|
||||
# sh_timer.c
|
||||
sh_timer_start_stop(int enable, int current) "%d (%d)"
|
||||
sh_timer_read(uint64_t offset) "tmu012_read 0x%" PRIx64
|
||||
sh_timer_write(uint64_t offset, uint64_t value) "tmu012_write 0x%" PRIx64 " 0x%08" PRIx64
|
||||
|
@ -54,15 +54,8 @@ int sh7750_register_io_device(struct SH7750State *s,
|
||||
sh7750_io_device *device);
|
||||
|
||||
/* sh_serial.c */
|
||||
#define TYPE_SH_SERIAL "sh-serial"
|
||||
#define SH_SERIAL_FEAT_SCIF (1 << 0)
|
||||
void sh_serial_init(MemoryRegion *sysmem,
|
||||
hwaddr base, int feat,
|
||||
uint32_t freq, Chardev *chr,
|
||||
qemu_irq eri_source,
|
||||
qemu_irq rxi_source,
|
||||
qemu_irq txi_source,
|
||||
qemu_irq tei_source,
|
||||
qemu_irq bri_source);
|
||||
|
||||
/* sh7750.c */
|
||||
qemu_irq sh7750_irl(struct SH7750State *s);
|
||||
|
@ -58,7 +58,7 @@ struct intc_desc {
|
||||
};
|
||||
|
||||
int sh_intc_get_pending_vector(struct intc_desc *desc, int imask);
|
||||
struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
|
||||
|
||||
void sh_intc_toggle_source(struct intc_source *source,
|
||||
int enable_adj, int assert_adj);
|
||||
|
||||
|
@ -2459,6 +2459,7 @@ if have_system
|
||||
'hw/s390x',
|
||||
'hw/scsi',
|
||||
'hw/sd',
|
||||
'hw/sh4',
|
||||
'hw/sparc',
|
||||
'hw/sparc64',
|
||||
'hw/ssi',
|
||||
|
Loading…
Reference in New Issue
Block a user