hsdk.c 34 KB

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