clock.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. *
  3. * arch/arm/mach-meson/clock.c
  4. *
  5. * Copyright (C) 2010 AMLOGIC, INC.
  6. *
  7. * License terms: GNU General Public License (GPL) version 2
  8. * Define clocks in the app platform.
  9. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/clk.h>
  14. #include <linux/init.h>
  15. #include <linux/spinlock.h>
  16. #include <linux/clkdev.h>
  17. #include <mach/clock.h>
  18. #include <mach/hardware.h>
  19. #include <mach/clk_set.h>
  20. #include <mach/am_regs.h>
  21. #include <mach/power_gate.h>
  22. static DEFINE_SPINLOCK(clockfw_lock);
  23. #ifdef CONFIG_INIT_A9_CLOCK_FREQ
  24. static unsigned long __initdata init_clock = CONFIG_INIT_A9_CLOCK;
  25. #else
  26. static unsigned long __initdata init_clock = 0;
  27. #endif
  28. // -----------------------------------------
  29. // clk_util_clk_msr
  30. // -----------------------------------------
  31. // from twister_core.v
  32. //
  33. // .clk0 ( am_ring_osc_clk_out[0] ),
  34. // .clk1 ( am_ring_osc_clk_out[1] ),
  35. // .clk2 ( ext_clk_to_msr_i ),
  36. // .clk3 ( cts_a9_clk ),
  37. // .clk4 ( cts_a9_periph_clk ),
  38. // .clk5 ( cts_a9_axi_clk ),
  39. // .clk6 ( cts_a9_at_clk ),
  40. // .clk7 ( cts_a9_apb_clk ),
  41. // .clk8 ( cts_arc625_clk ),
  42. // .clk9 ( sys_pll_div3 ),
  43. // .clk10 ( ddr_pll_clk ),
  44. // .clk11 ( other_pll_clk ),
  45. // .clk12 ( aud_pll_clk ),
  46. // .clk13 ( demod_pll_clk240 ),
  47. // .clk14 ( demod_pll_adc_clk ),
  48. // .clk15 ( demod_pll_wifi_adc_clk ),
  49. // .clk16 ( demod_pll_adc_clk_57 ),
  50. // .clk17 ( demod_pll_clk400 ),
  51. // .clk18 ( demod_pll_wifi_dac_clk ),
  52. // .clk19 ( vid_pll_clk ),
  53. // .clk20 ( vid_pll_ref_clk ),
  54. // .clk21 ( HDMI_CH0_TMDSCLK ),
  55. //
  56. // For Example
  57. //
  58. // unsigend long clk81_clk = clk_util_clk_msr( 2, // mux select 2
  59. // 50 ); // measure for 50uS
  60. //
  61. // returns a value in "clk81_clk" in Hz
  62. //
  63. // The "uS_gate_time" can be anything between 1uS and 65535 uS, but the limitation is
  64. // the circuit will only count 65536 clocks. Therefore the uS_gate_time is limited by
  65. //
  66. // uS_gate_time <= 65535/(expect clock frequency in MHz)
  67. //
  68. // For example, if the expected frequency is 400Mhz, then the uS_gate_time should
  69. // be less than 163.
  70. //
  71. // Your measurement resolution is:
  72. //
  73. // 100% / (uS_gate_time * measure_val )
  74. //
  75. //
  76. //unsigned int clk_util_clk_msr_rl(unsigned int clk_mux)
  77. unsigned int clk_util_clk_msr(unsigned int clk_mux)
  78. {
  79. unsigned int regval = 0;
  80. WRITE_CBUS_REG(MSR_CLK_REG0, 0);
  81. // Set the measurement gate to 64uS
  82. CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, 0xffff);
  83. SET_CBUS_REG_MASK(MSR_CLK_REG0, (64 - 1)); //64uS is enough for measure the frequence?
  84. // Disable continuous measurement
  85. // disable interrupts
  86. CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, ((1 << 18) | (1 << 17)));
  87. CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, (0x1f << 20));
  88. SET_CBUS_REG_MASK(MSR_CLK_REG0, (clk_mux << 20) | // Select MUX
  89. (1 << 19) | // enable the clock
  90. (1 << 16)); //enable measuring
  91. // Wait for the measurement to be done
  92. regval = READ_CBUS_REG(MSR_CLK_REG0);
  93. do {
  94. regval = READ_CBUS_REG(MSR_CLK_REG0);
  95. } while (regval & (1 << 31));
  96. // disable measuring
  97. CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, (1 << 16));
  98. regval = (READ_CBUS_REG(MSR_CLK_REG2) + 31) & 0x000FFFFF;
  99. // Return value in MHz*measured_val
  100. return (regval >> 6);
  101. }
  102. long clk_round_rate(struct clk *clk, unsigned long rate)
  103. {
  104. if (rate < clk->min)
  105. return clk->min;
  106. if (rate > clk->max)
  107. return clk->max;
  108. return rate;
  109. }
  110. EXPORT_SYMBOL(clk_round_rate);
  111. unsigned long clk_get_rate(struct clk *clk)
  112. {
  113. if (!clk)
  114. return 0;
  115. if (clk->get_rate)
  116. return clk->get_rate(clk);
  117. return clk->rate;
  118. }
  119. EXPORT_SYMBOL(clk_get_rate);
  120. int clk_set_rate(struct clk *clk, unsigned long rate)
  121. {
  122. unsigned long flags;
  123. int ret;
  124. if (clk == NULL || clk->set_rate == NULL)
  125. return -EINVAL;
  126. spin_lock_irqsave(&clockfw_lock, flags);
  127. ret = clk->set_rate(clk, rate);
  128. spin_unlock_irqrestore(&clockfw_lock, flags);
  129. return ret;
  130. }
  131. EXPORT_SYMBOL(clk_set_rate);
  132. static unsigned long xtal_get_rate(struct clk *clk)
  133. {
  134. unsigned long rate;
  135. rate = get_xtal_clock(); /*refresh from register */
  136. clk->rate = rate;
  137. return rate;
  138. }
  139. static int clk_set_rate_sys_pll(struct clk *clk, unsigned long rate)
  140. {
  141. unsigned long r = rate;
  142. int ret;
  143. if (r < 1000)
  144. r = r * 1000000;
  145. ret = sys_clkpll_setting(0, r);
  146. if (ret == 0)
  147. clk->rate = r;
  148. return ret;
  149. }
  150. static int clk_set_rate_other_pll(struct clk *clk, unsigned long rate)
  151. {
  152. unsigned long r = rate;
  153. int ret;
  154. if (r < 1000)
  155. r = r * 1000000;
  156. ret = other_pll_setting(0, r);
  157. if (ret == 0)
  158. clk->rate = r;
  159. return ret;
  160. }
  161. static int clk_set_rate_clk81(struct clk *clk, unsigned long rate)
  162. {
  163. unsigned long r = rate;
  164. struct clk *father_clk;
  165. unsigned long r1;
  166. int ret;
  167. int divider = 4;
  168. if (r < 1000)
  169. r = r * 1000000;
  170. if (r < 100000000)
  171. divider = 8;
  172. father_clk = clk_get_sys("clk_other_pll", NULL);
  173. r1 = clk_get_rate(father_clk);
  174. if (r1 != r * divider) {
  175. ret = father_clk->set_rate(father_clk, r * divider);
  176. if (ret != 0)
  177. return ret;
  178. }
  179. clk->rate = r;
  180. WRITE_MPEG_REG(HHI_MPEG_CLK_CNTL, (1 << 12) | // select other PLL
  181. ((divider - 1) << 0) | // div1
  182. (1 << 7) | // cntl_hi_mpeg_div_en, enable gating
  183. (1 << 8)); // Connect clk81 to the PLL divider output
  184. return 0;
  185. }
  186. static int clk_set_rate_a9_clk(struct clk *clk, unsigned long rate)
  187. {
  188. unsigned long r = rate;
  189. struct clk *father_clk;
  190. unsigned long r1;
  191. int ret;
  192. if (r < 1000)
  193. r = r * 1000000;
  194. father_clk = clk_get_sys("clk_sys_pll", NULL);
  195. r1 = clk_get_rate(father_clk);
  196. if (!r1)
  197. return -1;
  198. if (r1 != r * 2 && r != 0) {
  199. ret = father_clk->set_rate(father_clk, r * 2);
  200. if (ret != 0)
  201. return ret;
  202. }
  203. clk->rate = r;
  204. WRITE_MPEG_REG(HHI_A9_CLK_CNTL, (0 << 10) | // 0 - sys_pll_clk, 1 - audio_pll_clk
  205. (1 << 0) | // 1 - sys/audio pll clk, 0 - XTAL
  206. (1 << 4) | // APB_CLK_ENABLE
  207. (1 << 5) | // AT_CLK_ENABLE
  208. (0 << 2) | // div1
  209. (1 << 7)); // Connect A9 to the PLL divider output
  210. return 0;
  211. }
  212. static struct clk xtal_clk = {
  213. .name = "clk_xtal",
  214. .rate = 24000000,
  215. .get_rate = xtal_get_rate,
  216. .set_rate = NULL,
  217. };
  218. static struct clk clk_sys_pll = {
  219. .name = "clk_sys_pll",
  220. .rate = 1200000000,
  221. .min = 200000000,
  222. .max = 2000000000,
  223. .set_rate = clk_set_rate_sys_pll,
  224. };
  225. static struct clk clk_other_pll = {
  226. .name = "clk_other_pll",
  227. .rate = 750000000,
  228. .min = 200000000,
  229. .max = 800000000,
  230. .set_rate = clk_set_rate_other_pll,
  231. };
  232. static struct clk clk_ddr_pll = {
  233. .name = "clk_ddr",
  234. .rate = 400000000,
  235. .set_rate = NULL,
  236. };
  237. static struct clk clk81 = {
  238. .name = "clk81",
  239. .rate = 187500000,
  240. .min = 100000000,
  241. .max = 400000000,
  242. .set_rate = clk_set_rate_clk81,
  243. };
  244. static struct clk a9_clk = {
  245. .name = "a9_clk",
  246. .rate = 600000000,
  247. .min = 200000000,
  248. #if defined(CONFIG_MACH_MESON_8726M_REFC03) || defined(CONFIG_MACH_MESON_8726M_REFC06)
  249. .max = 750000000,
  250. #elif defined(CONFIG_MACH_MESON_8726M_REFC08)
  251. .max = 800000000,
  252. #else
  253. .max = 850000000,
  254. #endif
  255. .set_rate = clk_set_rate_a9_clk,
  256. };
  257. REGISTER_CLK(AHB_BRIDGE);
  258. REGISTER_CLK(AHB_SRAM);
  259. REGISTER_CLK(AIU_ADC);
  260. REGISTER_CLK(AIU_MIXER_REG);
  261. REGISTER_CLK(AIU_AUD_MIXER);
  262. REGISTER_CLK(AIU_AIFIFO2);
  263. REGISTER_CLK(AIU_AMCLK_MEASURE);
  264. REGISTER_CLK(AIU_I2S_OUT);
  265. REGISTER_CLK(AIU_IEC958);
  266. REGISTER_CLK(AIU_AI_TOP_GLUE);
  267. REGISTER_CLK(AIU_AUD_DAC);
  268. REGISTER_CLK(AIU_ICE958_AMCLK);
  269. REGISTER_CLK(AIU_I2S_DAC_AMCLK);
  270. REGISTER_CLK(AIU_I2S_SLOW);
  271. REGISTER_CLK(AIU_AUD_DAC_CLK);
  272. REGISTER_CLK(ASSIST_MISC);
  273. REGISTER_CLK(AMRISC);
  274. REGISTER_CLK(AUD_BUF);
  275. REGISTER_CLK(AUD_IN);
  276. REGISTER_CLK(BLK_MOV);
  277. REGISTER_CLK(BT656_IN);
  278. REGISTER_CLK(DEMUX);
  279. REGISTER_CLK(MMC_DDR);
  280. REGISTER_CLK(DDR);
  281. REGISTER_CLK(ETHERNET);
  282. REGISTER_CLK(GE2D);
  283. REGISTER_CLK(HDMI_MPEG_DOMAIN);
  284. REGISTER_CLK(HIU_PARSER_TOP);
  285. REGISTER_CLK(HIU_PARSER);
  286. REGISTER_CLK(ISA);
  287. REGISTER_CLK(MEDIA_CPU);
  288. REGISTER_CLK(MISC_USB0_TO_DDR);
  289. REGISTER_CLK(MISC_USB1_TO_DDR);
  290. REGISTER_CLK(MISC_SATA_TO_DDR);
  291. REGISTER_CLK(AHB_CONTROL_BUS);
  292. REGISTER_CLK(AHB_DATA_BUS);
  293. REGISTER_CLK(AXI_BUS);
  294. REGISTER_CLK(ROM_CLK);
  295. REGISTER_CLK(EFUSE);
  296. REGISTER_CLK(AHB_ARB0);
  297. REGISTER_CLK(RESET);
  298. REGISTER_CLK(MDEC_CLK_PIC_DC);
  299. REGISTER_CLK(MDEC_CLK_DBLK);
  300. REGISTER_CLK(MDEC_CLK_PSC);
  301. REGISTER_CLK(MDEC_CLK_ASSIST);
  302. REGISTER_CLK(MC_CLK);
  303. REGISTER_CLK(IQIDCT_CLK);
  304. REGISTER_CLK(VLD_CLK);
  305. REGISTER_CLK(NAND);
  306. REGISTER_CLK(RESERVED0);
  307. REGISTER_CLK(VGHL_PWM);
  308. REGISTER_CLK(LED_PWM);
  309. REGISTER_CLK(UART1);
  310. REGISTER_CLK(SDIO);
  311. REGISTER_CLK(ASYNC_FIFO);
  312. REGISTER_CLK(STREAM);
  313. REGISTER_CLK(RTC);
  314. REGISTER_CLK(UART0);
  315. REGISTER_CLK(RANDOM_NUM_GEN);
  316. REGISTER_CLK(SMART_CARD_MPEG_DOMAIN);
  317. REGISTER_CLK(SMART_CARD);
  318. REGISTER_CLK(SAR_ADC);
  319. REGISTER_CLK(I2C);
  320. REGISTER_CLK(IR_REMOTE);
  321. REGISTER_CLK(_1200XXX);
  322. REGISTER_CLK(SATA);
  323. REGISTER_CLK(SPI1);
  324. REGISTER_CLK(USB1);
  325. REGISTER_CLK(USB0);
  326. REGISTER_CLK(VI_CORE);
  327. REGISTER_CLK(LCD);
  328. REGISTER_CLK(ENC480P_MPEG_DOMAIN);
  329. REGISTER_CLK(ENC480I);
  330. REGISTER_CLK(VENC_MISC);
  331. REGISTER_CLK(ENC480P);
  332. REGISTER_CLK(HDMI);
  333. REGISTER_CLK(VCLK3_DAC);
  334. REGISTER_CLK(VCLK3_MISC);
  335. REGISTER_CLK(VCLK3_DVI);
  336. REGISTER_CLK(VCLK2_VIU);
  337. REGISTER_CLK(VCLK2_VENC_DVI);
  338. REGISTER_CLK(VCLK2_VENC_ENC480P);
  339. REGISTER_CLK(VCLK2_VENC_BIST);
  340. REGISTER_CLK(VCLK1_VENC_656);
  341. REGISTER_CLK(VCLK1_VENC_DVI);
  342. REGISTER_CLK(VCLK1_VENC_ENCI);
  343. REGISTER_CLK(VCLK1_VENC_BIST);
  344. REGISTER_CLK(VIDEO_IN);
  345. REGISTER_CLK(WIFI);
  346. static struct clk_lookup lookups[] = {
  347. {
  348. .dev_id = "clk_xtal",
  349. .clk = &xtal_clk,
  350. },
  351. {
  352. .dev_id = "clk_sys_pll",
  353. .clk = &clk_sys_pll,
  354. },
  355. {
  356. .dev_id = "clk_other_pll",
  357. .clk = &clk_other_pll,
  358. },
  359. {
  360. .dev_id = "clk_ddr_pll",
  361. .clk = &clk_ddr_pll,
  362. },
  363. {
  364. .dev_id = "clk81",
  365. .clk = &clk81,
  366. },
  367. {
  368. .dev_id = "a9_clk",
  369. .clk = &a9_clk,
  370. },
  371. CLK_LOOKUP_ITEM(AHB_BRIDGE),
  372. CLK_LOOKUP_ITEM(AHB_SRAM),
  373. CLK_LOOKUP_ITEM(AIU_ADC),
  374. CLK_LOOKUP_ITEM(AIU_MIXER_REG),
  375. CLK_LOOKUP_ITEM(AIU_AUD_MIXER),
  376. CLK_LOOKUP_ITEM(AIU_AIFIFO2),
  377. CLK_LOOKUP_ITEM(AIU_AMCLK_MEASURE),
  378. CLK_LOOKUP_ITEM(AIU_I2S_OUT),
  379. CLK_LOOKUP_ITEM(AIU_IEC958),
  380. CLK_LOOKUP_ITEM(AIU_AI_TOP_GLUE),
  381. CLK_LOOKUP_ITEM(AIU_AUD_DAC),
  382. CLK_LOOKUP_ITEM(AIU_ICE958_AMCLK),
  383. CLK_LOOKUP_ITEM(AIU_I2S_DAC_AMCLK),
  384. CLK_LOOKUP_ITEM(AIU_I2S_SLOW),
  385. CLK_LOOKUP_ITEM(AIU_AUD_DAC_CLK),
  386. CLK_LOOKUP_ITEM(ASSIST_MISC),
  387. CLK_LOOKUP_ITEM(AMRISC),
  388. CLK_LOOKUP_ITEM(AUD_BUF),
  389. CLK_LOOKUP_ITEM(AUD_IN),
  390. CLK_LOOKUP_ITEM(BLK_MOV),
  391. CLK_LOOKUP_ITEM(BT656_IN),
  392. CLK_LOOKUP_ITEM(DEMUX),
  393. CLK_LOOKUP_ITEM(MMC_DDR),
  394. CLK_LOOKUP_ITEM(DDR),
  395. CLK_LOOKUP_ITEM(ETHERNET),
  396. CLK_LOOKUP_ITEM(GE2D),
  397. CLK_LOOKUP_ITEM(HDMI_MPEG_DOMAIN),
  398. CLK_LOOKUP_ITEM(HIU_PARSER_TOP),
  399. CLK_LOOKUP_ITEM(HIU_PARSER),
  400. CLK_LOOKUP_ITEM(ISA),
  401. CLK_LOOKUP_ITEM(MEDIA_CPU),
  402. CLK_LOOKUP_ITEM(MISC_USB0_TO_DDR),
  403. CLK_LOOKUP_ITEM(MISC_USB1_TO_DDR),
  404. CLK_LOOKUP_ITEM(MISC_SATA_TO_DDR),
  405. CLK_LOOKUP_ITEM(AHB_CONTROL_BUS),
  406. CLK_LOOKUP_ITEM(AHB_DATA_BUS),
  407. CLK_LOOKUP_ITEM(AXI_BUS),
  408. CLK_LOOKUP_ITEM(ROM_CLK),
  409. CLK_LOOKUP_ITEM(EFUSE),
  410. CLK_LOOKUP_ITEM(AHB_ARB0),
  411. CLK_LOOKUP_ITEM(RESET),
  412. CLK_LOOKUP_ITEM(MDEC_CLK_PIC_DC),
  413. CLK_LOOKUP_ITEM(MDEC_CLK_DBLK),
  414. CLK_LOOKUP_ITEM(MDEC_CLK_PSC),
  415. CLK_LOOKUP_ITEM(MDEC_CLK_ASSIST),
  416. CLK_LOOKUP_ITEM(MC_CLK),
  417. CLK_LOOKUP_ITEM(IQIDCT_CLK),
  418. CLK_LOOKUP_ITEM(VLD_CLK),
  419. CLK_LOOKUP_ITEM(NAND),
  420. CLK_LOOKUP_ITEM(RESERVED0),
  421. CLK_LOOKUP_ITEM(VGHL_PWM),
  422. CLK_LOOKUP_ITEM(LED_PWM),
  423. CLK_LOOKUP_ITEM(UART1),
  424. CLK_LOOKUP_ITEM(SDIO),
  425. CLK_LOOKUP_ITEM(ASYNC_FIFO),
  426. CLK_LOOKUP_ITEM(STREAM),
  427. CLK_LOOKUP_ITEM(RTC),
  428. CLK_LOOKUP_ITEM(UART0),
  429. CLK_LOOKUP_ITEM(RANDOM_NUM_GEN),
  430. CLK_LOOKUP_ITEM(SMART_CARD_MPEG_DOMAIN),
  431. CLK_LOOKUP_ITEM(SMART_CARD),
  432. CLK_LOOKUP_ITEM(SAR_ADC),
  433. CLK_LOOKUP_ITEM(I2C),
  434. CLK_LOOKUP_ITEM(IR_REMOTE),
  435. CLK_LOOKUP_ITEM(_1200XXX),
  436. CLK_LOOKUP_ITEM(SATA),
  437. CLK_LOOKUP_ITEM(SPI1),
  438. CLK_LOOKUP_ITEM(USB1),
  439. CLK_LOOKUP_ITEM(USB0),
  440. CLK_LOOKUP_ITEM(VI_CORE),
  441. CLK_LOOKUP_ITEM(LCD),
  442. CLK_LOOKUP_ITEM(ENC480P_MPEG_DOMAIN),
  443. CLK_LOOKUP_ITEM(ENC480I),
  444. CLK_LOOKUP_ITEM(VENC_MISC),
  445. CLK_LOOKUP_ITEM(ENC480P),
  446. CLK_LOOKUP_ITEM(HDMI),
  447. CLK_LOOKUP_ITEM(VCLK3_DAC),
  448. CLK_LOOKUP_ITEM(VCLK3_MISC),
  449. CLK_LOOKUP_ITEM(VCLK3_DVI),
  450. CLK_LOOKUP_ITEM(VCLK2_VIU),
  451. CLK_LOOKUP_ITEM(VCLK2_VENC_DVI),
  452. CLK_LOOKUP_ITEM(VCLK2_VENC_ENC480P),
  453. CLK_LOOKUP_ITEM(VCLK2_VENC_BIST),
  454. CLK_LOOKUP_ITEM(VCLK1_VENC_656),
  455. CLK_LOOKUP_ITEM(VCLK1_VENC_DVI),
  456. CLK_LOOKUP_ITEM(VCLK1_VENC_ENCI),
  457. CLK_LOOKUP_ITEM(VCLK1_VENC_BIST),
  458. CLK_LOOKUP_ITEM(VIDEO_IN),
  459. CLK_LOOKUP_ITEM(WIFI)
  460. };
  461. static int __init meson_clock_init(void)
  462. {
  463. if (init_clock && init_clock != a9_clk.rate) {
  464. if (sys_clkpll_setting(0, init_clock << 1) == 0) {
  465. a9_clk.rate = init_clock;
  466. clk_sys_pll.rate = init_clock << 1;
  467. }
  468. }
  469. /* Register the lookups */
  470. clkdev_add_table(lookups, ARRAY_SIZE(lookups));
  471. return 0;
  472. }
  473. /* initialize clocking early to be available later in the boot */
  474. core_initcall(meson_clock_init);
  475. unsigned long long clkparse(const char *ptr, char **retptr)
  476. {
  477. char *endptr; /* local pointer to end of parsed string */
  478. unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
  479. switch (*endptr) {
  480. case 'G':
  481. case 'g':
  482. ret *= 1000;
  483. case 'M':
  484. case 'm':
  485. ret *= 1000;
  486. case 'K':
  487. case 'k':
  488. ret *= 1000;
  489. endptr++;
  490. default:
  491. break;
  492. }
  493. if (retptr)
  494. *retptr = endptr;
  495. return ret;
  496. }
  497. static int __init a9_clock_setup(char *ptr)
  498. {
  499. init_clock = clkparse(ptr, 0);
  500. if (sys_clkpll_setting(0, init_clock << 1) == 0) {
  501. a9_clk.rate = init_clock;
  502. clk_sys_pll.rate = init_clock << 1;
  503. }
  504. return 0;
  505. }
  506. __setup("a9_clk=", a9_clock_setup);
  507. static int __init clk81_clock_setup(char *ptr)
  508. {
  509. int clock = clkparse(ptr, 0);
  510. int divider = 4;
  511. if (clock < 100000000)
  512. divider = 8;
  513. if (other_pll_setting(0, clock * divider) == 0) {
  514. /* todo: uart baudrate depends on clk81, assume 115200 baudrate */
  515. int baudrate = (clock / (115200 * 4)) - 1;
  516. clk_other_pll.rate = clock * divider;
  517. clk81.rate = clock;
  518. WRITE_MPEG_REG(HHI_MPEG_CLK_CNTL, // MPEG clk81 set to other/4
  519. (1 << 12) | // select other PLL
  520. ((divider - 1) << 0) | // div1
  521. (1 << 7) | // cntl_hi_mpeg_div_en, enable gating
  522. (1 << 8)); // Connect clk81 to the PLL divider output
  523. CLEAR_CBUS_REG_MASK(UART0_CONTROL, (1 << 19) | 0xFFF);
  524. SET_CBUS_REG_MASK(UART0_CONTROL, (baudrate & 0xfff));
  525. CLEAR_CBUS_REG_MASK(UART1_CONTROL, (1 << 19) | 0xFFF);
  526. SET_CBUS_REG_MASK(UART1_CONTROL, (baudrate & 0xfff));
  527. }
  528. return 0;
  529. }
  530. __setup("clk81=", clk81_clock_setup);
  531. int clk_enable(struct clk *clk)
  532. {
  533. unsigned long flags;
  534. spin_lock_irqsave(&clockfw_lock, flags);
  535. if (clk->clock_index >= 0 && clk->clock_index < GCLK_IDX_MAX
  536. && clk->clock_gate_reg_adr != 0) {
  537. if (GCLK_ref[clk->clock_index]++ == 0) {
  538. SET_CBUS_REG_MASK(clk->clock_gate_reg_adr,
  539. clk->clock_gate_reg_mask);
  540. }
  541. }
  542. spin_unlock_irqrestore(&clockfw_lock, flags);
  543. return 0;
  544. }
  545. EXPORT_SYMBOL(clk_enable);
  546. void clk_disable(struct clk *clk)
  547. {
  548. unsigned long flags;
  549. spin_lock_irqsave(&clockfw_lock, flags);
  550. if (clk->clock_index >= 0 && clk->clock_index < GCLK_IDX_MAX
  551. && clk->clock_gate_reg_adr != 0) {
  552. if ((GCLK_ref[clk->clock_index] != 0)
  553. && (--GCLK_ref[clk->clock_index] == 0))
  554. CLEAR_CBUS_REG_MASK(clk->clock_gate_reg_adr,
  555. clk->clock_gate_reg_mask);
  556. }
  557. spin_unlock_irqrestore(&clockfw_lock, flags);
  558. }
  559. EXPORT_SYMBOL(clk_disable);