2
0

r2d.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * Renesas SH7751R R2D-PLUS emulation
  3. *
  4. * Copyright (c) 2007 Magnus Damm
  5. * Copyright (c) 2008 Paul Mundt
  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 "hw.h"
  26. #include "sh.h"
  27. #include "devices.h"
  28. #include "sysemu.h"
  29. #include "boards.h"
  30. #include "pci.h"
  31. #include "net.h"
  32. #include "sh7750_regs.h"
  33. #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
  34. #define SDRAM_SIZE 0x04000000
  35. #define SM501_VRAM_SIZE 0x800000
  36. /* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
  37. #define LINUX_LOAD_OFFSET 0x800000
  38. #define PA_IRLMSK 0x00
  39. #define PA_POWOFF 0x30
  40. #define PA_VERREG 0x32
  41. #define PA_OUTPORT 0x36
  42. typedef struct {
  43. uint16_t bcr;
  44. uint16_t irlmsk;
  45. uint16_t irlmon;
  46. uint16_t cfctl;
  47. uint16_t cfpow;
  48. uint16_t dispctl;
  49. uint16_t sdmpow;
  50. uint16_t rtcce;
  51. uint16_t pcicd;
  52. uint16_t voyagerrts;
  53. uint16_t cfrst;
  54. uint16_t admrts;
  55. uint16_t extrst;
  56. uint16_t cfcdintclr;
  57. uint16_t keyctlclr;
  58. uint16_t pad0;
  59. uint16_t pad1;
  60. uint16_t powoff;
  61. uint16_t verreg;
  62. uint16_t inport;
  63. uint16_t outport;
  64. uint16_t bverreg;
  65. /* output pin */
  66. qemu_irq irl;
  67. } r2d_fpga_t;
  68. enum r2d_fpga_irq {
  69. PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
  70. SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
  71. NR_IRQS
  72. };
  73. static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
  74. [CF_IDE] = { 1, 1<<9 },
  75. [CF_CD] = { 2, 1<<8 },
  76. [PCI_INTA] = { 9, 1<<14 },
  77. [PCI_INTB] = { 10, 1<<13 },
  78. [PCI_INTC] = { 3, 1<<12 },
  79. [PCI_INTD] = { 0, 1<<11 },
  80. [SM501] = { 4, 1<<10 },
  81. [KEY] = { 5, 1<<6 },
  82. [RTC_A] = { 6, 1<<5 },
  83. [RTC_T] = { 7, 1<<4 },
  84. [SDCARD] = { 8, 1<<7 },
  85. [EXT] = { 11, 1<<0 },
  86. [TP] = { 12, 1<<15 },
  87. };
  88. static void update_irl(r2d_fpga_t *fpga)
  89. {
  90. int i, irl = 15;
  91. for (i = 0; i < NR_IRQS; i++)
  92. if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
  93. if (irqtab[i].irl < irl)
  94. irl = irqtab[i].irl;
  95. qemu_set_irq(fpga->irl, irl ^ 15);
  96. }
  97. static void r2d_fpga_irq_set(void *opaque, int n, int level)
  98. {
  99. r2d_fpga_t *fpga = opaque;
  100. if (level)
  101. fpga->irlmon |= irqtab[n].msk;
  102. else
  103. fpga->irlmon &= ~irqtab[n].msk;
  104. update_irl(fpga);
  105. }
  106. static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr)
  107. {
  108. r2d_fpga_t *s = opaque;
  109. switch (addr) {
  110. case PA_IRLMSK:
  111. return s->irlmsk;
  112. case PA_OUTPORT:
  113. return s->outport;
  114. case PA_POWOFF:
  115. return s->powoff;
  116. case PA_VERREG:
  117. return 0x10;
  118. }
  119. return 0;
  120. }
  121. static void
  122. r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value)
  123. {
  124. r2d_fpga_t *s = opaque;
  125. switch (addr) {
  126. case PA_IRLMSK:
  127. s->irlmsk = value;
  128. update_irl(s);
  129. break;
  130. case PA_OUTPORT:
  131. s->outport = value;
  132. break;
  133. case PA_POWOFF:
  134. s->powoff = value;
  135. break;
  136. case PA_VERREG:
  137. /* Discard writes */
  138. break;
  139. }
  140. }
  141. static CPUReadMemoryFunc *r2d_fpga_readfn[] = {
  142. r2d_fpga_read,
  143. r2d_fpga_read,
  144. NULL,
  145. };
  146. static CPUWriteMemoryFunc *r2d_fpga_writefn[] = {
  147. r2d_fpga_write,
  148. r2d_fpga_write,
  149. NULL,
  150. };
  151. static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
  152. {
  153. int iomemtype;
  154. r2d_fpga_t *s;
  155. s = qemu_mallocz(sizeof(r2d_fpga_t));
  156. s->irl = irl;
  157. iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn,
  158. r2d_fpga_writefn, s);
  159. cpu_register_physical_memory(base, 0x40, iomemtype);
  160. return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
  161. }
  162. static void r2d_pci_set_irq(qemu_irq *p, int n, int l)
  163. {
  164. qemu_set_irq(p[n], l);
  165. }
  166. static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
  167. {
  168. const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
  169. return intx[d->devfn >> 3];
  170. }
  171. static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
  172. const char *boot_device,
  173. const char *kernel_filename, const char *kernel_cmdline,
  174. const char *initrd_filename, const char *cpu_model)
  175. {
  176. CPUState *env;
  177. struct SH7750State *s;
  178. ram_addr_t sdram_addr, sm501_vga_ram_addr;
  179. qemu_irq *irq;
  180. PCIBus *pci;
  181. int i;
  182. if (!cpu_model)
  183. cpu_model = "SH7751R";
  184. env = cpu_init(cpu_model);
  185. if (!env) {
  186. fprintf(stderr, "Unable to find CPU definition\n");
  187. exit(1);
  188. }
  189. /* Allocate memory space */
  190. sdram_addr = qemu_ram_alloc(SDRAM_SIZE);
  191. cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
  192. /* Register peripherals */
  193. s = sh7750_init(env);
  194. irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
  195. pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
  196. sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE);
  197. sm501_init(0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE,
  198. serial_hds[2]);
  199. /* onboard CF (True IDE mode, Master only). */
  200. if ((i = drive_get_index(IF_IDE, 0, 0)) != -1)
  201. mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
  202. drives_table[i].bdrv, NULL);
  203. /* NIC: rtl8139 on-board, and 2 slots. */
  204. for (i = 0; i < nb_nics; i++)
  205. pci_nic_init(pci, &nd_table[i], (i==0)? 2<<3: -1, "rtl8139");
  206. /* Todo: register on board registers */
  207. if (kernel_filename) {
  208. int kernel_size;
  209. /* initialization which should be done by firmware */
  210. stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
  211. stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
  212. if (kernel_cmdline) {
  213. kernel_size = load_image_targphys(kernel_filename,
  214. SDRAM_BASE + LINUX_LOAD_OFFSET,
  215. SDRAM_SIZE - LINUX_LOAD_OFFSET);
  216. env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000;
  217. pstrcpy_targphys(SDRAM_BASE + 0x10100, 256, kernel_cmdline);
  218. } else {
  219. kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE, SDRAM_SIZE);
  220. env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */
  221. }
  222. if (kernel_size < 0) {
  223. fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
  224. exit(1);
  225. }
  226. }
  227. }
  228. QEMUMachine r2d_machine = {
  229. .name = "r2d",
  230. .desc = "r2d-plus board",
  231. .init = r2d_init,
  232. .ram_require = (SDRAM_SIZE + SM501_VRAM_SIZE) | RAMSIZE_FIXED,
  233. };