mtk_dcm.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  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) 2015. 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. | STALL_DCM_TYPE | BIG_CORE_DCM_TYPE
  84. | GIC_SYNC_DCM_TYPE | RGU_DCM_TYPE
  85. | INFRA_DCM_TYPE
  86. | DDRPHY_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE
  87. );
  88. static unsigned int init_dcm_type = (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE
  89. | STALL_DCM_TYPE | BIG_CORE_DCM_TYPE
  90. | GIC_SYNC_DCM_TYPE | RGU_DCM_TYPE
  91. | INFRA_DCM_TYPE
  92. );
  93. /*****************************************
  94. * following is implementation per DCM module.
  95. * 1. per-DCM function is 1-argu with ON/OFF/MODE option.
  96. *****************************************/
  97. typedef int (*DCM_FUNC)(int);
  98. typedef void (*DCM_PRESET_FUNC)(void);
  99. int dcm_topckg(ENUM_TOPCKG_DCM on)
  100. {
  101. return 0;
  102. }
  103. void dcm_infracfg_ao_emi_indiv(int on)
  104. {
  105. }
  106. int dcm_infra(ENUM_INFRA_DCM on)
  107. {
  108. dcm_infracfg_ao_infra_bus_dcm(on);
  109. dcm_infracfg_ao_infra_emi_local_dcm(on);
  110. dcm_infracfg_ao_infra_rx_p2p_dcm(on);
  111. dcm_infracfg_ao_peri_bus_dcm(on);
  112. dcm_infracfg_ao_peri_module_dcm(on);
  113. return 0;
  114. }
  115. int dcm_peri(ENUM_PERI_DCM on)
  116. {
  117. return 0;
  118. }
  119. int dcm_armcore(ENUM_ARMCORE_DCM mode)
  120. {
  121. dcm_mcu_misccfg_bus_arm_pll_divider_dcm(mode);
  122. dcm_mcu_misccfg_mp0_arm_pll_divider_dcm(mode);
  123. dcm_mcu_misccfg_mp1_arm_pll_divider_dcm(mode);
  124. return 0;
  125. }
  126. int dcm_mcusys(ENUM_MCUSYS_DCM on)
  127. {
  128. dcm_mcu_misccfg_adb400_dcm(on);
  129. dcm_mcu_misccfg_bus_sync_dcm(on);
  130. dcm_mcu_misccfg_bus_clock_dcm(on);
  131. dcm_mcu_misccfg_bus_fabric_dcm(on);
  132. dcm_mcu_misccfg_l2_shared_dcm(on);
  133. dcm_mcu_misccfg_mp0_sync_dcm_enable(on);
  134. dcm_mcu_misccfg_mp1_sync_dcm_enable(on);
  135. dcm_mcu_misccfg_mcu_misc_dcm(on);
  136. dcm_mcu_misc1cfg_mcsia_dcm(on);
  137. return 0;
  138. }
  139. int dcm_big_core(ENUM_BIG_CORE_DCM on)
  140. {
  141. return 0;
  142. }
  143. int dcm_stall_preset(void)
  144. {
  145. dcm_mcu_misccfg_mp_stall_dcm(DCM_ON);
  146. return 0;
  147. }
  148. int dcm_stall(ENUM_STALL_DCM on)
  149. {
  150. dcm_mcu_misccfg_mp0_stall_dcm(on);
  151. dcm_mcu_misccfg_mp1_stall_dcm(on);
  152. return 0;
  153. }
  154. int dcm_gic_sync(ENUM_GIC_SYNC_DCM on)
  155. {
  156. dcm_mcu_misccfg_gic_sync_dcm(on);
  157. return 0;
  158. }
  159. int dcm_last_core(ENUM_LAST_CORE_DCM on)
  160. {
  161. return 0;
  162. }
  163. int dcm_rgu(ENUM_RGU_DCM on)
  164. {
  165. dcm_mp0_cpucfg_mp0_rgu_dcm(on);
  166. dcm_mp1_cpucfg_mp1_rgu_dcm(on);
  167. return 0;
  168. }
  169. int dcm_dramc_ao(ENUM_DRAMC_AO_DCM on)
  170. {
  171. dcm_dramc_ch0_top1_dramc_dcm(on);
  172. dcm_dramc_ch1_top1_dramc_dcm(on);
  173. return 0;
  174. }
  175. int dcm_ddrphy(ENUM_DDRPHY_DCM on)
  176. {
  177. dcm_dramc_ch0_top0_ddrphy(on);
  178. dcm_dramc_ch1_top0_ddrphy(on);
  179. return 0;
  180. }
  181. int dcm_emi(ENUM_EMI_DCM on)
  182. {
  183. dcm_emi_dcm_emi_group(on);
  184. dcm_chn0_emi_dcm_emi_group(on);
  185. dcm_chn1_emi_dcm_emi_group(on);
  186. return 0;
  187. }
  188. int dcm_lpdma(ENUM_LPDMA_DCM on)
  189. {
  190. return 0;
  191. }
  192. /*****************************************************/
  193. typedef struct _dcm {
  194. int current_state;
  195. int saved_state;
  196. int disable_refcnt;
  197. int default_state;
  198. DCM_FUNC func;
  199. DCM_PRESET_FUNC preset_func;
  200. int typeid;
  201. char *name;
  202. } DCM;
  203. static DCM dcm_array[NR_DCM_TYPE] = {
  204. {
  205. .typeid = ARMCORE_DCM_TYPE,
  206. .name = "ARMCORE_DCM",
  207. .func = (DCM_FUNC) dcm_armcore,
  208. .current_state = ARMCORE_DCM_MODE1,
  209. .default_state = ARMCORE_DCM_MODE1,
  210. .disable_refcnt = 0,
  211. },
  212. {
  213. .typeid = MCUSYS_DCM_TYPE,
  214. .name = "MCUSYS_DCM",
  215. .func = (DCM_FUNC) dcm_mcusys,
  216. .current_state = MCUSYS_DCM_ON,
  217. .default_state = MCUSYS_DCM_ON,
  218. .disable_refcnt = 0,
  219. },
  220. {
  221. .typeid = INFRA_DCM_TYPE,
  222. .name = "INFRA_DCM",
  223. .func = (DCM_FUNC) dcm_infra,
  224. /*.preset_func = (DCM_PRESET_FUNC) dcm_infra_preset,*/
  225. .current_state = INFRA_DCM_ON,
  226. .default_state = INFRA_DCM_ON,
  227. .disable_refcnt = 0,
  228. },
  229. {
  230. .typeid = PERI_DCM_TYPE,
  231. .name = "PERI_DCM",
  232. .func = (DCM_FUNC) dcm_peri,
  233. /*.preset_func = (DCM_PRESET_FUNC) dcm_peri_preset,*/
  234. .current_state = PERI_DCM_ON,
  235. .default_state = PERI_DCM_ON,
  236. .disable_refcnt = 0,
  237. },
  238. {
  239. .typeid = EMI_DCM_TYPE,
  240. .name = "EMI_DCM",
  241. .func = (DCM_FUNC) dcm_emi,
  242. .current_state = EMI_DCM_ON,
  243. .default_state = EMI_DCM_ON,
  244. .disable_refcnt = 0,
  245. },
  246. {
  247. .typeid = DRAMC_DCM_TYPE,
  248. .name = "DRAMC_DCM",
  249. .func = (DCM_FUNC) dcm_dramc_ao,
  250. .current_state = DRAMC_AO_DCM_ON,
  251. .default_state = DRAMC_AO_DCM_ON,
  252. .disable_refcnt = 0,
  253. },
  254. {
  255. .typeid = DDRPHY_DCM_TYPE,
  256. .name = "DDRPHY_DCM",
  257. .func = (DCM_FUNC) dcm_ddrphy,
  258. .current_state = DDRPHY_DCM_ON,
  259. .default_state = DDRPHY_DCM_ON,
  260. .disable_refcnt = 0,
  261. },
  262. {
  263. .typeid = STALL_DCM_TYPE,
  264. .name = "STALL_DCM",
  265. .func = (DCM_FUNC) dcm_stall,
  266. .preset_func = (DCM_PRESET_FUNC) dcm_stall_preset,
  267. .current_state = STALL_DCM_ON,
  268. .default_state = STALL_DCM_ON,
  269. .disable_refcnt = 0,
  270. },
  271. {
  272. .typeid = BIG_CORE_DCM_TYPE,
  273. .name = "BIG_CORE_DCM",
  274. .func = (DCM_FUNC) dcm_big_core,
  275. .current_state = BIG_CORE_DCM_ON,
  276. .default_state = BIG_CORE_DCM_ON,
  277. .disable_refcnt = 0,
  278. },
  279. {
  280. .typeid = GIC_SYNC_DCM_TYPE,
  281. .name = "GIC_SYNC_DCM",
  282. .func = (DCM_FUNC) dcm_gic_sync,
  283. .current_state = GIC_SYNC_DCM_ON,
  284. .default_state = GIC_SYNC_DCM_ON,
  285. .disable_refcnt = 0,
  286. },
  287. {
  288. .typeid = LAST_CORE_DCM_TYPE,
  289. .name = "LAST_CORE_DCM",
  290. .func = (DCM_FUNC) dcm_last_core,
  291. .current_state = LAST_CORE_DCM_ON,
  292. .default_state = LAST_CORE_DCM_ON,
  293. .disable_refcnt = 0,
  294. },
  295. {
  296. .typeid = RGU_DCM_TYPE,
  297. .name = "RGU_CORE_DCM",
  298. .func = (DCM_FUNC) dcm_rgu,
  299. .current_state = RGU_DCM_ON,
  300. .default_state = RGU_DCM_ON,
  301. .disable_refcnt = 0,
  302. },
  303. {
  304. .typeid = TOPCKG_DCM_TYPE,
  305. .name = "TOPCKG_DCM",
  306. .func = (DCM_FUNC) dcm_topckg,
  307. .current_state = TOPCKG_DCM_ON,
  308. .default_state = TOPCKG_DCM_ON,
  309. .disable_refcnt = 0,
  310. },
  311. {
  312. .typeid = LPDMA_DCM_TYPE,
  313. .name = "LPDMA_DCM",
  314. .func = (DCM_FUNC) dcm_lpdma,
  315. .current_state = LPDMA_DCM_ON,
  316. .default_state = LPDMA_DCM_ON,
  317. .disable_refcnt = 0,
  318. },
  319. };
  320. /*****************************************
  321. * DCM driver will provide regular APIs :
  322. * 1. dcm_restore(type) to recovery CURRENT_STATE before any power-off reset.
  323. * 2. dcm_set_default(type) to reset as cold-power-on init state.
  324. * 3. dcm_disable(type) to disable all dcm.
  325. * 4. dcm_set_state(type) to set dcm state.
  326. * 5. dcm_dump_state(type) to show CURRENT_STATE.
  327. * 6. /sys/power/dcm_state interface: 'restore', 'disable', 'dump', 'set'. 4 commands.
  328. *
  329. * spsecified APIs for workaround:
  330. * 1. (definitely no workaround now)
  331. *****************************************/
  332. void dcm_set_default(unsigned int type)
  333. {
  334. int i;
  335. DCM *dcm;
  336. #ifndef ENABLE_DCM_IN_LK
  337. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X\n", __func__, type, init_dcm_type);
  338. #else
  339. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X, INIT_DCM_TYPE_BY_K=0x%X\n",
  340. __func__, type, init_dcm_type, INIT_DCM_TYPE_BY_K);
  341. #endif
  342. mutex_lock(&dcm_lock);
  343. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  344. if (type & dcm->typeid) {
  345. dcm->saved_state = dcm->default_state;
  346. dcm->current_state = dcm->default_state;
  347. dcm->disable_refcnt = 0;
  348. #ifdef ENABLE_DCM_IN_LK
  349. if (INIT_DCM_TYPE_BY_K & dcm->typeid) {
  350. #endif
  351. if (dcm->preset_func)
  352. dcm->preset_func();
  353. dcm->func(dcm->current_state);
  354. #ifdef ENABLE_DCM_IN_LK
  355. }
  356. #endif
  357. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  358. dcm->name, dcm->typeid, dcm->current_state,
  359. dcm->disable_refcnt);
  360. }
  361. }
  362. dcm_smc_msg_send(init_dcm_type);
  363. mutex_unlock(&dcm_lock);
  364. }
  365. void dcm_set_state(unsigned int type, int state)
  366. {
  367. int i;
  368. DCM *dcm;
  369. unsigned int init_dcm_type_pre = init_dcm_type;
  370. dcm_warn("[%s]type:0x%X, set:%d, init_dcm_type_pre=0x%X\n",
  371. __func__, type, state, init_dcm_type_pre);
  372. mutex_lock(&dcm_lock);
  373. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  374. if (type & dcm->typeid) {
  375. type &= ~(dcm->typeid);
  376. dcm->saved_state = state;
  377. if (dcm->disable_refcnt == 0) {
  378. if (state)
  379. init_dcm_type |= dcm->typeid;
  380. else
  381. init_dcm_type &= ~(dcm->typeid);
  382. dcm->current_state = state;
  383. dcm->func(dcm->current_state);
  384. }
  385. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  386. dcm->name, dcm->typeid, dcm->current_state,
  387. dcm->disable_refcnt);
  388. }
  389. }
  390. if (init_dcm_type_pre != init_dcm_type) {
  391. dcm_warn("[%s]type:0x%X, set:%d, init_dcm_type=0x%X->0x%X\n",
  392. __func__, type, state, init_dcm_type_pre, init_dcm_type);
  393. dcm_smc_msg_send(init_dcm_type);
  394. }
  395. mutex_unlock(&dcm_lock);
  396. }
  397. void dcm_disable(unsigned int type)
  398. {
  399. int i;
  400. DCM *dcm;
  401. unsigned int init_dcm_type_pre = init_dcm_type;
  402. dcm_warn("[%s]type:0x%X\n", __func__, type);
  403. mutex_lock(&dcm_lock);
  404. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  405. if (type & dcm->typeid) {
  406. type &= ~(dcm->typeid);
  407. dcm->current_state = DCM_OFF;
  408. if (dcm->disable_refcnt++ == 0)
  409. init_dcm_type &= ~(dcm->typeid);
  410. dcm->func(dcm->current_state);
  411. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  412. dcm->name, dcm->typeid, dcm->current_state,
  413. dcm->disable_refcnt);
  414. }
  415. }
  416. if (init_dcm_type_pre != init_dcm_type) {
  417. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X->0x%X\n",
  418. __func__, type, init_dcm_type_pre, init_dcm_type);
  419. dcm_smc_msg_send(init_dcm_type);
  420. }
  421. mutex_unlock(&dcm_lock);
  422. }
  423. void dcm_restore(unsigned int type)
  424. {
  425. int i;
  426. DCM *dcm;
  427. unsigned int init_dcm_type_pre = init_dcm_type;
  428. dcm_warn("[%s]type:0x%X\n", __func__, type);
  429. mutex_lock(&dcm_lock);
  430. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  431. if (type & dcm->typeid) {
  432. type &= ~(dcm->typeid);
  433. if (dcm->disable_refcnt > 0)
  434. dcm->disable_refcnt--;
  435. if (dcm->disable_refcnt == 0) {
  436. if (dcm->saved_state)
  437. init_dcm_type |= dcm->typeid;
  438. else
  439. init_dcm_type &= ~(dcm->typeid);
  440. dcm->current_state = dcm->saved_state;
  441. dcm->func(dcm->current_state);
  442. }
  443. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  444. dcm->name, dcm->typeid, dcm->current_state,
  445. dcm->disable_refcnt);
  446. }
  447. }
  448. if (init_dcm_type_pre != init_dcm_type) {
  449. dcm_warn("[%s]type:0x%X, init_dcm_type=0x%X->0x%X\n",
  450. __func__, type, init_dcm_type_pre, init_dcm_type);
  451. dcm_smc_msg_send(init_dcm_type);
  452. }
  453. mutex_unlock(&dcm_lock);
  454. }
  455. void dcm_dump_state(int type)
  456. {
  457. int i;
  458. DCM *dcm;
  459. dcm_info("\n******** dcm dump state *********\n");
  460. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  461. if (type & dcm->typeid) {
  462. dcm_info("[%s 0x%X] current state:%d (%d)\n",
  463. dcm->name, dcm->typeid, dcm->current_state,
  464. dcm->disable_refcnt);
  465. }
  466. }
  467. }
  468. void dcm_dump_regs(void)
  469. {
  470. dcm_info("\n******** dcm dump register *********\n");
  471. REG_DUMP(MP0_CPUCFG_MP0_RGU_DCM_CONFIG);
  472. REG_DUMP(MP1_CPUCFG_MP1_RGU_DCM_CONFIG);
  473. REG_DUMP(L2C_SRAM_CTRL);
  474. REG_DUMP(CCI_CLK_CTRL);
  475. REG_DUMP(BUS_FABRIC_DCM_CTRL);
  476. REG_DUMP(MCU_MISC_DCM_CTRL);
  477. REG_DUMP(CCI_ADB400_DCM_CONFIG);
  478. REG_DUMP(SYNC_DCM_CONFIG);
  479. REG_DUMP(SYNC_DCM_CLUSTER_CONFIG);
  480. REG_DUMP(MP_GIC_RGU_SYNC_DCM);
  481. REG_DUMP(MP0_PLL_DIVIDER_CFG);
  482. REG_DUMP(MP1_PLL_DIVIDER_CFG);
  483. REG_DUMP(BUS_PLL_DIVIDER_CFG);
  484. REG_DUMP(MCSIA_DCM_EN);
  485. REG_DUMP(INFRA_BUS_DCM_CTRL);
  486. REG_DUMP(PERI_BUS_DCM_CTRL);
  487. REG_DUMP(MEM_DCM_CTRL);
  488. REG_DUMP(P2P_RX_CLK_ON);
  489. REG_DUMP(EMI_CONM);
  490. REG_DUMP(EMI_CONN);
  491. REG_DUMP(CHN0_EMI_CHN_EMI_CONB);
  492. REG_DUMP(CHN1_EMI_CHN_EMI_CONB);
  493. REG_DUMP(DRAMC_CH0_TOP1_DRAMC_PD_CTRL);
  494. REG_DUMP(DRAMC_CH0_TOP1_CLKAR);
  495. REG_DUMP(DRAMC_CH1_TOP1_DRAMC_PD_CTRL);
  496. REG_DUMP(DRAMC_CH1_TOP1_CLKAR);
  497. REG_DUMP(DRAMC_CH0_TOP0_MISC_CG_CTRL0);
  498. REG_DUMP(DRAMC_CH0_TOP0_MISC_CG_CTRL2);
  499. REG_DUMP(DRAMC_CH0_TOP0_MISC_CTRL3);
  500. REG_DUMP(DRAMC_CH0_TOP0_SHU1_B0_DQ8);
  501. REG_DUMP(DRAMC_CH0_TOP0_SHU1_B1_DQ8);
  502. REG_DUMP(DRAMC_CH0_TOP0_SHU1_CA_CMD8);
  503. REG_DUMP(DRAMC_CH0_TOP0_SHU2_B0_DQ8);
  504. REG_DUMP(DRAMC_CH0_TOP0_SHU2_B1_DQ8);
  505. REG_DUMP(DRAMC_CH0_TOP0_SHU2_CA_CMD8);
  506. REG_DUMP(DRAMC_CH0_TOP0_SHU3_B0_DQ8);
  507. REG_DUMP(DRAMC_CH0_TOP0_SHU3_B1_DQ8);
  508. REG_DUMP(DRAMC_CH0_TOP0_SHU3_CA_CMD8);
  509. REG_DUMP(DRAMC_CH0_TOP0_SHU4_B0_DQ8);
  510. REG_DUMP(DRAMC_CH0_TOP0_SHU4_B1_DQ8);
  511. REG_DUMP(DRAMC_CH0_TOP0_SHU4_CA_CMD8);
  512. REG_DUMP(DRAMC_CH1_TOP0_MISC_CG_CTRL0);
  513. REG_DUMP(DRAMC_CH1_TOP0_MISC_CG_CTRL2);
  514. REG_DUMP(DRAMC_CH1_TOP0_MISC_CTRL3);
  515. REG_DUMP(DRAMC_CH1_TOP0_SHU1_B0_DQ8);
  516. REG_DUMP(DRAMC_CH1_TOP0_SHU1_B1_DQ8);
  517. REG_DUMP(DRAMC_CH1_TOP0_SHU1_CA_CMD8);
  518. REG_DUMP(DRAMC_CH1_TOP0_SHU2_B0_DQ8);
  519. REG_DUMP(DRAMC_CH1_TOP0_SHU2_B1_DQ8);
  520. REG_DUMP(DRAMC_CH1_TOP0_SHU2_CA_CMD8);
  521. REG_DUMP(DRAMC_CH1_TOP0_SHU3_B0_DQ8);
  522. REG_DUMP(DRAMC_CH1_TOP0_SHU3_B1_DQ8);
  523. REG_DUMP(DRAMC_CH1_TOP0_SHU3_CA_CMD8);
  524. REG_DUMP(DRAMC_CH1_TOP0_SHU4_B0_DQ8);
  525. REG_DUMP(DRAMC_CH1_TOP0_SHU4_B1_DQ8);
  526. REG_DUMP(DRAMC_CH1_TOP0_SHU4_CA_CMD8);
  527. }
  528. static int mt_dcm_dts_map(void)
  529. {
  530. return 0;
  531. }
  532. int mt_dcm_init(void)
  533. {
  534. #ifdef DCM_BRINGUP
  535. dcm_warn("%s: skipped for bring up\n", __func__);
  536. return 0;
  537. #endif
  538. if (dcm_initiated)
  539. return 0;
  540. if (mt_dcm_dts_map()) {
  541. dcm_err("%s: failed due to DTS failed\n", __func__);
  542. return -1;
  543. }
  544. #if 0 /* WORKAROUND: Disable big core reg protection */
  545. reg_write(0x10202008, aor(reg_read(0x10202008), ~(0x3), 0x1));
  546. dcm_info("%s: 0x10202008=0x%x\n", __func__, reg_read(0x10202008));
  547. #endif
  548. #ifdef CTRL_BIGCORE_DCM_IN_KERNEL
  549. /* big ext buck iso power on */
  550. reg_write(0x10B00260, reg_read(0x10B00260) & ~(0x1 << 2));
  551. dcm_info("%s: 0x10B00260=0x%x\n", __func__, reg_read(0x10B00260));
  552. dcm_cpu_cluster_stat |= DCM_CPU_CLUSTER_B;
  553. #endif
  554. #ifndef DCM_DEFAULT_ALL_OFF
  555. /** enable all dcm **/
  556. dcm_set_default(init_dcm_type);
  557. #else /* DCM_DEFAULT_ALL_OFF */
  558. dcm_set_state(all_dcm_type, DCM_OFF);
  559. #endif /* #ifndef DCM_DEFAULT_ALL_OFF */
  560. dcm_dump_regs();
  561. dcm_initiated = 1;
  562. return 0;
  563. }
  564. late_initcall(mt_dcm_init);
  565. /**** public APIs *****/
  566. void mt_dcm_disable(void)
  567. {
  568. if (!dcm_initiated)
  569. return;
  570. dcm_disable(all_dcm_type);
  571. }
  572. void mt_dcm_restore(void)
  573. {
  574. if (!dcm_initiated)
  575. return;
  576. dcm_restore(all_dcm_type);
  577. }
  578. unsigned int sync_dcm_convert_freq2div(unsigned int freq)
  579. {
  580. unsigned int div = 0, min_freq = SYNC_DCM_CLK_MIN_FREQ;
  581. if (freq < min_freq)
  582. return 0;
  583. /* max divided ratio = Floor (CPU Frequency / (4 or 5) * system timer Frequency) */
  584. div = (freq / min_freq) - 1;
  585. if (div > SYNC_DCM_MAX_DIV_VAL)
  586. return SYNC_DCM_MAX_DIV_VAL;
  587. return div;
  588. }
  589. int sync_dcm_set_cci_div(unsigned int cci)
  590. {
  591. if (!dcm_initiated)
  592. return -1;
  593. /*
  594. * 1. set xxx_sync_dcm_div first
  595. * 2. set xxx_sync_dcm_tog from 0 to 1 for making sure it is toggled
  596. */
  597. reg_write(MCUCFG_SYNC_DCM_CCI_REG,
  598. aor(reg_read(MCUCFG_SYNC_DCM_CCI_REG),
  599. ~MCUCFG_SYNC_DCM_SEL_CCI_MASK,
  600. cci << MCUCFG_SYNC_DCM_SEL_CCI));
  601. reg_write(MCUCFG_SYNC_DCM_CCI_REG, aor(reg_read(MCUCFG_SYNC_DCM_CCI_REG),
  602. ~MCUCFG_SYNC_DCM_CCI_TOGMASK,
  603. MCUCFG_SYNC_DCM_CCI_TOG0));
  604. reg_write(MCUCFG_SYNC_DCM_CCI_REG, aor(reg_read(MCUCFG_SYNC_DCM_CCI_REG),
  605. ~MCUCFG_SYNC_DCM_CCI_TOGMASK,
  606. MCUCFG_SYNC_DCM_CCI_TOG1));
  607. dcm_dbg("%s: MCUCFG_SYNC_DCM_CCI_REG=0x%X, cci_div_sel=%u/%u\n",
  608. __func__, reg_read(MCUCFG_SYNC_DCM_CCI_REG),
  609. (and(reg_read(MCUCFG_SYNC_DCM_CCI_REG),
  610. MCUCFG_SYNC_DCM_SEL_CCI_MASK) >> MCUCFG_SYNC_DCM_SEL_CCI),
  611. cci);
  612. return 0;
  613. }
  614. int sync_dcm_set_cci_freq(unsigned int cci)
  615. {
  616. dcm_dbg("%s: cci=%u\n", __func__, cci);
  617. sync_dcm_set_cci_div(sync_dcm_convert_freq2div(cci));
  618. return 0;
  619. }
  620. int sync_dcm_set_mp0_div(unsigned int mp0)
  621. {
  622. unsigned int mp0_lo = (mp0 & 0xF);
  623. unsigned int mp0_hi = (mp0 & 0x70) >> 4;
  624. if (!dcm_initiated)
  625. return -1;
  626. /*
  627. * 1. set xxx_sync_dcm_div first
  628. * 2. set xxx_sync_dcm_tog from 0 to 1 for making sure it is toggled
  629. */
  630. reg_write(MCUCFG_SYNC_DCM_MP0_REG,
  631. aor(reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  632. ~(MCUCFG_SYNC_DCM_SEL_MP0_LO_MASK |
  633. MCUCFG_SYNC_DCM_SEL_MP0_HI_MASK),
  634. (mp0_lo << MCUCFG_SYNC_DCM_SEL_MP0_LO) |
  635. (mp0_hi << MCUCFG_SYNC_DCM_SEL_MP0_HI)));
  636. reg_write(MCUCFG_SYNC_DCM_MP0_REG, aor(reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  637. ~MCUCFG_SYNC_DCM_MP0_TOGMASK,
  638. MCUCFG_SYNC_DCM_MP0_TOG0));
  639. reg_write(MCUCFG_SYNC_DCM_MP0_REG, aor(reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  640. ~MCUCFG_SYNC_DCM_MP0_TOGMASK,
  641. MCUCFG_SYNC_DCM_MP0_TOG1));
  642. dcm_dbg("%s: MCUCFG_SYNC_DCM_MP0_REG=0x%X, mp0_div_sel=%u/%u, mp0_hi/lo=%u/%u\n",
  643. __func__, reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  644. (or((and(reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  645. MCUCFG_SYNC_DCM_SEL_MP0_LO_MASK) >>
  646. MCUCFG_SYNC_DCM_SEL_MP0_LO),
  647. (and(reg_read(MCUCFG_SYNC_DCM_MP0_REG),
  648. MCUCFG_SYNC_DCM_SEL_MP0_HI_MASK) >>
  649. MCUCFG_SYNC_DCM_SEL_MP0_HI))),
  650. mp0, mp0_hi, mp0_lo);
  651. return 0;
  652. }
  653. int sync_dcm_set_mp0_freq(unsigned int mp0)
  654. {
  655. dcm_dbg("%s: mp0=%u\n", __func__, mp0);
  656. sync_dcm_set_mp0_div(sync_dcm_convert_freq2div(mp0));
  657. return 0;
  658. }
  659. int sync_dcm_set_mp1_div(unsigned int mp1)
  660. {
  661. if (!dcm_initiated)
  662. return -1;
  663. /*
  664. * 1. set xxx_sync_dcm_div first
  665. * 2. set xxx_sync_dcm_tog from 0 to 1 for making sure it is toggled
  666. */
  667. reg_write(MCUCFG_SYNC_DCM_MP1_REG,
  668. aor(reg_read(MCUCFG_SYNC_DCM_MP1_REG),
  669. ~MCUCFG_SYNC_DCM_SEL_MP1_MASK,
  670. mp1 << MCUCFG_SYNC_DCM_SEL_MP1));
  671. reg_write(MCUCFG_SYNC_DCM_MP1_REG, aor(reg_read(MCUCFG_SYNC_DCM_MP1_REG),
  672. ~MCUCFG_SYNC_DCM_MP1_TOGMASK,
  673. MCUCFG_SYNC_DCM_MP1_TOG0));
  674. reg_write(MCUCFG_SYNC_DCM_MP1_REG, aor(reg_read(MCUCFG_SYNC_DCM_MP1_REG),
  675. ~MCUCFG_SYNC_DCM_MP1_TOGMASK,
  676. MCUCFG_SYNC_DCM_MP1_TOG1));
  677. dcm_dbg("%s: MCUCFG_SYNC_DCM_MP1_REG=0x%X, mp1_div_sel=%u/%u\n",
  678. __func__, reg_read(MCUCFG_SYNC_DCM_MP1_REG),
  679. (and(reg_read(MCUCFG_SYNC_DCM_MP1_REG),
  680. MCUCFG_SYNC_DCM_SEL_MP1_MASK) >> MCUCFG_SYNC_DCM_SEL_MP1),
  681. mp1);
  682. return 0;
  683. }
  684. int sync_dcm_set_mp1_freq(unsigned int mp1)
  685. {
  686. dcm_dbg("%s: mp1=%u\n", __func__, mp1);
  687. sync_dcm_set_mp1_div(sync_dcm_convert_freq2div(mp1));
  688. return 0;
  689. }
  690. int sync_dcm_set_mp2_div(unsigned int mp2)
  691. {
  692. return 0;
  693. }
  694. int sync_dcm_set_mp2_freq(unsigned int mp2)
  695. {
  696. return 0;
  697. }
  698. /* unit of frequency is MHz */
  699. int sync_dcm_set_cpu_freq(unsigned int cci, unsigned int mp0, unsigned int mp1, unsigned int mp2)
  700. {
  701. sync_dcm_set_cci_freq(cci);
  702. sync_dcm_set_mp0_freq(mp0);
  703. sync_dcm_set_mp1_freq(mp1);
  704. sync_dcm_set_mp2_freq(mp2);
  705. return 0;
  706. }
  707. int sync_dcm_set_cpu_div(unsigned int cci, unsigned int mp0, unsigned int mp1, unsigned int mp2)
  708. {
  709. sync_dcm_set_cci_div(cci);
  710. sync_dcm_set_mp0_div(mp0);
  711. sync_dcm_set_mp1_div(mp1);
  712. sync_dcm_set_mp2_div(mp2);
  713. return 0;
  714. }