hsdk.c 28 KB

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