2
0

arm_sysctl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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/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, SYS_BUS_DEVICE(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, hwaddr 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. qemu_log_mask(LOG_GUEST_ERROR,
  177. "arm_sysctl_read: Bad register offset 0x%x\n",
  178. (int)offset);
  179. return 0;
  180. }
  181. }
  182. static void arm_sysctl_write(void *opaque, hwaddr offset,
  183. uint64_t val, unsigned size)
  184. {
  185. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  186. switch (offset) {
  187. case 0x08: /* LED */
  188. s->leds = val;
  189. break;
  190. case 0x0c: /* OSC0 */
  191. case 0x10: /* OSC1 */
  192. case 0x14: /* OSC2 */
  193. case 0x18: /* OSC3 */
  194. case 0x1c: /* OSC4 */
  195. /* ??? */
  196. break;
  197. case 0x20: /* LOCK */
  198. if (val == LOCK_VALUE)
  199. s->lockval = val;
  200. else
  201. s->lockval = val & 0x7fff;
  202. break;
  203. case 0x28: /* CFGDATA1 */
  204. /* ??? Need to implement this. */
  205. s->cfgdata1 = val;
  206. break;
  207. case 0x2c: /* CFGDATA2 */
  208. /* ??? Need to implement this. */
  209. s->cfgdata2 = val;
  210. break;
  211. case 0x30: /* FLAGSSET */
  212. s->flags |= val;
  213. break;
  214. case 0x34: /* FLAGSCLR */
  215. s->flags &= ~val;
  216. break;
  217. case 0x38: /* NVFLAGSSET */
  218. s->nvflags |= val;
  219. break;
  220. case 0x3c: /* NVFLAGSCLR */
  221. s->nvflags &= ~val;
  222. break;
  223. case 0x40: /* RESETCTL */
  224. switch (board_id(s)) {
  225. case BOARD_ID_PB926:
  226. if (s->lockval == LOCK_VALUE) {
  227. s->resetlevel = val;
  228. if (val & 0x100) {
  229. qemu_system_reset_request();
  230. }
  231. }
  232. break;
  233. case BOARD_ID_PBX:
  234. case BOARD_ID_PBA8:
  235. if (s->lockval == LOCK_VALUE) {
  236. s->resetlevel = val;
  237. if (val & 0x04) {
  238. qemu_system_reset_request();
  239. }
  240. }
  241. break;
  242. case BOARD_ID_VEXPRESS:
  243. case BOARD_ID_EB:
  244. default:
  245. /* reserved: RAZ/WI */
  246. break;
  247. }
  248. break;
  249. case 0x44: /* PCICTL */
  250. /* nothing to do. */
  251. break;
  252. case 0x4c: /* FLASH */
  253. break;
  254. case 0x50: /* CLCD */
  255. switch (board_id(s)) {
  256. case BOARD_ID_PB926:
  257. /* On 926 bits 13:8 are R/O, bits 1:0 control
  258. * the mux that defines how to interpret the PL110
  259. * graphics format, and other bits are r/w but we
  260. * don't implement them to do anything.
  261. */
  262. s->sys_clcd &= 0x3f00;
  263. s->sys_clcd |= val & ~0x3f00;
  264. qemu_set_irq(s->pl110_mux_ctrl, val & 3);
  265. break;
  266. case BOARD_ID_EB:
  267. /* The EB is the same except that there is no mux since
  268. * the EB has a PL111.
  269. */
  270. s->sys_clcd &= 0x3f00;
  271. s->sys_clcd |= val & ~0x3f00;
  272. break;
  273. case BOARD_ID_PBA8:
  274. case BOARD_ID_PBX:
  275. /* On PBA8 and PBX bit 7 is r/w and all other bits
  276. * are either r/o or RAZ/WI.
  277. */
  278. s->sys_clcd &= (1 << 7);
  279. s->sys_clcd |= val & ~(1 << 7);
  280. break;
  281. case BOARD_ID_VEXPRESS:
  282. default:
  283. /* On VExpress this register is unimplemented and will RAZ/WI */
  284. break;
  285. }
  286. break;
  287. case 0x54: /* CLCDSER */
  288. case 0x64: /* DMAPSR0 */
  289. case 0x68: /* DMAPSR1 */
  290. case 0x6c: /* DMAPSR2 */
  291. case 0x70: /* IOSEL */
  292. case 0x74: /* PLDCTL */
  293. case 0x80: /* BUSID */
  294. case 0x84: /* PROCID0 */
  295. case 0x88: /* PROCID1 */
  296. case 0x8c: /* OSCRESET0 */
  297. case 0x90: /* OSCRESET1 */
  298. case 0x94: /* OSCRESET2 */
  299. case 0x98: /* OSCRESET3 */
  300. case 0x9c: /* OSCRESET4 */
  301. break;
  302. case 0xa0: /* SYS_CFGDATA */
  303. if (board_id(s) != BOARD_ID_VEXPRESS) {
  304. goto bad_reg;
  305. }
  306. s->sys_cfgdata = val;
  307. return;
  308. case 0xa4: /* SYS_CFGCTRL */
  309. if (board_id(s) != BOARD_ID_VEXPRESS) {
  310. goto bad_reg;
  311. }
  312. s->sys_cfgctrl = val & ~(3 << 18);
  313. s->sys_cfgstat = 1; /* complete */
  314. switch (s->sys_cfgctrl) {
  315. case 0xc0800000: /* SYS_CFG_SHUTDOWN to motherboard */
  316. qemu_system_shutdown_request();
  317. break;
  318. case 0xc0900000: /* SYS_CFG_REBOOT to motherboard */
  319. qemu_system_reset_request();
  320. break;
  321. default:
  322. s->sys_cfgstat |= 2; /* error */
  323. }
  324. s->sys_cfgctrl &= ~(1 << 31);
  325. return;
  326. case 0xa8: /* SYS_CFGSTAT */
  327. if (board_id(s) != BOARD_ID_VEXPRESS) {
  328. goto bad_reg;
  329. }
  330. s->sys_cfgstat = val & 3;
  331. return;
  332. default:
  333. bad_reg:
  334. qemu_log_mask(LOG_GUEST_ERROR,
  335. "arm_sysctl_write: Bad register offset 0x%x\n",
  336. (int)offset);
  337. return;
  338. }
  339. }
  340. static const MemoryRegionOps arm_sysctl_ops = {
  341. .read = arm_sysctl_read,
  342. .write = arm_sysctl_write,
  343. .endianness = DEVICE_NATIVE_ENDIAN,
  344. };
  345. static void arm_sysctl_gpio_set(void *opaque, int line, int level)
  346. {
  347. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  348. switch (line) {
  349. case ARM_SYSCTL_GPIO_MMC_WPROT:
  350. {
  351. /* For PB926 and EB write-protect is bit 2 of SYS_MCI;
  352. * for all later boards it is bit 1.
  353. */
  354. int bit = 2;
  355. if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) {
  356. bit = 4;
  357. }
  358. s->sys_mci &= ~bit;
  359. if (level) {
  360. s->sys_mci |= bit;
  361. }
  362. break;
  363. }
  364. case ARM_SYSCTL_GPIO_MMC_CARDIN:
  365. s->sys_mci &= ~1;
  366. if (level) {
  367. s->sys_mci |= 1;
  368. }
  369. break;
  370. }
  371. }
  372. static int arm_sysctl_init(SysBusDevice *dev)
  373. {
  374. arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
  375. memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
  376. sysbus_init_mmio(dev, &s->iomem);
  377. qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
  378. qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
  379. return 0;
  380. }
  381. static Property arm_sysctl_properties[] = {
  382. DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
  383. DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
  384. DEFINE_PROP_END_OF_LIST(),
  385. };
  386. static void arm_sysctl_class_init(ObjectClass *klass, void *data)
  387. {
  388. DeviceClass *dc = DEVICE_CLASS(klass);
  389. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  390. k->init = arm_sysctl_init;
  391. dc->reset = arm_sysctl_reset;
  392. dc->vmsd = &vmstate_arm_sysctl;
  393. dc->props = arm_sysctl_properties;
  394. }
  395. static const TypeInfo arm_sysctl_info = {
  396. .name = "realview_sysctl",
  397. .parent = TYPE_SYS_BUS_DEVICE,
  398. .instance_size = sizeof(arm_sysctl_state),
  399. .class_init = arm_sysctl_class_init,
  400. };
  401. static void arm_sysctl_register_types(void)
  402. {
  403. type_register_static(&arm_sysctl_info);
  404. }
  405. type_init(arm_sysctl_register_types)