arm_sysctl.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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 "qemu/osdep.h"
  10. #include "hw/irq.h"
  11. #include "hw/qdev-properties.h"
  12. #include "qemu/timer.h"
  13. #include "sysemu/runstate.h"
  14. #include "qemu/bitops.h"
  15. #include "hw/sysbus.h"
  16. #include "migration/vmstate.h"
  17. #include "hw/arm/primecell.h"
  18. #include "qemu/log.h"
  19. #include "qemu/module.h"
  20. #include "qom/object.h"
  21. #define LOCK_VALUE 0xa05f
  22. #define TYPE_ARM_SYSCTL "realview_sysctl"
  23. OBJECT_DECLARE_SIMPLE_TYPE(arm_sysctl_state, ARM_SYSCTL)
  24. struct arm_sysctl_state {
  25. SysBusDevice parent_obj;
  26. MemoryRegion iomem;
  27. qemu_irq pl110_mux_ctrl;
  28. uint32_t sys_id;
  29. uint32_t leds;
  30. uint16_t lockval;
  31. uint32_t cfgdata1;
  32. uint32_t cfgdata2;
  33. uint32_t flags;
  34. uint32_t nvflags;
  35. uint32_t resetlevel;
  36. uint32_t proc_id;
  37. uint32_t sys_mci;
  38. uint32_t sys_cfgdata;
  39. uint32_t sys_cfgctrl;
  40. uint32_t sys_cfgstat;
  41. uint32_t sys_clcd;
  42. uint32_t mb_clock[6];
  43. uint32_t *db_clock;
  44. uint32_t db_num_vsensors;
  45. uint32_t *db_voltage;
  46. uint32_t db_num_clocks;
  47. uint32_t *db_clock_reset;
  48. };
  49. static const VMStateDescription vmstate_arm_sysctl = {
  50. .name = "realview_sysctl",
  51. .version_id = 4,
  52. .minimum_version_id = 1,
  53. .fields = (VMStateField[]) {
  54. VMSTATE_UINT32(leds, arm_sysctl_state),
  55. VMSTATE_UINT16(lockval, arm_sysctl_state),
  56. VMSTATE_UINT32(cfgdata1, arm_sysctl_state),
  57. VMSTATE_UINT32(cfgdata2, arm_sysctl_state),
  58. VMSTATE_UINT32(flags, arm_sysctl_state),
  59. VMSTATE_UINT32(nvflags, arm_sysctl_state),
  60. VMSTATE_UINT32(resetlevel, arm_sysctl_state),
  61. VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2),
  62. VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
  63. VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
  64. VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
  65. VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
  66. VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4),
  67. VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks,
  68. 4, vmstate_info_uint32, uint32_t),
  69. VMSTATE_END_OF_LIST()
  70. }
  71. };
  72. /* The PB926 actually uses a different format for
  73. * its SYS_ID register. Fortunately the bits which are
  74. * board type on later boards are distinct.
  75. */
  76. #define BOARD_ID_PB926 0x100
  77. #define BOARD_ID_EB 0x140
  78. #define BOARD_ID_PBA8 0x178
  79. #define BOARD_ID_PBX 0x182
  80. #define BOARD_ID_VEXPRESS 0x190
  81. static int board_id(arm_sysctl_state *s)
  82. {
  83. /* Extract the board ID field from the SYS_ID register value */
  84. return (s->sys_id >> 16) & 0xfff;
  85. }
  86. static void arm_sysctl_reset(DeviceState *d)
  87. {
  88. arm_sysctl_state *s = ARM_SYSCTL(d);
  89. int i;
  90. s->leds = 0;
  91. s->lockval = 0;
  92. s->cfgdata1 = 0;
  93. s->cfgdata2 = 0;
  94. s->flags = 0;
  95. s->resetlevel = 0;
  96. /* Motherboard oscillators (in Hz) */
  97. s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */
  98. s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */
  99. s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */
  100. s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */
  101. s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */
  102. s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */
  103. /* Daughterboard oscillators: reset from property values */
  104. for (i = 0; i < s->db_num_clocks; i++) {
  105. s->db_clock[i] = s->db_clock_reset[i];
  106. }
  107. if (board_id(s) == BOARD_ID_VEXPRESS) {
  108. /* On VExpress this register will RAZ/WI */
  109. s->sys_clcd = 0;
  110. } else {
  111. /* All others: CLCDID 0x1f, indicating VGA */
  112. s->sys_clcd = 0x1f00;
  113. }
  114. }
  115. static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
  116. unsigned size)
  117. {
  118. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  119. switch (offset) {
  120. case 0x00: /* ID */
  121. return s->sys_id;
  122. case 0x04: /* SW */
  123. /* General purpose hardware switches.
  124. We don't have a useful way of exposing these to the user. */
  125. return 0;
  126. case 0x08: /* LED */
  127. return s->leds;
  128. case 0x20: /* LOCK */
  129. return s->lockval;
  130. case 0x0c: /* OSC0 */
  131. case 0x10: /* OSC1 */
  132. case 0x14: /* OSC2 */
  133. case 0x18: /* OSC3 */
  134. case 0x1c: /* OSC4 */
  135. case 0x24: /* 100HZ */
  136. /* ??? Implement these. */
  137. return 0;
  138. case 0x28: /* CFGDATA1 */
  139. return s->cfgdata1;
  140. case 0x2c: /* CFGDATA2 */
  141. return s->cfgdata2;
  142. case 0x30: /* FLAGS */
  143. return s->flags;
  144. case 0x38: /* NVFLAGS */
  145. return s->nvflags;
  146. case 0x40: /* RESETCTL */
  147. if (board_id(s) == BOARD_ID_VEXPRESS) {
  148. /* reserved: RAZ/WI */
  149. return 0;
  150. }
  151. return s->resetlevel;
  152. case 0x44: /* PCICTL */
  153. return 1;
  154. case 0x48: /* MCI */
  155. return s->sys_mci;
  156. case 0x4c: /* FLASH */
  157. return 0;
  158. case 0x50: /* CLCD */
  159. return s->sys_clcd;
  160. case 0x54: /* CLCDSER */
  161. return 0;
  162. case 0x58: /* BOOTCS */
  163. return 0;
  164. case 0x5c: /* 24MHz */
  165. return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24000000,
  166. NANOSECONDS_PER_SECOND);
  167. case 0x60: /* MISC */
  168. return 0;
  169. case 0x84: /* PROCID0 */
  170. return s->proc_id;
  171. case 0x88: /* PROCID1 */
  172. return 0xff000000;
  173. case 0x64: /* DMAPSR0 */
  174. case 0x68: /* DMAPSR1 */
  175. case 0x6c: /* DMAPSR2 */
  176. case 0x70: /* IOSEL */
  177. case 0x74: /* PLDCTL */
  178. case 0x80: /* BUSID */
  179. case 0x8c: /* OSCRESET0 */
  180. case 0x90: /* OSCRESET1 */
  181. case 0x94: /* OSCRESET2 */
  182. case 0x98: /* OSCRESET3 */
  183. case 0x9c: /* OSCRESET4 */
  184. case 0xc0: /* SYS_TEST_OSC0 */
  185. case 0xc4: /* SYS_TEST_OSC1 */
  186. case 0xc8: /* SYS_TEST_OSC2 */
  187. case 0xcc: /* SYS_TEST_OSC3 */
  188. case 0xd0: /* SYS_TEST_OSC4 */
  189. return 0;
  190. case 0xa0: /* SYS_CFGDATA */
  191. if (board_id(s) != BOARD_ID_VEXPRESS) {
  192. goto bad_reg;
  193. }
  194. return s->sys_cfgdata;
  195. case 0xa4: /* SYS_CFGCTRL */
  196. if (board_id(s) != BOARD_ID_VEXPRESS) {
  197. goto bad_reg;
  198. }
  199. return s->sys_cfgctrl;
  200. case 0xa8: /* SYS_CFGSTAT */
  201. if (board_id(s) != BOARD_ID_VEXPRESS) {
  202. goto bad_reg;
  203. }
  204. return s->sys_cfgstat;
  205. default:
  206. bad_reg:
  207. qemu_log_mask(LOG_GUEST_ERROR,
  208. "arm_sysctl_read: Bad register offset 0x%x\n",
  209. (int)offset);
  210. return 0;
  211. }
  212. }
  213. /* SYS_CFGCTRL functions */
  214. #define SYS_CFG_OSC 1
  215. #define SYS_CFG_VOLT 2
  216. #define SYS_CFG_AMP 3
  217. #define SYS_CFG_TEMP 4
  218. #define SYS_CFG_RESET 5
  219. #define SYS_CFG_SCC 6
  220. #define SYS_CFG_MUXFPGA 7
  221. #define SYS_CFG_SHUTDOWN 8
  222. #define SYS_CFG_REBOOT 9
  223. #define SYS_CFG_DVIMODE 11
  224. #define SYS_CFG_POWER 12
  225. #define SYS_CFG_ENERGY 13
  226. /* SYS_CFGCTRL site field values */
  227. #define SYS_CFG_SITE_MB 0
  228. #define SYS_CFG_SITE_DB1 1
  229. #define SYS_CFG_SITE_DB2 2
  230. /**
  231. * vexpress_cfgctrl_read:
  232. * @s: arm_sysctl_state pointer
  233. * @dcc, @function, @site, @position, @device: split out values from
  234. * SYS_CFGCTRL register
  235. * @val: pointer to where to put the read data on success
  236. *
  237. * Handle a VExpress SYS_CFGCTRL register read. On success, return true and
  238. * write the read value to *val. On failure, return false (and val may
  239. * or may not be written to).
  240. */
  241. static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
  242. unsigned int function, unsigned int site,
  243. unsigned int position, unsigned int device,
  244. uint32_t *val)
  245. {
  246. /* We don't support anything other than DCC 0, board stack position 0
  247. * or sites other than motherboard/daughterboard:
  248. */
  249. if (dcc != 0 || position != 0 ||
  250. (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
  251. goto cfgctrl_unimp;
  252. }
  253. switch (function) {
  254. case SYS_CFG_VOLT:
  255. if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) {
  256. *val = s->db_voltage[device];
  257. return true;
  258. }
  259. if (site == SYS_CFG_SITE_MB && device == 0) {
  260. /* There is only one motherboard voltage sensor:
  261. * VIO : 3.3V : bus voltage between mother and daughterboard
  262. */
  263. *val = 3300000;
  264. return true;
  265. }
  266. break;
  267. case SYS_CFG_OSC:
  268. if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
  269. /* motherboard clock */
  270. *val = s->mb_clock[device];
  271. return true;
  272. }
  273. if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
  274. /* daughterboard clock */
  275. *val = s->db_clock[device];
  276. return true;
  277. }
  278. break;
  279. default:
  280. break;
  281. }
  282. cfgctrl_unimp:
  283. qemu_log_mask(LOG_UNIMP,
  284. "arm_sysctl: Unimplemented SYS_CFGCTRL read of function "
  285. "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
  286. function, dcc, site, position, device);
  287. return false;
  288. }
  289. /**
  290. * vexpress_cfgctrl_write:
  291. * @s: arm_sysctl_state pointer
  292. * @dcc, @function, @site, @position, @device: split out values from
  293. * SYS_CFGCTRL register
  294. * @val: data to write
  295. *
  296. * Handle a VExpress SYS_CFGCTRL register write. On success, return true.
  297. * On failure, return false.
  298. */
  299. static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
  300. unsigned int function, unsigned int site,
  301. unsigned int position, unsigned int device,
  302. uint32_t val)
  303. {
  304. /* We don't support anything other than DCC 0, board stack position 0
  305. * or sites other than motherboard/daughterboard:
  306. */
  307. if (dcc != 0 || position != 0 ||
  308. (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
  309. goto cfgctrl_unimp;
  310. }
  311. switch (function) {
  312. case SYS_CFG_OSC:
  313. if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
  314. /* motherboard clock */
  315. s->mb_clock[device] = val;
  316. return true;
  317. }
  318. if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
  319. /* daughterboard clock */
  320. s->db_clock[device] = val;
  321. return true;
  322. }
  323. break;
  324. case SYS_CFG_MUXFPGA:
  325. if (site == SYS_CFG_SITE_MB && device == 0) {
  326. /* Select whether video output comes from motherboard
  327. * or daughterboard: log and ignore as QEMU doesn't
  328. * support this.
  329. */
  330. qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output "
  331. "not supported, ignoring\n");
  332. return true;
  333. }
  334. break;
  335. case SYS_CFG_SHUTDOWN:
  336. if (site == SYS_CFG_SITE_MB && device == 0) {
  337. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  338. return true;
  339. }
  340. break;
  341. case SYS_CFG_REBOOT:
  342. if (site == SYS_CFG_SITE_MB && device == 0) {
  343. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  344. return true;
  345. }
  346. break;
  347. case SYS_CFG_DVIMODE:
  348. if (site == SYS_CFG_SITE_MB && device == 0) {
  349. /* Selecting DVI mode is meaningless for QEMU: we will
  350. * always display the output correctly according to the
  351. * pixel height/width programmed into the CLCD controller.
  352. */
  353. return true;
  354. }
  355. default:
  356. break;
  357. }
  358. cfgctrl_unimp:
  359. qemu_log_mask(LOG_UNIMP,
  360. "arm_sysctl: Unimplemented SYS_CFGCTRL write of function "
  361. "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
  362. function, dcc, site, position, device);
  363. return false;
  364. }
  365. static void arm_sysctl_write(void *opaque, hwaddr offset,
  366. uint64_t val, unsigned size)
  367. {
  368. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  369. switch (offset) {
  370. case 0x08: /* LED */
  371. s->leds = val;
  372. break;
  373. case 0x0c: /* OSC0 */
  374. case 0x10: /* OSC1 */
  375. case 0x14: /* OSC2 */
  376. case 0x18: /* OSC3 */
  377. case 0x1c: /* OSC4 */
  378. /* ??? */
  379. break;
  380. case 0x20: /* LOCK */
  381. if (val == LOCK_VALUE)
  382. s->lockval = val;
  383. else
  384. s->lockval = val & 0x7fff;
  385. break;
  386. case 0x28: /* CFGDATA1 */
  387. /* ??? Need to implement this. */
  388. s->cfgdata1 = val;
  389. break;
  390. case 0x2c: /* CFGDATA2 */
  391. /* ??? Need to implement this. */
  392. s->cfgdata2 = val;
  393. break;
  394. case 0x30: /* FLAGSSET */
  395. s->flags |= val;
  396. break;
  397. case 0x34: /* FLAGSCLR */
  398. s->flags &= ~val;
  399. break;
  400. case 0x38: /* NVFLAGSSET */
  401. s->nvflags |= val;
  402. break;
  403. case 0x3c: /* NVFLAGSCLR */
  404. s->nvflags &= ~val;
  405. break;
  406. case 0x40: /* RESETCTL */
  407. switch (board_id(s)) {
  408. case BOARD_ID_PB926:
  409. if (s->lockval == LOCK_VALUE) {
  410. s->resetlevel = val;
  411. if (val & 0x100) {
  412. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  413. }
  414. }
  415. break;
  416. case BOARD_ID_PBX:
  417. case BOARD_ID_PBA8:
  418. if (s->lockval == LOCK_VALUE) {
  419. s->resetlevel = val;
  420. if (val & 0x04) {
  421. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  422. }
  423. }
  424. break;
  425. case BOARD_ID_VEXPRESS:
  426. case BOARD_ID_EB:
  427. default:
  428. /* reserved: RAZ/WI */
  429. break;
  430. }
  431. break;
  432. case 0x44: /* PCICTL */
  433. /* nothing to do. */
  434. break;
  435. case 0x4c: /* FLASH */
  436. break;
  437. case 0x50: /* CLCD */
  438. switch (board_id(s)) {
  439. case BOARD_ID_PB926:
  440. /* On 926 bits 13:8 are R/O, bits 1:0 control
  441. * the mux that defines how to interpret the PL110
  442. * graphics format, and other bits are r/w but we
  443. * don't implement them to do anything.
  444. */
  445. s->sys_clcd &= 0x3f00;
  446. s->sys_clcd |= val & ~0x3f00;
  447. qemu_set_irq(s->pl110_mux_ctrl, val & 3);
  448. break;
  449. case BOARD_ID_EB:
  450. /* The EB is the same except that there is no mux since
  451. * the EB has a PL111.
  452. */
  453. s->sys_clcd &= 0x3f00;
  454. s->sys_clcd |= val & ~0x3f00;
  455. break;
  456. case BOARD_ID_PBA8:
  457. case BOARD_ID_PBX:
  458. /* On PBA8 and PBX bit 7 is r/w and all other bits
  459. * are either r/o or RAZ/WI.
  460. */
  461. s->sys_clcd &= (1 << 7);
  462. s->sys_clcd |= val & ~(1 << 7);
  463. break;
  464. case BOARD_ID_VEXPRESS:
  465. default:
  466. /* On VExpress this register is unimplemented and will RAZ/WI */
  467. break;
  468. }
  469. break;
  470. case 0x54: /* CLCDSER */
  471. case 0x64: /* DMAPSR0 */
  472. case 0x68: /* DMAPSR1 */
  473. case 0x6c: /* DMAPSR2 */
  474. case 0x70: /* IOSEL */
  475. case 0x74: /* PLDCTL */
  476. case 0x80: /* BUSID */
  477. case 0x84: /* PROCID0 */
  478. case 0x88: /* PROCID1 */
  479. case 0x8c: /* OSCRESET0 */
  480. case 0x90: /* OSCRESET1 */
  481. case 0x94: /* OSCRESET2 */
  482. case 0x98: /* OSCRESET3 */
  483. case 0x9c: /* OSCRESET4 */
  484. break;
  485. case 0xa0: /* SYS_CFGDATA */
  486. if (board_id(s) != BOARD_ID_VEXPRESS) {
  487. goto bad_reg;
  488. }
  489. s->sys_cfgdata = val;
  490. return;
  491. case 0xa4: /* SYS_CFGCTRL */
  492. if (board_id(s) != BOARD_ID_VEXPRESS) {
  493. goto bad_reg;
  494. }
  495. /* Undefined bits [19:18] are RAZ/WI, and writing to
  496. * the start bit just triggers the action; it always reads
  497. * as zero.
  498. */
  499. s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
  500. if (val & (1 << 31)) {
  501. /* Start bit set -- actually do something */
  502. unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
  503. unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
  504. unsigned int site = extract32(s->sys_cfgctrl, 16, 2);
  505. unsigned int position = extract32(s->sys_cfgctrl, 12, 4);
  506. unsigned int device = extract32(s->sys_cfgctrl, 0, 12);
  507. s->sys_cfgstat = 1; /* complete */
  508. if (s->sys_cfgctrl & (1 << 30)) {
  509. if (!vexpress_cfgctrl_write(s, dcc, function, site, position,
  510. device, s->sys_cfgdata)) {
  511. s->sys_cfgstat |= 2; /* error */
  512. }
  513. } else {
  514. uint32_t val;
  515. if (!vexpress_cfgctrl_read(s, dcc, function, site, position,
  516. device, &val)) {
  517. s->sys_cfgstat |= 2; /* error */
  518. } else {
  519. s->sys_cfgdata = val;
  520. }
  521. }
  522. }
  523. s->sys_cfgctrl &= ~(1 << 31);
  524. return;
  525. case 0xa8: /* SYS_CFGSTAT */
  526. if (board_id(s) != BOARD_ID_VEXPRESS) {
  527. goto bad_reg;
  528. }
  529. s->sys_cfgstat = val & 3;
  530. return;
  531. default:
  532. bad_reg:
  533. qemu_log_mask(LOG_GUEST_ERROR,
  534. "arm_sysctl_write: Bad register offset 0x%x\n",
  535. (int)offset);
  536. return;
  537. }
  538. }
  539. static const MemoryRegionOps arm_sysctl_ops = {
  540. .read = arm_sysctl_read,
  541. .write = arm_sysctl_write,
  542. .endianness = DEVICE_NATIVE_ENDIAN,
  543. };
  544. static void arm_sysctl_gpio_set(void *opaque, int line, int level)
  545. {
  546. arm_sysctl_state *s = (arm_sysctl_state *)opaque;
  547. switch (line) {
  548. case ARM_SYSCTL_GPIO_MMC_WPROT:
  549. {
  550. /* For PB926 and EB write-protect is bit 2 of SYS_MCI;
  551. * for all later boards it is bit 1.
  552. */
  553. int bit = 2;
  554. if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) {
  555. bit = 4;
  556. }
  557. s->sys_mci &= ~bit;
  558. if (level) {
  559. s->sys_mci |= bit;
  560. }
  561. break;
  562. }
  563. case ARM_SYSCTL_GPIO_MMC_CARDIN:
  564. s->sys_mci &= ~1;
  565. if (level) {
  566. s->sys_mci |= 1;
  567. }
  568. break;
  569. }
  570. }
  571. static void arm_sysctl_init(Object *obj)
  572. {
  573. DeviceState *dev = DEVICE(obj);
  574. SysBusDevice *sd = SYS_BUS_DEVICE(obj);
  575. arm_sysctl_state *s = ARM_SYSCTL(obj);
  576. memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s,
  577. "arm-sysctl", 0x1000);
  578. sysbus_init_mmio(sd, &s->iomem);
  579. qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2);
  580. qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
  581. }
  582. static void arm_sysctl_realize(DeviceState *d, Error **errp)
  583. {
  584. arm_sysctl_state *s = ARM_SYSCTL(d);
  585. s->db_clock = g_new0(uint32_t, s->db_num_clocks);
  586. }
  587. static void arm_sysctl_finalize(Object *obj)
  588. {
  589. arm_sysctl_state *s = ARM_SYSCTL(obj);
  590. g_free(s->db_voltage);
  591. g_free(s->db_clock);
  592. g_free(s->db_clock_reset);
  593. }
  594. static Property arm_sysctl_properties[] = {
  595. DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
  596. DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
  597. /* Daughterboard power supply voltages (as reported via SYS_CFG) */
  598. DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors,
  599. db_voltage, qdev_prop_uint32, uint32_t),
  600. /* Daughterboard clock reset values (as reported via SYS_CFG) */
  601. DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks,
  602. db_clock_reset, qdev_prop_uint32, uint32_t),
  603. DEFINE_PROP_END_OF_LIST(),
  604. };
  605. static void arm_sysctl_class_init(ObjectClass *klass, void *data)
  606. {
  607. DeviceClass *dc = DEVICE_CLASS(klass);
  608. dc->realize = arm_sysctl_realize;
  609. dc->reset = arm_sysctl_reset;
  610. dc->vmsd = &vmstate_arm_sysctl;
  611. device_class_set_props(dc, arm_sysctl_properties);
  612. }
  613. static const TypeInfo arm_sysctl_info = {
  614. .name = TYPE_ARM_SYSCTL,
  615. .parent = TYPE_SYS_BUS_DEVICE,
  616. .instance_size = sizeof(arm_sysctl_state),
  617. .instance_init = arm_sysctl_init,
  618. .instance_finalize = arm_sysctl_finalize,
  619. .class_init = arm_sysctl_class_init,
  620. };
  621. static void arm_sysctl_register_types(void)
  622. {
  623. type_register_static(&arm_sysctl_info);
  624. }
  625. type_init(arm_sysctl_register_types)