|
|
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:
1.1.1.7 ! root 26: #include "sysbus.h"
1.1 root 27: #include "hw.h"
28: #include "sh.h"
1.1.1.2 root 29: #include "devices.h"
1.1 root 30: #include "sysemu.h"
31: #include "boards.h"
1.1.1.2 root 32: #include "pci.h"
33: #include "net.h"
34: #include "sh7750_regs.h"
1.1.1.5 root 35: #include "ide.h"
36: #include "loader.h"
1.1.1.6 root 37: #include "usb.h"
38: #include "flash.h"
1.1.1.7 ! root 39: #include "blockdev.h"
1.1.1.6 root 40:
41: #define FLASH_BASE 0x00000000
42: #define FLASH_SIZE 0x02000000
1.1 root 43:
44: #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
45: #define SDRAM_SIZE 0x04000000
46:
1.1.1.2 root 47: #define SM501_VRAM_SIZE 0x800000
48:
1.1.1.6 root 49: #define BOOT_PARAMS_OFFSET 0x0010000
1.1.1.3 root 50: /* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
1.1.1.6 root 51: #define LINUX_LOAD_OFFSET 0x0800000
52: #define INITRD_LOAD_OFFSET 0x1800000
1.1.1.3 root 53:
1.1.1.2 root 54: #define PA_IRLMSK 0x00
55: #define PA_POWOFF 0x30
56: #define PA_VERREG 0x32
57: #define PA_OUTPORT 0x36
58:
59: typedef struct {
60: uint16_t bcr;
61: uint16_t irlmsk;
62: uint16_t irlmon;
63: uint16_t cfctl;
64: uint16_t cfpow;
65: uint16_t dispctl;
66: uint16_t sdmpow;
67: uint16_t rtcce;
68: uint16_t pcicd;
69: uint16_t voyagerrts;
70: uint16_t cfrst;
71: uint16_t admrts;
72: uint16_t extrst;
73: uint16_t cfcdintclr;
74: uint16_t keyctlclr;
75: uint16_t pad0;
76: uint16_t pad1;
77: uint16_t verreg;
78: uint16_t inport;
79: uint16_t outport;
80: uint16_t bverreg;
81:
82: /* output pin */
83: qemu_irq irl;
84: } r2d_fpga_t;
85:
86: enum r2d_fpga_irq {
87: PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
88: SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
89: NR_IRQS
90: };
91:
92: static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
93: [CF_IDE] = { 1, 1<<9 },
94: [CF_CD] = { 2, 1<<8 },
95: [PCI_INTA] = { 9, 1<<14 },
96: [PCI_INTB] = { 10, 1<<13 },
97: [PCI_INTC] = { 3, 1<<12 },
98: [PCI_INTD] = { 0, 1<<11 },
99: [SM501] = { 4, 1<<10 },
100: [KEY] = { 5, 1<<6 },
101: [RTC_A] = { 6, 1<<5 },
102: [RTC_T] = { 7, 1<<4 },
103: [SDCARD] = { 8, 1<<7 },
104: [EXT] = { 11, 1<<0 },
105: [TP] = { 12, 1<<15 },
106: };
107:
108: static void update_irl(r2d_fpga_t *fpga)
109: {
110: int i, irl = 15;
111: for (i = 0; i < NR_IRQS; i++)
112: if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
113: if (irqtab[i].irl < irl)
114: irl = irqtab[i].irl;
115: qemu_set_irq(fpga->irl, irl ^ 15);
116: }
117:
118: static void r2d_fpga_irq_set(void *opaque, int n, int level)
119: {
120: r2d_fpga_t *fpga = opaque;
121: if (level)
122: fpga->irlmon |= irqtab[n].msk;
123: else
124: fpga->irlmon &= ~irqtab[n].msk;
125: update_irl(fpga);
126: }
127:
128: static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr)
129: {
130: r2d_fpga_t *s = opaque;
131:
132: switch (addr) {
133: case PA_IRLMSK:
134: return s->irlmsk;
135: case PA_OUTPORT:
136: return s->outport;
137: case PA_POWOFF:
1.1.1.6 root 138: return 0x00;
1.1.1.2 root 139: case PA_VERREG:
140: return 0x10;
141: }
142:
143: return 0;
144: }
145:
146: static void
147: r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value)
148: {
149: r2d_fpga_t *s = opaque;
150:
151: switch (addr) {
152: case PA_IRLMSK:
153: s->irlmsk = value;
154: update_irl(s);
155: break;
156: case PA_OUTPORT:
157: s->outport = value;
158: break;
159: case PA_POWOFF:
1.1.1.6 root 160: if (value & 1) {
161: qemu_system_shutdown_request();
162: }
163: break;
1.1.1.2 root 164: case PA_VERREG:
165: /* Discard writes */
166: break;
167: }
168: }
169:
1.1.1.5 root 170: static CPUReadMemoryFunc * const r2d_fpga_readfn[] = {
1.1.1.2 root 171: r2d_fpga_read,
172: r2d_fpga_read,
173: NULL,
174: };
175:
1.1.1.5 root 176: static CPUWriteMemoryFunc * const r2d_fpga_writefn[] = {
1.1.1.2 root 177: r2d_fpga_write,
178: r2d_fpga_write,
179: NULL,
180: };
181:
182: static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
183: {
184: int iomemtype;
185: r2d_fpga_t *s;
186:
187: s = qemu_mallocz(sizeof(r2d_fpga_t));
188:
189: s->irl = irl;
190:
1.1.1.4 root 191: iomemtype = cpu_register_io_memory(r2d_fpga_readfn,
1.1.1.7 ! root 192: r2d_fpga_writefn, s,
! 193: DEVICE_NATIVE_ENDIAN);
1.1.1.2 root 194: cpu_register_physical_memory(base, 0x40, iomemtype);
195: return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
196: }
197:
1.1.1.7 ! root 198: typedef struct ResetData {
! 199: CPUState *env;
! 200: uint32_t vector;
! 201: } ResetData;
1.1.1.2 root 202:
1.1.1.7 ! root 203: static void main_cpu_reset(void *opaque)
1.1.1.2 root 204: {
1.1.1.7 ! root 205: ResetData *s = (ResetData *)opaque;
! 206: CPUState *env = s->env;
! 207:
! 208: cpu_reset(env);
! 209: env->pc = s->vector;
1.1.1.2 root 210: }
211:
1.1.1.6 root 212: static struct __attribute__((__packed__))
213: {
214: int mount_root_rdonly;
215: int ramdisk_flags;
216: int orig_root_dev;
217: int loader_type;
218: int initrd_start;
219: int initrd_size;
220:
221: char pad[232];
222:
223: char kernel_cmdline[256];
224: } boot_params;
225:
1.1.1.4 root 226: static void r2d_init(ram_addr_t ram_size,
1.1.1.2 root 227: const char *boot_device,
1.1 root 228: const char *kernel_filename, const char *kernel_cmdline,
229: const char *initrd_filename, const char *cpu_model)
230: {
231: CPUState *env;
1.1.1.7 ! root 232: ResetData *reset_info;
1.1 root 233: struct SH7750State *s;
1.1.1.4 root 234: ram_addr_t sdram_addr;
1.1.1.2 root 235: qemu_irq *irq;
1.1.1.5 root 236: DriveInfo *dinfo;
1.1.1.2 root 237: int i;
1.1 root 238:
239: if (!cpu_model)
1.1.1.2 root 240: cpu_model = "SH7751R";
1.1 root 241:
242: env = cpu_init(cpu_model);
243: if (!env) {
244: fprintf(stderr, "Unable to find CPU definition\n");
245: exit(1);
246: }
1.1.1.7 ! root 247: reset_info = qemu_mallocz(sizeof(ResetData));
! 248: reset_info->env = env;
! 249: reset_info->vector = env->pc;
! 250: qemu_register_reset(main_cpu_reset, reset_info);
1.1 root 251:
252: /* Allocate memory space */
1.1.1.6 root 253: sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
1.1.1.2 root 254: cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
1.1 root 255: /* Register peripherals */
256: s = sh7750_init(env);
1.1.1.2 root 257: irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
1.1.1.7 ! root 258: sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
! 259: irq[PCI_INTC], irq[PCI_INTD], NULL);
1.1.1.2 root 260:
1.1.1.4 root 261: sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
1.1.1.2 root 262:
263: /* onboard CF (True IDE mode, Master only). */
1.1.1.6 root 264: dinfo = drive_get(IF_IDE, 0, 0);
265: mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
266: dinfo, NULL);
267:
268: /* onboard flash memory */
269: dinfo = drive_get(IF_PFLASH, 0, 0);
270: pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE),
271: dinfo ? dinfo->bdrv : NULL, (16 * 1024),
272: FLASH_SIZE >> 16,
273: 1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
274: 0x555, 0x2aa, 0);
1.1.1.2 root 275:
276: /* NIC: rtl8139 on-board, and 2 slots. */
277: for (i = 0; i < nb_nics; i++)
1.1.1.5 root 278: pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
1.1.1.2 root 279:
1.1.1.6 root 280: /* USB keyboard */
281: usbdevice_create("keyboard");
282:
1.1 root 283: /* Todo: register on board registers */
1.1.1.6 root 284: memset(&boot_params, 0, sizeof(boot_params));
285:
1.1.1.3 root 286: if (kernel_filename) {
1.1.1.6 root 287: int kernel_size;
1.1 root 288:
1.1.1.6 root 289: kernel_size = load_image_targphys(kernel_filename,
290: SDRAM_BASE + LINUX_LOAD_OFFSET,
291: INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
292: if (kernel_size < 0) {
293: fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
294: exit(1);
295: }
296:
297: /* initialization which should be done by firmware */
298: stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
299: stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
1.1.1.7 ! root 300: reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
1.1.1.6 root 301: }
302:
303: if (initrd_filename) {
304: int initrd_size;
305:
306: initrd_size = load_image_targphys(initrd_filename,
307: SDRAM_BASE + INITRD_LOAD_OFFSET,
308: SDRAM_SIZE - INITRD_LOAD_OFFSET);
309:
310: if (initrd_size < 0) {
311: fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
312: exit(1);
313: }
314:
315: /* initialization which should be done by firmware */
316: boot_params.loader_type = 1;
317: boot_params.initrd_start = INITRD_LOAD_OFFSET;
318: boot_params.initrd_size = initrd_size;
1.1 root 319: }
1.1.1.6 root 320:
321: if (kernel_cmdline) {
322: strncpy(boot_params.kernel_cmdline, kernel_cmdline,
323: sizeof(boot_params.kernel_cmdline));
324: }
325:
326: rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
327: SDRAM_BASE + BOOT_PARAMS_OFFSET);
1.1 root 328: }
329:
1.1.1.4 root 330: static QEMUMachine r2d_machine = {
1.1.1.2 root 331: .name = "r2d",
332: .desc = "r2d-plus board",
333: .init = r2d_init,
1.1 root 334: };
1.1.1.4 root 335:
336: static void r2d_machine_init(void)
337: {
338: qemu_register_machine(&r2d_machine);
339: }
340:
341: machine_init(r2d_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.