ci_smumgr.c 97 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981
  1. /*
  2. * Copyright 2017 Advanced Micro Devices, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. */
  23. #include <linux/module.h>
  24. #include <linux/slab.h>
  25. #include <linux/fb.h>
  26. #include "linux/delay.h"
  27. #include <linux/types.h>
  28. #include "smumgr.h"
  29. #include "pp_debug.h"
  30. #include "ci_smumgr.h"
  31. #include "ppsmc.h"
  32. #include "smu7_hwmgr.h"
  33. #include "hardwaremanager.h"
  34. #include "ppatomctrl.h"
  35. #include "cgs_common.h"
  36. #include "atombios.h"
  37. #include "pppcielanes.h"
  38. #include "smu/smu_7_0_1_d.h"
  39. #include "smu/smu_7_0_1_sh_mask.h"
  40. #include "dce/dce_8_0_d.h"
  41. #include "dce/dce_8_0_sh_mask.h"
  42. #include "bif/bif_4_1_d.h"
  43. #include "bif/bif_4_1_sh_mask.h"
  44. #include "gca/gfx_7_2_d.h"
  45. #include "gca/gfx_7_2_sh_mask.h"
  46. #include "gmc/gmc_7_1_d.h"
  47. #include "gmc/gmc_7_1_sh_mask.h"
  48. #include "processpptables.h"
  49. #define MC_CG_ARB_FREQ_F0 0x0a
  50. #define MC_CG_ARB_FREQ_F1 0x0b
  51. #define MC_CG_ARB_FREQ_F2 0x0c
  52. #define MC_CG_ARB_FREQ_F3 0x0d
  53. #define SMC_RAM_END 0x40000
  54. #define CISLAND_MINIMUM_ENGINE_CLOCK 800
  55. #define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5
  56. static const struct ci_pt_defaults defaults_hawaii_xt = {
  57. 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000,
  58. { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 },
  59. { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 }
  60. };
  61. static const struct ci_pt_defaults defaults_hawaii_pro = {
  62. 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062,
  63. { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 },
  64. { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 }
  65. };
  66. static const struct ci_pt_defaults defaults_bonaire_xt = {
  67. 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
  68. { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 },
  69. { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
  70. };
  71. static const struct ci_pt_defaults defaults_saturn_xt = {
  72. 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000,
  73. { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D },
  74. { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 }
  75. };
  76. static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr,
  77. uint32_t smc_addr, uint32_t limit)
  78. {
  79. if ((0 != (3 & smc_addr))
  80. || ((smc_addr + 3) >= limit)) {
  81. pr_err("smc_addr invalid \n");
  82. return -EINVAL;
  83. }
  84. cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr);
  85. PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
  86. return 0;
  87. }
  88. static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address,
  89. const uint8_t *src, uint32_t byte_count, uint32_t limit)
  90. {
  91. int result;
  92. uint32_t data = 0;
  93. uint32_t original_data;
  94. uint32_t addr = 0;
  95. uint32_t extra_shift;
  96. if ((3 & smc_start_address)
  97. || ((smc_start_address + byte_count) >= limit)) {
  98. pr_err("smc_start_address invalid \n");
  99. return -EINVAL;
  100. }
  101. addr = smc_start_address;
  102. while (byte_count >= 4) {
  103. /* Bytes are written into the SMC address space with the MSB first. */
  104. data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
  105. result = ci_set_smc_sram_address(hwmgr, addr, limit);
  106. if (0 != result)
  107. return result;
  108. cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data);
  109. src += 4;
  110. byte_count -= 4;
  111. addr += 4;
  112. }
  113. if (0 != byte_count) {
  114. data = 0;
  115. result = ci_set_smc_sram_address(hwmgr, addr, limit);
  116. if (0 != result)
  117. return result;
  118. original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0);
  119. extra_shift = 8 * (4 - byte_count);
  120. while (byte_count > 0) {
  121. /* Bytes are written into the SMC addres space with the MSB first. */
  122. data = (0x100 * data) + *src++;
  123. byte_count--;
  124. }
  125. data <<= extra_shift;
  126. data |= (original_data & ~((~0UL) << extra_shift));
  127. result = ci_set_smc_sram_address(hwmgr, addr, limit);
  128. if (0 != result)
  129. return result;
  130. cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data);
  131. }
  132. return 0;
  133. }
  134. static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr)
  135. {
  136. static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 };
  137. ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1);
  138. return 0;
  139. }
  140. bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr)
  141. {
  142. return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
  143. CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
  144. && (0x20100 <= cgs_read_ind_register(hwmgr->device,
  145. CGS_IND_REG__SMC, ixSMC_PC_C)));
  146. }
  147. static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr,
  148. uint32_t *value, uint32_t limit)
  149. {
  150. int result;
  151. result = ci_set_smc_sram_address(hwmgr, smc_addr, limit);
  152. if (result)
  153. return result;
  154. *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0);
  155. return 0;
  156. }
  157. static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
  158. {
  159. int ret;
  160. cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0);
  161. cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg);
  162. PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
  163. ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP);
  164. if (ret != 1)
  165. pr_info("\n failed to send message %x ret is %d\n", msg, ret);
  166. return 0;
  167. }
  168. static int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
  169. uint16_t msg, uint32_t parameter)
  170. {
  171. cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter);
  172. return ci_send_msg_to_smc(hwmgr, msg);
  173. }
  174. static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
  175. {
  176. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  177. struct amdgpu_device *adev = hwmgr->adev;
  178. uint32_t dev_id;
  179. dev_id = adev->pdev->device;
  180. switch (dev_id) {
  181. case 0x67BA:
  182. case 0x67B1:
  183. smu_data->power_tune_defaults = &defaults_hawaii_pro;
  184. break;
  185. case 0x67B8:
  186. case 0x66B0:
  187. smu_data->power_tune_defaults = &defaults_hawaii_xt;
  188. break;
  189. case 0x6640:
  190. case 0x6641:
  191. case 0x6646:
  192. case 0x6647:
  193. smu_data->power_tune_defaults = &defaults_saturn_xt;
  194. break;
  195. case 0x6649:
  196. case 0x6650:
  197. case 0x6651:
  198. case 0x6658:
  199. case 0x665C:
  200. case 0x665D:
  201. case 0x67A0:
  202. case 0x67A1:
  203. case 0x67A2:
  204. case 0x67A8:
  205. case 0x67A9:
  206. case 0x67AA:
  207. case 0x67B9:
  208. case 0x67BE:
  209. default:
  210. smu_data->power_tune_defaults = &defaults_bonaire_xt;
  211. break;
  212. }
  213. }
  214. static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
  215. struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table,
  216. uint32_t clock, uint32_t *vol)
  217. {
  218. uint32_t i = 0;
  219. if (allowed_clock_voltage_table->count == 0)
  220. return -EINVAL;
  221. for (i = 0; i < allowed_clock_voltage_table->count; i++) {
  222. if (allowed_clock_voltage_table->entries[i].clk >= clock) {
  223. *vol = allowed_clock_voltage_table->entries[i].v;
  224. return 0;
  225. }
  226. }
  227. *vol = allowed_clock_voltage_table->entries[i - 1].v;
  228. return 0;
  229. }
  230. static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr,
  231. uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk)
  232. {
  233. const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  234. struct pp_atomctrl_clock_dividers_vi dividers;
  235. uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
  236. uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
  237. uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
  238. uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
  239. uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
  240. uint32_t ref_clock;
  241. uint32_t ref_divider;
  242. uint32_t fbdiv;
  243. int result;
  244. /* get the engine clock dividers for this clock value */
  245. result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, &dividers);
  246. PP_ASSERT_WITH_CODE(result == 0,
  247. "Error retrieving Engine Clock dividers from VBIOS.",
  248. return result);
  249. /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */
  250. ref_clock = atomctrl_get_reference_clock(hwmgr);
  251. ref_divider = 1 + dividers.uc_pll_ref_div;
  252. /* low 14 bits is fraction and high 12 bits is divider */
  253. fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
  254. /* SPLL_FUNC_CNTL setup */
  255. spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
  256. SPLL_REF_DIV, dividers.uc_pll_ref_div);
  257. spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
  258. SPLL_PDIV_A, dividers.uc_pll_post_div);
  259. /* SPLL_FUNC_CNTL_3 setup*/
  260. spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
  261. SPLL_FB_DIV, fbdiv);
  262. /* set to use fractional accumulation*/
  263. spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
  264. SPLL_DITHEN, 1);
  265. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  266. PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
  267. struct pp_atomctrl_internal_ss_info ss_info;
  268. uint32_t vco_freq = clock * dividers.uc_pll_post_div;
  269. if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr,
  270. vco_freq, &ss_info)) {
  271. uint32_t clk_s = ref_clock * 5 /
  272. (ref_divider * ss_info.speed_spectrum_rate);
  273. uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage *
  274. fbdiv / (clk_s * 10000);
  275. cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
  276. CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s);
  277. cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
  278. CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
  279. cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2,
  280. CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v);
  281. }
  282. }
  283. sclk->SclkFrequency = clock;
  284. sclk->CgSpllFuncCntl3 = spll_func_cntl_3;
  285. sclk->CgSpllFuncCntl4 = spll_func_cntl_4;
  286. sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum;
  287. sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2;
  288. sclk->SclkDid = (uint8_t)dividers.pll_post_divider;
  289. return 0;
  290. }
  291. static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr,
  292. const struct phm_phase_shedding_limits_table *pl,
  293. uint32_t sclk, uint32_t *p_shed)
  294. {
  295. unsigned int i;
  296. /* use the minimum phase shedding */
  297. *p_shed = 1;
  298. for (i = 0; i < pl->count; i++) {
  299. if (sclk < pl->entries[i].Sclk) {
  300. *p_shed = i;
  301. break;
  302. }
  303. }
  304. }
  305. static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock,
  306. uint32_t clock_insr)
  307. {
  308. uint8_t i;
  309. uint32_t temp;
  310. uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK);
  311. if (clock < min) {
  312. pr_info("Engine clock can't satisfy stutter requirement!\n");
  313. return 0;
  314. }
  315. for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
  316. temp = clock >> i;
  317. if (temp >= min || i == 0)
  318. break;
  319. }
  320. return i;
  321. }
  322. static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
  323. uint32_t clock, struct SMU7_Discrete_GraphicsLevel *level)
  324. {
  325. int result;
  326. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  327. result = ci_calculate_sclk_params(hwmgr, clock, level);
  328. /* populate graphics levels */
  329. result = ci_get_dependency_volt_by_clk(hwmgr,
  330. hwmgr->dyn_state.vddc_dependency_on_sclk, clock,
  331. (uint32_t *)(&level->MinVddc));
  332. if (result) {
  333. pr_err("vdd_dep_on_sclk table is NULL\n");
  334. return result;
  335. }
  336. level->SclkFrequency = clock;
  337. level->MinVddcPhases = 1;
  338. if (data->vddc_phase_shed_control)
  339. ci_populate_phase_value_based_on_sclk(hwmgr,
  340. hwmgr->dyn_state.vddc_phase_shed_limits_table,
  341. clock,
  342. &level->MinVddcPhases);
  343. level->ActivityLevel = data->current_profile_setting.sclk_activity;
  344. level->CcPwrDynRm = 0;
  345. level->CcPwrDynRm1 = 0;
  346. level->EnabledForActivity = 0;
  347. /* this level can be used for throttling.*/
  348. level->EnabledForThrottle = 1;
  349. level->UpH = data->current_profile_setting.sclk_up_hyst;
  350. level->DownH = data->current_profile_setting.sclk_down_hyst;
  351. level->VoltageDownH = 0;
  352. level->PowerThrottle = 0;
  353. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  354. PHM_PlatformCaps_SclkDeepSleep))
  355. level->DeepSleepDivId =
  356. ci_get_sleep_divider_id_from_clock(clock,
  357. CISLAND_MINIMUM_ENGINE_CLOCK);
  358. /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
  359. level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
  360. if (0 == result) {
  361. level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE);
  362. CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases);
  363. CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency);
  364. CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
  365. CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3);
  366. CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4);
  367. CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum);
  368. CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2);
  369. CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
  370. CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
  371. }
  372. return result;
  373. }
  374. static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
  375. {
  376. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  377. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  378. struct smu7_dpm_table *dpm_table = &data->dpm_table;
  379. int result = 0;
  380. uint32_t array = smu_data->dpm_table_start +
  381. offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
  382. uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) *
  383. SMU7_MAX_LEVELS_GRAPHICS;
  384. struct SMU7_Discrete_GraphicsLevel *levels =
  385. smu_data->smc_state_table.GraphicsLevel;
  386. uint32_t i;
  387. for (i = 0; i < dpm_table->sclk_table.count; i++) {
  388. result = ci_populate_single_graphic_level(hwmgr,
  389. dpm_table->sclk_table.dpm_levels[i].value,
  390. &levels[i]);
  391. if (result)
  392. return result;
  393. if (i > 1)
  394. smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
  395. if (i == (dpm_table->sclk_table.count - 1))
  396. smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark =
  397. PPSMC_DISPLAY_WATERMARK_HIGH;
  398. }
  399. smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
  400. smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count;
  401. data->dpm_level_enable_mask.sclk_dpm_enable_mask =
  402. phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
  403. result = ci_copy_bytes_to_smc(hwmgr, array,
  404. (u8 *)levels, array_size,
  405. SMC_RAM_END);
  406. return result;
  407. }
  408. static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr)
  409. {
  410. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  411. const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
  412. smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
  413. smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc;
  414. smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
  415. smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
  416. return 0;
  417. }
  418. static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr)
  419. {
  420. uint16_t tdc_limit;
  421. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  422. const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
  423. tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256);
  424. smu_data->power_tune_table.TDC_VDDC_PkgLimit =
  425. CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
  426. smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
  427. defaults->tdc_vddc_throttle_release_limit_perc;
  428. smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
  429. return 0;
  430. }
  431. static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
  432. {
  433. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  434. const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
  435. uint32_t temp;
  436. if (ci_read_smc_sram_dword(hwmgr,
  437. fuse_table_offset +
  438. offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl),
  439. (uint32_t *)&temp, SMC_RAM_END))
  440. PP_ASSERT_WITH_CODE(false,
  441. "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
  442. return -EINVAL);
  443. else
  444. smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
  445. return 0;
  446. }
  447. static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
  448. {
  449. uint16_t tmp;
  450. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  451. if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15))
  452. || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity)
  453. tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity;
  454. else
  455. tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity;
  456. smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp);
  457. return 0;
  458. }
  459. static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr)
  460. {
  461. int i;
  462. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  463. uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd;
  464. uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd;
  465. uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2;
  466. PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table,
  467. "The CAC Leakage table does not exist!", return -EINVAL);
  468. PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8,
  469. "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL);
  470. PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count,
  471. "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL);
  472. for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) {
  473. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) {
  474. lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1);
  475. hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2);
  476. hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3);
  477. } else {
  478. lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc);
  479. hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage);
  480. }
  481. }
  482. return 0;
  483. }
  484. static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr)
  485. {
  486. int i;
  487. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  488. uint8_t *vid = smu_data->power_tune_table.VddCVid;
  489. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  490. PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8,
  491. "There should never be more than 8 entries for VddcVid!!!",
  492. return -EINVAL);
  493. for (i = 0; i < (int)data->vddc_voltage_table.count; i++)
  494. vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value);
  495. return 0;
  496. }
  497. static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr)
  498. {
  499. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  500. u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd;
  501. u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd;
  502. int i, min, max;
  503. min = max = hi_vid[0];
  504. for (i = 0; i < 8; i++) {
  505. if (0 != hi_vid[i]) {
  506. if (min > hi_vid[i])
  507. min = hi_vid[i];
  508. if (max < hi_vid[i])
  509. max = hi_vid[i];
  510. }
  511. if (0 != lo_vid[i]) {
  512. if (min > lo_vid[i])
  513. min = lo_vid[i];
  514. if (max < lo_vid[i])
  515. max = lo_vid[i];
  516. }
  517. }
  518. if ((min == 0) || (max == 0))
  519. return -EINVAL;
  520. smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max;
  521. smu_data->power_tune_table.GnbLPMLMinVid = (u8)min;
  522. return 0;
  523. }
  524. static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
  525. {
  526. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  527. uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
  528. uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
  529. struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table;
  530. HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
  531. LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
  532. smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
  533. CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
  534. smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
  535. CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
  536. return 0;
  537. }
  538. static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr)
  539. {
  540. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  541. uint32_t pm_fuse_table_offset;
  542. int ret = 0;
  543. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  544. PHM_PlatformCaps_PowerContainment)) {
  545. if (ci_read_smc_sram_dword(hwmgr,
  546. SMU7_FIRMWARE_HEADER_LOCATION +
  547. offsetof(SMU7_Firmware_Header, PmFuseTable),
  548. &pm_fuse_table_offset, SMC_RAM_END)) {
  549. pr_err("Attempt to get pm_fuse_table_offset Failed!\n");
  550. return -EINVAL;
  551. }
  552. /* DW0 - DW3 */
  553. ret = ci_populate_bapm_vddc_vid_sidd(hwmgr);
  554. /* DW4 - DW5 */
  555. ret |= ci_populate_vddc_vid(hwmgr);
  556. /* DW6 */
  557. ret |= ci_populate_svi_load_line(hwmgr);
  558. /* DW7 */
  559. ret |= ci_populate_tdc_limit(hwmgr);
  560. /* DW8 */
  561. ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset);
  562. ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset);
  563. ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr);
  564. ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr);
  565. if (ret)
  566. return ret;
  567. ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset,
  568. (uint8_t *)&smu_data->power_tune_table,
  569. sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END);
  570. }
  571. return ret;
  572. }
  573. static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
  574. {
  575. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  576. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  577. const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults;
  578. SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table);
  579. struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table;
  580. struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table;
  581. const uint16_t *def1, *def2;
  582. int i, j, k;
  583. dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256));
  584. dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
  585. dpm_table->DTETjOffset = 0;
  586. dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES);
  587. dpm_table->GpuTjHyst = 8;
  588. dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
  589. if (ppm) {
  590. dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000;
  591. dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256;
  592. } else {
  593. dpm_table->PPM_PkgPwrLimit = 0;
  594. dpm_table->PPM_TemperatureLimit = 0;
  595. }
  596. CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit);
  597. CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit);
  598. dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient);
  599. def1 = defaults->bapmti_r;
  600. def2 = defaults->bapmti_rc;
  601. for (i = 0; i < SMU7_DTE_ITERATIONS; i++) {
  602. for (j = 0; j < SMU7_DTE_SOURCES; j++) {
  603. for (k = 0; k < SMU7_DTE_SINKS; k++) {
  604. dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1);
  605. dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2);
  606. def1++;
  607. def2++;
  608. }
  609. }
  610. }
  611. return 0;
  612. }
  613. static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr,
  614. pp_atomctrl_voltage_table_entry *tab, uint16_t *hi,
  615. uint16_t *lo)
  616. {
  617. uint16_t v_index;
  618. bool vol_found = false;
  619. *hi = tab->value * VOLTAGE_SCALE;
  620. *lo = tab->value * VOLTAGE_SCALE;
  621. PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk,
  622. "The SCLK/VDDC Dependency Table does not exist.\n",
  623. return -EINVAL);
  624. if (NULL == hwmgr->dyn_state.cac_leakage_table) {
  625. pr_warn("CAC Leakage Table does not exist, using vddc.\n");
  626. return 0;
  627. }
  628. for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
  629. if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
  630. vol_found = true;
  631. if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
  632. *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
  633. *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE);
  634. } else {
  635. pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n");
  636. *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
  637. *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
  638. }
  639. break;
  640. }
  641. }
  642. if (!vol_found) {
  643. for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
  644. if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
  645. vol_found = true;
  646. if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
  647. *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
  648. *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE;
  649. } else {
  650. pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table.");
  651. *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
  652. *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
  653. }
  654. break;
  655. }
  656. }
  657. if (!vol_found)
  658. pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n");
  659. }
  660. return 0;
  661. }
  662. static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr,
  663. pp_atomctrl_voltage_table_entry *tab,
  664. SMU7_Discrete_VoltageLevel *smc_voltage_tab)
  665. {
  666. int result;
  667. result = ci_get_std_voltage_value_sidd(hwmgr, tab,
  668. &smc_voltage_tab->StdVoltageHiSidd,
  669. &smc_voltage_tab->StdVoltageLoSidd);
  670. if (result) {
  671. smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE;
  672. smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE;
  673. }
  674. smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE);
  675. CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd);
  676. CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd);
  677. return 0;
  678. }
  679. static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
  680. SMU7_Discrete_DpmTable *table)
  681. {
  682. unsigned int count;
  683. int result;
  684. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  685. table->VddcLevelCount = data->vddc_voltage_table.count;
  686. for (count = 0; count < table->VddcLevelCount; count++) {
  687. result = ci_populate_smc_voltage_table(hwmgr,
  688. &(data->vddc_voltage_table.entries[count]),
  689. &(table->VddcLevel[count]));
  690. PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL);
  691. /* GPIO voltage control */
  692. if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) {
  693. table->VddcLevel[count].Smio = (uint8_t) count;
  694. table->Smio[count] |= data->vddc_voltage_table.entries[count].smio_low;
  695. table->SmioMaskVddcVid |= data->vddc_voltage_table.entries[count].smio_low;
  696. } else {
  697. table->VddcLevel[count].Smio = 0;
  698. }
  699. }
  700. CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
  701. return 0;
  702. }
  703. static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
  704. SMU7_Discrete_DpmTable *table)
  705. {
  706. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  707. uint32_t count;
  708. int result;
  709. table->VddciLevelCount = data->vddci_voltage_table.count;
  710. for (count = 0; count < table->VddciLevelCount; count++) {
  711. result = ci_populate_smc_voltage_table(hwmgr,
  712. &(data->vddci_voltage_table.entries[count]),
  713. &(table->VddciLevel[count]));
  714. PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL);
  715. if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
  716. table->VddciLevel[count].Smio = (uint8_t) count;
  717. table->Smio[count] |= data->vddci_voltage_table.entries[count].smio_low;
  718. table->SmioMaskVddciVid |= data->vddci_voltage_table.entries[count].smio_low;
  719. } else {
  720. table->VddciLevel[count].Smio = 0;
  721. }
  722. }
  723. CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
  724. return 0;
  725. }
  726. static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
  727. SMU7_Discrete_DpmTable *table)
  728. {
  729. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  730. uint32_t count;
  731. int result;
  732. table->MvddLevelCount = data->mvdd_voltage_table.count;
  733. for (count = 0; count < table->MvddLevelCount; count++) {
  734. result = ci_populate_smc_voltage_table(hwmgr,
  735. &(data->mvdd_voltage_table.entries[count]),
  736. &table->MvddLevel[count]);
  737. PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL);
  738. if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
  739. table->MvddLevel[count].Smio = (uint8_t) count;
  740. table->Smio[count] |= data->mvdd_voltage_table.entries[count].smio_low;
  741. table->SmioMaskMvddVid |= data->mvdd_voltage_table.entries[count].smio_low;
  742. } else {
  743. table->MvddLevel[count].Smio = 0;
  744. }
  745. }
  746. CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
  747. return 0;
  748. }
  749. static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
  750. SMU7_Discrete_DpmTable *table)
  751. {
  752. int result;
  753. result = ci_populate_smc_vddc_table(hwmgr, table);
  754. PP_ASSERT_WITH_CODE(0 == result,
  755. "can not populate VDDC voltage table to SMC", return -EINVAL);
  756. result = ci_populate_smc_vdd_ci_table(hwmgr, table);
  757. PP_ASSERT_WITH_CODE(0 == result,
  758. "can not populate VDDCI voltage table to SMC", return -EINVAL);
  759. result = ci_populate_smc_mvdd_table(hwmgr, table);
  760. PP_ASSERT_WITH_CODE(0 == result,
  761. "can not populate MVDD voltage table to SMC", return -EINVAL);
  762. return 0;
  763. }
  764. static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr,
  765. struct SMU7_Discrete_Ulv *state)
  766. {
  767. uint32_t voltage_response_time, ulv_voltage;
  768. int result;
  769. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  770. state->CcPwrDynRm = 0;
  771. state->CcPwrDynRm1 = 0;
  772. result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage);
  773. PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;);
  774. if (ulv_voltage == 0) {
  775. data->ulv_supported = false;
  776. return 0;
  777. }
  778. if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) {
  779. /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
  780. if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
  781. state->VddcOffset = 0;
  782. else
  783. /* used in SMIO Mode. not implemented for now. this is backup only for CI. */
  784. state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage);
  785. } else {
  786. /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
  787. if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
  788. state->VddcOffsetVid = 0;
  789. else /* used in SVI2 Mode */
  790. state->VddcOffsetVid = (uint8_t)(
  791. (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage)
  792. * VOLTAGE_VID_OFFSET_SCALE2
  793. / VOLTAGE_VID_OFFSET_SCALE1);
  794. }
  795. state->VddcPhase = 1;
  796. CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
  797. CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
  798. CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
  799. return 0;
  800. }
  801. static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr,
  802. SMU7_Discrete_Ulv *ulv_level)
  803. {
  804. return ci_populate_ulv_level(hwmgr, ulv_level);
  805. }
  806. static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table)
  807. {
  808. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  809. struct smu7_dpm_table *dpm_table = &data->dpm_table;
  810. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  811. uint32_t i;
  812. /* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/
  813. for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
  814. table->LinkLevel[i].PcieGenSpeed =
  815. (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
  816. table->LinkLevel[i].PcieLaneCount =
  817. (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
  818. table->LinkLevel[i].EnabledForActivity = 1;
  819. table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5);
  820. table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30);
  821. }
  822. smu_data->smc_state_table.LinkLevelCount =
  823. (uint8_t)dpm_table->pcie_speed_table.count;
  824. data->dpm_level_enable_mask.pcie_dpm_enable_mask =
  825. phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
  826. return 0;
  827. }
  828. static int ci_calculate_mclk_params(
  829. struct pp_hwmgr *hwmgr,
  830. uint32_t memory_clock,
  831. SMU7_Discrete_MemoryLevel *mclk,
  832. bool strobe_mode,
  833. bool dllStateOn
  834. )
  835. {
  836. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  837. uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
  838. uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
  839. uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
  840. uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
  841. uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
  842. uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
  843. uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
  844. uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1;
  845. uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2;
  846. pp_atomctrl_memory_clock_param mpll_param;
  847. int result;
  848. result = atomctrl_get_memory_pll_dividers_si(hwmgr,
  849. memory_clock, &mpll_param, strobe_mode);
  850. PP_ASSERT_WITH_CODE(0 == result,
  851. "Error retrieving Memory Clock Parameters from VBIOS.", return result);
  852. mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
  853. mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
  854. MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf);
  855. mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
  856. MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac);
  857. mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
  858. MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode);
  859. mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
  860. MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
  861. if (data->is_memory_gddr5) {
  862. mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
  863. MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel);
  864. mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
  865. MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
  866. }
  867. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  868. PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
  869. pp_atomctrl_internal_ss_info ss_info;
  870. uint32_t freq_nom;
  871. uint32_t tmp;
  872. uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
  873. /* for GDDR5 for all modes and DDR3 */
  874. if (1 == mpll_param.qdr)
  875. freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
  876. else
  877. freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
  878. /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
  879. tmp = (freq_nom / reference_clock);
  880. tmp = tmp * tmp;
  881. if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
  882. uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
  883. uint32_t clkv =
  884. (uint32_t)((((131 * ss_info.speed_spectrum_percentage *
  885. ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
  886. mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
  887. mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
  888. }
  889. }
  890. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  891. MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
  892. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  893. MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
  894. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  895. MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
  896. mclk->MclkFrequency = memory_clock;
  897. mclk->MpllFuncCntl = mpll_func_cntl;
  898. mclk->MpllFuncCntl_1 = mpll_func_cntl_1;
  899. mclk->MpllFuncCntl_2 = mpll_func_cntl_2;
  900. mclk->MpllAdFuncCntl = mpll_ad_func_cntl;
  901. mclk->MpllDqFuncCntl = mpll_dq_func_cntl;
  902. mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl;
  903. mclk->DllCntl = dll_cntl;
  904. mclk->MpllSs1 = mpll_ss1;
  905. mclk->MpllSs2 = mpll_ss2;
  906. return 0;
  907. }
  908. static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock,
  909. bool strobe_mode)
  910. {
  911. uint8_t mc_para_index;
  912. if (strobe_mode) {
  913. if (memory_clock < 12500)
  914. mc_para_index = 0x00;
  915. else if (memory_clock > 47500)
  916. mc_para_index = 0x0f;
  917. else
  918. mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
  919. } else {
  920. if (memory_clock < 65000)
  921. mc_para_index = 0x00;
  922. else if (memory_clock > 135000)
  923. mc_para_index = 0x0f;
  924. else
  925. mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
  926. }
  927. return mc_para_index;
  928. }
  929. static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
  930. {
  931. uint8_t mc_para_index;
  932. if (memory_clock < 10000)
  933. mc_para_index = 0;
  934. else if (memory_clock >= 80000)
  935. mc_para_index = 0x0f;
  936. else
  937. mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
  938. return mc_para_index;
  939. }
  940. static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl,
  941. uint32_t memory_clock, uint32_t *p_shed)
  942. {
  943. unsigned int i;
  944. *p_shed = 1;
  945. for (i = 0; i < pl->count; i++) {
  946. if (memory_clock < pl->entries[i].Mclk) {
  947. *p_shed = i;
  948. break;
  949. }
  950. }
  951. return 0;
  952. }
  953. static int ci_populate_single_memory_level(
  954. struct pp_hwmgr *hwmgr,
  955. uint32_t memory_clock,
  956. SMU7_Discrete_MemoryLevel *memory_level
  957. )
  958. {
  959. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  960. int result = 0;
  961. bool dll_state_on;
  962. uint32_t mclk_edc_wr_enable_threshold = 40000;
  963. uint32_t mclk_edc_enable_threshold = 40000;
  964. uint32_t mclk_strobe_mode_threshold = 40000;
  965. if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) {
  966. result = ci_get_dependency_volt_by_clk(hwmgr,
  967. hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc);
  968. PP_ASSERT_WITH_CODE((0 == result),
  969. "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result);
  970. }
  971. if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
  972. result = ci_get_dependency_volt_by_clk(hwmgr,
  973. hwmgr->dyn_state.vddci_dependency_on_mclk,
  974. memory_clock,
  975. &memory_level->MinVddci);
  976. PP_ASSERT_WITH_CODE((0 == result),
  977. "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result);
  978. }
  979. if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) {
  980. result = ci_get_dependency_volt_by_clk(hwmgr,
  981. hwmgr->dyn_state.mvdd_dependency_on_mclk,
  982. memory_clock,
  983. &memory_level->MinMvdd);
  984. PP_ASSERT_WITH_CODE((0 == result),
  985. "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result);
  986. }
  987. memory_level->MinVddcPhases = 1;
  988. if (data->vddc_phase_shed_control) {
  989. ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table,
  990. memory_clock, &memory_level->MinVddcPhases);
  991. }
  992. memory_level->EnabledForThrottle = 1;
  993. memory_level->EnabledForActivity = 1;
  994. memory_level->UpH = data->current_profile_setting.mclk_up_hyst;
  995. memory_level->DownH = data->current_profile_setting.mclk_down_hyst;
  996. memory_level->VoltageDownH = 0;
  997. /* Indicates maximum activity level for this performance level.*/
  998. memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
  999. memory_level->StutterEnable = 0;
  1000. memory_level->StrobeEnable = 0;
  1001. memory_level->EdcReadEnable = 0;
  1002. memory_level->EdcWriteEnable = 0;
  1003. memory_level->RttEnable = 0;
  1004. /* default set to low watermark. Highest level will be set to high later.*/
  1005. memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
  1006. data->display_timing.num_existing_displays = hwmgr->display_config->num_display;
  1007. /* stutter mode not support on ci */
  1008. /* decide strobe mode*/
  1009. memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) &&
  1010. (memory_clock <= mclk_strobe_mode_threshold);
  1011. /* decide EDC mode and memory clock ratio*/
  1012. if (data->is_memory_gddr5) {
  1013. memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock,
  1014. memory_level->StrobeEnable);
  1015. if ((mclk_edc_enable_threshold != 0) &&
  1016. (memory_clock > mclk_edc_enable_threshold)) {
  1017. memory_level->EdcReadEnable = 1;
  1018. }
  1019. if ((mclk_edc_wr_enable_threshold != 0) &&
  1020. (memory_clock > mclk_edc_wr_enable_threshold)) {
  1021. memory_level->EdcWriteEnable = 1;
  1022. }
  1023. if (memory_level->StrobeEnable) {
  1024. if (ci_get_mclk_frequency_ratio(memory_clock, 1) >=
  1025. ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf))
  1026. dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
  1027. else
  1028. dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
  1029. } else
  1030. dll_state_on = data->dll_default_on;
  1031. } else {
  1032. memory_level->StrobeRatio =
  1033. ci_get_ddr3_mclk_frequency_ratio(memory_clock);
  1034. dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
  1035. }
  1036. result = ci_calculate_mclk_params(hwmgr,
  1037. memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
  1038. if (0 == result) {
  1039. memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE);
  1040. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases);
  1041. memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE);
  1042. memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE);
  1043. /* MCLK frequency in units of 10KHz*/
  1044. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
  1045. /* Indicates maximum activity level for this performance level.*/
  1046. CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
  1047. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
  1048. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
  1049. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
  1050. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
  1051. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
  1052. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
  1053. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
  1054. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
  1055. CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
  1056. }
  1057. return result;
  1058. }
  1059. static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
  1060. {
  1061. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1062. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1063. struct smu7_dpm_table *dpm_table = &data->dpm_table;
  1064. int result;
  1065. struct amdgpu_device *adev = hwmgr->adev;
  1066. uint32_t dev_id;
  1067. uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel);
  1068. uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY;
  1069. SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel;
  1070. uint32_t i;
  1071. memset(levels, 0x00, level_array_size);
  1072. for (i = 0; i < dpm_table->mclk_table.count; i++) {
  1073. PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
  1074. "can not populate memory level as memory clock is zero", return -EINVAL);
  1075. result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value,
  1076. &(smu_data->smc_state_table.MemoryLevel[i]));
  1077. if (0 != result)
  1078. return result;
  1079. }
  1080. smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
  1081. dev_id = adev->pdev->device;
  1082. if ((dpm_table->mclk_table.count >= 2)
  1083. && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) {
  1084. smu_data->smc_state_table.MemoryLevel[1].MinVddci =
  1085. smu_data->smc_state_table.MemoryLevel[0].MinVddci;
  1086. smu_data->smc_state_table.MemoryLevel[1].MinMvdd =
  1087. smu_data->smc_state_table.MemoryLevel[0].MinMvdd;
  1088. }
  1089. smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
  1090. CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
  1091. smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
  1092. data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
  1093. smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
  1094. result = ci_copy_bytes_to_smc(hwmgr,
  1095. level_array_address, (uint8_t *)levels, (uint32_t)level_array_size,
  1096. SMC_RAM_END);
  1097. return result;
  1098. }
  1099. static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk,
  1100. SMU7_Discrete_VoltageLevel *voltage)
  1101. {
  1102. const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1103. uint32_t i = 0;
  1104. if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
  1105. /* find mvdd value which clock is more than request */
  1106. for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) {
  1107. if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) {
  1108. /* Always round to higher voltage. */
  1109. voltage->Voltage = data->mvdd_voltage_table.entries[i].value;
  1110. break;
  1111. }
  1112. }
  1113. PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count,
  1114. "MVDD Voltage is outside the supported range.", return -EINVAL);
  1115. } else {
  1116. return -EINVAL;
  1117. }
  1118. return 0;
  1119. }
  1120. static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
  1121. SMU7_Discrete_DpmTable *table)
  1122. {
  1123. int result = 0;
  1124. const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1125. struct pp_atomctrl_clock_dividers_vi dividers;
  1126. SMU7_Discrete_VoltageLevel voltage_level;
  1127. uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
  1128. uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
  1129. uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
  1130. uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
  1131. /* The ACPI state should not do DPM on DC (or ever).*/
  1132. table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
  1133. if (data->acpi_vddc)
  1134. table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE);
  1135. else
  1136. table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE);
  1137. table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1;
  1138. /* assign zero for now*/
  1139. table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
  1140. /* get the engine clock dividers for this clock value*/
  1141. result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
  1142. table->ACPILevel.SclkFrequency, &dividers);
  1143. PP_ASSERT_WITH_CODE(result == 0,
  1144. "Error retrieving Engine Clock dividers from VBIOS.", return result);
  1145. /* divider ID for required SCLK*/
  1146. table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
  1147. table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
  1148. table->ACPILevel.DeepSleepDivId = 0;
  1149. spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
  1150. CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0);
  1151. spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
  1152. CG_SPLL_FUNC_CNTL, SPLL_RESET, 1);
  1153. spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2,
  1154. CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4);
  1155. table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
  1156. table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
  1157. table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
  1158. table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
  1159. table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
  1160. table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
  1161. table->ACPILevel.CcPwrDynRm = 0;
  1162. table->ACPILevel.CcPwrDynRm1 = 0;
  1163. /* For various features to be enabled/disabled while this level is active.*/
  1164. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
  1165. /* SCLK frequency in units of 10KHz*/
  1166. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
  1167. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
  1168. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
  1169. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
  1170. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
  1171. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
  1172. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
  1173. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
  1174. CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
  1175. /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
  1176. table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc;
  1177. table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;
  1178. if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
  1179. table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc;
  1180. else {
  1181. if (data->acpi_vddci != 0)
  1182. table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE);
  1183. else
  1184. table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE);
  1185. }
  1186. if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level))
  1187. table->MemoryACPILevel.MinMvdd =
  1188. PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
  1189. else
  1190. table->MemoryACPILevel.MinMvdd = 0;
  1191. /* Force reset on DLL*/
  1192. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  1193. MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
  1194. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  1195. MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
  1196. /* Disable DLL in ACPIState*/
  1197. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  1198. MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
  1199. mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
  1200. MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
  1201. /* Enable DLL bypass signal*/
  1202. dll_cntl = PHM_SET_FIELD(dll_cntl,
  1203. DLL_CNTL, MRDCK0_BYPASS, 0);
  1204. dll_cntl = PHM_SET_FIELD(dll_cntl,
  1205. DLL_CNTL, MRDCK1_BYPASS, 0);
  1206. table->MemoryACPILevel.DllCntl =
  1207. PP_HOST_TO_SMC_UL(dll_cntl);
  1208. table->MemoryACPILevel.MclkPwrmgtCntl =
  1209. PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
  1210. table->MemoryACPILevel.MpllAdFuncCntl =
  1211. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
  1212. table->MemoryACPILevel.MpllDqFuncCntl =
  1213. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
  1214. table->MemoryACPILevel.MpllFuncCntl =
  1215. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
  1216. table->MemoryACPILevel.MpllFuncCntl_1 =
  1217. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
  1218. table->MemoryACPILevel.MpllFuncCntl_2 =
  1219. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
  1220. table->MemoryACPILevel.MpllSs1 =
  1221. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
  1222. table->MemoryACPILevel.MpllSs2 =
  1223. PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
  1224. table->MemoryACPILevel.EnabledForThrottle = 0;
  1225. table->MemoryACPILevel.EnabledForActivity = 0;
  1226. table->MemoryACPILevel.UpH = 0;
  1227. table->MemoryACPILevel.DownH = 100;
  1228. table->MemoryACPILevel.VoltageDownH = 0;
  1229. /* Indicates maximum activity level for this performance level.*/
  1230. table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
  1231. table->MemoryACPILevel.StutterEnable = 0;
  1232. table->MemoryACPILevel.StrobeEnable = 0;
  1233. table->MemoryACPILevel.EdcReadEnable = 0;
  1234. table->MemoryACPILevel.EdcWriteEnable = 0;
  1235. table->MemoryACPILevel.RttEnable = 0;
  1236. return result;
  1237. }
  1238. static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
  1239. SMU7_Discrete_DpmTable *table)
  1240. {
  1241. int result = 0;
  1242. uint8_t count;
  1243. struct pp_atomctrl_clock_dividers_vi dividers;
  1244. struct phm_uvd_clock_voltage_dependency_table *uvd_table =
  1245. hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
  1246. table->UvdLevelCount = (uint8_t)(uvd_table->count);
  1247. for (count = 0; count < table->UvdLevelCount; count++) {
  1248. table->UvdLevel[count].VclkFrequency =
  1249. uvd_table->entries[count].vclk;
  1250. table->UvdLevel[count].DclkFrequency =
  1251. uvd_table->entries[count].dclk;
  1252. table->UvdLevel[count].MinVddc =
  1253. uvd_table->entries[count].v * VOLTAGE_SCALE;
  1254. table->UvdLevel[count].MinVddcPhases = 1;
  1255. result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
  1256. table->UvdLevel[count].VclkFrequency, &dividers);
  1257. PP_ASSERT_WITH_CODE((0 == result),
  1258. "can not find divide id for Vclk clock", return result);
  1259. table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
  1260. result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
  1261. table->UvdLevel[count].DclkFrequency, &dividers);
  1262. PP_ASSERT_WITH_CODE((0 == result),
  1263. "can not find divide id for Dclk clock", return result);
  1264. table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
  1265. CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
  1266. CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
  1267. CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc);
  1268. }
  1269. return result;
  1270. }
  1271. static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
  1272. SMU7_Discrete_DpmTable *table)
  1273. {
  1274. int result = -EINVAL;
  1275. uint8_t count;
  1276. struct pp_atomctrl_clock_dividers_vi dividers;
  1277. struct phm_vce_clock_voltage_dependency_table *vce_table =
  1278. hwmgr->dyn_state.vce_clock_voltage_dependency_table;
  1279. table->VceLevelCount = (uint8_t)(vce_table->count);
  1280. table->VceBootLevel = 0;
  1281. for (count = 0; count < table->VceLevelCount; count++) {
  1282. table->VceLevel[count].Frequency = vce_table->entries[count].evclk;
  1283. table->VceLevel[count].MinVoltage =
  1284. vce_table->entries[count].v * VOLTAGE_SCALE;
  1285. table->VceLevel[count].MinPhases = 1;
  1286. result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
  1287. table->VceLevel[count].Frequency, &dividers);
  1288. PP_ASSERT_WITH_CODE((0 == result),
  1289. "can not find divide id for VCE engine clock",
  1290. return result);
  1291. table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
  1292. CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
  1293. CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage);
  1294. }
  1295. return result;
  1296. }
  1297. static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
  1298. SMU7_Discrete_DpmTable *table)
  1299. {
  1300. int result = -EINVAL;
  1301. uint8_t count;
  1302. struct pp_atomctrl_clock_dividers_vi dividers;
  1303. struct phm_acp_clock_voltage_dependency_table *acp_table =
  1304. hwmgr->dyn_state.acp_clock_voltage_dependency_table;
  1305. table->AcpLevelCount = (uint8_t)(acp_table->count);
  1306. table->AcpBootLevel = 0;
  1307. for (count = 0; count < table->AcpLevelCount; count++) {
  1308. table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk;
  1309. table->AcpLevel[count].MinVoltage = acp_table->entries[count].v;
  1310. table->AcpLevel[count].MinPhases = 1;
  1311. result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
  1312. table->AcpLevel[count].Frequency, &dividers);
  1313. PP_ASSERT_WITH_CODE((0 == result),
  1314. "can not find divide id for engine clock", return result);
  1315. table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
  1316. CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
  1317. CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage);
  1318. }
  1319. return result;
  1320. }
  1321. static int ci_populate_memory_timing_parameters(
  1322. struct pp_hwmgr *hwmgr,
  1323. uint32_t engine_clock,
  1324. uint32_t memory_clock,
  1325. struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs
  1326. )
  1327. {
  1328. uint32_t dramTiming;
  1329. uint32_t dramTiming2;
  1330. uint32_t burstTime;
  1331. int result;
  1332. result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
  1333. engine_clock, memory_clock);
  1334. PP_ASSERT_WITH_CODE(result == 0,
  1335. "Error calling VBIOS to set DRAM_TIMING.", return result);
  1336. dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
  1337. dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
  1338. burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
  1339. arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming);
  1340. arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
  1341. arb_regs->McArbBurstTime = (uint8_t)burstTime;
  1342. return 0;
  1343. }
  1344. static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
  1345. {
  1346. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1347. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1348. int result = 0;
  1349. SMU7_Discrete_MCArbDramTimingTable arb_regs;
  1350. uint32_t i, j;
  1351. memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable));
  1352. for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
  1353. for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
  1354. result = ci_populate_memory_timing_parameters
  1355. (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
  1356. data->dpm_table.mclk_table.dpm_levels[j].value,
  1357. &arb_regs.entries[i][j]);
  1358. if (0 != result)
  1359. break;
  1360. }
  1361. }
  1362. if (0 == result) {
  1363. result = ci_copy_bytes_to_smc(
  1364. hwmgr,
  1365. smu_data->arb_table_start,
  1366. (uint8_t *)&arb_regs,
  1367. sizeof(SMU7_Discrete_MCArbDramTimingTable),
  1368. SMC_RAM_END
  1369. );
  1370. }
  1371. return result;
  1372. }
  1373. static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
  1374. SMU7_Discrete_DpmTable *table)
  1375. {
  1376. int result = 0;
  1377. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1378. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1379. table->GraphicsBootLevel = 0;
  1380. table->MemoryBootLevel = 0;
  1381. /* find boot level from dpm table*/
  1382. result = phm_find_boot_level(&(data->dpm_table.sclk_table),
  1383. data->vbios_boot_state.sclk_bootup_value,
  1384. (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel));
  1385. if (0 != result) {
  1386. smu_data->smc_state_table.GraphicsBootLevel = 0;
  1387. pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n");
  1388. result = 0;
  1389. }
  1390. result = phm_find_boot_level(&(data->dpm_table.mclk_table),
  1391. data->vbios_boot_state.mclk_bootup_value,
  1392. (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel));
  1393. if (0 != result) {
  1394. smu_data->smc_state_table.MemoryBootLevel = 0;
  1395. pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n");
  1396. result = 0;
  1397. }
  1398. table->BootVddc = data->vbios_boot_state.vddc_bootup_value;
  1399. table->BootVddci = data->vbios_boot_state.vddci_bootup_value;
  1400. table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
  1401. return result;
  1402. }
  1403. static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr,
  1404. SMU7_Discrete_MCRegisters *mc_reg_table)
  1405. {
  1406. const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend;
  1407. uint32_t i, j;
  1408. for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) {
  1409. if (smu_data->mc_reg_table.validflag & 1<<j) {
  1410. PP_ASSERT_WITH_CODE(i < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE,
  1411. "Index of mc_reg_table->address[] array out of boundary", return -EINVAL);
  1412. mc_reg_table->address[i].s0 =
  1413. PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0);
  1414. mc_reg_table->address[i].s1 =
  1415. PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1);
  1416. i++;
  1417. }
  1418. }
  1419. mc_reg_table->last = (uint8_t)i;
  1420. return 0;
  1421. }
  1422. static void ci_convert_mc_registers(
  1423. const struct ci_mc_reg_entry *entry,
  1424. SMU7_Discrete_MCRegisterSet *data,
  1425. uint32_t num_entries, uint32_t valid_flag)
  1426. {
  1427. uint32_t i, j;
  1428. for (i = 0, j = 0; j < num_entries; j++) {
  1429. if (valid_flag & 1<<j) {
  1430. data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]);
  1431. i++;
  1432. }
  1433. }
  1434. }
  1435. static int ci_convert_mc_reg_table_entry_to_smc(
  1436. struct pp_hwmgr *hwmgr,
  1437. const uint32_t memory_clock,
  1438. SMU7_Discrete_MCRegisterSet *mc_reg_table_data
  1439. )
  1440. {
  1441. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1442. uint32_t i = 0;
  1443. for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) {
  1444. if (memory_clock <=
  1445. smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) {
  1446. break;
  1447. }
  1448. }
  1449. if ((i == smu_data->mc_reg_table.num_entries) && (i > 0))
  1450. --i;
  1451. ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i],
  1452. mc_reg_table_data, smu_data->mc_reg_table.last,
  1453. smu_data->mc_reg_table.validflag);
  1454. return 0;
  1455. }
  1456. static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
  1457. SMU7_Discrete_MCRegisters *mc_regs)
  1458. {
  1459. int result = 0;
  1460. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1461. int res;
  1462. uint32_t i;
  1463. for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
  1464. res = ci_convert_mc_reg_table_entry_to_smc(
  1465. hwmgr,
  1466. data->dpm_table.mclk_table.dpm_levels[i].value,
  1467. &mc_regs->data[i]
  1468. );
  1469. if (0 != res)
  1470. result = res;
  1471. }
  1472. return result;
  1473. }
  1474. static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
  1475. {
  1476. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1477. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1478. uint32_t address;
  1479. int32_t result;
  1480. if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
  1481. return 0;
  1482. memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters));
  1483. result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs));
  1484. if (result != 0)
  1485. return result;
  1486. address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]);
  1487. return ci_copy_bytes_to_smc(hwmgr, address,
  1488. (uint8_t *)&smu_data->mc_regs.data[0],
  1489. sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count,
  1490. SMC_RAM_END);
  1491. }
  1492. static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
  1493. {
  1494. int result;
  1495. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1496. memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters));
  1497. result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs));
  1498. PP_ASSERT_WITH_CODE(0 == result,
  1499. "Failed to initialize MCRegTable for the MC register addresses!", return result;);
  1500. result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs);
  1501. PP_ASSERT_WITH_CODE(0 == result,
  1502. "Failed to initialize MCRegTable for driver state!", return result;);
  1503. return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start,
  1504. (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END);
  1505. }
  1506. static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr)
  1507. {
  1508. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1509. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1510. uint8_t count, level;
  1511. count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count);
  1512. for (level = 0; level < count; level++) {
  1513. if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk
  1514. >= data->vbios_boot_state.sclk_bootup_value) {
  1515. smu_data->smc_state_table.GraphicsBootLevel = level;
  1516. break;
  1517. }
  1518. }
  1519. count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count);
  1520. for (level = 0; level < count; level++) {
  1521. if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk
  1522. >= data->vbios_boot_state.mclk_bootup_value) {
  1523. smu_data->smc_state_table.MemoryBootLevel = level;
  1524. break;
  1525. }
  1526. }
  1527. return 0;
  1528. }
  1529. static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr,
  1530. SMU7_Discrete_DpmTable *table)
  1531. {
  1532. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1533. if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control)
  1534. table->SVI2Enable = 1;
  1535. else
  1536. table->SVI2Enable = 0;
  1537. return 0;
  1538. }
  1539. static int ci_start_smc(struct pp_hwmgr *hwmgr)
  1540. {
  1541. /* set smc instruct start point at 0x0 */
  1542. ci_program_jump_on_start(hwmgr);
  1543. /* enable smc clock */
  1544. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
  1545. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0);
  1546. PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS,
  1547. INTERRUPTS_ENABLED, 1);
  1548. return 0;
  1549. }
  1550. static int ci_populate_vr_config(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table)
  1551. {
  1552. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1553. uint16_t config;
  1554. config = VR_SVI2_PLANE_1;
  1555. table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
  1556. if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
  1557. config = VR_SVI2_PLANE_2;
  1558. table->VRConfig |= config;
  1559. } else {
  1560. pr_info("VDDCshould be on SVI2 controller!");
  1561. }
  1562. if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
  1563. config = VR_SVI2_PLANE_2;
  1564. table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
  1565. } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
  1566. config = VR_SMIO_PATTERN_1;
  1567. table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
  1568. }
  1569. if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
  1570. config = VR_SMIO_PATTERN_2;
  1571. table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
  1572. }
  1573. return 0;
  1574. }
  1575. static int ci_init_smc_table(struct pp_hwmgr *hwmgr)
  1576. {
  1577. int result;
  1578. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1579. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1580. SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table);
  1581. struct pp_atomctrl_gpio_pin_assignment gpio_pin;
  1582. u32 i;
  1583. ci_initialize_power_tune_defaults(hwmgr);
  1584. memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table));
  1585. if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control)
  1586. ci_populate_smc_voltage_tables(hwmgr, table);
  1587. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  1588. PHM_PlatformCaps_AutomaticDCTransition))
  1589. table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
  1590. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  1591. PHM_PlatformCaps_StepVddc))
  1592. table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
  1593. if (data->is_memory_gddr5)
  1594. table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
  1595. if (data->ulv_supported) {
  1596. result = ci_populate_ulv_state(hwmgr, &(table->Ulv));
  1597. PP_ASSERT_WITH_CODE(0 == result,
  1598. "Failed to initialize ULV state!", return result);
  1599. cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
  1600. ixCG_ULV_PARAMETER, 0x40035);
  1601. }
  1602. result = ci_populate_all_graphic_levels(hwmgr);
  1603. PP_ASSERT_WITH_CODE(0 == result,
  1604. "Failed to initialize Graphics Level!", return result);
  1605. result = ci_populate_all_memory_levels(hwmgr);
  1606. PP_ASSERT_WITH_CODE(0 == result,
  1607. "Failed to initialize Memory Level!", return result);
  1608. result = ci_populate_smc_link_level(hwmgr, table);
  1609. PP_ASSERT_WITH_CODE(0 == result,
  1610. "Failed to initialize Link Level!", return result);
  1611. result = ci_populate_smc_acpi_level(hwmgr, table);
  1612. PP_ASSERT_WITH_CODE(0 == result,
  1613. "Failed to initialize ACPI Level!", return result);
  1614. result = ci_populate_smc_vce_level(hwmgr, table);
  1615. PP_ASSERT_WITH_CODE(0 == result,
  1616. "Failed to initialize VCE Level!", return result);
  1617. result = ci_populate_smc_acp_level(hwmgr, table);
  1618. PP_ASSERT_WITH_CODE(0 == result,
  1619. "Failed to initialize ACP Level!", return result);
  1620. /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */
  1621. /* need to populate the ARB settings for the initial state. */
  1622. result = ci_program_memory_timing_parameters(hwmgr);
  1623. PP_ASSERT_WITH_CODE(0 == result,
  1624. "Failed to Write ARB settings for the initial state.", return result);
  1625. result = ci_populate_smc_uvd_level(hwmgr, table);
  1626. PP_ASSERT_WITH_CODE(0 == result,
  1627. "Failed to initialize UVD Level!", return result);
  1628. table->UvdBootLevel = 0;
  1629. table->VceBootLevel = 0;
  1630. table->AcpBootLevel = 0;
  1631. table->SamuBootLevel = 0;
  1632. table->GraphicsBootLevel = 0;
  1633. table->MemoryBootLevel = 0;
  1634. result = ci_populate_smc_boot_level(hwmgr, table);
  1635. PP_ASSERT_WITH_CODE(0 == result,
  1636. "Failed to initialize Boot Level!", return result);
  1637. result = ci_populate_smc_initial_state(hwmgr);
  1638. PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result);
  1639. result = ci_populate_bapm_parameters_in_dpm_table(hwmgr);
  1640. PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result);
  1641. table->UVDInterval = 1;
  1642. table->VCEInterval = 1;
  1643. table->ACPInterval = 1;
  1644. table->SAMUInterval = 1;
  1645. table->GraphicsVoltageChangeEnable = 1;
  1646. table->GraphicsThermThrottleEnable = 1;
  1647. table->GraphicsInterval = 1;
  1648. table->VoltageInterval = 1;
  1649. table->ThermalInterval = 1;
  1650. table->TemperatureLimitHigh =
  1651. (data->thermal_temp_setting.temperature_high *
  1652. SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
  1653. table->TemperatureLimitLow =
  1654. (data->thermal_temp_setting.temperature_low *
  1655. SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
  1656. table->MemoryVoltageChangeEnable = 1;
  1657. table->MemoryInterval = 1;
  1658. table->VoltageResponseTime = 0;
  1659. table->VddcVddciDelta = 4000;
  1660. table->PhaseResponseTime = 0;
  1661. table->MemoryThermThrottleEnable = 1;
  1662. PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count),
  1663. "There must be 1 or more PCIE levels defined in PPTable.",
  1664. return -EINVAL);
  1665. table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count;
  1666. table->PCIeGenInterval = 1;
  1667. result = ci_populate_vr_config(hwmgr, table);
  1668. PP_ASSERT_WITH_CODE(0 == result,
  1669. "Failed to populate VRConfig setting!", return result);
  1670. data->vr_config = table->VRConfig;
  1671. ci_populate_smc_svi2_config(hwmgr, table);
  1672. for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++)
  1673. CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]);
  1674. table->ThermGpio = 17;
  1675. table->SclkStepSize = 0x4000;
  1676. if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
  1677. table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
  1678. phm_cap_set(hwmgr->platform_descriptor.platformCaps,
  1679. PHM_PlatformCaps_RegulatorHot);
  1680. } else {
  1681. table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
  1682. phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
  1683. PHM_PlatformCaps_RegulatorHot);
  1684. }
  1685. table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
  1686. CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
  1687. CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
  1688. CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid);
  1689. CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase);
  1690. CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid);
  1691. CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid);
  1692. CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
  1693. CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
  1694. CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
  1695. table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta);
  1696. CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
  1697. CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
  1698. table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE);
  1699. table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE);
  1700. table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE);
  1701. /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
  1702. result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start +
  1703. offsetof(SMU7_Discrete_DpmTable, SystemFlags),
  1704. (uint8_t *)&(table->SystemFlags),
  1705. sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController),
  1706. SMC_RAM_END);
  1707. PP_ASSERT_WITH_CODE(0 == result,
  1708. "Failed to upload dpm data to SMC memory!", return result;);
  1709. result = ci_populate_initial_mc_reg_table(hwmgr);
  1710. PP_ASSERT_WITH_CODE((0 == result),
  1711. "Failed to populate initialize MC Reg table!", return result);
  1712. result = ci_populate_pm_fuses(hwmgr);
  1713. PP_ASSERT_WITH_CODE(0 == result,
  1714. "Failed to populate PM fuses to SMC memory!", return result);
  1715. ci_start_smc(hwmgr);
  1716. return 0;
  1717. }
  1718. static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
  1719. {
  1720. struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1721. SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
  1722. uint32_t duty100;
  1723. uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
  1724. uint16_t fdo_min, slope1, slope2;
  1725. uint32_t reference_clock;
  1726. int res;
  1727. uint64_t tmp64;
  1728. if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
  1729. return 0;
  1730. if (hwmgr->thermal_controller.fanInfo.bNoFan) {
  1731. phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
  1732. PHM_PlatformCaps_MicrocodeFanControl);
  1733. return 0;
  1734. }
  1735. if (0 == ci_data->fan_table_start) {
  1736. phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
  1737. return 0;
  1738. }
  1739. duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
  1740. if (0 == duty100) {
  1741. phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
  1742. return 0;
  1743. }
  1744. tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
  1745. do_div(tmp64, 10000);
  1746. fdo_min = (uint16_t)tmp64;
  1747. t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
  1748. t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
  1749. pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
  1750. pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
  1751. slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
  1752. slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
  1753. fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
  1754. fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
  1755. fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
  1756. fan_table.Slope1 = cpu_to_be16(slope1);
  1757. fan_table.Slope2 = cpu_to_be16(slope2);
  1758. fan_table.FdoMin = cpu_to_be16(fdo_min);
  1759. fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
  1760. fan_table.HystUp = cpu_to_be16(1);
  1761. fan_table.HystSlope = cpu_to_be16(1);
  1762. fan_table.TempRespLim = cpu_to_be16(5);
  1763. reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
  1764. fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
  1765. fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
  1766. fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
  1767. res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END);
  1768. return 0;
  1769. }
  1770. static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
  1771. {
  1772. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1773. if (data->need_update_smu7_dpm_table &
  1774. (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
  1775. return ci_program_memory_timing_parameters(hwmgr);
  1776. return 0;
  1777. }
  1778. static int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr)
  1779. {
  1780. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1781. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1782. int result = 0;
  1783. uint32_t low_sclk_interrupt_threshold = 0;
  1784. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  1785. PHM_PlatformCaps_SclkThrottleLowNotification)
  1786. && (data->low_sclk_interrupt_threshold != 0)) {
  1787. low_sclk_interrupt_threshold =
  1788. data->low_sclk_interrupt_threshold;
  1789. CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
  1790. result = ci_copy_bytes_to_smc(
  1791. hwmgr,
  1792. smu_data->dpm_table_start +
  1793. offsetof(SMU7_Discrete_DpmTable,
  1794. LowSclkInterruptT),
  1795. (uint8_t *)&low_sclk_interrupt_threshold,
  1796. sizeof(uint32_t),
  1797. SMC_RAM_END);
  1798. }
  1799. result = ci_update_and_upload_mc_reg_table(hwmgr);
  1800. PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result);
  1801. result = ci_program_mem_timing_parameters(hwmgr);
  1802. PP_ASSERT_WITH_CODE((result == 0),
  1803. "Failed to program memory timing parameters!",
  1804. );
  1805. return result;
  1806. }
  1807. static uint32_t ci_get_offsetof(uint32_t type, uint32_t member)
  1808. {
  1809. switch (type) {
  1810. case SMU_SoftRegisters:
  1811. switch (member) {
  1812. case HandshakeDisables:
  1813. return offsetof(SMU7_SoftRegisters, HandshakeDisables);
  1814. case VoltageChangeTimeout:
  1815. return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout);
  1816. case AverageGraphicsActivity:
  1817. return offsetof(SMU7_SoftRegisters, AverageGraphicsA);
  1818. case PreVBlankGap:
  1819. return offsetof(SMU7_SoftRegisters, PreVBlankGap);
  1820. case VBlankTimeout:
  1821. return offsetof(SMU7_SoftRegisters, VBlankTimeout);
  1822. case DRAM_LOG_ADDR_H:
  1823. return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_H);
  1824. case DRAM_LOG_ADDR_L:
  1825. return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_L);
  1826. case DRAM_LOG_PHY_ADDR_H:
  1827. return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_H);
  1828. case DRAM_LOG_PHY_ADDR_L:
  1829. return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_L);
  1830. case DRAM_LOG_BUFF_SIZE:
  1831. return offsetof(SMU7_SoftRegisters, DRAM_LOG_BUFF_SIZE);
  1832. }
  1833. break;
  1834. case SMU_Discrete_DpmTable:
  1835. switch (member) {
  1836. case LowSclkInterruptThreshold:
  1837. return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT);
  1838. }
  1839. break;
  1840. }
  1841. pr_debug("can't get the offset of type %x member %x\n", type, member);
  1842. return 0;
  1843. }
  1844. static uint32_t ci_get_mac_definition(uint32_t value)
  1845. {
  1846. switch (value) {
  1847. case SMU_MAX_LEVELS_GRAPHICS:
  1848. return SMU7_MAX_LEVELS_GRAPHICS;
  1849. case SMU_MAX_LEVELS_MEMORY:
  1850. return SMU7_MAX_LEVELS_MEMORY;
  1851. case SMU_MAX_LEVELS_LINK:
  1852. return SMU7_MAX_LEVELS_LINK;
  1853. case SMU_MAX_ENTRIES_SMIO:
  1854. return SMU7_MAX_ENTRIES_SMIO;
  1855. case SMU_MAX_LEVELS_VDDC:
  1856. return SMU7_MAX_LEVELS_VDDC;
  1857. case SMU_MAX_LEVELS_VDDCI:
  1858. return SMU7_MAX_LEVELS_VDDCI;
  1859. case SMU_MAX_LEVELS_MVDD:
  1860. return SMU7_MAX_LEVELS_MVDD;
  1861. }
  1862. pr_debug("can't get the mac of %x\n", value);
  1863. return 0;
  1864. }
  1865. static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr)
  1866. {
  1867. uint32_t byte_count, start_addr;
  1868. uint8_t *src;
  1869. uint32_t data;
  1870. struct cgs_firmware_info info = {0};
  1871. cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info);
  1872. hwmgr->is_kicker = info.is_kicker;
  1873. hwmgr->smu_version = info.version;
  1874. byte_count = info.image_size;
  1875. src = (uint8_t *)info.kptr;
  1876. start_addr = info.ucode_start_address;
  1877. if (byte_count > SMC_RAM_END) {
  1878. pr_err("SMC address is beyond the SMC RAM area.\n");
  1879. return -EINVAL;
  1880. }
  1881. cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr);
  1882. PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
  1883. for (; byte_count >= 4; byte_count -= 4) {
  1884. data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
  1885. cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data);
  1886. src += 4;
  1887. }
  1888. PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
  1889. if (0 != byte_count) {
  1890. pr_err("SMC size must be divisible by 4\n");
  1891. return -EINVAL;
  1892. }
  1893. return 0;
  1894. }
  1895. static int ci_upload_firmware(struct pp_hwmgr *hwmgr)
  1896. {
  1897. if (ci_is_smc_ram_running(hwmgr)) {
  1898. pr_info("smc is running, no need to load smc firmware\n");
  1899. return 0;
  1900. }
  1901. PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS,
  1902. boot_seq_done, 1);
  1903. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL,
  1904. pre_fetcher_en, 1);
  1905. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1);
  1906. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1);
  1907. return ci_load_smc_ucode(hwmgr);
  1908. }
  1909. static int ci_process_firmware_header(struct pp_hwmgr *hwmgr)
  1910. {
  1911. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  1912. struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  1913. uint32_t tmp = 0;
  1914. int result;
  1915. bool error = false;
  1916. if (ci_upload_firmware(hwmgr))
  1917. return -EINVAL;
  1918. result = ci_read_smc_sram_dword(hwmgr,
  1919. SMU7_FIRMWARE_HEADER_LOCATION +
  1920. offsetof(SMU7_Firmware_Header, DpmTable),
  1921. &tmp, SMC_RAM_END);
  1922. if (0 == result)
  1923. ci_data->dpm_table_start = tmp;
  1924. error |= (0 != result);
  1925. result = ci_read_smc_sram_dword(hwmgr,
  1926. SMU7_FIRMWARE_HEADER_LOCATION +
  1927. offsetof(SMU7_Firmware_Header, SoftRegisters),
  1928. &tmp, SMC_RAM_END);
  1929. if (0 == result) {
  1930. data->soft_regs_start = tmp;
  1931. ci_data->soft_regs_start = tmp;
  1932. }
  1933. error |= (0 != result);
  1934. result = ci_read_smc_sram_dword(hwmgr,
  1935. SMU7_FIRMWARE_HEADER_LOCATION +
  1936. offsetof(SMU7_Firmware_Header, mcRegisterTable),
  1937. &tmp, SMC_RAM_END);
  1938. if (0 == result)
  1939. ci_data->mc_reg_table_start = tmp;
  1940. result = ci_read_smc_sram_dword(hwmgr,
  1941. SMU7_FIRMWARE_HEADER_LOCATION +
  1942. offsetof(SMU7_Firmware_Header, FanTable),
  1943. &tmp, SMC_RAM_END);
  1944. if (0 == result)
  1945. ci_data->fan_table_start = tmp;
  1946. error |= (0 != result);
  1947. result = ci_read_smc_sram_dword(hwmgr,
  1948. SMU7_FIRMWARE_HEADER_LOCATION +
  1949. offsetof(SMU7_Firmware_Header, mcArbDramTimingTable),
  1950. &tmp, SMC_RAM_END);
  1951. if (0 == result)
  1952. ci_data->arb_table_start = tmp;
  1953. error |= (0 != result);
  1954. result = ci_read_smc_sram_dword(hwmgr,
  1955. SMU7_FIRMWARE_HEADER_LOCATION +
  1956. offsetof(SMU7_Firmware_Header, Version),
  1957. &tmp, SMC_RAM_END);
  1958. if (0 == result)
  1959. hwmgr->microcode_version_info.SMC = tmp;
  1960. error |= (0 != result);
  1961. return error ? 1 : 0;
  1962. }
  1963. static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr)
  1964. {
  1965. return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
  1966. }
  1967. static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg)
  1968. {
  1969. bool result = true;
  1970. switch (in_reg) {
  1971. case mmMC_SEQ_RAS_TIMING:
  1972. *out_reg = mmMC_SEQ_RAS_TIMING_LP;
  1973. break;
  1974. case mmMC_SEQ_DLL_STBY:
  1975. *out_reg = mmMC_SEQ_DLL_STBY_LP;
  1976. break;
  1977. case mmMC_SEQ_G5PDX_CMD0:
  1978. *out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
  1979. break;
  1980. case mmMC_SEQ_G5PDX_CMD1:
  1981. *out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
  1982. break;
  1983. case mmMC_SEQ_G5PDX_CTRL:
  1984. *out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
  1985. break;
  1986. case mmMC_SEQ_CAS_TIMING:
  1987. *out_reg = mmMC_SEQ_CAS_TIMING_LP;
  1988. break;
  1989. case mmMC_SEQ_MISC_TIMING:
  1990. *out_reg = mmMC_SEQ_MISC_TIMING_LP;
  1991. break;
  1992. case mmMC_SEQ_MISC_TIMING2:
  1993. *out_reg = mmMC_SEQ_MISC_TIMING2_LP;
  1994. break;
  1995. case mmMC_SEQ_PMG_DVS_CMD:
  1996. *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
  1997. break;
  1998. case mmMC_SEQ_PMG_DVS_CTL:
  1999. *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
  2000. break;
  2001. case mmMC_SEQ_RD_CTL_D0:
  2002. *out_reg = mmMC_SEQ_RD_CTL_D0_LP;
  2003. break;
  2004. case mmMC_SEQ_RD_CTL_D1:
  2005. *out_reg = mmMC_SEQ_RD_CTL_D1_LP;
  2006. break;
  2007. case mmMC_SEQ_WR_CTL_D0:
  2008. *out_reg = mmMC_SEQ_WR_CTL_D0_LP;
  2009. break;
  2010. case mmMC_SEQ_WR_CTL_D1:
  2011. *out_reg = mmMC_SEQ_WR_CTL_D1_LP;
  2012. break;
  2013. case mmMC_PMG_CMD_EMRS:
  2014. *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
  2015. break;
  2016. case mmMC_PMG_CMD_MRS:
  2017. *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
  2018. break;
  2019. case mmMC_PMG_CMD_MRS1:
  2020. *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
  2021. break;
  2022. case mmMC_SEQ_PMG_TIMING:
  2023. *out_reg = mmMC_SEQ_PMG_TIMING_LP;
  2024. break;
  2025. case mmMC_PMG_CMD_MRS2:
  2026. *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
  2027. break;
  2028. case mmMC_SEQ_WR_CTL_2:
  2029. *out_reg = mmMC_SEQ_WR_CTL_2_LP;
  2030. break;
  2031. default:
  2032. result = false;
  2033. break;
  2034. }
  2035. return result;
  2036. }
  2037. static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table)
  2038. {
  2039. uint32_t i;
  2040. uint16_t address;
  2041. for (i = 0; i < table->last; i++) {
  2042. table->mc_reg_address[i].s0 =
  2043. ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address)
  2044. ? address : table->mc_reg_address[i].s1;
  2045. }
  2046. return 0;
  2047. }
  2048. static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table,
  2049. struct ci_mc_reg_table *ni_table)
  2050. {
  2051. uint8_t i, j;
  2052. PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE),
  2053. "Invalid VramInfo table.", return -EINVAL);
  2054. PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
  2055. "Invalid VramInfo table.", return -EINVAL);
  2056. for (i = 0; i < table->last; i++)
  2057. ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
  2058. ni_table->last = table->last;
  2059. for (i = 0; i < table->num_entries; i++) {
  2060. ni_table->mc_reg_table_entry[i].mclk_max =
  2061. table->mc_reg_table_entry[i].mclk_max;
  2062. for (j = 0; j < table->last; j++) {
  2063. ni_table->mc_reg_table_entry[i].mc_data[j] =
  2064. table->mc_reg_table_entry[i].mc_data[j];
  2065. }
  2066. }
  2067. ni_table->num_entries = table->num_entries;
  2068. return 0;
  2069. }
  2070. static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr,
  2071. struct ci_mc_reg_table *table)
  2072. {
  2073. uint8_t i, j, k;
  2074. uint32_t temp_reg;
  2075. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  2076. for (i = 0, j = table->last; i < table->last; i++) {
  2077. PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE),
  2078. "Invalid VramInfo table.", return -EINVAL);
  2079. switch (table->mc_reg_address[i].s1) {
  2080. case mmMC_SEQ_MISC1:
  2081. temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS);
  2082. table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
  2083. table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
  2084. for (k = 0; k < table->num_entries; k++) {
  2085. table->mc_reg_table_entry[k].mc_data[j] =
  2086. ((temp_reg & 0xffff0000)) |
  2087. ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
  2088. }
  2089. j++;
  2090. PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE),
  2091. "Invalid VramInfo table.", return -EINVAL);
  2092. temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
  2093. table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
  2094. table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
  2095. for (k = 0; k < table->num_entries; k++) {
  2096. table->mc_reg_table_entry[k].mc_data[j] =
  2097. (temp_reg & 0xffff0000) |
  2098. (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
  2099. if (!data->is_memory_gddr5)
  2100. table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
  2101. }
  2102. j++;
  2103. if (!data->is_memory_gddr5) {
  2104. PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE),
  2105. "Invalid VramInfo table.", return -EINVAL);
  2106. table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
  2107. table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
  2108. for (k = 0; k < table->num_entries; k++) {
  2109. table->mc_reg_table_entry[k].mc_data[j] =
  2110. (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
  2111. }
  2112. j++;
  2113. }
  2114. break;
  2115. case mmMC_SEQ_RESERVE_M:
  2116. temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
  2117. table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
  2118. table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
  2119. for (k = 0; k < table->num_entries; k++) {
  2120. table->mc_reg_table_entry[k].mc_data[j] =
  2121. (temp_reg & 0xffff0000) |
  2122. (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
  2123. }
  2124. j++;
  2125. break;
  2126. default:
  2127. break;
  2128. }
  2129. }
  2130. table->last = j;
  2131. return 0;
  2132. }
  2133. static int ci_set_valid_flag(struct ci_mc_reg_table *table)
  2134. {
  2135. uint8_t i, j;
  2136. for (i = 0; i < table->last; i++) {
  2137. for (j = 1; j < table->num_entries; j++) {
  2138. if (table->mc_reg_table_entry[j-1].mc_data[i] !=
  2139. table->mc_reg_table_entry[j].mc_data[i]) {
  2140. table->validflag |= (1 << i);
  2141. break;
  2142. }
  2143. }
  2144. }
  2145. return 0;
  2146. }
  2147. static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
  2148. {
  2149. int result;
  2150. struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
  2151. pp_atomctrl_mc_reg_table *table;
  2152. struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table;
  2153. uint8_t module_index = ci_get_memory_modile_index(hwmgr);
  2154. table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
  2155. if (NULL == table)
  2156. return -ENOMEM;
  2157. /* Program additional LP registers that are no longer programmed by VBIOS */
  2158. cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
  2159. cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
  2160. cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
  2161. cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
  2162. cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
  2163. cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
  2164. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
  2165. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
  2166. cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
  2167. cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
  2168. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
  2169. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
  2170. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
  2171. cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
  2172. cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
  2173. cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
  2174. cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
  2175. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
  2176. cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
  2177. cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
  2178. memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table));
  2179. result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
  2180. if (0 == result)
  2181. result = ci_copy_vbios_smc_reg_table(table, ni_table);
  2182. if (0 == result) {
  2183. ci_set_s0_mc_reg_index(ni_table);
  2184. result = ci_set_mc_special_registers(hwmgr, ni_table);
  2185. }
  2186. if (0 == result)
  2187. ci_set_valid_flag(ni_table);
  2188. kfree(table);
  2189. return result;
  2190. }
  2191. static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr)
  2192. {
  2193. return ci_is_smc_ram_running(hwmgr);
  2194. }
  2195. static int ci_smu_init(struct pp_hwmgr *hwmgr)
  2196. {
  2197. struct ci_smumgr *ci_priv = NULL;
  2198. ci_priv = kzalloc(sizeof(struct ci_smumgr), GFP_KERNEL);
  2199. if (ci_priv == NULL)
  2200. return -ENOMEM;
  2201. hwmgr->smu_backend = ci_priv;
  2202. return 0;
  2203. }
  2204. static int ci_smu_fini(struct pp_hwmgr *hwmgr)
  2205. {
  2206. kfree(hwmgr->smu_backend);
  2207. hwmgr->smu_backend = NULL;
  2208. return 0;
  2209. }
  2210. static int ci_start_smu(struct pp_hwmgr *hwmgr)
  2211. {
  2212. return 0;
  2213. }
  2214. static int ci_update_dpm_settings(struct pp_hwmgr *hwmgr,
  2215. void *profile_setting)
  2216. {
  2217. struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
  2218. struct ci_smumgr *smu_data = (struct ci_smumgr *)
  2219. (hwmgr->smu_backend);
  2220. struct profile_mode_setting *setting;
  2221. struct SMU7_Discrete_GraphicsLevel *levels =
  2222. smu_data->smc_state_table.GraphicsLevel;
  2223. uint32_t array = smu_data->dpm_table_start +
  2224. offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
  2225. uint32_t mclk_array = smu_data->dpm_table_start +
  2226. offsetof(SMU7_Discrete_DpmTable, MemoryLevel);
  2227. struct SMU7_Discrete_MemoryLevel *mclk_levels =
  2228. smu_data->smc_state_table.MemoryLevel;
  2229. uint32_t i;
  2230. uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
  2231. if (profile_setting == NULL)
  2232. return -EINVAL;
  2233. setting = (struct profile_mode_setting *)profile_setting;
  2234. if (setting->bupdate_sclk) {
  2235. if (!data->sclk_dpm_key_disabled)
  2236. smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
  2237. for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
  2238. if (levels[i].ActivityLevel !=
  2239. cpu_to_be16(setting->sclk_activity)) {
  2240. levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
  2241. clk_activity_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
  2242. + offsetof(SMU7_Discrete_GraphicsLevel, ActivityLevel);
  2243. offset = clk_activity_offset & ~0x3;
  2244. tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
  2245. tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
  2246. cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
  2247. }
  2248. if (levels[i].UpH != setting->sclk_up_hyst ||
  2249. levels[i].DownH != setting->sclk_down_hyst) {
  2250. levels[i].UpH = setting->sclk_up_hyst;
  2251. levels[i].DownH = setting->sclk_down_hyst;
  2252. up_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
  2253. + offsetof(SMU7_Discrete_GraphicsLevel, UpH);
  2254. down_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
  2255. + offsetof(SMU7_Discrete_GraphicsLevel, DownH);
  2256. offset = up_hyst_offset & ~0x3;
  2257. tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
  2258. tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpH, sizeof(uint8_t));
  2259. tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownH, sizeof(uint8_t));
  2260. cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
  2261. }
  2262. }
  2263. if (!data->sclk_dpm_key_disabled)
  2264. smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
  2265. }
  2266. if (setting->bupdate_mclk) {
  2267. if (!data->mclk_dpm_key_disabled)
  2268. smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
  2269. for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
  2270. if (mclk_levels[i].ActivityLevel !=
  2271. cpu_to_be16(setting->mclk_activity)) {
  2272. mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
  2273. clk_activity_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
  2274. + offsetof(SMU7_Discrete_MemoryLevel, ActivityLevel);
  2275. offset = clk_activity_offset & ~0x3;
  2276. tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
  2277. tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
  2278. cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
  2279. }
  2280. if (mclk_levels[i].UpH != setting->mclk_up_hyst ||
  2281. mclk_levels[i].DownH != setting->mclk_down_hyst) {
  2282. mclk_levels[i].UpH = setting->mclk_up_hyst;
  2283. mclk_levels[i].DownH = setting->mclk_down_hyst;
  2284. up_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
  2285. + offsetof(SMU7_Discrete_MemoryLevel, UpH);
  2286. down_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
  2287. + offsetof(SMU7_Discrete_MemoryLevel, DownH);
  2288. offset = up_hyst_offset & ~0x3;
  2289. tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
  2290. tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpH, sizeof(uint8_t));
  2291. tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownH, sizeof(uint8_t));
  2292. cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
  2293. }
  2294. }
  2295. if (!data->mclk_dpm_key_disabled)
  2296. smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
  2297. }
  2298. return 0;
  2299. }
  2300. static int ci_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
  2301. {
  2302. struct amdgpu_device *adev = hwmgr->adev;
  2303. struct smu7_hwmgr *data = hwmgr->backend;
  2304. struct ci_smumgr *smu_data = hwmgr->smu_backend;
  2305. struct phm_uvd_clock_voltage_dependency_table *uvd_table =
  2306. hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
  2307. uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
  2308. AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
  2309. AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
  2310. AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
  2311. uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc :
  2312. hwmgr->dyn_state.max_clock_voltage_on_dc.vddc;
  2313. int32_t i;
  2314. if (PP_CAP(PHM_PlatformCaps_UVDDPM) || uvd_table->count <= 0)
  2315. smu_data->smc_state_table.UvdBootLevel = 0;
  2316. else
  2317. smu_data->smc_state_table.UvdBootLevel = uvd_table->count - 1;
  2318. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475,
  2319. UvdBootLevel, smu_data->smc_state_table.UvdBootLevel);
  2320. data->dpm_level_enable_mask.uvd_dpm_enable_mask = 0;
  2321. for (i = uvd_table->count - 1; i >= 0; i--) {
  2322. if (uvd_table->entries[i].v <= max_vddc)
  2323. data->dpm_level_enable_mask.uvd_dpm_enable_mask |= 1 << i;
  2324. if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_UVDDPM))
  2325. break;
  2326. }
  2327. ci_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask,
  2328. data->dpm_level_enable_mask.uvd_dpm_enable_mask);
  2329. return 0;
  2330. }
  2331. static int ci_update_vce_smc_table(struct pp_hwmgr *hwmgr)
  2332. {
  2333. struct amdgpu_device *adev = hwmgr->adev;
  2334. struct smu7_hwmgr *data = hwmgr->backend;
  2335. struct phm_vce_clock_voltage_dependency_table *vce_table =
  2336. hwmgr->dyn_state.vce_clock_voltage_dependency_table;
  2337. uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
  2338. AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
  2339. AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
  2340. AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
  2341. uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc :
  2342. hwmgr->dyn_state.max_clock_voltage_on_dc.vddc;
  2343. int32_t i;
  2344. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475,
  2345. VceBootLevel, 0); /* temp hard code to level 0, vce can set min evclk*/
  2346. data->dpm_level_enable_mask.vce_dpm_enable_mask = 0;
  2347. for (i = vce_table->count - 1; i >= 0; i--) {
  2348. if (vce_table->entries[i].v <= max_vddc)
  2349. data->dpm_level_enable_mask.vce_dpm_enable_mask |= 1 << i;
  2350. if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_VCEDPM))
  2351. break;
  2352. }
  2353. ci_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask,
  2354. data->dpm_level_enable_mask.vce_dpm_enable_mask);
  2355. return 0;
  2356. }
  2357. static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
  2358. {
  2359. switch (type) {
  2360. case SMU_UVD_TABLE:
  2361. ci_update_uvd_smc_table(hwmgr);
  2362. break;
  2363. case SMU_VCE_TABLE:
  2364. ci_update_vce_smc_table(hwmgr);
  2365. break;
  2366. default:
  2367. break;
  2368. }
  2369. return 0;
  2370. }
  2371. static void ci_reset_smc(struct pp_hwmgr *hwmgr)
  2372. {
  2373. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
  2374. SMC_SYSCON_RESET_CNTL,
  2375. rst_reg, 1);
  2376. }
  2377. static void ci_stop_smc_clock(struct pp_hwmgr *hwmgr)
  2378. {
  2379. PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
  2380. SMC_SYSCON_CLOCK_CNTL_0,
  2381. ck_disable, 1);
  2382. }
  2383. static int ci_stop_smc(struct pp_hwmgr *hwmgr)
  2384. {
  2385. ci_reset_smc(hwmgr);
  2386. ci_stop_smc_clock(hwmgr);
  2387. return 0;
  2388. }
  2389. const struct pp_smumgr_func ci_smu_funcs = {
  2390. .smu_init = ci_smu_init,
  2391. .smu_fini = ci_smu_fini,
  2392. .start_smu = ci_start_smu,
  2393. .check_fw_load_finish = NULL,
  2394. .request_smu_load_fw = NULL,
  2395. .request_smu_load_specific_fw = NULL,
  2396. .send_msg_to_smc = ci_send_msg_to_smc,
  2397. .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter,
  2398. .download_pptable_settings = NULL,
  2399. .upload_pptable_settings = NULL,
  2400. .get_offsetof = ci_get_offsetof,
  2401. .process_firmware_header = ci_process_firmware_header,
  2402. .init_smc_table = ci_init_smc_table,
  2403. .update_sclk_threshold = ci_update_sclk_threshold,
  2404. .thermal_setup_fan_table = ci_thermal_setup_fan_table,
  2405. .populate_all_graphic_levels = ci_populate_all_graphic_levels,
  2406. .populate_all_memory_levels = ci_populate_all_memory_levels,
  2407. .get_mac_definition = ci_get_mac_definition,
  2408. .initialize_mc_reg_table = ci_initialize_mc_reg_table,
  2409. .is_dpm_running = ci_is_dpm_running,
  2410. .update_dpm_settings = ci_update_dpm_settings,
  2411. .update_smc_table = ci_update_smc_table,
  2412. .stop_smc = ci_stop_smc,
  2413. };