hsdk.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
  4. * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
  5. */
  6. #include <common.h>
  7. #include <config.h>
  8. #include <cpu_func.h>
  9. #include <env.h>
  10. #include <linux/printk.h>
  11. #include <linux/kernel.h>
  12. #include <linux/io.h>
  13. #include <asm/arcregs.h>
  14. #include <fdt_support.h>
  15. #include <dwmmc.h>
  16. #include <malloc.h>
  17. #include <usb.h>
  18. #include "clk-lib.h"
  19. #include "env-lib.h"
  20. DECLARE_GLOBAL_DATA_PTR;
  21. #define ALL_CPU_MASK GENMASK(NR_CPUS - 1, 0)
  22. #define MASTER_CPU_ID 0
  23. #define APERTURE_SHIFT 28
  24. #define NO_CCM 0x10
  25. #define SLAVE_CPU_READY 0x12345678
  26. #define BOOTSTAGE_1 1 /* after SP, FP setup, before HW init */
  27. #define BOOTSTAGE_2 2 /* after HW init, before self halt */
  28. #define BOOTSTAGE_3 3 /* after self halt */
  29. #define BOOTSTAGE_4 4 /* before app launch */
  30. #define BOOTSTAGE_5 5 /* after app launch, unreachable */
  31. #define RESET_VECTOR_ADDR 0x0
  32. #define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
  33. #define CREG_CPU_START (CREG_BASE + 0x400)
  34. #define CREG_CPU_START_MASK 0xF
  35. #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000)
  36. #define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108)
  37. #define SDIO_UHS_REG_EXT_DIV_2 (2 << 30)
  38. /* Uncached access macros */
  39. #define arc_read_uncached_32(ptr) \
  40. ({ \
  41. unsigned int __ret; \
  42. __asm__ __volatile__( \
  43. " ld.di %0, [%1] \n" \
  44. : "=r"(__ret) \
  45. : "r"(ptr)); \
  46. __ret; \
  47. })
  48. #define arc_write_uncached_32(ptr, data)\
  49. ({ \
  50. __asm__ __volatile__( \
  51. " st.di %0, [%1] \n" \
  52. : \
  53. : "r"(data), "r"(ptr)); \
  54. })
  55. struct hsdk_env_core_ctl {
  56. u32_env entry[NR_CPUS];
  57. u32_env iccm[NR_CPUS];
  58. u32_env dccm[NR_CPUS];
  59. };
  60. struct hsdk_env_common_ctl {
  61. bool halt_on_boot;
  62. u32_env core_mask;
  63. u32_env cpu_freq;
  64. u32_env axi_freq;
  65. u32_env tun_freq;
  66. u32_env nvlim;
  67. u32_env icache;
  68. u32_env dcache;
  69. };
  70. /*
  71. * Uncached cross-cpu structure. All CPUs must access to this structure fields
  72. * only with arc_read_uncached_32() / arc_write_uncached_32() accessors (which
  73. * implement ld.di / st.di instructions). Simultaneous cached and uncached
  74. * access to this area will lead to data loss.
  75. * We flush all data caches in board_early_init_r() as we don't want to have
  76. * any dirty line in L1d$ or SL$ in this area.
  77. */
  78. struct hsdk_cross_cpu {
  79. /* slave CPU ready flag */
  80. u32 ready_flag;
  81. /* address of the area, which can be used for stack by slave CPU */
  82. u32 stack_ptr;
  83. /* slave CPU status - bootstage number */
  84. s32 status[NR_CPUS];
  85. /*
  86. * Slave CPU data - it is copy of corresponding fields in
  87. * hsdk_env_core_ctl and hsdk_env_common_ctl structures which are
  88. * required for slave CPUs initialization.
  89. * This fields can be populated by copying from hsdk_env_core_ctl
  90. * and hsdk_env_common_ctl structures with sync_cross_cpu_data()
  91. * function.
  92. */
  93. u32 entry[NR_CPUS];
  94. u32 iccm[NR_CPUS];
  95. u32 dccm[NR_CPUS];
  96. u32 core_mask;
  97. u32 icache;
  98. u32 dcache;
  99. u8 cache_padding[ARCH_DMA_MINALIGN];
  100. } __aligned(ARCH_DMA_MINALIGN);
  101. /* Place for slave CPUs temporary stack */
  102. static u32 slave_stack[256 * NR_CPUS] __aligned(ARCH_DMA_MINALIGN);
  103. static struct hsdk_env_common_ctl env_common = {};
  104. static struct hsdk_env_core_ctl env_core = {};
  105. static struct hsdk_cross_cpu cross_cpu_data;
  106. static const struct env_map_common env_map_common[] = {
  107. { "core_mask", ENV_HEX, true, 0x1, 0xF, &env_common.core_mask },
  108. { "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim },
  109. { "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache },
  110. { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache },
  111. {}
  112. };
  113. static const struct env_map_common env_map_clock[] = {
  114. { "cpu_freq", ENV_DEC, false, 100, 1000, &env_common.cpu_freq },
  115. { "axi_freq", ENV_DEC, false, 200, 800, &env_common.axi_freq },
  116. { "tun_freq", ENV_DEC, false, 0, 150, &env_common.tun_freq },
  117. {}
  118. };
  119. static const struct env_map_percpu env_map_core[] = {
  120. { "core_iccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.iccm },
  121. { "core_dccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.dccm },
  122. {}
  123. };
  124. static const struct env_map_common env_map_mask[] = {
  125. { "core_mask", ENV_HEX, false, 0x1, 0xF, &env_common.core_mask },
  126. {}
  127. };
  128. static const struct env_map_percpu env_map_go[] = {
  129. { "core_entry", ENV_HEX, true, {0, 0, 0, 0}, {U32_MAX, U32_MAX, U32_MAX, U32_MAX}, &env_core.entry },
  130. {}
  131. };
  132. static void sync_cross_cpu_data(void)
  133. {
  134. u32 value;
  135. for (u32 i = 0; i < NR_CPUS; i++) {
  136. value = env_core.entry[i].val;
  137. arc_write_uncached_32(&cross_cpu_data.entry[i], value);
  138. }
  139. for (u32 i = 0; i < NR_CPUS; i++) {
  140. value = env_core.iccm[i].val;
  141. arc_write_uncached_32(&cross_cpu_data.iccm[i], value);
  142. }
  143. for (u32 i = 0; i < NR_CPUS; i++) {
  144. value = env_core.dccm[i].val;
  145. arc_write_uncached_32(&cross_cpu_data.dccm[i], value);
  146. }
  147. value = env_common.core_mask.val;
  148. arc_write_uncached_32(&cross_cpu_data.core_mask, value);
  149. value = env_common.icache.val;
  150. arc_write_uncached_32(&cross_cpu_data.icache, value);
  151. value = env_common.dcache.val;
  152. arc_write_uncached_32(&cross_cpu_data.dcache, value);
  153. }
  154. /* Can be used only on master CPU */
  155. static bool is_cpu_used(u32 cpu_id)
  156. {
  157. return !!(env_common.core_mask.val & BIT(cpu_id));
  158. }
  159. /* TODO: add ICCM BCR and DCCM BCR runtime check */
  160. static void init_slave_cpu_func(u32 core)
  161. {
  162. u32 val;
  163. /* Remap ICCM to another memory region if it exists */
  164. val = arc_read_uncached_32(&cross_cpu_data.iccm[core]);
  165. if (val != NO_CCM)
  166. write_aux_reg(ARC_AUX_ICCM_BASE, val << APERTURE_SHIFT);
  167. /* Remap DCCM to another memory region if it exists */
  168. val = arc_read_uncached_32(&cross_cpu_data.dccm[core]);
  169. if (val != NO_CCM)
  170. write_aux_reg(ARC_AUX_DCCM_BASE, val << APERTURE_SHIFT);
  171. if (arc_read_uncached_32(&cross_cpu_data.icache))
  172. icache_enable();
  173. else
  174. icache_disable();
  175. if (arc_read_uncached_32(&cross_cpu_data.dcache))
  176. dcache_enable();
  177. else
  178. dcache_disable();
  179. }
  180. static void init_cluster_nvlim(void)
  181. {
  182. u32 val = env_common.nvlim.val << APERTURE_SHIFT;
  183. flush_dcache_all();
  184. write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val);
  185. write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
  186. flush_n_invalidate_dcache_all();
  187. }
  188. static void init_master_icache(void)
  189. {
  190. if (icache_status()) {
  191. /* I$ is enabled - we need to disable it */
  192. if (!env_common.icache.val)
  193. icache_disable();
  194. } else {
  195. /* I$ is disabled - we need to enable it */
  196. if (env_common.icache.val) {
  197. icache_enable();
  198. /* invalidate I$ right after enable */
  199. invalidate_icache_all();
  200. }
  201. }
  202. }
  203. static void init_master_dcache(void)
  204. {
  205. if (dcache_status()) {
  206. /* D$ is enabled - we need to disable it */
  207. if (!env_common.dcache.val)
  208. dcache_disable();
  209. } else {
  210. /* D$ is disabled - we need to enable it */
  211. if (env_common.dcache.val)
  212. dcache_enable();
  213. /* TODO: probably we need ti invalidate D$ right after enable */
  214. }
  215. }
  216. static int cleanup_before_go(void)
  217. {
  218. disable_interrupts();
  219. sync_n_cleanup_cache_all();
  220. return 0;
  221. }
  222. void slave_cpu_set_boot_addr(u32 addr)
  223. {
  224. /* All cores have reset vector pointing to 0 */
  225. writel(addr, (void __iomem *)RESET_VECTOR_ADDR);
  226. /* Make sure other cores see written value in memory */
  227. sync_n_cleanup_cache_all();
  228. }
  229. static inline void halt_this_cpu(void)
  230. {
  231. __builtin_arc_flag(1);
  232. }
  233. static void smp_kick_cpu_x(u32 cpu_id)
  234. {
  235. int cmd = readl((void __iomem *)CREG_CPU_START);
  236. if (cpu_id > NR_CPUS)
  237. return;
  238. cmd &= ~CREG_CPU_START_MASK;
  239. cmd |= (1 << cpu_id);
  240. writel(cmd, (void __iomem *)CREG_CPU_START);
  241. }
  242. static u32 prepare_cpu_ctart_reg(void)
  243. {
  244. int cmd = readl((void __iomem *)CREG_CPU_START);
  245. cmd &= ~CREG_CPU_START_MASK;
  246. return cmd | env_common.core_mask.val;
  247. }
  248. /* slave CPU entry for configuration */
  249. __attribute__((naked, noreturn, flatten)) noinline void hsdk_core_init_f(void)
  250. {
  251. __asm__ __volatile__(
  252. "ld.di r8, [%0]\n"
  253. "mov %%sp, r8\n"
  254. "mov %%fp, %%sp\n"
  255. : /* no output */
  256. : "r" (&cross_cpu_data.stack_ptr));
  257. invalidate_icache_all();
  258. arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_1);
  259. init_slave_cpu_func(CPU_ID_GET());
  260. arc_write_uncached_32(&cross_cpu_data.ready_flag, SLAVE_CPU_READY);
  261. arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_2);
  262. /* Halt the processor until the master kick us again */
  263. halt_this_cpu();
  264. /*
  265. * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
  266. * cores but we leave them for gebug purposes.
  267. */
  268. __builtin_arc_nop();
  269. __builtin_arc_nop();
  270. __builtin_arc_nop();
  271. arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_3);
  272. /* get the updated entry - invalidate i$ */
  273. invalidate_icache_all();
  274. arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_4);
  275. /* Run our program */
  276. ((void (*)(void))(arc_read_uncached_32(&cross_cpu_data.entry[CPU_ID_GET()])))();
  277. /* This bootstage is unreachable as we don't return from app we launch */
  278. arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_5);
  279. /* Something went terribly wrong */
  280. while (true)
  281. halt_this_cpu();
  282. }
  283. static void clear_cross_cpu_data(void)
  284. {
  285. arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
  286. arc_write_uncached_32(&cross_cpu_data.stack_ptr, 0);
  287. for (u32 i = 0; i < NR_CPUS; i++)
  288. arc_write_uncached_32(&cross_cpu_data.status[i], 0);
  289. }
  290. static noinline void do_init_slave_cpu(u32 cpu_id)
  291. {
  292. /* attempts number for check clave CPU ready_flag */
  293. u32 attempts = 100;
  294. u32 stack_ptr = (u32)(slave_stack + (64 * cpu_id));
  295. if (cpu_id >= NR_CPUS)
  296. return;
  297. arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
  298. /* Use global unique place for each slave cpu stack */
  299. arc_write_uncached_32(&cross_cpu_data.stack_ptr, stack_ptr);
  300. debug("CPU %u: stack pool base: %p\n", cpu_id, slave_stack);
  301. debug("CPU %u: current slave stack base: %x\n", cpu_id, stack_ptr);
  302. slave_cpu_set_boot_addr((u32)hsdk_core_init_f);
  303. smp_kick_cpu_x(cpu_id);
  304. debug("CPU %u: cross-cpu flag: %x [before timeout]\n", cpu_id,
  305. arc_read_uncached_32(&cross_cpu_data.ready_flag));
  306. while (!arc_read_uncached_32(&cross_cpu_data.ready_flag) && attempts--)
  307. mdelay(10);
  308. /* Just to be sure that slave cpu is halted after it set ready_flag */
  309. mdelay(20);
  310. /*
  311. * Only print error here if we reach timeout as there is no option to
  312. * halt slave cpu (or check that slave cpu is halted)
  313. */
  314. if (!attempts)
  315. pr_err("CPU %u is not responding after init!\n", cpu_id);
  316. /* Check current stage of slave cpu */
  317. if (arc_read_uncached_32(&cross_cpu_data.status[cpu_id]) != BOOTSTAGE_2)
  318. pr_err("CPU %u status is unexpected: %d\n", cpu_id,
  319. arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
  320. debug("CPU %u: cross-cpu flag: %x [after timeout]\n", cpu_id,
  321. arc_read_uncached_32(&cross_cpu_data.ready_flag));
  322. debug("CPU %u: status: %d [after timeout]\n", cpu_id,
  323. arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
  324. }
  325. static void do_init_slave_cpus(void)
  326. {
  327. clear_cross_cpu_data();
  328. sync_cross_cpu_data();
  329. debug("cross_cpu_data location: %#x\n", (u32)&cross_cpu_data);
  330. for (u32 i = MASTER_CPU_ID + 1; i < NR_CPUS; i++)
  331. if (is_cpu_used(i))
  332. do_init_slave_cpu(i);
  333. }
  334. static void do_init_master_cpu(void)
  335. {
  336. /*
  337. * Setup master caches even if master isn't used as we want to use
  338. * same cache configuration on all running CPUs
  339. */
  340. init_master_icache();
  341. init_master_dcache();
  342. }
  343. enum hsdk_axi_masters {
  344. M_HS_CORE = 0,
  345. M_HS_RTT,
  346. M_AXI_TUN,
  347. M_HDMI_VIDEO,
  348. M_HDMI_AUDIO,
  349. M_USB_HOST,
  350. M_ETHERNET,
  351. M_SDIO,
  352. M_GPU,
  353. M_DMAC_0,
  354. M_DMAC_1,
  355. M_DVFS
  356. };
  357. #define UPDATE_VAL 1
  358. /*
  359. * m master AXI_M_m_SLV0 AXI_M_m_SLV1 AXI_M_m_OFFSET0 AXI_M_m_OFFSET1
  360. * 0 HS (CBU) 0x11111111 0x63111111 0xFEDCBA98 0x0E543210
  361. * 1 HS (RTT) 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  362. * 2 AXI Tunnel 0x88888888 0x88888888 0xFEDCBA98 0x76543210
  363. * 3 HDMI-VIDEO 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  364. * 4 HDMI-ADUIO 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  365. * 5 USB-HOST 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98
  366. * 6 ETHERNET 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98
  367. * 7 SDIO 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98
  368. * 8 GPU 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  369. * 9 DMAC (port #1) 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  370. * 10 DMAC (port #2) 0x77777777 0x77777777 0xFEDCBA98 0x76543210
  371. * 11 DVFS 0x00000000 0x60000000 0x00000000 0x00000000
  372. *
  373. * Please read ARC HS Development IC Specification, section 17.2 for more
  374. * information about apertures configuration.
  375. * NOTE: we intentionally modify default settings in U-boot. Default settings
  376. * are specified in "Table 111 CREG Address Decoder register reset values".
  377. */
  378. #define CREG_AXI_M_SLV0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m)))
  379. #define CREG_AXI_M_SLV1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x004))
  380. #define CREG_AXI_M_OFT0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x008))
  381. #define CREG_AXI_M_OFT1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x00C))
  382. #define CREG_AXI_M_UPDT(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x014))
  383. #define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010))
  384. #define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180))
  385. #define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194))
  386. void init_memory_bridge(void)
  387. {
  388. u32 reg;
  389. /*
  390. * M_HS_CORE has one unic register - BOOT.
  391. * We need to clean boot mirror (BOOT[1:0]) bits in them.
  392. */
  393. reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3);
  394. writel(reg, CREG_AXI_M_HS_CORE_BOOT);
  395. writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE));
  396. writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
  397. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE));
  398. writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
  399. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
  400. writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT));
  401. writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT));
  402. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT));
  403. writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT));
  404. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT));
  405. writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN));
  406. writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN));
  407. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN));
  408. writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN));
  409. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN));
  410. writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO));
  411. writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO));
  412. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO));
  413. writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO));
  414. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO));
  415. writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO));
  416. writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO));
  417. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO));
  418. writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO));
  419. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO));
  420. writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST));
  421. writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST));
  422. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST));
  423. writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST));
  424. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
  425. writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET));
  426. writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET));
  427. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET));
  428. writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET));
  429. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
  430. writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO));
  431. writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO));
  432. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO));
  433. writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO));
  434. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
  435. writel(0x77777777, CREG_AXI_M_SLV0(M_GPU));
  436. writel(0x77777777, CREG_AXI_M_SLV1(M_GPU));
  437. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU));
  438. writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
  439. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
  440. writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
  441. writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
  442. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
  443. writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
  444. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
  445. writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
  446. writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
  447. writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
  448. writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
  449. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
  450. writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
  451. writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
  452. writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
  453. writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
  454. writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
  455. writel(0x00000000, CREG_PAE);
  456. writel(UPDATE_VAL, CREG_PAE_UPDT);
  457. }
  458. static void setup_clocks(void)
  459. {
  460. ulong rate;
  461. /* Setup CPU clock */
  462. if (env_common.cpu_freq.set) {
  463. rate = env_common.cpu_freq.val;
  464. soc_clk_ctl("cpu-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
  465. }
  466. /* Setup TUN clock */
  467. if (env_common.tun_freq.set) {
  468. rate = env_common.tun_freq.val;
  469. if (rate)
  470. soc_clk_ctl("tun-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
  471. else
  472. soc_clk_ctl("tun-clk", NULL, CLK_OFF);
  473. }
  474. if (env_common.axi_freq.set) {
  475. rate = env_common.axi_freq.val;
  476. soc_clk_ctl("axi-clk", &rate, CLK_SET | CLK_ON | CLK_MHZ);
  477. }
  478. }
  479. static void do_init_cluster(void)
  480. {
  481. /*
  482. * A multi-core ARC HS configuration always includes only one
  483. * ARC_AUX_NON_VOLATILE_LIMIT register, which is shared by all the
  484. * cores.
  485. */
  486. init_cluster_nvlim();
  487. }
  488. static int check_master_cpu_id(void)
  489. {
  490. if (CPU_ID_GET() == MASTER_CPU_ID)
  491. return 0;
  492. pr_err("u-boot runs on non-master cpu with id: %lu\n", CPU_ID_GET());
  493. return -ENOENT;
  494. }
  495. static noinline int prepare_cpus(void)
  496. {
  497. int ret;
  498. ret = check_master_cpu_id();
  499. if (ret)
  500. return ret;
  501. ret = envs_process_and_validate(env_map_common, env_map_core, is_cpu_used);
  502. if (ret)
  503. return ret;
  504. printf("CPU start mask is %#x\n", env_common.core_mask.val);
  505. do_init_slave_cpus();
  506. do_init_master_cpu();
  507. do_init_cluster();
  508. return 0;
  509. }
  510. static int hsdk_go_run(u32 cpu_start_reg)
  511. {
  512. /* Cleanup caches, disable interrupts */
  513. cleanup_before_go();
  514. if (env_common.halt_on_boot)
  515. halt_this_cpu();
  516. /*
  517. * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
  518. * cores but we leave them for gebug purposes.
  519. */
  520. __builtin_arc_nop();
  521. __builtin_arc_nop();
  522. __builtin_arc_nop();
  523. /* Kick chosen slave CPUs */
  524. writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
  525. if (is_cpu_used(MASTER_CPU_ID))
  526. ((void (*)(void))(env_core.entry[MASTER_CPU_ID].val))();
  527. else
  528. halt_this_cpu();
  529. pr_err("u-boot still runs on cpu [%ld]\n", CPU_ID_GET());
  530. /*
  531. * We will never return after executing our program if master cpu used
  532. * otherwise halt master cpu manually.
  533. */
  534. while (true)
  535. halt_this_cpu();
  536. return 0;
  537. }
  538. int board_prep_linux(bootm_headers_t *images)
  539. {
  540. int ret, ofst;
  541. char mask[15];
  542. ret = envs_read_validate_common(env_map_mask);
  543. if (ret)
  544. return ret;
  545. /* Rollback to default values */
  546. if (!env_common.core_mask.set) {
  547. env_common.core_mask.val = ALL_CPU_MASK;
  548. env_common.core_mask.set = true;
  549. }
  550. printf("CPU start mask is %#x\n", env_common.core_mask.val);
  551. if (!is_cpu_used(MASTER_CPU_ID))
  552. pr_err("ERR: try to launch linux with CPU[0] disabled! It doesn't work for ARC.\n");
  553. /*
  554. * If we want to launch linux on all CPUs we don't need to patch
  555. * linux DTB as it is default configuration
  556. */
  557. if (env_common.core_mask.val == ALL_CPU_MASK)
  558. return 0;
  559. if (!IMAGE_ENABLE_OF_LIBFDT || !images->ft_len) {
  560. pr_err("WARN: core_mask setup will work properly only with external DTB!\n");
  561. return 0;
  562. }
  563. /* patch '/possible-cpus' property according to cpu mask */
  564. ofst = fdt_path_offset(images->ft_addr, "/");
  565. sprintf(mask, "%s%s%s%s",
  566. is_cpu_used(0) ? "0," : "",
  567. is_cpu_used(1) ? "1," : "",
  568. is_cpu_used(2) ? "2," : "",
  569. is_cpu_used(3) ? "3," : "");
  570. ret = fdt_setprop_string(images->ft_addr, ofst, "possible-cpus", mask);
  571. /*
  572. * If we failed to patch '/possible-cpus' property we don't need break
  573. * linux loading process: kernel will handle it but linux will print
  574. * warning like "Timeout: CPU1 FAILED to comeup !!!".
  575. * So warn here about error, but return 0 like no error had occurred.
  576. */
  577. if (ret)
  578. pr_err("WARN: failed to patch '/possible-cpus' property, ret=%d\n",
  579. ret);
  580. return 0;
  581. }
  582. void board_jump_and_run(ulong entry, int zero, int arch, uint params)
  583. {
  584. void (*kernel_entry)(int zero, int arch, uint params);
  585. u32 cpu_start_reg;
  586. kernel_entry = (void (*)(int, int, uint))entry;
  587. /* Prepare CREG_CPU_START for kicking chosen CPUs */
  588. cpu_start_reg = prepare_cpu_ctart_reg();
  589. /* In case of run without hsdk_init */
  590. slave_cpu_set_boot_addr(entry);
  591. /* In case of run with hsdk_init */
  592. for (u32 i = 0; i < NR_CPUS; i++) {
  593. env_core.entry[i].val = entry;
  594. env_core.entry[i].set = true;
  595. }
  596. /* sync cross_cpu struct as we updated core-entry variables */
  597. sync_cross_cpu_data();
  598. /* Kick chosen slave CPUs */
  599. writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
  600. if (is_cpu_used(0))
  601. kernel_entry(zero, arch, params);
  602. }
  603. static int hsdk_go_prepare_and_run(void)
  604. {
  605. /* Prepare CREG_CPU_START for kicking chosen CPUs */
  606. u32 reg = prepare_cpu_ctart_reg();
  607. if (env_common.halt_on_boot)
  608. printf("CPU will halt before application start, start application with debugger.\n");
  609. return hsdk_go_run(reg);
  610. }
  611. static int do_hsdk_go(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  612. {
  613. int ret;
  614. /*
  615. * Check for 'halt' parameter. 'halt' = enter halt-mode just before
  616. * starting the application; can be used for debug.
  617. */
  618. if (argc > 1) {
  619. env_common.halt_on_boot = !strcmp(argv[1], "halt");
  620. if (!env_common.halt_on_boot) {
  621. pr_err("Unrecognised parameter: \'%s\'\n", argv[1]);
  622. return CMD_RET_FAILURE;
  623. }
  624. }
  625. ret = check_master_cpu_id();
  626. if (ret)
  627. return ret;
  628. ret = envs_process_and_validate(env_map_mask, env_map_go, is_cpu_used);
  629. if (ret)
  630. return ret;
  631. /* sync cross_cpu struct as we updated core-entry variables */
  632. sync_cross_cpu_data();
  633. ret = hsdk_go_prepare_and_run();
  634. return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
  635. }
  636. U_BOOT_CMD(
  637. hsdk_go, 3, 0, do_hsdk_go,
  638. "Synopsys HSDK specific command",
  639. " - Boot stand-alone application on HSDK\n"
  640. "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n"
  641. );
  642. static int do_hsdk_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  643. {
  644. static bool done = false;
  645. int ret;
  646. /* hsdk_init can be run only once */
  647. if (done) {
  648. printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n");
  649. return CMD_RET_FAILURE;
  650. }
  651. ret = prepare_cpus();
  652. if (!ret)
  653. done = true;
  654. return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
  655. }
  656. U_BOOT_CMD(
  657. hsdk_init, 1, 0, do_hsdk_init,
  658. "Synopsys HSDK specific command",
  659. "- Init HSDK HW\n"
  660. );
  661. static int do_hsdk_clock_set(cmd_tbl_t *cmdtp, int flag, int argc,
  662. char *const argv[])
  663. {
  664. int ret = 0;
  665. /* Strip off leading subcommand argument */
  666. argc--;
  667. argv++;
  668. envs_cleanup_common(env_map_clock);
  669. if (!argc) {
  670. printf("Set clocks to values specified in environment\n");
  671. ret = envs_read_common(env_map_clock);
  672. } else {
  673. printf("Set clocks to values specified in args\n");
  674. ret = args_envs_enumerate(env_map_clock, 2, argc, argv);
  675. }
  676. if (ret)
  677. return CMD_RET_FAILURE;
  678. ret = envs_validate_common(env_map_clock);
  679. if (ret)
  680. return CMD_RET_FAILURE;
  681. /* Setup clock tree HW */
  682. setup_clocks();
  683. return CMD_RET_SUCCESS;
  684. }
  685. static int do_hsdk_clock_get(cmd_tbl_t *cmdtp, int flag, int argc,
  686. char *const argv[])
  687. {
  688. ulong rate;
  689. if (soc_clk_ctl("cpu-clk", &rate, CLK_GET | CLK_MHZ))
  690. return CMD_RET_FAILURE;
  691. if (env_set_ulong("cpu_freq", rate))
  692. return CMD_RET_FAILURE;
  693. if (soc_clk_ctl("tun-clk", &rate, CLK_GET | CLK_MHZ))
  694. return CMD_RET_FAILURE;
  695. if (env_set_ulong("tun_freq", rate))
  696. return CMD_RET_FAILURE;
  697. if (soc_clk_ctl("axi-clk", &rate, CLK_GET | CLK_MHZ))
  698. return CMD_RET_FAILURE;
  699. if (env_set_ulong("axi_freq", rate))
  700. return CMD_RET_FAILURE;
  701. printf("Clock values are saved to environment\n");
  702. return CMD_RET_SUCCESS;
  703. }
  704. static int do_hsdk_clock_print(cmd_tbl_t *cmdtp, int flag, int argc,
  705. char *const argv[])
  706. {
  707. /* Main clocks */
  708. soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
  709. soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
  710. soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
  711. soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
  712. return CMD_RET_SUCCESS;
  713. }
  714. static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc,
  715. char *const argv[])
  716. {
  717. /*
  718. * NOTE: as of today we don't use some peripherals like HDMI / EBI
  719. * so we don't want to print their clocks ("hdmi-sys-clk", "hdmi-pll",
  720. * "hdmi-clk", "ebi-clk"). Nevertheless their clock subsystems is fully
  721. * functional and we can print their clocks if it is required
  722. */
  723. /* CPU clock domain */
  724. soc_clk_ctl("cpu-pll", NULL, CLK_PRINT | CLK_MHZ);
  725. soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
  726. printf("\n");
  727. /* SYS clock domain */
  728. soc_clk_ctl("sys-pll", NULL, CLK_PRINT | CLK_MHZ);
  729. soc_clk_ctl("apb-clk", NULL, CLK_PRINT | CLK_MHZ);
  730. soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
  731. soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ);
  732. soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ);
  733. soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ);
  734. /* soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); */
  735. soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ);
  736. soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
  737. soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
  738. soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ);
  739. soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
  740. soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ);
  741. soc_clk_ctl("spi-clk", NULL, CLK_PRINT | CLK_MHZ);
  742. soc_clk_ctl("i2c-clk", NULL, CLK_PRINT | CLK_MHZ);
  743. /* soc_clk_ctl("ebi-clk", NULL, CLK_PRINT | CLK_MHZ); */
  744. soc_clk_ctl("uart-clk", NULL, CLK_PRINT | CLK_MHZ);
  745. printf("\n");
  746. /* DDR clock domain */
  747. soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
  748. printf("\n");
  749. /* HDMI clock domain */
  750. /* soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); */
  751. /* soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); */
  752. /* printf("\n"); */
  753. /* TUN clock domain */
  754. soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ);
  755. soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
  756. soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ);
  757. soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ);
  758. printf("\n");
  759. return CMD_RET_SUCCESS;
  760. }
  761. cmd_tbl_t cmd_hsdk_clock[] = {
  762. U_BOOT_CMD_MKENT(set, 3, 0, do_hsdk_clock_set, "", ""),
  763. U_BOOT_CMD_MKENT(get, 3, 0, do_hsdk_clock_get, "", ""),
  764. U_BOOT_CMD_MKENT(print, 4, 0, do_hsdk_clock_print, "", ""),
  765. U_BOOT_CMD_MKENT(print_all, 4, 0, do_hsdk_clock_print_all, "", ""),
  766. };
  767. static int do_hsdk_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  768. {
  769. cmd_tbl_t *c;
  770. if (argc < 2)
  771. return CMD_RET_USAGE;
  772. /* Strip off leading 'hsdk_clock' command argument */
  773. argc--;
  774. argv++;
  775. c = find_cmd_tbl(argv[0], cmd_hsdk_clock, ARRAY_SIZE(cmd_hsdk_clock));
  776. if (!c)
  777. return CMD_RET_USAGE;
  778. return c->cmd(cmdtp, flag, argc, argv);
  779. }
  780. U_BOOT_CMD(
  781. hsdk_clock, CONFIG_SYS_MAXARGS, 0, do_hsdk_clock,
  782. "Synopsys HSDK specific clock command",
  783. "set - Set clock to values specified in environment / command line arguments\n"
  784. "hsdk_clock get - Save clock values to environment\n"
  785. "hsdk_clock print - Print main clock values to console\n"
  786. "hsdk_clock print_all - Print all clock values to console\n"
  787. );
  788. /* init calls */
  789. int board_early_init_f(void)
  790. {
  791. /*
  792. * Setup AXI apertures unconditionally as we want to have DDR
  793. * in 0x00000000 region when we are kicking slave cpus.
  794. */
  795. init_memory_bridge();
  796. /*
  797. * Switch SDIO external ciu clock divider from default div-by-8 to
  798. * minimum possible div-by-2.
  799. */
  800. writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
  801. return 0;
  802. }
  803. int board_early_init_r(void)
  804. {
  805. /*
  806. * TODO: Init USB here to be able read environment from USB MSD.
  807. * It can be done with usb_init() call. We can't do it right now
  808. * due to brocken USB IP SW reset and lack of USB IP HW reset in
  809. * linux kernel (if we init USB here we will break USB in linux)
  810. */
  811. /*
  812. * Flush all d$ as we want to use uncached area with st.di / ld.di
  813. * instructions and we don't want to have any dirty line in L1d$ or SL$
  814. * in this area. It is enough to flush all d$ once here as we access to
  815. * uncached area with regular st (non .di) instruction only when we copy
  816. * data during u-boot relocation.
  817. */
  818. flush_dcache_all();
  819. printf("Relocation Offset is: %08lx\n", gd->reloc_off);
  820. return 0;
  821. }
  822. int board_late_init(void)
  823. {
  824. /*
  825. * Populate environment with clock frequency values -
  826. * run hsdk_clock get callback without uboot command run.
  827. */
  828. do_hsdk_clock_get(NULL, 0, 0, NULL);
  829. return 0;
  830. }
  831. int checkboard(void)
  832. {
  833. puts("Board: Synopsys ARC HS Development Kit\n");
  834. return 0;
  835. };