mt_dcm.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. #include <linux/init.h>
  2. #include <linux/export.h>
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/cpumask.h>
  6. #include <linux/cpu.h>
  7. #include <asm/bug.h>
  8. #include <mt-plat/mt_io.h>
  9. #include <mt-plat/sync_write.h>
  10. #include "mt_dcm.h"
  11. #include <mach/mt_secure_api.h>
  12. #include <linux/of.h>
  13. #include <linux/of_address.h>
  14. #include <mt_dramc.h>
  15. /* #define DCM_DEFAULT_ALL_OFF */
  16. #if defined(CONFIG_OF)
  17. static unsigned long topckgen_base;
  18. static unsigned long mcucfg_base;
  19. static unsigned long mcucfg_phys_base;
  20. static unsigned long dramc_ao_base;
  21. static unsigned long emi_reg_base;
  22. static unsigned long infracfg_ao_base;
  23. static unsigned long pericfg_base;
  24. static unsigned long efuse_base;
  25. static unsigned long apmixed_base;
  26. static unsigned long ddrphy_base;
  27. #define MCUCFG_NODE "mediatek,MCUCFG"
  28. #define INFRACFG_AO_NODE "mediatek,INFRACFG_AO"
  29. #define TOPCKGEN_NODE "mediatek,CKSYS"
  30. #define PERICFG_NODE "mediatek,PERICFG"
  31. #define EMI_REG_NODE "mediatek,EMI"
  32. #define EFUSE_NODE "mediatek,EFUSEC"
  33. #define APMIXED_NODE "mediatek,APMIXED"
  34. #undef INFRACFG_AO_BASE
  35. #undef MCUCFG_BASE
  36. #undef TOPCKGEN_BASE
  37. #define INFRACFG_AO_BASE (infracfg_ao_base) /* 0xF0000000 */
  38. #define MCUCFG_BASE (mcucfg_base) /* 0xF0200000 */
  39. #define TOPCKGEN_BASE (topckgen_base) /* 0xF0210000 */
  40. #define PERICFG_BASE (pericfg_base) /* 0xF0002000 */
  41. #define DRAMC_AO_BASE (dramc_ao_base) /* 0xF0214000 */
  42. #define EMI_REG_BASE (emi_reg_base) /* 0xF0203000 */
  43. #define EFUSE_BASE (efuse_base) /* 0xF0206000 */
  44. #define APMIXED_BASE (apmixed_base) /* 0x10209000 */
  45. #define DDRPHY_BASE (ddrphy_base) /* 0xF0213000 */
  46. #else /* #if defined (CONFIG_OF) */
  47. #undef INFRACFG_AO_BASE
  48. #undef MCUCFG_BASE
  49. #undef TOPCKGEN_BASE
  50. #define INFRACFG_AO_BASE 0xF0000000
  51. #define MCUCFG_BASE 0xF0200000
  52. #define TOPCKGEN_BASE 0xF0210000
  53. #define PERICFG_BASE 0xF0002000
  54. #define DRAMC_AO_BASE 0xF0214000
  55. #define EMI_REG_BASE 0xF0203000
  56. #define EFUSE_BASE 0xF0206000
  57. #define APMIXED_BASE 0xF0209000
  58. #define DDRPHY_BASE 0xF0213000
  59. #endif /* #if defined (CONFIG_OF) */
  60. /* APMIXED */
  61. #define APMIXED_PLL_CON2 (APMIXED_BASE + 0x08) /* 0x10209008 */
  62. /* MCUCFG registers */
  63. #define MCUCFG_ACLKEN_DIV (MCUCFG_BASE + 0x640) /* 0x10200640 */
  64. #define MCUCFG_L2C_SRAM_CTRL (MCUCFG_BASE + 0x648) /* 0x10200648 */
  65. #define MCUCFG_CCI_CLK_CTRL (MCUCFG_BASE + 0x660) /* 0x10200660 */
  66. #define MCUCFG_BUS_FABRIC_DCM_CTRL (MCUCFG_BASE + 0x668) /* 0x10200668 */
  67. #define MCUCFG_ACLKEN_DIV_PHYS (mcucfg_phys_base + 0x640) /* 0x10200640 */
  68. #define MCUCFG_L2C_SRAM_CTRL_PHYS (mcucfg_phys_base + 0x648) /* 0x10200648 */
  69. #define MCUCFG_CCI_CLK_CTRL_PHYS (mcucfg_phys_base + 0x660) /* 0x10200660 */
  70. #define MCUCFG_BUS_FABRIC_DCM_CTRL_PHYS (mcucfg_phys_base + 0x668) /* 0x10200668 */
  71. /* INFRASYS_AO */
  72. #define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x0000) /* 0x100000000 */
  73. #define TOP_CKDIV1 (INFRACFG_AO_BASE + 0x0008) /* 0x100000008 */
  74. #define INFRA_TOPCKGEN_DCMCTL (INFRACFG_AO_BASE + 0x010) /* 0x10000010 */
  75. #define INFRA_TOPCKGEN_DCMDBC (INFRACFG_AO_BASE + 0x014) /* 0x10000014 */
  76. #define INFRA_GLOBALCON_DCMCTL (INFRACFG_AO_BASE + 0x050) /* 0x10000050 */
  77. #define INFRA_GLOBALCON_DCMDBC (INFRACFG_AO_BASE + 0x054) /* 0x10000054 */
  78. #define INFRA_GLOBALCON_DCMFSEL (INFRACFG_AO_BASE + 0x058) /* 0x10000058 */
  79. /* TOPCKGEN */
  80. #define TOPCKG_DCM_CFG (TOPCKGEN_BASE + 0x4) /* 0x10210004 */
  81. #define TOPCKG_CLK_MISC_CFG_2 (TOPCKGEN_BASE + 0x218) /* 0x10210218 */
  82. /* perisys */
  83. #define PERI_GLOBALCON_DCMCTL (PERICFG_BASE + 0x050) /* 0x10002050 */
  84. #define PERI_GLOBALCON_DCMDBC (PERICFG_BASE + 0x054) /* 0x10002054 */
  85. #define PERI_GLOBALCON_DCMFSEL (PERICFG_BASE + 0x058) /* 0x10002058 */
  86. /* DRAMC_AO */
  87. #define DRAMC_PD_CTRL (DRAMC_AO_BASE + 0x1dc) /* 0x102141dc */
  88. #define DRAMC_CLKCTRL (DRAMC_AO_BASE + 0x130) /* 0x10214130 */
  89. #define DRAMC_PERFCTL0 (DRAMC_AO_BASE + 0x1ec) /* 0x102141ec */
  90. #define DRAMC_GDDR3CTL1 (DRAMC_AO_BASE + 0x0f4) /* 0x102140f4 */
  91. /* ddrphy */
  92. #define DDRPHY_MEMPLL_DIVIDER (DDRPHY_BASE + 0x640) /* 0x10213640 */
  93. /* EMI */
  94. #define EMI_CONM (EMI_REG_BASE + 0x060) /* 0x10203060 */
  95. /* efuse */
  96. #define EFUSE_REG_DCM_ON (EFUSE_BASE + 0x55c) /* 0x1020655c */
  97. #define TAG "[Power/dcm] "
  98. /* #define DCM_ENABLE_DCM_CFG */
  99. #define dcm_err(fmt, args...) pr_err(TAG fmt, ##args)
  100. #define dcm_warn(fmt, args...) pr_warn(TAG fmt, ##args)
  101. #define dcm_info(fmt, args...) pr_warn(TAG fmt, ##args)
  102. #define dcm_dbg(fmt, args...) pr_debug(TAG fmt, ##args)
  103. #define dcm_ver(fmt, args...) pr_debug(TAG fmt, ##args)
  104. /** macro **/
  105. #define and(v, a) ((v) & (a))
  106. #define or(v, o) ((v) | (o))
  107. #define aor(v, a, o) (((v) & (a)) | (o))
  108. #define reg_read(addr) __raw_readl(IOMEM(addr))
  109. #define reg_write(addr, val) mt_reg_sync_writel((val), ((void *)addr))
  110. #if defined(CONFIG_ARM_PSCI) || defined(CONFIG_MTK_PSCI)
  111. #define MCUSYS_SMC_WRITE(addr, val) mcusys_smc_write_phy(addr##_PHYS, val)
  112. #else
  113. #define MCUSYS_SMC_WRITE(addr, val) mcusys_smc_write(addr, val)
  114. #endif
  115. #define REG_DUMP(addr) dcm_info("%-30s(0x%08lx): 0x%08x\n", #addr, addr, reg_read(addr))
  116. #define DCM_OFF (0)
  117. #define DCM_ON (1)
  118. /** global **/
  119. static DEFINE_MUTEX(dcm_lock);
  120. static unsigned int dcm_initiated;
  121. /*****************************************
  122. * following is implementation per DCM module.
  123. * 1. per-DCM function is 1-argu with ON/OFF/MODE option.
  124. *****************************************/
  125. typedef int (*DCM_FUNC) (int);
  126. /** 0x10000014 INFRA_TOPCKGEN_DCMDBC
  127. * 6 0 topckgen_dcm_dbc_cnt.
  128. * BUT, this field does not behave as its name.
  129. * only topckgen_dcm_dbc_cnt[0] is using as ARMPLL DCM mode 1 switch.
  130. **/
  131. /** 0x10000010 INFRA_TOPCKGEN_DCMCTL
  132. * 1 1 arm_dcm_wfi_enable
  133. * 2 2 arm_dcm_wfe_enable
  134. **/
  135. typedef enum {
  136. ARMCORE_DCM_OFF = DCM_OFF,
  137. ARMCORE_DCM_MODE1 = DCM_ON,
  138. ARMCORE_DCM_MODE2 = DCM_ON + 1,
  139. } ENUM_ARMCORE_DCM;
  140. /** 0x0000 TOP_CKMUXSEL
  141. * 3 2 mux1_sel * "00: CLKSQ, 01: ARMPLL, 10: MAINPLL, 11: 1'b0"
  142. **/
  143. /** 0x0008 TOP_CKDIV1
  144. * 4 0 clkdiv1_sel
  145. **/
  146. int dcm_armcore_pll_clkdiv(int pll, int div)
  147. {
  148. BUG_ON(pll < 0 || pll > 2);
  149. #if 0 /* FIXME, should we have to switch 26M first? */
  150. reg_write(TOP_CKMUXSEL, aor(reg_read(TOP_CKMUXSEL), ~(3 << 2), 0 << 0)); /* 26Mhz */
  151. #endif
  152. {
  153. /* the cg of pll_src_2 */
  154. if (pll == 2)
  155. reg_write(APMIXED_PLL_CON2,
  156. aor(reg_read(APMIXED_PLL_CON2), ~(0x1 << 5), 1 << 5));
  157. }
  158. reg_write(TOP_CKMUXSEL, aor(reg_read(TOP_CKMUXSEL), ~(3 << 2), pll << 2));
  159. {
  160. /* cg clear after mux */
  161. if (pll != 2)
  162. reg_write(APMIXED_PLL_CON2,
  163. aor(reg_read(APMIXED_PLL_CON2), ~(0x1 << 5), 0 << 5));
  164. }
  165. reg_write(TOP_CKDIV1, aor(reg_read(TOP_CKDIV1), ~(0x1f << 0), div << 0));
  166. return 0;
  167. }
  168. int dcm_armcore(ENUM_ARMCORE_DCM mode)
  169. {
  170. if (mode == ARMCORE_DCM_OFF) {
  171. /* swithc to mode 2, and turn wfi/wfe-enable off */
  172. /* disable mode 1 */
  173. reg_write(INFRA_TOPCKGEN_DCMDBC, and(reg_read(INFRA_TOPCKGEN_DCMDBC), ~(1 << 0)));
  174. /* disable wfi/wfe-en */
  175. reg_write(INFRA_TOPCKGEN_DCMCTL, aor(reg_read(INFRA_TOPCKGEN_DCMCTL), ~(0x3 << 1), (0 << 1)));
  176. return 0;
  177. }
  178. if (mode == ARMCORE_DCM_MODE2) {
  179. /* switch to mode 2 */
  180. /* disable mode 1 */
  181. reg_write(INFRA_TOPCKGEN_DCMDBC, and(reg_read(INFRA_TOPCKGEN_DCMDBC), ~(1 << 0)));
  182. reg_write(INFRA_TOPCKGEN_DCMCTL,
  183. aor(reg_read(INFRA_TOPCKGEN_DCMCTL), ~(3 << 1), (3 << 1)));
  184. /* OVERRIDE pll mux and clkdiv !! */
  185. dcm_armcore_pll_clkdiv(1, (3 << 3) | (0)); /* armpll, 6/6 */
  186. }
  187. else if (mode == ARMCORE_DCM_MODE1) {
  188. /* switch to mode 1, and mode 2 off */
  189. /* enable mode 1 */
  190. reg_write(INFRA_TOPCKGEN_DCMDBC, aor(reg_read(INFRA_TOPCKGEN_DCMDBC), ~(1 << 0), (1 << 0)));
  191. reg_write(INFRA_TOPCKGEN_DCMCTL,
  192. aor(reg_read(INFRA_TOPCKGEN_DCMCTL), ~(3 << 1), (0 << 1)));
  193. }
  194. return 0;
  195. }
  196. /**************************
  197. * MCUSYS DCM
  198. **************************/
  199. /** mcucfg+0x0640 ACLKEN_DIV
  200. * 4 0 axi_div_sel, "L2C SRAM interface and MCU_BIU clock divider setting ::
  201. 5'h01: 1/1 x cpu clock ,
  202. 5'h11: 1/1 x cpu clock ,
  203. 5'b12: 1/2 x cpu clock ,
  204. 5'b14: 1/4 x cpu clock
  205. * Please set 0x1020-0640 bit[4:0], 5’h12 for 1/2 CPU clock.
  206. * mcu_biu can only run up to 1/2 of 1.3GHz CPU clock.
  207. **/
  208. #define MCUCFG_ACLKEN_DIV_MASK (0x01f << 0)
  209. #define MCUCFG_ACLKEN_DIV_ON (0x12 << 0)
  210. #define MCUCFG_ACLKEN_DIV_OFF (0x12 << 0)
  211. /** 0x0648 L2C_SRAM_CTRL
  212. * 0 0 l2c_sram_dcm_en, L2C SRAM DCM enable, "0: Disable, 1: Enable"
  213. **/
  214. #define MCUCFG_L2C_SRAM_CTRL_MASK (0x1 << 0)
  215. #define MCUCFG_L2C_SRAM_CTRL_ON (0x1 << 0)
  216. #define MCUCFG_L2C_SRAM_CTRL_OFF (0x0 << 0)
  217. /** 0x0660 CCI_CLK_CTRL
  218. * 8 8 MCU_BUS_DCM_EN "0: Disable, 1: Enable"
  219. **/
  220. #define MCUCFG_CCI_CLK_CTRL_MASK (0x1 << 8)
  221. #define MCUCFG_CCI_CLK_CTRL_ON (0x1 << 8)
  222. #define MCUCFG_CCI_CLK_CTRL_OFF (0x0 << 8)
  223. /** 0x0668 BUS_FABRIC_DCM_CTRL
  224. * 0 0 ACLK_INFRA_dynamic_CG_en "0: disable, 1: enable"
  225. * 1 1 ACLK_EMI_dynamic_CG_en "0: disable, 1: enable"
  226. * 8 8 InfraCLK_INFRA_dynamic_CG_en "0: disable, 1: enable"
  227. * 9 9 EMICLK_EMI_dynamic_CG_en "0: disable, 1: enable"
  228. **/
  229. #define MCUCFG_BUS_FABRIC_DCM_CTRL_MASK ((3<<0) | (3<<8))
  230. #define MCUCFG_BUS_FABRIC_DCM_CTRL_ON ((3<<0) | (3<<8))
  231. #define MCUCFG_BUS_FABRIC_DCM_CTRL_OFF ((0<<0) | (0<<8))
  232. typedef enum {
  233. MCUSYS_DCM_OFF = DCM_OFF,
  234. MCUSYS_DCM_ON = DCM_ON,
  235. } ENUM_MCUSYS_DCM;
  236. int dcm_mcusys(ENUM_MCUSYS_DCM on)
  237. {
  238. if (on == MCUSYS_DCM_OFF) {
  239. /* MCUSYS CCI CTRL, */
  240. MCUSYS_SMC_WRITE(MCUCFG_CCI_CLK_CTRL,
  241. aor(reg_read(MCUCFG_CCI_CLK_CTRL), ~MCUCFG_CCI_CLK_CTRL_MASK,
  242. MCUCFG_CCI_CLK_CTRL_OFF));
  243. /* L2C SRAM DCM */
  244. MCUSYS_SMC_WRITE(MCUCFG_L2C_SRAM_CTRL,
  245. aor(reg_read(MCUCFG_L2C_SRAM_CTRL), ~MCUCFG_L2C_SRAM_CTRL_MASK,
  246. MCUCFG_L2C_SRAM_CTRL_OFF));
  247. /* bus_fabric_dcm_ctrl */
  248. MCUSYS_SMC_WRITE(MCUCFG_BUS_FABRIC_DCM_CTRL,
  249. aor(reg_read(MCUCFG_BUS_FABRIC_DCM_CTRL),
  250. ~MCUCFG_BUS_FABRIC_DCM_CTRL_MASK,
  251. MCUCFG_BUS_FABRIC_DCM_CTRL_OFF));
  252. } else {
  253. MCUSYS_SMC_WRITE(MCUCFG_CCI_CLK_CTRL,
  254. aor(reg_read(MCUCFG_CCI_CLK_CTRL), ~MCUCFG_CCI_CLK_CTRL_MASK,
  255. MCUCFG_CCI_CLK_CTRL_ON));
  256. /* L2C SRAM DCM */
  257. MCUSYS_SMC_WRITE(MCUCFG_L2C_SRAM_CTRL,
  258. aor(reg_read(MCUCFG_L2C_SRAM_CTRL), ~MCUCFG_L2C_SRAM_CTRL_MASK,
  259. MCUCFG_L2C_SRAM_CTRL_ON));
  260. /* bus_fabric_dcm_ctrl */
  261. MCUSYS_SMC_WRITE(MCUCFG_BUS_FABRIC_DCM_CTRL,
  262. aor(reg_read(MCUCFG_BUS_FABRIC_DCM_CTRL),
  263. ~MCUCFG_BUS_FABRIC_DCM_CTRL_MASK,
  264. MCUCFG_BUS_FABRIC_DCM_CTRL_ON));
  265. }
  266. return 0;
  267. }
  268. /** 0x10210004 DCM_CFG
  269. * 4 0 dcm_full_fsel (axi bus dcm full fsel)
  270. * 7 7 dcm_enable
  271. * 14 8 dcm_dbc_cnt
  272. * 15 15 dcm_dbc_enable
  273. * 20 16 mem_dcm_full_fsel ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32")
  274. * 21 21 mem_dcm_cfg_latch
  275. * 22 22 mem_dcm_idle_align
  276. * 23 23 mem_dcm_enable
  277. * 30 24 mem_dcm_dbc_cnt
  278. * 31 31 mem_dcm_dbc_enable
  279. **/
  280. #define TOPCKG_DCM_CFG_MASK ((0x1f<<0) | (1<<7) | (0x7f<<8) | (1<<15))
  281. #define TOPCKG_DCM_CFG_ON ((0<<0) | (1<<7) | (0<<8) | (0<<15))
  282. #define TOPCKG_DCM_CFG_OFF (0<<7)
  283. /* Used for slow idle to enable or disable TOPCK DCM */
  284. #define TOPCKG_DCM_CFG_QMASK (1<<7)
  285. #define TOPCKG_DCM_CFG_QON (1<<7)
  286. #define TOPCKG_DCM_CFG_QOFF (0<<7)
  287. #define TOPCKG_DCM_CFG_FMEM_MASK ((0x1f<<16) | (1<<21) | (1<<22) \
  288. | (1<<23) | (0x7f<<24) | (1<<31))
  289. #define TOPCKG_DCM_CFG_FMEM_ON ((0<<16) | (1<<21) | (0x1<<22) \
  290. | (1<<23) | (0<<24) | (0<<31))
  291. #define TOPCKG_DCM_CFG_FMEM_OFF ((1<<21) | (0<<23))
  292. /* toggle mem_dcm_cfg_latch since it's triggered by rising edge */
  293. #define TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK (1<<21)
  294. #define TOPCKG_DCM_CFG_FMEM_TOGGLE_CLEAR (0<<21)
  295. #define TOPCKG_DCM_CFG_FMEM_TOGGLE_ON (1<<21)
  296. /** TOPCKG_CLK_MISC_CFG_2
  297. * 7 0 mem_dcm_force_idle (0: does not force idle, 1: force idle to high)
  298. **/
  299. #define TOPCKG_CLK_MISC_CFG_2_MASK (0xf<<0)
  300. #define TOPCKG_CLK_MISC_CFG_2_ON (0xf<<0)
  301. #define TOPCKG_CLK_MISC_CFG_2_OFF (0x0<<0)
  302. /** 0x10000010 INFRA_TOPCKGEN_DCMCTL
  303. * 0 0 infra_dcm_enable
  304. * this field actually is to activate clock ratio between infra/fast_peri/slow_peri.
  305. * and need to set when bus clock switch from CLKSQ to PLL.
  306. * do ASSERT, for each time infra/peri bus dcm setting.
  307. **/
  308. #define ASSERT_INFRA_DCMCTL() \
  309. do { \
  310. volatile unsigned int dcmctl; \
  311. dcmctl = reg_read(INFRA_TOPCKGEN_DCMCTL); \
  312. BUG_ON(!(dcmctl & 1)); \
  313. } while (0)
  314. /** 0x10000050 INFRA_GLOBALCON_DCMCTL
  315. * 0 0 faxi_dcm_enable
  316. * 1 1 fmem_dcm_enable
  317. * 8 8 axi_clock_gated_en
  318. * 9 9 l2c_sram_infra_dcm_en
  319. **/
  320. #define INFRA_GLOBALCON_DCMCTL_MASK (0x00000303)
  321. #define INFRA_GLOBALCON_DCMCTL_ON (0x00000303)
  322. #define INFRA_GLOBALCON_DCMCTL_OFF (0x00000000)
  323. /** 0x10000054 INFRA_GLOBALCON_DCMDBC
  324. * 6 0 dcm_dbc_cnt (default 7'h7F)
  325. * 8 8 faxi_dcm_dbc_enable
  326. * 22 16 dcm_dbc_cnt_fmem (default 7'h7F)
  327. * 24 24 dcm_dbc_enable_fmem
  328. **/
  329. #define INFRA_GLOBALCON_DCMDBC_MASK ((0x7f<<0) | (1<<8) | (0x7f<<16) | (1<<24))
  330. #define INFRA_GLOBALCON_DCMDBC_ON ((0<<0) | (1<<8) | (0<<16) | (1<<24))
  331. #define INFRA_GLOBALCON_DCMDBC_OFF INFRA_GLOBALCON_DCMDBC_ON /* dont-care */
  332. /** 0x10000058 INFRA_GLOBALCON_DCMFSEL
  333. * 2 0 dcm_qtr_fsel ("1xx: 1/4, 01x: 1/8, 001: 1/16, 000: 1/32")
  334. * 11 8 dcm_half_fsel ("1xxx:1/2, 01xx: 1/4, 001x: 1/8, 0001: 1/16, 0000: 1/32")
  335. * 20 16 dcm_full_fsel ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32")
  336. * 28 24 dcm_full_fsel_fmem ("1xxxx:1/1, 01xxx:1/2, 001xx: 1/4, 0001x: 1/8, 00001: 1/16, 00000: 1/32")
  337. **/
  338. #define INFRA_GLOBALCON_DCMFSEL_MASK ((0x7<<0) | (0x7<<8) | (0x1f<<16) | (0x1f<<24))
  339. #define INFRA_GLOBALCON_DCMFSEL_ON ((0<<0) | (0<<8) | (0x10<<16) | (0x10<<24))
  340. #define INFRA_GLOBALCON_DCMFSEL_OFF (INFRA_GLOBALCON_DCMFSEL_ON) /* dont-care */
  341. typedef enum {
  342. TOPCKG_DCM_OFF = DCM_OFF,
  343. TOPCKG_DCM_ON = DCM_ON,
  344. } ENUM_TOPCKG_DCM;
  345. typedef enum {
  346. INFRA_DCM_OFF = DCM_OFF,
  347. INFRA_DCM_ON = DCM_ON,
  348. } ENUM_INFRA_DCM;
  349. int dcm_topckg_dbc(int on, int cnt)
  350. {
  351. int value;
  352. cnt &= 0x7f;
  353. on = (on != 0) ? 1 : 0;
  354. value = (cnt << 8) | (cnt << 24) | (on << 15) | (on << 31);
  355. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  356. ~((0xff << 8) | (0xff << 24)), value));
  357. return 0;
  358. }
  359. /** input argument
  360. * 0: 1/1
  361. * 1: 1/2
  362. * 2: 1/4
  363. * 3: 1/8
  364. * 4: 1/16
  365. * 5: 1/32
  366. **/
  367. int dcm_topckg_rate(unsigned int fmem, unsigned int faxi)
  368. {
  369. fmem = 0x10 >> fmem;
  370. faxi = 0x10 >> faxi;
  371. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  372. ~((0x1f << 0) | (0x1f << 16)), (fmem << 16) | (faxi << 0)));
  373. return 0;
  374. }
  375. /** FMEM DCM enable or disable (separate fmem DCM setting from TOPCK)
  376. * For writing reg successfully, we need to toggle mem_dcm_cfg_latch first.
  377. **/
  378. int dcm_fmem(ENUM_TOPCKG_DCM on)
  379. {
  380. if (on) {
  381. /* write reverse value of 21th bit */
  382. reg_write(TOPCKG_DCM_CFG,
  383. aor(reg_read(TOPCKG_DCM_CFG),
  384. ~TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK,
  385. and(~reg_read(TOPCKG_DCM_CFG), TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK)));
  386. reg_write(TOPCKG_DCM_CFG,
  387. aor(reg_read(TOPCKG_DCM_CFG),
  388. ~TOPCKG_DCM_CFG_FMEM_MASK, TOPCKG_DCM_CFG_FMEM_ON));
  389. /* Debug only: force fmem enter idle */
  390. /* reg_write(TOPCKG_CLK_MISC_CFG_2, TOPCKG_CLK_MISC_CFG_2_ON); */
  391. } else {
  392. /* write reverse value of 21th bit */
  393. reg_write(TOPCKG_DCM_CFG,
  394. aor(reg_read(TOPCKG_DCM_CFG),
  395. ~TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK,
  396. and(~reg_read(TOPCKG_DCM_CFG), TOPCKG_DCM_CFG_FMEM_TOGGLE_MASK)));
  397. reg_write(TOPCKG_DCM_CFG,
  398. aor(reg_read(TOPCKG_DCM_CFG),
  399. ~TOPCKG_DCM_CFG_FMEM_MASK, TOPCKG_DCM_CFG_FMEM_OFF));
  400. /* Debug only: force fmem enter idle */
  401. /* reg_write(TOPCKG_CLK_MISC_CFG_2, TOPCKG_CLK_MISC_CFG_2_OFF); */
  402. }
  403. return 0;
  404. }
  405. int dcm_topckg(ENUM_TOPCKG_DCM on)
  406. {
  407. if (on) {
  408. dcm_fmem(on);
  409. /* please be noticed, here TOPCKG_DCM_CFG_ON will overrid dbc/fsel setting !! */
  410. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  411. ~TOPCKG_DCM_CFG_MASK, TOPCKG_DCM_CFG_ON));
  412. } else {
  413. dcm_fmem(on);
  414. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  415. ~TOPCKG_DCM_CFG_MASK, TOPCKG_DCM_CFG_OFF));
  416. }
  417. return 0;
  418. }
  419. /* cnt : 0~0x7f */
  420. int dcm_infra_dbc(int on, int cnt)
  421. {
  422. int value;
  423. cnt &= 0x7f;
  424. on = (on != 0) ? 1 : 0;
  425. value = (cnt << 0) | (cnt << 16) | (on << 8) | (on << 24);
  426. reg_write(INFRA_GLOBALCON_DCMDBC, aor(reg_read(INFRA_GLOBALCON_DCMDBC),
  427. ~INFRA_GLOBALCON_DCMDBC_MASK, value));
  428. return 0;
  429. }
  430. /** input argument
  431. * 0: 1/1
  432. * 1: 1/2
  433. * 2: 1/4
  434. * 3: 1/8
  435. * 4: 1/16
  436. * 5: 1/32
  437. **/
  438. int dcm_infra_rate(unsigned fmem, unsigned int full, unsigned int half, unsigned int quarter)
  439. {
  440. BUG_ON(half < 1);
  441. BUG_ON(quarter < 2);
  442. fmem = 0x10 >> fmem;
  443. full = 0x10 >> full;
  444. half = 0x10 >> half;
  445. quarter = 0x10 >> quarter;
  446. reg_write(INFRA_GLOBALCON_DCMFSEL, aor(reg_read(INFRA_GLOBALCON_DCMFSEL),
  447. ~INFRA_GLOBALCON_DCMFSEL_MASK,
  448. (fmem << 24) | (full << 16) | (half << 8) | (quarter
  449. << 0)));
  450. return 0;
  451. }
  452. int dcm_infra(ENUM_INFRA_DCM on)
  453. {
  454. ASSERT_INFRA_DCMCTL();
  455. if (on) {
  456. #if 1 /* override the dbc and fsel setting !! */
  457. reg_write(INFRA_GLOBALCON_DCMDBC,
  458. aor(reg_read(INFRA_GLOBALCON_DCMDBC), ~INFRA_GLOBALCON_DCMDBC_MASK,
  459. INFRA_GLOBALCON_DCMDBC_ON));
  460. reg_write(INFRA_GLOBALCON_DCMFSEL,
  461. aor(reg_read(INFRA_GLOBALCON_DCMFSEL), ~INFRA_GLOBALCON_DCMFSEL_MASK,
  462. INFRA_GLOBALCON_DCMFSEL_ON));
  463. #endif
  464. reg_write(INFRA_GLOBALCON_DCMCTL,
  465. aor(reg_read(INFRA_GLOBALCON_DCMCTL), ~INFRA_GLOBALCON_DCMCTL_MASK,
  466. INFRA_GLOBALCON_DCMCTL_ON));
  467. } else {
  468. reg_write(INFRA_GLOBALCON_DCMCTL,
  469. aor(reg_read(INFRA_GLOBALCON_DCMCTL), ~INFRA_GLOBALCON_DCMCTL_MASK,
  470. INFRA_GLOBALCON_DCMCTL_OFF));
  471. }
  472. return 0;
  473. }
  474. /** 0x10002050 PERI_GLOBALCON_DCMCTL
  475. * 0 0 DCM_ENABLE
  476. * 1 1 AXI_CLOCK_GATED_EN
  477. * 7 4 AHB_BUS_SLP_REQ
  478. * 12 8 DCM_IDLE_BYPASS_EN
  479. **/
  480. /** 0x10002054 PERI_GLOBALCON_DCMDBC
  481. * 7 7 DCM_DBC_ENABLE
  482. * 6 0 DCM_DBC_CNT
  483. **/
  484. /** 0x10002058 PERI_GLOBALCON_DCMFSEL
  485. * 20 16 DCM_FULL_FSEL
  486. * 11 8 DCM_HALF_FSEL
  487. * 2 0 DCM_QTR_FSEL
  488. **/
  489. #define PERI_GLOBALCON_DCMCTL_MASK ((1<<0) | (1<<1) | (0xf<<4) | (0xf<<8))
  490. #define PERI_GLOBALCON_DCMCTL_ON ((1<<0) | (1<<1) | (0xf<<4) | (0x0<<8))
  491. #define PERI_GLOBALCON_DCMCTL_OFF ((0<<0) | (0<<1) | (0x0<<4) | (0x0<<8))
  492. #define PERI_GLOBALCON_DCMDBC_MASK ((0x7f<<0) | (1<<7))
  493. #define PERI_GLOBALCON_DCMDBC_ON ((0x70<<0) | (1<<7))
  494. #define PERI_GLOBALCON_DCMDBC_OFF ((0x70<<0) | (0<<7))
  495. #define PERI_GLOBALCON_DCMFSEL_MASK ((0x7<<0) | (0xf<<8) | (0x1f<<16))
  496. #define PERI_GLOBALCON_DCMFSEL_ON ((0<<0) | (0<<8) | (0x0<<16))
  497. #define PERI_GLOBALCON_DCMFSEL_OFF ((0<<0) | (0<<8) | (0x0<<16))
  498. typedef enum {
  499. PERI_DCM_OFF = DCM_OFF,
  500. PERI_DCM_ON = DCM_ON,
  501. } ENUM_PERI_DCM;
  502. /* cnt: 0~0x7f */
  503. int dcm_peri_dbc(int on, int cnt)
  504. {
  505. BUG_ON(cnt > 0x7f);
  506. on = (on != 0) ? 1 : 0;
  507. reg_write(PERI_GLOBALCON_DCMDBC,
  508. aor(reg_read(PERI_GLOBALCON_DCMDBC),
  509. ~PERI_GLOBALCON_DCMDBC_MASK, ((cnt << 0) | (on << 7))));
  510. return 0;
  511. }
  512. /** input argument
  513. * 0: 1/1
  514. * 1: 1/2
  515. * 2: 1/4
  516. * 3: 1/8
  517. * 4: 1/16
  518. * 5: 1/32
  519. * default: 5, 5, 5
  520. **/
  521. int dcm_peri_rate(unsigned int full, unsigned int half, unsigned int quarter)
  522. {
  523. BUG_ON(half < 1);
  524. BUG_ON(quarter < 2);
  525. full = 0x10 >> full;
  526. half = 0x10 >> half;
  527. quarter = 0x10 >> quarter;
  528. reg_write(PERI_GLOBALCON_DCMFSEL, aor(reg_read(PERI_GLOBALCON_DCMFSEL),
  529. ~PERI_GLOBALCON_DCMFSEL_MASK,
  530. (full << 16) | (half << 8) | (quarter << 0)));
  531. return 0;
  532. }
  533. int dcm_peri(ENUM_PERI_DCM on)
  534. {
  535. if (on) {
  536. #if 1 /* override the dbc and fsel setting !! */
  537. reg_write(PERI_GLOBALCON_DCMDBC,
  538. aor(reg_read(PERI_GLOBALCON_DCMDBC), ~PERI_GLOBALCON_DCMDBC_MASK,
  539. PERI_GLOBALCON_DCMDBC_ON));
  540. reg_write(PERI_GLOBALCON_DCMFSEL,
  541. aor(reg_read(PERI_GLOBALCON_DCMFSEL), ~PERI_GLOBALCON_DCMFSEL_MASK,
  542. PERI_GLOBALCON_DCMFSEL_ON));
  543. #endif
  544. reg_write(PERI_GLOBALCON_DCMCTL, aor(reg_read(PERI_GLOBALCON_DCMCTL),
  545. ~PERI_GLOBALCON_DCMCTL_MASK,
  546. PERI_GLOBALCON_DCMCTL_ON));
  547. } else {
  548. #if 1 /* override the dbc and fsel setting !! */
  549. reg_write(PERI_GLOBALCON_DCMDBC,
  550. aor(reg_read(PERI_GLOBALCON_DCMDBC), ~PERI_GLOBALCON_DCMDBC_MASK,
  551. PERI_GLOBALCON_DCMDBC_OFF));
  552. reg_write(PERI_GLOBALCON_DCMFSEL,
  553. aor(reg_read(PERI_GLOBALCON_DCMFSEL), ~PERI_GLOBALCON_DCMFSEL_MASK,
  554. PERI_GLOBALCON_DCMFSEL_OFF));
  555. #endif
  556. reg_write(PERI_GLOBALCON_DCMCTL, aor(reg_read(PERI_GLOBALCON_DCMCTL),
  557. ~PERI_GLOBALCON_DCMCTL_MASK,
  558. PERI_GLOBALCON_DCMCTL_OFF));
  559. }
  560. return 0;
  561. }
  562. /** 0x102141dc DRAMC_PD_CTRL
  563. * 31 31 COMBCLKCTRL ("DQPHY clock dynamic gating control (gating during All-bank Refresh), 1 : controlled by dramc , 0 : always no gating" )
  564. * 30 30 PHYCLKDYNGEN ("CMDPHY clock dynamic gating control, 1 : controlled by dramc, 0 : always no gating")
  565. * 25 25 DCMEN ("DRAMC non-freerun clock gating function, 0: disable, 1: enable")
  566. **/
  567. typedef enum {
  568. DRAMC_AO_DCM_OFF = DCM_OFF,
  569. DRAMC_AO_DCM_ON = DCM_ON,
  570. } ENUM_DRAMC_AO_DCM;
  571. int dcm_dramc_ao(ENUM_DRAMC_AO_DCM on)
  572. {
  573. if (on) {
  574. reg_write(DRAMC_PD_CTRL, aor(reg_read(DRAMC_PD_CTRL),
  575. ~((1 << 25) | (1 << 30) | (1 << 31)),
  576. ((1 << 25) | (1 << 30) | (1 << 31))));
  577. } else {
  578. reg_write(DRAMC_PD_CTRL, aor(reg_read(DRAMC_PD_CTRL),
  579. ~((1 << 25) | (1 << 30) | (1 << 31)),
  580. ((0 << 25) | (0 << 30) | (0 << 31))));
  581. }
  582. return 0;
  583. }
  584. /** 0x10203060 EMI_CONM
  585. * 31 24 EMI_DCM_DIS
  586. **/
  587. typedef enum {
  588. EMI_DCM_OFF = DCM_OFF,
  589. EMI_DCM_ON = DCM_ON,
  590. } ENUM_EMI_DCM;
  591. int dcm_emi(ENUM_EMI_DCM on)
  592. {
  593. if (on)
  594. reg_write(EMI_CONM, aor(reg_read(EMI_CONM), ~(0xff << 24), (0 << 24)));
  595. else
  596. reg_write(EMI_CONM, aor(reg_read(EMI_CONM), ~(0xff << 24), (0xff << 24)));
  597. return 0;
  598. }
  599. #if defined(CONFIG_ARCH_MT6753)
  600. /** 0x10213640 DDRPHY_MEMPLL_DIVIDER
  601. * 15 15 R_COMB_M_CK_CG_EN -> 0:Disable, 1: Enable
  602. * 17 17 R_MEMPLL3_CKOUT_CG_EN
  603. * ...
  604. * 31 31 R_D_MIO_CK_CG_EN
  605. **/
  606. #define DDRPHY_MEMPLL_DIVIDER_MASK ((1<<15) | (0x7ff<<17))
  607. #define DDRPHY_MEMPLL_DIVIDER_ON ((1<<15) | (0x7ff<<17))
  608. #define DDRPHY_MEMPLL_DIVIDER_OFF ((0<<15) | (0x0<<17))
  609. typedef enum {
  610. DDRPHY_DCM_OFF = DCM_OFF,
  611. DDRPHY_DCM_ON = DCM_ON,
  612. } ENUM_DDRPHY_DCM;
  613. int dcm_ddrphy(ENUM_DDRPHY_DCM on)
  614. {
  615. if (on) {
  616. reg_write(DDRPHY_MEMPLL_DIVIDER,
  617. aor(reg_read(DDRPHY_MEMPLL_DIVIDER),
  618. ~DDRPHY_MEMPLL_DIVIDER_MASK, DDRPHY_MEMPLL_DIVIDER_ON));
  619. } else {
  620. reg_write(DDRPHY_MEMPLL_DIVIDER,
  621. aor(reg_read(DDRPHY_MEMPLL_DIVIDER),
  622. ~DDRPHY_MEMPLL_DIVIDER_MASK, DDRPHY_MEMPLL_DIVIDER_OFF));
  623. }
  624. return 0;
  625. }
  626. #endif /* CONFIG_ARCH_MT6753 */
  627. /** 0x1020655c EFUSE_REG_DCM_ON
  628. * 0 0 DCM_ON
  629. **/
  630. typedef enum {
  631. EFUSE_DCM_OFF = DCM_OFF,
  632. EFUSE_DCM_ON = DCM_ON,
  633. } ENUM_EFUSE_DCM;
  634. int dcm_efuse(ENUM_EFUSE_DCM on)
  635. {
  636. if (on)
  637. reg_write(EFUSE_REG_DCM_ON, aor(reg_read(EFUSE_REG_DCM_ON), ~(1 << 0), (1 << 0)));
  638. else
  639. reg_write(EFUSE_REG_DCM_ON, aor(reg_read(EFUSE_REG_DCM_ON), ~(1 << 0), (0 << 0)));
  640. return 0;
  641. }
  642. /*****************************************************/
  643. enum {
  644. ARMCORE_DCM = 0,
  645. MCUSYS_DCM,
  646. INFRA_DCM,
  647. PERI_DCM,
  648. EMI_DCM,
  649. DRAMC_DCM,
  650. TOPCKG_DCM,
  651. EFUSE_DCM,
  652. #if defined(CONFIG_ARCH_MT6753)
  653. DDRPHY_DCM,
  654. NR_DCM = 9,
  655. #else /* !CONFIG_ARCH_MT6753 */
  656. NR_DCM = 8,
  657. #endif /* CONFIG_ARCH_MT6753 */
  658. };
  659. enum {
  660. ARMCORE_DCM_TYPE = (1U << 0),
  661. MCUSYS_DCM_TYPE = (1U << 1),
  662. INFRA_DCM_TYPE = (1U << 2),
  663. PERI_DCM_TYPE = (1U << 3),
  664. EMI_DCM_TYPE = (1U << 4),
  665. DRAMC_DCM_TYPE = (1U << 5),
  666. TOPCKG_DCM_TYPE = (1U << 6),
  667. EFUSE_DCM_TYPE = (1U << 7),
  668. #if defined(CONFIG_ARCH_MT6753)
  669. DDRPHY_DCM_TYPE = (1U << 8),
  670. NR_DCM_TYPE = 9,
  671. #else /* !CONFIG_ARCH_MT6753 */
  672. NR_DCM_TYPE = 8,
  673. #endif /* CONFIG_ARCH_MT6753 */
  674. };
  675. /* Do not do infra DCM ON/OFF here due to H/W limitation. Do it on preloader
  676. * instead */
  677. #if defined(CONFIG_ARCH_MT6753)
  678. #define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | INFRA_DCM_TYPE | \
  679. PERI_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE | \
  680. TOPCKG_DCM_TYPE | EFUSE_DCM_TYPE | DDRPHY_DCM_TYPE)
  681. #define INIT_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | /*INFRA_DCM_TYPE |*/ \
  682. PERI_DCM_TYPE | /* EMI_DCM_TYPE | DRAMC_DCM_TYPE |*/ \
  683. TOPCKG_DCM_TYPE | EFUSE_DCM_TYPE /*| DDRPHY_DCM_TYPE */)
  684. #else /* !CONFIG_ARCH_MT6753 */
  685. #define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | INFRA_DCM_TYPE | \
  686. PERI_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE | \
  687. TOPCKG_DCM_TYPE | EFUSE_DCM_TYPE)
  688. #define INIT_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE | /*INFRA_DCM_TYPE |*/ \
  689. PERI_DCM_TYPE | /* EMI_DCM_TYPE | DRAMC_DCM_TYPE |*/ \
  690. TOPCKG_DCM_TYPE | EFUSE_DCM_TYPE)
  691. #endif /* CONFIG_ARCH_MT6753 */
  692. typedef struct _dcm {
  693. int current_state;
  694. int saved_state;
  695. int disable_refcnt;
  696. int default_state;
  697. DCM_FUNC func;
  698. int typeid;
  699. char *name;
  700. } DCM;
  701. static DCM dcm_array[NR_DCM_TYPE] = {
  702. {
  703. .typeid = ARMCORE_DCM_TYPE,
  704. .name = "ARMCORE_DCM",
  705. .func = (DCM_FUNC) dcm_armcore,
  706. .current_state = ARMCORE_DCM_MODE1,
  707. .default_state = ARMCORE_DCM_MODE1,
  708. .disable_refcnt = 0,
  709. },
  710. {
  711. .typeid = MCUSYS_DCM_TYPE,
  712. .name = "MCUSYS_DCM",
  713. .func = (DCM_FUNC) dcm_mcusys,
  714. .current_state = MCUSYS_DCM_ON,
  715. .default_state = MCUSYS_DCM_ON,
  716. .disable_refcnt = 0,
  717. },
  718. {
  719. .typeid = INFRA_DCM_TYPE,
  720. .name = "INFRA_DCM",
  721. .func = (DCM_FUNC) dcm_infra,
  722. .current_state = INFRA_DCM_ON,
  723. .default_state = INFRA_DCM_ON,
  724. .disable_refcnt = 0,
  725. },
  726. {
  727. .typeid = PERI_DCM_TYPE,
  728. .name = "PERI_DCM",
  729. .func = (DCM_FUNC) dcm_peri,
  730. .current_state = PERI_DCM_ON,
  731. .default_state = PERI_DCM_ON,
  732. .disable_refcnt = 0,
  733. },
  734. {
  735. .typeid = EMI_DCM_TYPE,
  736. .name = "EMI_DCM",
  737. .func = (DCM_FUNC) dcm_emi,
  738. .current_state = EMI_DCM_ON,
  739. .default_state = EMI_DCM_ON,
  740. .disable_refcnt = 0,
  741. },
  742. {
  743. .typeid = DRAMC_DCM_TYPE,
  744. .name = "DRAMC_DCM",
  745. .func = (DCM_FUNC) dcm_dramc_ao,
  746. .current_state = DRAMC_AO_DCM_ON,
  747. .default_state = DRAMC_AO_DCM_ON,
  748. .disable_refcnt = 0,
  749. },
  750. {
  751. .typeid = TOPCKG_DCM_TYPE,
  752. .name = "TOPCKG_DCM",
  753. .func = (DCM_FUNC) dcm_topckg,
  754. .current_state = TOPCKG_DCM_ON,
  755. .default_state = TOPCKG_DCM_ON,
  756. .disable_refcnt = 0,
  757. },
  758. {
  759. .typeid = EFUSE_DCM_TYPE,
  760. .name = "EFUSE_DCM",
  761. .func = (DCM_FUNC) dcm_efuse,
  762. .current_state = EFUSE_DCM_ON,
  763. .default_state = EFUSE_DCM_ON,
  764. .disable_refcnt = 0,
  765. },
  766. #if defined(CONFIG_ARCH_MT6753)
  767. {
  768. .typeid = DDRPHY_DCM_TYPE,
  769. .name = "DDRPHY_DCM",
  770. .func = (DCM_FUNC) dcm_ddrphy,
  771. .current_state = DDRPHY_DCM_ON,
  772. .default_state = DDRPHY_DCM_ON,
  773. .disable_refcnt = 0,
  774. },
  775. #endif /* CONFIG_ARCH_MT6753 */
  776. };
  777. /*****************************************
  778. * DCM driver will provide regular APIs :
  779. * 1. dcm_restore(type) to recovery CURRENT_STATE before any power-off reset.
  780. * 2. dcm_set_default(type) to reset as cold-power-on init state.
  781. * 3. dcm_disable(type) to disable all dcm.
  782. * 4. dcm_set_state(type) to set dcm state.
  783. * 5. dcm_dump_state(type) to show CURRENT_STATE.
  784. * 6. /sys/power/dcm_state interface: 'restore', 'disable', 'dump', 'set'. 4 commands.
  785. *
  786. * spsecified APIs for workaround:
  787. * 1. (definitely no workaround now)
  788. *****************************************/
  789. void dcm_set_default(unsigned int type)
  790. {
  791. int i;
  792. DCM *dcm;
  793. dcm_info("[%s]type:0x%08x\n", __func__, type);
  794. mutex_lock(&dcm_lock);
  795. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  796. if (type & dcm->typeid) {
  797. dcm->saved_state = dcm->current_state = dcm->default_state;
  798. dcm->disable_refcnt = 0;
  799. dcm->func(dcm->current_state);
  800. dcm_info("[%16s 0x%08x] current state:%d (%d)\n",
  801. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  802. }
  803. }
  804. mutex_unlock(&dcm_lock);
  805. }
  806. void dcm_set_state(unsigned int type, int state)
  807. {
  808. int i;
  809. DCM *dcm;
  810. dcm_info("[%s]type:0x%08x, set:%d\n", __func__, type, state);
  811. mutex_lock(&dcm_lock);
  812. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  813. if (type & dcm->typeid) {
  814. type &= ~(dcm->typeid);
  815. dcm->saved_state = state;
  816. if (dcm->disable_refcnt == 0) {
  817. dcm->current_state = state;
  818. dcm->func(dcm->current_state);
  819. }
  820. dcm_info("[%16s 0x%08x] current state:%d (%d)\n",
  821. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  822. }
  823. }
  824. mutex_unlock(&dcm_lock);
  825. }
  826. void dcm_disable(unsigned int type)
  827. {
  828. int i;
  829. DCM *dcm;
  830. dcm_info("[%s]type:0x%08x\n", __func__, type);
  831. mutex_lock(&dcm_lock);
  832. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  833. if (type & dcm->typeid) {
  834. type &= ~(dcm->typeid);
  835. dcm->current_state = DCM_OFF;
  836. dcm->disable_refcnt++;
  837. dcm->func(dcm->current_state);
  838. dcm_info("[%16s 0x%08x] current state:%d (%d)\n",
  839. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  840. }
  841. }
  842. mutex_unlock(&dcm_lock);
  843. }
  844. void dcm_restore(unsigned int type)
  845. {
  846. int i;
  847. DCM *dcm;
  848. dcm_info("[%s]type:0x%08x\n", __func__, type);
  849. mutex_lock(&dcm_lock);
  850. for (i = 0, dcm = &dcm_array[0]; type && (i < NR_DCM_TYPE); i++, dcm++) {
  851. if (type & dcm->typeid) {
  852. type &= ~(dcm->typeid);
  853. if (dcm->disable_refcnt > 0)
  854. dcm->disable_refcnt--;
  855. if (dcm->disable_refcnt == 0) {
  856. dcm->current_state = dcm->saved_state;
  857. dcm->func(dcm->current_state);
  858. }
  859. dcm_info("[%16s 0x%08x] current state:%d (%d)\n",
  860. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  861. }
  862. }
  863. mutex_unlock(&dcm_lock);
  864. }
  865. void dcm_dump_state(int type)
  866. {
  867. int i;
  868. DCM *dcm;
  869. dcm_info("\n******** dcm dump state *********\n");
  870. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++) {
  871. if (type & dcm->typeid) {
  872. dcm_info("[%-16s 0x%08x] current state:%d (%d)\n",
  873. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  874. }
  875. }
  876. }
  877. void dcm_dump_regs(void)
  878. {
  879. dcm_info("\n******** dcm dump register *********\n");
  880. REG_DUMP(APMIXED_PLL_CON2);
  881. REG_DUMP(MCUCFG_ACLKEN_DIV);
  882. REG_DUMP(MCUCFG_L2C_SRAM_CTRL);
  883. REG_DUMP(MCUCFG_CCI_CLK_CTRL);
  884. REG_DUMP(MCUCFG_BUS_FABRIC_DCM_CTRL);
  885. REG_DUMP(TOP_CKMUXSEL);
  886. REG_DUMP(TOP_CKDIV1);
  887. REG_DUMP(INFRA_TOPCKGEN_DCMCTL);
  888. REG_DUMP(INFRA_TOPCKGEN_DCMDBC);
  889. REG_DUMP(INFRA_GLOBALCON_DCMCTL);
  890. REG_DUMP(INFRA_GLOBALCON_DCMDBC);
  891. REG_DUMP(INFRA_GLOBALCON_DCMFSEL);
  892. REG_DUMP(TOPCKG_DCM_CFG);
  893. REG_DUMP(PERI_GLOBALCON_DCMCTL);
  894. REG_DUMP(PERI_GLOBALCON_DCMDBC);
  895. REG_DUMP(PERI_GLOBALCON_DCMFSEL);
  896. REG_DUMP(DRAMC_PD_CTRL);
  897. REG_DUMP(DRAMC_CLKCTRL);
  898. REG_DUMP(DRAMC_PERFCTL0);
  899. REG_DUMP(DRAMC_GDDR3CTL1);
  900. REG_DUMP(DDRPHY_MEMPLL_DIVIDER);
  901. REG_DUMP(EMI_CONM);
  902. REG_DUMP(EFUSE_REG_DCM_ON);
  903. }
  904. #if defined(CONFIG_PM)
  905. static ssize_t dcm_state_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  906. {
  907. int len = 0;
  908. char *p = buf;
  909. int i;
  910. DCM *dcm;
  911. /* dcm_dump_state(ALL_DCM_TYPE); */
  912. p += sprintf(p, "\n******** dcm dump state *********\n");
  913. for (i = 0, dcm = &dcm_array[0]; i < NR_DCM_TYPE; i++, dcm++)
  914. p += sprintf(p, "[%-16s 0x%08x] current state:%d (%d)\n",
  915. dcm->name, dcm->typeid, dcm->current_state, dcm->disable_refcnt);
  916. p += sprintf(p, "\n********** dcm_state help *********\n");
  917. p += sprintf(p, "set: echo set [mask] [mode] > /sys/power/dcm_state\n");
  918. p += sprintf(p, "disable: echo disable [mask] > /sys/power/dcm_state\n");
  919. p += sprintf(p, "restore: echo restore [mask] > /sys/power/dcm_state\n");
  920. p += sprintf(p, "dump: echo dump [mask] > /sys/power/dcm_state\n");
  921. p += sprintf(p, "***** [mask] is hexl bit mask of dcm;\n");
  922. p += sprintf(p, "***** [mode] is type of DCM to set and retained\n");
  923. len = p - buf;
  924. return len;
  925. }
  926. static ssize_t dcm_state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
  927. size_t n)
  928. {
  929. char cmd[16];
  930. unsigned int mask;
  931. int ret, mode;
  932. if (sscanf(buf, "%15s %x", cmd, &mask) == 2) {
  933. mask &= ALL_DCM_TYPE;
  934. if (!strcmp(cmd, "restore")) {
  935. /* dcm_dump_regs(); */
  936. dcm_restore(mask);
  937. /* dcm_dump_regs(); */
  938. } else if (!strcmp(cmd, "disable")) {
  939. /* dcm_dump_regs(); */
  940. dcm_disable(mask);
  941. /* dcm_dump_regs(); */
  942. } else if (!strcmp(cmd, "dump")) {
  943. dcm_dump_state(mask);
  944. dcm_dump_regs();
  945. } else if (!strcmp(cmd, "set")) {
  946. if (sscanf(buf, "%15s %x %d", cmd, &mask, &mode) == 3) {
  947. mask &= ALL_DCM_TYPE;
  948. dcm_set_state(mask, mode);
  949. }
  950. } else {
  951. dcm_info("SORRY, do not support your command: %s\n", cmd);
  952. }
  953. ret = n;
  954. } else {
  955. dcm_info("SORRY, do not support your command.\n");
  956. ret = -EINVAL;
  957. }
  958. return ret;
  959. }
  960. static struct kobj_attribute dcm_state_attr = {
  961. .attr = {
  962. .name = "dcm_state",
  963. .mode = 0644,
  964. },
  965. .show = dcm_state_show,
  966. .store = dcm_state_store,
  967. };
  968. #endif /* #if defined (CONFIG_PM) */
  969. #if defined(CONFIG_OF)
  970. static int mt_dcm_dts_map(void)
  971. {
  972. struct device_node *node;
  973. struct resource r;
  974. /* topckgen */
  975. node = of_find_compatible_node(NULL, NULL, TOPCKGEN_NODE);
  976. if (!node) {
  977. dcm_info("error: cannot find node " TOPCKGEN_NODE);
  978. BUG();
  979. }
  980. topckgen_base = (unsigned long)of_iomap(node, 0);
  981. if (!topckgen_base) {
  982. dcm_info("error: cannot iomap " TOPCKGEN_NODE);
  983. BUG();
  984. }
  985. /* mcucfg */
  986. node = of_find_compatible_node(NULL, NULL, MCUCFG_NODE);
  987. if (!node) {
  988. dcm_info("error: cannot find node " MCUCFG_NODE);
  989. BUG();
  990. }
  991. if (of_address_to_resource(node, 0, &r)) {
  992. dcm_info("error: cannot get phys addr" MCUCFG_NODE);
  993. BUG();
  994. }
  995. mcucfg_phys_base = r.start;
  996. mcucfg_base = (unsigned long)of_iomap(node, 0);
  997. if (!mcucfg_base) {
  998. dcm_info("error: cannot iomap " MCUCFG_NODE);
  999. BUG();
  1000. }
  1001. /* dramc */
  1002. dramc_ao_base = (unsigned long)mt_dramc_base_get();
  1003. if (!dramc_ao_base) {
  1004. dcm_info("error: cannot get dramc_ao_base from dram api");
  1005. BUG();
  1006. }
  1007. /* emi_reg */
  1008. node = of_find_compatible_node(NULL, NULL, EMI_REG_NODE);
  1009. if (!node) {
  1010. dcm_info("error: cannot find node " EMI_REG_NODE);
  1011. BUG();
  1012. }
  1013. emi_reg_base = (unsigned long)of_iomap(node, 0);
  1014. if (!emi_reg_base) {
  1015. dcm_info("error: cannot iomap " EMI_REG_NODE);
  1016. BUG();
  1017. }
  1018. /* ddrphy */
  1019. ddrphy_base = (unsigned long)mt_ddrphy_base_get();
  1020. if (!ddrphy_base) {
  1021. dcm_info("error: cannot get ddrphy_base from dram api");
  1022. BUG();
  1023. }
  1024. /* infracfg_ao */
  1025. node = of_find_compatible_node(NULL, NULL, INFRACFG_AO_NODE);
  1026. if (!node) {
  1027. dcm_info("error: cannot find node " INFRACFG_AO_NODE);
  1028. BUG();
  1029. }
  1030. infracfg_ao_base = (unsigned long)of_iomap(node, 0);
  1031. if (!infracfg_ao_base) {
  1032. dcm_info("error: cannot iomap " INFRACFG_AO_NODE);
  1033. BUG();
  1034. }
  1035. /* pericfg */
  1036. node = of_find_compatible_node(NULL, NULL, PERICFG_NODE);
  1037. if (!node) {
  1038. dcm_info("error: cannot find node " PERICFG_NODE);
  1039. BUG();
  1040. }
  1041. pericfg_base = (unsigned long)of_iomap(node, 0);
  1042. if (!pericfg_base) {
  1043. dcm_info("error: cannot iomap " PERICFG_NODE);
  1044. BUG();
  1045. }
  1046. /* efuse */
  1047. node = of_find_compatible_node(NULL, NULL, EFUSE_NODE);
  1048. if (!node) {
  1049. dcm_info("error: cannot find node " EFUSE_NODE);
  1050. BUG();
  1051. }
  1052. efuse_base = (unsigned long)of_iomap(node, 0);
  1053. if (!efuse_base) {
  1054. dcm_info("error: cannot iomap " EFUSE_NODE);
  1055. BUG();
  1056. }
  1057. /* apmixed */
  1058. node = of_find_compatible_node(NULL, NULL, APMIXED_NODE);
  1059. if (!node) {
  1060. dcm_info("error: cannot find node " APMIXED_NODE);
  1061. BUG();
  1062. }
  1063. apmixed_base = (unsigned long)of_iomap(node, 0);
  1064. if (!apmixed_base) {
  1065. dcm_info("error: cannot iomap " APMIXED_NODE);
  1066. BUG();
  1067. }
  1068. return 0;
  1069. }
  1070. #else
  1071. static int mt_dcm_dts_map(void)
  1072. {
  1073. return 0;
  1074. }
  1075. #endif
  1076. int mt_dcm_init(void)
  1077. {
  1078. if (dcm_initiated)
  1079. return 0;
  1080. /** workaround **/
  1081. dcm_initiated = 1;
  1082. mt_dcm_dts_map();
  1083. #if !defined(DCM_DEFAULT_ALL_OFF)
  1084. /** enable all dcm **/
  1085. dcm_set_default(INIT_DCM_TYPE);
  1086. /* default TOPCKG DCM OFF for I2C performance but keep others setting as DCM ON */
  1087. mt_dcm_topckg_disable();
  1088. #else /* #if !defined (DCM_DEFAULT_ALL_OFF) */
  1089. dcm_set_state(ALL_DCM_TYPE, DCM_OFF);
  1090. #endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */
  1091. dcm_dump_regs();
  1092. #if defined(CONFIG_PM)
  1093. {
  1094. int err = 0;
  1095. err = sysfs_create_file(power_kobj, &dcm_state_attr.attr);
  1096. if (err)
  1097. dcm_err("[%s]: fail to create sysfs\n", __func__);
  1098. }
  1099. #if defined(DCM_DEBUG_MON)
  1100. {
  1101. int err = 0;
  1102. err = sysfs_create_file(power_kobj, &dcm_debug_mon_attr.attr);
  1103. if (err)
  1104. dcm_err("[%s]: fail to create sysfs\n", __func__);
  1105. }
  1106. #endif /* #if defined (DCM_DEBUG_MON) */
  1107. #endif /* #if defined (CONFIG_PM) */
  1108. return 0;
  1109. }
  1110. late_initcall(mt_dcm_init);
  1111. /**** public APIs *****/
  1112. void mt_dcm_disable(void)
  1113. {
  1114. mt_dcm_init();
  1115. dcm_disable(ALL_DCM_TYPE);
  1116. }
  1117. EXPORT_SYMBOL(mt_dcm_disable);
  1118. void mt_dcm_restore(void)
  1119. {
  1120. mt_dcm_init();
  1121. dcm_restore(ALL_DCM_TYPE);
  1122. }
  1123. EXPORT_SYMBOL(mt_dcm_restore);
  1124. /* mt_dcm_topckg_disable/enable is used for slow idle */
  1125. void mt_dcm_topckg_disable(void)
  1126. {
  1127. #if !defined(DCM_DEFAULT_ALL_OFF)
  1128. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  1129. ~TOPCKG_DCM_CFG_QMASK, TOPCKG_DCM_CFG_QOFF));
  1130. #endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */
  1131. }
  1132. EXPORT_SYMBOL(mt_dcm_topckg_disable);
  1133. /* mt_dcm_topckg_disable/enable is used for slow idle */
  1134. void mt_dcm_topckg_enable(void)
  1135. {
  1136. #if !defined(DCM_DEFAULT_ALL_OFF)
  1137. if (dcm_array[TOPCKG_DCM].current_state != DCM_OFF) {
  1138. reg_write(TOPCKG_DCM_CFG, aor(reg_read(TOPCKG_DCM_CFG),
  1139. ~TOPCKG_DCM_CFG_QMASK, TOPCKG_DCM_CFG_QON));
  1140. }
  1141. #endif /* #if !defined (DCM_DEFAULT_ALL_OFF) */
  1142. }
  1143. EXPORT_SYMBOL(mt_dcm_topckg_enable);
  1144. void mt_dcm_topck_off(void)
  1145. {
  1146. mt_dcm_init();
  1147. dcm_set_state(TOPCKG_DCM_TYPE, DCM_OFF);
  1148. }
  1149. EXPORT_SYMBOL(mt_dcm_topck_off);
  1150. void mt_dcm_topck_on(void)
  1151. {
  1152. mt_dcm_init();
  1153. dcm_set_state(TOPCKG_DCM_TYPE, DCM_ON);
  1154. }
  1155. EXPORT_SYMBOL(mt_dcm_topck_on);
  1156. void mt_dcm_peri_off(void)
  1157. {
  1158. mt_dcm_init();
  1159. dcm_set_state(PERI_DCM_TYPE, DCM_OFF);
  1160. }
  1161. EXPORT_SYMBOL(mt_dcm_peri_off);
  1162. void mt_dcm_peri_on(void)
  1163. {
  1164. mt_dcm_init();
  1165. dcm_set_state(PERI_DCM_TYPE, DCM_ON);
  1166. }
  1167. EXPORT_SYMBOL(mt_dcm_peri_on);