aspeed_scu.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. /*
  2. * ASPEED System Control Unit
  3. *
  4. * Andrew Jeffery <andrew@aj.id.au>
  5. *
  6. * Copyright 2016 IBM Corp.
  7. *
  8. * This code is licensed under the GPL version 2 or later. See
  9. * the COPYING file in the top-level directory.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "hw/misc/aspeed_scu.h"
  13. #include "hw/qdev-properties.h"
  14. #include "migration/vmstate.h"
  15. #include "qapi/error.h"
  16. #include "qapi/visitor.h"
  17. #include "qemu/bitops.h"
  18. #include "qemu/log.h"
  19. #include "qemu/guest-random.h"
  20. #include "qemu/module.h"
  21. #include "trace.h"
  22. #define TO_REG(offset) ((offset) >> 2)
  23. #define PROT_KEY TO_REG(0x00)
  24. #define SYS_RST_CTRL TO_REG(0x04)
  25. #define CLK_SEL TO_REG(0x08)
  26. #define CLK_STOP_CTRL TO_REG(0x0C)
  27. #define FREQ_CNTR_CTRL TO_REG(0x10)
  28. #define FREQ_CNTR_EVAL TO_REG(0x14)
  29. #define IRQ_CTRL TO_REG(0x18)
  30. #define D2PLL_PARAM TO_REG(0x1C)
  31. #define MPLL_PARAM TO_REG(0x20)
  32. #define HPLL_PARAM TO_REG(0x24)
  33. #define FREQ_CNTR_RANGE TO_REG(0x28)
  34. #define MISC_CTRL1 TO_REG(0x2C)
  35. #define PCI_CTRL1 TO_REG(0x30)
  36. #define PCI_CTRL2 TO_REG(0x34)
  37. #define PCI_CTRL3 TO_REG(0x38)
  38. #define SYS_RST_STATUS TO_REG(0x3C)
  39. #define SOC_SCRATCH1 TO_REG(0x40)
  40. #define SOC_SCRATCH2 TO_REG(0x44)
  41. #define MAC_CLK_DELAY TO_REG(0x48)
  42. #define MISC_CTRL2 TO_REG(0x4C)
  43. #define VGA_SCRATCH1 TO_REG(0x50)
  44. #define VGA_SCRATCH2 TO_REG(0x54)
  45. #define VGA_SCRATCH3 TO_REG(0x58)
  46. #define VGA_SCRATCH4 TO_REG(0x5C)
  47. #define VGA_SCRATCH5 TO_REG(0x60)
  48. #define VGA_SCRATCH6 TO_REG(0x64)
  49. #define VGA_SCRATCH7 TO_REG(0x68)
  50. #define VGA_SCRATCH8 TO_REG(0x6C)
  51. #define HW_STRAP1 TO_REG(0x70)
  52. #define RNG_CTRL TO_REG(0x74)
  53. #define RNG_DATA TO_REG(0x78)
  54. #define SILICON_REV TO_REG(0x7C)
  55. #define PINMUX_CTRL1 TO_REG(0x80)
  56. #define PINMUX_CTRL2 TO_REG(0x84)
  57. #define PINMUX_CTRL3 TO_REG(0x88)
  58. #define PINMUX_CTRL4 TO_REG(0x8C)
  59. #define PINMUX_CTRL5 TO_REG(0x90)
  60. #define PINMUX_CTRL6 TO_REG(0x94)
  61. #define WDT_RST_CTRL TO_REG(0x9C)
  62. #define PINMUX_CTRL7 TO_REG(0xA0)
  63. #define PINMUX_CTRL8 TO_REG(0xA4)
  64. #define PINMUX_CTRL9 TO_REG(0xA8)
  65. #define WAKEUP_EN TO_REG(0xC0)
  66. #define WAKEUP_CTRL TO_REG(0xC4)
  67. #define HW_STRAP2 TO_REG(0xD0)
  68. #define FREE_CNTR4 TO_REG(0xE0)
  69. #define FREE_CNTR4_EXT TO_REG(0xE4)
  70. #define CPU2_CTRL TO_REG(0x100)
  71. #define CPU2_BASE_SEG1 TO_REG(0x104)
  72. #define CPU2_BASE_SEG2 TO_REG(0x108)
  73. #define CPU2_BASE_SEG3 TO_REG(0x10C)
  74. #define CPU2_BASE_SEG4 TO_REG(0x110)
  75. #define CPU2_BASE_SEG5 TO_REG(0x114)
  76. #define CPU2_CACHE_CTRL TO_REG(0x118)
  77. #define CHIP_ID0 TO_REG(0x150)
  78. #define CHIP_ID1 TO_REG(0x154)
  79. #define UART_HPLL_CLK TO_REG(0x160)
  80. #define PCIE_CTRL TO_REG(0x180)
  81. #define BMC_MMIO_CTRL TO_REG(0x184)
  82. #define RELOC_DECODE_BASE1 TO_REG(0x188)
  83. #define RELOC_DECODE_BASE2 TO_REG(0x18C)
  84. #define MAILBOX_DECODE_BASE TO_REG(0x190)
  85. #define SRAM_DECODE_BASE1 TO_REG(0x194)
  86. #define SRAM_DECODE_BASE2 TO_REG(0x198)
  87. #define BMC_REV TO_REG(0x19C)
  88. #define BMC_DEV_ID TO_REG(0x1A4)
  89. #define AST2600_PROT_KEY TO_REG(0x00)
  90. #define AST2600_SILICON_REV TO_REG(0x04)
  91. #define AST2600_SILICON_REV2 TO_REG(0x14)
  92. #define AST2600_SYS_RST_CTRL TO_REG(0x40)
  93. #define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44)
  94. #define AST2600_SYS_RST_CTRL2 TO_REG(0x50)
  95. #define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
  96. #define AST2600_CLK_STOP_CTRL TO_REG(0x80)
  97. #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
  98. #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
  99. #define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
  100. #define AST2600_DEBUG_CTRL TO_REG(0xC8)
  101. #define AST2600_DEBUG_CTRL2 TO_REG(0xD8)
  102. #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
  103. #define AST2600_HPLL_PARAM TO_REG(0x200)
  104. #define AST2600_HPLL_EXT TO_REG(0x204)
  105. #define AST2600_APLL_PARAM TO_REG(0x210)
  106. #define AST2600_APLL_EXT TO_REG(0x214)
  107. #define AST2600_MPLL_PARAM TO_REG(0x220)
  108. #define AST2600_MPLL_EXT TO_REG(0x224)
  109. #define AST2600_EPLL_PARAM TO_REG(0x240)
  110. #define AST2600_EPLL_EXT TO_REG(0x244)
  111. #define AST2600_DPLL_PARAM TO_REG(0x260)
  112. #define AST2600_DPLL_EXT TO_REG(0x264)
  113. #define AST2600_CLK_SEL TO_REG(0x300)
  114. #define AST2600_CLK_SEL2 TO_REG(0x304)
  115. #define AST2600_CLK_SEL3 TO_REG(0x308)
  116. #define AST2600_CLK_SEL4 TO_REG(0x310)
  117. #define AST2600_CLK_SEL5 TO_REG(0x314)
  118. #define AST2600_UARTCLK TO_REG(0x338)
  119. #define AST2600_HUARTCLK TO_REG(0x33C)
  120. #define AST2600_HW_STRAP1 TO_REG(0x500)
  121. #define AST2600_HW_STRAP1_CLR TO_REG(0x504)
  122. #define AST2600_HW_STRAP1_PROT TO_REG(0x508)
  123. #define AST2600_HW_STRAP2 TO_REG(0x510)
  124. #define AST2600_HW_STRAP2_CLR TO_REG(0x514)
  125. #define AST2600_HW_STRAP2_PROT TO_REG(0x518)
  126. #define AST2600_RNG_CTRL TO_REG(0x524)
  127. #define AST2600_RNG_DATA TO_REG(0x540)
  128. #define AST2600_CHIP_ID0 TO_REG(0x5B0)
  129. #define AST2600_CHIP_ID1 TO_REG(0x5B4)
  130. #define AST2600_CLK TO_REG(0x40)
  131. #define AST2700_SILICON_REV TO_REG(0x00)
  132. #define AST2700_HW_STRAP1 TO_REG(0x10)
  133. #define AST2700_HW_STRAP1_CLR TO_REG(0x14)
  134. #define AST2700_HW_STRAP1_LOCK TO_REG(0x20)
  135. #define AST2700_HW_STRAP1_SEC1 TO_REG(0x24)
  136. #define AST2700_HW_STRAP1_SEC2 TO_REG(0x28)
  137. #define AST2700_HW_STRAP1_SEC3 TO_REG(0x2C)
  138. #define AST2700_SCU_CLK_SEL_1 TO_REG(0x280)
  139. #define AST2700_SCU_HPLL_PARAM TO_REG(0x300)
  140. #define AST2700_SCU_HPLL_EXT_PARAM TO_REG(0x304)
  141. #define AST2700_SCU_DPLL_PARAM TO_REG(0x308)
  142. #define AST2700_SCU_DPLL_EXT_PARAM TO_REG(0x30c)
  143. #define AST2700_SCU_MPLL_PARAM TO_REG(0x310)
  144. #define AST2700_SCU_MPLL_EXT_PARAM TO_REG(0x314)
  145. #define AST2700_SCU_D1CLK_PARAM TO_REG(0x320)
  146. #define AST2700_SCU_D2CLK_PARAM TO_REG(0x330)
  147. #define AST2700_SCU_CRT1CLK_PARAM TO_REG(0x340)
  148. #define AST2700_SCU_CRT2CLK_PARAM TO_REG(0x350)
  149. #define AST2700_SCU_MPHYCLK_PARAM TO_REG(0x360)
  150. #define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
  151. #define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
  152. #define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
  153. #define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900)
  154. #define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
  155. #define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
  156. #define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260)
  157. #define AST2700_SCUIO_CLK_STOP_CLR_2 TO_REG(0x264)
  158. #define AST2700_SCUIO_CLK_SEL_1 TO_REG(0x280)
  159. #define AST2700_SCUIO_CLK_SEL_2 TO_REG(0x284)
  160. #define AST2700_SCUIO_HPLL_PARAM TO_REG(0x300)
  161. #define AST2700_SCUIO_HPLL_EXT_PARAM TO_REG(0x304)
  162. #define AST2700_SCUIO_APLL_PARAM TO_REG(0x310)
  163. #define AST2700_SCUIO_APLL_EXT_PARAM TO_REG(0x314)
  164. #define AST2700_SCUIO_DPLL_PARAM TO_REG(0x320)
  165. #define AST2700_SCUIO_DPLL_EXT_PARAM TO_REG(0x324)
  166. #define AST2700_SCUIO_DPLL_PARAM_READ TO_REG(0x328)
  167. #define AST2700_SCUIO_DPLL_EXT_PARAM_READ TO_REG(0x32c)
  168. #define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
  169. #define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
  170. #define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
  171. #define SCU_IO_REGION_SIZE 0x1000
  172. static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
  173. [SYS_RST_CTRL] = 0xFFCFFEDCU,
  174. [CLK_SEL] = 0xF3F40000U,
  175. [CLK_STOP_CTRL] = 0x19FC3E8BU,
  176. [D2PLL_PARAM] = 0x00026108U,
  177. [MPLL_PARAM] = 0x00030291U,
  178. [HPLL_PARAM] = 0x00000291U,
  179. [MISC_CTRL1] = 0x00000010U,
  180. [PCI_CTRL1] = 0x20001A03U,
  181. [PCI_CTRL2] = 0x20001A03U,
  182. [PCI_CTRL3] = 0x04000030U,
  183. [SYS_RST_STATUS] = 0x00000001U,
  184. [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
  185. [MISC_CTRL2] = 0x00000023U,
  186. [RNG_CTRL] = 0x0000000EU,
  187. [PINMUX_CTRL2] = 0x0000F000U,
  188. [PINMUX_CTRL3] = 0x01000000U,
  189. [PINMUX_CTRL4] = 0x000000FFU,
  190. [PINMUX_CTRL5] = 0x0000A000U,
  191. [WDT_RST_CTRL] = 0x003FFFF3U,
  192. [PINMUX_CTRL8] = 0xFFFF0000U,
  193. [PINMUX_CTRL9] = 0x000FFFFFU,
  194. [FREE_CNTR4] = 0x000000FFU,
  195. [FREE_CNTR4_EXT] = 0x000000FFU,
  196. [CPU2_BASE_SEG1] = 0x80000000U,
  197. [CPU2_BASE_SEG4] = 0x1E600000U,
  198. [CPU2_BASE_SEG5] = 0xC0000000U,
  199. [UART_HPLL_CLK] = 0x00001903U,
  200. [PCIE_CTRL] = 0x0000007BU,
  201. [BMC_DEV_ID] = 0x00002402U
  202. };
  203. /* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
  204. /* AST2500 revision A1 */
  205. static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
  206. [SYS_RST_CTRL] = 0xFFCFFEDCU,
  207. [CLK_SEL] = 0xF3F40000U,
  208. [CLK_STOP_CTRL] = 0x19FC3E8BU,
  209. [D2PLL_PARAM] = 0x00026108U,
  210. [MPLL_PARAM] = 0x00030291U,
  211. [HPLL_PARAM] = 0x93000400U,
  212. [MISC_CTRL1] = 0x00000010U,
  213. [PCI_CTRL1] = 0x20001A03U,
  214. [PCI_CTRL2] = 0x20001A03U,
  215. [PCI_CTRL3] = 0x04000030U,
  216. [SYS_RST_STATUS] = 0x00000001U,
  217. [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
  218. [MISC_CTRL2] = 0x00000023U,
  219. [RNG_CTRL] = 0x0000000EU,
  220. [PINMUX_CTRL2] = 0x0000F000U,
  221. [PINMUX_CTRL3] = 0x03000000U,
  222. [PINMUX_CTRL4] = 0x00000000U,
  223. [PINMUX_CTRL5] = 0x0000A000U,
  224. [WDT_RST_CTRL] = 0x023FFFF3U,
  225. [PINMUX_CTRL8] = 0xFFFF0000U,
  226. [PINMUX_CTRL9] = 0x000FFFFFU,
  227. [FREE_CNTR4] = 0x000000FFU,
  228. [FREE_CNTR4_EXT] = 0x000000FFU,
  229. [CPU2_BASE_SEG1] = 0x80000000U,
  230. [CPU2_BASE_SEG4] = 0x1E600000U,
  231. [CPU2_BASE_SEG5] = 0xC0000000U,
  232. [CHIP_ID0] = 0x1234ABCDU,
  233. [CHIP_ID1] = 0x88884444U,
  234. [UART_HPLL_CLK] = 0x00001903U,
  235. [PCIE_CTRL] = 0x0000007BU,
  236. [BMC_DEV_ID] = 0x00002402U
  237. };
  238. static uint32_t aspeed_scu_get_random(void)
  239. {
  240. uint32_t num;
  241. qemu_guest_getrandom_nofail(&num, sizeof(num));
  242. return num;
  243. }
  244. uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s)
  245. {
  246. return ASPEED_SCU_GET_CLASS(s)->get_apb(s);
  247. }
  248. static uint32_t aspeed_2400_scu_get_apb_freq(AspeedSCUState *s)
  249. {
  250. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
  251. uint32_t hpll = asc->calc_hpll(s, s->regs[HPLL_PARAM]);
  252. return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1)
  253. / asc->apb_divider;
  254. }
  255. static uint32_t aspeed_2600_scu_get_apb_freq(AspeedSCUState *s)
  256. {
  257. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
  258. uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
  259. return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL]) + 1)
  260. / asc->apb_divider;
  261. }
  262. static uint32_t aspeed_1030_scu_get_apb_freq(AspeedSCUState *s)
  263. {
  264. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
  265. uint32_t hpll = asc->calc_hpll(s, s->regs[AST2600_HPLL_PARAM]);
  266. return hpll / (SCU_AST1030_CLK_GET_PCLK_DIV(s->regs[AST2600_CLK_SEL4]) + 1)
  267. / asc->apb_divider;
  268. }
  269. static uint32_t aspeed_2700_scu_get_apb_freq(AspeedSCUState *s)
  270. {
  271. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
  272. uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCU_HPLL_PARAM]);
  273. return hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[AST2700_SCU_CLK_SEL_1]) + 1)
  274. / asc->apb_divider;
  275. }
  276. static uint32_t aspeed_2700_scuio_get_apb_freq(AspeedSCUState *s)
  277. {
  278. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s);
  279. uint32_t hpll = asc->calc_hpll(s, s->regs[AST2700_SCUIO_HPLL_PARAM]);
  280. return hpll /
  281. (SCUIO_AST2700_CLK_GET_PCLK_DIV(s->regs[AST2700_SCUIO_CLK_SEL_1]) + 1)
  282. / asc->apb_divider;
  283. }
  284. static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
  285. {
  286. AspeedSCUState *s = ASPEED_SCU(opaque);
  287. int reg = TO_REG(offset);
  288. if (reg >= ASPEED_SCU_NR_REGS) {
  289. qemu_log_mask(LOG_GUEST_ERROR,
  290. "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
  291. __func__, offset);
  292. return 0;
  293. }
  294. switch (reg) {
  295. case RNG_DATA:
  296. /*
  297. * On hardware, RNG_DATA works regardless of
  298. * the state of the enable bit in RNG_CTRL
  299. */
  300. s->regs[RNG_DATA] = aspeed_scu_get_random();
  301. break;
  302. case WAKEUP_EN:
  303. qemu_log_mask(LOG_GUEST_ERROR,
  304. "%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
  305. __func__, offset);
  306. break;
  307. }
  308. trace_aspeed_scu_read(offset, size, s->regs[reg]);
  309. return s->regs[reg];
  310. }
  311. static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
  312. uint64_t data, unsigned size)
  313. {
  314. AspeedSCUState *s = ASPEED_SCU(opaque);
  315. int reg = TO_REG(offset);
  316. if (reg >= ASPEED_SCU_NR_REGS) {
  317. qemu_log_mask(LOG_GUEST_ERROR,
  318. "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
  319. __func__, offset);
  320. return;
  321. }
  322. if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
  323. !s->regs[PROT_KEY]) {
  324. qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
  325. }
  326. trace_aspeed_scu_write(offset, size, data);
  327. switch (reg) {
  328. case PROT_KEY:
  329. s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
  330. return;
  331. case SILICON_REV:
  332. case FREQ_CNTR_EVAL:
  333. case VGA_SCRATCH1 ... VGA_SCRATCH8:
  334. case RNG_DATA:
  335. case FREE_CNTR4:
  336. case FREE_CNTR4_EXT:
  337. qemu_log_mask(LOG_GUEST_ERROR,
  338. "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
  339. __func__, offset);
  340. return;
  341. }
  342. s->regs[reg] = data;
  343. }
  344. static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
  345. uint64_t data, unsigned size)
  346. {
  347. AspeedSCUState *s = ASPEED_SCU(opaque);
  348. int reg = TO_REG(offset);
  349. if (reg >= ASPEED_SCU_NR_REGS) {
  350. qemu_log_mask(LOG_GUEST_ERROR,
  351. "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
  352. __func__, offset);
  353. return;
  354. }
  355. if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
  356. !s->regs[PROT_KEY]) {
  357. qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
  358. return;
  359. }
  360. trace_aspeed_scu_write(offset, size, data);
  361. switch (reg) {
  362. case PROT_KEY:
  363. s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
  364. return;
  365. case HW_STRAP1:
  366. s->regs[HW_STRAP1] |= data;
  367. return;
  368. case SILICON_REV:
  369. s->regs[HW_STRAP1] &= ~data;
  370. return;
  371. case FREQ_CNTR_EVAL:
  372. case VGA_SCRATCH1 ... VGA_SCRATCH8:
  373. case RNG_DATA:
  374. case FREE_CNTR4:
  375. case FREE_CNTR4_EXT:
  376. case CHIP_ID0:
  377. case CHIP_ID1:
  378. qemu_log_mask(LOG_GUEST_ERROR,
  379. "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
  380. __func__, offset);
  381. return;
  382. }
  383. s->regs[reg] = data;
  384. }
  385. static const MemoryRegionOps aspeed_ast2400_scu_ops = {
  386. .read = aspeed_scu_read,
  387. .write = aspeed_ast2400_scu_write,
  388. .endianness = DEVICE_LITTLE_ENDIAN,
  389. .impl = {
  390. .min_access_size = 4,
  391. .max_access_size = 4,
  392. },
  393. .valid = {
  394. .min_access_size = 1,
  395. .max_access_size = 4,
  396. },
  397. };
  398. static const MemoryRegionOps aspeed_ast2500_scu_ops = {
  399. .read = aspeed_scu_read,
  400. .write = aspeed_ast2500_scu_write,
  401. .endianness = DEVICE_LITTLE_ENDIAN,
  402. .impl.min_access_size = 4,
  403. .impl.max_access_size = 4,
  404. .valid.min_access_size = 1,
  405. .valid.max_access_size = 4,
  406. .valid.unaligned = false,
  407. };
  408. static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
  409. {
  410. if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN ||
  411. ASPEED_SCU_GET_CLASS(s)->clkin_25Mhz) {
  412. return 25000000;
  413. } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
  414. return 48000000;
  415. } else {
  416. return 24000000;
  417. }
  418. }
  419. /*
  420. * Strapped frequencies for the AST2400 in MHz. They depend on the
  421. * clkin frequency.
  422. */
  423. static const uint32_t hpll_ast2400_freqs[][4] = {
  424. { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
  425. { 400, 375, 350, 425 }, /* 25MHz */
  426. };
  427. static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
  428. {
  429. uint8_t freq_select;
  430. bool clk_25m_in;
  431. uint32_t clkin = aspeed_scu_get_clkin(s);
  432. if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
  433. return 0;
  434. }
  435. if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
  436. uint32_t multiplier = 1;
  437. if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
  438. uint32_t n = (hpll_reg >> 5) & 0x3f;
  439. uint32_t od = (hpll_reg >> 4) & 0x1;
  440. uint32_t d = hpll_reg & 0xf;
  441. multiplier = (2 - od) * ((n + 2) / (d + 1));
  442. }
  443. return clkin * multiplier;
  444. }
  445. /* HW strapping */
  446. clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
  447. freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
  448. return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
  449. }
  450. static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
  451. {
  452. uint32_t multiplier = 1;
  453. uint32_t clkin = aspeed_scu_get_clkin(s);
  454. if (hpll_reg & SCU_H_PLL_OFF) {
  455. return 0;
  456. }
  457. if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
  458. uint32_t p = (hpll_reg >> 13) & 0x3f;
  459. uint32_t m = (hpll_reg >> 5) & 0xff;
  460. uint32_t n = hpll_reg & 0x1f;
  461. multiplier = ((m + 1) / (n + 1)) / (p + 1);
  462. }
  463. return clkin * multiplier;
  464. }
  465. static uint32_t aspeed_2600_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll_reg)
  466. {
  467. uint32_t multiplier = 1;
  468. uint32_t clkin = aspeed_scu_get_clkin(s);
  469. if (hpll_reg & SCU_AST2600_H_PLL_OFF) {
  470. return 0;
  471. }
  472. if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) {
  473. uint32_t p = (hpll_reg >> 19) & 0xf;
  474. uint32_t n = (hpll_reg >> 13) & 0x3f;
  475. uint32_t m = hpll_reg & 0x1fff;
  476. multiplier = ((m + 1) / (n + 1)) / (p + 1);
  477. }
  478. return clkin * multiplier;
  479. }
  480. static void aspeed_scu_reset(DeviceState *dev)
  481. {
  482. AspeedSCUState *s = ASPEED_SCU(dev);
  483. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
  484. memcpy(s->regs, asc->resets, asc->nr_regs * 4);
  485. s->regs[SILICON_REV] = s->silicon_rev;
  486. s->regs[HW_STRAP1] = s->hw_strap1;
  487. s->regs[HW_STRAP2] = s->hw_strap2;
  488. s->regs[PROT_KEY] = s->hw_prot_key;
  489. }
  490. static uint32_t aspeed_silicon_revs[] = {
  491. AST2400_A0_SILICON_REV,
  492. AST2400_A1_SILICON_REV,
  493. AST2500_A0_SILICON_REV,
  494. AST2500_A1_SILICON_REV,
  495. AST2600_A0_SILICON_REV,
  496. AST2600_A1_SILICON_REV,
  497. AST2600_A2_SILICON_REV,
  498. AST2600_A3_SILICON_REV,
  499. AST1030_A0_SILICON_REV,
  500. AST1030_A1_SILICON_REV,
  501. AST2700_A0_SILICON_REV,
  502. AST2720_A0_SILICON_REV,
  503. AST2750_A0_SILICON_REV,
  504. AST2700_A1_SILICON_REV,
  505. AST2750_A1_SILICON_REV,
  506. };
  507. bool is_supported_silicon_rev(uint32_t silicon_rev)
  508. {
  509. int i;
  510. for (i = 0; i < ARRAY_SIZE(aspeed_silicon_revs); i++) {
  511. if (silicon_rev == aspeed_silicon_revs[i]) {
  512. return true;
  513. }
  514. }
  515. return false;
  516. }
  517. static void aspeed_scu_realize(DeviceState *dev, Error **errp)
  518. {
  519. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  520. AspeedSCUState *s = ASPEED_SCU(dev);
  521. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
  522. if (!is_supported_silicon_rev(s->silicon_rev)) {
  523. error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
  524. s->silicon_rev);
  525. return;
  526. }
  527. memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
  528. TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
  529. sysbus_init_mmio(sbd, &s->iomem);
  530. }
  531. static const VMStateDescription vmstate_aspeed_scu = {
  532. .name = "aspeed.scu",
  533. .version_id = 2,
  534. .minimum_version_id = 2,
  535. .fields = (const VMStateField[]) {
  536. VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
  537. VMSTATE_END_OF_LIST()
  538. }
  539. };
  540. static const Property aspeed_scu_properties[] = {
  541. DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
  542. DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
  543. DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
  544. DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
  545. };
  546. static void aspeed_scu_class_init(ObjectClass *klass, void *data)
  547. {
  548. DeviceClass *dc = DEVICE_CLASS(klass);
  549. dc->realize = aspeed_scu_realize;
  550. device_class_set_legacy_reset(dc, aspeed_scu_reset);
  551. dc->desc = "ASPEED System Control Unit";
  552. dc->vmsd = &vmstate_aspeed_scu;
  553. device_class_set_props(dc, aspeed_scu_properties);
  554. }
  555. static const TypeInfo aspeed_scu_info = {
  556. .name = TYPE_ASPEED_SCU,
  557. .parent = TYPE_SYS_BUS_DEVICE,
  558. .instance_size = sizeof(AspeedSCUState),
  559. .class_init = aspeed_scu_class_init,
  560. .class_size = sizeof(AspeedSCUClass),
  561. .abstract = true,
  562. };
  563. static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
  564. {
  565. DeviceClass *dc = DEVICE_CLASS(klass);
  566. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  567. dc->desc = "ASPEED 2400 System Control Unit";
  568. asc->resets = ast2400_a0_resets;
  569. asc->calc_hpll = aspeed_2400_scu_calc_hpll;
  570. asc->get_apb = aspeed_2400_scu_get_apb_freq;
  571. asc->apb_divider = 2;
  572. asc->nr_regs = ASPEED_SCU_NR_REGS;
  573. asc->clkin_25Mhz = false;
  574. asc->ops = &aspeed_ast2400_scu_ops;
  575. }
  576. static const TypeInfo aspeed_2400_scu_info = {
  577. .name = TYPE_ASPEED_2400_SCU,
  578. .parent = TYPE_ASPEED_SCU,
  579. .instance_size = sizeof(AspeedSCUState),
  580. .class_init = aspeed_2400_scu_class_init,
  581. };
  582. static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
  583. {
  584. DeviceClass *dc = DEVICE_CLASS(klass);
  585. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  586. dc->desc = "ASPEED 2500 System Control Unit";
  587. asc->resets = ast2500_a1_resets;
  588. asc->calc_hpll = aspeed_2500_scu_calc_hpll;
  589. asc->get_apb = aspeed_2400_scu_get_apb_freq;
  590. asc->apb_divider = 4;
  591. asc->nr_regs = ASPEED_SCU_NR_REGS;
  592. asc->clkin_25Mhz = false;
  593. asc->ops = &aspeed_ast2500_scu_ops;
  594. }
  595. static const TypeInfo aspeed_2500_scu_info = {
  596. .name = TYPE_ASPEED_2500_SCU,
  597. .parent = TYPE_ASPEED_SCU,
  598. .instance_size = sizeof(AspeedSCUState),
  599. .class_init = aspeed_2500_scu_class_init,
  600. };
  601. static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
  602. unsigned size)
  603. {
  604. AspeedSCUState *s = ASPEED_SCU(opaque);
  605. int reg = TO_REG(offset);
  606. if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
  607. qemu_log_mask(LOG_GUEST_ERROR,
  608. "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
  609. __func__, offset);
  610. return 0;
  611. }
  612. switch (reg) {
  613. case AST2600_HPLL_EXT:
  614. case AST2600_EPLL_EXT:
  615. case AST2600_MPLL_EXT:
  616. /* PLLs are always "locked" */
  617. return s->regs[reg] | BIT(31);
  618. case AST2600_RNG_DATA:
  619. /*
  620. * On hardware, RNG_DATA works regardless of the state of the
  621. * enable bit in RNG_CTRL
  622. *
  623. * TODO: Check this is true for ast2600
  624. */
  625. s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
  626. break;
  627. }
  628. trace_aspeed_scu_read(offset, size, s->regs[reg]);
  629. return s->regs[reg];
  630. }
  631. static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
  632. uint64_t data64, unsigned size)
  633. {
  634. AspeedSCUState *s = ASPEED_SCU(opaque);
  635. int reg = TO_REG(offset);
  636. /* Truncate here so bitwise operations below behave as expected */
  637. uint32_t data = data64;
  638. if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
  639. qemu_log_mask(LOG_GUEST_ERROR,
  640. "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
  641. __func__, offset);
  642. return;
  643. }
  644. if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
  645. qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
  646. }
  647. trace_aspeed_scu_write(offset, size, data);
  648. switch (reg) {
  649. case AST2600_PROT_KEY:
  650. s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
  651. return;
  652. case AST2600_HW_STRAP1:
  653. case AST2600_HW_STRAP2:
  654. if (s->regs[reg + 2]) {
  655. return;
  656. }
  657. /* fall through */
  658. case AST2600_SYS_RST_CTRL:
  659. case AST2600_SYS_RST_CTRL2:
  660. case AST2600_CLK_STOP_CTRL:
  661. case AST2600_CLK_STOP_CTRL2:
  662. /* W1S (Write 1 to set) registers */
  663. s->regs[reg] |= data;
  664. return;
  665. case AST2600_SYS_RST_CTRL_CLR:
  666. case AST2600_SYS_RST_CTRL2_CLR:
  667. case AST2600_CLK_STOP_CTRL_CLR:
  668. case AST2600_CLK_STOP_CTRL2_CLR:
  669. case AST2600_HW_STRAP1_CLR:
  670. case AST2600_HW_STRAP2_CLR:
  671. /*
  672. * W1C (Write 1 to clear) registers are offset by one address from
  673. * the data register
  674. */
  675. s->regs[reg - 1] &= ~data;
  676. return;
  677. case AST2600_RNG_DATA:
  678. case AST2600_SILICON_REV:
  679. case AST2600_SILICON_REV2:
  680. case AST2600_CHIP_ID0:
  681. case AST2600_CHIP_ID1:
  682. /* Add read only registers here */
  683. qemu_log_mask(LOG_GUEST_ERROR,
  684. "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
  685. __func__, offset);
  686. return;
  687. }
  688. s->regs[reg] = data;
  689. }
  690. static const MemoryRegionOps aspeed_ast2600_scu_ops = {
  691. .read = aspeed_ast2600_scu_read,
  692. .write = aspeed_ast2600_scu_write,
  693. .endianness = DEVICE_LITTLE_ENDIAN,
  694. .impl.min_access_size = 4,
  695. .impl.max_access_size = 4,
  696. .valid.min_access_size = 1,
  697. .valid.max_access_size = 4,
  698. .valid.unaligned = false,
  699. };
  700. static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
  701. [AST2600_SYS_RST_CTRL] = 0xF7C3FED8,
  702. [AST2600_SYS_RST_CTRL2] = 0x0DFFFFFC,
  703. [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
  704. [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
  705. [AST2600_DEBUG_CTRL] = 0x00000FFF,
  706. [AST2600_DEBUG_CTRL2] = 0x000000FF,
  707. [AST2600_SDRAM_HANDSHAKE] = 0x00000000,
  708. [AST2600_HPLL_PARAM] = 0x1000408F,
  709. [AST2600_APLL_PARAM] = 0x1000405F,
  710. [AST2600_MPLL_PARAM] = 0x1008405F,
  711. [AST2600_EPLL_PARAM] = 0x1004077F,
  712. [AST2600_DPLL_PARAM] = 0x1078405F,
  713. [AST2600_CLK_SEL] = 0xF3940000,
  714. [AST2600_CLK_SEL2] = 0x00700000,
  715. [AST2600_CLK_SEL3] = 0x00000000,
  716. [AST2600_CLK_SEL4] = 0xF3F40000,
  717. [AST2600_CLK_SEL5] = 0x30000000,
  718. [AST2600_UARTCLK] = 0x00014506,
  719. [AST2600_HUARTCLK] = 0x000145C0,
  720. [AST2600_CHIP_ID0] = 0x1234ABCD,
  721. [AST2600_CHIP_ID1] = 0x88884444,
  722. };
  723. static void aspeed_ast2600_scu_reset(DeviceState *dev)
  724. {
  725. AspeedSCUState *s = ASPEED_SCU(dev);
  726. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
  727. memcpy(s->regs, asc->resets, asc->nr_regs * 4);
  728. /*
  729. * A0 reports A0 in _REV, but subsequent revisions report A1 regardless
  730. * of actual revision. QEMU and Linux only support A1 onwards so this is
  731. * sufficient.
  732. */
  733. s->regs[AST2600_SILICON_REV] = AST2600_A3_SILICON_REV;
  734. s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
  735. s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
  736. s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
  737. s->regs[PROT_KEY] = s->hw_prot_key;
  738. }
  739. static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
  740. {
  741. DeviceClass *dc = DEVICE_CLASS(klass);
  742. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  743. dc->desc = "ASPEED 2600 System Control Unit";
  744. device_class_set_legacy_reset(dc, aspeed_ast2600_scu_reset);
  745. asc->resets = ast2600_a3_resets;
  746. asc->calc_hpll = aspeed_2600_scu_calc_hpll;
  747. asc->get_apb = aspeed_2600_scu_get_apb_freq;
  748. asc->apb_divider = 4;
  749. asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
  750. asc->clkin_25Mhz = true;
  751. asc->ops = &aspeed_ast2600_scu_ops;
  752. }
  753. static const TypeInfo aspeed_2600_scu_info = {
  754. .name = TYPE_ASPEED_2600_SCU,
  755. .parent = TYPE_ASPEED_SCU,
  756. .instance_size = sizeof(AspeedSCUState),
  757. .class_init = aspeed_2600_scu_class_init,
  758. };
  759. static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset,
  760. unsigned size)
  761. {
  762. AspeedSCUState *s = ASPEED_SCU(opaque);
  763. int reg = TO_REG(offset);
  764. if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
  765. qemu_log_mask(LOG_GUEST_ERROR,
  766. "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
  767. __func__, offset);
  768. return 0;
  769. }
  770. switch (reg) {
  771. default:
  772. qemu_log_mask(LOG_GUEST_ERROR,
  773. "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
  774. __func__, offset);
  775. }
  776. trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]);
  777. return s->regs[reg];
  778. }
  779. static void aspeed_ast2700_scu_write(void *opaque, hwaddr offset,
  780. uint64_t data64, unsigned size)
  781. {
  782. AspeedSCUState *s = ASPEED_SCU(opaque);
  783. int reg = TO_REG(offset);
  784. /* Truncate here so bitwise operations below behave as expected */
  785. uint32_t data = data64;
  786. if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
  787. qemu_log_mask(LOG_GUEST_ERROR,
  788. "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
  789. __func__, offset);
  790. return;
  791. }
  792. trace_aspeed_ast2700_scu_write(offset, size, data);
  793. switch (reg) {
  794. default:
  795. qemu_log_mask(LOG_GUEST_ERROR,
  796. "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
  797. __func__, offset);
  798. break;
  799. }
  800. s->regs[reg] = data;
  801. }
  802. static const MemoryRegionOps aspeed_ast2700_scu_ops = {
  803. .read = aspeed_ast2700_scu_read,
  804. .write = aspeed_ast2700_scu_write,
  805. .endianness = DEVICE_LITTLE_ENDIAN,
  806. .impl.min_access_size = 4,
  807. .impl.max_access_size = 4,
  808. .valid.min_access_size = 1,
  809. .valid.max_access_size = 8,
  810. .valid.unaligned = false,
  811. };
  812. static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
  813. [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
  814. [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
  815. [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
  816. [AST2700_HW_STRAP1_SEC2] = 0x00000000,
  817. [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
  818. [AST2700_SCU_HPLL_PARAM] = 0x0000009f,
  819. [AST2700_SCU_HPLL_EXT_PARAM] = 0x8000004f,
  820. [AST2700_SCU_DPLL_PARAM] = 0x0080009f,
  821. [AST2700_SCU_DPLL_EXT_PARAM] = 0x8000004f,
  822. [AST2700_SCU_MPLL_PARAM] = 0x00000040,
  823. [AST2700_SCU_MPLL_EXT_PARAM] = 0x80000000,
  824. [AST2700_SCU_D1CLK_PARAM] = 0x00050002,
  825. [AST2700_SCU_D2CLK_PARAM] = 0x00050002,
  826. [AST2700_SCU_CRT1CLK_PARAM] = 0x00050002,
  827. [AST2700_SCU_CRT2CLK_PARAM] = 0x00050002,
  828. [AST2700_SCU_MPHYCLK_PARAM] = 0x0000004c,
  829. [AST2700_SCU_FREQ_CNTR] = 0x000375eb,
  830. [AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
  831. [AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
  832. [AST2700_SCU_VGA_SCRATCH_0] = 0x00000040,
  833. };
  834. static void aspeed_ast2700_scu_reset(DeviceState *dev)
  835. {
  836. AspeedSCUState *s = ASPEED_SCU(dev);
  837. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
  838. memcpy(s->regs, asc->resets, asc->nr_regs * 4);
  839. s->regs[AST2700_SILICON_REV] = s->silicon_rev;
  840. s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
  841. }
  842. static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
  843. {
  844. DeviceClass *dc = DEVICE_CLASS(klass);
  845. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  846. dc->desc = "ASPEED 2700 System Control Unit";
  847. device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
  848. asc->resets = ast2700_a0_resets;
  849. asc->calc_hpll = aspeed_2600_scu_calc_hpll;
  850. asc->get_apb = aspeed_2700_scu_get_apb_freq;
  851. asc->apb_divider = 4;
  852. asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
  853. asc->clkin_25Mhz = true;
  854. asc->ops = &aspeed_ast2700_scu_ops;
  855. }
  856. static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset,
  857. unsigned size)
  858. {
  859. AspeedSCUState *s = ASPEED_SCU(opaque);
  860. int reg = TO_REG(offset);
  861. if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
  862. qemu_log_mask(LOG_GUEST_ERROR,
  863. "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
  864. __func__, offset);
  865. return 0;
  866. }
  867. switch (reg) {
  868. default:
  869. qemu_log_mask(LOG_GUEST_ERROR,
  870. "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n",
  871. __func__, offset);
  872. }
  873. trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]);
  874. return s->regs[reg];
  875. }
  876. static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
  877. uint64_t data64, unsigned size)
  878. {
  879. AspeedSCUState *s = ASPEED_SCU(opaque);
  880. int reg = TO_REG(offset);
  881. /* Truncate here so bitwise operations below behave as expected */
  882. uint32_t data = data64;
  883. bool updated = false;
  884. if (reg >= ASPEED_AST2700_SCU_NR_REGS) {
  885. qemu_log_mask(LOG_GUEST_ERROR,
  886. "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
  887. __func__, offset);
  888. return;
  889. }
  890. trace_aspeed_ast2700_scuio_write(offset, size, data);
  891. switch (reg) {
  892. case AST2700_SCUIO_CLK_STOP_CTL_1:
  893. case AST2700_SCUIO_CLK_STOP_CTL_2:
  894. s->regs[reg] |= data;
  895. updated = true;
  896. break;
  897. case AST2700_SCUIO_CLK_STOP_CLR_1:
  898. case AST2700_SCUIO_CLK_STOP_CLR_2:
  899. s->regs[reg - 1] ^= data;
  900. updated = true;
  901. break;
  902. default:
  903. qemu_log_mask(LOG_GUEST_ERROR,
  904. "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
  905. __func__, offset);
  906. break;
  907. }
  908. if (!updated) {
  909. s->regs[reg] = data;
  910. }
  911. }
  912. static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
  913. .read = aspeed_ast2700_scuio_read,
  914. .write = aspeed_ast2700_scuio_write,
  915. .endianness = DEVICE_LITTLE_ENDIAN,
  916. .impl.min_access_size = 4,
  917. .impl.max_access_size = 4,
  918. .valid.min_access_size = 1,
  919. .valid.max_access_size = 8,
  920. .valid.unaligned = false,
  921. };
  922. static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
  923. [AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
  924. [AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
  925. [AST2700_HW_STRAP1_SEC1] = 0x000000FF,
  926. [AST2700_HW_STRAP1_SEC2] = 0x00000000,
  927. [AST2700_HW_STRAP1_SEC3] = 0x1000408F,
  928. [AST2700_SCUIO_CLK_STOP_CTL_1] = 0xffff8400,
  929. [AST2700_SCUIO_CLK_STOP_CTL_2] = 0x00005f30,
  930. [AST2700_SCUIO_CLK_SEL_1] = 0x86900000,
  931. [AST2700_SCUIO_CLK_SEL_2] = 0x00400000,
  932. [AST2700_SCUIO_HPLL_PARAM] = 0x10000027,
  933. [AST2700_SCUIO_HPLL_EXT_PARAM] = 0x80000014,
  934. [AST2700_SCUIO_APLL_PARAM] = 0x1000001f,
  935. [AST2700_SCUIO_APLL_EXT_PARAM] = 0x8000000f,
  936. [AST2700_SCUIO_DPLL_PARAM] = 0x106e42ce,
  937. [AST2700_SCUIO_DPLL_EXT_PARAM] = 0x80000167,
  938. [AST2700_SCUIO_DPLL_PARAM_READ] = 0x106e42ce,
  939. [AST2700_SCUIO_DPLL_EXT_PARAM_READ] = 0x80000167,
  940. [AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
  941. [AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
  942. [AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
  943. };
  944. static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
  945. {
  946. DeviceClass *dc = DEVICE_CLASS(klass);
  947. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  948. dc->desc = "ASPEED 2700 System Control Unit I/O";
  949. device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
  950. asc->resets = ast2700_a0_resets_io;
  951. asc->calc_hpll = aspeed_2600_scu_calc_hpll;
  952. asc->get_apb = aspeed_2700_scuio_get_apb_freq;
  953. asc->apb_divider = 2;
  954. asc->nr_regs = ASPEED_AST2700_SCU_NR_REGS;
  955. asc->clkin_25Mhz = true;
  956. asc->ops = &aspeed_ast2700_scuio_ops;
  957. }
  958. static const TypeInfo aspeed_2700_scu_info = {
  959. .name = TYPE_ASPEED_2700_SCU,
  960. .parent = TYPE_ASPEED_SCU,
  961. .instance_size = sizeof(AspeedSCUState),
  962. .class_init = aspeed_2700_scu_class_init,
  963. };
  964. static const TypeInfo aspeed_2700_scuio_info = {
  965. .name = TYPE_ASPEED_2700_SCUIO,
  966. .parent = TYPE_ASPEED_SCU,
  967. .instance_size = sizeof(AspeedSCUState),
  968. .class_init = aspeed_2700_scuio_class_init,
  969. };
  970. static const uint32_t ast1030_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
  971. [AST2600_SYS_RST_CTRL] = 0xFFC3FED8,
  972. [AST2600_SYS_RST_CTRL2] = 0x09FFFFFC,
  973. [AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
  974. [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
  975. [AST2600_DEBUG_CTRL2] = 0x00000000,
  976. [AST2600_HPLL_PARAM] = 0x10004077,
  977. [AST2600_HPLL_EXT] = 0x00000031,
  978. [AST2600_CLK_SEL4] = 0x43F90900,
  979. [AST2600_CLK_SEL5] = 0x40000000,
  980. [AST2600_CHIP_ID0] = 0xDEADBEEF,
  981. [AST2600_CHIP_ID1] = 0x0BADCAFE,
  982. };
  983. static void aspeed_ast1030_scu_reset(DeviceState *dev)
  984. {
  985. AspeedSCUState *s = ASPEED_SCU(dev);
  986. AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
  987. memcpy(s->regs, asc->resets, asc->nr_regs * 4);
  988. s->regs[AST2600_SILICON_REV] = AST1030_A1_SILICON_REV;
  989. s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
  990. s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
  991. s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
  992. s->regs[PROT_KEY] = s->hw_prot_key;
  993. }
  994. static void aspeed_1030_scu_class_init(ObjectClass *klass, void *data)
  995. {
  996. DeviceClass *dc = DEVICE_CLASS(klass);
  997. AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
  998. dc->desc = "ASPEED 1030 System Control Unit";
  999. device_class_set_legacy_reset(dc, aspeed_ast1030_scu_reset);
  1000. asc->resets = ast1030_a1_resets;
  1001. asc->calc_hpll = aspeed_2600_scu_calc_hpll;
  1002. asc->get_apb = aspeed_1030_scu_get_apb_freq;
  1003. asc->apb_divider = 2;
  1004. asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
  1005. asc->clkin_25Mhz = true;
  1006. asc->ops = &aspeed_ast2600_scu_ops;
  1007. }
  1008. static const TypeInfo aspeed_1030_scu_info = {
  1009. .name = TYPE_ASPEED_1030_SCU,
  1010. .parent = TYPE_ASPEED_SCU,
  1011. .instance_size = sizeof(AspeedSCUState),
  1012. .class_init = aspeed_1030_scu_class_init,
  1013. };
  1014. static void aspeed_scu_register_types(void)
  1015. {
  1016. type_register_static(&aspeed_scu_info);
  1017. type_register_static(&aspeed_2400_scu_info);
  1018. type_register_static(&aspeed_2500_scu_info);
  1019. type_register_static(&aspeed_2600_scu_info);
  1020. type_register_static(&aspeed_1030_scu_info);
  1021. type_register_static(&aspeed_2700_scu_info);
  1022. type_register_static(&aspeed_2700_scuio_info);
  1023. }
  1024. type_init(aspeed_scu_register_types);