hsdk.c 34 KB

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