17a2771d1SPaolo Bonzini /*
27a2771d1SPaolo Bonzini * SH7750 device
37a2771d1SPaolo Bonzini *
47a2771d1SPaolo Bonzini * Copyright (c) 2007 Magnus Damm
57a2771d1SPaolo Bonzini * Copyright (c) 2005 Samuel Tardieu
67a2771d1SPaolo Bonzini *
77a2771d1SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
87a2771d1SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
97a2771d1SPaolo Bonzini * in the Software without restriction, including without limitation the rights
107a2771d1SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
117a2771d1SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
127a2771d1SPaolo Bonzini * furnished to do so, subject to the following conditions:
137a2771d1SPaolo Bonzini *
147a2771d1SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
157a2771d1SPaolo Bonzini * all copies or substantial portions of the Software.
167a2771d1SPaolo Bonzini *
177a2771d1SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187a2771d1SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197a2771d1SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
207a2771d1SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
217a2771d1SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
227a2771d1SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
237a2771d1SPaolo Bonzini * THE SOFTWARE.
247a2771d1SPaolo Bonzini */
2564552b6bSMarkus Armbruster
269d4c9946SPeter Maydell #include "qemu/osdep.h"
27beeb5209SBALATON Zoltan #include "qapi/error.h"
28beeb5209SBALATON Zoltan #include "hw/sysbus.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
300d09e41aSPaolo Bonzini #include "hw/sh4/sh.h"
317a2771d1SPaolo Bonzini #include "sysemu/sysemu.h"
32beeb5209SBALATON Zoltan #include "hw/qdev-properties.h"
33beeb5209SBALATON Zoltan #include "hw/qdev-properties-system.h"
3447b43a1fSPaolo Bonzini #include "sh7750_regs.h"
3547b43a1fSPaolo Bonzini #include "sh7750_regnames.h"
360d09e41aSPaolo Bonzini #include "hw/sh4/sh_intc.h"
3795f4dc44SPhilippe Mathieu-Daudé #include "hw/timer/tmu012.h"
3863c91552SPaolo Bonzini #include "exec/exec-all.h"
39ad52cfc1SBALATON Zoltan #include "trace.h"
407a2771d1SPaolo Bonzini
417a2771d1SPaolo Bonzini typedef struct SH7750State {
427a2771d1SPaolo Bonzini MemoryRegion iomem;
437a2771d1SPaolo Bonzini MemoryRegion iomem_1f0;
447a2771d1SPaolo Bonzini MemoryRegion iomem_ff0;
457a2771d1SPaolo Bonzini MemoryRegion iomem_1f8;
467a2771d1SPaolo Bonzini MemoryRegion iomem_ff8;
477a2771d1SPaolo Bonzini MemoryRegion iomem_1fc;
487a2771d1SPaolo Bonzini MemoryRegion iomem_ffc;
497a2771d1SPaolo Bonzini MemoryRegion mmct_iomem;
507a2771d1SPaolo Bonzini /* CPU */
512f493feeSAndreas Färber SuperHCPU *cpu;
527a2771d1SPaolo Bonzini /* Peripheral frequency in Hz */
537a2771d1SPaolo Bonzini uint32_t periph_freq;
547a2771d1SPaolo Bonzini /* SDRAM controller */
557a2771d1SPaolo Bonzini uint32_t bcr1;
567a2771d1SPaolo Bonzini uint16_t bcr2;
577a2771d1SPaolo Bonzini uint16_t bcr3;
587a2771d1SPaolo Bonzini uint32_t bcr4;
597a2771d1SPaolo Bonzini uint16_t rfcr;
607a2771d1SPaolo Bonzini /* PCMCIA controller */
617a2771d1SPaolo Bonzini uint16_t pcr;
627a2771d1SPaolo Bonzini /* IO ports */
637a2771d1SPaolo Bonzini uint16_t gpioic;
647a2771d1SPaolo Bonzini uint32_t pctra;
657a2771d1SPaolo Bonzini uint32_t pctrb;
667a2771d1SPaolo Bonzini uint16_t portdira; /* Cached */
677a2771d1SPaolo Bonzini uint16_t portpullupa; /* Cached */
687a2771d1SPaolo Bonzini uint16_t portdirb; /* Cached */
697a2771d1SPaolo Bonzini uint16_t portpullupb; /* Cached */
707a2771d1SPaolo Bonzini uint16_t pdtra;
717a2771d1SPaolo Bonzini uint16_t pdtrb;
727a2771d1SPaolo Bonzini uint16_t periph_pdtra; /* Imposed by the peripherals */
737a2771d1SPaolo Bonzini uint16_t periph_portdira; /* Direction seen from the peripherals */
747a2771d1SPaolo Bonzini uint16_t periph_pdtrb; /* Imposed by the peripherals */
757a2771d1SPaolo Bonzini uint16_t periph_portdirb; /* Direction seen from the peripherals */
767a2771d1SPaolo Bonzini
777a2771d1SPaolo Bonzini /* Cache */
787a2771d1SPaolo Bonzini uint32_t ccr;
797a2771d1SPaolo Bonzini
807a2771d1SPaolo Bonzini struct intc_desc intc;
817a2771d1SPaolo Bonzini } SH7750State;
827a2771d1SPaolo Bonzini
has_bcr3_and_bcr4(SH7750State * s)837a2771d1SPaolo Bonzini static inline int has_bcr3_and_bcr4(SH7750State *s)
847a2771d1SPaolo Bonzini {
852f493feeSAndreas Färber return s->cpu->env.features & SH_FEATURE_BCR3_AND_BCR4;
867a2771d1SPaolo Bonzini }
8722138965SBALATON Zoltan
8822138965SBALATON Zoltan /*
8922138965SBALATON Zoltan * I/O ports
9022138965SBALATON Zoltan */
917a2771d1SPaolo Bonzini
portdir(uint32_t v)927a2771d1SPaolo Bonzini static uint16_t portdir(uint32_t v)
937a2771d1SPaolo Bonzini {
947a2771d1SPaolo Bonzini #define EVENPORTMASK(n) ((v & (1 << ((n) << 1))) >> (n))
957a2771d1SPaolo Bonzini return
967a2771d1SPaolo Bonzini EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
977a2771d1SPaolo Bonzini EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
987a2771d1SPaolo Bonzini EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
997a2771d1SPaolo Bonzini EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
1007a2771d1SPaolo Bonzini EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
1017a2771d1SPaolo Bonzini EVENPORTMASK(0);
1027a2771d1SPaolo Bonzini }
1037a2771d1SPaolo Bonzini
portpullup(uint32_t v)1047a2771d1SPaolo Bonzini static uint16_t portpullup(uint32_t v)
1057a2771d1SPaolo Bonzini {
1067a2771d1SPaolo Bonzini #define ODDPORTMASK(n) ((v & (1 << (((n) << 1) + 1))) >> (n))
1077a2771d1SPaolo Bonzini return
1087a2771d1SPaolo Bonzini ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
1097a2771d1SPaolo Bonzini ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
1107a2771d1SPaolo Bonzini ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
1117a2771d1SPaolo Bonzini ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
1127a2771d1SPaolo Bonzini ODDPORTMASK(1) | ODDPORTMASK(0);
1137a2771d1SPaolo Bonzini }
1147a2771d1SPaolo Bonzini
porta_lines(SH7750State * s)1157a2771d1SPaolo Bonzini static uint16_t porta_lines(SH7750State *s)
1167a2771d1SPaolo Bonzini {
1177a2771d1SPaolo Bonzini return (s->portdira & s->pdtra) | /* CPU */
1187a2771d1SPaolo Bonzini (s->periph_portdira & s->periph_pdtra) | /* Peripherals */
1197a2771d1SPaolo Bonzini (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
1207a2771d1SPaolo Bonzini }
1217a2771d1SPaolo Bonzini
portb_lines(SH7750State * s)1227a2771d1SPaolo Bonzini static uint16_t portb_lines(SH7750State *s)
1237a2771d1SPaolo Bonzini {
1247a2771d1SPaolo Bonzini return (s->portdirb & s->pdtrb) | /* CPU */
1257a2771d1SPaolo Bonzini (s->periph_portdirb & s->periph_pdtrb) | /* Peripherals */
1267a2771d1SPaolo Bonzini (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
1277a2771d1SPaolo Bonzini }
1287a2771d1SPaolo Bonzini
porta_changed(SH7750State * s,uint16_t prev)1297a2771d1SPaolo Bonzini static void porta_changed(SH7750State *s, uint16_t prev)
1307a2771d1SPaolo Bonzini {
131*76180a67SPhilippe Mathieu-Daudé uint16_t currenta;
1327a2771d1SPaolo Bonzini
1337a2771d1SPaolo Bonzini currenta = porta_lines(s);
134ac3c9e74SBALATON Zoltan if (currenta == prev) {
1357a2771d1SPaolo Bonzini return;
136ac3c9e74SBALATON Zoltan }
137ad52cfc1SBALATON Zoltan trace_sh7750_porta(prev, currenta, s->pdtra, s->pctra);
138ac3c9e74SBALATON Zoltan }
1397a2771d1SPaolo Bonzini
portb_changed(SH7750State * s,uint16_t prev)1407a2771d1SPaolo Bonzini static void portb_changed(SH7750State *s, uint16_t prev)
1417a2771d1SPaolo Bonzini {
142*76180a67SPhilippe Mathieu-Daudé uint16_t currentb;
1437a2771d1SPaolo Bonzini
1447a2771d1SPaolo Bonzini currentb = portb_lines(s);
145ac3c9e74SBALATON Zoltan if (currentb == prev) {
1467a2771d1SPaolo Bonzini return;
147ac3c9e74SBALATON Zoltan }
148ad52cfc1SBALATON Zoltan trace_sh7750_portb(prev, currentb, s->pdtrb, s->pctrb);
149ac3c9e74SBALATON Zoltan }
1507a2771d1SPaolo Bonzini
15122138965SBALATON Zoltan /*
15222138965SBALATON Zoltan * Memory
15322138965SBALATON Zoltan */
1547a2771d1SPaolo Bonzini
error_access(const char * kind,hwaddr addr)1557a2771d1SPaolo Bonzini static void error_access(const char *kind, hwaddr addr)
1567a2771d1SPaolo Bonzini {
157883f2c59SPhilippe Mathieu-Daudé fprintf(stderr, "%s to %s (0x" HWADDR_FMT_plx ") not supported\n",
1587a2771d1SPaolo Bonzini kind, regname(addr), addr);
1597a2771d1SPaolo Bonzini }
1607a2771d1SPaolo Bonzini
ignore_access(const char * kind,hwaddr addr)1617a2771d1SPaolo Bonzini static void ignore_access(const char *kind, hwaddr addr)
1627a2771d1SPaolo Bonzini {
163883f2c59SPhilippe Mathieu-Daudé fprintf(stderr, "%s to %s (0x" HWADDR_FMT_plx ") ignored\n",
1647a2771d1SPaolo Bonzini kind, regname(addr), addr);
1657a2771d1SPaolo Bonzini }
1667a2771d1SPaolo Bonzini
sh7750_mem_readb(void * opaque,hwaddr addr)1677a2771d1SPaolo Bonzini static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
1687a2771d1SPaolo Bonzini {
1697a2771d1SPaolo Bonzini switch (addr) {
1707a2771d1SPaolo Bonzini default:
1717a2771d1SPaolo Bonzini error_access("byte read", addr);
1727a2771d1SPaolo Bonzini abort();
1737a2771d1SPaolo Bonzini }
1747a2771d1SPaolo Bonzini }
1757a2771d1SPaolo Bonzini
sh7750_mem_readw(void * opaque,hwaddr addr)1767a2771d1SPaolo Bonzini static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
1777a2771d1SPaolo Bonzini {
1787a2771d1SPaolo Bonzini SH7750State *s = opaque;
1797a2771d1SPaolo Bonzini
1807a2771d1SPaolo Bonzini switch (addr) {
1817a2771d1SPaolo Bonzini case SH7750_BCR2_A7:
1827a2771d1SPaolo Bonzini return s->bcr2;
1837a2771d1SPaolo Bonzini case SH7750_BCR3_A7:
184ac3c9e74SBALATON Zoltan if (!has_bcr3_and_bcr4(s)) {
1857a2771d1SPaolo Bonzini error_access("word read", addr);
186ac3c9e74SBALATON Zoltan }
1877a2771d1SPaolo Bonzini return s->bcr3;
1887a2771d1SPaolo Bonzini case SH7750_FRQCR_A7:
1897a2771d1SPaolo Bonzini return 0;
1907a2771d1SPaolo Bonzini case SH7750_PCR_A7:
1917a2771d1SPaolo Bonzini return s->pcr;
1927a2771d1SPaolo Bonzini case SH7750_RFCR_A7:
1937a2771d1SPaolo Bonzini fprintf(stderr,
1947a2771d1SPaolo Bonzini "Read access to refresh count register, incrementing\n");
1957a2771d1SPaolo Bonzini return s->rfcr++;
1967a2771d1SPaolo Bonzini case SH7750_PDTRA_A7:
1977a2771d1SPaolo Bonzini return porta_lines(s);
1987a2771d1SPaolo Bonzini case SH7750_PDTRB_A7:
1997a2771d1SPaolo Bonzini return portb_lines(s);
2007a2771d1SPaolo Bonzini case SH7750_RTCOR_A7:
2017a2771d1SPaolo Bonzini case SH7750_RTCNT_A7:
2027a2771d1SPaolo Bonzini case SH7750_RTCSR_A7:
2037a2771d1SPaolo Bonzini ignore_access("word read", addr);
2047a2771d1SPaolo Bonzini return 0;
2057a2771d1SPaolo Bonzini default:
2067a2771d1SPaolo Bonzini error_access("word read", addr);
2077a2771d1SPaolo Bonzini abort();
2087a2771d1SPaolo Bonzini }
2097a2771d1SPaolo Bonzini }
2107a2771d1SPaolo Bonzini
sh7750_mem_readl(void * opaque,hwaddr addr)2117a2771d1SPaolo Bonzini static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
2127a2771d1SPaolo Bonzini {
2137a2771d1SPaolo Bonzini SH7750State *s = opaque;
214b350ab75SAndreas Färber SuperHCPUClass *scc;
2157a2771d1SPaolo Bonzini
2167a2771d1SPaolo Bonzini switch (addr) {
2177a2771d1SPaolo Bonzini case SH7750_BCR1_A7:
2187a2771d1SPaolo Bonzini return s->bcr1;
2197a2771d1SPaolo Bonzini case SH7750_BCR4_A7:
220ac3c9e74SBALATON Zoltan if (!has_bcr3_and_bcr4(s)) {
2217a2771d1SPaolo Bonzini error_access("long read", addr);
222ac3c9e74SBALATON Zoltan }
2237a2771d1SPaolo Bonzini return s->bcr4;
2247a2771d1SPaolo Bonzini case SH7750_WCR1_A7:
2257a2771d1SPaolo Bonzini case SH7750_WCR2_A7:
2267a2771d1SPaolo Bonzini case SH7750_WCR3_A7:
2277a2771d1SPaolo Bonzini case SH7750_MCR_A7:
2287a2771d1SPaolo Bonzini ignore_access("long read", addr);
2297a2771d1SPaolo Bonzini return 0;
2307a2771d1SPaolo Bonzini case SH7750_MMUCR_A7:
2312f493feeSAndreas Färber return s->cpu->env.mmucr;
2327a2771d1SPaolo Bonzini case SH7750_PTEH_A7:
2332f493feeSAndreas Färber return s->cpu->env.pteh;
2347a2771d1SPaolo Bonzini case SH7750_PTEL_A7:
2352f493feeSAndreas Färber return s->cpu->env.ptel;
2367a2771d1SPaolo Bonzini case SH7750_TTB_A7:
2372f493feeSAndreas Färber return s->cpu->env.ttb;
2387a2771d1SPaolo Bonzini case SH7750_TEA_A7:
2392f493feeSAndreas Färber return s->cpu->env.tea;
2407a2771d1SPaolo Bonzini case SH7750_TRA_A7:
2412f493feeSAndreas Färber return s->cpu->env.tra;
2427a2771d1SPaolo Bonzini case SH7750_EXPEVT_A7:
2432f493feeSAndreas Färber return s->cpu->env.expevt;
2447a2771d1SPaolo Bonzini case SH7750_INTEVT_A7:
2452f493feeSAndreas Färber return s->cpu->env.intevt;
2467a2771d1SPaolo Bonzini case SH7750_CCR_A7:
2477a2771d1SPaolo Bonzini return s->ccr;
2487a2771d1SPaolo Bonzini case 0x1f000030: /* Processor version */
249b350ab75SAndreas Färber scc = SUPERH_CPU_GET_CLASS(s->cpu);
250b350ab75SAndreas Färber return scc->pvr;
2517a2771d1SPaolo Bonzini case 0x1f000040: /* Cache version */
252b350ab75SAndreas Färber scc = SUPERH_CPU_GET_CLASS(s->cpu);
253b350ab75SAndreas Färber return scc->cvr;
2547a2771d1SPaolo Bonzini case 0x1f000044: /* Processor revision */
255b350ab75SAndreas Färber scc = SUPERH_CPU_GET_CLASS(s->cpu);
256b350ab75SAndreas Färber return scc->prr;
2577a2771d1SPaolo Bonzini default:
2587a2771d1SPaolo Bonzini error_access("long read", addr);
2597a2771d1SPaolo Bonzini abort();
2607a2771d1SPaolo Bonzini }
2617a2771d1SPaolo Bonzini }
2627a2771d1SPaolo Bonzini
2637a2771d1SPaolo Bonzini #define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
2647a2771d1SPaolo Bonzini && a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
sh7750_mem_writeb(void * opaque,hwaddr addr,uint32_t mem_value)2657a2771d1SPaolo Bonzini static void sh7750_mem_writeb(void *opaque, hwaddr addr,
2667a2771d1SPaolo Bonzini uint32_t mem_value)
2677a2771d1SPaolo Bonzini {
2687a2771d1SPaolo Bonzini
2697a2771d1SPaolo Bonzini if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
2707a2771d1SPaolo Bonzini ignore_access("byte write", addr);
2717a2771d1SPaolo Bonzini return;
2727a2771d1SPaolo Bonzini }
2737a2771d1SPaolo Bonzini
2747a2771d1SPaolo Bonzini error_access("byte write", addr);
2757a2771d1SPaolo Bonzini abort();
2767a2771d1SPaolo Bonzini }
2777a2771d1SPaolo Bonzini
sh7750_mem_writew(void * opaque,hwaddr addr,uint32_t mem_value)2787a2771d1SPaolo Bonzini static void sh7750_mem_writew(void *opaque, hwaddr addr,
2797a2771d1SPaolo Bonzini uint32_t mem_value)
2807a2771d1SPaolo Bonzini {
2817a2771d1SPaolo Bonzini SH7750State *s = opaque;
2827a2771d1SPaolo Bonzini uint16_t temp;
2837a2771d1SPaolo Bonzini
2847a2771d1SPaolo Bonzini switch (addr) {
2857a2771d1SPaolo Bonzini /* SDRAM controller */
2867a2771d1SPaolo Bonzini case SH7750_BCR2_A7:
2877a2771d1SPaolo Bonzini s->bcr2 = mem_value;
2887a2771d1SPaolo Bonzini return;
2897a2771d1SPaolo Bonzini case SH7750_BCR3_A7:
290ac3c9e74SBALATON Zoltan if (!has_bcr3_and_bcr4(s)) {
2917a2771d1SPaolo Bonzini error_access("word write", addr);
292ac3c9e74SBALATON Zoltan }
2937a2771d1SPaolo Bonzini s->bcr3 = mem_value;
2947a2771d1SPaolo Bonzini return;
2957a2771d1SPaolo Bonzini case SH7750_PCR_A7:
2967a2771d1SPaolo Bonzini s->pcr = mem_value;
2977a2771d1SPaolo Bonzini return;
2987a2771d1SPaolo Bonzini case SH7750_RTCNT_A7:
2997a2771d1SPaolo Bonzini case SH7750_RTCOR_A7:
3007a2771d1SPaolo Bonzini case SH7750_RTCSR_A7:
3017a2771d1SPaolo Bonzini ignore_access("word write", addr);
3027a2771d1SPaolo Bonzini return;
3037a2771d1SPaolo Bonzini /* IO ports */
3047a2771d1SPaolo Bonzini case SH7750_PDTRA_A7:
3057a2771d1SPaolo Bonzini temp = porta_lines(s);
3067a2771d1SPaolo Bonzini s->pdtra = mem_value;
3077a2771d1SPaolo Bonzini porta_changed(s, temp);
3087a2771d1SPaolo Bonzini return;
3097a2771d1SPaolo Bonzini case SH7750_PDTRB_A7:
3107a2771d1SPaolo Bonzini temp = portb_lines(s);
3117a2771d1SPaolo Bonzini s->pdtrb = mem_value;
3127a2771d1SPaolo Bonzini portb_changed(s, temp);
3137a2771d1SPaolo Bonzini return;
3147a2771d1SPaolo Bonzini case SH7750_RFCR_A7:
3157a2771d1SPaolo Bonzini fprintf(stderr, "Write access to refresh count register\n");
3167a2771d1SPaolo Bonzini s->rfcr = mem_value;
3177a2771d1SPaolo Bonzini return;
3187a2771d1SPaolo Bonzini case SH7750_GPIOIC_A7:
3197a2771d1SPaolo Bonzini s->gpioic = mem_value;
3207a2771d1SPaolo Bonzini if (mem_value != 0) {
3217a2771d1SPaolo Bonzini fprintf(stderr, "I/O interrupts not implemented\n");
3227a2771d1SPaolo Bonzini abort();
3237a2771d1SPaolo Bonzini }
3247a2771d1SPaolo Bonzini return;
3257a2771d1SPaolo Bonzini default:
3267a2771d1SPaolo Bonzini error_access("word write", addr);
3277a2771d1SPaolo Bonzini abort();
3287a2771d1SPaolo Bonzini }
3297a2771d1SPaolo Bonzini }
3307a2771d1SPaolo Bonzini
sh7750_mem_writel(void * opaque,hwaddr addr,uint32_t mem_value)3317a2771d1SPaolo Bonzini static void sh7750_mem_writel(void *opaque, hwaddr addr,
3327a2771d1SPaolo Bonzini uint32_t mem_value)
3337a2771d1SPaolo Bonzini {
3347a2771d1SPaolo Bonzini SH7750State *s = opaque;
3357a2771d1SPaolo Bonzini uint16_t temp;
3367a2771d1SPaolo Bonzini
3377a2771d1SPaolo Bonzini switch (addr) {
3387a2771d1SPaolo Bonzini /* SDRAM controller */
3397a2771d1SPaolo Bonzini case SH7750_BCR1_A7:
3407a2771d1SPaolo Bonzini s->bcr1 = mem_value;
3417a2771d1SPaolo Bonzini return;
3427a2771d1SPaolo Bonzini case SH7750_BCR4_A7:
343ac3c9e74SBALATON Zoltan if (!has_bcr3_and_bcr4(s)) {
3447a2771d1SPaolo Bonzini error_access("long write", addr);
345ac3c9e74SBALATON Zoltan }
3467a2771d1SPaolo Bonzini s->bcr4 = mem_value;
3477a2771d1SPaolo Bonzini return;
3487a2771d1SPaolo Bonzini case SH7750_WCR1_A7:
3497a2771d1SPaolo Bonzini case SH7750_WCR2_A7:
3507a2771d1SPaolo Bonzini case SH7750_WCR3_A7:
3517a2771d1SPaolo Bonzini case SH7750_MCR_A7:
3527a2771d1SPaolo Bonzini ignore_access("long write", addr);
3537a2771d1SPaolo Bonzini return;
3547a2771d1SPaolo Bonzini /* IO ports */
3557a2771d1SPaolo Bonzini case SH7750_PCTRA_A7:
3567a2771d1SPaolo Bonzini temp = porta_lines(s);
3577a2771d1SPaolo Bonzini s->pctra = mem_value;
3587a2771d1SPaolo Bonzini s->portdira = portdir(mem_value);
3597a2771d1SPaolo Bonzini s->portpullupa = portpullup(mem_value);
3607a2771d1SPaolo Bonzini porta_changed(s, temp);
3617a2771d1SPaolo Bonzini return;
3627a2771d1SPaolo Bonzini case SH7750_PCTRB_A7:
3637a2771d1SPaolo Bonzini temp = portb_lines(s);
3647a2771d1SPaolo Bonzini s->pctrb = mem_value;
3657a2771d1SPaolo Bonzini s->portdirb = portdir(mem_value);
3667a2771d1SPaolo Bonzini s->portpullupb = portpullup(mem_value);
3677a2771d1SPaolo Bonzini portb_changed(s, temp);
3687a2771d1SPaolo Bonzini return;
3697a2771d1SPaolo Bonzini case SH7750_MMUCR_A7:
3707a2771d1SPaolo Bonzini if (mem_value & MMUCR_TI) {
3712f493feeSAndreas Färber cpu_sh4_invalidate_tlb(&s->cpu->env);
3727a2771d1SPaolo Bonzini }
3732f493feeSAndreas Färber s->cpu->env.mmucr = mem_value & ~MMUCR_TI;
3747a2771d1SPaolo Bonzini return;
3757a2771d1SPaolo Bonzini case SH7750_PTEH_A7:
3767a2771d1SPaolo Bonzini /* If asid changes, clear all registered tlb entries. */
3772f493feeSAndreas Färber if ((s->cpu->env.pteh & 0xff) != (mem_value & 0xff)) {
378d10eb08fSAlex Bennée tlb_flush(CPU(s->cpu));
3792f493feeSAndreas Färber }
3802f493feeSAndreas Färber s->cpu->env.pteh = mem_value;
3817a2771d1SPaolo Bonzini return;
3827a2771d1SPaolo Bonzini case SH7750_PTEL_A7:
3832f493feeSAndreas Färber s->cpu->env.ptel = mem_value;
3847a2771d1SPaolo Bonzini return;
3857a2771d1SPaolo Bonzini case SH7750_PTEA_A7:
3862f493feeSAndreas Färber s->cpu->env.ptea = mem_value & 0x0000000f;
3877a2771d1SPaolo Bonzini return;
3887a2771d1SPaolo Bonzini case SH7750_TTB_A7:
3892f493feeSAndreas Färber s->cpu->env.ttb = mem_value;
3907a2771d1SPaolo Bonzini return;
3917a2771d1SPaolo Bonzini case SH7750_TEA_A7:
3922f493feeSAndreas Färber s->cpu->env.tea = mem_value;
3937a2771d1SPaolo Bonzini return;
3947a2771d1SPaolo Bonzini case SH7750_TRA_A7:
3952f493feeSAndreas Färber s->cpu->env.tra = mem_value & 0x000007ff;
3967a2771d1SPaolo Bonzini return;
3977a2771d1SPaolo Bonzini case SH7750_EXPEVT_A7:
3982f493feeSAndreas Färber s->cpu->env.expevt = mem_value & 0x000007ff;
3997a2771d1SPaolo Bonzini return;
4007a2771d1SPaolo Bonzini case SH7750_INTEVT_A7:
4012f493feeSAndreas Färber s->cpu->env.intevt = mem_value & 0x000007ff;
4027a2771d1SPaolo Bonzini return;
4037a2771d1SPaolo Bonzini case SH7750_CCR_A7:
4047a2771d1SPaolo Bonzini s->ccr = mem_value;
4057a2771d1SPaolo Bonzini return;
4067a2771d1SPaolo Bonzini default:
4077a2771d1SPaolo Bonzini error_access("long write", addr);
4087a2771d1SPaolo Bonzini abort();
4097a2771d1SPaolo Bonzini }
4107a2771d1SPaolo Bonzini }
4117a2771d1SPaolo Bonzini
sh7750_mem_readfn(void * opaque,hwaddr addr,unsigned size)412d2af524aSPeter Maydell static uint64_t sh7750_mem_readfn(void *opaque, hwaddr addr, unsigned size)
413d2af524aSPeter Maydell {
414d2af524aSPeter Maydell switch (size) {
415d2af524aSPeter Maydell case 1:
416d2af524aSPeter Maydell return sh7750_mem_readb(opaque, addr);
417d2af524aSPeter Maydell case 2:
418d2af524aSPeter Maydell return sh7750_mem_readw(opaque, addr);
419d2af524aSPeter Maydell case 4:
420d2af524aSPeter Maydell return sh7750_mem_readl(opaque, addr);
421d2af524aSPeter Maydell default:
422d2af524aSPeter Maydell g_assert_not_reached();
423d2af524aSPeter Maydell }
424d2af524aSPeter Maydell }
425d2af524aSPeter Maydell
sh7750_mem_writefn(void * opaque,hwaddr addr,uint64_t value,unsigned size)426d2af524aSPeter Maydell static void sh7750_mem_writefn(void *opaque, hwaddr addr,
427d2af524aSPeter Maydell uint64_t value, unsigned size)
428d2af524aSPeter Maydell {
429d2af524aSPeter Maydell switch (size) {
430d2af524aSPeter Maydell case 1:
431d2af524aSPeter Maydell sh7750_mem_writeb(opaque, addr, value);
432d2af524aSPeter Maydell break;
433d2af524aSPeter Maydell case 2:
434d2af524aSPeter Maydell sh7750_mem_writew(opaque, addr, value);
435d2af524aSPeter Maydell break;
436d2af524aSPeter Maydell case 4:
437d2af524aSPeter Maydell sh7750_mem_writel(opaque, addr, value);
438d2af524aSPeter Maydell break;
439d2af524aSPeter Maydell default:
440d2af524aSPeter Maydell g_assert_not_reached();
441d2af524aSPeter Maydell }
442d2af524aSPeter Maydell }
443d2af524aSPeter Maydell
4447a2771d1SPaolo Bonzini static const MemoryRegionOps sh7750_mem_ops = {
445d2af524aSPeter Maydell .read = sh7750_mem_readfn,
446d2af524aSPeter Maydell .write = sh7750_mem_writefn,
447d2af524aSPeter Maydell .valid.min_access_size = 1,
448d2af524aSPeter Maydell .valid.max_access_size = 4,
4497a2771d1SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
4507a2771d1SPaolo Bonzini };
4517a2771d1SPaolo Bonzini
45222138965SBALATON Zoltan /*
45322138965SBALATON Zoltan * sh775x interrupt controller tables for sh_intc.c
4547a2771d1SPaolo Bonzini * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
4557a2771d1SPaolo Bonzini */
4567a2771d1SPaolo Bonzini
4577a2771d1SPaolo Bonzini enum {
4587a2771d1SPaolo Bonzini UNUSED = 0,
4597a2771d1SPaolo Bonzini
4607a2771d1SPaolo Bonzini /* interrupt sources */
4617a2771d1SPaolo Bonzini IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
4627a2771d1SPaolo Bonzini IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
4637a2771d1SPaolo Bonzini IRL0, IRL1, IRL2, IRL3,
4647a2771d1SPaolo Bonzini HUDI, GPIOI,
4657a2771d1SPaolo Bonzini DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
4667a2771d1SPaolo Bonzini DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
4677a2771d1SPaolo Bonzini DMAC_DMAE,
4687a2771d1SPaolo Bonzini PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
4697a2771d1SPaolo Bonzini PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
4707a2771d1SPaolo Bonzini TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
4717a2771d1SPaolo Bonzini RTC_ATI, RTC_PRI, RTC_CUI,
4727a2771d1SPaolo Bonzini SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
4737a2771d1SPaolo Bonzini SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
4747a2771d1SPaolo Bonzini WDT,
4757a2771d1SPaolo Bonzini REF_RCMI, REF_ROVI,
4767a2771d1SPaolo Bonzini
4777a2771d1SPaolo Bonzini /* interrupt groups */
4787a2771d1SPaolo Bonzini DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
4797a2771d1SPaolo Bonzini /* irl bundle */
4807a2771d1SPaolo Bonzini IRL,
4817a2771d1SPaolo Bonzini
4827a2771d1SPaolo Bonzini NR_SOURCES,
4837a2771d1SPaolo Bonzini };
4847a2771d1SPaolo Bonzini
4857a2771d1SPaolo Bonzini static struct intc_vect vectors[] = {
4867a2771d1SPaolo Bonzini INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
4877a2771d1SPaolo Bonzini INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
4887a2771d1SPaolo Bonzini INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
4897a2771d1SPaolo Bonzini INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
4907a2771d1SPaolo Bonzini INTC_VECT(RTC_CUI, 0x4c0),
4917a2771d1SPaolo Bonzini INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
4927a2771d1SPaolo Bonzini INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
4937a2771d1SPaolo Bonzini INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
4947a2771d1SPaolo Bonzini INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
4957a2771d1SPaolo Bonzini INTC_VECT(WDT, 0x560),
4967a2771d1SPaolo Bonzini INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
4977a2771d1SPaolo Bonzini };
4987a2771d1SPaolo Bonzini
4997a2771d1SPaolo Bonzini static struct intc_group groups[] = {
5007a2771d1SPaolo Bonzini INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
5017a2771d1SPaolo Bonzini INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
5027a2771d1SPaolo Bonzini INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
5037a2771d1SPaolo Bonzini INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
5047a2771d1SPaolo Bonzini INTC_GROUP(REF, REF_RCMI, REF_ROVI),
5057a2771d1SPaolo Bonzini };
5067a2771d1SPaolo Bonzini
5077a2771d1SPaolo Bonzini static struct intc_prio_reg prio_registers[] = {
5087a2771d1SPaolo Bonzini { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
5097a2771d1SPaolo Bonzini { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
5107a2771d1SPaolo Bonzini { 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
5117a2771d1SPaolo Bonzini { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
512b3793b8aSBALATON Zoltan { 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0, TMU4, TMU3,
5137a2771d1SPaolo Bonzini PCIC1, PCIC0_PCISERR } },
5147a2771d1SPaolo Bonzini };
5157a2771d1SPaolo Bonzini
5167a2771d1SPaolo Bonzini /* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
5177a2771d1SPaolo Bonzini
5187a2771d1SPaolo Bonzini static struct intc_vect vectors_dma4[] = {
5197a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
5207a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
5217a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMAE, 0x6c0),
5227a2771d1SPaolo Bonzini };
5237a2771d1SPaolo Bonzini
5247a2771d1SPaolo Bonzini static struct intc_group groups_dma4[] = {
5257a2771d1SPaolo Bonzini INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
5267a2771d1SPaolo Bonzini DMAC_DMTE3, DMAC_DMAE),
5277a2771d1SPaolo Bonzini };
5287a2771d1SPaolo Bonzini
5297a2771d1SPaolo Bonzini /* SH7750R and SH7751R both have 8-channel DMA controllers */
5307a2771d1SPaolo Bonzini
5317a2771d1SPaolo Bonzini static struct intc_vect vectors_dma8[] = {
5327a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
5337a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
5347a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
5357a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
5367a2771d1SPaolo Bonzini INTC_VECT(DMAC_DMAE, 0x6c0),
5377a2771d1SPaolo Bonzini };
5387a2771d1SPaolo Bonzini
5397a2771d1SPaolo Bonzini static struct intc_group groups_dma8[] = {
5407a2771d1SPaolo Bonzini INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
5417a2771d1SPaolo Bonzini DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
5427a2771d1SPaolo Bonzini DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
5437a2771d1SPaolo Bonzini };
5447a2771d1SPaolo Bonzini
5457a2771d1SPaolo Bonzini /* SH7750R, SH7751 and SH7751R all have two extra timer channels */
5467a2771d1SPaolo Bonzini
5477a2771d1SPaolo Bonzini static struct intc_vect vectors_tmu34[] = {
5487a2771d1SPaolo Bonzini INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
5497a2771d1SPaolo Bonzini };
5507a2771d1SPaolo Bonzini
5517a2771d1SPaolo Bonzini static struct intc_mask_reg mask_registers[] = {
5527a2771d1SPaolo Bonzini { 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
5537a2771d1SPaolo Bonzini { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5547a2771d1SPaolo Bonzini 0, 0, 0, 0, 0, 0, TMU4, TMU3,
5557a2771d1SPaolo Bonzini PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
5567a2771d1SPaolo Bonzini PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
5577a2771d1SPaolo Bonzini PCIC1_PCIDMA3, PCIC0_PCISERR } },
5587a2771d1SPaolo Bonzini };
5597a2771d1SPaolo Bonzini
5607a2771d1SPaolo Bonzini /* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
5617a2771d1SPaolo Bonzini
5627a2771d1SPaolo Bonzini static struct intc_vect vectors_irlm[] = {
5637a2771d1SPaolo Bonzini INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
5647a2771d1SPaolo Bonzini INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
5657a2771d1SPaolo Bonzini };
5667a2771d1SPaolo Bonzini
5677a2771d1SPaolo Bonzini /* SH7751 and SH7751R both have PCI */
5687a2771d1SPaolo Bonzini
5697a2771d1SPaolo Bonzini static struct intc_vect vectors_pci[] = {
5707a2771d1SPaolo Bonzini INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
5717a2771d1SPaolo Bonzini INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
5727a2771d1SPaolo Bonzini INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
5737a2771d1SPaolo Bonzini INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
5747a2771d1SPaolo Bonzini };
5757a2771d1SPaolo Bonzini
5767a2771d1SPaolo Bonzini static struct intc_group groups_pci[] = {
5777a2771d1SPaolo Bonzini INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
5787a2771d1SPaolo Bonzini PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
5797a2771d1SPaolo Bonzini };
5807a2771d1SPaolo Bonzini
5817a2771d1SPaolo Bonzini static struct intc_vect vectors_irl[] = {
5827a2771d1SPaolo Bonzini INTC_VECT(IRL_0, 0x200),
5837a2771d1SPaolo Bonzini INTC_VECT(IRL_1, 0x220),
5847a2771d1SPaolo Bonzini INTC_VECT(IRL_2, 0x240),
5857a2771d1SPaolo Bonzini INTC_VECT(IRL_3, 0x260),
5867a2771d1SPaolo Bonzini INTC_VECT(IRL_4, 0x280),
5877a2771d1SPaolo Bonzini INTC_VECT(IRL_5, 0x2a0),
5887a2771d1SPaolo Bonzini INTC_VECT(IRL_6, 0x2c0),
5897a2771d1SPaolo Bonzini INTC_VECT(IRL_7, 0x2e0),
5907a2771d1SPaolo Bonzini INTC_VECT(IRL_8, 0x300),
5917a2771d1SPaolo Bonzini INTC_VECT(IRL_9, 0x320),
5927a2771d1SPaolo Bonzini INTC_VECT(IRL_A, 0x340),
5937a2771d1SPaolo Bonzini INTC_VECT(IRL_B, 0x360),
5947a2771d1SPaolo Bonzini INTC_VECT(IRL_C, 0x380),
5957a2771d1SPaolo Bonzini INTC_VECT(IRL_D, 0x3a0),
5967a2771d1SPaolo Bonzini INTC_VECT(IRL_E, 0x3c0),
5977a2771d1SPaolo Bonzini };
5987a2771d1SPaolo Bonzini
5997a2771d1SPaolo Bonzini static struct intc_group groups_irl[] = {
6007a2771d1SPaolo Bonzini INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
6017a2771d1SPaolo Bonzini IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
6027a2771d1SPaolo Bonzini };
6037a2771d1SPaolo Bonzini
60422138965SBALATON Zoltan /*
60522138965SBALATON Zoltan * Memory mapped cache and TLB
60622138965SBALATON Zoltan */
6077a2771d1SPaolo Bonzini
6087a2771d1SPaolo Bonzini #define MM_REGION_MASK 0x07000000
6097a2771d1SPaolo Bonzini #define MM_ICACHE_ADDR (0)
6107a2771d1SPaolo Bonzini #define MM_ICACHE_DATA (1)
6117a2771d1SPaolo Bonzini #define MM_ITLB_ADDR (2)
6127a2771d1SPaolo Bonzini #define MM_ITLB_DATA (3)
6137a2771d1SPaolo Bonzini #define MM_OCACHE_ADDR (4)
6147a2771d1SPaolo Bonzini #define MM_OCACHE_DATA (5)
6157a2771d1SPaolo Bonzini #define MM_UTLB_ADDR (6)
6167a2771d1SPaolo Bonzini #define MM_UTLB_DATA (7)
6177a2771d1SPaolo Bonzini #define MM_REGION_TYPE(addr) ((addr & MM_REGION_MASK) >> 24)
6187a2771d1SPaolo Bonzini
invalid_read(void * opaque,hwaddr addr)6197a2771d1SPaolo Bonzini static uint64_t invalid_read(void *opaque, hwaddr addr)
6207a2771d1SPaolo Bonzini {
6217a2771d1SPaolo Bonzini abort();
6227a2771d1SPaolo Bonzini
6237a2771d1SPaolo Bonzini return 0;
6247a2771d1SPaolo Bonzini }
6257a2771d1SPaolo Bonzini
sh7750_mmct_read(void * opaque,hwaddr addr,unsigned size)6267a2771d1SPaolo Bonzini static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
6277a2771d1SPaolo Bonzini unsigned size)
6287a2771d1SPaolo Bonzini {
6297a2771d1SPaolo Bonzini SH7750State *s = opaque;
6307a2771d1SPaolo Bonzini uint32_t ret = 0;
6317a2771d1SPaolo Bonzini
6327a2771d1SPaolo Bonzini if (size != 4) {
6337a2771d1SPaolo Bonzini return invalid_read(opaque, addr);
6347a2771d1SPaolo Bonzini }
6357a2771d1SPaolo Bonzini
6367a2771d1SPaolo Bonzini switch (MM_REGION_TYPE(addr)) {
6377a2771d1SPaolo Bonzini case MM_ICACHE_ADDR:
6387a2771d1SPaolo Bonzini case MM_ICACHE_DATA:
6397a2771d1SPaolo Bonzini /* do nothing */
6407a2771d1SPaolo Bonzini break;
6417a2771d1SPaolo Bonzini case MM_ITLB_ADDR:
6422f493feeSAndreas Färber ret = cpu_sh4_read_mmaped_itlb_addr(&s->cpu->env, addr);
6437a2771d1SPaolo Bonzini break;
6447a2771d1SPaolo Bonzini case MM_ITLB_DATA:
6452f493feeSAndreas Färber ret = cpu_sh4_read_mmaped_itlb_data(&s->cpu->env, addr);
6467a2771d1SPaolo Bonzini break;
6477a2771d1SPaolo Bonzini case MM_OCACHE_ADDR:
6487a2771d1SPaolo Bonzini case MM_OCACHE_DATA:
6497a2771d1SPaolo Bonzini /* do nothing */
6507a2771d1SPaolo Bonzini break;
6517a2771d1SPaolo Bonzini case MM_UTLB_ADDR:
6522f493feeSAndreas Färber ret = cpu_sh4_read_mmaped_utlb_addr(&s->cpu->env, addr);
6537a2771d1SPaolo Bonzini break;
6547a2771d1SPaolo Bonzini case MM_UTLB_DATA:
6552f493feeSAndreas Färber ret = cpu_sh4_read_mmaped_utlb_data(&s->cpu->env, addr);
6567a2771d1SPaolo Bonzini break;
6577a2771d1SPaolo Bonzini default:
6587a2771d1SPaolo Bonzini abort();
6597a2771d1SPaolo Bonzini }
6607a2771d1SPaolo Bonzini
6617a2771d1SPaolo Bonzini return ret;
6627a2771d1SPaolo Bonzini }
6637a2771d1SPaolo Bonzini
invalid_write(void * opaque,hwaddr addr,uint64_t mem_value)6647a2771d1SPaolo Bonzini static void invalid_write(void *opaque, hwaddr addr,
6657a2771d1SPaolo Bonzini uint64_t mem_value)
6667a2771d1SPaolo Bonzini {
6677a2771d1SPaolo Bonzini abort();
6687a2771d1SPaolo Bonzini }
6697a2771d1SPaolo Bonzini
sh7750_mmct_write(void * opaque,hwaddr addr,uint64_t mem_value,unsigned size)6707a2771d1SPaolo Bonzini static void sh7750_mmct_write(void *opaque, hwaddr addr,
6717a2771d1SPaolo Bonzini uint64_t mem_value, unsigned size)
6727a2771d1SPaolo Bonzini {
6737a2771d1SPaolo Bonzini SH7750State *s = opaque;
6747a2771d1SPaolo Bonzini
6757a2771d1SPaolo Bonzini if (size != 4) {
6767a2771d1SPaolo Bonzini invalid_write(opaque, addr, mem_value);
6777a2771d1SPaolo Bonzini }
6787a2771d1SPaolo Bonzini
6797a2771d1SPaolo Bonzini switch (MM_REGION_TYPE(addr)) {
6807a2771d1SPaolo Bonzini case MM_ICACHE_ADDR:
6817a2771d1SPaolo Bonzini case MM_ICACHE_DATA:
6827a2771d1SPaolo Bonzini /* do nothing */
6837a2771d1SPaolo Bonzini break;
6847a2771d1SPaolo Bonzini case MM_ITLB_ADDR:
6852f493feeSAndreas Färber cpu_sh4_write_mmaped_itlb_addr(&s->cpu->env, addr, mem_value);
6867a2771d1SPaolo Bonzini break;
6877a2771d1SPaolo Bonzini case MM_ITLB_DATA:
6882f493feeSAndreas Färber cpu_sh4_write_mmaped_itlb_data(&s->cpu->env, addr, mem_value);
6897a2771d1SPaolo Bonzini abort();
6907a2771d1SPaolo Bonzini break;
6917a2771d1SPaolo Bonzini case MM_OCACHE_ADDR:
6927a2771d1SPaolo Bonzini case MM_OCACHE_DATA:
6937a2771d1SPaolo Bonzini /* do nothing */
6947a2771d1SPaolo Bonzini break;
6957a2771d1SPaolo Bonzini case MM_UTLB_ADDR:
6962f493feeSAndreas Färber cpu_sh4_write_mmaped_utlb_addr(&s->cpu->env, addr, mem_value);
6977a2771d1SPaolo Bonzini break;
6987a2771d1SPaolo Bonzini case MM_UTLB_DATA:
6992f493feeSAndreas Färber cpu_sh4_write_mmaped_utlb_data(&s->cpu->env, addr, mem_value);
7007a2771d1SPaolo Bonzini break;
7017a2771d1SPaolo Bonzini default:
7027a2771d1SPaolo Bonzini abort();
7037a2771d1SPaolo Bonzini break;
7047a2771d1SPaolo Bonzini }
7057a2771d1SPaolo Bonzini }
7067a2771d1SPaolo Bonzini
7077a2771d1SPaolo Bonzini static const MemoryRegionOps sh7750_mmct_ops = {
7087a2771d1SPaolo Bonzini .read = sh7750_mmct_read,
7097a2771d1SPaolo Bonzini .write = sh7750_mmct_write,
7107a2771d1SPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
7117a2771d1SPaolo Bonzini };
7127a2771d1SPaolo Bonzini
sh7750_init(SuperHCPU * cpu,MemoryRegion * sysmem)7132f493feeSAndreas Färber SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
7147a2771d1SPaolo Bonzini {
7157a2771d1SPaolo Bonzini SH7750State *s;
716beeb5209SBALATON Zoltan DeviceState *dev;
717beeb5209SBALATON Zoltan SysBusDevice *sb;
718beeb5209SBALATON Zoltan MemoryRegion *mr, *alias;
7197a2771d1SPaolo Bonzini
720b21e2380SMarkus Armbruster s = g_new0(SH7750State, 1);
7217a2771d1SPaolo Bonzini s->cpu = cpu;
7227a2771d1SPaolo Bonzini s->periph_freq = 60000000; /* 60MHz */
7232c9b15caSPaolo Bonzini memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
7247a2771d1SPaolo Bonzini "memory", 0x1fc01000);
7257a2771d1SPaolo Bonzini
7262c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0",
7277a2771d1SPaolo Bonzini &s->iomem, 0x1f000000, 0x1000);
7287a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
7297a2771d1SPaolo Bonzini
7302c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0",
7317a2771d1SPaolo Bonzini &s->iomem, 0x1f000000, 0x1000);
7327a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
7337a2771d1SPaolo Bonzini
7342c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8",
7357a2771d1SPaolo Bonzini &s->iomem, 0x1f800000, 0x1000);
7367a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
7377a2771d1SPaolo Bonzini
7382c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8",
7397a2771d1SPaolo Bonzini &s->iomem, 0x1f800000, 0x1000);
7407a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
7417a2771d1SPaolo Bonzini
7422c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc",
7437a2771d1SPaolo Bonzini &s->iomem, 0x1fc00000, 0x1000);
7447a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
7457a2771d1SPaolo Bonzini
7462c9b15caSPaolo Bonzini memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc",
7477a2771d1SPaolo Bonzini &s->iomem, 0x1fc00000, 0x1000);
7487a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
7497a2771d1SPaolo Bonzini
7502c9b15caSPaolo Bonzini memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s,
7517a2771d1SPaolo Bonzini "cache-and-tlb", 0x08000000);
7527a2771d1SPaolo Bonzini memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
7537a2771d1SPaolo Bonzini
7547a2771d1SPaolo Bonzini sh_intc_init(sysmem, &s->intc, NR_SOURCES,
7557a2771d1SPaolo Bonzini _INTC_ARRAY(mask_registers),
7567a2771d1SPaolo Bonzini _INTC_ARRAY(prio_registers));
7577a2771d1SPaolo Bonzini
7587a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
7597a2771d1SPaolo Bonzini _INTC_ARRAY(vectors),
7607a2771d1SPaolo Bonzini _INTC_ARRAY(groups));
7617a2771d1SPaolo Bonzini
7622f493feeSAndreas Färber cpu->env.intc_handle = &s->intc;
7637a2771d1SPaolo Bonzini
764beeb5209SBALATON Zoltan /* SCI */
765beeb5209SBALATON Zoltan dev = qdev_new(TYPE_SH_SERIAL);
766beeb5209SBALATON Zoltan dev->id = g_strdup("sci");
767beeb5209SBALATON Zoltan qdev_prop_set_chr(dev, "chardev", serial_hd(0));
768beeb5209SBALATON Zoltan sb = SYS_BUS_DEVICE(dev);
769beeb5209SBALATON Zoltan sysbus_realize_and_unref(sb, &error_fatal);
770beeb5209SBALATON Zoltan sysbus_mmio_map(sb, 0, 0xffe00000);
771beeb5209SBALATON Zoltan alias = g_malloc(sizeof(*alias));
772beeb5209SBALATON Zoltan mr = sysbus_mmio_get_region(sb, 0);
773beeb5209SBALATON Zoltan memory_region_init_alias(alias, OBJECT(dev), "sci-a7", mr,
774beeb5209SBALATON Zoltan 0, memory_region_size(mr));
775beeb5209SBALATON Zoltan memory_region_add_subregion(sysmem, A7ADDR(0xffe00000), alias);
776beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCI1_ERI]);
777beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCI1_RXI]);
778beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCI1_TXI]);
779beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "tei", 0, s->intc.irqs[SCI1_TEI]);
780beeb5209SBALATON Zoltan
781beeb5209SBALATON Zoltan /* SCIF */
782beeb5209SBALATON Zoltan dev = qdev_new(TYPE_SH_SERIAL);
783beeb5209SBALATON Zoltan dev->id = g_strdup("scif");
784beeb5209SBALATON Zoltan qdev_prop_set_chr(dev, "chardev", serial_hd(1));
785beeb5209SBALATON Zoltan qdev_prop_set_uint8(dev, "features", SH_SERIAL_FEAT_SCIF);
786beeb5209SBALATON Zoltan sb = SYS_BUS_DEVICE(dev);
787beeb5209SBALATON Zoltan sysbus_realize_and_unref(sb, &error_fatal);
788beeb5209SBALATON Zoltan sysbus_mmio_map(sb, 0, 0xffe80000);
789beeb5209SBALATON Zoltan alias = g_malloc(sizeof(*alias));
790beeb5209SBALATON Zoltan mr = sysbus_mmio_get_region(sb, 0);
791beeb5209SBALATON Zoltan memory_region_init_alias(alias, OBJECT(dev), "scif-a7", mr,
792beeb5209SBALATON Zoltan 0, memory_region_size(mr));
793beeb5209SBALATON Zoltan memory_region_add_subregion(sysmem, A7ADDR(0xffe80000), alias);
794beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "eri", 0, s->intc.irqs[SCIF_ERI]);
795beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "rxi", 0, s->intc.irqs[SCIF_RXI]);
796beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "txi", 0, s->intc.irqs[SCIF_TXI]);
797beeb5209SBALATON Zoltan qdev_connect_gpio_out_named(dev, "bri", 0, s->intc.irqs[SCIF_BRI]);
7987a2771d1SPaolo Bonzini
7997a2771d1SPaolo Bonzini tmu012_init(sysmem, 0x1fd80000,
8007a2771d1SPaolo Bonzini TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
8017a2771d1SPaolo Bonzini s->periph_freq,
8027a2771d1SPaolo Bonzini s->intc.irqs[TMU0],
8037a2771d1SPaolo Bonzini s->intc.irqs[TMU1],
8047a2771d1SPaolo Bonzini s->intc.irqs[TMU2_TUNI],
8057a2771d1SPaolo Bonzini s->intc.irqs[TMU2_TICPI]);
8067a2771d1SPaolo Bonzini
8072f493feeSAndreas Färber if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
8087a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8097a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_dma4),
8107a2771d1SPaolo Bonzini _INTC_ARRAY(groups_dma4));
8117a2771d1SPaolo Bonzini }
8127a2771d1SPaolo Bonzini
8132f493feeSAndreas Färber if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
8147a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8157a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_dma8),
8167a2771d1SPaolo Bonzini _INTC_ARRAY(groups_dma8));
8177a2771d1SPaolo Bonzini }
8187a2771d1SPaolo Bonzini
8192f493feeSAndreas Färber if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
8207a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8217a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_tmu34),
8227a2771d1SPaolo Bonzini NULL, 0);
8237a2771d1SPaolo Bonzini tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
8247a2771d1SPaolo Bonzini s->intc.irqs[TMU3],
8257a2771d1SPaolo Bonzini s->intc.irqs[TMU4],
8267a2771d1SPaolo Bonzini NULL, NULL);
8277a2771d1SPaolo Bonzini }
8287a2771d1SPaolo Bonzini
8292f493feeSAndreas Färber if (cpu->env.id & (SH_CPU_SH7751_ALL)) {
8307a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8317a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_pci),
8327a2771d1SPaolo Bonzini _INTC_ARRAY(groups_pci));
8337a2771d1SPaolo Bonzini }
8347a2771d1SPaolo Bonzini
8352f493feeSAndreas Färber if (cpu->env.id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
8367a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8377a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_irlm),
8387a2771d1SPaolo Bonzini NULL, 0);
8397a2771d1SPaolo Bonzini }
8407a2771d1SPaolo Bonzini
8417a2771d1SPaolo Bonzini sh_intc_register_sources(&s->intc,
8427a2771d1SPaolo Bonzini _INTC_ARRAY(vectors_irl),
8437a2771d1SPaolo Bonzini _INTC_ARRAY(groups_irl));
8447a2771d1SPaolo Bonzini return s;
8457a2771d1SPaolo Bonzini }
8467a2771d1SPaolo Bonzini
sh7750_irl(SH7750State * s)8477a2771d1SPaolo Bonzini qemu_irq sh7750_irl(SH7750State *s)
8487a2771d1SPaolo Bonzini {
8499b12fb10SBALATON Zoltan sh_intc_toggle_source(&s->intc.sources[IRL], 1, 0); /* enable */
8509b12fb10SBALATON Zoltan return qemu_allocate_irq(sh_intc_set_irl, &s->intc.sources[IRL], 0);
8517a2771d1SPaolo Bonzini }
852