arm_sysctl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * Status and system control registers for ARM RealView/Versatile boards.
  3. *
  4. * Copyright (c) 2006-2007 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licensed under the GPL.
  8. */
  9. #include "hw.h"
  10. #include "qemu-timer.h"
  11. #include "sysbus.h"
  12. #include "primecell.h"
  13. #include "sysemu.h"
  14. #define LOCK_VALUE 0xa05f
  15. typedef struct {
  16. SysBusDevice busdev;
  17. MemoryRegion iomem;
  18. qemu_irq pl110_mux_ctrl;
  19. uint32_t sys_id;
  20. uint32_t leds;
  21. uint16_t lockval;
  22. uint32_t cfgdata1;
  23. uint32_t cfgdata2;
  24. uint32_t flags;
  25. uint32_t nvflags;
  26. uint32_t resetlevel;
  27. uint32_t proc_id;
  28. uint32_t sys_mci;
  29. uint32_t sys_cfgdata;
  30. uint32_t sys_cfgctrl;
  31. uint32_t sys_cfgstat;
  32. uint32_t sys_clcd;
  33. } arm_sysctl_state;
  34. static const VMStateDescription vmstate_arm_sysctl = {
  35. .name = "realview_sysctl",
  36. .version_id = 3,
  37. .minimum_version_id = 1,
  38. .fields = (VMStateField[]) {
  39. VMSTATE_UINT32(leds, arm_sysctl_state),
  40. VMSTATE_UINT16(lockval, arm_sysctl_state),
  41. VMSTATE_UINT32(cfgdata1, arm_sysctl_state),
  42. VMSTATE_UINT32(cfgdata2, arm_sysctl_state),
  43. VMSTATE_UINT32(flags, arm_sysctl_state),
  44. VMSTATE_UINT32(nvflags, arm_sysctl_state),
  45. VMSTATE_UINT32(resetlevel, arm_sysctl_state),
  46. VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2),
  47. VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
  48. VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
  49. VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
  50. VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
  51. VMSTATE_END_OF_LIST()
  52. }
  53. };
  54. /* The PB926 actually uses a different format for
  55. * its SYS_ID register. Fortunately the bits which are
  56. * board type on later boards are distinct.
  57. */
  58. #define BOARD_ID_PB926 0x100
  59. #define BOARD_ID_EB 0x140
  60. #define BOARD_ID_PBA8 0x178
  61. #define BOARD_ID_PBX 0x182
  62. #define BOARD_ID_VEXPRESS 0x190
  63. static int board_id(arm_sysctl_state *s)
  64. {
  65. /* Extract the board ID field from the SYS_ID register value */
  66. return (s->sys_id >> 16) & 0xfff;
  67. }
  68. static void arm_sysctl_reset(DeviceState *d)
  69. {
  70. arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sysbus_from_qdev(d));
  71. s->leds = 0;
  72. s->lockval = 0;
  73. s->cfgdata1 = 0;
  74. s->cfgdata2 = 0;
  75. s->flags = 0;
  76. s->resetlevel = 0;
  77. if (board_id(s) == BOARD_ID_VEXPRESS) {
  78. /* On VExpress this register will RAZ/WI */
  79. s->sys_clcd = 0;
  80. } else {
  81. /* All others: CLCDID 0x1f, indicating VGA */
  82. s->sys_clcd = 0x1f00;
  83. }
  84. }
  85. static uint64_t arm_sysctl_read(void *opaque, target_phys_addr_t offset,
  86. unsigned size)
  87. {
  88. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  89. switch (offset) {
  90. case 0x00: /* ID */
  91. return s->sys_id;
  92. case 0x04: /* SW */
  93. /* General purpose hardware switches.
  94. We don't have a useful way of exposing these to the user. */
  95. return 0;
  96. case 0x08: /* LED */
  97. return s->leds;
  98. case 0x20: /* LOCK */
  99. return s->lockval;
  100. case 0x0c: /* OSC0 */
  101. case 0x10: /* OSC1 */
  102. case 0x14: /* OSC2 */
  103. case 0x18: /* OSC3 */
  104. case 0x1c: /* OSC4 */
  105. case 0x24: /* 100HZ */
  106. /* ??? Implement these. */
  107. return 0;
  108. case 0x28: /* CFGDATA1 */
  109. return s->cfgdata1;
  110. case 0x2c: /* CFGDATA2 */
  111. return s->cfgdata2;
  112. case 0x30: /* FLAGS */
  113. return s->flags;
  114. case 0x38: /* NVFLAGS */
  115. return s->nvflags;
  116. case 0x40: /* RESETCTL */
  117. if (board_id(s) == BOARD_ID_VEXPRESS) {
  118. /* reserved: RAZ/WI */
  119. return 0;
  120. }
  121. return s->resetlevel;
  122. case 0x44: /* PCICTL */
  123. return 1;
  124. case 0x48: /* MCI */
  125. return s->sys_mci;
  126. case 0x4c: /* FLASH */
  127. return 0;
  128. case 0x50: /* CLCD */
  129. return s->sys_clcd;
  130. case 0x54: /* CLCDSER */
  131. return 0;
  132. case 0x58: /* BOOTCS */
  133. return 0;
  134. case 0x5c: /* 24MHz */
  135. return muldiv64(qemu_get_clock_ns(vm_clock), 24000000, get_ticks_per_sec());
  136. case 0x60: /* MISC */
  137. return 0;
  138. case 0x84: /* PROCID0 */
  139. return s->proc_id;
  140. case 0x88: /* PROCID1 */
  141. return 0xff000000;
  142. case 0x64: /* DMAPSR0 */
  143. case 0x68: /* DMAPSR1 */
  144. case 0x6c: /* DMAPSR2 */
  145. case 0x70: /* IOSEL */
  146. case 0x74: /* PLDCTL */
  147. case 0x80: /* BUSID */
  148. case 0x8c: /* OSCRESET0 */
  149. case 0x90: /* OSCRESET1 */
  150. case 0x94: /* OSCRESET2 */
  151. case 0x98: /* OSCRESET3 */
  152. case 0x9c: /* OSCRESET4 */
  153. case 0xc0: /* SYS_TEST_OSC0 */
  154. case 0xc4: /* SYS_TEST_OSC1 */
  155. case 0xc8: /* SYS_TEST_OSC2 */
  156. case 0xcc: /* SYS_TEST_OSC3 */
  157. case 0xd0: /* SYS_TEST_OSC4 */
  158. return 0;
  159. case 0xa0: /* SYS_CFGDATA */
  160. if (board_id(s) != BOARD_ID_VEXPRESS) {
  161. goto bad_reg;
  162. }
  163. return s->sys_cfgdata;
  164. case 0xa4: /* SYS_CFGCTRL */
  165. if (board_id(s) != BOARD_ID_VEXPRESS) {
  166. goto bad_reg;
  167. }
  168. return s->sys_cfgctrl;
  169. case 0xa8: /* SYS_CFGSTAT */
  170. if (board_id(s) != BOARD_ID_VEXPRESS) {
  171. goto bad_reg;
  172. }
  173. return s->sys_cfgstat;
  174. default:
  175. bad_reg:
  176. printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
  177. return 0;
  178. }
  179. }
  180. static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
  181. uint64_t val, unsigned size)
  182. {
  183. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  184. switch (offset) {
  185. case 0x08: /* LED */
  186. s->leds = val;
  187. case 0x0c: /* OSC0 */
  188. case 0x10: /* OSC1 */
  189. case 0x14: /* OSC2 */
  190. case 0x18: /* OSC3 */
  191. case 0x1c: /* OSC4 */
  192. /* ??? */
  193. break;
  194. case 0x20: /* LOCK */
  195. if (val == LOCK_VALUE)
  196. s->lockval = val;
  197. else
  198. s->lockval = val & 0x7fff;
  199. break;
  200. case 0x28: /* CFGDATA1 */
  201. /* ??? Need to implement this. */
  202. s->cfgdata1 = val;
  203. break;
  204. case 0x2c: /* CFGDATA2 */
  205. /* ??? Need to implement this. */
  206. s->cfgdata2 = val;
  207. break;
  208. case 0x30: /* FLAGSSET */
  209. s->flags |= val;
  210. break;
  211. case 0x34: /* FLAGSCLR */
  212. s->flags &= ~val;
  213. break;
  214. case 0x38: /* NVFLAGSSET */
  215. s->nvflags |= val;
  216. break;
  217. case 0x3c: /* NVFLAGSCLR */
  218. s->nvflags &= ~val;
  219. break;
  220. case 0x40: /* RESETCTL */
  221. switch (board_id(s)) {
  222. case BOARD_ID_PB926:
  223. if (s->lockval == LOCK_VALUE) {
  224. s->resetlevel = val;
  225. if (val & 0x100) {
  226. qemu_system_reset_request();
  227. }
  228. }
  229. break;
  230. case BOARD_ID_PBX:
  231. case BOARD_ID_PBA8:
  232. if (s->lockval == LOCK_VALUE) {
  233. s->resetlevel = val;
  234. if (val & 0x04) {
  235. qemu_system_reset_request();
  236. }
  237. }
  238. break;
  239. case BOARD_ID_VEXPRESS:
  240. case BOARD_ID_EB:
  241. default:
  242. /* reserved: RAZ/WI */
  243. break;
  244. }
  245. break;
  246. case 0x44: /* PCICTL */
  247. /* nothing to do. */
  248. break;
  249. case 0x4c: /* FLASH */
  250. break;
  251. case 0x50: /* CLCD */
  252. switch (board_id(s)) {
  253. case BOARD_ID_PB926:
  254. /* On 926 bits 13:8 are R/O, bits 1:0 control
  255. * the mux that defines how to interpret the PL110
  256. * graphics format, and other bits are r/w but we
  257. * don't implement them to do anything.
  258. */
  259. s->sys_clcd &= 0x3f00;
  260. s->sys_clcd |= val & ~0x3f00;
  261. qemu_set_irq(s->pl110_mux_ctrl, val & 3);
  262. break;
  263. case BOARD_ID_EB:
  264. /* The EB is the same except that there is no mux since
  265. * the EB has a PL111.
  266. */
  267. s->sys_clcd &= 0x3f00;
  268. s->sys_clcd |= val & ~0x3f00;
  269. break;
  270. case BOARD_ID_PBA8:
  271. case BOARD_ID_PBX:
  272. /* On PBA8 and PBX bit 7 is r/w and all other bits
  273. * are either r/o or RAZ/WI.
  274. */
  275. s->sys_clcd &= (1 << 7);
  276. s->sys_clcd |= val & ~(1 << 7);
  277. break;
  278. case BOARD_ID_VEXPRESS:
  279. default:
  280. /* On VExpress this register is unimplemented and will RAZ/WI */
  281. break;
  282. }
  283. case 0x54: /* CLCDSER */
  284. case 0x64: /* DMAPSR0 */
  285. case 0x68: /* DMAPSR1 */
  286. case 0x6c: /* DMAPSR2 */
  287. case 0x70: /* IOSEL */
  288. case 0x74: /* PLDCTL */
  289. case 0x80: /* BUSID */
  290. case 0x84: /* PROCID0 */
  291. case 0x88: /* PROCID1 */
  292. case 0x8c: /* OSCRESET0 */
  293. case 0x90: /* OSCRESET1 */
  294. case 0x94: /* OSCRESET2 */
  295. case 0x98: /* OSCRESET3 */
  296. case 0x9c: /* OSCRESET4 */
  297. break;
  298. case 0xa0: /* SYS_CFGDATA */
  299. if (board_id(s) != BOARD_ID_VEXPRESS) {
  300. goto bad_reg;
  301. }
  302. s->sys_cfgdata = val;
  303. return;
  304. case 0xa4: /* SYS_CFGCTRL */
  305. if (board_id(s) != BOARD_ID_VEXPRESS) {
  306. goto bad_reg;
  307. }
  308. s->sys_cfgctrl = val & ~(3 << 18);
  309. s->sys_cfgstat = 1; /* complete */
  310. switch (s->sys_cfgctrl) {
  311. case 0xc0800000: /* SYS_CFG_SHUTDOWN to motherboard */
  312. qemu_system_shutdown_request();
  313. break;
  314. case 0xc0900000: /* SYS_CFG_REBOOT to motherboard */
  315. qemu_system_reset_request();
  316. break;
  317. default:
  318. s->sys_cfgstat |= 2; /* error */
  319. }
  320. return;
  321. case 0xa8: /* SYS_CFGSTAT */
  322. if (board_id(s) != BOARD_ID_VEXPRESS) {
  323. goto bad_reg;
  324. }
  325. s->sys_cfgstat = val & 3;
  326. return;
  327. default:
  328. bad_reg:
  329. printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
  330. return;
  331. }
  332. }
  333. static const MemoryRegionOps arm_sysctl_ops = {
  334. .read = arm_sysctl_read,
  335. .write = arm_sysctl_write,
  336. .endianness = DEVICE_NATIVE_ENDIAN,
  337. };
  338. static void arm_sysctl_gpio_set(void *opaque, int line, int level)
  339. {
  340. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  341. switch (line) {
  342. case ARM_SYSCTL_GPIO_MMC_WPROT:
  343. {
  344. /* For PB926 and EB write-protect is bit 2 of SYS_MCI;
  345. * for all later boards it is bit 1.
  346. */
  347. int bit = 2;
  348. if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) {
  349. bit = 4;
  350. }
  351. s->sys_mci &= ~bit;
  352. if (level) {
  353. s->sys_mci |= bit;
  354. }
  355. break;
  356. }
  357. case ARM_SYSCTL_GPIO_MMC_CARDIN:
  358. s->sys_mci &= ~1;
  359. if (level) {
  360. s->sys_mci |= 1;
  361. }
  362. break;
  363. }
  364. }
  365. static int arm_sysctl_init(SysBusDevice *dev)
  366. {
  367. arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
  368. memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
  369. sysbus_init_mmio(dev, &s->iomem);
  370. qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
  371. qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
  372. return 0;
  373. }
  374. static Property arm_sysctl_properties[] = {
  375. DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
  376. DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
  377. DEFINE_PROP_END_OF_LIST(),
  378. };
  379. static void arm_sysctl_class_init(ObjectClass *klass, void *data)
  380. {
  381. DeviceClass *dc = DEVICE_CLASS(klass);
  382. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  383. k->init = arm_sysctl_init;
  384. dc->reset = arm_sysctl_reset;
  385. dc->vmsd = &vmstate_arm_sysctl;
  386. dc->props = arm_sysctl_properties;
  387. }
  388. static TypeInfo arm_sysctl_info = {
  389. .name = "realview_sysctl",
  390. .parent = TYPE_SYS_BUS_DEVICE,
  391. .instance_size = sizeof(arm_sysctl_state),
  392. .class_init = arm_sysctl_class_init,
  393. };
  394. static void arm_sysctl_register_types(void)
  395. {
  396. type_register_static(&arm_sysctl_info);
  397. }
  398. type_init(arm_sysctl_register_types)