mtk_dcm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2017. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <mtk_dcm.h>
  32. #include <debug.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <arch/arm.h>
  36. #include <arch/arm/mmu.h>
  37. #include <arch/ops.h>
  38. #include <target/board.h>
  39. #include <platform/mt_reg_base.h>
  40. #include <platform/mt_typedefs.h>
  41. #include <platform/sync_write.h>
  42. #include <mtk_dcm_autogen.h>
  43. #define late_initcall(a)
  44. #define DEFINE_MUTEX(a)
  45. #define mutex_lock(a)
  46. #define mutex_unlock(a)
  47. #define IOMEM(a) (a)
  48. extern unsigned long mt_secure_call(unsigned long, unsigned long, unsigned long, unsigned long);
  49. #define MTK_SIP_KERNEL_MCSI_NS_ACCESS 0x8200028B
  50. #define mcsi_reg_read(offset) \
  51. mt_secure_call(MTK_SIP_KERNEL_MCSI_NS_ACCESS, 0, offset, 0)
  52. #define mcsi_reg_write(val, offset) \
  53. mt_secure_call(MTK_SIP_KERNEL_MCSI_NS_ACCESS, 1, offset, val)
  54. #define MTK_SIP_KERNEL_DCM 0x82000230
  55. #define dcm_smc_msg(init_type) \
  56. mt_secure_call(MTK_SIP_KERNEL_DCM, init_type, 0, 0)
  57. #define dcm_smc_read_cnt(type) \
  58. mt_secure_call(MTK_SIP_KERNEL_DCM, type, 1, 0)
  59. #define __raw_readl(addr) DRV_Reg32(addr)
  60. #define reg_read(addr) __raw_readl(IOMEM(addr))
  61. #define reg_write(addr, val) mt_reg_sync_writel((val), ((void *)addr))
  62. #define MCUSYS_SMC_WRITE(addr, val) reg_write(addr, val)
  63. #define MCSI_SMC_WRITE(addr, val) mcsi_reg_write(val, (addr##_PHYS & 0xFFFF))
  64. #define MCSI_SMC_READ(addr) mcsi_reg_read(addr##_PHYS & 0xFFFF)
  65. #define dcm_smc_msg_send(msg) dcm_smc_msg(msg)
  66. #define dcm_err(fmt, args...) dprintf(CRITICAL, fmt, ##args)
  67. #define dcm_warn(fmt, args...) dprintf(CRITICAL, fmt, ##args)
  68. #define dcm_info(fmt, args...) dprintf(INFO, fmt, ##args)
  69. #define dcm_dbg(fmt, args...) dprintf(SPEW, fmt, ##args)
  70. #define dcm_ver(fmt, args...) dprintf(SPEW, fmt, ##args)
  71. #define REG_DUMP(addr) dcm_info("%-30s(0x%08x): 0x%08x\n", #addr, addr, reg_read(addr))
  72. #define SECURE_REG_DUMP(addr) dcm_info("%-30s(0x%08x): 0x%08lx\n", #addr, addr, mcsi_reg_read(addr##_PHYS & 0xFFFF))
  73. /** macro **/
  74. #define and(v, a) ((v) & (a))
  75. #define or(v, o) ((v) | (o))
  76. #define aor(v, a, o) (((v) & (a)) | (o))
  77. /** global **/
  78. static short dcm_initiated;
  79. #ifdef CTRL_BIGCORE_DCM_IN_KERNEL
  80. static short dcm_cpu_cluster_stat;
  81. #endif
  82. static unsigned int all_dcm_type = (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE
  83. | INFRA_DCM_TYPE
  84. | EMI_DCM_TYPE | DRAMC_DCM_TYPE
  85. );
  86. static unsigned int init_dcm_type = (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE
  87. | INFRA_DCM_TYPE
  88. );
  89. /*****************************************
  90. * following is implementation per DCM module.
  91. * 1. per-DCM function is 1-argu with ON/OFF/MODE option.
  92. *****************************************/
  93. typedef int (*DCM_FUNC)(int);
  94. typedef void (*DCM_PRESET_FUNC)(void);
  95. int dcm_topckg(ENUM_TOPCKG_DCM on)
  96. {
  97. return 0;
  98. }
  99. void dcm_infracfg_ao_emi_indiv(int on)
  100. {
  101. }
  102. int dcm_infra(ENUM_INFRA_DCM on)
  103. {
  104. /* dcm_infracfg_ao_dcm_dfs_mem_ctrl(on); */
  105. /* dcm_infracfg_ao_dcm_mem_ctrl(on); */
  106. dcm_infracfg_ao_dcm_infra_bus(on);
  107. dcm_infracfg_ao_dcm_peri_bus(on);
  108. dcm_infracfg_ao_dcm_top_p2p_rx_ck(on);
  109. return 0;
  110. }
  111. int dcm_peri(ENUM_PERI_DCM on)
  112. {
  113. return 0;
  114. }
  115. int dcm_armcore(ENUM_ARMCORE_DCM mode)
  116. {
  117. dcm_topckgen_ao_mcu_armpll_ca7ll(mode);
  118. return 0;
  119. }
  120. int dcm_mcusys(ENUM_MCUSYS_DCM on)
  121. {
  122. dcm_mcucfg_bus_clock_dcm(on);
  123. dcm_mcucfg_bus_fabric_dcm(on);
  124. dcm_mcucfg_l2_shared_dcm(on);
  125. dcm_mcucfg_mcu_misc_dcm(on);
  126. return 0;
  127. }
  128. int dcm_big_core(ENUM_BIG_CORE_DCM on)
  129. {
  130. return 0;
  131. }
  132. int dcm_stall_preset(void)
  133. {
  134. return 0;
  135. }
  136. int dcm_stall(ENUM_STALL_DCM on)
  137. {
  138. return 0;
  139. }
  140. int dcm_gic_sync(ENUM_GIC_SYNC_DCM on)
  141. {
  142. return 0;
  143. }
  144. int dcm_last_core(ENUM_LAST_CORE_DCM on)
  145. {
  146. return 0;
  147. }
  148. int dcm_rgu(ENUM_RGU_DCM on)
  149. {
  150. return 0;
  151. }
  152. int dcm_dramc_ao(ENUM_DRAMC_AO_DCM on)
  153. {
  154. dcm_dramc_dramc_dcm(on);
  155. return 0;
  156. }
  157. int dcm_ddrphy(ENUM_DDRPHY_DCM on)
  158. {
  159. return 0;
  160. }
  161. int dcm_emi(ENUM_EMI_DCM on)
  162. {
  163. dcm_emi_dcm_emi_group(on);
  164. dcm_chn0_emi_dcm_emi_group(on);
  165. return 0;
  166. }
  167. int dcm_lpdma(ENUM_LPDMA_DCM on)
  168. {
  169. return 0;
  170. }
  171. /*****************************************************/
  172. typedef struct _dcm {
  173. int current_state;
  174. int saved_state;
  175. int disable_refcnt;
  176. int default_state;
  177. DCM_FUNC func;
  178. DCM_PRESET_FUNC preset_func;
  179. int typeid;
  180. char *name;
  181. } DCM;
  182. static DCM dcm_array[NR_DCM_TYPE] = {
  183. {
  184. .typeid = ARMCORE_DCM_TYPE,
  185. .name = "ARMCORE_DCM",
  186. .func = (DCM_FUNC) dcm_armcore,
  187. .current_state = ARMCORE_DCM_MODE1,
  188. .default_state = ARMCORE_DCM_MODE1,
  189. .disable_refcnt = 0,
  190. },
  191. {
  192. .typeid = MCUSYS_DCM_TYPE,
  193. .name = "MCUSYS_DCM",
  194. .func = (DCM_FUNC) dcm_mcusys,
  195. .current_state = MCUSYS_DCM_ON,
  196. .default_state = MCUSYS_DCM_ON,
  197. .disable_refcnt = 0,
  198. },
  199. {
  200. .typeid = INFRA_DCM_TYPE,
  201. .name = "INFRA_DCM",
  202. .func = (DCM_FUNC) dcm_infra,
  203. /*.preset_func = (DCM_PRESET_FUNC) dcm_infra_preset,*/
  204. .current_state = INFRA_DCM_ON,
  205. .default_state = INFRA_DCM_ON,
  206. .disable_refcnt = 0,
  207. },
  208. {
  209. .typeid = PERI_DCM_TYPE,
  210. .name = "PERI_DCM",
  211. .func = (DCM_FUNC) dcm_peri,
  212. /*.preset_func = (DCM_PRESET_FUNC) dcm_peri_preset,*/
  213. .current_state = PERI_DCM_ON,
  214. .default_state = PERI_DCM_ON,
  215. .disable_refcnt = 0,
  216. },
  217. {
  218. .typeid = EMI_DCM_TYPE,
  219. .name = "EMI_DCM",
  220. .func = (DCM_FUNC) dcm_emi,
  221. .current_state = EMI_DCM_ON,
  222. .default_state = EMI_DCM_ON,
  223. .disable_refcnt = 0,
  224. },
  225. {
  226. .typeid = DRAMC_DCM_TYPE,
  227. .name = "DRAMC_DCM",
  228. .func = (DCM_FUNC) dcm_dramc_ao,
  229. .current_state = DRAMC_AO_DCM_ON,
  230. .default_state = DRAMC_AO_DCM_ON,
  231. .disable_refcnt = 0,
  232. },
  233. {
  234. .typeid = DDRPHY_DCM_TYPE,
  235. .name = "DDRPHY_DCM",
  236. .func = (DCM_FUNC) dcm_ddrphy,
  237. .current_state = DDRPHY_DCM_ON,
  238. .default_state = DDRPHY_DCM_ON,
  239. .disable_refcnt = 0,
  240. },
  241. {
  242. .typeid = STALL_DCM_TYPE,
  243. .name = "STALL_DCM",
  244. .func = (DCM_FUNC) dcm_stall,
  245. .preset_func = (DCM_PRESET_FUNC) dcm_stall_preset,
  246. .current_state = STALL_DCM_ON,
  247. .default_state = STALL_DCM_ON,
  248. .disable_refcnt = 0,
  249. },
  250. {
  251. .typeid = BIG_CORE_DCM_TYPE,
  252. .name = "BIG_CORE_DCM",
  253. .func = (DCM_FUNC) dcm_big_core,
  254. .current_state = BIG_CORE_DCM_ON,
  255. .default_state = BIG_CORE_DCM_ON,
  256. .disable_refcnt = 0,
  257. },
  258. {
  259. .typeid = GIC_SYNC_DCM_TYPE,
  260. .name = "GIC_SYNC_DCM",
  261. .func = (DCM_FUNC) dcm_gic_sync,
  262. .current_state = GIC_SYNC_DCM_ON,
  263. .default_state = GIC_SYNC_DCM_ON,
  264. .disable_refcnt = 0,
  265. },
  266. {
  267. .typeid = LAST_CORE_DCM_TYPE,
  268. .name = "LAST_CORE_DCM",
  269. .func = (DCM_FUNC) dcm_last_core,
  270. .current_state = LAST_CORE_DCM_ON,
  271. .default_state = LAST_CORE_DCM_ON,
  272. .disable_refcnt = 0,
  273. },
  274. {
  275. .typeid = RGU_DCM_TYPE,
  276. .name = "RGU_CORE_DCM",
  277. .func = (DCM_FUNC) dcm_rgu,
  278. .current_state = RGU_DCM_ON,
  279. .default_state = RGU_DCM_ON,
  280. .disable_refcnt = 0,
  281. },
  282. {
  283. .typeid = TOPCKG_DCM_TYPE,
  284. .name = "TOPCKG_DCM",
  285. .func = (DCM_FUNC) dcm_topckg,
  286. .current_state = TOPCKG_DCM_ON,
  287. .default_state = TOPCKG_DCM_ON,
  288. .disable_refcnt = 0,
  289. },
  290. {
  291. .typeid = LPDMA_DCM_TYPE,
  292. .name = "LPDMA_DCM",
  293. .func = (DCM_FUNC) dcm_lpdma,
  294. .current_state = LPDMA_DCM_ON,
  295. .default_state = LPDMA_DCM_ON,
  296. .disable_refcnt = 0,
  297. },
  298. };
  299. /*****************************************
  300. * DCM driver will provide regular APIs :
  301. * 1. dcm_restore(type) to recovery CURRENT_STATE before any power-off reset.
  302. * 2. dcm_set_default(type) to reset as cold-power-on init state.
  303. * 3. dcm_disable(type) to disable all dcm.
  304. * 4. dcm_set_state(type) to set dcm state.
  305. * 5. dcm_dump_state(type) to show CURRENT_STATE.
  306. * 6. /sys/power/dcm_state interface: 'restore', 'disable', 'dump', 'set'. 4 commands.
  307. *
  308. * spsecified APIs for workaround:
  309. * 1. (definitely no workaround now)
  310. *****************************************/
  311. void dcm_set_default(unsigned int type)
  312. {
  313. int i;
  314. DCM *dcm;
  315. #ifndef ENABLE_DCM_IN_LK
  316. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X\n", __func__, type, init_dcm_type);
  317. #else
  318. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X, INIT_DCM_TYPE_BY_K=0x%X\n",
  319. __func__, type, init_dcm_type, INIT_DCM_TYPE_BY_K);
  320. #endif
  321. mutex_lock(&dcm_lock);
  322. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  323. if (type & dcm->typeid) {
  324. dcm->saved_state = dcm->default_state;
  325. dcm->current_state = dcm->default_state;
  326. dcm->disable_refcnt = 0;
  327. #ifdef ENABLE_DCM_IN_LK
  328. if (INIT_DCM_TYPE_BY_K & dcm->typeid) {
  329. #endif
  330. if (dcm->preset_func)
  331. dcm->preset_func();
  332. dcm->func(dcm->current_state);
  333. #ifdef ENABLE_DCM_IN_LK
  334. }
  335. #endif
  336. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  337. dcm->name, dcm->typeid, dcm->current_state,
  338. dcm->disable_refcnt);
  339. }
  340. }
  341. dcm_smc_msg_send(init_dcm_type);
  342. mutex_unlock(&dcm_lock);
  343. }
  344. void dcm_set_state(unsigned int type, int state)
  345. {
  346. int i;
  347. DCM *dcm;
  348. unsigned int init_dcm_type_pre = init_dcm_type;
  349. dcm_warn("[%s]type:0x%X, set:%d, init_dcm_type_pre=0x%X\n",
  350. __func__, type, state, init_dcm_type_pre);
  351. mutex_lock(&dcm_lock);
  352. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  353. if (type & dcm->typeid) {
  354. type &= ~(dcm->typeid);
  355. dcm->saved_state = state;
  356. if (dcm->disable_refcnt == 0) {
  357. if (state)
  358. init_dcm_type |= dcm->typeid;
  359. else
  360. init_dcm_type &= ~(dcm->typeid);
  361. dcm->current_state = state;
  362. dcm->func(dcm->current_state);
  363. }
  364. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  365. dcm->name, dcm->typeid, dcm->current_state,
  366. dcm->disable_refcnt);
  367. }
  368. }
  369. if (init_dcm_type_pre != init_dcm_type) {
  370. dcm_warn("[%s]type:0x%X, set:%d, init_dcm_type=0x%X->0x%X\n",
  371. __func__, type, state, init_dcm_type_pre, init_dcm_type);
  372. dcm_smc_msg_send(init_dcm_type);
  373. }
  374. mutex_unlock(&dcm_lock);
  375. }
  376. void dcm_disable(unsigned int type)
  377. {
  378. int i;
  379. DCM *dcm;
  380. unsigned int init_dcm_type_pre = init_dcm_type;
  381. dcm_warn("[%s]type:0x%X\n", __func__, type);
  382. mutex_lock(&dcm_lock);
  383. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  384. if (type & dcm->typeid) {
  385. type &= ~(dcm->typeid);
  386. dcm->current_state = DCM_OFF;
  387. if (dcm->disable_refcnt++ == 0)
  388. init_dcm_type &= ~(dcm->typeid);
  389. dcm->func(dcm->current_state);
  390. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  391. dcm->name, dcm->typeid, dcm->current_state,
  392. dcm->disable_refcnt);
  393. }
  394. }
  395. if (init_dcm_type_pre != init_dcm_type) {
  396. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X->0x%X\n",
  397. __func__, type, init_dcm_type_pre, init_dcm_type);
  398. dcm_smc_msg_send(init_dcm_type);
  399. }
  400. mutex_unlock(&dcm_lock);
  401. }
  402. void dcm_restore(unsigned int type)
  403. {
  404. int i;
  405. DCM *dcm;
  406. unsigned int init_dcm_type_pre = init_dcm_type;
  407. dcm_warn("[%s]type:0x%X\n", __func__, type);
  408. mutex_lock(&dcm_lock);
  409. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  410. if (type & dcm->typeid) {
  411. type &= ~(dcm->typeid);
  412. if (dcm->disable_refcnt > 0)
  413. dcm->disable_refcnt--;
  414. if (dcm->disable_refcnt == 0) {
  415. if (dcm->saved_state)
  416. init_dcm_type |= dcm->typeid;
  417. else
  418. init_dcm_type &= ~(dcm->typeid);
  419. dcm->current_state = dcm->saved_state;
  420. dcm->func(dcm->current_state);
  421. }
  422. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  423. dcm->name, dcm->typeid, dcm->current_state,
  424. dcm->disable_refcnt);
  425. }
  426. }
  427. if (init_dcm_type_pre != init_dcm_type) {
  428. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X->0x%X\n",
  429. __func__, type, init_dcm_type_pre, init_dcm_type);
  430. dcm_smc_msg_send(init_dcm_type);
  431. }
  432. mutex_unlock(&dcm_lock);
  433. }
  434. void dcm_dump_state(int type)
  435. {
  436. int i;
  437. DCM *dcm;
  438. dcm_info("\n******** dcm dump state *********\n");
  439. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  440. if (type & dcm->typeid) {
  441. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  442. dcm->name, dcm->typeid, dcm->current_state,
  443. dcm->disable_refcnt);
  444. }
  445. }
  446. }
  447. void dcm_dump_regs(void)
  448. {
  449. dcm_info("\n******** dcm dump register *********\n");
  450. REG_DUMP(INFRA_BUS_DCM_CTRL);
  451. REG_DUMP(PERI_BUS_DCM_CTRL);
  452. REG_DUMP(MEM_DCM_CTRL);
  453. REG_DUMP(DFS_MEM_DCM_CTRL);
  454. REG_DUMP(P2P_RX_CLK_ON);
  455. REG_DUMP(INFRA_TOPCKGEN_DCMCTL);
  456. REG_DUMP(DRAMC_DRAMC_PD_CTRL);
  457. REG_DUMP(L2C_SRAM_CTRL);
  458. REG_DUMP(CCI_CLK_CTRL);
  459. REG_DUMP(BUS_FABRIC_DCM_CTRL);
  460. REG_DUMP(MCU_MISC_DCM_CTRL);
  461. REG_DUMP(EMI_CONM);
  462. REG_DUMP(EMI_CONN);
  463. REG_DUMP(CHN0_EMI_CHN_EMI_CONB);
  464. REG_DUMP(EFUSEC_DCM_ON);
  465. }
  466. static int mt_dcm_dts_map(void)
  467. {
  468. return 0;
  469. }
  470. int mt_dcm_init(void)
  471. {
  472. #ifdef DCM_BRINGUP
  473. dcm_warn("%s: skipped for bring up\n", __func__);
  474. return 0;
  475. #endif
  476. if (dcm_initiated)
  477. return 0;
  478. if (mt_dcm_dts_map()) {
  479. dcm_err("%s: failed due to DTS failed\n", __func__);
  480. return -1;
  481. }
  482. #if 0 /* WORKAROUND: Disable big core reg protection */
  483. reg_write(0x10202008, aor(reg_read(0x10202008), ~(0x3), 0x1));
  484. dcm_info("%s: 0x10202008=0x%x\n", __func__, reg_read(0x10202008));
  485. #endif
  486. #ifdef CTRL_BIGCORE_DCM_IN_KERNEL
  487. /* big ext buck iso power on */
  488. reg_write(0x10B00260, reg_read(0x10B00260) & ~(0x1 << 2));
  489. dcm_info("%s: 0x10B00260=0x%x\n", __func__, reg_read(0x10B00260));
  490. dcm_cpu_cluster_stat |= DCM_CPU_CLUSTER_B;
  491. #endif
  492. #ifndef DCM_DEFAULT_ALL_OFF
  493. /** enable all dcm **/
  494. dcm_set_default(init_dcm_type);
  495. #else /* DCM_DEFAULT_ALL_OFF */
  496. dcm_set_state(all_dcm_type, DCM_OFF);
  497. #endif /* #ifndef DCM_DEFAULT_ALL_OFF */
  498. dcm_dump_regs();
  499. dcm_initiated = 1;
  500. return 0;
  501. }
  502. late_initcall(mt_dcm_init);
  503. /**** public APIs *****/
  504. void mt_dcm_disable(void)
  505. {
  506. if (!dcm_initiated)
  507. return;
  508. dcm_disable(all_dcm_type);
  509. }
  510. void mt_dcm_restore(void)
  511. {
  512. if (!dcm_initiated)
  513. return;
  514. dcm_restore(all_dcm_type);
  515. }
  516. unsigned int sync_dcm_convert_freq2div(unsigned int freq)
  517. {
  518. unsigned int div = 0, min_freq = SYNC_DCM_CLK_MIN_FREQ;
  519. if (freq < min_freq)
  520. return 0;
  521. /* max divided ratio = Floor (CPU Frequency / (4 or 5) * system timer Frequency) */
  522. div = (freq / min_freq) - 1;
  523. if (div > SYNC_DCM_MAX_DIV_VAL)
  524. return SYNC_DCM_MAX_DIV_VAL;
  525. return div;
  526. }
  527. int sync_dcm_set_cci_div(unsigned int cci)
  528. {
  529. return 0;
  530. }
  531. int sync_dcm_set_cci_freq(unsigned int cci)
  532. {
  533. dcm_dbg("%s: cci=%u\n", __func__, cci);
  534. sync_dcm_set_cci_div(sync_dcm_convert_freq2div(cci));
  535. return 0;
  536. }
  537. int sync_dcm_set_mp0_div(unsigned int mp0)
  538. {
  539. return 0;
  540. }
  541. int sync_dcm_set_mp0_freq(unsigned int mp0)
  542. {
  543. dcm_dbg("%s: mp0=%u\n", __func__, mp0);
  544. sync_dcm_set_mp0_div(sync_dcm_convert_freq2div(mp0));
  545. return 0;
  546. }
  547. int sync_dcm_set_mp1_div(unsigned int mp1)
  548. {
  549. return 0;
  550. }
  551. int sync_dcm_set_mp1_freq(unsigned int mp1)
  552. {
  553. dcm_dbg("%s: mp1=%u\n", __func__, mp1);
  554. sync_dcm_set_mp1_div(sync_dcm_convert_freq2div(mp1));
  555. return 0;
  556. }
  557. int sync_dcm_set_mp2_div(unsigned int mp2)
  558. {
  559. return 0;
  560. }
  561. int sync_dcm_set_mp2_freq(unsigned int mp2)
  562. {
  563. return 0;
  564. }
  565. /* unit of frequency is MHz */
  566. int sync_dcm_set_cpu_freq(unsigned int cci, unsigned int mp0, unsigned int mp1, unsigned int mp2)
  567. {
  568. sync_dcm_set_cci_freq(cci);
  569. sync_dcm_set_mp0_freq(mp0);
  570. sync_dcm_set_mp1_freq(mp1);
  571. sync_dcm_set_mp2_freq(mp2);
  572. return 0;
  573. }
  574. int sync_dcm_set_cpu_div(unsigned int cci, unsigned int mp0, unsigned int mp1, unsigned int mp2)
  575. {
  576. sync_dcm_set_cci_div(cci);
  577. sync_dcm_set_mp0_div(mp0);
  578. sync_dcm_set_mp1_div(mp1);
  579. sync_dcm_set_mp2_div(mp2);
  580. return 0;
  581. }