clock_config.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. /*
  2. * Copyright (C) 2020-2021 Alibaba Group Holding Limited
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/types.h>
  9. #include <linux/bitops.h>
  10. #include <linux/errno.h>
  11. #include <linux/printk.h>
  12. #include <div64.h>
  13. #include <thead/clock_config.h>
  14. #define ap_base ((void __iomem *)0xffff011000)
  15. #define aon_base ((void __iomem *)0xfffff46000)
  16. #define AP_REE_CLKGEN_BASE (0xffef010000)
  17. #define AP_DPU0_PLL_CFG1 (AP_REE_CLKGEN_BASE + 0x44)
  18. #define AP_DPU1_PLL_CFG1 (AP_REE_CLKGEN_BASE + 0x54)
  19. #define AP_PERI_CLK_CFG (AP_REE_CLKGEN_BASE + 0x204)
  20. #define AP_CTRL_CLK_CFG (AP_REE_CLKGEN_BASE + 0x208)
  21. #define MISCSYS_TEE_REG_BASE (0xfffc02d000)
  22. #define MISCSYS_TEE_CLK_CTRL_TEE (MISCSYS_TEE_REG_BASE + 0x120)
  23. /* VOSYS_SYREG_R */
  24. #define VOSYS_SYSREG_BASE (0xffef528000)
  25. #define VOSYS_CLK_GATE_REG (VOSYS_SYSREG_BASE + 0x50)
  26. #define VOSYS_CLK_GATE1_REG (VOSYS_SYSREG_BASE + 0x54)
  27. #define VOSYS_DPU_CCLK_CFG (VOSYS_SYSREG_BASE + 0x64)
  28. /* VISYS_SYSREG_R */
  29. #define VISYS_SYSREG_BASE (0xffe4040000)
  30. #define VISYS_MIPI_CSI0_PIXELCLK (VISYS_SYSREG_BASE + 0x30)
  31. #define VISYS_ISP0_CLK_CFG (VISYS_SYSREG_BASE + 0x24)
  32. #define VISYS_ISP1_CLK_CFG (VISYS_SYSREG_BASE + 0x28)
  33. #define VISYS_ISP_RY_CLK_CFG (VISYS_SYSREG_BASE + 0x2c)
  34. /* APSYS_SYSREG_R */
  35. #define APSYS_CLKGEN_BASE (0xffef010000)
  36. #define APSYS_DPU0_PLL_DIV_CFG (APSYS_CLKGEN_BASE + 0x1e8)
  37. #define APSYS_DPU1_PLL_DIV_CFG (APSYS_CLKGEN_BASE + 0x1ec)
  38. /* AP_DPU0_PLL_CFG1 */
  39. #define AP_DPU0_PLL_RST BIT(29)
  40. /* AP_DPU1_PLL_CFG1 */
  41. #define AP_DPU1_PLL_RST BIT(29)
  42. /* AP_PERI_CLK_CFG */
  43. #define GMAC1_CLK_EN BIT(26)
  44. #define PADCTRL1_APSYS_PCLK_EN BIT(24)
  45. #define DSMART_CLK_EN BIT(23)
  46. #define PADCTRL0_APSYS_PCLK_EN BIT(22)
  47. #define GMAC_AXI_CLK_EN BIT(21)
  48. #define GPIO3_CLK_EN BIT(20)
  49. #define GMAC0_CLK_EN BIT(19)
  50. #define PWM_CLK_EN BIT(18)
  51. #define QSPI0_CLK_EN BIT(17)
  52. #define QSPI1_CLK_EN BIT(16)
  53. #define SPI_CLK_EN BIT(15)
  54. #define UART0_CLK_EN BIT(14)
  55. #define UART1_CLK_EN BIT(13)
  56. #define UART2_CLK_EN BIT(12)
  57. #define UART3_CLK_EN BIT(11)
  58. #define UART4_CLK_EN BIT(10)
  59. #define UART5_CLK_EN BIT(9)
  60. #define GPIO0_CLK_EN BIT(8)
  61. #define GPIO1_CLK_EN BIT(7)
  62. #define GPIO2_CLK_EN BIT(6)
  63. #define I2C0_CLK_EN BIT(5)
  64. #define I2C1_CLK_EN BIT(4)
  65. #define I2C2_CLK_EN BIT(3)
  66. #define I2C3_CLK_EN BIT(2)
  67. #define I2C4_CLK_EN BIT(1)
  68. #define I2C5_CLK_EN BIT(0)
  69. /* AP_CTRL_CLK_CFG */
  70. #define SPINLOCK_CLK_EN BIT(10)
  71. #define CHIP_DBG_CLK_EN BIT(9)
  72. #define DMAC_CPUSYS_CLK_EN BIT(8)
  73. #define MBOX0_PCLK_EN BIT(7)
  74. #define MBOX1_PCLK_EN BIT(6)
  75. #define MBOX2_PCLK_EN BIT(5)
  76. #define MBOX3_PCLK_EN BIT(4)
  77. #define WDT0_CLK_EN BIT(3)
  78. #define WDT1_CLK_EN BIT(2)
  79. #define TIMER0_CLK_EN BIT(1)
  80. #define TIMER1_CLK_EN BIT(0)
  81. /* MISCSYS_TEE_CLK_CTRL_TEE */
  82. #define TEE_DMAC_CLK_EN BIT(6)
  83. /* VOSYS_CLK_GATE_REG */
  84. #define CLKCTRL_DPU_PIXELCLK0_EN BIT(5)
  85. #define CLKCTRL_DPU_PIXELCLK1_EN BIT(6)
  86. #define CLKCTRL_DPU_HCLK_EN BIT(7)
  87. #define CLKCTRL_DPU_ACLK_EN BIT(8)
  88. #define CLKCTRL_DPU_CCLK_EN BIT(9)
  89. #define CLKCTRL_HDMI_SFR_CLK_EN BIT(10)
  90. #define CLKCTRL_HDMI_PCLK_EN BIT(11)
  91. #define CLKCTRL_HDMI_CEC_CLK_EN BIT(12)
  92. #define CLKCTRL_HDMI_I2S_CLK_EN BIT(19)
  93. #define CLKCTRL_MIPI_DSI0_PCLK_EN BIT(13)
  94. #define CLKCTRL_MIPI_DSI0_CFG_CLK_EN BIT(15)
  95. #define CLKCTRL_MIPI_DSI0_REFCLK_EN BIT(17)
  96. #define CLKCTRL_MIPIDSI0_PIXCLK_EN BIT(30)
  97. #define CLKCTRL_MIPI_DSI1_PCLK_EN BIT(14)
  98. #define CLKCTRL_MIPI_DSI1_CFG_CLK_EN BIT(16)
  99. #define CLKCTRL_MIPI_DSI1_REFCLK_EN BIT(18)
  100. #define CLKCTRL_MIPIDSI1_PIXCLK_EN BIT(31)
  101. /* VOSYS_CLK_GATE1_REG */
  102. #define CLKCTRL_HDMI_PIXCLK_EN BIT(0)
  103. /* VOSYS_DPU_CCLK_CFG */
  104. #define VOSYS_DPU_CCLK_DIV_NUM_MASK 0xf
  105. #define VOSYS_DPU_CCLK_DIV_NUM_SHIFT 0
  106. #define VOSYS_DPU_CCLK_DIV_EN BIT(4)
  107. /* VISYS_MIPI_CSI0_PIXELCLK */
  108. #define VISYS_MIPI_CSI0_PIXELCLK_DIV_NUM_SHIFT 0
  109. #define VISYS_MIPI_CSI0_PIXELCLK_DIV_NUM_MASK 0xf
  110. #define VISYS_MIPI_CSI0_PIXELCLK_DIV_EN BIT(4)
  111. /* VISYS_ISP0_CLK_CFG */
  112. #define VISYS_ISP0_CLK_DIV_EN BIT(4)
  113. #define VISYS_ISP0_CLK_DIV_NUM_SHIFT (0)
  114. #define VISYS_ISP0_CLK_DIV_NUM_MASK 0xf
  115. /* VISYS_ISP1_CLK_CFG */
  116. #define VISYS_ISP1_CLK_DIV_EN BIT(4)
  117. #define VISYS_ISP1_CLK_DIV_NUM_SHIFT (0)
  118. #define VISYS_ISP1_CLK_DIV_NUM_MASK 0xf
  119. /* VISYS_ISP_RY_CLK_CFG */
  120. #define VISYS_ISP_RY_CLK_DIV_EN BIT(4)
  121. #define VISYS_ISP_RY_CLK_DIV_NUM_SHIFT (0)
  122. #define VISYS_ISP_RY_CLK_DIV_NUM_MASK 0xf
  123. /* APSYS_DPU0_PLL_DIV_CFG */
  124. #define APSYS_DPU0_PLL_DIV_CLK_DIV_EN BIT(8)
  125. #define APSYS_DPU0_PLL_DIV_CLK_DIV_NUM_MASK 0xff
  126. #define APSYS_DPU0_PLL_DIV_CLK_DIV_NUM_SHIFT 0
  127. /* APSYS_DPU1_PLL_DIV_CFG */
  128. #define APSYS_DPU1_PLL_DIV_CLK_DIV_EN BIT(8)
  129. #define APSYS_DPU1_PLL_DIV_CLK_DIV_NUM_MASK 0xff
  130. #define APSYS_DPU1_PLL_DIV_CLK_DIV_NUM_SHIFT 0
  131. enum multimedia_div_type {
  132. VI_MIPI_CSI0_DIV,
  133. VI_ISP0_CORE_DIV,
  134. VI_ISP1_CORE_DIV,
  135. VI_ISP_RY_CORE_DIV,
  136. VO_DPU_CORE_DIV,
  137. VO_DPU_PLL0_DIV,
  138. VO_DPU_PLL1_DIV,
  139. };
  140. #define C910_CCLK 0
  141. #define C910_CCLK_I0 1
  142. #define CLK_END 16
  143. #define LIGHT_PLL_CFG1 0x4
  144. #define LIGHT_REFDIV_MASK GENMASK(5, 0)
  145. #define LIGHT_REFDIV_SHIFT 0
  146. #define LIGHT_FBDIV_MASK GENMASK(19, 8)
  147. #define LIGHT_FBDIV_SHIFT 8
  148. #define LIGHT_POSTDIV1_MASK GENMASK(22, 20)
  149. #define LIGHT_POSTDIV1_SHIFT 20
  150. #define LIGHT_POSTDIV2_MASK GENMASK(26, 24)
  151. #define LIGHT_POSTDIV2_SHIFT 24
  152. #define LIGHT_FRAC_MASK GENMASK(23, 0)
  153. #define LIGHT_FRAC_SHIFT 0
  154. #define LIGHT_FRAC_DIV BIT(24)
  155. #define LIGHT_DSMPD_MASK BIT(24)
  156. #define LIGHT_DACPD_MASK BIT(25)
  157. #define LIGHT_PLL_RATE(_vco, _rate, _r, _b, _f, _p, _k) \
  158. { \
  159. .vco_rate = (_vco), \
  160. .rate = (_rate), \
  161. .refdiv = (_r), \
  162. .fbdiv = (_b), \
  163. .frac = (_f), \
  164. .postdiv1 = (_p), \
  165. .postdiv2 = (_k), \
  166. }
  167. enum light_pll_mode {
  168. PLL_MODE_FRAC,
  169. PLL_MODE_INT,
  170. };
  171. enum light_pll_outtype {
  172. LIGHT_PLL_VCO,
  173. LIGHT_PLL_DIV,
  174. };
  175. struct clk_fixed {
  176. const char *clk_name;
  177. unsigned long rate;
  178. };
  179. struct light_pll_rate_table {
  180. unsigned long vco_rate;
  181. unsigned long rate;
  182. unsigned int refdiv;
  183. unsigned int fbdiv;
  184. unsigned int frac;
  185. unsigned int postdiv1;
  186. unsigned int postdiv2;
  187. };
  188. struct clk_lightpll {
  189. const char *clk_name;
  190. void __iomem *base;
  191. enum light_pll_clktype clk_type;
  192. enum light_pll_outtype out_type;
  193. enum light_pll_mode pll_mode;
  194. const struct light_pll_rate_table *rate_table;
  195. int rate_count;
  196. u32 cfg0_reg_off;
  197. u32 pll_sts_off;
  198. int pll_lock_bit;
  199. int pll_rst_bit;
  200. int pll_bypass_bit;
  201. enum clk_device_type clk_dev_type;
  202. };
  203. struct clk_fixed clks_fixed[] = {
  204. {"video_pll_foutvco", 2376000000U},
  205. {"gmac_pll_foutpostdiv", 1000000000U},
  206. };
  207. static const struct light_pll_rate_table light_cpupll_tbl[] = {
  208. /* vco_rate postdiv_rate refdiv fbdiv frac postdiv1 postdiv2 */
  209. LIGHT_PLL_RATE(3000000000U, 125000000U, 1, 125, 0, 6, 4),
  210. LIGHT_PLL_RATE(3000000000U, 1000000000U, 1, 125, 0, 3, 1),
  211. LIGHT_PLL_RATE(3000000000U, 1500000000U, 1, 125, 0, 2, 1),
  212. LIGHT_PLL_RATE(1800000000U, 1800000000U, 1, 75, 0, 1, 1),
  213. LIGHT_PLL_RATE(2256000000U, 752000000U, 1, 94, 0, 3, 1),
  214. LIGHT_PLL_RATE(3000000000U, 300000000U, 1, 125, 0, 5, 2),
  215. LIGHT_PLL_RATE(1848000000U, 1848000000U, 1, 77, 0, 1, 1),
  216. LIGHT_PLL_RATE(1872000000U, 1872000000U, 1, 78, 0, 1, 1),
  217. };
  218. static const struct light_pll_rate_table light_audio_pll_tbl[] = {
  219. LIGHT_PLL_RATE(864000000U, 288000000U, 1, 36, 0, 3, 1), /* INT MODE */
  220. LIGHT_PLL_RATE(884736000U, 294912000U, 1, 36, 14495600U, 3, 1), /* FRAC MODE */
  221. LIGHT_PLL_RATE(2064384000U, 294912000U, 1, 86, 268500U, 7, 1), /* FRAC MODE */
  222. };
  223. static const struct light_pll_rate_table light_sys_pll_tbl[] = {
  224. LIGHT_PLL_RATE(2424000000U, 134667000U, 1, 101, 0, 6, 3), /* INT MODE */
  225. LIGHT_PLL_RATE(884736000U, 294912000U, 1, 36, 14495600, 3, 1), /* FRAC MODE */
  226. LIGHT_PLL_RATE(2438553600U, 135475200U, 1, 101, 10173704, 6, 3), /* FRAC MODE */
  227. };
  228. static const struct light_pll_rate_table light_dpu_pll_tbl[] = {
  229. LIGHT_PLL_RATE(1188000000U, 1188000000U, 1, 0x31, 0x800000, 1, 1), /* FRAC MODE */
  230. LIGHT_PLL_RATE(1611200000U, 805600000U, 200, 0x43, 0x222222, 2, 1), /* FRAC MODE */
  231. };
  232. static const struct light_pll_rate_table light_gmac_pll_tbl[] = {
  233. LIGHT_PLL_RATE(3000000000U, 1000000000U, 1, 125, 0, 3, 1),
  234. };
  235. struct clk_lightpll light_cpu_pll0div = {
  236. .clk_name = "cpu_pll0_foutpostdiv",
  237. .base = ap_base,
  238. .out_type = LIGHT_PLL_DIV,
  239. .clk_type = LIGHT_CPU_PLL0,
  240. .rate_table = light_cpupll_tbl,
  241. .rate_count = ARRAY_SIZE(light_cpupll_tbl),
  242. .cfg0_reg_off = 0x0,
  243. .pll_sts_off = 0x80,
  244. .pll_lock_bit = BIT(1),
  245. .pll_bypass_bit = BIT(30),
  246. .pll_rst_bit = BIT(29),
  247. .pll_mode = PLL_MODE_INT,
  248. .clk_dev_type = CLK_DEV_PLL,
  249. };
  250. struct clk_lightpll light_cpu_pll1div = {
  251. .clk_name = "cpu_pll1_foutpostdiv",
  252. .base = ap_base,
  253. .out_type = LIGHT_PLL_DIV,
  254. .clk_type = LIGHT_CPU_PLL1,
  255. .rate_table = light_cpupll_tbl,
  256. .rate_count = ARRAY_SIZE(light_cpupll_tbl),
  257. .cfg0_reg_off = 0x10,
  258. .pll_sts_off = 0x80,
  259. .pll_lock_bit = BIT(4),
  260. .pll_bypass_bit = BIT(30),
  261. .pll_rst_bit = BIT(29),
  262. .pll_mode = PLL_MODE_INT,
  263. .clk_dev_type = CLK_DEV_PLL,
  264. };
  265. #define AUDIO_PLL_INT_MODE
  266. struct clk_lightpll light_audio_plldiv = {
  267. .clk_name = "audio_pll_foutpostdiv",
  268. .base = aon_base,
  269. .out_type = LIGHT_PLL_DIV,
  270. .clk_type = LIGHT_AUDIO_PLL,
  271. .rate_table = light_audio_pll_tbl,
  272. .rate_count = ARRAY_SIZE(light_audio_pll_tbl),
  273. .cfg0_reg_off = 0x0,
  274. .pll_sts_off = 0x90,
  275. .pll_lock_bit = BIT(0),
  276. .pll_bypass_bit = BIT(30),
  277. .pll_rst_bit = BIT(29),
  278. #ifndef AUDIO_PLL_INT_MODE
  279. .pll_mode = PLL_MODE_FRAC,
  280. #else
  281. .pll_mode = PLL_MODE_INT,
  282. #endif
  283. .clk_dev_type = CLK_DEV_PLL,
  284. };
  285. struct clk_lightpll light_audio_pllvco = {
  286. .clk_name = "audio_pll_foutvco",
  287. .base = aon_base,
  288. .out_type = LIGHT_PLL_VCO,
  289. .clk_type = LIGHT_AUDIO_PLL,
  290. .rate_table = light_audio_pll_tbl,
  291. .rate_count = ARRAY_SIZE(light_audio_pll_tbl),
  292. .cfg0_reg_off = 0x0,
  293. .pll_sts_off = 0x90,
  294. .pll_lock_bit = BIT(0),
  295. .pll_bypass_bit = BIT(30),
  296. .pll_rst_bit = BIT(29),
  297. #ifndef AUDIO_PLL_INT_MODE
  298. .pll_mode = PLL_MODE_FRAC,
  299. #else
  300. .pll_mode = PLL_MODE_INT,
  301. #endif
  302. .clk_dev_type = CLK_DEV_PLL,
  303. };
  304. #define SYS_PLL_INT_MODE
  305. struct clk_lightpll light_sys_plldiv = {
  306. .clk_name = "sys_pll_foutpostdiv",
  307. .base = aon_base,
  308. .out_type = LIGHT_PLL_DIV,
  309. .clk_type = LIGHT_SYS_PLL,
  310. .rate_table = light_sys_pll_tbl,
  311. .rate_count = ARRAY_SIZE(light_sys_pll_tbl),
  312. .cfg0_reg_off = 0x10,
  313. .pll_sts_off = 0x90,
  314. .pll_lock_bit = BIT(1),
  315. .pll_bypass_bit = BIT(30),
  316. .pll_rst_bit = BIT(29),
  317. #ifndef SYS_PLL_INT_MODE
  318. .pll_mode = PLL_MODE_FRAC,
  319. #else
  320. .pll_mode = PLL_MODE_INT,
  321. #endif
  322. .clk_dev_type = CLK_DEV_PLL,
  323. };
  324. struct clk_lightpll light_sys_pllvco = {
  325. .clk_name = "sys_pll_foutvco",
  326. .base = aon_base,
  327. .out_type = LIGHT_PLL_VCO,
  328. .clk_type = LIGHT_SYS_PLL,
  329. .rate_table = light_sys_pll_tbl,
  330. .rate_count = ARRAY_SIZE(light_sys_pll_tbl),
  331. .cfg0_reg_off = 0x10,
  332. .pll_sts_off = 0x90,
  333. .pll_lock_bit = BIT(1),
  334. .pll_bypass_bit = BIT(30),
  335. .pll_rst_bit = BIT(29),
  336. #ifndef SYS_PLL_INT_MODE
  337. .pll_mode = PLL_MODE_FRAC,
  338. #else
  339. .pll_mode = PLL_MODE_INT,
  340. #endif
  341. .clk_dev_type = CLK_DEV_PLL,
  342. };
  343. #define DPU_PLL_INT_MODE
  344. struct clk_lightpll light_dpu0_plldiv = {
  345. .clk_name = "dpu0_pll_foutpostdiv",
  346. .base = ap_base,
  347. .out_type = LIGHT_PLL_DIV,
  348. .clk_type = LIGHT_DPU0_PLL,
  349. .rate_table = light_dpu_pll_tbl,
  350. .rate_count = ARRAY_SIZE(light_dpu_pll_tbl),
  351. .cfg0_reg_off = 0x40,
  352. .pll_sts_off = 0x80,
  353. .pll_lock_bit = BIT(8),
  354. .pll_bypass_bit = BIT(30),
  355. .pll_rst_bit = BIT(29),
  356. #ifndef DPU_PLL_INT_MODE
  357. .pll_mode = PLL_MODE_FRAC,
  358. #else
  359. .pll_mode = PLL_MODE_INT,
  360. #endif
  361. .clk_dev_type = CLK_DEV_PLL,
  362. };
  363. struct clk_lightpll light_dpu1_plldiv = {
  364. .clk_name = "dpu1_pll_foutpostdiv",
  365. .base = ap_base,
  366. .out_type = LIGHT_PLL_DIV,
  367. .clk_type = LIGHT_DPU1_PLL,
  368. .rate_table = light_dpu_pll_tbl,
  369. .rate_count = ARRAY_SIZE(light_dpu_pll_tbl),
  370. .cfg0_reg_off = 0x50,
  371. .pll_sts_off = 0x80,
  372. .pll_lock_bit = BIT(9),
  373. .pll_bypass_bit = BIT(30),
  374. .pll_rst_bit = BIT(29),
  375. #ifndef DPU_PLL_INT_MODE
  376. .pll_mode = PLL_MODE_FRAC,
  377. #else
  378. .pll_mode = PLL_MODE_INT,
  379. #endif
  380. .clk_dev_type = CLK_DEV_PLL,
  381. };
  382. struct clk_lightpll light_gmac_plldiv = {
  383. .clk_name = "gmac_pll_foutpostdiv",
  384. .base = ap_base,
  385. .out_type = LIGHT_PLL_DIV,
  386. .clk_type = LIGHT_GMAC_PLL,
  387. .rate_table = light_gmac_pll_tbl,
  388. .rate_count = ARRAY_SIZE(light_gmac_pll_tbl),
  389. .cfg0_reg_off = 0x20,
  390. .pll_sts_off = 0x80,
  391. .pll_lock_bit = BIT(3),
  392. .pll_bypass_bit = BIT(30),
  393. .pll_rst_bit = BIT(29),
  394. .pll_mode = PLL_MODE_INT,
  395. .clk_dev_type = CLK_DEV_PLL,
  396. };
  397. struct clk_lightpll *clks_pll[] = {
  398. &light_cpu_pll0div,
  399. &light_cpu_pll1div,
  400. &light_audio_plldiv,
  401. &light_audio_pllvco,
  402. &light_sys_plldiv,
  403. &light_sys_pllvco,
  404. &light_dpu0_plldiv,
  405. &light_dpu1_plldiv,
  406. &light_gmac_plldiv,
  407. };
  408. static const struct light_pll_rate_table *light_get_pll_div_settings(
  409. struct clk_lightpll *pll, unsigned long rate)
  410. {
  411. const struct light_pll_rate_table *rate_table = pll->rate_table;
  412. int i;
  413. for (i = 0; i < pll->rate_count; i++)
  414. if (rate == rate_table[i].rate)
  415. return &rate_table[i];
  416. return NULL;
  417. }
  418. static const struct light_pll_rate_table *light_get_pll_vco_settings(
  419. struct clk_lightpll *pll, unsigned long rate)
  420. {
  421. const struct light_pll_rate_table *rate_table = pll->rate_table;
  422. int i;
  423. for (i = 0; i < pll->rate_count; i++)
  424. if (rate == rate_table[i].vco_rate)
  425. return &rate_table[i];
  426. return NULL;
  427. }
  428. static inline bool clk_light_pll_change(struct clk_lightpll *pll,
  429. const struct light_pll_rate_table *rate)
  430. {
  431. u32 refdiv_old, fbdiv_old, postdiv1_old, postdiv2_old, frac_old;
  432. u32 cfg0, cfg1;
  433. bool pll_changed;
  434. cfg0 = readl(pll->base + pll->cfg0_reg_off);
  435. cfg1 = readl(pll->base + pll->cfg0_reg_off + LIGHT_PLL_CFG1);
  436. refdiv_old = (cfg0 & LIGHT_REFDIV_MASK) >> LIGHT_REFDIV_SHIFT;
  437. fbdiv_old = (cfg0 & LIGHT_FBDIV_MASK) >> LIGHT_FBDIV_SHIFT;
  438. postdiv1_old = (cfg0 & LIGHT_POSTDIV1_MASK) >> LIGHT_POSTDIV1_SHIFT;
  439. postdiv2_old = (cfg0 & LIGHT_POSTDIV2_MASK) >> LIGHT_POSTDIV2_SHIFT;
  440. frac_old = (cfg1 & LIGHT_FRAC_MASK) >> LIGHT_FRAC_SHIFT;
  441. pll_changed = rate->refdiv != refdiv_old || rate->fbdiv != fbdiv_old ||
  442. rate->postdiv1 != postdiv1_old || rate->postdiv2 != postdiv2_old;
  443. if (pll->pll_mode == PLL_MODE_FRAC)
  444. pll_changed |= (rate->frac != frac_old);
  445. return pll_changed;
  446. }
  447. static int clk_light_pll_wait_lock(struct clk_lightpll *pll)
  448. {
  449. u32 count = 0;
  450. bool lock_done = false;
  451. while (count++ < 1000) {
  452. if (readl(pll->base + pll->pll_sts_off) & pll->pll_lock_bit) {
  453. lock_done = true;
  454. break;
  455. }
  456. mdelay(1);
  457. }
  458. if (lock_done)
  459. return 0;
  460. return -EBUSY;
  461. }
  462. int clk_pll_set_rate(struct clk_lightpll *pll, unsigned long drate)
  463. {
  464. const struct light_pll_rate_table *rate;
  465. void __iomem *cfg1_off;
  466. u32 tmp, div_val;
  467. int ret;
  468. if (pll->out_type == LIGHT_PLL_VCO) {
  469. rate = light_get_pll_vco_settings(pll, drate);
  470. if (!rate) {
  471. printf("%s: Invalid rate : %lu for pll clk\n", __func__, drate);
  472. return -EINVAL;
  473. }
  474. } else {
  475. rate = light_get_pll_div_settings(pll, drate);
  476. if (!rate) {
  477. printf("%s: Invalid rate : %lu for pll clk\n", __func__, drate);
  478. return -EINVAL;
  479. }
  480. }
  481. if (!clk_light_pll_change(pll, rate))
  482. return 0;
  483. /* Enable RST */
  484. cfg1_off = pll->base + pll->cfg0_reg_off + LIGHT_PLL_CFG1;
  485. tmp = readl(cfg1_off);
  486. tmp |= pll->pll_rst_bit;
  487. writel(tmp, cfg1_off);
  488. div_val = (rate->refdiv << LIGHT_REFDIV_SHIFT) |
  489. (rate->fbdiv << LIGHT_FBDIV_SHIFT) |
  490. (rate->postdiv1 << LIGHT_POSTDIV1_SHIFT) |
  491. (rate->postdiv2 << LIGHT_POSTDIV2_SHIFT);
  492. writel(div_val, pll->base + pll->cfg0_reg_off);
  493. if (pll->pll_mode == PLL_MODE_FRAC) {
  494. tmp &= ~LIGHT_DSMPD_MASK;
  495. tmp |= LIGHT_DACPD_MASK;
  496. tmp &= ~(LIGHT_FRAC_MASK << LIGHT_FRAC_SHIFT);
  497. tmp |= rate->frac;
  498. writel(tmp, cfg1_off);
  499. }
  500. udelay(3);
  501. /* Disable RST */
  502. tmp &= ~pll->pll_rst_bit;
  503. writel(tmp, cfg1_off);
  504. /* Wait Lock, ~20us cost */
  505. ret = clk_light_pll_wait_lock(pll);
  506. if (ret)
  507. return ret;
  508. /* HW requires 30us for pll stable */
  509. udelay(30);
  510. return 0;
  511. }
  512. unsigned long clk_pll_round_rate(struct clk_lightpll *pll, unsigned long rate)
  513. {
  514. const struct light_pll_rate_table *rate_table = pll->rate_table;
  515. unsigned long best = 0, now = 0;
  516. unsigned int i, best_i = 0;
  517. for (i = 0; i < pll->rate_count; i++) {
  518. if (pll->out_type == LIGHT_PLL_DIV)
  519. now = rate_table[i].rate;
  520. else if (pll->out_type == LIGHT_PLL_VCO)
  521. now = rate_table[i].vco_rate;
  522. else {
  523. printf("invalid pll mode\n");
  524. return 0;
  525. }
  526. if (rate == now) {
  527. if (pll->out_type == LIGHT_PLL_DIV)
  528. return rate_table[i].rate;
  529. else
  530. return rate_table[i].vco_rate;
  531. } else if (abs(now - rate) < abs(best - rate)) {
  532. best = now;
  533. best_i = i;
  534. }
  535. }
  536. /* return minimum supported value */
  537. if (pll->out_type == LIGHT_PLL_DIV)
  538. return rate_table[best_i].rate;
  539. return rate_table[best_i].vco_rate;
  540. }
  541. unsigned long clk_pll_recalc_rate(struct clk_lightpll *pll, unsigned long prate)
  542. {
  543. u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
  544. u32 pll_cfg0, pll_cfg1;
  545. u64 fvco = 0;
  546. pll_cfg0 = readl(pll->base + pll->cfg0_reg_off);
  547. pll_cfg1 = readl(pll->base + pll->cfg0_reg_off + LIGHT_PLL_CFG1);
  548. refdiv = (pll_cfg0 & LIGHT_REFDIV_MASK) >> LIGHT_REFDIV_SHIFT;
  549. fbdiv = (pll_cfg0 & LIGHT_FBDIV_MASK) >> LIGHT_FBDIV_SHIFT;
  550. postdiv1 = (pll_cfg0 & LIGHT_POSTDIV1_MASK) >> LIGHT_POSTDIV1_SHIFT;
  551. postdiv2 = (pll_cfg0 & LIGHT_POSTDIV2_MASK) >> LIGHT_POSTDIV2_SHIFT;
  552. frac = (pll_cfg1 & LIGHT_FRAC_MASK) >> LIGHT_FRAC_SHIFT;
  553. pr_debug("reg_pll_cfg0: 0x%p, reg_pll_cfg1: 0x%p\n", (pll->base + pll->cfg0_reg_off), (pll->base + pll->cfg0_reg_off + LIGHT_PLL_CFG1));
  554. pr_debug("refdiv = %d, fbdiv = %d, postdiv1 = %d, postdiv2 = %d, frac = %d, mode = %d\n",
  555. refdiv, fbdiv, postdiv1, postdiv2, frac, pll->pll_mode);
  556. /* rate calculation:
  557. * INT mode: FOUTVCO = FREE * FBDIV / REFDIV
  558. * FRAC mode:FOUTVCO = (FREE * FBDIV + FREE * FRAC/BIT(24)) / REFDIV
  559. */
  560. if (pll->pll_mode == PLL_MODE_FRAC)
  561. fvco = (prate * frac) / LIGHT_FRAC_DIV;
  562. fvco += (prate * fbdiv);
  563. do_div(fvco, refdiv);
  564. if (pll->out_type == LIGHT_PLL_DIV)
  565. do_div(fvco, postdiv1 * postdiv2);
  566. pr_debug("fvco = %lluHZ\n", fvco);
  567. return fvco;
  568. }
  569. struct clk_lightmux {
  570. const char *clk_name;
  571. void __iomem *reg;
  572. u8 shift;
  573. u8 width;
  574. const struct clk_info * parents;
  575. int num_parents;
  576. enum clk_device_type clk_dev_type;
  577. };
  578. static const struct clk_info c910_cclk_sels[] = {
  579. {"c910_cclk_i0", CLK_DEV_MUX},
  580. {"cpu_pll1_foutpostdiv", CLK_DEV_PLL},
  581. };
  582. static const struct clk_info c910_cclk_i0_sels[] = {
  583. { "cpu_pll0_foutpostdiv", CLK_DEV_PLL},
  584. { "osc_24m", CLK_DEV_ROOT},
  585. };
  586. static const struct clk_info gmac_pll_bypass_sels[] = {
  587. {"gmac_pll_foutpostdiv", CLK_DEV_FIXED},
  588. { "osc_24m", CLK_DEV_ROOT},
  589. };
  590. static const struct clk_info ahb2_cpusys_hclk_sels[] = {
  591. {"ahb2_cpusys_hclk_out_div", CLK_DEV_DIV},
  592. {"osc_24m", CLK_DEV_ROOT},
  593. };
  594. static const struct clk_info perisys_ahb_hclk_sels[] = {
  595. {"perisys_ahb_hclk_out_div", CLK_DEV_DIV},
  596. {"osc_24m", CLK_DEV_ROOT},
  597. };
  598. struct clk_lightmux clks_mux[] = {
  599. {"c910_cclk", ap_base + 0x100, 0, 1, c910_cclk_sels, ARRAY_SIZE(c910_cclk_sels), CLK_DEV_MUX},
  600. {"c910_cclk_i0", ap_base + 0x100, 1, 1, c910_cclk_i0_sels, ARRAY_SIZE(c910_cclk_i0_sels), CLK_DEV_MUX},
  601. {"gmac_pll_bypass", ap_base + 0x24, 30, 1, gmac_pll_bypass_sels, ARRAY_SIZE(gmac_pll_bypass_sels), CLK_DEV_MUX},
  602. {"ahb2_cpusys_hclk", ap_base + 0x120, 5, 1, ahb2_cpusys_hclk_sels, ARRAY_SIZE(ahb2_cpusys_hclk_sels), CLK_DEV_MUX},
  603. {"perisys_ahb_hclk", ap_base + 0x140, 5, 1, perisys_ahb_hclk_sels, ARRAY_SIZE(perisys_ahb_hclk_sels), CLK_DEV_MUX},
  604. };
  605. const struct clk_info *clk_light_get_parent(const char *clk_name)
  606. {
  607. struct clk_lightmux *clk = NULL;
  608. int idx, i;
  609. for (i = 0; i < ARRAY_SIZE(clks_mux); i++) {
  610. if (strcmp(clk_name, clks_mux[i].clk_name))
  611. continue;
  612. clk = &clks_mux[i];
  613. break;
  614. }
  615. if (!clk) {
  616. printf("%s is not a clock mux\n", clk_name);
  617. return NULL;
  618. }
  619. idx = (readl(clk->reg) >> clk->shift) & clk->width;
  620. return &clk->parents[idx];
  621. }
  622. int clk_light_set_parent(const char *clk_name, const char *parent)
  623. {
  624. struct clk_lightmux *clk = NULL;
  625. int i;
  626. u32 val;
  627. for (i = 0; i < ARRAY_SIZE(clks_mux); i++) {
  628. if (strcmp(clk_name, clks_mux[i].clk_name))
  629. continue;
  630. clk = &clks_mux[i];
  631. break;
  632. }
  633. if (!clk) {
  634. printf("%s is not a clock mux, can not switch parent clock\n", clk_name);
  635. return -EINVAL;
  636. }
  637. if (!strcmp(clk->clk_name, parent))
  638. return 0;
  639. debug("clk->num_parents = %d\n", clk->num_parents);
  640. for (i = 0; i < clk->num_parents; i++) {
  641. pr_debug("parent%d:%s\n", i, clk->parents[i].clk_name);
  642. if (!strcmp(parent, clk->parents[i].clk_name))
  643. break;
  644. }
  645. if (i >= clk->num_parents) {
  646. printf("No target parent clock found\n");
  647. return -EINVAL;
  648. }
  649. val = readl(clk->reg);
  650. val &= ~(clk->width << clk->shift);
  651. val |= (i & clk->width)<< clk->shift;
  652. writel(val, clk->reg);
  653. return 0;
  654. }
  655. #define NPU_CCLK_OUT_DIV 0
  656. #define div_mask(d) ((1 << (d->width)) - 1)
  657. enum light_div_type {
  658. MUX_TYPE_DIV,
  659. MUX_TYPE_CDE,
  660. };
  661. struct clk_lightdiv {
  662. const char *clk_name;
  663. enum clk_device_type clk_dev_type;
  664. const char *parent;
  665. enum clk_device_type p_clk_dev_type;
  666. void __iomem *reg;
  667. u8 shift;
  668. u8 width;
  669. u8 sync_en;
  670. enum light_div_type div_type;
  671. u16 min_div;
  672. u16 max_div;
  673. };
  674. struct clk_lightdiv clks_div[] = {
  675. {"npu_cclk_out_div", CLK_DEV_DIV, "video_pll_foutvco", CLK_DEV_FIXED, ap_base + 0x1c8, 0, 3, 3, MUX_TYPE_DIV, 3, 7},
  676. {"ahb2_cpusys_hclk_out_div", CLK_DEV_DIV, "gmac_pll_fout1ph0", CLK_DEV_FACTOR, ap_base + 0x120, 0, 3, 4, MUX_TYPE_DIV, 2, 7},
  677. {"apb3_cpusys_pclk", CLK_DEV_DIV, "ahb2_cpusys_hclk", CLK_DEV_MUX, ap_base + 0x130, 0, 3, 3, MUX_TYPE_CDE, 1, 7},
  678. {"perisys_ahb_hclk_out_div", CLK_DEV_DIV, "gmac_pll_fout1ph0", CLK_DEV_FACTOR, ap_base + 0x140, 0, 4, 4, MUX_TYPE_DIV, 2, 7},
  679. {"perisys_apb_pclk", CLK_DEV_DIV, "perisys_ahb_hclk", CLK_DEV_MUX, ap_base + 0x150, 0, 3, 3, MUX_TYPE_CDE, 3, 7},
  680. };
  681. int clk_lightdiv_set_rate(struct clk_lightdiv *lightdiv, unsigned long rate, unsigned long parent_rate)
  682. {
  683. unsigned int divider, value;
  684. u32 val;
  685. divider = parent_rate / rate;
  686. /* DIV is zero based divider, but CDE is not */
  687. if (lightdiv->div_type == MUX_TYPE_DIV)
  688. value = divider;
  689. else
  690. value = divider - 1;
  691. /* handle the div valid range */
  692. if (value > lightdiv->max_div)
  693. value = lightdiv->max_div;
  694. if (value < lightdiv->min_div)
  695. value = lightdiv->min_div;
  696. val = readl(lightdiv->reg);
  697. val &= ~BIT(lightdiv->sync_en);
  698. writel(val, lightdiv->reg);
  699. udelay(1);
  700. val &= ~(div_mask(lightdiv) << lightdiv->shift);
  701. val |= value << lightdiv->shift;
  702. writel(val, lightdiv->reg);
  703. udelay(1);
  704. val |= BIT(lightdiv->sync_en);
  705. writel(val, lightdiv->reg);
  706. return 0;
  707. }
  708. unsigned long clk_lightdiv_recalc_rate(struct clk_lightdiv *lightdiv, unsigned long prate)
  709. {
  710. unsigned int divider, value;
  711. u32 val;
  712. val = readl(lightdiv->reg);
  713. value = (val >> lightdiv->shift) & div_mask(lightdiv);
  714. if (lightdiv->div_type == MUX_TYPE_DIV)
  715. divider = value;
  716. else
  717. divider = value + 1;
  718. pr_debug("divider parent rate: %ld, divider: %d\n", prate, divider);
  719. return prate / divider;
  720. }
  721. struct clk_light_fixed_factor {
  722. const char *clk_name;
  723. enum clk_device_type clk_dev_type;
  724. const char *parent;
  725. enum clk_device_type p_clk_dev_type;
  726. unsigned int mult;
  727. unsigned int div;
  728. };
  729. struct clk_light_fixed_factor clks_factor[] = {
  730. {"gmac_pll_fout1ph0", CLK_DEV_FACTOR, "gmac_pll_bypass", CLK_DEV_MUX, 1, 2},
  731. };
  732. unsigned long clk_light_factor_recalc_rate(struct clk_light_fixed_factor *fix, unsigned long prate)
  733. {
  734. unsigned long long int rate;
  735. rate = (unsigned long long int)prate * fix->mult;
  736. do_div(rate, fix->div);
  737. return (unsigned long)rate;
  738. }
  739. unsigned long clk_light_get_rate(const char *clk_name, enum clk_device_type clk_dev_type)
  740. {
  741. unsigned long rate;
  742. int i;
  743. if (clk_dev_type == CLK_DEV_PLL) {
  744. struct clk_lightpll *pll = NULL;
  745. for (i = 0; i < ARRAY_SIZE(clks_pll); i++) {
  746. if (strcmp(clk_name, (clks_pll[i])->clk_name))
  747. continue;
  748. pll = clks_pll[i];
  749. break;
  750. }
  751. if (!pll) {
  752. printf("No pll clock '%s' registered\n", clk_name);
  753. return 0;
  754. }
  755. rate = clk_pll_recalc_rate(pll, 24000000U);
  756. } else if (clk_dev_type == CLK_DEV_FIXED) {
  757. struct clk_fixed *fixed = NULL;
  758. for (i = 0; i < ARRAY_SIZE(clks_fixed); i++) {
  759. if (strcmp(clk_name, clks_fixed[i].clk_name))
  760. continue;
  761. fixed = &clks_fixed[i];
  762. }
  763. if (!fixed) {
  764. printf("No fixed clock '%s' registered\n", clk_name);
  765. return 0;
  766. }
  767. rate = fixed->rate;
  768. } else if (clk_dev_type == CLK_DEV_MUX) {
  769. struct clk_lightmux *mux = NULL;
  770. const struct clk_info *mux_parent;
  771. for (i = 0; i < ARRAY_SIZE(clks_mux); i++) {
  772. if (strcmp(clk_name, clks_mux[i].clk_name))
  773. continue;
  774. mux = &clks_mux[i];
  775. break;
  776. }
  777. if (!mux) {
  778. printf("No mux clock '%s' registered\n", clk_name);
  779. return 0;
  780. }
  781. mux_parent = clk_light_get_parent(mux->clk_name);
  782. pr_debug("%s parent: %s\n", clk_name, mux_parent->clk_name);
  783. rate = clk_light_get_rate(mux_parent->clk_name, mux_parent->clk_dev_type);
  784. if (!rate)
  785. return rate;
  786. } else if (clk_dev_type == CLK_DEV_DIV) {
  787. struct clk_lightdiv *div = NULL;
  788. unsigned long prate;
  789. for (i = 0; i < ARRAY_SIZE(clks_div); i++) {
  790. if (strcmp(clk_name, clks_div[i].clk_name))
  791. continue;
  792. div = &clks_div[i];
  793. break;
  794. }
  795. if (!div) {
  796. printf("No div clock '%s' registered\n", clk_name);
  797. return -EINVAL;
  798. }
  799. prate = clk_light_get_rate(div->parent, div->p_clk_dev_type);
  800. if (!prate)
  801. return prate;
  802. rate = clk_lightdiv_recalc_rate(div, prate);
  803. } else if (clk_dev_type == CLK_DEV_FACTOR) {
  804. struct clk_light_fixed_factor *factor = NULL;
  805. unsigned long prate;
  806. for (i = 0; i < ARRAY_SIZE(clks_factor); i++) {
  807. if (strcmp(clk_name, clks_factor[i].clk_name))
  808. continue;
  809. factor = &clks_factor[i];
  810. break;
  811. }
  812. if (!factor) {
  813. printf("No factor clock '%s' registered\n", clk_name);
  814. return -EINVAL;
  815. }
  816. prate = clk_light_get_rate(factor->parent, factor->p_clk_dev_type);
  817. if (!prate)
  818. return prate;
  819. rate = clk_light_factor_recalc_rate(factor, prate);
  820. } else if (clk_dev_type == CLK_DEV_ROOT) {
  821. rate = 24000000U;
  822. } else {
  823. printf("Incorrect clock device type\n");
  824. rate = 0;
  825. }
  826. return rate;
  827. }
  828. int clk_light_set_rate(const char *clk_name, enum clk_device_type clk_dev_type, unsigned long rate)
  829. {
  830. int i, ret = 0;
  831. if (clk_dev_type == CLK_DEV_MUX) {
  832. struct clk_lightmux *mux = NULL;
  833. const struct clk_info *mux_parent;
  834. for (i = 0; i < ARRAY_SIZE(clks_mux); i++) {
  835. if (strcmp(clk_name, clks_mux[i].clk_name))
  836. continue;
  837. mux = &clks_mux[i];
  838. break;
  839. }
  840. if (!mux) {
  841. printf("No mux clock '%s' registered\n", clk_name);
  842. return -EINVAL;
  843. }
  844. mux_parent = clk_light_get_parent(mux->clk_name);
  845. ret = clk_light_set_rate(mux_parent->clk_name, mux_parent->clk_dev_type, rate);
  846. } else if (clk_dev_type == CLK_DEV_PLL) {
  847. struct clk_lightpll *pll = NULL;
  848. for (i = 0; i < ARRAY_SIZE(clks_pll); i++) {
  849. if (strcmp(clk_name, (clks_pll[i])->clk_name))
  850. continue;
  851. pll = clks_pll[i];
  852. break;
  853. }
  854. if (!pll) {
  855. printf("No pll clock '%s' registered\n", clk_name);
  856. return -EINVAL;
  857. }
  858. ret = clk_pll_set_rate(pll, rate);
  859. } else if (clk_dev_type == CLK_DEV_DIV) {
  860. unsigned long prate;
  861. struct clk_lightdiv *div = NULL;
  862. for (i = 0; i < ARRAY_SIZE(clks_div); i++) {
  863. if (strcmp(clk_name, clks_div[i].clk_name))
  864. continue;
  865. div = &clks_div[i];
  866. break;
  867. }
  868. if (!div) {
  869. printf("No div clock '%s' registered\n", clk_name);
  870. return -EINVAL;
  871. }
  872. prate = clk_light_get_rate(div->parent, div->p_clk_dev_type);
  873. if (!prate)
  874. return -EINVAL;
  875. ret = clk_lightdiv_set_rate(div, rate, prate);
  876. } else {
  877. printf("Incorrect clock device type\n");
  878. return -EINVAL;
  879. }
  880. return ret;
  881. }
  882. /* disable some modules' clk that will not work in u-boot phase */
  883. void ap_peri_clk_disable(void)
  884. {
  885. unsigned int clk_cfg;
  886. #if (defined CONFIG_TARGET_LIGHT_FM_C910_VAL_B) || (defined CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || (defined CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || (defined CONFIG_TARGET_LIGHT_FM_C910_B_POWER)
  887. clk_cfg = readl((void __iomem *)AP_PERI_CLK_CFG);
  888. clk_cfg &= ~(GMAC1_CLK_EN);
  889. writel(clk_cfg, (void __iomem *)AP_PERI_CLK_CFG);
  890. #endif
  891. clk_cfg = readl((void __iomem *)MISCSYS_TEE_CLK_CTRL_TEE);
  892. clk_cfg &= ~(TEE_DMAC_CLK_EN);
  893. writel(clk_cfg, (void __iomem *)MISCSYS_TEE_CLK_CTRL_TEE);
  894. }
  895. void ap_dpu_clk_endisable(bool en)
  896. {
  897. unsigned int cfg = readl((void __iomem *)VOSYS_CLK_GATE_REG);
  898. if (en)
  899. cfg |= (CLKCTRL_DPU_PIXELCLK0_EN | CLKCTRL_DPU_PIXELCLK1_EN | CLKCTRL_DPU_HCLK_EN |
  900. CLKCTRL_DPU_ACLK_EN | CLKCTRL_DPU_CCLK_EN);
  901. else
  902. cfg &= ~(CLKCTRL_DPU_PIXELCLK0_EN | CLKCTRL_DPU_PIXELCLK1_EN | CLKCTRL_DPU_HCLK_EN |
  903. CLKCTRL_DPU_ACLK_EN | CLKCTRL_DPU_CCLK_EN);
  904. writel(cfg, (void __iomem *)VOSYS_CLK_GATE_REG);
  905. }
  906. void ap_hdmi_clk_endisable(bool en)
  907. {
  908. unsigned int cfg = readl((void __iomem *)VOSYS_CLK_GATE_REG);
  909. unsigned int cfg1 = readl((void __iomem *)VOSYS_CLK_GATE1_REG);
  910. if (en) {
  911. cfg |= (CLKCTRL_HDMI_SFR_CLK_EN | CLKCTRL_HDMI_PCLK_EN | CLKCTRL_HDMI_CEC_CLK_EN |
  912. CLKCTRL_HDMI_I2S_CLK_EN);
  913. cfg1 |= CLKCTRL_HDMI_PIXCLK_EN;
  914. } else {
  915. cfg &= ~(CLKCTRL_HDMI_SFR_CLK_EN | CLKCTRL_HDMI_PCLK_EN | CLKCTRL_HDMI_CEC_CLK_EN |
  916. CLKCTRL_HDMI_I2S_CLK_EN);
  917. cfg1 &= ~CLKCTRL_HDMI_PIXCLK_EN;
  918. }
  919. writel(cfg, (void __iomem *)VOSYS_CLK_GATE_REG);
  920. writel(cfg1, (void __iomem *)VOSYS_CLK_GATE1_REG);
  921. }
  922. void ap_mipi_dsi0_clk_endisable(bool en)
  923. {
  924. unsigned int cfg = readl((void __iomem *)VOSYS_CLK_GATE_REG);
  925. unsigned int cfg1 = readl((void __iomem *)AP_DPU0_PLL_CFG1);
  926. if (en) {
  927. cfg |= (CLKCTRL_MIPI_DSI0_PCLK_EN | CLKCTRL_MIPI_DSI0_CFG_CLK_EN | CLKCTRL_MIPI_DSI0_REFCLK_EN |
  928. CLKCTRL_MIPIDSI0_PIXCLK_EN);
  929. cfg1 &= ~AP_DPU0_PLL_RST;
  930. } else {
  931. cfg &= ~(CLKCTRL_MIPI_DSI0_PCLK_EN | CLKCTRL_MIPI_DSI0_CFG_CLK_EN | CLKCTRL_MIPI_DSI0_REFCLK_EN |
  932. CLKCTRL_MIPIDSI0_PIXCLK_EN);
  933. cfg1 |= AP_DPU0_PLL_RST;
  934. }
  935. writel(cfg, (void __iomem *)VOSYS_CLK_GATE_REG);
  936. writel(cfg1, (void __iomem *)AP_DPU0_PLL_CFG1);
  937. }
  938. void ap_mipi_dsi1_clk_endisable(bool en)
  939. {
  940. unsigned int cfg = readl((void __iomem *)VOSYS_CLK_GATE_REG);
  941. unsigned int cfg1 = readl((void __iomem *)AP_DPU1_PLL_CFG1);
  942. if (en) {
  943. cfg |= (CLKCTRL_MIPI_DSI1_PCLK_EN | CLKCTRL_MIPI_DSI1_CFG_CLK_EN | CLKCTRL_MIPI_DSI1_REFCLK_EN |
  944. CLKCTRL_MIPIDSI1_PIXCLK_EN);
  945. cfg1 &= ~AP_DPU1_PLL_RST;
  946. } else {
  947. cfg &= ~(CLKCTRL_MIPI_DSI1_PCLK_EN | CLKCTRL_MIPI_DSI1_CFG_CLK_EN | CLKCTRL_MIPI_DSI1_REFCLK_EN |
  948. CLKCTRL_MIPIDSI1_PIXCLK_EN);
  949. cfg1 |= AP_DPU1_PLL_RST;
  950. }
  951. writel(cfg, (void __iomem *)VOSYS_CLK_GATE_REG);
  952. writel(cfg1, (void __iomem *)AP_DPU1_PLL_CFG1);
  953. }
  954. static void ap_multimedia_div_num_set(enum multimedia_div_type type, unsigned int div_num)
  955. {
  956. unsigned long div_reg;
  957. unsigned int div_num_shift, div_num_mask, div_en;
  958. unsigned int div_cfg;
  959. switch (type) {
  960. case VI_MIPI_CSI0_DIV:
  961. div_reg = VISYS_MIPI_CSI0_PIXELCLK;
  962. div_num_shift = VISYS_MIPI_CSI0_PIXELCLK_DIV_NUM_SHIFT;
  963. div_num_mask = VISYS_MIPI_CSI0_PIXELCLK_DIV_NUM_MASK;
  964. div_en = VISYS_MIPI_CSI0_PIXELCLK_DIV_EN;
  965. break;
  966. case VI_ISP0_CORE_DIV:
  967. div_reg = VISYS_ISP0_CLK_CFG;
  968. div_num_shift = VISYS_ISP0_CLK_DIV_NUM_SHIFT;
  969. div_num_mask = VISYS_ISP0_CLK_DIV_NUM_MASK;
  970. div_en = VISYS_ISP0_CLK_DIV_EN;
  971. break;
  972. case VI_ISP1_CORE_DIV:
  973. div_reg = VISYS_ISP1_CLK_CFG;
  974. div_num_shift = VISYS_ISP1_CLK_DIV_NUM_SHIFT;
  975. div_num_mask = VISYS_ISP1_CLK_DIV_NUM_MASK;
  976. div_en = VISYS_ISP1_CLK_DIV_EN;
  977. break;
  978. case VI_ISP_RY_CORE_DIV:
  979. div_reg = VISYS_ISP_RY_CLK_CFG;
  980. div_num_shift = VISYS_ISP_RY_CLK_DIV_NUM_SHIFT;
  981. div_num_mask = VISYS_ISP_RY_CLK_DIV_NUM_MASK;
  982. div_en = VISYS_ISP_RY_CLK_DIV_EN;
  983. break;
  984. case VO_DPU_CORE_DIV:
  985. div_reg = VOSYS_DPU_CCLK_CFG;
  986. div_num_shift = VOSYS_DPU_CCLK_DIV_NUM_SHIFT;
  987. div_num_mask = VOSYS_DPU_CCLK_DIV_NUM_MASK;
  988. div_en = VOSYS_DPU_CCLK_DIV_EN;
  989. break;
  990. case VO_DPU_PLL0_DIV:
  991. div_reg =APSYS_DPU0_PLL_DIV_CFG;
  992. div_num_shift = APSYS_DPU0_PLL_DIV_CLK_DIV_NUM_SHIFT;
  993. div_num_mask = APSYS_DPU0_PLL_DIV_CLK_DIV_NUM_MASK;
  994. div_en = APSYS_DPU0_PLL_DIV_CLK_DIV_EN;
  995. break;
  996. case VO_DPU_PLL1_DIV:
  997. div_reg =APSYS_DPU1_PLL_DIV_CFG;
  998. div_num_shift = APSYS_DPU1_PLL_DIV_CLK_DIV_NUM_SHIFT;
  999. div_num_mask = APSYS_DPU1_PLL_DIV_CLK_DIV_NUM_MASK;
  1000. div_en = APSYS_DPU1_PLL_DIV_CLK_DIV_EN;
  1001. break;
  1002. default:
  1003. printf("invalid ap multimedia divider type\n");
  1004. return;
  1005. }
  1006. div_cfg = readl((void __iomem *)div_reg);
  1007. div_cfg &= ~div_en;
  1008. writel(div_cfg, (void __iomem *)div_reg);
  1009. div_cfg &= ~(div_num_mask << div_num_shift);
  1010. div_cfg |= (div_num & div_num_mask) << div_num_shift;
  1011. div_cfg |= div_en;
  1012. writel(div_cfg, (void __iomem *)div_reg);
  1013. }
  1014. int clk_config(void)
  1015. {
  1016. unsigned long rate = clk_light_get_rate("c910_cclk", CLK_DEV_MUX);
  1017. if (!rate)
  1018. return -EINVAL;
  1019. printf("C910 CPU FREQ: %ldMHz\n", rate / 1000000);
  1020. rate = clk_light_get_rate("ahb2_cpusys_hclk", CLK_DEV_MUX);
  1021. if (!rate)
  1022. return -EINVAL;
  1023. printf("AHB2_CPUSYS_HCLK FREQ: %ldMHz\n", rate / 1000000);
  1024. rate = clk_light_get_rate("apb3_cpusys_pclk", CLK_DEV_DIV);
  1025. if (!rate)
  1026. return -EINVAL;
  1027. printf("AHB3_CPUSYS_PCLK FREQ: %ldMHz\n", rate / 1000000);
  1028. rate = clk_light_get_rate("perisys_ahb_hclk", CLK_DEV_MUX);
  1029. if (!rate)
  1030. return -EINVAL;
  1031. printf("PERISYS_AHB_HCLK FREQ: %ldMHz\n", rate / 1000000);
  1032. rate = clk_light_get_rate("perisys_apb_pclk", CLK_DEV_DIV);
  1033. if (!rate)
  1034. return -EINVAL;
  1035. printf("PERISYS_APB_PCLK FREQ: %ldMHz\n", rate / 1000000);
  1036. rate = clk_light_get_rate("gmac_pll_foutpostdiv", CLK_DEV_PLL);
  1037. if (!rate)
  1038. return -EINVAL;
  1039. printf("GMAC PLL POSTDIV FREQ: %ldMHZ\n", rate / 1000000);
  1040. rate = clk_light_get_rate("dpu0_pll_foutpostdiv", CLK_DEV_PLL);
  1041. if (!rate)
  1042. return -EINVAL;
  1043. printf("DPU0 PLL POSTDIV FREQ: %ldMHZ\n", rate / 1000000);
  1044. rate = clk_light_get_rate("dpu1_pll_foutpostdiv", CLK_DEV_PLL);
  1045. if (!rate)
  1046. return -EINVAL;
  1047. printf("DPU1 PLL POSTDIV FREQ: %ldMHZ\n", rate / 1000000);
  1048. #ifdef AUDIO_PLL_FREQ_PRINT
  1049. rate = clk_light_get_rate("audio_pll_foutpostdiv", CLK_DEV_PLL);
  1050. if (!rate)
  1051. return -EINVAL;
  1052. printf("AUDIO PLL POSTDIV FREQ: %ldMHZ\n", rate / 1000000);
  1053. rate = clk_light_get_rate("audio_pll_foutvco", CLK_DEV_PLL);
  1054. if (!rate)
  1055. return -EINVAL;
  1056. printf("AUDIO PLL FOUVCO FREQ: %ldMHZ\n", rate / 1000000);
  1057. #endif
  1058. #ifdef SYS_PLL_FREQ_PRINT
  1059. rate = clk_light_get_rate("sys_pll_foutpostdiv", CLK_DEV_PLL);
  1060. if (!rate)
  1061. return -EINVAL;
  1062. printf("SYS PLL POSTDIV FREQ: %ldMHZ\n", rate / 1000000);
  1063. rate = clk_light_get_rate("sys_pll_foutvco", CLK_DEV_PLL);
  1064. if (!rate)
  1065. return -EINVAL;
  1066. printf("SYS PLL FOUVCO FREQ: %ldMHZ\n", rate / 1000000);
  1067. #endif
  1068. #ifdef CPU_PLL_FREQ_SET
  1069. ret = clk_light_set_rate("cpu_pll1_foutpostdiv", CLK_DEV_PLL, 1500000000U);
  1070. if (ret)
  1071. return ret;
  1072. ret = clk_light_set_parent("c910_cclk", "cpu_pll1_foutpostdiv");
  1073. if (ret)
  1074. return ret;
  1075. #endif
  1076. /* The boards other than the LightA board perform the bus down-speed operation */
  1077. #if defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || defined (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_POWER) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_B)
  1078. ap_multimedia_div_num_set(VI_MIPI_CSI0_DIV, 12); /* Input frquency: 2376MHZ */
  1079. ap_multimedia_div_num_set(VI_ISP0_CORE_DIV, 15); /* Input frquency: 2376MHZ */
  1080. ap_multimedia_div_num_set(VI_ISP1_CORE_DIV, 12); /* Input frquency: 2376MHZ */
  1081. ap_multimedia_div_num_set(VI_ISP_RY_CORE_DIV, 12); /* Input frquency: 2376MHZ */
  1082. ap_multimedia_div_num_set(VO_DPU_CORE_DIV, 4); /* Input frquency: 2376MHZ */
  1083. ap_multimedia_div_num_set(VO_DPU_PLL0_DIV, 16);
  1084. ap_multimedia_div_num_set(VO_DPU_PLL1_DIV, 4);
  1085. #endif
  1086. ap_hdmi_clk_endisable(false);
  1087. ap_mipi_dsi1_clk_endisable(false);
  1088. return 0;
  1089. }