2
0

npcm_gcr.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Nuvoton NPCM7xx/8xx System Global Control Registers.
  3. *
  4. * Copyright 2020 Google LLC
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * for more details.
  15. */
  16. #include "qemu/osdep.h"
  17. #include "hw/misc/npcm_gcr.h"
  18. #include "hw/qdev-properties.h"
  19. #include "migration/vmstate.h"
  20. #include "qapi/error.h"
  21. #include "qemu/cutils.h"
  22. #include "qemu/log.h"
  23. #include "qemu/module.h"
  24. #include "qemu/units.h"
  25. #include "trace.h"
  26. #define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
  27. #define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
  28. enum NPCM7xxGCRRegisters {
  29. NPCM7XX_GCR_PDID,
  30. NPCM7XX_GCR_PWRON,
  31. NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
  32. NPCM7XX_GCR_MFSEL2,
  33. NPCM7XX_GCR_MISCPE,
  34. NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
  35. NPCM7XX_GCR_INTCR,
  36. NPCM7XX_GCR_INTSR,
  37. NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
  38. NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
  39. NPCM7XX_GCR_MFSEL3,
  40. NPCM7XX_GCR_SRCNT,
  41. NPCM7XX_GCR_RESSR,
  42. NPCM7XX_GCR_RLOCKR1,
  43. NPCM7XX_GCR_FLOCKR1,
  44. NPCM7XX_GCR_DSCNT,
  45. NPCM7XX_GCR_MDLR,
  46. NPCM7XX_GCR_SCRPAD3,
  47. NPCM7XX_GCR_SCRPAD2,
  48. NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
  49. NPCM7XX_GCR_INTCR3,
  50. NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
  51. NPCM7XX_GCR_MFSEL4,
  52. NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
  53. NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
  54. NPCM7XX_GCR_CP2BST,
  55. NPCM7XX_GCR_B2CPNT,
  56. NPCM7XX_GCR_CPPCTL,
  57. NPCM7XX_GCR_I2CSEGSEL,
  58. NPCM7XX_GCR_I2CSEGCTL,
  59. NPCM7XX_GCR_VSRCR,
  60. NPCM7XX_GCR_MLOCKR,
  61. NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
  62. NPCM7XX_GCR_USB1PHYCTL,
  63. NPCM7XX_GCR_USB2PHYCTL,
  64. };
  65. static const uint32_t npcm7xx_cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
  66. [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
  67. [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
  68. [NPCM7XX_GCR_SPSWC] = 0x00000003,
  69. [NPCM7XX_GCR_INTCR] = 0x0000035e,
  70. [NPCM7XX_GCR_HIFCR] = 0x0000004e,
  71. [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
  72. [NPCM7XX_GCR_RESSR] = 0x80000000,
  73. [NPCM7XX_GCR_DSCNT] = 0x000000c0,
  74. [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
  75. [NPCM7XX_GCR_SCRPAD] = 0x00000008,
  76. [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
  77. [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
  78. };
  79. enum NPCM8xxGCRRegisters {
  80. NPCM8XX_GCR_PDID,
  81. NPCM8XX_GCR_PWRON,
  82. NPCM8XX_GCR_MISCPE = 0x014 / sizeof(uint32_t),
  83. NPCM8XX_GCR_FLOCKR2 = 0x020 / sizeof(uint32_t),
  84. NPCM8XX_GCR_FLOCKR3,
  85. NPCM8XX_GCR_A35_MODE = 0x034 / sizeof(uint32_t),
  86. NPCM8XX_GCR_SPSWC,
  87. NPCM8XX_GCR_INTCR,
  88. NPCM8XX_GCR_INTSR,
  89. NPCM8XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
  90. NPCM8XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
  91. NPCM8XX_GCR_SRCNT = 0x068 / sizeof(uint32_t),
  92. NPCM8XX_GCR_RESSR,
  93. NPCM8XX_GCR_RLOCKR1,
  94. NPCM8XX_GCR_FLOCKR1,
  95. NPCM8XX_GCR_DSCNT,
  96. NPCM8XX_GCR_MDLR,
  97. NPCM8XX_GCR_SCRPAD_C = 0x080 / sizeof(uint32_t),
  98. NPCM8XX_GCR_SCRPAD_B,
  99. NPCM8XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
  100. NPCM8XX_GCR_INTCR3,
  101. NPCM8XX_GCR_PCIRCTL = 0x0a0 / sizeof(uint32_t),
  102. NPCM8XX_GCR_VSINTR,
  103. NPCM8XX_GCR_SD2SUR1 = 0x0b4 / sizeof(uint32_t),
  104. NPCM8XX_GCR_SD2SUR2,
  105. NPCM8XX_GCR_INTCR4 = 0x0c0 / sizeof(uint32_t),
  106. NPCM8XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
  107. NPCM8XX_GCR_CP2BST,
  108. NPCM8XX_GCR_B2CPNT,
  109. NPCM8XX_GCR_CPPCTL,
  110. NPCM8XX_GCR_I2CSEGSEL = 0x0e0 / sizeof(uint32_t),
  111. NPCM8XX_GCR_I2CSEGCTL,
  112. NPCM8XX_GCR_VSRCR,
  113. NPCM8XX_GCR_MLOCKR,
  114. NPCM8XX_GCR_SCRPAD = 0x13c / sizeof(uint32_t),
  115. NPCM8XX_GCR_USB1PHYCTL,
  116. NPCM8XX_GCR_USB2PHYCTL,
  117. NPCM8XX_GCR_USB3PHYCTL,
  118. NPCM8XX_GCR_MFSEL1 = 0x260 / sizeof(uint32_t),
  119. NPCM8XX_GCR_MFSEL2,
  120. NPCM8XX_GCR_MFSEL3,
  121. NPCM8XX_GCR_MFSEL4,
  122. NPCM8XX_GCR_MFSEL5,
  123. NPCM8XX_GCR_MFSEL6,
  124. NPCM8XX_GCR_MFSEL7,
  125. NPCM8XX_GCR_MFSEL_LK1 = 0x280 / sizeof(uint32_t),
  126. NPCM8XX_GCR_MFSEL_LK2,
  127. NPCM8XX_GCR_MFSEL_LK3,
  128. NPCM8XX_GCR_MFSEL_LK4,
  129. NPCM8XX_GCR_MFSEL_LK5,
  130. NPCM8XX_GCR_MFSEL_LK6,
  131. NPCM8XX_GCR_MFSEL_LK7,
  132. NPCM8XX_GCR_MFSEL_SET1 = 0x2a0 / sizeof(uint32_t),
  133. NPCM8XX_GCR_MFSEL_SET2,
  134. NPCM8XX_GCR_MFSEL_SET3,
  135. NPCM8XX_GCR_MFSEL_SET4,
  136. NPCM8XX_GCR_MFSEL_SET5,
  137. NPCM8XX_GCR_MFSEL_SET6,
  138. NPCM8XX_GCR_MFSEL_SET7,
  139. NPCM8XX_GCR_MFSEL_CLR1 = 0x2c0 / sizeof(uint32_t),
  140. NPCM8XX_GCR_MFSEL_CLR2,
  141. NPCM8XX_GCR_MFSEL_CLR3,
  142. NPCM8XX_GCR_MFSEL_CLR4,
  143. NPCM8XX_GCR_MFSEL_CLR5,
  144. NPCM8XX_GCR_MFSEL_CLR6,
  145. NPCM8XX_GCR_MFSEL_CLR7,
  146. NPCM8XX_GCR_WD0RCRLK = 0x400 / sizeof(uint32_t),
  147. NPCM8XX_GCR_WD1RCRLK,
  148. NPCM8XX_GCR_WD2RCRLK,
  149. NPCM8XX_GCR_SWRSTC1LK,
  150. NPCM8XX_GCR_SWRSTC2LK,
  151. NPCM8XX_GCR_SWRSTC3LK,
  152. NPCM8XX_GCR_TIPRSTCLK,
  153. NPCM8XX_GCR_CORSTCLK,
  154. NPCM8XX_GCR_WD0RCRBLK,
  155. NPCM8XX_GCR_WD1RCRBLK,
  156. NPCM8XX_GCR_WD2RCRBLK,
  157. NPCM8XX_GCR_SWRSTC1BLK,
  158. NPCM8XX_GCR_SWRSTC2BLK,
  159. NPCM8XX_GCR_SWRSTC3BLK,
  160. NPCM8XX_GCR_TIPRSTCBLK,
  161. NPCM8XX_GCR_CORSTCBLK,
  162. /* 64 scratch pad registers start here. 0xe00 ~ 0xefc */
  163. NPCM8XX_GCR_SCRPAD_00 = 0xe00 / sizeof(uint32_t),
  164. /* 32 semaphore registers start here. 0xf00 ~ 0xf7c */
  165. NPCM8XX_GCR_GP_SEMFR_00 = 0xf00 / sizeof(uint32_t),
  166. NPCM8XX_GCR_GP_SEMFR_31 = 0xf7c / sizeof(uint32_t),
  167. };
  168. static const uint32_t npcm8xx_cold_reset_values[NPCM8XX_GCR_NR_REGS] = {
  169. [NPCM8XX_GCR_PDID] = 0x04a35850, /* Arbel A1 */
  170. [NPCM8XX_GCR_MISCPE] = 0x0000ffff,
  171. [NPCM8XX_GCR_A35_MODE] = 0xfff4ff30,
  172. [NPCM8XX_GCR_SPSWC] = 0x00000003,
  173. [NPCM8XX_GCR_INTCR] = 0x0010035e,
  174. [NPCM8XX_GCR_HIFCR] = 0x0000004e,
  175. [NPCM8XX_GCR_SD2SUR1] = 0xfdc80000,
  176. [NPCM8XX_GCR_SD2SUR2] = 0x5200b130,
  177. [NPCM8XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
  178. [NPCM8XX_GCR_RESSR] = 0x80000000,
  179. [NPCM8XX_GCR_DAVCLVLR] = 0x5a00f3cf,
  180. [NPCM8XX_GCR_INTCR3] = 0x5e001002,
  181. [NPCM8XX_GCR_VSRCR] = 0x00004800,
  182. [NPCM8XX_GCR_SCRPAD] = 0x00000008,
  183. [NPCM8XX_GCR_USB1PHYCTL] = 0x034730e4,
  184. [NPCM8XX_GCR_USB2PHYCTL] = 0x034730e4,
  185. [NPCM8XX_GCR_USB3PHYCTL] = 0x034730e4,
  186. /* All 32 semaphores should be initialized to 1. */
  187. [NPCM8XX_GCR_GP_SEMFR_00...NPCM8XX_GCR_GP_SEMFR_31] = 0x00000001,
  188. };
  189. static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size)
  190. {
  191. uint32_t reg = offset / sizeof(uint32_t);
  192. NPCMGCRState *s = opaque;
  193. NPCMGCRClass *c = NPCM_GCR_GET_CLASS(s);
  194. uint64_t value;
  195. if (reg >= c->nr_regs) {
  196. qemu_log_mask(LOG_GUEST_ERROR,
  197. "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
  198. __func__, offset);
  199. return 0;
  200. }
  201. switch (size) {
  202. case 4:
  203. value = s->regs[reg];
  204. break;
  205. case 8:
  206. g_assert(!(reg & 1));
  207. value = deposit64(s->regs[reg], 32, 32, s->regs[reg + 1]);
  208. break;
  209. default:
  210. g_assert_not_reached();
  211. }
  212. trace_npcm_gcr_read(offset, value);
  213. return value;
  214. }
  215. static void npcm_gcr_write(void *opaque, hwaddr offset,
  216. uint64_t v, unsigned size)
  217. {
  218. uint32_t reg = offset / sizeof(uint32_t);
  219. NPCMGCRState *s = opaque;
  220. NPCMGCRClass *c = NPCM_GCR_GET_CLASS(s);
  221. uint32_t value = v;
  222. trace_npcm_gcr_write(offset, v);
  223. if (reg >= c->nr_regs) {
  224. qemu_log_mask(LOG_GUEST_ERROR,
  225. "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
  226. __func__, offset);
  227. return;
  228. }
  229. switch (size) {
  230. case 4:
  231. switch (reg) {
  232. case NPCM7XX_GCR_PDID:
  233. case NPCM7XX_GCR_PWRON:
  234. case NPCM7XX_GCR_INTSR:
  235. qemu_log_mask(LOG_GUEST_ERROR,
  236. "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
  237. __func__, offset);
  238. return;
  239. case NPCM7XX_GCR_RESSR:
  240. case NPCM7XX_GCR_CP2BST:
  241. /* Write 1 to clear */
  242. value = s->regs[reg] & ~value;
  243. break;
  244. case NPCM7XX_GCR_RLOCKR1:
  245. case NPCM7XX_GCR_MDLR:
  246. /* Write 1 to set */
  247. value |= s->regs[reg];
  248. break;
  249. };
  250. s->regs[reg] = value;
  251. break;
  252. case 8:
  253. g_assert(!(reg & 1));
  254. s->regs[reg] = value;
  255. s->regs[reg + 1] = extract64(v, 32, 32);
  256. break;
  257. default:
  258. g_assert_not_reached();
  259. }
  260. }
  261. static bool npcm_gcr_check_mem_op(void *opaque, hwaddr offset,
  262. unsigned size, bool is_write,
  263. MemTxAttrs attrs)
  264. {
  265. NPCMGCRClass *c = NPCM_GCR_GET_CLASS(opaque);
  266. if (offset >= c->nr_regs * sizeof(uint32_t)) {
  267. return false;
  268. }
  269. switch (size) {
  270. case 4:
  271. return true;
  272. case 8:
  273. if (offset >= NPCM8XX_GCR_SCRPAD_00 * sizeof(uint32_t) &&
  274. offset < (NPCM8XX_GCR_NR_REGS - 1) * sizeof(uint32_t)) {
  275. return true;
  276. } else {
  277. return false;
  278. }
  279. default:
  280. return false;
  281. }
  282. }
  283. static const struct MemoryRegionOps npcm_gcr_ops = {
  284. .read = npcm_gcr_read,
  285. .write = npcm_gcr_write,
  286. .endianness = DEVICE_LITTLE_ENDIAN,
  287. .valid = {
  288. .min_access_size = 4,
  289. .max_access_size = 8,
  290. .accepts = npcm_gcr_check_mem_op,
  291. .unaligned = false,
  292. },
  293. };
  294. static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
  295. {
  296. NPCMGCRState *s = NPCM_GCR(obj);
  297. NPCMGCRClass *c = NPCM_GCR_GET_CLASS(obj);
  298. g_assert(sizeof(s->regs) >= sizeof(c->cold_reset_values));
  299. g_assert(sizeof(s->regs) >= c->nr_regs * sizeof(uint32_t));
  300. memcpy(s->regs, c->cold_reset_values, c->nr_regs * sizeof(uint32_t));
  301. /* These 3 registers are at the same location in both 7xx and 8xx. */
  302. s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
  303. s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
  304. s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
  305. }
  306. static void npcm8xx_gcr_enter_reset(Object *obj, ResetType type)
  307. {
  308. NPCMGCRState *s = NPCM_GCR(obj);
  309. NPCMGCRClass *c = NPCM_GCR_GET_CLASS(obj);
  310. memcpy(s->regs, c->cold_reset_values, c->nr_regs * sizeof(uint32_t));
  311. /* These 3 registers are at the same location in both 7xx and 8xx. */
  312. s->regs[NPCM8XX_GCR_PWRON] = s->reset_pwron;
  313. s->regs[NPCM8XX_GCR_MDLR] = s->reset_mdlr;
  314. s->regs[NPCM8XX_GCR_INTCR3] = s->reset_intcr3;
  315. s->regs[NPCM8XX_GCR_SCRPAD_B] = s->reset_scrpad_b;
  316. }
  317. static void npcm_gcr_realize(DeviceState *dev, Error **errp)
  318. {
  319. ERRP_GUARD();
  320. NPCMGCRState *s = NPCM_GCR(dev);
  321. uint64_t dram_size;
  322. Object *obj;
  323. obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
  324. if (!obj) {
  325. error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
  326. return;
  327. }
  328. dram_size = memory_region_size(MEMORY_REGION(obj));
  329. if (!is_power_of_2(dram_size) ||
  330. dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
  331. dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
  332. g_autofree char *sz = size_to_str(dram_size);
  333. g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
  334. g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
  335. error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
  336. error_append_hint(errp,
  337. "DRAM size must be a power of two between %s and %s,"
  338. " inclusive.\n", min_sz, max_sz);
  339. return;
  340. }
  341. /* Power-on reset value */
  342. s->reset_intcr3 = 0x00001002;
  343. /*
  344. * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
  345. * DRAM size, and is normally initialized by the boot block as part of DRAM
  346. * training. However, since we don't have a complete emulation of the
  347. * memory controller and try to make it look like it has already been
  348. * initialized, the boot block will skip this initialization, and we need
  349. * to make sure this field is set correctly up front.
  350. *
  351. * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
  352. * DRAM will be interpreted as 128 MiB.
  353. *
  354. * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
  355. */
  356. s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
  357. /*
  358. * The boot block starting from 0.0.6 for NPCM8xx SoCs stores the DRAM size
  359. * in the SCRPAD2 registers. We need to set this field correctly since
  360. * the initialization is skipped as we mentioned above.
  361. * https://github.com/Nuvoton-Israel/u-boot/blob/npcm8mnx-v2019.01_tmp/board/nuvoton/arbel/arbel.c#L737
  362. */
  363. s->reset_scrpad_b = dram_size;
  364. }
  365. static void npcm_gcr_init(Object *obj)
  366. {
  367. NPCMGCRState *s = NPCM_GCR(obj);
  368. memory_region_init_io(&s->iomem, obj, &npcm_gcr_ops, s,
  369. TYPE_NPCM_GCR, 4 * KiB);
  370. sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
  371. }
  372. static const VMStateDescription vmstate_npcm_gcr = {
  373. .name = "npcm-gcr",
  374. .version_id = 2,
  375. .minimum_version_id = 2,
  376. .fields = (const VMStateField[]) {
  377. VMSTATE_UINT32_ARRAY(regs, NPCMGCRState, NPCM_GCR_MAX_NR_REGS),
  378. VMSTATE_END_OF_LIST(),
  379. },
  380. };
  381. static const Property npcm_gcr_properties[] = {
  382. DEFINE_PROP_UINT32("disabled-modules", NPCMGCRState, reset_mdlr, 0),
  383. DEFINE_PROP_UINT32("power-on-straps", NPCMGCRState, reset_pwron, 0),
  384. };
  385. static void npcm_gcr_class_init(ObjectClass *klass, void *data)
  386. {
  387. DeviceClass *dc = DEVICE_CLASS(klass);
  388. dc->realize = npcm_gcr_realize;
  389. dc->vmsd = &vmstate_npcm_gcr;
  390. device_class_set_props(dc, npcm_gcr_properties);
  391. }
  392. static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
  393. {
  394. NPCMGCRClass *c = NPCM_GCR_CLASS(klass);
  395. DeviceClass *dc = DEVICE_CLASS(klass);
  396. ResettableClass *rc = RESETTABLE_CLASS(klass);
  397. dc->desc = "NPCM7xx System Global Control Registers";
  398. rc->phases.enter = npcm7xx_gcr_enter_reset;
  399. c->nr_regs = NPCM7XX_GCR_NR_REGS;
  400. c->cold_reset_values = npcm7xx_cold_reset_values;
  401. rc->phases.enter = npcm7xx_gcr_enter_reset;
  402. }
  403. static void npcm8xx_gcr_class_init(ObjectClass *klass, void *data)
  404. {
  405. NPCMGCRClass *c = NPCM_GCR_CLASS(klass);
  406. DeviceClass *dc = DEVICE_CLASS(klass);
  407. ResettableClass *rc = RESETTABLE_CLASS(klass);
  408. dc->desc = "NPCM8xx System Global Control Registers";
  409. c->nr_regs = NPCM8XX_GCR_NR_REGS;
  410. c->cold_reset_values = npcm8xx_cold_reset_values;
  411. rc->phases.enter = npcm8xx_gcr_enter_reset;
  412. }
  413. static const TypeInfo npcm_gcr_info[] = {
  414. {
  415. .name = TYPE_NPCM_GCR,
  416. .parent = TYPE_SYS_BUS_DEVICE,
  417. .instance_size = sizeof(NPCMGCRState),
  418. .instance_init = npcm_gcr_init,
  419. .class_size = sizeof(NPCMGCRClass),
  420. .class_init = npcm_gcr_class_init,
  421. .abstract = true,
  422. },
  423. {
  424. .name = TYPE_NPCM7XX_GCR,
  425. .parent = TYPE_NPCM_GCR,
  426. .class_init = npcm7xx_gcr_class_init,
  427. },
  428. {
  429. .name = TYPE_NPCM8XX_GCR,
  430. .parent = TYPE_NPCM_GCR,
  431. .class_init = npcm8xx_gcr_class_init,
  432. },
  433. };
  434. DEFINE_TYPES(npcm_gcr_info)