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