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/address-spaces.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), 1);
 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 const MemoryRegionOps sh7750_mem_ops = {
 454    .old_mmio = {
 455        .read = {sh7750_mem_readb,
 456                 sh7750_mem_readw,
 457                 sh7750_mem_readl },
 458        .write = {sh7750_mem_writeb,
 459                  sh7750_mem_writew,
 460                  sh7750_mem_writel },
 461    },
 462    .endianness = DEVICE_NATIVE_ENDIAN,
 463};
 464
 465/* sh775x interrupt controller tables for sh_intc.c
 466 * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
 467 */
 468
 469enum {
 470        UNUSED = 0,
 471
 472        /* interrupt sources */
 473        IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
 474        IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
 475        IRL0, IRL1, IRL2, IRL3,
 476        HUDI, GPIOI,
 477        DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
 478        DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
 479        DMAC_DMAE,
 480        PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
 481        PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
 482        TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
 483        RTC_ATI, RTC_PRI, RTC_CUI,
 484        SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
 485        SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
 486        WDT,
 487        REF_RCMI, REF_ROVI,
 488
 489        /* interrupt groups */
 490        DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
 491        /* irl bundle */
 492        IRL,
 493
 494        NR_SOURCES,
 495};
 496
 497static struct intc_vect vectors[] = {
 498        INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
 499        INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
 500        INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
 501        INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
 502        INTC_VECT(RTC_CUI, 0x4c0),
 503        INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
 504        INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
 505        INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
 506        INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
 507        INTC_VECT(WDT, 0x560),
 508        INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
 509};
 510
 511static struct intc_group groups[] = {
 512        INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
 513        INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
 514        INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
 515        INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
 516        INTC_GROUP(REF, REF_RCMI, REF_ROVI),
 517};
 518
 519static struct intc_prio_reg prio_registers[] = {
 520        { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
 521        { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
 522        { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
 523        { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
 524        { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
 525                                                 TMU4, TMU3,
 526                                                 PCIC1, PCIC0_PCISERR } },
 527};
 528
 529/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
 530
 531static struct intc_vect vectors_dma4[] = {
 532        INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
 533        INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
 534        INTC_VECT(DMAC_DMAE, 0x6c0),
 535};
 536
 537static struct intc_group groups_dma4[] = {
 538        INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
 539                   DMAC_DMTE3, DMAC_DMAE),
 540};
 541
 542/* SH7750R and SH7751R both have 8-channel DMA controllers */
 543
 544static struct intc_vect vectors_dma8[] = {
 545        INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
 546        INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
 547        INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
 548        INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
 549        INTC_VECT(DMAC_DMAE, 0x6c0),
 550};
 551
 552static struct intc_group groups_dma8[] = {
 553        INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
 554                   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
 555                   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
 556};
 557
 558/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
 559
 560static struct intc_vect vectors_tmu34[] = {
 561        INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
 562};
 563
 564static struct intc_mask_reg mask_registers[] = {
 565        { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
 566          { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 567            0, 0, 0, 0, 0, 0, TMU4, TMU3,
 568            PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
 569            PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
 570            PCIC1_PCIDMA3, PCIC0_PCISERR } },
 571};
 572
 573/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
 574
 575static struct intc_vect vectors_irlm[] = {
 576        INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
 577        INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
 578};
 579
 580/* SH7751 and SH7751R both have PCI */
 581
 582static struct intc_vect vectors_pci[] = {
 583        INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
 584        INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
 585        INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
 586        INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
 587};
 588
 589static struct intc_group groups_pci[] = {
 590        INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
 591                   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
 592};
 593
 594static struct intc_vect vectors_irl[] = {
 595        INTC_VECT(IRL_0, 0x200),
 596        INTC_VECT(IRL_1, 0x220),
 597        INTC_VECT(IRL_2, 0x240),
 598        INTC_VECT(IRL_3, 0x260),
 599        INTC_VECT(IRL_4, 0x280),
 600        INTC_VECT(IRL_5, 0x2a0),
 601        INTC_VECT(IRL_6, 0x2c0),
 602        INTC_VECT(IRL_7, 0x2e0),
 603        INTC_VECT(IRL_8, 0x300),
 604        INTC_VECT(IRL_9, 0x320),
 605        INTC_VECT(IRL_A, 0x340),
 606        INTC_VECT(IRL_B, 0x360),
 607        INTC_VECT(IRL_C, 0x380),
 608        INTC_VECT(IRL_D, 0x3a0),
 609        INTC_VECT(IRL_E, 0x3c0),
 610};
 611
 612static struct intc_group groups_irl[] = {
 613        INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
 614                IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
 615};
 616
 617/**********************************************************************
 618 Memory mapped cache and TLB
 619**********************************************************************/
 620
 621#define MM_REGION_MASK   0x07000000
 622#define MM_ICACHE_ADDR   (0)
 623#define MM_ICACHE_DATA   (1)
 624#define MM_ITLB_ADDR     (2)
 625#define MM_ITLB_DATA     (3)
 626#define MM_OCACHE_ADDR   (4)
 627#define MM_OCACHE_DATA   (5)
 628#define MM_UTLB_ADDR     (6)
 629#define MM_UTLB_DATA     (7)
 630#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
 631
 632static uint64_t invalid_read(void *opaque, hwaddr addr)
 633{
 634    abort();
 635
 636    return 0;
 637}
 638
 639static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
 640                                 unsigned size)
 641{
 642    SH7750State *s = opaque;
 643    uint32_t ret = 0;
 644
 645    if (size != 4) {
 646        return invalid_read(opaque, addr);
 647    }
 648
 649    switch (MM_REGION_TYPE(addr)) {
 650    case MM_ICACHE_ADDR:
 651    case MM_ICACHE_DATA:
 652        /* do nothing */
 653        break;
 654    case MM_ITLB_ADDR:
 655        ret = cpu_sh4_read_mmaped_itlb_addr(&s->cpu->env, addr);
 656        break;
 657    case MM_ITLB_DATA:
 658        ret = cpu_sh4_read_mmaped_itlb_data(&s->cpu->env, addr);
 659        break;
 660    case MM_OCACHE_ADDR:
 661    case MM_OCACHE_DATA:
 662        /* do nothing */
 663        break;
 664    case MM_UTLB_ADDR:
 665        ret = cpu_sh4_read_mmaped_utlb_addr(&s->cpu->env, addr);
 666        break;
 667    case MM_UTLB_DATA:
 668        ret = cpu_sh4_read_mmaped_utlb_data(&s->cpu->env, addr);
 669        break;
 670    default:
 671        abort();
 672    }
 673
 674    return ret;
 675}
 676
 677static void invalid_write(void *opaque, hwaddr addr,
 678                          uint64_t mem_value)
 679{
 680    abort();
 681}
 682
 683static void sh7750_mmct_write(void *opaque, hwaddr addr,
 684                              uint64_t mem_value, unsigned size)
 685{
 686    SH7750State *s = opaque;
 687
 688    if (size != 4) {
 689        invalid_write(opaque, addr, mem_value);
 690    }
 691
 692    switch (MM_REGION_TYPE(addr)) {
 693    case MM_ICACHE_ADDR:
 694    case MM_ICACHE_DATA:
 695        /* do nothing */
 696        break;
 697    case MM_ITLB_ADDR:
 698        cpu_sh4_write_mmaped_itlb_addr(&s->cpu->env, addr, mem_value);
 699        break;
 700    case MM_ITLB_DATA:
 701        cpu_sh4_write_mmaped_itlb_data(&s->cpu->env, addr, mem_value);
 702        abort();
 703        break;
 704    case MM_OCACHE_ADDR:
 705    case MM_OCACHE_DATA:
 706        /* do nothing */
 707        break;
 708    case MM_UTLB_ADDR:
 709        cpu_sh4_write_mmaped_utlb_addr(&s->cpu->env, addr, mem_value);
 710        break;
 711    case MM_UTLB_DATA:
 712        cpu_sh4_write_mmaped_utlb_data(&s->cpu->env, addr, mem_value);
 713        break;
 714    default:
 715        abort();
 716        break;
 717    }
 718}
 719
 720static const MemoryRegionOps sh7750_mmct_ops = {
 721    .read = sh7750_mmct_read,
 722    .write = sh7750_mmct_write,
 723    .endianness = DEVICE_NATIVE_ENDIAN,
 724};
 725
 726SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
 727{
 728    SH7750State *s;
 729
 730    s = g_malloc0(sizeof(SH7750State));
 731    s->cpu = cpu;
 732    s->periph_freq = 60000000;  /* 60MHz */
 733    memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
 734                          "memory", 0x1fc01000);
 735
 736    memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0",
 737                             &s->iomem, 0x1f000000, 0x1000);
 738    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
 739
 740    memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0",
 741                             &s->iomem, 0x1f000000, 0x1000);
 742    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
 743
 744    memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8",
 745                             &s->iomem, 0x1f800000, 0x1000);
 746    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
 747
 748    memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8",
 749                             &s->iomem, 0x1f800000, 0x1000);
 750    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
 751
 752    memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc",
 753                             &s->iomem, 0x1fc00000, 0x1000);
 754    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
 755
 756    memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc",
 757                             &s->iomem, 0x1fc00000, 0x1000);
 758    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
 759
 760    memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s,
 761                          "cache-and-tlb", 0x08000000);
 762    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 763
 764    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
 765                 _INTC_ARRAY(mask_registers),
 766                 _INTC_ARRAY(prio_registers));
 767
 768    sh_intc_register_sources(&s->intc,
 769                             _INTC_ARRAY(vectors),
 770                             _INTC_ARRAY(groups));
 771
 772    cpu->env.intc_handle = &s->intc;
 773
 774    sh_serial_init(sysmem, 0x1fe00000,
 775                   0, s->periph_freq, serial_hds[0],
 776                   s->intc.irqs[SCI1_ERI],
 777                   s->intc.irqs[SCI1_RXI],
 778                   s->intc.irqs[SCI1_TXI],
 779                   s->intc.irqs[SCI1_TEI],
 780                   NULL);
 781    sh_serial_init(sysmem, 0x1fe80000,
 782                   SH_SERIAL_FEAT_SCIF,
 783                   s->periph_freq, serial_hds[1],
 784                   s->intc.irqs[SCIF_ERI],
 785                   s->intc.irqs[SCIF_RXI],
 786                   s->intc.irqs[SCIF_TXI],
 787                   NULL,
 788                   s->intc.irqs[SCIF_BRI]);
 789
 790    tmu012_init(sysmem, 0x1fd80000,
 791                TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
 792                s->periph_freq,
 793                s->intc.irqs[TMU0],
 794                s->intc.irqs[TMU1],
 795                s->intc.irqs[TMU2_TUNI],
 796                s->intc.irqs[TMU2_TICPI]);
 797
 798    if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
 799        sh_intc_register_sources(&s->intc,
 800                                 _INTC_ARRAY(vectors_dma4),
 801                                 _INTC_ARRAY(groups_dma4));
 802    }
 803
 804    if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
 805        sh_intc_register_sources(&s->intc,
 806                                 _INTC_ARRAY(vectors_dma8),
 807                                 _INTC_ARRAY(groups_dma8));
 808    }
 809
 810    if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
 811        sh_intc_register_sources(&s->intc,
 812                                 _INTC_ARRAY(vectors_tmu34),
 813                                 NULL, 0);
 814        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
 815                    s->intc.irqs[TMU3],
 816                    s->intc.irqs[TMU4],
 817                    NULL, NULL);
 818    }
 819
 820    if (cpu->env.id & (SH_CPU_SH7751_ALL)) {
 821        sh_intc_register_sources(&s->intc,
 822                                 _INTC_ARRAY(vectors_pci),
 823                                 _INTC_ARRAY(groups_pci));
 824    }
 825
 826    if (cpu->env.id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
 827        sh_intc_register_sources(&s->intc,
 828                                 _INTC_ARRAY(vectors_irlm),
 829                                 NULL, 0);
 830    }
 831
 832    sh_intc_register_sources(&s->intc,
 833                                _INTC_ARRAY(vectors_irl),
 834                                _INTC_ARRAY(groups_irl));
 835    return s;
 836}
 837
 838qemu_irq sh7750_irl(SH7750State *s)
 839{
 840    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
 841    return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), 0);
 842}
 843