spl_ark1668e.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <common.h>
  3. #include <spl.h>
  4. #include <asm/arch/timer.h>
  5. #include <asm/arch/ark1668e-sysreg.h>
  6. #include <asm/arch/ark-common.h>
  7. #include <asm-generic/gpio.h>
  8. #define CPUPLL_CLK 800
  9. #define LCDPLL_CLK 480
  10. #define AXIPLL_CLK 432
  11. #define AHBPLL_CLK 336
  12. #define APBPLL_CLK 480
  13. #define DDRPLL_CLK 360
  14. #define MACPLL_CLK 1000
  15. #define AUDPLL_CLK 480
  16. enum sscg_clk_id {
  17. SSCG_CPU,
  18. SSCG_LCD,
  19. SSCG_MAC,
  20. };
  21. enum pll_clk_id {
  22. PLL_AXI,
  23. PLL_AHB,
  24. PLL_APB,
  25. PLL_AUD,
  26. PLL_TV,
  27. PLL_DDR,
  28. };
  29. /*
  30. * fref=24MHz, nr=2, fint=12MHz
  31. * fvco=1000~2000MHz
  32. * rs = 4 (fvcomax/fint=166)
  33. * nf[23:15] integer nf[14:0] fraction
  34. */
  35. static void set_sscg_clk(int clk_id, unsigned int freq_khz)
  36. {
  37. unsigned int nr = 2, fint = 12000, rs = 4;
  38. unsigned int od, fvco, nfx, nff, cpa, cpax;
  39. int i;
  40. unsigned int cfg0, cfg1, cfg2;
  41. unsigned int regval;
  42. if (clk_id == SSCG_MAC) {
  43. nr = 3;
  44. fint = 8000;
  45. rs = 7;
  46. }
  47. freq_khz = freq_khz / fint * fint;
  48. for (i = 0; i < 8; i++) {
  49. fvco = freq_khz * (1 << i);
  50. if (fvco >= 1000 * 1000 && fvco <= 2000 * 1000) {
  51. od = i;
  52. break;
  53. }
  54. }
  55. if (i == 8)
  56. goto fail;
  57. nfx = fvco / fint;
  58. if (nfx >= 50 && nfx <= 100) {
  59. cpa = nfx * 4;
  60. cpax = 3;
  61. } else if (nfx > 100 && nfx <= 200) {
  62. cpa = nfx * 2;
  63. cpax = 1;
  64. } else if (nfx > 200 && nfx <= 400) {
  65. cpa = nfx;
  66. cpax = 0;
  67. }
  68. else
  69. goto fail;
  70. nff = ((1 << 15) * (fvco / 1000) / (fint / 1000)) & ((1 << 15) - 1);
  71. if (clk_id == SSCG_CPU) {
  72. cfg0 = SYS_CPUPLL_CFG_0;
  73. cfg1 = SYS_CPUPLL_CFG_1;
  74. cfg2 = SYS_CPUPLL_CFG_2;
  75. } else if (clk_id == SSCG_LCD) {
  76. cfg0 = SYS_LCDPLL_CFG_0;
  77. cfg1 = SYS_LCDPLL_CFG_1;
  78. cfg2 = SYS_LCDPLL_CFG_2;
  79. } else if (clk_id == SSCG_MAC) {
  80. cfg0 = SYS_MACPLL_CFG_0;
  81. cfg1 = SYS_MACPLL_CFG_1;
  82. cfg2 = SYS_MACPLL_CFG_2;
  83. } else {
  84. puts("Invalid sscg clk_id.\n");
  85. return;
  86. }
  87. /* disable clk first */
  88. write_sys_reg(read_sys_reg(cfg1) | (1 << 27), cfg1);
  89. regval = read_sys_reg(cfg0);
  90. regval &= ~0x3FFFFF;
  91. regval |= (cpa << 0) | (cpax << 9) | (rs << 11) | (nr << 15);
  92. write_sys_reg(regval, cfg0);
  93. regval = read_sys_reg(cfg1);
  94. regval &= ~0x7FFFFFF;
  95. regval |= ((nfx<<15) | nff) | (od << 24);
  96. write_sys_reg(regval, cfg1);
  97. write_sys_reg(read_sys_reg(cfg2) | 1, cfg2);
  98. /* enable clk */
  99. write_sys_reg(read_sys_reg(cfg1) & ~(1 << 27), cfg1);
  100. return ;
  101. fail:
  102. puts("Unsupported sscg freq.\n");
  103. }
  104. /*
  105. * vcoout = fref*(ns/ms)
  106. * clkout = vcoout/ps/2
  107. */
  108. static void set_pll_clk(int clk_id, unsigned int freq_mhz)
  109. {
  110. unsigned int ms;//[2:0]
  111. unsigned int ns;//[11:3]
  112. unsigned int ps;//[16:12]
  113. unsigned int vcoout;
  114. unsigned int fin;
  115. volatile unsigned int cfg0;
  116. unsigned int regval;
  117. ms = 2;
  118. fin = 24 / ms;
  119. freq_mhz = freq_mhz / fin * fin;
  120. for (ps = 0; ps < 32; ps++) {
  121. vcoout = freq_mhz * ps * 2;
  122. if (vcoout >= 1000 && vcoout <= 2000)
  123. break;
  124. }
  125. if (ps == 32)
  126. goto fail;
  127. ns = vcoout / fin;
  128. switch (clk_id) {
  129. case PLL_AXI:
  130. cfg0 = SYS_AXIPLL_CFG_0;
  131. break;
  132. case PLL_AHB:
  133. cfg0 = SYS_AHBPLL_CFG_0;
  134. break;
  135. case PLL_APB:
  136. cfg0 = SYS_APBPLL_CFG_0;
  137. break;
  138. case PLL_AUD:
  139. cfg0 = SYS_AUDPLL_CFG_0;
  140. break;
  141. case PLL_TV:
  142. cfg0 = SYS_TVPLL_CFG_0;
  143. break;
  144. case PLL_DDR:
  145. cfg0 = SYS_DDRPLL_CFG_0;
  146. break;
  147. default:
  148. puts("Invalid pll clk_id.\n");
  149. return;
  150. }
  151. /* disable clk first */
  152. write_sys_reg(read_sys_reg(cfg0) & ~(1 << 17), cfg0);
  153. regval = read_sys_reg(cfg0);
  154. regval &= ~0x1FFFF;
  155. regval |= (ms << 0) | (ns << 3) | (ps << 12);
  156. write_sys_reg(regval, cfg0);
  157. /* enable clk */
  158. write_sys_reg(read_sys_reg(cfg0) | (1 << 17), cfg0);
  159. return;
  160. fail:
  161. puts("Unsupported pll freq.\n");
  162. }
  163. static void switch_to_main_crystal_osc(void)
  164. {
  165. unsigned int cpu_freq = CPUPLL_CLK;
  166. unsigned int regval;
  167. /* switch to 24M clk first */
  168. write_sys_reg(0x04040404, SYS_CLK_SEL);
  169. udelay(50);
  170. set_sscg_clk(SSCG_CPU, CPUPLL_CLK * 1000);
  171. set_sscg_clk(SSCG_LCD, LCDPLL_CLK * 1000);
  172. set_sscg_clk(SSCG_MAC, MACPLL_CLK * 1000);
  173. set_pll_clk(PLL_AXI, AXIPLL_CLK);
  174. set_pll_clk(PLL_AHB, AHBPLL_CLK);
  175. set_pll_clk(PLL_APB, APBPLL_CLK);
  176. set_pll_clk(PLL_DDR, DDRPLL_CLK);
  177. set_pll_clk(PLL_AUD, AUDPLL_CLK);
  178. udelay(100);
  179. /* sync cpu bclk */
  180. regval = read_sys_reg(SYS_CPU_CFG2);
  181. regval &= ~(0x3<<12);
  182. if(cpu_freq > 1000)
  183. regval |= (2<<12);
  184. else if(cpu_freq > 500)
  185. regval |= (1<<12);
  186. write_sys_reg(regval, SYS_CPU_CFG2);
  187. /* switch to sys pll clk */
  188. /* ahb and pclk and pclk1 must have the same clk source */
  189. /* change the config will cause mfc working fail */
  190. /* ahb and apb clk */
  191. regval = 0x04040404;
  192. regval |= (2 << 12) | (1 << 8) | (5 << 4) | 1;
  193. write_sys_reg(regval, SYS_CLK_SEL);
  194. udelay(50);
  195. /* pclk1 */
  196. regval = 0x40;
  197. regval |= (1 << 4) | 5;
  198. write_sys_reg(regval, SYS_DEVICE_CLK_CFG6);
  199. udelay(50);
  200. /* switch from 24MHz to pll */
  201. regval = read_sys_reg(SYS_CLK_SEL);
  202. regval &= ~((1 << 26) | (1 << 18) | (1 << 10) | (1 << 2));
  203. write_sys_reg(regval, SYS_CLK_SEL);
  204. udelay(50);
  205. regval = read_sys_reg(SYS_DEVICE_CLK_CFG6);
  206. regval &= ~(1 << 6);
  207. write_sys_reg(regval, SYS_DEVICE_CLK_CFG6);
  208. udelay(50);
  209. /* mfc clk adjusting */
  210. /* the mfc clk can't reconfig at other place */
  211. regval = read_sys_reg(SYS_DEVICE_CLK_CFG1);
  212. regval &= ~(0x7 << 16);
  213. regval |= (2 << 16);
  214. write_sys_reg(regval, SYS_DEVICE_CLK_CFG1);
  215. udelay(50);
  216. regval = read_sys_reg(SYS_DEVICE_CLK_CFG1);
  217. regval &= ~(0xf << 19);
  218. regval |= (1 << 19);
  219. write_sys_reg(regval, SYS_DEVICE_CLK_CFG1);
  220. udelay(50);
  221. regval &= ~(0xf << 19);
  222. regval |= (3 << 19);
  223. write_sys_reg(regval, SYS_DEVICE_CLK_CFG1);
  224. udelay(50);
  225. /* switch to ddrpll clk */
  226. regval = read_sys_reg(SYS_DEVICE_CLK_CFG3);
  227. regval &= ~((0x7 << 18) | (0xf << 22));
  228. regval |= (2 << 18) | (0 << 22);
  229. write_sys_reg(regval, SYS_DEVICE_CLK_CFG3);
  230. udelay(50);
  231. return;
  232. }
  233. #define rWDT_CR *(volatile unsigned int *)0xe4b00000
  234. void board_init_f(ulong dummy)
  235. {
  236. u32 tmp;
  237. /* Disable watch dog */
  238. rWDT_CR = 0;
  239. timer_init();
  240. switch_to_main_crystal_osc();
  241. board_early_init_f();
  242. preloader_console_init();
  243. //slect nand pad
  244. tmp = read_sys_reg(SYS_PAD_CTRL08);
  245. tmp &= ~((0x7<<27) | (0x7<<24)|(0x7<<21) | (0x7<<18) | (0x7<<15)|(0x7<<12)|(0x7<<9)|(0x7<<6));
  246. tmp |=((0x1<<27) | (0x1<<24)|(0x1<<21) | (0x1<<18) | (0x1<<15)|(0x1<<12)|(0x1<<9)|(0x1<<6));
  247. write_sys_reg(tmp, SYS_PAD_CTRL08);
  248. tmp = read_sys_reg(SYS_PAD_CTRL09);
  249. tmp &= ~((0x7<<15) | (0x7<<12) | (0x7<<9)|(0x7<<6)|(0x7<<3)|(0x7<<0));
  250. tmp |=((1<<15)|(1<<12)|(1<<9)|(1<<6)|(1<<3)|(1<<0));//enable nand cle, ale,ren,wen
  251. write_sys_reg(tmp, SYS_PAD_CTRL09);
  252. // mem_init();
  253. ddr3_sdramc_init();
  254. ark_watchdog_start(1500);
  255. }
  256. #ifndef CONFIG_SPL_LIBCOMMON_SUPPORT
  257. void puts(const char *s)
  258. {
  259. serial_puts(s);
  260. }
  261. void putc(const char c)
  262. {
  263. serial_putc(c);
  264. }
  265. #endif
  266. #ifndef CONFIG_SPL_LIBGENERIC_SUPPORT
  267. void udelay(unsigned long usec)
  268. {
  269. timer_delay_us(usec);
  270. }
  271. void hang(void)
  272. {
  273. for (;;);
  274. }
  275. uint32_t __div64_32(uint64_t *n, uint32_t base)
  276. {
  277. uint64_t rem = *n;
  278. uint64_t b = base;
  279. uint64_t res, d = 1;
  280. uint32_t high = rem >> 32;
  281. /* Reduce the thing a bit first */
  282. res = 0;
  283. if (high >= base) {
  284. high /= base;
  285. res = (uint64_t) high << 32;
  286. rem -= (uint64_t) (high*base) << 32;
  287. }
  288. while ((int64_t)b > 0 && b < rem) {
  289. b = b+b;
  290. d = d+d;
  291. }
  292. do {
  293. if (rem >= b) {
  294. rem -= b;
  295. res += d;
  296. }
  297. b >>= 1;
  298. d >>= 1;
  299. } while (d);
  300. *n = res;
  301. return rem;
  302. }
  303. void * memmove(void * dest,const void *src,size_t count)
  304. {
  305. char *tmp, *s;
  306. if (dest <= src) {
  307. memcpy(dest, src, count);
  308. } else {
  309. tmp = (char *) dest + count;
  310. s = (char *) src + count;
  311. while (count--)
  312. *--tmp = *--s;
  313. }
  314. return dest;
  315. }
  316. #endif