clk_px30.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) Copyright 2017 Rockchip Electronics Co., Ltd
  4. */
  5. #include <common.h>
  6. #include <bitfield.h>
  7. #include <clk-uclass.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <log.h>
  11. #include <malloc.h>
  12. #include <syscon.h>
  13. #include <asm/arch-rockchip/clock.h>
  14. #include <asm/arch-rockchip/cru_px30.h>
  15. #include <asm/arch-rockchip/hardware.h>
  16. #include <asm/io.h>
  17. #include <dm/lists.h>
  18. #include <dt-bindings/clock/px30-cru.h>
  19. #include <linux/bitops.h>
  20. #include <linux/delay.h>
  21. DECLARE_GLOBAL_DATA_PTR;
  22. enum {
  23. VCO_MAX_HZ = 3200U * 1000000,
  24. VCO_MIN_HZ = 800 * 1000000,
  25. OUTPUT_MAX_HZ = 3200U * 1000000,
  26. OUTPUT_MIN_HZ = 24 * 1000000,
  27. };
  28. #define PX30_VOP_PLL_LIMIT 600000000
  29. #define PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
  30. _postdiv2, _dsmpd, _frac) \
  31. { \
  32. .rate = _rate##U, \
  33. .fbdiv = _fbdiv, \
  34. .postdiv1 = _postdiv1, \
  35. .refdiv = _refdiv, \
  36. .postdiv2 = _postdiv2, \
  37. .dsmpd = _dsmpd, \
  38. .frac = _frac, \
  39. }
  40. #define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
  41. { \
  42. .rate = _rate##U, \
  43. .aclk_div = _aclk_div, \
  44. .pclk_div = _pclk_div, \
  45. }
  46. #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
  47. #define PX30_CLK_DUMP(_id, _name, _iscru) \
  48. { \
  49. .id = _id, \
  50. .name = _name, \
  51. .is_cru = _iscru, \
  52. }
  53. static struct pll_rate_table px30_pll_rates[] = {
  54. /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
  55. PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
  56. PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
  57. PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
  58. PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
  59. PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
  60. PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
  61. PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
  62. };
  63. static struct cpu_rate_table px30_cpu_rates[] = {
  64. PX30_CPUCLK_RATE(1200000000, 1, 5),
  65. PX30_CPUCLK_RATE(1008000000, 1, 5),
  66. PX30_CPUCLK_RATE(816000000, 1, 3),
  67. PX30_CPUCLK_RATE(600000000, 1, 3),
  68. PX30_CPUCLK_RATE(408000000, 1, 1),
  69. };
  70. static u8 pll_mode_shift[PLL_COUNT] = {
  71. APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
  72. NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
  73. };
  74. static u32 pll_mode_mask[PLL_COUNT] = {
  75. APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
  76. NPLL_MODE_MASK, GPLL_MODE_MASK
  77. };
  78. static struct pll_rate_table auto_table;
  79. static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
  80. enum px30_pll_id pll_id);
  81. static struct pll_rate_table *pll_clk_set_by_auto(u32 drate)
  82. {
  83. struct pll_rate_table *rate = &auto_table;
  84. u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
  85. u32 postdiv1, postdiv2 = 1;
  86. u32 fref_khz;
  87. u32 diff_khz, best_diff_khz;
  88. const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
  89. const u32 max_postdiv1 = 7, max_postdiv2 = 7;
  90. u32 vco_khz;
  91. u32 rate_khz = drate / KHz;
  92. if (!drate) {
  93. printf("%s: the frequency can't be 0 Hz\n", __func__);
  94. return NULL;
  95. }
  96. postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz);
  97. if (postdiv1 > max_postdiv1) {
  98. postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
  99. postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
  100. }
  101. vco_khz = rate_khz * postdiv1 * postdiv2;
  102. if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
  103. postdiv2 > max_postdiv2) {
  104. printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
  105. __func__, rate_khz);
  106. return NULL;
  107. }
  108. rate->postdiv1 = postdiv1;
  109. rate->postdiv2 = postdiv2;
  110. best_diff_khz = vco_khz;
  111. for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
  112. fref_khz = ref_khz / refdiv;
  113. fbdiv = vco_khz / fref_khz;
  114. if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
  115. continue;
  116. diff_khz = vco_khz - fbdiv * fref_khz;
  117. if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
  118. fbdiv++;
  119. diff_khz = fref_khz - diff_khz;
  120. }
  121. if (diff_khz >= best_diff_khz)
  122. continue;
  123. best_diff_khz = diff_khz;
  124. rate->refdiv = refdiv;
  125. rate->fbdiv = fbdiv;
  126. }
  127. if (best_diff_khz > 4 * (MHz / KHz)) {
  128. printf("%s: Failed to match output frequency %u bestis %u Hz\n",
  129. __func__, rate_khz,
  130. best_diff_khz * KHz);
  131. return NULL;
  132. }
  133. return rate;
  134. }
  135. static const struct pll_rate_table *get_pll_settings(unsigned long rate)
  136. {
  137. unsigned int rate_count = ARRAY_SIZE(px30_pll_rates);
  138. int i;
  139. for (i = 0; i < rate_count; i++) {
  140. if (rate == px30_pll_rates[i].rate)
  141. return &px30_pll_rates[i];
  142. }
  143. return pll_clk_set_by_auto(rate);
  144. }
  145. static const struct cpu_rate_table *get_cpu_settings(unsigned long rate)
  146. {
  147. unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates);
  148. int i;
  149. for (i = 0; i < rate_count; i++) {
  150. if (rate == px30_cpu_rates[i].rate)
  151. return &px30_cpu_rates[i];
  152. }
  153. return NULL;
  154. }
  155. /*
  156. * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
  157. * Formulas also embedded within the Fractional PLL Verilog model:
  158. * If DSMPD = 1 (DSM is disabled, "integer mode")
  159. * FOUTVCO = FREF / REFDIV * FBDIV
  160. * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
  161. * Where:
  162. * FOUTVCO = Fractional PLL non-divided output frequency
  163. * FOUTPOSTDIV = Fractional PLL divided output frequency
  164. * (output of second post divider)
  165. * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
  166. * REFDIV = Fractional PLL input reference clock divider
  167. * FBDIV = Integer value programmed into feedback divide
  168. *
  169. */
  170. static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode,
  171. enum px30_pll_id pll_id,
  172. unsigned long drate)
  173. {
  174. const struct pll_rate_table *rate;
  175. uint vco_hz, output_hz;
  176. rate = get_pll_settings(drate);
  177. if (!rate) {
  178. printf("%s unsupport rate\n", __func__);
  179. return -EINVAL;
  180. }
  181. /* All PLLs have same VCO and output frequency range restrictions. */
  182. vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000;
  183. output_hz = vco_hz / rate->postdiv1 / rate->postdiv2;
  184. debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
  185. pll, rate->fbdiv, rate->refdiv, rate->postdiv1,
  186. rate->postdiv2, vco_hz, output_hz);
  187. assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
  188. output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
  189. /*
  190. * When power on or changing PLL setting,
  191. * we must force PLL into slow mode to ensure output stable clock.
  192. */
  193. rk_clrsetreg(mode, pll_mode_mask[pll_id],
  194. PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
  195. /* use integer mode */
  196. rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
  197. /* Power down */
  198. rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
  199. rk_clrsetreg(&pll->con0,
  200. PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
  201. (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv);
  202. rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
  203. (rate->postdiv2 << PLL_POSTDIV2_SHIFT |
  204. rate->refdiv << PLL_REFDIV_SHIFT));
  205. /* Power Up */
  206. rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
  207. /* waiting for pll lock */
  208. while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
  209. udelay(1);
  210. rk_clrsetreg(mode, pll_mode_mask[pll_id],
  211. PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
  212. return 0;
  213. }
  214. static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode,
  215. enum px30_pll_id pll_id)
  216. {
  217. u32 refdiv, fbdiv, postdiv1, postdiv2;
  218. u32 con, shift, mask;
  219. con = readl(mode);
  220. shift = pll_mode_shift[pll_id];
  221. mask = pll_mode_mask[pll_id];
  222. switch ((con & mask) >> shift) {
  223. case PLLMUX_FROM_XIN24M:
  224. return OSC_HZ;
  225. case PLLMUX_FROM_PLL:
  226. /* normal mode */
  227. con = readl(&pll->con0);
  228. postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
  229. fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
  230. con = readl(&pll->con1);
  231. postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
  232. refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
  233. return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
  234. case PLLMUX_FROM_RTC32K:
  235. default:
  236. return 32768;
  237. }
  238. }
  239. static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  240. {
  241. struct px30_cru *cru = priv->cru;
  242. u32 div, con;
  243. switch (clk_id) {
  244. case SCLK_I2C0:
  245. con = readl(&cru->clksel_con[49]);
  246. div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
  247. break;
  248. case SCLK_I2C1:
  249. con = readl(&cru->clksel_con[49]);
  250. div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
  251. break;
  252. case SCLK_I2C2:
  253. con = readl(&cru->clksel_con[50]);
  254. div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
  255. break;
  256. case SCLK_I2C3:
  257. con = readl(&cru->clksel_con[50]);
  258. div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
  259. break;
  260. default:
  261. printf("do not support this i2c bus\n");
  262. return -EINVAL;
  263. }
  264. return DIV_TO_RATE(priv->gpll_hz, div);
  265. }
  266. static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
  267. {
  268. struct px30_cru *cru = priv->cru;
  269. int src_clk_div;
  270. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  271. assert(src_clk_div - 1 <= 127);
  272. switch (clk_id) {
  273. case SCLK_I2C0:
  274. rk_clrsetreg(&cru->clksel_con[49],
  275. CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
  276. CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
  277. (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
  278. CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
  279. break;
  280. case SCLK_I2C1:
  281. rk_clrsetreg(&cru->clksel_con[49],
  282. CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
  283. CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
  284. (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
  285. CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
  286. break;
  287. case SCLK_I2C2:
  288. rk_clrsetreg(&cru->clksel_con[50],
  289. CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
  290. CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
  291. (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
  292. CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
  293. break;
  294. case SCLK_I2C3:
  295. rk_clrsetreg(&cru->clksel_con[50],
  296. CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
  297. CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
  298. (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
  299. CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
  300. break;
  301. default:
  302. printf("do not support this i2c bus\n");
  303. return -EINVAL;
  304. }
  305. return px30_i2c_get_clk(priv, clk_id);
  306. }
  307. /*
  308. * calculate best rational approximation for a given fraction
  309. * taking into account restricted register size, e.g. to find
  310. * appropriate values for a pll with 5 bit denominator and
  311. * 8 bit numerator register fields, trying to set up with a
  312. * frequency ratio of 3.1415, one would say:
  313. *
  314. * rational_best_approximation(31415, 10000,
  315. * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
  316. *
  317. * you may look at given_numerator as a fixed point number,
  318. * with the fractional part size described in given_denominator.
  319. *
  320. * for theoretical background, see:
  321. * http://en.wikipedia.org/wiki/Continued_fraction
  322. */
  323. static void rational_best_approximation(unsigned long given_numerator,
  324. unsigned long given_denominator,
  325. unsigned long max_numerator,
  326. unsigned long max_denominator,
  327. unsigned long *best_numerator,
  328. unsigned long *best_denominator)
  329. {
  330. unsigned long n, d, n0, d0, n1, d1;
  331. n = given_numerator;
  332. d = given_denominator;
  333. n0 = 0;
  334. d1 = 0;
  335. n1 = 1;
  336. d0 = 1;
  337. for (;;) {
  338. unsigned long t, a;
  339. if (n1 > max_numerator || d1 > max_denominator) {
  340. n1 = n0;
  341. d1 = d0;
  342. break;
  343. }
  344. if (d == 0)
  345. break;
  346. t = d;
  347. a = n / d;
  348. d = n % d;
  349. n = t;
  350. t = n0 + a * n1;
  351. n0 = n1;
  352. n1 = t;
  353. t = d0 + a * d1;
  354. d0 = d1;
  355. d1 = t;
  356. }
  357. *best_numerator = n1;
  358. *best_denominator = d1;
  359. }
  360. static ulong px30_i2s_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  361. {
  362. u32 con, fracdiv, gate;
  363. u32 clk_src = priv->gpll_hz / 2;
  364. unsigned long m, n;
  365. struct px30_cru *cru = priv->cru;
  366. switch (clk_id) {
  367. case SCLK_I2S1:
  368. con = readl(&cru->clksel_con[30]);
  369. fracdiv = readl(&cru->clksel_con[31]);
  370. gate = readl(&cru->clkgate_con[10]);
  371. m = fracdiv & CLK_I2S1_FRAC_NUMERATOR_MASK;
  372. m >>= CLK_I2S1_FRAC_NUMERATOR_SHIFT;
  373. n = fracdiv & CLK_I2S1_FRAC_DENOMINATOR_MASK;
  374. n >>= CLK_I2S1_FRAC_DENOMINATOR_SHIFT;
  375. debug("con30: 0x%x, gate: 0x%x, frac: 0x%x\n",
  376. con, gate, fracdiv);
  377. break;
  378. default:
  379. printf("do not support this i2s bus\n");
  380. return -EINVAL;
  381. }
  382. return clk_src * n / m;
  383. }
  384. static ulong px30_i2s_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
  385. {
  386. u32 clk_src;
  387. unsigned long m, n, val;
  388. struct px30_cru *cru = priv->cru;
  389. clk_src = priv->gpll_hz / 2;
  390. rational_best_approximation(hz, clk_src,
  391. GENMASK(16 - 1, 0),
  392. GENMASK(16 - 1, 0),
  393. &m, &n);
  394. switch (clk_id) {
  395. case SCLK_I2S1:
  396. rk_clrsetreg(&cru->clksel_con[30],
  397. CLK_I2S1_PLL_SEL_MASK, CLK_I2S1_PLL_SEL_GPLL);
  398. rk_clrsetreg(&cru->clksel_con[30],
  399. CLK_I2S1_DIV_CON_MASK, 0x1);
  400. rk_clrsetreg(&cru->clksel_con[30],
  401. CLK_I2S1_SEL_MASK, CLK_I2S1_SEL_FRAC);
  402. val = m << CLK_I2S1_FRAC_NUMERATOR_SHIFT | n;
  403. writel(val, &cru->clksel_con[31]);
  404. rk_clrsetreg(&cru->clkgate_con[10],
  405. CLK_I2S1_OUT_MCLK_PAD_MASK,
  406. CLK_I2S1_OUT_MCLK_PAD_ENABLE);
  407. break;
  408. default:
  409. printf("do not support this i2s bus\n");
  410. return -EINVAL;
  411. }
  412. return px30_i2s_get_clk(priv, clk_id);
  413. }
  414. static ulong px30_nandc_get_clk(struct px30_clk_priv *priv)
  415. {
  416. struct px30_cru *cru = priv->cru;
  417. u32 div, con;
  418. con = readl(&cru->clksel_con[15]);
  419. div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT;
  420. return DIV_TO_RATE(priv->gpll_hz, div);
  421. }
  422. static ulong px30_nandc_set_clk(struct px30_clk_priv *priv,
  423. ulong set_rate)
  424. {
  425. struct px30_cru *cru = priv->cru;
  426. int src_clk_div;
  427. /* Select nandc source from GPLL by default */
  428. /* nandc clock defaulg div 2 internal, need provide double in cru */
  429. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate);
  430. assert(src_clk_div - 1 <= 31);
  431. rk_clrsetreg(&cru->clksel_con[15],
  432. NANDC_CLK_SEL_MASK | NANDC_PLL_MASK |
  433. NANDC_DIV_MASK,
  434. NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT |
  435. NANDC_SEL_GPLL << NANDC_PLL_SHIFT |
  436. (src_clk_div - 1) << NANDC_DIV_SHIFT);
  437. return px30_nandc_get_clk(priv);
  438. }
  439. static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id)
  440. {
  441. struct px30_cru *cru = priv->cru;
  442. u32 div, con, con_id;
  443. switch (clk_id) {
  444. case HCLK_SDMMC:
  445. case SCLK_SDMMC:
  446. con_id = 16;
  447. break;
  448. case HCLK_EMMC:
  449. case SCLK_EMMC:
  450. case SCLK_EMMC_SAMPLE:
  451. con_id = 20;
  452. break;
  453. default:
  454. return -EINVAL;
  455. }
  456. con = readl(&cru->clksel_con[con_id]);
  457. div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
  458. if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
  459. == EMMC_SEL_24M)
  460. return DIV_TO_RATE(OSC_HZ, div) / 2;
  461. else
  462. return DIV_TO_RATE(priv->gpll_hz, div) / 2;
  463. }
  464. static ulong px30_mmc_set_clk(struct px30_clk_priv *priv,
  465. ulong clk_id, ulong set_rate)
  466. {
  467. struct px30_cru *cru = priv->cru;
  468. int src_clk_div;
  469. u32 con_id;
  470. switch (clk_id) {
  471. case HCLK_SDMMC:
  472. case SCLK_SDMMC:
  473. con_id = 16;
  474. break;
  475. case HCLK_EMMC:
  476. case SCLK_EMMC:
  477. con_id = 20;
  478. break;
  479. default:
  480. return -EINVAL;
  481. }
  482. /* Select clk_sdmmc/emmc source from GPLL by default */
  483. /* mmc clock defaulg div 2 internal, need provide double in cru */
  484. src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
  485. if (src_clk_div > 127) {
  486. /* use 24MHz source for 400KHz clock */
  487. src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
  488. rk_clrsetreg(&cru->clksel_con[con_id],
  489. EMMC_PLL_MASK | EMMC_DIV_MASK,
  490. EMMC_SEL_24M << EMMC_PLL_SHIFT |
  491. (src_clk_div - 1) << EMMC_DIV_SHIFT);
  492. } else {
  493. rk_clrsetreg(&cru->clksel_con[con_id],
  494. EMMC_PLL_MASK | EMMC_DIV_MASK,
  495. EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
  496. (src_clk_div - 1) << EMMC_DIV_SHIFT);
  497. }
  498. rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
  499. EMMC_CLK_SEL_EMMC);
  500. return px30_mmc_get_clk(priv, clk_id);
  501. }
  502. static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  503. {
  504. struct px30_cru *cru = priv->cru;
  505. u32 div, con;
  506. switch (clk_id) {
  507. case SCLK_PWM0:
  508. con = readl(&cru->clksel_con[52]);
  509. div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
  510. break;
  511. case SCLK_PWM1:
  512. con = readl(&cru->clksel_con[52]);
  513. div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
  514. break;
  515. default:
  516. printf("do not support this pwm bus\n");
  517. return -EINVAL;
  518. }
  519. return DIV_TO_RATE(priv->gpll_hz, div);
  520. }
  521. static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
  522. {
  523. struct px30_cru *cru = priv->cru;
  524. int src_clk_div;
  525. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  526. assert(src_clk_div - 1 <= 127);
  527. switch (clk_id) {
  528. case SCLK_PWM0:
  529. rk_clrsetreg(&cru->clksel_con[52],
  530. CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
  531. CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
  532. (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
  533. CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
  534. break;
  535. case SCLK_PWM1:
  536. rk_clrsetreg(&cru->clksel_con[52],
  537. CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
  538. CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
  539. (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
  540. CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
  541. break;
  542. default:
  543. printf("do not support this pwm bus\n");
  544. return -EINVAL;
  545. }
  546. return px30_pwm_get_clk(priv, clk_id);
  547. }
  548. static ulong px30_saradc_get_clk(struct px30_clk_priv *priv)
  549. {
  550. struct px30_cru *cru = priv->cru;
  551. u32 div, con;
  552. con = readl(&cru->clksel_con[55]);
  553. div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
  554. return DIV_TO_RATE(OSC_HZ, div);
  555. }
  556. static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz)
  557. {
  558. struct px30_cru *cru = priv->cru;
  559. int src_clk_div;
  560. src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
  561. assert(src_clk_div - 1 <= 2047);
  562. rk_clrsetreg(&cru->clksel_con[55],
  563. CLK_SARADC_DIV_CON_MASK,
  564. (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
  565. return px30_saradc_get_clk(priv);
  566. }
  567. static ulong px30_tsadc_get_clk(struct px30_clk_priv *priv)
  568. {
  569. struct px30_cru *cru = priv->cru;
  570. u32 div, con;
  571. con = readl(&cru->clksel_con[54]);
  572. div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
  573. return DIV_TO_RATE(OSC_HZ, div);
  574. }
  575. static ulong px30_tsadc_set_clk(struct px30_clk_priv *priv, uint hz)
  576. {
  577. struct px30_cru *cru = priv->cru;
  578. int src_clk_div;
  579. src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
  580. assert(src_clk_div - 1 <= 2047);
  581. rk_clrsetreg(&cru->clksel_con[54],
  582. CLK_SARADC_DIV_CON_MASK,
  583. (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
  584. return px30_tsadc_get_clk(priv);
  585. }
  586. static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  587. {
  588. struct px30_cru *cru = priv->cru;
  589. u32 div, con;
  590. switch (clk_id) {
  591. case SCLK_SPI0:
  592. con = readl(&cru->clksel_con[53]);
  593. div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
  594. break;
  595. case SCLK_SPI1:
  596. con = readl(&cru->clksel_con[53]);
  597. div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
  598. break;
  599. default:
  600. printf("do not support this pwm bus\n");
  601. return -EINVAL;
  602. }
  603. return DIV_TO_RATE(priv->gpll_hz, div);
  604. }
  605. static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
  606. {
  607. struct px30_cru *cru = priv->cru;
  608. int src_clk_div;
  609. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  610. assert(src_clk_div - 1 <= 127);
  611. switch (clk_id) {
  612. case SCLK_SPI0:
  613. rk_clrsetreg(&cru->clksel_con[53],
  614. CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
  615. CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
  616. (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
  617. CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
  618. break;
  619. case SCLK_SPI1:
  620. rk_clrsetreg(&cru->clksel_con[53],
  621. CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
  622. CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
  623. (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
  624. CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
  625. break;
  626. default:
  627. printf("do not support this pwm bus\n");
  628. return -EINVAL;
  629. }
  630. return px30_spi_get_clk(priv, clk_id);
  631. }
  632. static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  633. {
  634. struct px30_cru *cru = priv->cru;
  635. u32 div, con, parent;
  636. switch (clk_id) {
  637. case ACLK_VOPB:
  638. case ACLK_VOPL:
  639. con = readl(&cru->clksel_con[3]);
  640. div = con & ACLK_VO_DIV_MASK;
  641. parent = priv->gpll_hz;
  642. break;
  643. case DCLK_VOPB:
  644. con = readl(&cru->clksel_con[5]);
  645. div = con & DCLK_VOPB_DIV_MASK;
  646. parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL);
  647. break;
  648. case DCLK_VOPL:
  649. con = readl(&cru->clksel_con[8]);
  650. div = con & DCLK_VOPL_DIV_MASK;
  651. parent = rkclk_pll_get_rate(&cru->pll[NPLL], &cru->mode, NPLL);
  652. break;
  653. default:
  654. return -ENOENT;
  655. }
  656. return DIV_TO_RATE(parent, div);
  657. }
  658. static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
  659. {
  660. struct px30_cru *cru = priv->cru;
  661. ulong npll_hz;
  662. int src_clk_div;
  663. switch (clk_id) {
  664. case ACLK_VOPB:
  665. case ACLK_VOPL:
  666. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  667. assert(src_clk_div - 1 <= 31);
  668. rk_clrsetreg(&cru->clksel_con[3],
  669. ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
  670. ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
  671. (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
  672. break;
  673. case DCLK_VOPB:
  674. if (hz < PX30_VOP_PLL_LIMIT) {
  675. src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz);
  676. if (src_clk_div % 2)
  677. src_clk_div = src_clk_div - 1;
  678. } else {
  679. src_clk_div = 1;
  680. }
  681. assert(src_clk_div - 1 <= 255);
  682. rkclk_set_pll(&cru->pll[CPLL], &cru->mode,
  683. CPLL, hz * src_clk_div);
  684. rk_clrsetreg(&cru->clksel_con[5],
  685. DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
  686. DCLK_VOPB_DIV_MASK,
  687. DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
  688. DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
  689. (src_clk_div - 1) << DCLK_VOPB_DIV_SHIFT);
  690. break;
  691. case DCLK_VOPL:
  692. npll_hz = px30_clk_get_pll_rate(priv, NPLL);
  693. if (npll_hz >= PX30_VOP_PLL_LIMIT && npll_hz >= hz &&
  694. npll_hz % hz == 0) {
  695. src_clk_div = npll_hz / hz;
  696. assert(src_clk_div - 1 <= 255);
  697. } else {
  698. if (hz < PX30_VOP_PLL_LIMIT) {
  699. src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT,
  700. hz);
  701. if (src_clk_div % 2)
  702. src_clk_div = src_clk_div - 1;
  703. } else {
  704. src_clk_div = 1;
  705. }
  706. assert(src_clk_div - 1 <= 255);
  707. rkclk_set_pll(&cru->pll[NPLL], &cru->mode, NPLL,
  708. hz * src_clk_div);
  709. }
  710. rk_clrsetreg(&cru->clksel_con[8],
  711. DCLK_VOPL_SEL_MASK | DCLK_VOPL_PLL_SEL_MASK |
  712. DCLK_VOPL_DIV_MASK,
  713. DCLK_VOPL_SEL_DIVOUT << DCLK_VOPL_SEL_SHIFT |
  714. DCLK_VOPL_PLL_SEL_NPLL << DCLK_VOPL_PLL_SEL_SHIFT |
  715. (src_clk_div - 1) << DCLK_VOPL_DIV_SHIFT);
  716. break;
  717. default:
  718. printf("do not support this vop freq\n");
  719. return -EINVAL;
  720. }
  721. return px30_vop_get_clk(priv, clk_id);
  722. }
  723. static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  724. {
  725. struct px30_cru *cru = priv->cru;
  726. u32 div, con, parent;
  727. switch (clk_id) {
  728. case ACLK_BUS_PRE:
  729. con = readl(&cru->clksel_con[23]);
  730. div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
  731. parent = priv->gpll_hz;
  732. break;
  733. case HCLK_BUS_PRE:
  734. con = readl(&cru->clksel_con[24]);
  735. div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
  736. parent = priv->gpll_hz;
  737. break;
  738. case PCLK_BUS_PRE:
  739. case PCLK_WDT_NS:
  740. parent = px30_bus_get_clk(priv, ACLK_BUS_PRE);
  741. con = readl(&cru->clksel_con[24]);
  742. div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
  743. break;
  744. default:
  745. return -ENOENT;
  746. }
  747. return DIV_TO_RATE(parent, div);
  748. }
  749. static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id,
  750. ulong hz)
  751. {
  752. struct px30_cru *cru = priv->cru;
  753. int src_clk_div;
  754. /*
  755. * select gpll as pd_bus bus clock source and
  756. * set up dependent divisors for PCLK/HCLK and ACLK clocks.
  757. */
  758. switch (clk_id) {
  759. case ACLK_BUS_PRE:
  760. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  761. assert(src_clk_div - 1 <= 31);
  762. rk_clrsetreg(&cru->clksel_con[23],
  763. BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
  764. BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
  765. (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
  766. break;
  767. case HCLK_BUS_PRE:
  768. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  769. assert(src_clk_div - 1 <= 31);
  770. rk_clrsetreg(&cru->clksel_con[24],
  771. BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK,
  772. BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
  773. (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
  774. break;
  775. case PCLK_BUS_PRE:
  776. src_clk_div =
  777. DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz);
  778. assert(src_clk_div - 1 <= 3);
  779. rk_clrsetreg(&cru->clksel_con[24],
  780. BUS_PCLK_DIV_MASK,
  781. (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
  782. break;
  783. default:
  784. printf("do not support this bus freq\n");
  785. return -EINVAL;
  786. }
  787. return px30_bus_get_clk(priv, clk_id);
  788. }
  789. static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  790. {
  791. struct px30_cru *cru = priv->cru;
  792. u32 div, con, parent;
  793. switch (clk_id) {
  794. case ACLK_PERI_PRE:
  795. con = readl(&cru->clksel_con[14]);
  796. div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
  797. parent = priv->gpll_hz;
  798. break;
  799. case HCLK_PERI_PRE:
  800. con = readl(&cru->clksel_con[14]);
  801. div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
  802. parent = priv->gpll_hz;
  803. break;
  804. default:
  805. return -ENOENT;
  806. }
  807. return DIV_TO_RATE(parent, div);
  808. }
  809. static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id,
  810. ulong hz)
  811. {
  812. struct px30_cru *cru = priv->cru;
  813. int src_clk_div;
  814. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  815. assert(src_clk_div - 1 <= 31);
  816. /*
  817. * select gpll as pd_peri bus clock source and
  818. * set up dependent divisors for HCLK and ACLK clocks.
  819. */
  820. switch (clk_id) {
  821. case ACLK_PERI_PRE:
  822. rk_clrsetreg(&cru->clksel_con[14],
  823. PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
  824. PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
  825. (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
  826. break;
  827. case HCLK_PERI_PRE:
  828. rk_clrsetreg(&cru->clksel_con[14],
  829. PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK,
  830. PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
  831. (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
  832. break;
  833. default:
  834. printf("do not support this peri freq\n");
  835. return -EINVAL;
  836. }
  837. return px30_peri_get_clk(priv, clk_id);
  838. }
  839. #ifndef CONFIG_SPL_BUILD
  840. static ulong px30_crypto_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  841. {
  842. struct px30_cru *cru = priv->cru;
  843. u32 div, con, parent;
  844. switch (clk_id) {
  845. case SCLK_CRYPTO:
  846. con = readl(&cru->clksel_con[25]);
  847. div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
  848. parent = priv->gpll_hz;
  849. break;
  850. case SCLK_CRYPTO_APK:
  851. con = readl(&cru->clksel_con[25]);
  852. div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
  853. parent = priv->gpll_hz;
  854. break;
  855. default:
  856. return -ENOENT;
  857. }
  858. return DIV_TO_RATE(parent, div);
  859. }
  860. static ulong px30_crypto_set_clk(struct px30_clk_priv *priv, ulong clk_id,
  861. ulong hz)
  862. {
  863. struct px30_cru *cru = priv->cru;
  864. int src_clk_div;
  865. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  866. assert(src_clk_div - 1 <= 31);
  867. /*
  868. * select gpll as crypto clock source and
  869. * set up dependent divisors for crypto clocks.
  870. */
  871. switch (clk_id) {
  872. case SCLK_CRYPTO:
  873. rk_clrsetreg(&cru->clksel_con[25],
  874. CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
  875. CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT |
  876. (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
  877. break;
  878. case SCLK_CRYPTO_APK:
  879. rk_clrsetreg(&cru->clksel_con[25],
  880. CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
  881. CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT |
  882. (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
  883. break;
  884. default:
  885. printf("do not support this peri freq\n");
  886. return -EINVAL;
  887. }
  888. return px30_crypto_get_clk(priv, clk_id);
  889. }
  890. static ulong px30_i2s1_mclk_get_clk(struct px30_clk_priv *priv, ulong clk_id)
  891. {
  892. struct px30_cru *cru = priv->cru;
  893. u32 con;
  894. con = readl(&cru->clksel_con[30]);
  895. if (!(con & CLK_I2S1_OUT_SEL_MASK))
  896. return -ENOENT;
  897. return 12000000;
  898. }
  899. static ulong px30_i2s1_mclk_set_clk(struct px30_clk_priv *priv, ulong clk_id,
  900. ulong hz)
  901. {
  902. struct px30_cru *cru = priv->cru;
  903. if (hz != 12000000) {
  904. printf("do not support this i2s1_mclk freq\n");
  905. return -EINVAL;
  906. }
  907. rk_clrsetreg(&cru->clksel_con[30], CLK_I2S1_OUT_SEL_MASK,
  908. CLK_I2S1_OUT_SEL_OSC);
  909. rk_clrsetreg(&cru->clkgate_con[10], CLK_I2S1_OUT_MCLK_PAD_MASK,
  910. CLK_I2S1_OUT_MCLK_PAD_ENABLE);
  911. return px30_i2s1_mclk_get_clk(priv, clk_id);
  912. }
  913. static ulong px30_mac_set_clk(struct px30_clk_priv *priv, uint hz)
  914. {
  915. struct px30_cru *cru = priv->cru;
  916. u32 con = readl(&cru->clksel_con[22]);
  917. ulong pll_rate;
  918. u8 div;
  919. if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_CPLL)
  920. pll_rate = px30_clk_get_pll_rate(priv, CPLL);
  921. else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
  922. pll_rate = px30_clk_get_pll_rate(priv, NPLL);
  923. else
  924. pll_rate = priv->gpll_hz;
  925. /*default set 50MHZ for gmac*/
  926. if (!hz)
  927. hz = 50000000;
  928. div = DIV_ROUND_UP(pll_rate, hz) - 1;
  929. assert(div < 32);
  930. rk_clrsetreg(&cru->clksel_con[22], CLK_GMAC_DIV_MASK,
  931. div << CLK_GMAC_DIV_SHIFT);
  932. return DIV_TO_RATE(pll_rate, div);
  933. }
  934. static int px30_mac_set_speed_clk(struct px30_clk_priv *priv, uint hz)
  935. {
  936. struct px30_cru *cru = priv->cru;
  937. if (hz != 2500000 && hz != 25000000) {
  938. debug("Unsupported mac speed:%d\n", hz);
  939. return -EINVAL;
  940. }
  941. rk_clrsetreg(&cru->clksel_con[23], RMII_CLK_SEL_MASK,
  942. ((hz == 2500000) ? 0 : 1) << RMII_CLK_SEL_SHIFT);
  943. return 0;
  944. }
  945. #endif
  946. static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
  947. enum px30_pll_id pll_id)
  948. {
  949. struct px30_cru *cru = priv->cru;
  950. return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
  951. }
  952. static ulong px30_clk_set_pll_rate(struct px30_clk_priv *priv,
  953. enum px30_pll_id pll_id, ulong hz)
  954. {
  955. struct px30_cru *cru = priv->cru;
  956. if (rkclk_set_pll(&cru->pll[pll_id], &cru->mode, pll_id, hz))
  957. return -EINVAL;
  958. return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
  959. }
  960. static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz)
  961. {
  962. struct px30_cru *cru = priv->cru;
  963. const struct cpu_rate_table *rate;
  964. ulong old_rate;
  965. rate = get_cpu_settings(hz);
  966. if (!rate) {
  967. printf("%s unsupport rate\n", __func__);
  968. return -EINVAL;
  969. }
  970. /*
  971. * select apll as cpu/core clock pll source and
  972. * set up dependent divisors for PERI and ACLK clocks.
  973. * core hz : apll = 1:1
  974. */
  975. old_rate = px30_clk_get_pll_rate(priv, APLL);
  976. if (old_rate > hz) {
  977. if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
  978. return -EINVAL;
  979. rk_clrsetreg(&cru->clksel_con[0],
  980. CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
  981. CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
  982. rate->aclk_div << CORE_ACLK_DIV_SHIFT |
  983. rate->pclk_div << CORE_DBG_DIV_SHIFT |
  984. CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
  985. 0 << CORE_DIV_CON_SHIFT);
  986. } else if (old_rate < hz) {
  987. rk_clrsetreg(&cru->clksel_con[0],
  988. CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
  989. CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
  990. rate->aclk_div << CORE_ACLK_DIV_SHIFT |
  991. rate->pclk_div << CORE_DBG_DIV_SHIFT |
  992. CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
  993. 0 << CORE_DIV_CON_SHIFT);
  994. if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
  995. return -EINVAL;
  996. }
  997. return px30_clk_get_pll_rate(priv, APLL);
  998. }
  999. static ulong px30_clk_get_rate(struct clk *clk)
  1000. {
  1001. struct px30_clk_priv *priv = dev_get_priv(clk->dev);
  1002. ulong rate = 0;
  1003. if (!priv->gpll_hz && clk->id > ARMCLK) {
  1004. printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
  1005. return -ENOENT;
  1006. }
  1007. debug("%s %ld\n", __func__, clk->id);
  1008. switch (clk->id) {
  1009. case PLL_APLL:
  1010. rate = px30_clk_get_pll_rate(priv, APLL);
  1011. break;
  1012. case PLL_DPLL:
  1013. rate = px30_clk_get_pll_rate(priv, DPLL);
  1014. break;
  1015. case PLL_CPLL:
  1016. rate = px30_clk_get_pll_rate(priv, CPLL);
  1017. break;
  1018. case PLL_NPLL:
  1019. rate = px30_clk_get_pll_rate(priv, NPLL);
  1020. break;
  1021. case ARMCLK:
  1022. rate = px30_clk_get_pll_rate(priv, APLL);
  1023. break;
  1024. case HCLK_SDMMC:
  1025. case HCLK_EMMC:
  1026. case SCLK_SDMMC:
  1027. case SCLK_EMMC:
  1028. case SCLK_EMMC_SAMPLE:
  1029. rate = px30_mmc_get_clk(priv, clk->id);
  1030. break;
  1031. case SCLK_I2C0:
  1032. case SCLK_I2C1:
  1033. case SCLK_I2C2:
  1034. case SCLK_I2C3:
  1035. rate = px30_i2c_get_clk(priv, clk->id);
  1036. break;
  1037. case SCLK_I2S1:
  1038. rate = px30_i2s_get_clk(priv, clk->id);
  1039. break;
  1040. case SCLK_NANDC:
  1041. rate = px30_nandc_get_clk(priv);
  1042. break;
  1043. case SCLK_PWM0:
  1044. case SCLK_PWM1:
  1045. rate = px30_pwm_get_clk(priv, clk->id);
  1046. break;
  1047. case SCLK_SARADC:
  1048. rate = px30_saradc_get_clk(priv);
  1049. break;
  1050. case SCLK_TSADC:
  1051. rate = px30_tsadc_get_clk(priv);
  1052. break;
  1053. case SCLK_SPI0:
  1054. case SCLK_SPI1:
  1055. rate = px30_spi_get_clk(priv, clk->id);
  1056. break;
  1057. case ACLK_VOPB:
  1058. case ACLK_VOPL:
  1059. case DCLK_VOPB:
  1060. case DCLK_VOPL:
  1061. rate = px30_vop_get_clk(priv, clk->id);
  1062. break;
  1063. case ACLK_BUS_PRE:
  1064. case HCLK_BUS_PRE:
  1065. case PCLK_BUS_PRE:
  1066. case PCLK_WDT_NS:
  1067. rate = px30_bus_get_clk(priv, clk->id);
  1068. break;
  1069. case ACLK_PERI_PRE:
  1070. case HCLK_PERI_PRE:
  1071. rate = px30_peri_get_clk(priv, clk->id);
  1072. break;
  1073. #ifndef CONFIG_SPL_BUILD
  1074. case SCLK_CRYPTO:
  1075. case SCLK_CRYPTO_APK:
  1076. rate = px30_crypto_get_clk(priv, clk->id);
  1077. break;
  1078. #endif
  1079. default:
  1080. return -ENOENT;
  1081. }
  1082. return rate;
  1083. }
  1084. static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
  1085. {
  1086. struct px30_clk_priv *priv = dev_get_priv(clk->dev);
  1087. ulong ret = 0;
  1088. if (!priv->gpll_hz && clk->id > ARMCLK) {
  1089. printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
  1090. return -ENOENT;
  1091. }
  1092. debug("%s %ld %ld\n", __func__, clk->id, rate);
  1093. switch (clk->id) {
  1094. case PLL_NPLL:
  1095. ret = px30_clk_set_pll_rate(priv, NPLL, rate);
  1096. break;
  1097. case ARMCLK:
  1098. ret = px30_armclk_set_clk(priv, rate);
  1099. break;
  1100. case HCLK_SDMMC:
  1101. case HCLK_EMMC:
  1102. case SCLK_SDMMC:
  1103. case SCLK_EMMC:
  1104. ret = px30_mmc_set_clk(priv, clk->id, rate);
  1105. break;
  1106. case SCLK_I2C0:
  1107. case SCLK_I2C1:
  1108. case SCLK_I2C2:
  1109. case SCLK_I2C3:
  1110. ret = px30_i2c_set_clk(priv, clk->id, rate);
  1111. break;
  1112. case SCLK_I2S1:
  1113. ret = px30_i2s_set_clk(priv, clk->id, rate);
  1114. break;
  1115. case SCLK_NANDC:
  1116. ret = px30_nandc_set_clk(priv, rate);
  1117. break;
  1118. case SCLK_PWM0:
  1119. case SCLK_PWM1:
  1120. ret = px30_pwm_set_clk(priv, clk->id, rate);
  1121. break;
  1122. case SCLK_SARADC:
  1123. ret = px30_saradc_set_clk(priv, rate);
  1124. break;
  1125. case SCLK_TSADC:
  1126. ret = px30_tsadc_set_clk(priv, rate);
  1127. break;
  1128. case SCLK_SPI0:
  1129. case SCLK_SPI1:
  1130. ret = px30_spi_set_clk(priv, clk->id, rate);
  1131. break;
  1132. case ACLK_VOPB:
  1133. case ACLK_VOPL:
  1134. case DCLK_VOPB:
  1135. case DCLK_VOPL:
  1136. ret = px30_vop_set_clk(priv, clk->id, rate);
  1137. break;
  1138. case ACLK_BUS_PRE:
  1139. case HCLK_BUS_PRE:
  1140. case PCLK_BUS_PRE:
  1141. ret = px30_bus_set_clk(priv, clk->id, rate);
  1142. break;
  1143. case ACLK_PERI_PRE:
  1144. case HCLK_PERI_PRE:
  1145. ret = px30_peri_set_clk(priv, clk->id, rate);
  1146. break;
  1147. #ifndef CONFIG_SPL_BUILD
  1148. case SCLK_CRYPTO:
  1149. case SCLK_CRYPTO_APK:
  1150. ret = px30_crypto_set_clk(priv, clk->id, rate);
  1151. break;
  1152. case SCLK_I2S1_OUT:
  1153. ret = px30_i2s1_mclk_set_clk(priv, clk->id, rate);
  1154. break;
  1155. case SCLK_GMAC:
  1156. case SCLK_GMAC_SRC:
  1157. ret = px30_mac_set_clk(priv, rate);
  1158. break;
  1159. case SCLK_GMAC_RMII:
  1160. ret = px30_mac_set_speed_clk(priv, rate);
  1161. break;
  1162. #endif
  1163. default:
  1164. return -ENOENT;
  1165. }
  1166. return ret;
  1167. }
  1168. #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
  1169. static int px30_gmac_set_parent(struct clk *clk, struct clk *parent)
  1170. {
  1171. struct px30_clk_priv *priv = dev_get_priv(clk->dev);
  1172. struct px30_cru *cru = priv->cru;
  1173. if (parent->id == SCLK_GMAC_SRC) {
  1174. debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
  1175. rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
  1176. RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
  1177. } else {
  1178. debug("%s: switching GMAC to external clock\n", __func__);
  1179. rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
  1180. RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
  1181. }
  1182. return 0;
  1183. }
  1184. static int px30_clk_set_parent(struct clk *clk, struct clk *parent)
  1185. {
  1186. switch (clk->id) {
  1187. case SCLK_GMAC:
  1188. return px30_gmac_set_parent(clk, parent);
  1189. default:
  1190. return -ENOENT;
  1191. }
  1192. }
  1193. #endif
  1194. static int px30_clk_enable(struct clk *clk)
  1195. {
  1196. switch (clk->id) {
  1197. case HCLK_HOST:
  1198. case SCLK_GMAC:
  1199. case SCLK_GMAC_RX_TX:
  1200. case SCLK_MAC_REF:
  1201. case SCLK_MAC_REFOUT:
  1202. case ACLK_GMAC:
  1203. case PCLK_GMAC:
  1204. case SCLK_GMAC_RMII:
  1205. /* Required to successfully probe the Designware GMAC driver */
  1206. return 0;
  1207. }
  1208. debug("%s: unsupported clk %ld\n", __func__, clk->id);
  1209. return -ENOENT;
  1210. }
  1211. static struct clk_ops px30_clk_ops = {
  1212. .get_rate = px30_clk_get_rate,
  1213. .set_rate = px30_clk_set_rate,
  1214. #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
  1215. .set_parent = px30_clk_set_parent,
  1216. #endif
  1217. .enable = px30_clk_enable,
  1218. };
  1219. static void px30_clk_init(struct px30_clk_priv *priv)
  1220. {
  1221. ulong npll_hz;
  1222. int ret;
  1223. npll_hz = px30_clk_get_pll_rate(priv, NPLL);
  1224. if (npll_hz != NPLL_HZ) {
  1225. ret = px30_clk_set_pll_rate(priv, NPLL, NPLL_HZ);
  1226. if (ret < 0)
  1227. printf("%s failed to set npll rate\n", __func__);
  1228. }
  1229. px30_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ);
  1230. px30_bus_set_clk(priv, HCLK_BUS_PRE, HCLK_BUS_HZ);
  1231. px30_bus_set_clk(priv, PCLK_BUS_PRE, PCLK_BUS_HZ);
  1232. px30_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ);
  1233. px30_peri_set_clk(priv, HCLK_PERI_PRE, HCLK_PERI_HZ);
  1234. }
  1235. static int px30_clk_probe(struct udevice *dev)
  1236. {
  1237. struct px30_clk_priv *priv = dev_get_priv(dev);
  1238. struct clk clk_gpll;
  1239. int ret;
  1240. if (px30_clk_get_pll_rate(priv, APLL) != APLL_HZ)
  1241. px30_armclk_set_clk(priv, APLL_HZ);
  1242. /* get the GPLL rate from the pmucru */
  1243. ret = clk_get_by_name(dev, "gpll", &clk_gpll);
  1244. if (ret) {
  1245. printf("%s: failed to get gpll clk from pmucru\n", __func__);
  1246. return ret;
  1247. }
  1248. priv->gpll_hz = clk_get_rate(&clk_gpll);
  1249. px30_clk_init(priv);
  1250. return 0;
  1251. }
  1252. static int px30_clk_of_to_plat(struct udevice *dev)
  1253. {
  1254. struct px30_clk_priv *priv = dev_get_priv(dev);
  1255. priv->cru = dev_read_addr_ptr(dev);
  1256. return 0;
  1257. }
  1258. static int px30_clk_bind(struct udevice *dev)
  1259. {
  1260. int ret;
  1261. struct udevice *sys_child;
  1262. struct sysreset_reg *priv;
  1263. /* The reset driver does not have a device node, so bind it here */
  1264. ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
  1265. &sys_child);
  1266. if (ret) {
  1267. debug("Warning: No sysreset driver: ret=%d\n", ret);
  1268. } else {
  1269. priv = malloc(sizeof(struct sysreset_reg));
  1270. priv->glb_srst_fst_value = offsetof(struct px30_cru,
  1271. glb_srst_fst);
  1272. priv->glb_srst_snd_value = offsetof(struct px30_cru,
  1273. glb_srst_snd);
  1274. sys_child->priv = priv;
  1275. }
  1276. #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
  1277. ret = offsetof(struct px30_cru, softrst_con[0]);
  1278. ret = rockchip_reset_bind(dev, ret, 12);
  1279. if (ret)
  1280. debug("Warning: software reset driver bind faile\n");
  1281. #endif
  1282. return 0;
  1283. }
  1284. static const struct udevice_id px30_clk_ids[] = {
  1285. { .compatible = "rockchip,px30-cru" },
  1286. { }
  1287. };
  1288. U_BOOT_DRIVER(rockchip_px30_cru) = {
  1289. .name = "rockchip_px30_cru",
  1290. .id = UCLASS_CLK,
  1291. .of_match = px30_clk_ids,
  1292. .priv_auto = sizeof(struct px30_clk_priv),
  1293. .of_to_plat = px30_clk_of_to_plat,
  1294. .ops = &px30_clk_ops,
  1295. .bind = px30_clk_bind,
  1296. .probe = px30_clk_probe,
  1297. };
  1298. static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv)
  1299. {
  1300. struct px30_pmucru *pmucru = priv->pmucru;
  1301. u32 div, con;
  1302. con = readl(&pmucru->pmu_clksel_con[0]);
  1303. div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT;
  1304. return DIV_TO_RATE(priv->gpll_hz, div);
  1305. }
  1306. static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
  1307. {
  1308. struct px30_pmucru *pmucru = priv->pmucru;
  1309. int src_clk_div;
  1310. src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
  1311. assert(src_clk_div - 1 <= 31);
  1312. rk_clrsetreg(&pmucru->pmu_clksel_con[0],
  1313. CLK_PMU_PCLK_DIV_MASK,
  1314. (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT);
  1315. return px30_pclk_pmu_get_pmuclk(priv);
  1316. }
  1317. static ulong px30_pmuclk_get_gpll_rate(struct px30_pmuclk_priv *priv)
  1318. {
  1319. struct px30_pmucru *pmucru = priv->pmucru;
  1320. return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
  1321. }
  1322. static ulong px30_pmuclk_set_gpll_rate(struct px30_pmuclk_priv *priv, ulong hz)
  1323. {
  1324. struct px30_pmucru *pmucru = priv->pmucru;
  1325. ulong pclk_pmu_rate;
  1326. u32 div;
  1327. if (priv->gpll_hz == hz)
  1328. return priv->gpll_hz;
  1329. div = DIV_ROUND_UP(hz, priv->gpll_hz);
  1330. /* save clock rate */
  1331. pclk_pmu_rate = px30_pclk_pmu_get_pmuclk(priv);
  1332. /* avoid rate too large, reduce rate first */
  1333. px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate / div);
  1334. /* change gpll rate */
  1335. rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz);
  1336. priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
  1337. /* restore clock rate */
  1338. px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate);
  1339. return priv->gpll_hz;
  1340. }
  1341. static ulong px30_pmuclk_get_rate(struct clk *clk)
  1342. {
  1343. struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
  1344. ulong rate = 0;
  1345. debug("%s %ld\n", __func__, clk->id);
  1346. switch (clk->id) {
  1347. case PLL_GPLL:
  1348. rate = px30_pmuclk_get_gpll_rate(priv);
  1349. break;
  1350. case PCLK_PMU_PRE:
  1351. rate = px30_pclk_pmu_get_pmuclk(priv);
  1352. break;
  1353. default:
  1354. return -ENOENT;
  1355. }
  1356. return rate;
  1357. }
  1358. static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate)
  1359. {
  1360. struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
  1361. ulong ret = 0;
  1362. debug("%s %ld %ld\n", __func__, clk->id, rate);
  1363. switch (clk->id) {
  1364. case PLL_GPLL:
  1365. ret = px30_pmuclk_set_gpll_rate(priv, rate);
  1366. break;
  1367. case PCLK_PMU_PRE:
  1368. ret = px30_pclk_pmu_set_pmuclk(priv, rate);
  1369. break;
  1370. default:
  1371. return -ENOENT;
  1372. }
  1373. return ret;
  1374. }
  1375. static struct clk_ops px30_pmuclk_ops = {
  1376. .get_rate = px30_pmuclk_get_rate,
  1377. .set_rate = px30_pmuclk_set_rate,
  1378. };
  1379. static void px30_pmuclk_init(struct px30_pmuclk_priv *priv)
  1380. {
  1381. priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
  1382. px30_pmuclk_set_gpll_rate(priv, GPLL_HZ);
  1383. px30_pclk_pmu_set_pmuclk(priv, PCLK_PMU_HZ);
  1384. }
  1385. static int px30_pmuclk_probe(struct udevice *dev)
  1386. {
  1387. struct px30_pmuclk_priv *priv = dev_get_priv(dev);
  1388. px30_pmuclk_init(priv);
  1389. return 0;
  1390. }
  1391. static int px30_pmuclk_of_to_plat(struct udevice *dev)
  1392. {
  1393. struct px30_pmuclk_priv *priv = dev_get_priv(dev);
  1394. priv->pmucru = dev_read_addr_ptr(dev);
  1395. return 0;
  1396. }
  1397. static const struct udevice_id px30_pmuclk_ids[] = {
  1398. { .compatible = "rockchip,px30-pmucru" },
  1399. { }
  1400. };
  1401. U_BOOT_DRIVER(rockchip_px30_pmucru) = {
  1402. .name = "rockchip_px30_pmucru",
  1403. .id = UCLASS_CLK,
  1404. .of_match = px30_pmuclk_ids,
  1405. .priv_auto = sizeof(struct px30_pmuclk_priv),
  1406. .of_to_plat = px30_pmuclk_of_to_plat,
  1407. .ops = &px30_pmuclk_ops,
  1408. .probe = px30_pmuclk_probe,
  1409. };