highbank.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Calxeda Highbank SoC emulation
  3. *
  4. * Copyright (c) 2010-2012 Calxeda
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2 or later, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "sysbus.h"
  20. #include "arm-misc.h"
  21. #include "devices.h"
  22. #include "loader.h"
  23. #include "net.h"
  24. #include "sysemu.h"
  25. #include "boards.h"
  26. #include "sysbus.h"
  27. #include "blockdev.h"
  28. #include "exec-memory.h"
  29. #define SMP_BOOT_ADDR 0x100
  30. #define SMP_BOOT_REG 0x40
  31. #define GIC_BASE_ADDR 0xfff10000
  32. #define NIRQ_GIC 160
  33. /* Board init. */
  34. static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
  35. {
  36. int n;
  37. uint32_t smpboot[] = {
  38. 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
  39. 0xe210000f, /* ands r0, r0, #0x0f */
  40. 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
  41. 0xe0830200, /* add r0, r3, r0, lsl #4 */
  42. 0xe59f2018, /* ldr r2, privbase */
  43. 0xe3a01001, /* mov r1, #1 */
  44. 0xe5821100, /* str r1, [r2, #256] */
  45. 0xe320f003, /* wfi */
  46. 0xe5901000, /* ldr r1, [r0] */
  47. 0xe1110001, /* tst r1, r1 */
  48. 0x0afffffb, /* beq <wfi> */
  49. 0xe12fff11, /* bx r1 */
  50. GIC_BASE_ADDR /* privbase: gic address. */
  51. };
  52. for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
  53. smpboot[n] = tswap32(smpboot[n]);
  54. }
  55. rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
  56. }
  57. static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
  58. {
  59. CPUARMState *env = &cpu->env;
  60. switch (info->nb_cpus) {
  61. case 4:
  62. stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
  63. case 3:
  64. stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
  65. case 2:
  66. stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
  67. env->regs[15] = SMP_BOOT_ADDR;
  68. break;
  69. default:
  70. break;
  71. }
  72. }
  73. #define NUM_REGS 0x200
  74. static void hb_regs_write(void *opaque, target_phys_addr_t offset,
  75. uint64_t value, unsigned size)
  76. {
  77. uint32_t *regs = opaque;
  78. if (offset == 0xf00) {
  79. if (value == 1 || value == 2) {
  80. qemu_system_reset_request();
  81. } else if (value == 3) {
  82. qemu_system_shutdown_request();
  83. }
  84. }
  85. regs[offset/4] = value;
  86. }
  87. static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
  88. unsigned size)
  89. {
  90. uint32_t *regs = opaque;
  91. uint32_t value = regs[offset/4];
  92. if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
  93. value |= 0x30000000;
  94. }
  95. return value;
  96. }
  97. static const MemoryRegionOps hb_mem_ops = {
  98. .read = hb_regs_read,
  99. .write = hb_regs_write,
  100. .endianness = DEVICE_NATIVE_ENDIAN,
  101. };
  102. typedef struct {
  103. SysBusDevice busdev;
  104. MemoryRegion *iomem;
  105. uint32_t regs[NUM_REGS];
  106. } HighbankRegsState;
  107. static VMStateDescription vmstate_highbank_regs = {
  108. .name = "highbank-regs",
  109. .version_id = 0,
  110. .minimum_version_id = 0,
  111. .minimum_version_id_old = 0,
  112. .fields = (VMStateField[]) {
  113. VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
  114. VMSTATE_END_OF_LIST(),
  115. },
  116. };
  117. static void highbank_regs_reset(DeviceState *dev)
  118. {
  119. SysBusDevice *sys_dev = sysbus_from_qdev(dev);
  120. HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
  121. s->regs[0x40] = 0x05F20121;
  122. s->regs[0x41] = 0x2;
  123. s->regs[0x42] = 0x05F30121;
  124. s->regs[0x43] = 0x05F40121;
  125. }
  126. static int highbank_regs_init(SysBusDevice *dev)
  127. {
  128. HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
  129. s->iomem = g_new(MemoryRegion, 1);
  130. memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
  131. 0x1000);
  132. sysbus_init_mmio(dev, s->iomem);
  133. return 0;
  134. }
  135. static void highbank_regs_class_init(ObjectClass *klass, void *data)
  136. {
  137. SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
  138. DeviceClass *dc = DEVICE_CLASS(klass);
  139. sbc->init = highbank_regs_init;
  140. dc->desc = "Calxeda Highbank registers";
  141. dc->vmsd = &vmstate_highbank_regs;
  142. dc->reset = highbank_regs_reset;
  143. }
  144. static TypeInfo highbank_regs_info = {
  145. .name = "highbank-regs",
  146. .parent = TYPE_SYS_BUS_DEVICE,
  147. .instance_size = sizeof(HighbankRegsState),
  148. .class_init = highbank_regs_class_init,
  149. };
  150. static void highbank_regs_register_types(void)
  151. {
  152. type_register_static(&highbank_regs_info);
  153. }
  154. type_init(highbank_regs_register_types)
  155. static struct arm_boot_info highbank_binfo;
  156. /* ram_size must be set to match the upper bound of memory in the
  157. * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
  158. * normally 0xff900000 or -m 4089. When running this board on a
  159. * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
  160. * device tree and pass -m 2047 to QEMU.
  161. */
  162. static void highbank_init(ram_addr_t ram_size,
  163. const char *boot_device,
  164. const char *kernel_filename, const char *kernel_cmdline,
  165. const char *initrd_filename, const char *cpu_model)
  166. {
  167. DeviceState *dev;
  168. SysBusDevice *busdev;
  169. qemu_irq *irqp;
  170. qemu_irq pic[128];
  171. int n;
  172. qemu_irq cpu_irq[4];
  173. MemoryRegion *sysram;
  174. MemoryRegion *dram;
  175. MemoryRegion *sysmem;
  176. char *sysboot_filename;
  177. if (!cpu_model) {
  178. cpu_model = "cortex-a9";
  179. }
  180. for (n = 0; n < smp_cpus; n++) {
  181. ARMCPU *cpu;
  182. cpu = cpu_arm_init(cpu_model);
  183. if (cpu == NULL) {
  184. fprintf(stderr, "Unable to find CPU definition\n");
  185. exit(1);
  186. }
  187. /* This will become a QOM property eventually */
  188. cpu->reset_cbar = GIC_BASE_ADDR;
  189. irqp = arm_pic_init_cpu(cpu);
  190. cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
  191. }
  192. sysmem = get_system_memory();
  193. dram = g_new(MemoryRegion, 1);
  194. memory_region_init_ram(dram, "highbank.dram", ram_size);
  195. /* SDRAM at address zero. */
  196. memory_region_add_subregion(sysmem, 0, dram);
  197. sysram = g_new(MemoryRegion, 1);
  198. memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
  199. memory_region_add_subregion(sysmem, 0xfff88000, sysram);
  200. if (bios_name != NULL) {
  201. sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
  202. if (sysboot_filename != NULL) {
  203. uint32_t filesize = get_image_size(sysboot_filename);
  204. if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
  205. hw_error("Unable to load %s\n", bios_name);
  206. }
  207. } else {
  208. hw_error("Unable to find %s\n", bios_name);
  209. }
  210. }
  211. dev = qdev_create(NULL, "a9mpcore_priv");
  212. qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
  213. qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
  214. qdev_init_nofail(dev);
  215. busdev = sysbus_from_qdev(dev);
  216. sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
  217. for (n = 0; n < smp_cpus; n++) {
  218. sysbus_connect_irq(busdev, n, cpu_irq[n]);
  219. }
  220. for (n = 0; n < 128; n++) {
  221. pic[n] = qdev_get_gpio_in(dev, n);
  222. }
  223. dev = qdev_create(NULL, "l2x0");
  224. qdev_init_nofail(dev);
  225. busdev = sysbus_from_qdev(dev);
  226. sysbus_mmio_map(busdev, 0, 0xfff12000);
  227. dev = qdev_create(NULL, "sp804");
  228. qdev_prop_set_uint32(dev, "freq0", 150000000);
  229. qdev_prop_set_uint32(dev, "freq1", 150000000);
  230. qdev_init_nofail(dev);
  231. busdev = sysbus_from_qdev(dev);
  232. sysbus_mmio_map(busdev, 0, 0xfff34000);
  233. sysbus_connect_irq(busdev, 0, pic[18]);
  234. sysbus_create_simple("pl011", 0xfff36000, pic[20]);
  235. dev = qdev_create(NULL, "highbank-regs");
  236. qdev_init_nofail(dev);
  237. busdev = sysbus_from_qdev(dev);
  238. sysbus_mmio_map(busdev, 0, 0xfff3c000);
  239. sysbus_create_simple("pl061", 0xfff30000, pic[14]);
  240. sysbus_create_simple("pl061", 0xfff31000, pic[15]);
  241. sysbus_create_simple("pl061", 0xfff32000, pic[16]);
  242. sysbus_create_simple("pl061", 0xfff33000, pic[17]);
  243. sysbus_create_simple("pl031", 0xfff35000, pic[19]);
  244. sysbus_create_simple("pl022", 0xfff39000, pic[23]);
  245. sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
  246. if (nd_table[0].used) {
  247. qemu_check_nic_model(&nd_table[0], "xgmac");
  248. dev = qdev_create(NULL, "xgmac");
  249. qdev_set_nic_properties(dev, &nd_table[0]);
  250. qdev_init_nofail(dev);
  251. sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
  252. sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
  253. sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
  254. sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
  255. qemu_check_nic_model(&nd_table[1], "xgmac");
  256. dev = qdev_create(NULL, "xgmac");
  257. qdev_set_nic_properties(dev, &nd_table[1]);
  258. qdev_init_nofail(dev);
  259. sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
  260. sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
  261. sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
  262. sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
  263. }
  264. highbank_binfo.ram_size = ram_size;
  265. highbank_binfo.kernel_filename = kernel_filename;
  266. highbank_binfo.kernel_cmdline = kernel_cmdline;
  267. highbank_binfo.initrd_filename = initrd_filename;
  268. /* highbank requires a dtb in order to boot, and the dtb will override
  269. * the board ID. The following value is ignored, so set it to -1 to be
  270. * clear that the value is meaningless.
  271. */
  272. highbank_binfo.board_id = -1;
  273. highbank_binfo.nb_cpus = smp_cpus;
  274. highbank_binfo.loader_start = 0;
  275. highbank_binfo.write_secondary_boot = hb_write_secondary;
  276. highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
  277. arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
  278. }
  279. static QEMUMachine highbank_machine = {
  280. .name = "highbank",
  281. .desc = "Calxeda Highbank (ECX-1000)",
  282. .init = highbank_init,
  283. .use_scsi = 1,
  284. .max_cpus = 4,
  285. };
  286. static void highbank_machine_init(void)
  287. {
  288. qemu_register_machine(&highbank_machine);
  289. }
  290. machine_init(highbank_machine_init);