arm_sysctl.c 20 KB

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