|
|
1.1 root 1: /*
2: * Renesas SH7751R R2D-PLUS emulation
3: *
4: * Copyright (c) 2007 Magnus Damm
1.1.1.2 ! root 5: * Copyright (c) 2008 Paul Mundt
1.1 root 6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the "Software"), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11: * copies of the Software, and to permit persons to whom the Software is
12: * furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included in
15: * all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23: * THE SOFTWARE.
24: */
25:
26: #include "hw.h"
27: #include "sh.h"
1.1.1.2 ! root 28: #include "devices.h"
1.1 root 29: #include "sysemu.h"
30: #include "boards.h"
1.1.1.2 ! root 31: #include "pci.h"
! 32: #include "net.h"
! 33: #include "sh7750_regs.h"
1.1 root 34:
35: #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
36: #define SDRAM_SIZE 0x04000000
37:
1.1.1.2 ! root 38: #define SM501_VRAM_SIZE 0x800000
! 39:
! 40: #define PA_IRLMSK 0x00
! 41: #define PA_POWOFF 0x30
! 42: #define PA_VERREG 0x32
! 43: #define PA_OUTPORT 0x36
! 44:
! 45: typedef struct {
! 46: uint16_t bcr;
! 47: uint16_t irlmsk;
! 48: uint16_t irlmon;
! 49: uint16_t cfctl;
! 50: uint16_t cfpow;
! 51: uint16_t dispctl;
! 52: uint16_t sdmpow;
! 53: uint16_t rtcce;
! 54: uint16_t pcicd;
! 55: uint16_t voyagerrts;
! 56: uint16_t cfrst;
! 57: uint16_t admrts;
! 58: uint16_t extrst;
! 59: uint16_t cfcdintclr;
! 60: uint16_t keyctlclr;
! 61: uint16_t pad0;
! 62: uint16_t pad1;
! 63: uint16_t powoff;
! 64: uint16_t verreg;
! 65: uint16_t inport;
! 66: uint16_t outport;
! 67: uint16_t bverreg;
! 68:
! 69: /* output pin */
! 70: qemu_irq irl;
! 71: } r2d_fpga_t;
! 72:
! 73: enum r2d_fpga_irq {
! 74: PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
! 75: SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
! 76: NR_IRQS
! 77: };
! 78:
! 79: static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
! 80: [CF_IDE] = { 1, 1<<9 },
! 81: [CF_CD] = { 2, 1<<8 },
! 82: [PCI_INTA] = { 9, 1<<14 },
! 83: [PCI_INTB] = { 10, 1<<13 },
! 84: [PCI_INTC] = { 3, 1<<12 },
! 85: [PCI_INTD] = { 0, 1<<11 },
! 86: [SM501] = { 4, 1<<10 },
! 87: [KEY] = { 5, 1<<6 },
! 88: [RTC_A] = { 6, 1<<5 },
! 89: [RTC_T] = { 7, 1<<4 },
! 90: [SDCARD] = { 8, 1<<7 },
! 91: [EXT] = { 11, 1<<0 },
! 92: [TP] = { 12, 1<<15 },
! 93: };
! 94:
! 95: static void update_irl(r2d_fpga_t *fpga)
! 96: {
! 97: int i, irl = 15;
! 98: for (i = 0; i < NR_IRQS; i++)
! 99: if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
! 100: if (irqtab[i].irl < irl)
! 101: irl = irqtab[i].irl;
! 102: qemu_set_irq(fpga->irl, irl ^ 15);
! 103: }
! 104:
! 105: static void r2d_fpga_irq_set(void *opaque, int n, int level)
! 106: {
! 107: r2d_fpga_t *fpga = opaque;
! 108: if (level)
! 109: fpga->irlmon |= irqtab[n].msk;
! 110: else
! 111: fpga->irlmon &= ~irqtab[n].msk;
! 112: update_irl(fpga);
! 113: }
! 114:
! 115: static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr)
! 116: {
! 117: r2d_fpga_t *s = opaque;
! 118:
! 119: switch (addr) {
! 120: case PA_IRLMSK:
! 121: return s->irlmsk;
! 122: case PA_OUTPORT:
! 123: return s->outport;
! 124: case PA_POWOFF:
! 125: return s->powoff;
! 126: case PA_VERREG:
! 127: return 0x10;
! 128: }
! 129:
! 130: return 0;
! 131: }
! 132:
! 133: static void
! 134: r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value)
! 135: {
! 136: r2d_fpga_t *s = opaque;
! 137:
! 138: switch (addr) {
! 139: case PA_IRLMSK:
! 140: s->irlmsk = value;
! 141: update_irl(s);
! 142: break;
! 143: case PA_OUTPORT:
! 144: s->outport = value;
! 145: break;
! 146: case PA_POWOFF:
! 147: s->powoff = value;
! 148: break;
! 149: case PA_VERREG:
! 150: /* Discard writes */
! 151: break;
! 152: }
! 153: }
! 154:
! 155: static CPUReadMemoryFunc *r2d_fpga_readfn[] = {
! 156: r2d_fpga_read,
! 157: r2d_fpga_read,
! 158: NULL,
! 159: };
! 160:
! 161: static CPUWriteMemoryFunc *r2d_fpga_writefn[] = {
! 162: r2d_fpga_write,
! 163: r2d_fpga_write,
! 164: NULL,
! 165: };
! 166:
! 167: static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
! 168: {
! 169: int iomemtype;
! 170: r2d_fpga_t *s;
! 171:
! 172: s = qemu_mallocz(sizeof(r2d_fpga_t));
! 173:
! 174: s->irl = irl;
! 175:
! 176: iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn,
! 177: r2d_fpga_writefn, s);
! 178: cpu_register_physical_memory(base, 0x40, iomemtype);
! 179: return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
! 180: }
! 181:
! 182: static void r2d_pci_set_irq(qemu_irq *p, int n, int l)
! 183: {
! 184: qemu_set_irq(p[n], l);
! 185: }
! 186:
! 187: static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
! 188: {
! 189: const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
! 190: return intx[d->devfn >> 3];
! 191: }
! 192:
! 193: static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
! 194: const char *boot_device,
1.1 root 195: const char *kernel_filename, const char *kernel_cmdline,
196: const char *initrd_filename, const char *cpu_model)
197: {
198: CPUState *env;
199: struct SH7750State *s;
1.1.1.2 ! root 200: ram_addr_t sdram_addr, sm501_vga_ram_addr;
! 201: qemu_irq *irq;
! 202: PCIBus *pci;
! 203: int i;
1.1 root 204:
205: if (!cpu_model)
1.1.1.2 ! root 206: cpu_model = "SH7751R";
1.1 root 207:
208: env = cpu_init(cpu_model);
209: if (!env) {
210: fprintf(stderr, "Unable to find CPU definition\n");
211: exit(1);
212: }
213:
214: /* Allocate memory space */
1.1.1.2 ! root 215: sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
! 216: cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
1.1 root 217: /* Register peripherals */
218: s = sh7750_init(env);
1.1.1.2 ! root 219: irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
! 220: pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
! 221:
! 222: sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
! 223: sm501_init(0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
! 224: serial_hds[2]);
! 225:
! 226: /* onboard CF (True IDE mode, Master only). */
! 227: if ((i = drive_get_index(IF_IDE, 0, 0)) != -1)
! 228: mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
! 229: drives_table[i].bdrv, NULL);
! 230:
! 231: /* NIC: rtl8139 on-board, and 2 slots. */
! 232: for (i = 0; i < nb_nics; i++)
! 233: pci_nic_init(pci, &nd_table[i], (i==0)? 2<<3: -1, "rtl8139");
! 234:
1.1 root 235: /* Todo: register on board registers */
236: {
237: int kernel_size;
1.1.1.2 ! root 238: /* initialization which should be done by firmware */
! 239: stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
! 240: stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
1.1 root 241:
242: kernel_size = load_image(kernel_filename, phys_ram_base);
243:
244: if (kernel_size < 0) {
245: fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
246: exit(1);
247: }
248:
249: env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
250: }
251: }
252:
253: QEMUMachine r2d_machine = {
1.1.1.2 ! root 254: .name = "r2d",
! 255: .desc = "r2d-plus board",
! 256: .init = r2d_init,
! 257: .ram_require = (SDRAM_SIZE + SM501_VRAM_SIZE) | RAMSIZE_FIXED,
1.1 root 258: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.