qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

sh7750.c (27709B)


      1 /*
      2  * SH7750 device
      3  *
      4  * Copyright (c) 2007 Magnus Damm
      5  * Copyright (c) 2005 Samuel Tardieu
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  */
     25 
     26 #include "qemu/osdep.h"
     27 #include "qapi/error.h"
     28 #include "hw/sysbus.h"
     29 #include "hw/irq.h"
     30 #include "hw/sh4/sh.h"
     31 #include "sysemu/sysemu.h"
     32 #include "hw/qdev-properties.h"
     33 #include "hw/qdev-properties-system.h"
     34 #include "sh7750_regs.h"
     35 #include "sh7750_regnames.h"
     36 #include "hw/sh4/sh_intc.h"
     37 #include "hw/timer/tmu012.h"
     38 #include "exec/exec-all.h"
     39 #include "trace.h"
     40 
     41 #define NB_DEVICES 4
     42 
     43 typedef struct SH7750State {
     44     MemoryRegion iomem;
     45     MemoryRegion iomem_1f0;
     46     MemoryRegion iomem_ff0;
     47     MemoryRegion iomem_1f8;
     48     MemoryRegion iomem_ff8;
     49     MemoryRegion iomem_1fc;
     50     MemoryRegion iomem_ffc;
     51     MemoryRegion mmct_iomem;
     52     /* CPU */
     53     SuperHCPU *cpu;
     54     /* Peripheral frequency in Hz */
     55     uint32_t periph_freq;
     56     /* SDRAM controller */
     57     uint32_t bcr1;
     58     uint16_t bcr2;
     59     uint16_t bcr3;
     60     uint32_t bcr4;
     61     uint16_t rfcr;
     62     /* PCMCIA controller */
     63     uint16_t pcr;
     64     /* IO ports */
     65     uint16_t gpioic;
     66     uint32_t pctra;
     67     uint32_t pctrb;
     68     uint16_t portdira;        /* Cached */
     69     uint16_t portpullupa;     /* Cached */
     70     uint16_t portdirb;        /* Cached */
     71     uint16_t portpullupb;     /* Cached */
     72     uint16_t pdtra;
     73     uint16_t pdtrb;
     74     uint16_t periph_pdtra;    /* Imposed by the peripherals */
     75     uint16_t periph_portdira; /* Direction seen from the peripherals */
     76     uint16_t periph_pdtrb;    /* Imposed by the peripherals */
     77     uint16_t periph_portdirb; /* Direction seen from the peripherals */
     78     sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
     79 
     80     /* Cache */
     81     uint32_t ccr;
     82 
     83     struct intc_desc intc;
     84 } SH7750State;
     85 
     86 static inline int has_bcr3_and_bcr4(SH7750State *s)
     87 {
     88     return s->cpu->env.features & SH_FEATURE_BCR3_AND_BCR4;
     89 }
     90 
     91 /*
     92  * I/O ports
     93  */
     94 
     95 int sh7750_register_io_device(SH7750State *s, sh7750_io_device *device)
     96 {
     97     int i;
     98 
     99     for (i = 0; i < NB_DEVICES; i++) {
    100         if (s->devices[i] == NULL) {
    101             s->devices[i] = device;
    102             return 0;
    103         }
    104     }
    105     return -1;
    106 }
    107 
    108 static uint16_t portdir(uint32_t v)
    109 {
    110 #define EVENPORTMASK(n) ((v & (1 << ((n) << 1))) >> (n))
    111     return
    112         EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
    113         EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
    114         EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
    115         EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
    116         EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
    117         EVENPORTMASK(0);
    118 }
    119 
    120 static uint16_t portpullup(uint32_t v)
    121 {
    122 #define ODDPORTMASK(n) ((v & (1 << (((n) << 1) + 1))) >> (n))
    123     return
    124         ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
    125         ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
    126         ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
    127         ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
    128         ODDPORTMASK(1) | ODDPORTMASK(0);
    129 }
    130 
    131 static uint16_t porta_lines(SH7750State *s)
    132 {
    133     return (s->portdira & s->pdtra) | /* CPU */
    134         (s->periph_portdira & s->periph_pdtra) | /* Peripherals */
    135         (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
    136 }
    137 
    138 static uint16_t portb_lines(SH7750State *s)
    139 {
    140     return (s->portdirb & s->pdtrb) | /* CPU */
    141         (s->periph_portdirb & s->periph_pdtrb) | /* Peripherals */
    142         (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
    143 }
    144 
    145 static void gen_port_interrupts(SH7750State *s)
    146 {
    147     /* XXXXX interrupts not generated */
    148 }
    149 
    150 static void porta_changed(SH7750State *s, uint16_t prev)
    151 {
    152     uint16_t currenta, changes;
    153     int i, r = 0;
    154 
    155     currenta = porta_lines(s);
    156     if (currenta == prev) {
    157         return;
    158     }
    159     trace_sh7750_porta(prev, currenta, s->pdtra, s->pctra);
    160     changes = currenta ^ prev;
    161 
    162     for (i = 0; i < NB_DEVICES; i++) {
    163         if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
    164             r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
    165                                                &s->periph_pdtra,
    166                                                &s->periph_portdira,
    167                                                &s->periph_pdtrb,
    168                                                &s->periph_portdirb);
    169         }
    170     }
    171 
    172     if (r) {
    173         gen_port_interrupts(s);
    174     }
    175 }
    176 
    177 static void portb_changed(SH7750State *s, uint16_t prev)
    178 {
    179     uint16_t currentb, changes;
    180     int i, r = 0;
    181 
    182     currentb = portb_lines(s);
    183     if (currentb == prev) {
    184         return;
    185     }
    186     trace_sh7750_portb(prev, currentb, s->pdtrb, s->pctrb);
    187     changes = currentb ^ prev;
    188 
    189     for (i = 0; i < NB_DEVICES; i++) {
    190         if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
    191             r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
    192                                                &s->periph_pdtra,
    193                                                &s->periph_portdira,
    194                                                &s->periph_pdtrb,
    195                                                &s->periph_portdirb);
    196         }
    197     }
    198 
    199     if (r) {
    200         gen_port_interrupts(s);
    201     }
    202 }
    203 
    204 /*
    205  * Memory
    206  */
    207 
    208 static void error_access(const char *kind, hwaddr addr)
    209 {
    210     fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
    211             kind, regname(addr), addr);
    212 }
    213 
    214 static void ignore_access(const char *kind, hwaddr addr)
    215 {
    216     fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
    217             kind, regname(addr), addr);
    218 }
    219 
    220 static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
    221 {
    222     switch (addr) {
    223     default:
    224         error_access("byte read", addr);
    225         abort();
    226     }
    227 }
    228 
    229 static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
    230 {
    231     SH7750State *s = opaque;
    232 
    233     switch (addr) {
    234     case SH7750_BCR2_A7:
    235         return s->bcr2;
    236     case SH7750_BCR3_A7:
    237         if (!has_bcr3_and_bcr4(s)) {
    238             error_access("word read", addr);
    239         }
    240         return s->bcr3;
    241     case SH7750_FRQCR_A7:
    242         return 0;
    243     case SH7750_PCR_A7:
    244         return s->pcr;
    245     case SH7750_RFCR_A7:
    246         fprintf(stderr,
    247                 "Read access to refresh count register, incrementing\n");
    248         return s->rfcr++;
    249     case SH7750_PDTRA_A7:
    250         return porta_lines(s);
    251     case SH7750_PDTRB_A7:
    252         return portb_lines(s);
    253     case SH7750_RTCOR_A7:
    254     case SH7750_RTCNT_A7:
    255     case SH7750_RTCSR_A7:
    256         ignore_access("word read", addr);
    257         return 0;
    258     default:
    259         error_access("word read", addr);
    260         abort();
    261     }
    262 }
    263 
    264 static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
    265 {
    266     SH7750State *s = opaque;
    267     SuperHCPUClass *scc;
    268 
    269     switch (addr) {
    270     case SH7750_BCR1_A7:
    271         return s->bcr1;
    272     case SH7750_BCR4_A7:
    273         if (!has_bcr3_and_bcr4(s)) {
    274             error_access("long read", addr);
    275         }
    276         return s->bcr4;
    277     case SH7750_WCR1_A7:
    278     case SH7750_WCR2_A7:
    279     case SH7750_WCR3_A7:
    280     case SH7750_MCR_A7:
    281         ignore_access("long read", addr);
    282         return 0;
    283     case SH7750_MMUCR_A7:
    284         return s->cpu->env.mmucr;
    285     case SH7750_PTEH_A7:
    286         return s->cpu->env.pteh;
    287     case SH7750_PTEL_A7:
    288         return s->cpu->env.ptel;
    289     case SH7750_TTB_A7:
    290         return s->cpu->env.ttb;
    291     case SH7750_TEA_A7:
    292         return s->cpu->env.tea;
    293     case SH7750_TRA_A7:
    294         return s->cpu->env.tra;
    295     case SH7750_EXPEVT_A7:
    296         return s->cpu->env.expevt;
    297     case SH7750_INTEVT_A7:
    298         return s->cpu->env.intevt;
    299     case SH7750_CCR_A7:
    300         return s->ccr;
    301     case 0x1f000030: /* Processor version */
    302         scc = SUPERH_CPU_GET_CLASS(s->cpu);
    303         return scc->pvr;
    304     case 0x1f000040: /* Cache version */
    305         scc = SUPERH_CPU_GET_CLASS(s->cpu);
    306         return scc->cvr;
    307     case 0x1f000044: /* Processor revision */
    308         scc = SUPERH_CPU_GET_CLASS(s->cpu);
    309         return scc->prr;
    310     default:
    311         error_access("long read", addr);
    312         abort();
    313     }
    314 }
    315 
    316 #define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
    317                         && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
    318 static void sh7750_mem_writeb(void *opaque, hwaddr addr,
    319                               uint32_t mem_value)
    320 {
    321 
    322     if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
    323         ignore_access("byte write", addr);
    324         return;
    325     }
    326 
    327     error_access("byte write", addr);
    328     abort();
    329 }
    330 
    331 static void sh7750_mem_writew(void *opaque, hwaddr addr,
    332                               uint32_t mem_value)
    333 {
    334     SH7750State *s = opaque;
    335     uint16_t temp;
    336 
    337     switch (addr) {
    338         /* SDRAM controller */
    339     case SH7750_BCR2_A7:
    340         s->bcr2 = mem_value;
    341         return;
    342     case SH7750_BCR3_A7:
    343         if (!has_bcr3_and_bcr4(s)) {
    344             error_access("word write", addr);
    345         }
    346         s->bcr3 = mem_value;
    347         return;
    348     case SH7750_PCR_A7:
    349         s->pcr = mem_value;
    350         return;
    351     case SH7750_RTCNT_A7:
    352     case SH7750_RTCOR_A7:
    353     case SH7750_RTCSR_A7:
    354         ignore_access("word write", addr);
    355         return;
    356         /* IO ports */
    357     case SH7750_PDTRA_A7:
    358         temp = porta_lines(s);
    359         s->pdtra = mem_value;
    360         porta_changed(s, temp);
    361         return;
    362     case SH7750_PDTRB_A7:
    363         temp = portb_lines(s);
    364         s->pdtrb = mem_value;
    365         portb_changed(s, temp);
    366         return;
    367     case SH7750_RFCR_A7:
    368         fprintf(stderr, "Write access to refresh count register\n");
    369         s->rfcr = mem_value;
    370         return;
    371     case SH7750_GPIOIC_A7:
    372         s->gpioic = mem_value;
    373         if (mem_value != 0) {
    374             fprintf(stderr, "I/O interrupts not implemented\n");
    375             abort();
    376         }
    377         return;
    378     default:
    379         error_access("word write", addr);
    380         abort();
    381     }
    382 }
    383 
    384 static void sh7750_mem_writel(void *opaque, hwaddr addr,
    385                               uint32_t mem_value)
    386 {
    387     SH7750State *s = opaque;
    388     uint16_t temp;
    389 
    390     switch (addr) {
    391         /* SDRAM controller */
    392     case SH7750_BCR1_A7:
    393         s->bcr1 = mem_value;
    394         return;
    395     case SH7750_BCR4_A7:
    396         if (!has_bcr3_and_bcr4(s)) {
    397             error_access("long write", addr);
    398         }
    399         s->bcr4 = mem_value;
    400         return;
    401     case SH7750_WCR1_A7:
    402     case SH7750_WCR2_A7:
    403     case SH7750_WCR3_A7:
    404     case SH7750_MCR_A7:
    405         ignore_access("long write", addr);
    406         return;
    407         /* IO ports */
    408     case SH7750_PCTRA_A7:
    409         temp = porta_lines(s);
    410         s->pctra = mem_value;
    411         s->portdira = portdir(mem_value);
    412         s->portpullupa = portpullup(mem_value);
    413         porta_changed(s, temp);
    414         return;
    415     case SH7750_PCTRB_A7:
    416         temp = portb_lines(s);
    417         s->pctrb = mem_value;
    418         s->portdirb = portdir(mem_value);
    419         s->portpullupb = portpullup(mem_value);
    420         portb_changed(s, temp);
    421         return;
    422     case SH7750_MMUCR_A7:
    423         if (mem_value & MMUCR_TI) {
    424             cpu_sh4_invalidate_tlb(&s->cpu->env);
    425         }
    426         s->cpu->env.mmucr = mem_value & ~MMUCR_TI;
    427         return;
    428     case SH7750_PTEH_A7:
    429         /* If asid changes, clear all registered tlb entries. */
    430         if ((s->cpu->env.pteh & 0xff) != (mem_value & 0xff)) {
    431             tlb_flush(CPU(s->cpu));
    432         }
    433         s->cpu->env.pteh = mem_value;
    434         return;
    435     case SH7750_PTEL_A7:
    436         s->cpu->env.ptel = mem_value;
    437         return;
    438     case SH7750_PTEA_A7:
    439         s->cpu->env.ptea = mem_value & 0x0000000f;
    440         return;
    441     case SH7750_TTB_A7:
    442         s->cpu->env.ttb = mem_value;
    443         return;
    444     case SH7750_TEA_A7:
    445         s->cpu->env.tea = mem_value;
    446         return;
    447     case SH7750_TRA_A7:
    448         s->cpu->env.tra = mem_value & 0x000007ff;
    449         return;
    450     case SH7750_EXPEVT_A7:
    451         s->cpu->env.expevt = mem_value & 0x000007ff;
    452         return;
    453     case SH7750_INTEVT_A7:
    454         s->cpu->env.intevt = mem_value & 0x000007ff;
    455         return;
    456     case SH7750_CCR_A7:
    457         s->ccr = mem_value;
    458         return;
    459     default:
    460         error_access("long write", addr);
    461         abort();
    462     }
    463 }
    464 
    465 static uint64_t sh7750_mem_readfn(void *opaque, hwaddr addr, unsigned size)
    466 {
    467     switch (size) {
    468     case 1:
    469         return sh7750_mem_readb(opaque, addr);
    470     case 2:
    471         return sh7750_mem_readw(opaque, addr);
    472     case 4:
    473         return sh7750_mem_readl(opaque, addr);
    474     default:
    475         g_assert_not_reached();
    476     }
    477 }
    478 
    479 static void sh7750_mem_writefn(void *opaque, hwaddr addr,
    480                                uint64_t value, unsigned size)
    481 {
    482     switch (size) {
    483     case 1:
    484         sh7750_mem_writeb(opaque, addr, value);
    485         break;
    486     case 2:
    487         sh7750_mem_writew(opaque, addr, value);
    488         break;
    489     case 4:
    490         sh7750_mem_writel(opaque, addr, value);
    491         break;
    492     default:
    493         g_assert_not_reached();
    494     }
    495 }
    496 
    497 static const MemoryRegionOps sh7750_mem_ops = {
    498     .read = sh7750_mem_readfn,
    499     .write = sh7750_mem_writefn,
    500     .valid.min_access_size = 1,
    501     .valid.max_access_size = 4,
    502     .endianness = DEVICE_NATIVE_ENDIAN,
    503 };
    504 
    505 /*
    506  * sh775x interrupt controller tables for sh_intc.c
    507  * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
    508  */
    509 
    510 enum {
    511     UNUSED = 0,
    512 
    513     /* interrupt sources */
    514     IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
    515     IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
    516     IRL0, IRL1, IRL2, IRL3,
    517     HUDI, GPIOI,
    518     DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
    519     DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
    520     DMAC_DMAE,
    521     PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    522     PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
    523     TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
    524     RTC_ATI, RTC_PRI, RTC_CUI,
    525     SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
    526     SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
    527     WDT,
    528     REF_RCMI, REF_ROVI,
    529 
    530     /* interrupt groups */
    531     DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
    532     /* irl bundle */
    533     IRL,
    534 
    535     NR_SOURCES,
    536 };
    537 
    538 static struct intc_vect vectors[] = {
    539     INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
    540     INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
    541     INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
    542     INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
    543     INTC_VECT(RTC_CUI, 0x4c0),
    544     INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
    545     INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
    546     INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
    547     INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
    548     INTC_VECT(WDT, 0x560),
    549     INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
    550 };
    551 
    552 static struct intc_group groups[] = {
    553     INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
    554     INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
    555     INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
    556     INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
    557     INTC_GROUP(REF, REF_RCMI, REF_ROVI),
    558 };
    559 
    560 static struct intc_prio_reg prio_registers[] = {
    561     { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
    562     { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
    563     { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
    564     { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
    565     { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0, TMU4, TMU3,
    566                                              PCIC1, PCIC0_PCISERR } },
    567 };
    568 
    569 /* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
    570 
    571 static struct intc_vect vectors_dma4[] = {
    572     INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
    573     INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
    574     INTC_VECT(DMAC_DMAE, 0x6c0),
    575 };
    576 
    577 static struct intc_group groups_dma4[] = {
    578     INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
    579                DMAC_DMTE3, DMAC_DMAE),
    580 };
    581 
    582 /* SH7750R and SH7751R both have 8-channel DMA controllers */
    583 
    584 static struct intc_vect vectors_dma8[] = {
    585     INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
    586     INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
    587     INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
    588     INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
    589     INTC_VECT(DMAC_DMAE, 0x6c0),
    590 };
    591 
    592 static struct intc_group groups_dma8[] = {
    593     INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
    594                DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
    595                DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
    596 };
    597 
    598 /* SH7750R, SH7751 and SH7751R all have two extra timer channels */
    599 
    600 static struct intc_vect vectors_tmu34[] = {
    601     INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
    602 };
    603 
    604 static struct intc_mask_reg mask_registers[] = {
    605     { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
    606       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    607         0, 0, 0, 0, 0, 0, TMU4, TMU3,
    608         PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    609         PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
    610         PCIC1_PCIDMA3, PCIC0_PCISERR } },
    611 };
    612 
    613 /* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
    614 
    615 static struct intc_vect vectors_irlm[] = {
    616     INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
    617     INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
    618 };
    619 
    620 /* SH7751 and SH7751R both have PCI */
    621 
    622 static struct intc_vect vectors_pci[] = {
    623     INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
    624     INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
    625     INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
    626     INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
    627 };
    628 
    629 static struct intc_group groups_pci[] = {
    630     INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    631                PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
    632 };
    633 
    634 static struct intc_vect vectors_irl[] = {
    635     INTC_VECT(IRL_0, 0x200),
    636     INTC_VECT(IRL_1, 0x220),
    637     INTC_VECT(IRL_2, 0x240),
    638     INTC_VECT(IRL_3, 0x260),
    639     INTC_VECT(IRL_4, 0x280),
    640     INTC_VECT(IRL_5, 0x2a0),
    641     INTC_VECT(IRL_6, 0x2c0),
    642     INTC_VECT(IRL_7, 0x2e0),
    643     INTC_VECT(IRL_8, 0x300),
    644     INTC_VECT(IRL_9, 0x320),
    645     INTC_VECT(IRL_A, 0x340),
    646     INTC_VECT(IRL_B, 0x360),
    647     INTC_VECT(IRL_C, 0x380),
    648     INTC_VECT(IRL_D, 0x3a0),
    649     INTC_VECT(IRL_E, 0x3c0),
    650 };
    651 
    652 static struct intc_group groups_irl[] = {
    653     INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
    654         IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
    655 };
    656 
    657 /*
    658  * Memory mapped cache and TLB
    659  */
    660 
    661 #define MM_REGION_MASK   0x07000000
    662 #define MM_ICACHE_ADDR   (0)
    663 #define MM_ICACHE_DATA   (1)
    664 #define MM_ITLB_ADDR     (2)
    665 #define MM_ITLB_DATA     (3)
    666 #define MM_OCACHE_ADDR   (4)
    667 #define MM_OCACHE_DATA   (5)
    668 #define MM_UTLB_ADDR     (6)
    669 #define MM_UTLB_DATA     (7)
    670 #define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
    671 
    672 static uint64_t invalid_read(void *opaque, hwaddr addr)
    673 {
    674     abort();
    675 
    676     return 0;
    677 }
    678 
    679 static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
    680                                  unsigned size)
    681 {
    682     SH7750State *s = opaque;
    683     uint32_t ret = 0;
    684 
    685     if (size != 4) {
    686         return invalid_read(opaque, addr);
    687     }
    688 
    689     switch (MM_REGION_TYPE(addr)) {
    690     case MM_ICACHE_ADDR:
    691     case MM_ICACHE_DATA:
    692         /* do nothing */
    693         break;
    694     case MM_ITLB_ADDR:
    695         ret = cpu_sh4_read_mmaped_itlb_addr(&s->cpu->env, addr);
    696         break;
    697     case MM_ITLB_DATA:
    698         ret = cpu_sh4_read_mmaped_itlb_data(&s->cpu->env, addr);
    699         break;
    700     case MM_OCACHE_ADDR:
    701     case MM_OCACHE_DATA:
    702         /* do nothing */
    703         break;
    704     case MM_UTLB_ADDR:
    705         ret = cpu_sh4_read_mmaped_utlb_addr(&s->cpu->env, addr);
    706         break;
    707     case MM_UTLB_DATA:
    708         ret = cpu_sh4_read_mmaped_utlb_data(&s->cpu->env, addr);
    709         break;
    710     default:
    711         abort();
    712     }
    713 
    714     return ret;
    715 }
    716 
    717 static void invalid_write(void *opaque, hwaddr addr,
    718                           uint64_t mem_value)
    719 {
    720     abort();
    721 }
    722 
    723 static void sh7750_mmct_write(void *opaque, hwaddr addr,
    724                               uint64_t mem_value, unsigned size)
    725 {
    726     SH7750State *s = opaque;
    727 
    728     if (size != 4) {
    729         invalid_write(opaque, addr, mem_value);
    730     }
    731 
    732     switch (MM_REGION_TYPE(addr)) {
    733     case MM_ICACHE_ADDR:
    734     case MM_ICACHE_DATA:
    735         /* do nothing */
    736         break;
    737     case MM_ITLB_ADDR:
    738         cpu_sh4_write_mmaped_itlb_addr(&s->cpu->env, addr, mem_value);
    739         break;
    740     case MM_ITLB_DATA:
    741         cpu_sh4_write_mmaped_itlb_data(&s->cpu->env, addr, mem_value);
    742         abort();
    743         break;
    744     case MM_OCACHE_ADDR:
    745     case MM_OCACHE_DATA:
    746         /* do nothing */
    747         break;
    748     case MM_UTLB_ADDR:
    749         cpu_sh4_write_mmaped_utlb_addr(&s->cpu->env, addr, mem_value);
    750         break;
    751     case MM_UTLB_DATA:
    752         cpu_sh4_write_mmaped_utlb_data(&s->cpu->env, addr, mem_value);
    753         break;
    754     default:
    755         abort();
    756         break;
    757     }
    758 }
    759 
    760 static const MemoryRegionOps sh7750_mmct_ops = {
    761     .read = sh7750_mmct_read,
    762     .write = sh7750_mmct_write,
    763     .endianness = DEVICE_NATIVE_ENDIAN,
    764 };
    765 
    766 SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
    767 {
    768     SH7750State *s;
    769     DeviceState *dev;
    770     SysBusDevice *sb;
    771     MemoryRegion *mr, *alias;
    772 
    773     s = g_new0(SH7750State, 1);
    774     s->cpu = cpu;
    775     s->periph_freq = 60000000; /* 60MHz */
    776     memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
    777                           "memory", 0x1fc01000);
    778 
    779     memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0",
    780                              &s->iomem, 0x1f000000, 0x1000);
    781     memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
    782 
    783     memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0",
    784                              &s->iomem, 0x1f000000, 0x1000);
    785     memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
    786 
    787     memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8",
    788                              &s->iomem, 0x1f800000, 0x1000);
    789     memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
    790 
    791     memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8",
    792                              &s->iomem, 0x1f800000, 0x1000);
    793     memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
    794 
    795     memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc",
    796                              &s->iomem, 0x1fc00000, 0x1000);
    797     memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
    798 
    799     memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc",
    800                              &s->iomem, 0x1fc00000, 0x1000);
    801     memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
    802 
    803     memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s,
    804                           "cache-and-tlb", 0x08000000);
    805     memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
    806 
    807     sh_intc_init(sysmem, &s->intc, NR_SOURCES,
    808                  _INTC_ARRAY(mask_registers),
    809                  _INTC_ARRAY(prio_registers));
    810 
    811     sh_intc_register_sources(&s->intc,
    812                              _INTC_ARRAY(vectors),
    813                              _INTC_ARRAY(groups));
    814 
    815     cpu->env.intc_handle = &s->intc;
    816 
    817     /* SCI */
    818     dev = qdev_new(TYPE_SH_SERIAL);
    819     dev->id = g_strdup("sci");
    820     qdev_prop_set_chr(dev, "chardev", serial_hd(0));
    821     sb = SYS_BUS_DEVICE(dev);
    822     sysbus_realize_and_unref(sb, &error_fatal);
    823     sysbus_mmio_map(sb, 0, 0xffe00000);
    824     alias = g_malloc(sizeof(*alias));
    825     mr = sysbus_mmio_get_region(sb, 0);
    826     memory_region_init_alias(alias, OBJECT(dev), "sci-a7", mr,
    827                              0, memory_region_size(mr));
    828     memory_region_add_subregion(sysmem, A7ADDR(0xffe00000), alias);
    829     qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCI1_ERI]);
    830     qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCI1_RXI]);
    831     qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCI1_TXI]);
    832     qdev_connect_gpio_out_named(dev, "tei", 0, s->intc.irqs[SCI1_TEI]);
    833 
    834     /* SCIF */
    835     dev = qdev_new(TYPE_SH_SERIAL);
    836     dev->id = g_strdup("scif");
    837     qdev_prop_set_chr(dev, "chardev", serial_hd(1));
    838     qdev_prop_set_uint8(dev, "features", SH_SERIAL_FEAT_SCIF);
    839     sb = SYS_BUS_DEVICE(dev);
    840     sysbus_realize_and_unref(sb, &error_fatal);
    841     sysbus_mmio_map(sb, 0, 0xffe80000);
    842     alias = g_malloc(sizeof(*alias));
    843     mr = sysbus_mmio_get_region(sb, 0);
    844     memory_region_init_alias(alias, OBJECT(dev), "scif-a7", mr,
    845                              0, memory_region_size(mr));
    846     memory_region_add_subregion(sysmem, A7ADDR(0xffe80000), alias);
    847     qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCIF_ERI]);
    848     qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCIF_RXI]);
    849     qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCIF_TXI]);
    850     qdev_connect_gpio_out_named(dev, "bri", 0, s->intc.irqs[SCIF_BRI]);
    851 
    852     tmu012_init(sysmem, 0x1fd80000,
    853                 TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
    854                 s->periph_freq,
    855                 s->intc.irqs[TMU0],
    856                 s->intc.irqs[TMU1],
    857                 s->intc.irqs[TMU2_TUNI],
    858                 s->intc.irqs[TMU2_TICPI]);
    859 
    860     if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
    861         sh_intc_register_sources(&s->intc,
    862                                  _INTC_ARRAY(vectors_dma4),
    863                                  _INTC_ARRAY(groups_dma4));
    864     }
    865 
    866     if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
    867         sh_intc_register_sources(&s->intc,
    868                                  _INTC_ARRAY(vectors_dma8),
    869                                  _INTC_ARRAY(groups_dma8));
    870     }
    871 
    872     if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
    873         sh_intc_register_sources(&s->intc,
    874                                  _INTC_ARRAY(vectors_tmu34),
    875                                  NULL, 0);
    876         tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
    877                     s->intc.irqs[TMU3],
    878                     s->intc.irqs[TMU4],
    879                     NULL, NULL);
    880     }
    881 
    882     if (cpu->env.id & (SH_CPU_SH7751_ALL)) {
    883         sh_intc_register_sources(&s->intc,
    884                                  _INTC_ARRAY(vectors_pci),
    885                                  _INTC_ARRAY(groups_pci));
    886     }
    887 
    888     if (cpu->env.id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
    889         sh_intc_register_sources(&s->intc,
    890                                  _INTC_ARRAY(vectors_irlm),
    891                                  NULL, 0);
    892     }
    893 
    894     sh_intc_register_sources(&s->intc,
    895                                 _INTC_ARRAY(vectors_irl),
    896                                 _INTC_ARRAY(groups_irl));
    897     return s;
    898 }
    899 
    900 qemu_irq sh7750_irl(SH7750State *s)
    901 {
    902     sh_intc_toggle_source(&s->intc.sources[IRL], 1, 0); /* enable */
    903     return qemu_allocate_irq(sh_intc_set_irl, &s->intc.sources[IRL], 0);
    904 }