1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719 |
- /*
- * Copyright 2021-2022 NXP
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
- #include <errno.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <common/debug.h>
- #include "csr.h"
- #include <ddr.h>
- #include "ddr4fw.h"
- #include <drivers/delay_timer.h>
- #ifdef NXP_WARM_BOOT
- #include <fspi_api.h>
- #endif
- #include "input.h"
- #include <lib/mmio.h>
- #include <lib/utils.h>
- #include <lib/xlat_tables/xlat_tables_v2.h>
- #ifdef DDR_PHY_DEBUG
- #include "messages.h"
- #endif
- #ifdef NXP_WARM_BOOT
- #include "phy.h"
- #endif
- #include "pie.h"
- #define TIMEOUTDEFAULT 500
- #define MAP_PHY_ADDR(pstate, n, instance, offset, c) \
- ((((pstate * n) + instance + c) << 12) + offset)
- static uint32_t map_phy_addr_space(uint32_t addr)
- {
- /* 23 bit addressing */
- uint32_t pstate = (addr & U(0x700000)) >> 20U; /* bit 22:20 */
- uint32_t block_type = (addr & U(0x0f0000)) >> 16U; /* bit 19:16 */
- uint32_t instance = (addr & U(0x00f000)) >> 12U; /* bit 15:12 */
- uint32_t offset = (addr & U(0x000fff)); /* bit 11:0 */
- switch (block_type) {
- case 0x0: /* 0x0 : ANIB */
- return MAP_PHY_ADDR(pstate, 12, instance, offset, 0);
- case 0x1: /* 0x1 : DBYTE */
- return MAP_PHY_ADDR(pstate, 10, instance, offset, 0x30);
- case 0x2: /* 0x2 : MASTER */
- return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x58);
- case 0x4: /* 0x4 : ACSM */
- return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x5c);
- case 0x5: /* 0x5 : μCTL Memory */
- return MAP_PHY_ADDR(pstate, 0, instance, offset, 0x60);
- case 0x7: /* 0x7 : PPGC */
- return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x68);
- case 0x9: /* 0x9 : INITENG */
- return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x69);
- case 0xc: /* 0xC : DRTUB */
- return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6d);
- case 0xd: /* 0xD : APB Only */
- return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6e);
- default:
- printf("ERR: Invalid block_type = 0x%x\n", block_type);
- return 0;
- }
- }
- static inline uint16_t *phy_io_addr(void *phy, uint32_t addr)
- {
- return phy + (map_phy_addr_space(addr) << 2);
- }
- static inline void phy_io_write16(uint16_t *phy, uint32_t addr, uint16_t data)
- {
- mmio_write_16((uintptr_t)phy_io_addr(phy, addr), data);
- #ifdef DEBUG_PHY_IO
- printf("0x%06x,0x%x\n", addr, data);
- #endif
- }
- static inline uint16_t phy_io_read16(uint16_t *phy, uint32_t addr)
- {
- uint16_t reg = mmio_read_16((uintptr_t) phy_io_addr(phy, addr));
- #ifdef DEBUG_PHY_IO
- printf("R: 0x%06x,0x%x\n", addr, reg);
- #endif
- return reg;
- }
- #ifdef NXP_APPLY_MAX_CDD
- #define CDD_VAL_READ_ADDR (0x054012)
- #define CDD_DATA_LEN (60)
- static void read_phy_reg(uint16_t *phy, uint32_t addr,
- uint16_t *buf, uint32_t len)
- {
- uint32_t i = 0U;
- for (i = 0U; i < len/2; i++) {
- buf[i] = phy_io_read16(phy, (addr + i));
- }
- }
- static uint32_t findrank(uint32_t cs_in_use)
- {
- uint32_t val = 0U;
- switch (cs_in_use) {
- case U(0xf):
- val = 4U;
- break;
- case U(0x3):
- val = 2U;
- break;
- case U(0x1):
- val = 1U;
- break;
- default:
- printf("Error - Invalid cs_in_use value\n");
- }
- return val;
- }
- static uint8_t findmax(uint8_t *buf, uint32_t len)
- {
- uint8_t max = 0U;
- uint32_t i = 0U;
- for (i = 0U; i < len; i++) {
- if (buf[i] > max) {
- max = buf[i];
- }
- }
- return max;
- }
- static void get_cdd_val(uint16_t **phy_ptr, uint32_t rank, uint32_t freq,
- uint32_t *tcfg0, uint32_t *tcfg4)
- {
- uint8_t cdd[CDD_DATA_LEN+4] = {0U};
- uint32_t i, val = 0U;
- uint16_t *phy;
- uint8_t buf[16] = {U(0x0)};
- uint8_t trr = 0U, tww = 0U, trw = 0U, twr = 0U;
- uint8_t rrmax = 0U, wwmax = 0U, rwmax = 0U, wrmax = 0U;
- uint8_t tmp = U(0x0);
- uint8_t *c = NULL;
- for (i = 0U; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, U(0x0));
- read_phy_reg(phy, CDD_VAL_READ_ADDR,
- (uint16_t *)&cdd, CDD_DATA_LEN);
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, U(0x1));
- /* CDD values and address
- *
- * 0x054012 0x24 cdd[0] CDD[X][X]
- * 0x054012 0x25 cdd[1] RR[3][2]
- * 0x054013 0x26 cdd[2] RR[3][1]
- * 0x054013 0x27 cdd[3] RR[3][0]
- * 0x054014 0x28 cdd[4] RR[2][3]
- * 0x054014 0x29 cdd[5] RR[2][1]
- * 0x054015 0x2a cdd[6] RR[2][0]
- * 0x054015 0x2b cdd[7] RR[1][3]
- * 0x054016 0x2c cdd[8] RR[1][2]
- * 0x054016 0x2d cdd[9] RR[1][0]
- * 0x054017 0x2e cdd[10] RR[0][3]
- * 0x054017 0x2f cdd[11] RR[0][2]
- * 0x054018 0x30 cdd[12] RR[0][1]
- * 0x054018 0x31 cdd[13] WW[3][2]
- * 0x054019 0x32 cdd[14] WW[3][1]
- * 0x054019 0x33 cdd[15] WW[3][0]
- * 0x05401a 0x34 cdd[16] WW[2][3]
- * 0x05401a 0x35 cdd[17] WW[2][1]
- * 0x05401b 0x36 cdd[18] WW[2][0]
- * 0x05401b 0x37 cdd[19] WW[1][3]
- * 0x05401c 0x38 cdd[20] WW[1][2]
- * 0x05401c 0x39 cdd[21] WW[1][0]
- * 0x05401d 0x3a cdd[22] WW[0][3]
- * 0x05401d 0x3b cdd[23] WW[0][2]
- * 0x05401e 0x3c cdd[24] WW[0][1]
- * 0x05401e 0x3d cdd[25] RW[3][3]
- * 0x05401f 0x3e cdd[26] RW[3][2]
- * 0x05401f 0x3f cdd[27] RW[3][1]
- * 0x054020 0x40 cdd[28] RW[3][0]
- * 0x054020 0x41 cdd[29] RW[2][3]
- * 0x054021 0x42 cdd[30] RW[2][2]
- * 0x054021 0x43 cdd[31] RW[2][1]
- * 0x054022 0x44 cdd[32] RW[2][0]
- * 0x054022 0x45 cdd[33] RW[1][3]
- * 0x054023 0x46 cdd[34] RW[1][2]
- * 0x054023 0x47 cdd[35] RW[1][1]
- * 0x054024 0x48 cdd[36] RW[1][0]
- * 0x054024 0x49 cdd[37] RW[0][3]
- * 0x054025 0x4a cdd[38] RW[0][2]
- * 0x054025 0x4b cdd[39] RW[0][1]
- * 0x054026 0x4c cdd[40] RW[0][0]
- * 0x054026 0x4d cdd[41] WR[3][3]
- * 0x054027 0x4e cdd[42] WR[3][2]
- * 0x054027 0x4f cdd[43] WR[3][1]
- * 0x054028 0x50 cdd[44] WR[3][0]
- * 0x054028 0x51 cdd[45] WR[2][3]
- * 0x054029 0x52 cdd[46] WR[2][2]
- * 0x054029 0x53 cdd[47] WR[2][1]
- * 0x05402a 0x54 cdd[48] WR[2][0]
- * 0x05402a 0x55 cdd[49] WR[1][3]
- * 0x05402b 0x56 cdd[50] WR[1][2]
- * 0x05402b 0x57 cdd[51] WR[1][1]
- * 0x05402c 0x58 cdd[52] WR[1][0]
- * 0x05402c 0x59 cdd[53] WR[0][3]
- * 0x05402d 0x5a cdd[54] WR[0][2]
- * 0x05402d 0x5b cdd[55] WR[0][1]
- * 0x05402e 0x5c cdd[56] WR[0][0]
- * 0x05402e 0x5d cdd[57] CDD[Y][Y]
- */
- switch (rank) {
- case 1U:
- tmp = rwmax;
- rwmax = cdd[40];
- if (tmp > rwmax) {
- rwmax = tmp;
- }
- break;
- case 2U:
- buf[0] = cdd[12];
- buf[1] = cdd[9];
- tmp = rrmax;
- rrmax = findmax(buf, 2U);
- if (tmp > rrmax) {
- rrmax = tmp;
- }
- buf[0] = cdd[24];
- buf[1] = cdd[21];
- tmp = wwmax;
- wwmax = findmax(buf, 2U);
- if (tmp > wwmax) {
- wwmax = tmp;
- }
- buf[0] = cdd[40];
- buf[1] = cdd[39];
- buf[2] = cdd[36];
- buf[3] = cdd[35];
- tmp = rwmax;
- rwmax = findmax(buf, 4U);
- if (tmp > rwmax) {
- rwmax = tmp;
- }
- wrmax = wwmax;
- break;
- case 4U:
- tmp = rrmax;
- c = &cdd[1];
- rrmax = findmax(c, 12U);
- if (tmp > rrmax) {
- rrmax = tmp;
- }
- tmp = wwmax;
- c = &cdd[13];
- wwmax = findmax(c, 12U);
- if (tmp > wwmax) {
- wwmax = tmp;
- }
- tmp = rwmax;
- c = &cdd[25];
- rwmax = findmax(c, 16U);
- if (tmp > rwmax) {
- rwmax = tmp;
- }
- wrmax = wwmax;
- break;
- }
- }
- rrmax += 3U;
- wwmax += 4U;
- if (wwmax > 7U) {
- wwmax = 7U;
- }
- if (rrmax > 7U) {
- rrmax = 7U;
- }
- if (wrmax > U(0xf)) {
- wrmax = 0U;
- }
- if (rwmax > U(0x7)) {
- rwmax = U(0x7);
- }
- val = *tcfg0;
- tww = (val >> 24U) & U(0x3);
- trr = (val >> 26U) & U(0x3);
- twr = (val >> 28U) & U(0x3);
- trw = (val >> 30U) & U(0x3);
- val = *tcfg4;
- tww = tww | (((val >> 8U) & U(0x1)) << 2U);
- trr = trr | (((val >> 10U) & U(0x1)) << 2U);
- twr = twr | (((val >> 12U) & U(0x1)) << 2U);
- trw = trw | (((val >> 14U) & U(0x3)) << 2U);
- if (trr > rrmax) {
- rrmax = trr;
- }
- if (tww > wwmax) {
- wwmax = tww;
- }
- if (trw > rwmax) {
- rwmax = trw;
- }
- if (twr > wrmax) {
- wrmax = twr;
- }
- debug("CDD rrmax %x wwmax %x rwmax %x wrmax %x\n",
- rrmax, wwmax, rwmax, wrmax);
- val = ((wwmax & U(0x3)) << 24U)
- | ((rrmax & U(0x3)) << 26U)
- | ((wrmax & U(0x3)) << 28U)
- | ((rwmax & U(0x3)) << 30U);
- *tcfg0 = (*tcfg0 & U(0x00FFFFFF)) | (val);
- val = (((wwmax >> 2U) & U(0x1)) << 8U)
- | (((rrmax >> 2U) & U(0x1)) << 10U)
- | (((wrmax >> 2U) & U(0x1)) << 12U)
- | (((rwmax >> 2U) & U(0x3)) << 14U);
- *tcfg4 = (*tcfg4 & U(0xffff00ff)) | val;
- }
- #endif
- #ifdef NXP_WARM_BOOT
- int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store,
- uint32_t num_of_phy, int train2d
- #ifdef NXP_APPLY_MAX_CDD
- , struct ddr_ctrl_reg_values *ddrctrl_regs
- #endif
- )
- {
- uint16_t *phy = NULL, value = 0x0;
- uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
- int i = 0, j = 0, ret = -EINVAL;
- ret = xspi_sector_erase(address_to_store, PHY_ERASE_SIZE);
- if (ret != 0) {
- return -EINVAL;
- }
- for (j = 0; j < num_of_phy; j++) {
- /* Save training values of all PHYs */
- phy = phy_ptr[j];
- size = sizeof(training_1D_values);
- num_of_regs = ARRAY_SIZE(training_1D_values);
- /* Enable access to the internal CSRs */
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, 0x0);
- /* Enable clocks in case they were disabled. */
- phy_io_write16(phy, t_drtub |
- csr_ucclk_hclk_enables_addr, 0x3);
- if (train2d != 0) {
- /* Address to store training values is
- * to be appended for next PHY
- */
- phy_store = address_to_store + (j *
- (sizeof(training_1D_values) +
- sizeof(training_2D_values)));
- } else {
- phy_store = address_to_store + (j *
- (sizeof(training_1D_values)));
- }
- debug("Saving 1D Training reg val at: %d\n", phy_store);
- for (i = 0; i < num_of_regs; i++) {
- value = phy_io_read16(phy, training_1D_values[i].addr);
- #ifdef DEBUG_WARM_RESET
- debug("%d. Reg: %x, value: %x PHY: %p\n", i,
- training_1D_values[i].addr, value,
- phy_io_addr(phy,
- training_1D_values[i].addr));
- #endif
- training_1D_values[i].data = value;
- }
- /* Storing 1D training values on flash */
- ret = xspi_write(phy_store, (void *)training_1D_values, size);
- if (train2d != 0) {
- phy_store = phy_store+size;
- size = sizeof(training_2D_values);
- num_of_regs = ARRAY_SIZE(training_2D_values);
- debug("Saving 2D Training reg val at:%d\n", phy_store);
- for (i = 0; i < num_of_regs; i++) {
- value = phy_io_read16(phy,
- training_2D_values[i].addr);
- training_2D_values[i].data = value;
- #ifdef DEBUG_WARM_RESET
- debug("%d.2D addr:0x%x,val:0x%x,PHY:0x%p\n",
- i, training_2D_values[i].addr,
- value, phy_io_addr(phy,
- training_2D_values[i].addr));
- #endif
- }
- /* Storing 2D training values on flash */
- ret = xspi_write(phy_store, training_2D_values,
- size);
- }
- #ifdef NXP_APPLY_MAX_CDD
- /* Save DDR control register Timing CFG 0 and 4 */
- phy_store += size;
- size = sizeof(ddrctrl_regs);
- if (ret != 0) {
- ret = xspi_write(phy_store, ddrctrl_regs, size);
- }
- #endif
- /* Disable clocks in case they were disabled. */
- phy_io_write16(phy, t_drtub |
- csr_ucclk_hclk_enables_addr, 0x0);
- /* Disable access to the internal CSRs */
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, 0x1);
- }
- if (ret != 0) {
- return -EINVAL;
- }
- return 0;
- }
- int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore,
- uint32_t num_of_phy, int train2d
- #ifdef NXP_APPLY_MAX_CDD
- , struct ddr_ctrl_reg_values *ddrctrl_regs
- #endif
- )
- {
- uint16_t *phy = NULL;
- uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
- int i = 0, j = 0, ret = -EINVAL;
- debug("Restoring Training register values\n");
- for (j = 0; j < num_of_phy; j++) {
- phy = phy_ptr[j];
- size = sizeof(training_1D_values);
- num_of_regs = ARRAY_SIZE(training_1D_values);
- if (train2d != 0) {
- /* The address to restore training values is
- * to be appended for next PHY
- */
- phy_store = address_to_restore + (j *
- (sizeof(training_1D_values) +
- sizeof(training_2D_values)));
- } else {
- phy_store = address_to_restore + (j *
- (sizeof(training_1D_values)));
- }
- /* Enable access to the internal CSRs */
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, 0x0);
- /* Enable clocks in case they were disabled. */
- phy_io_write16(phy, t_drtub |
- csr_ucclk_hclk_enables_addr, 0x3);
- /* Reading 1D training values from flash*/
- ret = xspi_read(phy_store, (uint32_t *)training_1D_values,
- size);
- if (ret != 0) {
- #ifdef DEBUG_WARM_RESET
- debug("Unable to Read 1D training values %d\n",
- ret);
- #endif
- return -EINVAL;
- }
- debug("Restoring 1D Training reg val at:%08x\n", phy_store);
- for (i = 0; i < num_of_regs; i++) {
- phy_io_write16(phy, training_1D_values[i].addr,
- training_1D_values[i].data);
- #ifdef DEBUG_WARM_RESET
- debug("%d. Reg: %x, value: %x PHY: %p\n", i,
- training_1D_values[i].addr,
- training_1D_values[i].data,
- phy_io_addr(phy,
- training_1D_values[i].addr));
- #endif
- }
- if (train2d != 0) {
- phy_store = phy_store + size;
- size = sizeof(training_2D_values);
- num_of_regs = ARRAY_SIZE(training_2D_values);
- /* Reading 2D training values from flash */
- ret = xspi_read(phy_store,
- (uint32_t *)training_2D_values, size);
- if (ret != 0) {
- #ifdef DEBUG_WARM_RESET
- debug("Unable to Read 2D training values %d\n",
- ret);
- #endif
- return -EINVAL;
- }
- debug("Restoring 2D Training reg val at:%08x\n",
- phy_store);
- for (i = 0; i < num_of_regs; i++) {
- phy_io_write16(phy, training_2D_values[i].addr,
- training_2D_values[i].data);
- #ifdef DEBUG_WARM_RESET
- debug("%d. Reg: %x, value: %x PHY: %p\n", i,
- training_2D_values[i].addr,
- training_2D_values[i].data,
- phy_io_addr(phy,
- training_1D_values[i].addr));
- #endif
- }
- }
- #ifdef NXP_APPLY_MAX_CDD
- phy_store = phy_store + size;
- size = sizeof(ddrctrl_regs);
- ret = xspi_read(phy_store, (uint32_t *)ddrctrl_regs, size);
- #endif
- /* Disable clocks in case they were disabled. */
- phy_io_write16(phy, t_drtub |
- csr_ucclk_hclk_enables_addr, 0x0);
- /* Disable access to the internal CSRs */
- phy_io_write16(phy, t_apbonly |
- csr_micro_cont_mux_sel_addr, 0x1);
- }
- if (ret != 0) {
- return -EINVAL;
- }
- return 0;
- }
- #endif
- static void load_pieimage(uint16_t *phy,
- enum dimm_types dimm_type)
- {
- int i;
- int size;
- const struct pie *image = NULL;
- switch (dimm_type) {
- case UDIMM:
- case SODIMM:
- case NODIMM:
- image = pie_udimm;
- size = ARRAY_SIZE(pie_udimm);
- break;
- case RDIMM:
- image = pie_rdimm;
- size = ARRAY_SIZE(pie_rdimm);
- break;
- case LRDIMM:
- image = pie_lrdimm;
- size = ARRAY_SIZE(pie_lrdimm);
- break;
- default:
- printf("Unsupported DIMM type\n");
- break;
- }
- if (image != NULL) {
- for (i = 0; i < size; i++)
- phy_io_write16(phy, image[i].addr, image[i].data);
- }
- }
- static void prog_acsm_playback(uint16_t *phy,
- const struct input *input, const void *msg)
- {
- int vec;
- const struct ddr4r1d *msg_blk;
- uint16_t acsmplayback[2][3];
- uint32_t f0rc0a;
- uint32_t f0rc3x;
- uint32_t f0rc5x;
- if (input->basic.dimm_type != RDIMM) {
- return;
- }
- msg_blk = msg;
- f0rc0a = (msg_blk->f0rc0a_d0 & U(0xf)) | U(0xa0);
- f0rc3x = (msg_blk->f0rc3x_d0 & U(0xff)) | U(0x300);
- f0rc5x = (input->adv.phy_gen2_umctl_f0rc5x & U(0xff)) | U(0x500);
- acsmplayback[0][0] = U(0x3ff) & f0rc0a;
- acsmplayback[1][0] = (U(0x1c00) & f0rc0a) >> 10U;
- acsmplayback[0][1] = U(0x3ff) & f0rc3x;
- acsmplayback[1][1] = (U(0x1c00) & f0rc3x) >> 10U;
- acsmplayback[0][2] = U(0x3ff) & f0rc5x;
- acsmplayback[1][2] = (U(0x1c00) & f0rc5x) >> 10U;
- for (vec = 0; vec < 3; vec++) {
- phy_io_write16(phy, t_acsm | (csr_acsm_playback0x0_addr +
- (vec << 1)), acsmplayback[0][vec]);
- phy_io_write16(phy, t_acsm | (csr_acsm_playback1x0_addr +
- (vec << 1)), acsmplayback[1][vec]);
- }
- }
- static void prog_acsm_ctr(uint16_t *phy,
- const struct input *input)
- {
- if (input->basic.dimm_type != RDIMM) {
- return;
- }
- phy_io_write16(phy, t_acsm | csr_acsm_ctrl13_addr,
- 0xf << csr_acsm_cke_enb_lsb);
- phy_io_write16(phy, t_acsm | csr_acsm_ctrl0_addr,
- csr_acsm_par_mode_mask | csr_acsm_2t_mode_mask);
- }
- static void prog_cal_rate_run(uint16_t *phy,
- const struct input *input)
- {
- int cal_rate;
- int cal_interval;
- int cal_once;
- uint32_t addr;
- cal_interval = input->adv.cal_interval;
- cal_once = input->adv.cal_once;
- cal_rate = 0x1 << csr_cal_run_lsb |
- cal_once << csr_cal_once_lsb |
- cal_interval << csr_cal_interval_lsb;
- addr = t_master | csr_cal_rate_addr;
- phy_io_write16(phy, addr, cal_rate);
- }
- static void prog_seq0bdly0(uint16_t *phy,
- const struct input *input)
- {
- int ps_count[4];
- int frq;
- uint32_t addr;
- int lower_freq_opt = 0;
- __unused const soc_info_t *soc_info;
- frq = input->basic.frequency >> 1;
- ps_count[0] = frq >> 3; /* 0.5 * frq / 4*/
- if (input->basic.frequency < 400) {
- lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 7 : 3;
- } else if (input->basic.frequency < 533) {
- lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 14 : 11;
- }
- /* 1.0 * frq / 4 - lower_freq */
- ps_count[1] = (frq >> 2) - lower_freq_opt;
- ps_count[2] = (frq << 1) + (frq >> 1); /* 10.0 * frq / 4 */
- #ifdef DDR_PLL_FIX
- soc_info = get_soc_info();
- if (soc_info->svr_reg.bf.maj_ver == 1) {
- ps_count[0] = 0x520; /* seq0bdly0 */
- ps_count[1] = 0xa41; /* seq0bdly1 */
- ps_count[2] = 0x668a; /* seq0bdly2 */
- }
- #endif
- if (frq > 266) {
- ps_count[3] = 44;
- } else if (frq > 200) {
- ps_count[3] = 33;
- } else {
- ps_count[3] = 16;
- }
- addr = t_master | csr_seq0bdly0_addr;
- phy_io_write16(phy, addr, ps_count[0]);
- debug("seq0bdly0 = 0x%x\n", phy_io_read16(phy, addr));
- addr = t_master | csr_seq0bdly1_addr;
- phy_io_write16(phy, addr, ps_count[1]);
- debug("seq0bdly1 = 0x%x\n", phy_io_read16(phy, addr));
- addr = t_master | csr_seq0bdly2_addr;
- phy_io_write16(phy, addr, ps_count[2]);
- debug("seq0bdly2 = 0x%x\n", phy_io_read16(phy, addr));
- addr = t_master | csr_seq0bdly3_addr;
- phy_io_write16(phy, addr, ps_count[3]);
- debug("seq0bdly3 = 0x%x\n", phy_io_read16(phy, addr));
- }
- /* Only RDIMM requires msg_blk */
- static void i_load_pie(uint16_t **phy_ptr,
- const struct input *input,
- const void *msg)
- {
- int i;
- uint16_t *phy;
- for (i = 0; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- phy_io_write16(phy,
- t_apbonly | csr_micro_cont_mux_sel_addr,
- 0U);
- load_pieimage(phy, input->basic.dimm_type);
- prog_seq0bdly0(phy, input);
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag0_addr,
- U(0x0000));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag1_addr,
- U(0x0173));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag2_addr,
- U(0x0060));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag3_addr,
- U(0x6110));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag4_addr,
- U(0x2152));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag5_addr,
- U(0xdfbd));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag6_addr,
- input->basic.dimm_type == RDIMM &&
- input->adv.phy_gen2_umctl_opt == 1U ?
- U(0x6000) : U(0xffff));
- phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag7_addr,
- U(0x6152));
- prog_acsm_playback(phy, input, msg); /* rdimm */
- prog_acsm_ctr(phy, input); /* rdimm */
- phy_io_write16(phy, t_master | csr_cal_zap_addr, U(0x1));
- prog_cal_rate_run(phy, input);
- phy_io_write16(phy, t_drtub | csr_ucclk_hclk_enables_addr,
- input->basic.dimm_type == RDIMM ? U(0x2) : 0U);
- phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 1U);
- }
- }
- static void phy_gen2_init_input(struct input *input)
- {
- int i;
- input->adv.dram_byte_swap = 0;
- input->adv.ext_cal_res_val = 0;
- input->adv.tx_slew_rise_dq = 0xf;
- input->adv.tx_slew_fall_dq = 0xf;
- input->adv.tx_slew_rise_ac = 0xf;
- input->adv.tx_slew_fall_ac = 0xf;
- input->adv.mem_alert_en = 0;
- input->adv.mem_alert_puimp = 5;
- input->adv.mem_alert_vref_level = 0x29;
- input->adv.mem_alert_sync_bypass = 0;
- input->adv.cal_interval = 0x9;
- input->adv.cal_once = 0;
- input->adv.dis_dyn_adr_tri = 0;
- input->adv.is2ttiming = 0;
- input->adv.d4rx_preamble_length = 0;
- input->adv.d4tx_preamble_length = 0;
- for (i = 0; i < 7; i++) {
- debug("mr[%d] = 0x%x\n", i, input->mr[i]);
- }
- debug("input->cs_d0 = 0x%x\n", input->cs_d0);
- debug("input->cs_d1 = 0x%x\n", input->cs_d1);
- debug("input->mirror = 0x%x\n", input->mirror);
- debug("PHY ODT impedance = %d ohm\n", input->adv.odtimpedance);
- debug("PHY DQ driver impedance = %d ohm\n", input->adv.tx_impedance);
- debug("PHY Addr driver impedance = %d ohm\n", input->adv.atx_impedance);
- for (i = 0; i < 4; i++) {
- debug("odt[%d] = 0x%x\n", i, input->odt[i]);
- }
- if (input->basic.dimm_type == RDIMM) {
- for (i = 0; i < 16; i++) {
- debug("input->rcw[%d] = 0x%x\n", i, input->rcw[i]);
- }
- debug("input->rcw3x = 0x%x\n", input->rcw3x);
- }
- }
- /*
- * All protocols share the same base structure of message block.
- * RDIMM and LRDIMM have more entries defined than UDIMM.
- * Create message blocks for 1D and 2D training.
- * Update len with message block size.
- */
- static int phy_gen2_msg_init(void *msg_1d,
- void *msg_2d,
- const struct input *input)
- {
- struct ddr4u1d *msg_blk = msg_1d;
- struct ddr4u2d *msg_blk_2d = msg_2d;
- struct ddr4r1d *msg_blk_r;
- struct ddr4lr1d *msg_blk_lr;
- switch (input->basic.dimm_type) {
- case UDIMM:
- case SODIMM:
- case NODIMM:
- msg_blk->dram_type = U(0x2);
- break;
- case RDIMM:
- msg_blk->dram_type = U(0x4);
- break;
- case LRDIMM:
- msg_blk->dram_type = U(0x5);
- break;
- default:
- ERROR("Unsupported DIMM type\n");
- return -EINVAL;
- }
- msg_blk->pstate = 0U;
- /*Enable quickRd2D, a substage of read deskew, to 1D training.*/
- msg_blk->reserved00 = U(0x20);
- /*Enable High-Effort WrDQ1D.*/
- msg_blk->reserved00 |= U(0x40);
- /* Enable 1D extra effort training.*/
- msg_blk->reserved1c[3] = U(0x3);
- if (input->basic.dimm_type == LRDIMM) {
- msg_blk->sequence_ctrl = U(0x3f1f);
- } else {
- msg_blk->sequence_ctrl = U(0x031f);
- }
- msg_blk->phy_config_override = 0U;
- #ifdef DDR_PHY_DEBUG
- msg_blk->hdt_ctrl = U(0x5);
- #else
- msg_blk->hdt_ctrl = U(0xc9);
- #endif
- msg_blk->msg_misc = U(0x0);
- msg_blk->dfimrlmargin = U(0x1);
- msg_blk->phy_vref = input->vref ? input->vref : U(0x61);
- msg_blk->cs_present = input->cs_d0 | input->cs_d1;
- msg_blk->cs_present_d0 = input->cs_d0;
- msg_blk->cs_present_d1 = input->cs_d1;
- if (input->mirror != 0) {
- msg_blk->addr_mirror = U(0x0a); /* odd CS are mirrored */
- }
- msg_blk->share2dvref_result = 1U;
- msg_blk->acsm_odt_ctrl0 = input->odt[0];
- msg_blk->acsm_odt_ctrl1 = input->odt[1];
- msg_blk->acsm_odt_ctrl2 = input->odt[2];
- msg_blk->acsm_odt_ctrl3 = input->odt[3];
- msg_blk->enabled_dqs = (input->basic.num_active_dbyte_dfi0 +
- input->basic.num_active_dbyte_dfi1) * 8;
- msg_blk->x16present = input->basic.dram_data_width == 0x10 ?
- msg_blk->cs_present : 0;
- msg_blk->d4misc = U(0x1);
- msg_blk->cs_setup_gddec = U(0x1);
- msg_blk->rtt_nom_wr_park0 = 0U;
- msg_blk->rtt_nom_wr_park1 = 0U;
- msg_blk->rtt_nom_wr_park2 = 0U;
- msg_blk->rtt_nom_wr_park3 = 0U;
- msg_blk->rtt_nom_wr_park4 = 0U;
- msg_blk->rtt_nom_wr_park5 = 0U;
- msg_blk->rtt_nom_wr_park6 = 0U;
- msg_blk->rtt_nom_wr_park7 = 0U;
- msg_blk->mr0 = input->mr[0];
- msg_blk->mr1 = input->mr[1];
- msg_blk->mr2 = input->mr[2];
- msg_blk->mr3 = input->mr[3];
- msg_blk->mr4 = input->mr[4];
- msg_blk->mr5 = input->mr[5];
- msg_blk->mr6 = input->mr[6];
- if ((msg_blk->mr4 & U(0x1c0)) != 0U) {
- ERROR("Setting DRAM CAL mode is not supported\n");
- }
- msg_blk->alt_cas_l = 0U;
- msg_blk->alt_wcas_l = 0U;
- msg_blk->dramfreq = input->basic.frequency * 2U;
- msg_blk->pll_bypass_en = input->basic.pll_bypass;
- msg_blk->dfi_freq_ratio = input->basic.dfi_freq_ratio == 0U ? 1U :
- input->basic.dfi_freq_ratio == 1U ? 2U :
- 4U;
- msg_blk->bpznres_val = input->adv.ext_cal_res_val;
- msg_blk->disabled_dbyte = 0U;
- debug("msg_blk->dram_type = 0x%x\n", msg_blk->dram_type);
- debug("msg_blk->sequence_ctrl = 0x%x\n", msg_blk->sequence_ctrl);
- debug("msg_blk->phy_cfg = 0x%x\n", msg_blk->phy_cfg);
- debug("msg_blk->x16present = 0x%x\n", msg_blk->x16present);
- debug("msg_blk->dramfreq = 0x%x\n", msg_blk->dramfreq);
- debug("msg_blk->pll_bypass_en = 0x%x\n", msg_blk->pll_bypass_en);
- debug("msg_blk->dfi_freq_ratio = 0x%x\n", msg_blk->dfi_freq_ratio);
- debug("msg_blk->phy_odt_impedance = 0x%x\n",
- msg_blk->phy_odt_impedance);
- debug("msg_blk->phy_drv_impedance = 0x%x\n",
- msg_blk->phy_drv_impedance);
- debug("msg_blk->bpznres_val = 0x%x\n", msg_blk->bpznres_val);
- debug("msg_blk->enabled_dqs = 0x%x\n", msg_blk->enabled_dqs);
- debug("msg_blk->acsm_odt_ctrl0 = 0x%x\n", msg_blk->acsm_odt_ctrl0);
- debug("msg_blk->acsm_odt_ctrl1 = 0x%x\n", msg_blk->acsm_odt_ctrl1);
- debug("msg_blk->acsm_odt_ctrl2 = 0x%x\n", msg_blk->acsm_odt_ctrl2);
- debug("msg_blk->acsm_odt_ctrl3 = 0x%x\n", msg_blk->acsm_odt_ctrl3);
- /* RDIMM only */
- if (input->basic.dimm_type == RDIMM ||
- input->basic.dimm_type == LRDIMM) {
- msg_blk_r = (struct ddr4r1d *)msg_blk;
- if (msg_blk_r->cs_present_d0 != 0U) {
- msg_blk_r->f0rc00_d0 = input->rcw[0];
- msg_blk_r->f0rc01_d0 = input->rcw[1];
- msg_blk_r->f0rc02_d0 = input->rcw[2];
- msg_blk_r->f0rc03_d0 = input->rcw[3];
- msg_blk_r->f0rc04_d0 = input->rcw[4];
- msg_blk_r->f0rc05_d0 = input->rcw[5];
- msg_blk_r->f0rc06_d0 = input->rcw[6];
- msg_blk_r->f0rc07_d0 = input->rcw[7];
- msg_blk_r->f0rc08_d0 = input->rcw[8];
- msg_blk_r->f0rc09_d0 = input->rcw[9];
- msg_blk_r->f0rc0a_d0 = input->rcw[10];
- msg_blk_r->f0rc0b_d0 = input->rcw[11];
- msg_blk_r->f0rc0c_d0 = input->rcw[12];
- msg_blk_r->f0rc0d_d0 = input->rcw[13];
- msg_blk_r->f0rc0e_d0 = input->rcw[14];
- msg_blk_r->f0rc0f_d0 = input->rcw[15];
- msg_blk_r->f0rc3x_d0 = input->rcw3x;
- }
- if (msg_blk_r->cs_present_d1 != 0) {
- msg_blk_r->f0rc00_d1 = input->rcw[0];
- msg_blk_r->f0rc01_d1 = input->rcw[1];
- msg_blk_r->f0rc02_d1 = input->rcw[2];
- msg_blk_r->f0rc03_d1 = input->rcw[3];
- msg_blk_r->f0rc04_d1 = input->rcw[4];
- msg_blk_r->f0rc05_d1 = input->rcw[5];
- msg_blk_r->f0rc06_d1 = input->rcw[6];
- msg_blk_r->f0rc07_d1 = input->rcw[7];
- msg_blk_r->f0rc08_d1 = input->rcw[8];
- msg_blk_r->f0rc09_d1 = input->rcw[9];
- msg_blk_r->f0rc0a_d1 = input->rcw[10];
- msg_blk_r->f0rc0b_d1 = input->rcw[11];
- msg_blk_r->f0rc0c_d1 = input->rcw[12];
- msg_blk_r->f0rc0d_d1 = input->rcw[13];
- msg_blk_r->f0rc0e_d1 = input->rcw[14];
- msg_blk_r->f0rc0f_d1 = input->rcw[15];
- msg_blk_r->f0rc3x_d1 = input->rcw3x;
- }
- if (input->basic.dimm_type == LRDIMM) {
- msg_blk_lr = (struct ddr4lr1d *)msg_blk;
- msg_blk_lr->bc0a_d0 = msg_blk_lr->f0rc0a_d0;
- msg_blk_lr->bc0a_d1 = msg_blk_lr->f0rc0a_d1;
- msg_blk_lr->f0bc6x_d0 = msg_blk_lr->f0rc3x_d0;
- msg_blk_lr->f0bc6x_d1 = msg_blk_lr->f0rc3x_d1;
- }
- }
- /* below is different for 1D and 2D message block */
- if (input->basic.train2d != 0) {
- memcpy(msg_blk_2d, msg_blk, sizeof(struct ddr4u1d));
- /*High-Effort WrDQ1D is applicable to 2D traning also*/
- msg_blk_2d->reserved00 |= U(0x40);
- msg_blk_2d->sequence_ctrl = U(0x0061);
- msg_blk_2d->rx2d_train_opt = 0U;
- msg_blk_2d->tx2d_train_opt = 0U;
- msg_blk_2d->share2dvref_result = 1U;
- msg_blk_2d->delay_weight2d = U(0x20);
- msg_blk_2d->voltage_weight2d = U(0x80);
- debug("rx2d_train_opt %d, tx2d_train_opt %d\n",
- msg_blk_2d->rx2d_train_opt,
- msg_blk_2d->tx2d_train_opt);
- }
- msg_blk->phy_cfg = (((msg_blk->mr3 & U(0x8)) != 0U) ||
- ((msg_blk_2d->mr3 & 0x8) != 0U)) ? 0U
- : input->adv.is2ttiming;
- return 0;
- }
- static void prog_tx_pre_drv_mode(uint16_t *phy,
- const struct input *input)
- {
- int lane, byte, b_addr, c_addr, p_addr;
- int tx_slew_rate, tx_pre_p, tx_pre_n;
- int tx_pre_drv_mode = 0x2;
- uint32_t addr;
- /* Program TxPreDrvMode with 0x2 */
- /* FIXME: TxPreDrvMode depends on DramType? */
- tx_pre_p = input->adv.tx_slew_rise_dq;
- tx_pre_n = input->adv.tx_slew_fall_dq;
- tx_slew_rate = tx_pre_drv_mode << csr_tx_pre_drv_mode_lsb |
- tx_pre_p << csr_tx_pre_p_lsb |
- tx_pre_n << csr_tx_pre_n_lsb;
- p_addr = 0;
- for (byte = 0; byte < input->basic.num_dbyte; byte++) {
- c_addr = byte << 12;
- for (lane = 0; lane <= 1; lane++) {
- b_addr = lane << 8;
- addr = p_addr | t_dbyte | c_addr | b_addr |
- csr_tx_slew_rate_addr;
- phy_io_write16(phy, addr, tx_slew_rate);
- }
- }
- }
- static void prog_atx_pre_drv_mode(uint16_t *phy,
- const struct input *input)
- {
- int anib, c_addr;
- int atx_slew_rate, atx_pre_p, atx_pre_n, atx_pre_drv_mode,
- ck_anib_inst[2];
- uint32_t addr;
- atx_pre_n = input->adv.tx_slew_fall_ac;
- atx_pre_p = input->adv.tx_slew_rise_ac;
- if (input->basic.num_anib == 8) {
- ck_anib_inst[0] = 1;
- ck_anib_inst[1] = 1;
- } else if (input->basic.num_anib == 10 || input->basic.num_anib == 12 ||
- input->basic.num_anib == 13) {
- ck_anib_inst[0] = 4;
- ck_anib_inst[1] = 5;
- } else {
- ERROR("Invalid number of aNIBs: %d\n", input->basic.num_anib);
- return;
- }
- for (anib = 0; anib < input->basic.num_anib; anib++) {
- c_addr = anib << 12;
- if (anib == ck_anib_inst[0] || anib == ck_anib_inst[1]) {
- atx_pre_drv_mode = 0;
- } else {
- atx_pre_drv_mode = 3;
- }
- atx_slew_rate = atx_pre_drv_mode << csr_atx_pre_drv_mode_lsb |
- atx_pre_n << csr_atx_pre_n_lsb |
- atx_pre_p << csr_atx_pre_p_lsb;
- addr = t_anib | c_addr | csr_atx_slew_rate_addr;
- phy_io_write16(phy, addr, atx_slew_rate);
- }
- }
- static void prog_enable_cs_multicast(uint16_t *phy,
- const struct input *input)
- {
- uint32_t addr = t_master | csr_enable_cs_multicast_addr;
- if (input->basic.dimm_type != RDIMM &&
- input->basic.dimm_type != LRDIMM) {
- return;
- }
- phy_io_write16(phy, addr, input->adv.cast_cs_to_cid);
- }
- static void prog_dfi_rd_data_cs_dest_map(uint16_t *phy,
- unsigned int ip_rev,
- const struct input *input,
- const struct ddr4lr1d *msg)
- {
- const struct ddr4lr1d *msg_blk;
- uint16_t dfi_xxdestm0 = 0U;
- uint16_t dfi_xxdestm1 = 0U;
- uint16_t dfi_xxdestm2 = 0U;
- uint16_t dfi_xxdestm3 = 0U;
- uint16_t dfi_rd_data_cs_dest_map;
- uint16_t dfi_wr_data_cs_dest_map;
- __unused const soc_info_t *soc_info;
- #ifdef ERRATA_DDR_A011396
- /* Only apply to DDRC 5.05.00 */
- soc_info = get_soc_info();
- if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) {
- phy_io_write16(phy,
- t_master | csr_dfi_rd_data_cs_dest_map_addr,
- 0U);
- return;
- }
- #endif
- msg_blk = msg;
- switch (input->basic.dimm_type) {
- case UDIMM:
- case SODIMM:
- case NODIMM:
- if ((msg_blk->msg_misc & U(0x40)) != 0U) {
- dfi_rd_data_cs_dest_map = U(0xa0);
- dfi_wr_data_cs_dest_map = U(0xa0);
- phy_io_write16(phy,
- t_master | csr_dfi_rd_data_cs_dest_map_addr,
- dfi_rd_data_cs_dest_map);
- phy_io_write16(phy,
- t_master | csr_dfi_wr_data_cs_dest_map_addr,
- dfi_wr_data_cs_dest_map);
- }
- break;
- case LRDIMM:
- if (msg->cs_present_d1 != 0U) {
- dfi_xxdestm2 = 1U;
- dfi_xxdestm3 = 1U;
- }
- dfi_rd_data_cs_dest_map =
- dfi_xxdestm0 << csr_dfi_rd_destm0_lsb |
- dfi_xxdestm1 << csr_dfi_rd_destm1_lsb |
- dfi_xxdestm2 << csr_dfi_rd_destm2_lsb |
- dfi_xxdestm3 << csr_dfi_rd_destm3_lsb;
- dfi_wr_data_cs_dest_map =
- dfi_xxdestm0 << csr_dfi_wr_destm0_lsb |
- dfi_xxdestm1 << csr_dfi_wr_destm1_lsb |
- dfi_xxdestm2 << csr_dfi_wr_destm2_lsb |
- dfi_xxdestm3 << csr_dfi_wr_destm3_lsb;
- phy_io_write16(phy, t_master | csr_dfi_rd_data_cs_dest_map_addr,
- dfi_rd_data_cs_dest_map);
- phy_io_write16(phy, t_master | csr_dfi_wr_data_cs_dest_map_addr,
- dfi_wr_data_cs_dest_map);
- break;
- default:
- break;
- }
- }
- static void prog_pll_ctrl(uint16_t *phy,
- const struct input *input)
- {
- uint32_t addr;
- int pll_ctrl1 = 0x21; /* 000100001b */
- int pll_ctrl4 = 0x17f; /* 101111111b */
- int pll_test_mode = 0x24; /* 00100100b */
- addr = t_master | csr_pll_ctrl1_addr;
- phy_io_write16(phy, addr, pll_ctrl1);
- debug("pll_ctrl1 = 0x%x\n", phy_io_read16(phy, addr));
- addr = t_master | csr_pll_test_mode_addr;
- phy_io_write16(phy, addr, pll_test_mode);
- debug("pll_test_mode = 0x%x\n", phy_io_read16(phy, addr));
- addr = t_master | csr_pll_ctrl4_addr;
- phy_io_write16(phy, addr, pll_ctrl4);
- debug("pll_ctrl4 = 0x%x\n", phy_io_read16(phy, addr));
- }
- static void prog_pll_ctrl2(uint16_t *phy,
- const struct input *input)
- {
- int pll_ctrl2;
- uint32_t addr = t_master | csr_pll_ctrl2_addr;
- if (input->basic.frequency / 2 < 235) {
- pll_ctrl2 = 0x7;
- } else if (input->basic.frequency / 2 < 313) {
- pll_ctrl2 = 0x6;
- } else if (input->basic.frequency / 2 < 469) {
- pll_ctrl2 = 0xb;
- } else if (input->basic.frequency / 2 < 625) {
- pll_ctrl2 = 0xa;
- } else if (input->basic.frequency / 2 < 938) {
- pll_ctrl2 = 0x19;
- } else if (input->basic.frequency / 2 < 1067) {
- pll_ctrl2 = 0x18;
- } else {
- pll_ctrl2 = 0x19;
- }
- phy_io_write16(phy, addr, pll_ctrl2);
- debug("pll_ctrl2 = 0x%x\n", phy_io_read16(phy, addr));
- }
- static void prog_dll_lck_param(uint16_t *phy, const struct input *input)
- {
- uint32_t addr = t_master | csr_dll_lockparam_addr;
- phy_io_write16(phy, addr, U(0x212));
- debug("dll_lck_param = 0x%x\n", phy_io_read16(phy, addr));
- }
- static void prog_dll_gain_ctl(uint16_t *phy, const struct input *input)
- {
- uint32_t addr = t_master | csr_dll_gain_ctl_addr;
- phy_io_write16(phy, addr, U(0x61));
- debug("dll_gain_ctl = 0x%x\n", phy_io_read16(phy, addr));
- }
- static void prog_pll_pwr_dn(uint16_t *phy,
- const struct input *input)
- {
- uint32_t addr;
- addr = t_master | csr_pll_pwr_dn_addr;
- phy_io_write16(phy, addr, 0U);
- debug("pll_pwrdn = 0x%x\n", phy_io_read16(phy, addr));
- }
- static void prog_ard_ptr_init_val(uint16_t *phy,
- const struct input *input)
- {
- int ard_ptr_init_val;
- uint32_t addr = t_master | csr_ard_ptr_init_val_addr;
- if (input->basic.frequency >= 933) {
- ard_ptr_init_val = 0x2;
- } else {
- ard_ptr_init_val = 0x1;
- }
- phy_io_write16(phy, addr, ard_ptr_init_val);
- }
- static void prog_dqs_preamble_control(uint16_t *phy,
- const struct input *input)
- {
- int data;
- uint32_t addr = t_master | csr_dqs_preamble_control_addr;
- const int wdqsextension = 0;
- const int lp4sttc_pre_bridge_rx_en = 0;
- const int lp4postamble_ext = 0;
- const int lp4tgl_two_tck_tx_dqs_pre = 0;
- const int position_dfe_init = 2;
- const int dll_rx_preamble_mode = 1;
- int two_tck_tx_dqs_pre = input->adv.d4tx_preamble_length;
- int two_tck_rx_dqs_pre = input->adv.d4rx_preamble_length;
- data = wdqsextension << csr_wdqsextension_lsb |
- lp4sttc_pre_bridge_rx_en << csr_lp4sttc_pre_bridge_rx_en_lsb |
- lp4postamble_ext << csr_lp4postamble_ext_lsb |
- lp4tgl_two_tck_tx_dqs_pre << csr_lp4tgl_two_tck_tx_dqs_pre_lsb |
- position_dfe_init << csr_position_dfe_init_lsb |
- two_tck_tx_dqs_pre << csr_two_tck_tx_dqs_pre_lsb |
- two_tck_rx_dqs_pre << csr_two_tck_rx_dqs_pre_lsb;
- phy_io_write16(phy, addr, data);
- data = dll_rx_preamble_mode << csr_dll_rx_preamble_mode_lsb;
- addr = t_master | csr_dbyte_dll_mode_cntrl_addr;
- phy_io_write16(phy, addr, data);
- }
- static void prog_proc_odt_time_ctl(uint16_t *phy,
- const struct input *input)
- {
- int proc_odt_time_ctl;
- uint32_t addr = t_master | csr_proc_odt_time_ctl_addr;
- if (input->adv.wdqsext != 0) {
- proc_odt_time_ctl = 0x3;
- } else if (input->basic.frequency <= 933) {
- proc_odt_time_ctl = 0xa;
- } else if (input->basic.frequency <= 1200) {
- if (input->adv.d4rx_preamble_length == 1) {
- proc_odt_time_ctl = 0x2;
- } else {
- proc_odt_time_ctl = 0x6;
- }
- } else {
- if (input->adv.d4rx_preamble_length == 1) {
- proc_odt_time_ctl = 0x3;
- } else {
- proc_odt_time_ctl = 0x7;
- }
- }
- phy_io_write16(phy, addr, proc_odt_time_ctl);
- }
- static const struct impedance_mapping map[] = {
- { 29, 0x3f },
- { 31, 0x3e },
- { 33, 0x3b },
- { 36, 0x3a },
- { 39, 0x39 },
- { 42, 0x38 },
- { 46, 0x1b },
- { 51, 0x1a },
- { 57, 0x19 },
- { 64, 0x18 },
- { 74, 0x0b },
- { 88, 0x0a },
- { 108, 0x09 },
- { 140, 0x08 },
- { 200, 0x03 },
- { 360, 0x02 },
- { 481, 0x01 },
- {}
- };
- static int map_impedance(int strength)
- {
- const struct impedance_mapping *tbl = map;
- int val = 0;
- if (strength == 0) {
- return 0;
- }
- while (tbl->ohm != 0U) {
- if (strength < tbl->ohm) {
- val = tbl->code;
- break;
- }
- tbl++;
- }
- return val;
- }
- static int map_odtstren_p(int strength, int hard_macro_ver)
- {
- int val = -1;
- if (hard_macro_ver == 4) {
- if (strength == 0) {
- val = 0;
- } else if (strength == 120) {
- val = 0x8;
- } else if (strength == 60) {
- val = 0x18;
- } else if (strength == 40) {
- val = 0x38;
- } else {
- printf("error: unsupported ODTStrenP %d\n", strength);
- }
- } else {
- val = map_impedance(strength);
- }
- return val;
- }
- static void prog_tx_odt_drv_stren(uint16_t *phy,
- const struct input *input)
- {
- int lane, byte, b_addr, c_addr;
- int tx_odt_drv_stren;
- int odtstren_p, odtstren_n;
- uint32_t addr;
- odtstren_p = map_odtstren_p(input->adv.odtimpedance,
- input->basic.hard_macro_ver);
- if (odtstren_p < 0) {
- return;
- }
- odtstren_n = 0; /* always high-z */
- tx_odt_drv_stren = odtstren_n << csr_odtstren_n_lsb | odtstren_p;
- for (byte = 0; byte < input->basic.num_dbyte; byte++) {
- c_addr = byte << 12;
- for (lane = 0; lane <= 1; lane++) {
- b_addr = lane << 8;
- addr = t_dbyte | c_addr | b_addr |
- csr_tx_odt_drv_stren_addr;
- phy_io_write16(phy, addr, tx_odt_drv_stren);
- }
- }
- }
- static int map_drvstren_fsdq_p(int strength, int hard_macro_ver)
- {
- int val = -1;
- if (hard_macro_ver == 4) {
- if (strength == 0) {
- val = 0x07;
- } else if (strength == 120) {
- val = 0x0F;
- } else if (strength == 60) {
- val = 0x1F;
- } else if (strength == 40) {
- val = 0x3F;
- } else {
- printf("error: unsupported drv_stren_fSDq_p %d\n",
- strength);
- }
- } else {
- val = map_impedance(strength);
- }
- return val;
- }
- static int map_drvstren_fsdq_n(int strength, int hard_macro_ver)
- {
- int val = -1;
- if (hard_macro_ver == 4) {
- if (strength == 0) {
- val = 0x00;
- } else if (strength == 120) {
- val = 0x08;
- } else if (strength == 60) {
- val = 0x18;
- } else if (strength == 40) {
- val = 0x38;
- } else {
- printf("error: unsupported drvStrenFSDqN %d\n",
- strength);
- }
- } else {
- val = map_impedance(strength);
- }
- return val;
- }
- static void prog_tx_impedance_ctrl1(uint16_t *phy,
- const struct input *input)
- {
- int lane, byte, b_addr, c_addr;
- int tx_impedance_ctrl1;
- int drv_stren_fsdq_p, drv_stren_fsdq_n;
- uint32_t addr;
- drv_stren_fsdq_p = map_drvstren_fsdq_p(input->adv.tx_impedance,
- input->basic.hard_macro_ver);
- drv_stren_fsdq_n = map_drvstren_fsdq_n(input->adv.tx_impedance,
- input->basic.hard_macro_ver);
- tx_impedance_ctrl1 = drv_stren_fsdq_n << csr_drv_stren_fsdq_n_lsb |
- drv_stren_fsdq_p << csr_drv_stren_fsdq_p_lsb;
- for (byte = 0; byte < input->basic.num_dbyte; byte++) {
- c_addr = byte << 12;
- for (lane = 0; lane <= 1; lane++) {
- b_addr = lane << 8;
- addr = t_dbyte | c_addr | b_addr |
- csr_tx_impedance_ctrl1_addr;
- phy_io_write16(phy, addr, tx_impedance_ctrl1);
- }
- }
- }
- static int map_adrv_stren_p(int strength, int hard_macro_ver)
- {
- int val = -1;
- if (hard_macro_ver == 4) {
- if (strength == 120) {
- val = 0x1c;
- } else if (strength == 60) {
- val = 0x1d;
- } else if (strength == 40) {
- val = 0x1f;
- } else {
- printf("error: unsupported aDrv_stren_p %d\n",
- strength);
- }
- } else {
- if (strength == 120) {
- val = 0x00;
- } else if (strength == 60) {
- val = 0x01;
- } else if (strength == 40) {
- val = 0x03;
- } else if (strength == 30) {
- val = 0x07;
- } else if (strength == 24) {
- val = 0x0f;
- } else if (strength == 20) {
- val = 0x1f;
- } else {
- printf("error: unsupported aDrv_stren_p %d\n",
- strength);
- }
- }
- return val;
- }
- static int map_adrv_stren_n(int strength, int hard_macro_ver)
- {
- int val = -1;
- if (hard_macro_ver == 4) {
- if (strength == 120) {
- val = 0x00;
- } else if (strength == 60) {
- val = 0x01;
- } else if (strength == 40) {
- val = 0x03;
- } else {
- printf("Error: unsupported ADrvStrenP %d\n", strength);
- }
- } else {
- if (strength == 120) {
- val = 0x00;
- } else if (strength == 60) {
- val = 0x01;
- } else if (strength == 40) {
- val = 0x03;
- } else if (strength == 30) {
- val = 0x07;
- } else if (strength == 24) {
- val = 0x0f;
- } else if (strength == 20) {
- val = 0x1f;
- } else {
- printf("Error: unsupported ADrvStrenP %d\n", strength);
- }
- }
- return val;
- }
- static void prog_atx_impedance(uint16_t *phy,
- const struct input *input)
- {
- int anib, c_addr;
- int atx_impedance;
- int adrv_stren_p;
- int adrv_stren_n;
- uint32_t addr;
- if (input->basic.hard_macro_ver == 4 &&
- input->adv.atx_impedance == 20) {
- printf("Error:ATxImpedance has to be 40 for HardMacroVer 4\n");
- return;
- }
- adrv_stren_p = map_adrv_stren_p(input->adv.atx_impedance,
- input->basic.hard_macro_ver);
- adrv_stren_n = map_adrv_stren_n(input->adv.atx_impedance,
- input->basic.hard_macro_ver);
- atx_impedance = adrv_stren_n << csr_adrv_stren_n_lsb |
- adrv_stren_p << csr_adrv_stren_p_lsb;
- for (anib = 0; anib < input->basic.num_anib; anib++) {
- c_addr = anib << 12;
- addr = t_anib | c_addr | csr_atx_impedance_addr;
- phy_io_write16(phy, addr, atx_impedance);
- }
- }
- static void prog_dfi_mode(uint16_t *phy,
- const struct input *input)
- {
- int dfi_mode;
- uint32_t addr;
- if (input->basic.dfi1exists == 1) {
- dfi_mode = 0x5; /* DFI1 exists but disabled */
- } else {
- dfi_mode = 0x1; /* DFI1 does not physically exists */
- }
- addr = t_master | csr_dfi_mode_addr;
- phy_io_write16(phy, addr, dfi_mode);
- }
- static void prog_acx4_anib_dis(uint16_t *phy, const struct input *input)
- {
- uint32_t addr;
- addr = t_master | csr_acx4_anib_dis_addr;
- phy_io_write16(phy, addr, 0x0);
- debug("%s 0x%x\n", __func__, phy_io_read16(phy, addr));
- }
- static void prog_dfi_camode(uint16_t *phy,
- const struct input *input)
- {
- int dfi_camode = 2;
- uint32_t addr = t_master | csr_dfi_camode_addr;
- phy_io_write16(phy, addr, dfi_camode);
- }
- static void prog_cal_drv_str0(uint16_t *phy,
- const struct input *input)
- {
- int cal_drv_str0;
- int cal_drv_str_pd50;
- int cal_drv_str_pu50;
- uint32_t addr;
- cal_drv_str_pu50 = input->adv.ext_cal_res_val;
- cal_drv_str_pd50 = cal_drv_str_pu50;
- cal_drv_str0 = cal_drv_str_pu50 << csr_cal_drv_str_pu50_lsb |
- cal_drv_str_pd50;
- addr = t_master | csr_cal_drv_str0_addr;
- phy_io_write16(phy, addr, cal_drv_str0);
- }
- static void prog_cal_uclk_info(uint16_t *phy,
- const struct input *input)
- {
- int cal_uclk_ticks_per1u_s;
- uint32_t addr;
- cal_uclk_ticks_per1u_s = input->basic.frequency >> 1;
- if (cal_uclk_ticks_per1u_s < 24) {
- cal_uclk_ticks_per1u_s = 24;
- }
- addr = t_master | csr_cal_uclk_info_addr;
- phy_io_write16(phy, addr, cal_uclk_ticks_per1u_s);
- }
- static void prog_cal_rate(uint16_t *phy,
- const struct input *input)
- {
- int cal_rate;
- int cal_interval;
- int cal_once;
- uint32_t addr;
- cal_interval = input->adv.cal_interval;
- cal_once = input->adv.cal_once;
- cal_rate = cal_once << csr_cal_once_lsb |
- cal_interval << csr_cal_interval_lsb;
- addr = t_master | csr_cal_rate_addr;
- phy_io_write16(phy, addr, cal_rate);
- }
- static void prog_vref_in_global(uint16_t *phy,
- const struct input *input,
- const struct ddr4u1d *msg)
- {
- int vref_in_global;
- int global_vref_in_dac = 0;
- int global_vref_in_sel = 0;
- uint32_t addr;
- /*
- * phy_vref_prcnt = msg->phy_vref / 128.0
- * global_vref_in_dac = (phy_vref_prcnt - 0.345) / 0.005;
- */
- global_vref_in_dac = (msg->phy_vref * 1000 - 345 * 128 + 320) /
- (5 * 128);
- vref_in_global = global_vref_in_dac << csr_global_vref_in_dac_lsb |
- global_vref_in_sel;
- addr = t_master | csr_vref_in_global_addr;
- phy_io_write16(phy, addr, vref_in_global);
- }
- static void prog_dq_dqs_rcv_cntrl(uint16_t *phy,
- const struct input *input)
- {
- int lane, byte, b_addr, c_addr;
- int dq_dqs_rcv_cntrl;
- int gain_curr_adj_defval = 0xb;
- int major_mode_dbyte = 3;
- int dfe_ctrl_defval = 0;
- int ext_vref_range_defval = 0;
- int sel_analog_vref = 1;
- uint32_t addr;
- #ifdef ERRATA_DDR_A050958
- gain_curr_adj_defval = 0x1f;
- #endif
- dq_dqs_rcv_cntrl = gain_curr_adj_defval << csr_gain_curr_adj_lsb |
- major_mode_dbyte << csr_major_mode_dbyte_lsb |
- dfe_ctrl_defval << csr_dfe_ctrl_lsb |
- ext_vref_range_defval << csr_ext_vref_range_lsb |
- sel_analog_vref << csr_sel_analog_vref_lsb;
- for (byte = 0; byte < input->basic.num_dbyte; byte++) {
- c_addr = byte << 12;
- for (lane = 0; lane <= 1; lane++) {
- b_addr = lane << 8;
- addr = t_dbyte | c_addr | b_addr |
- csr_dq_dqs_rcv_cntrl_addr;
- phy_io_write16(phy, addr, dq_dqs_rcv_cntrl);
- }
- }
- }
- static void prog_mem_alert_control(uint16_t *phy,
- const struct input *input)
- {
- int mem_alert_control;
- int mem_alert_control2;
- int malertpu_en;
- int malertrx_en;
- int malertvref_level;
- int malertpu_stren;
- int malertsync_bypass;
- int malertdisable_val_defval = 1;
- uint32_t addr;
- if (input->basic.dram_type == DDR4 && input->adv.mem_alert_en == 1) {
- malertpu_en = 1;
- malertrx_en = 1;
- malertpu_stren = input->adv.mem_alert_puimp;
- malertvref_level = input->adv.mem_alert_vref_level;
- malertsync_bypass = input->adv.mem_alert_sync_bypass;
- mem_alert_control = malertdisable_val_defval << 14 |
- malertrx_en << 13 |
- malertpu_en << 12 |
- malertpu_stren << 8 |
- malertvref_level;
- mem_alert_control2 = malertsync_bypass <<
- csr_malertsync_bypass_lsb;
- addr = t_master | csr_mem_alert_control_addr;
- phy_io_write16(phy, addr, mem_alert_control);
- addr = t_master | csr_mem_alert_control2_addr;
- phy_io_write16(phy, addr, mem_alert_control2);
- }
- }
- static void prog_dfi_freq_ratio(uint16_t *phy,
- const struct input *input)
- {
- int dfi_freq_ratio;
- uint32_t addr = t_master | csr_dfi_freq_ratio_addr;
- dfi_freq_ratio = input->basic.dfi_freq_ratio;
- phy_io_write16(phy, addr, dfi_freq_ratio);
- }
- static void prog_tristate_mode_ca(uint16_t *phy,
- const struct input *input)
- {
- int tristate_mode_ca;
- int dis_dyn_adr_tri;
- int ddr2tmode;
- int ck_dis_val_def = 1;
- uint32_t addr = t_master | csr_tristate_mode_ca_addr;
- dis_dyn_adr_tri = input->adv.dis_dyn_adr_tri;
- ddr2tmode = input->adv.is2ttiming;
- tristate_mode_ca = ck_dis_val_def << csr_ck_dis_val_lsb |
- ddr2tmode << csr_ddr2tmode_lsb |
- dis_dyn_adr_tri << csr_dis_dyn_adr_tri_lsb;
- phy_io_write16(phy, addr, tristate_mode_ca);
- }
- static void prog_dfi_xlat(uint16_t *phy,
- const struct input *input)
- {
- uint16_t loop_vector;
- int dfifreqxlat_dat;
- int pllbypass_dat;
- uint32_t addr;
- /* fIXME: Shall unused P1, P2, P3 be bypassed? */
- pllbypass_dat = input->basic.pll_bypass; /* only [0] is used */
- for (loop_vector = 0; loop_vector < 8; loop_vector++) {
- if (loop_vector == 0) {
- dfifreqxlat_dat = pllbypass_dat + 0x5555;
- } else if (loop_vector == 7) {
- dfifreqxlat_dat = 0xf000;
- } else {
- dfifreqxlat_dat = 0x5555;
- }
- addr = t_master | (csr_dfi_freq_xlat0_addr + loop_vector);
- phy_io_write16(phy, addr, dfifreqxlat_dat);
- }
- }
- static void prog_dbyte_misc_mode(uint16_t *phy,
- const struct input *input,
- const struct ddr4u1d *msg)
- {
- int dbyte_misc_mode;
- int dq_dqs_rcv_cntrl1;
- int dq_dqs_rcv_cntrl1_1;
- int byte, c_addr;
- uint32_t addr;
- dbyte_misc_mode = 0x1 << csr_dbyte_disable_lsb;
- dq_dqs_rcv_cntrl1 = 0x1ff << csr_power_down_rcvr_lsb |
- 0x1 << csr_power_down_rcvr_dqs_lsb |
- 0x1 << csr_rx_pad_standby_en_lsb;
- dq_dqs_rcv_cntrl1_1 = (0x100 << csr_power_down_rcvr_lsb |
- csr_rx_pad_standby_en_mask);
- for (byte = 0; byte < input->basic.num_dbyte; byte++) {
- c_addr = byte << 12;
- if (byte <= input->basic.num_active_dbyte_dfi0 - 1) {
- /* disable RDBI lane if not used. */
- if ((input->basic.dram_data_width != 4) &&
- (((msg->mr5 >> 12) & 0x1) == 0)) {
- addr = t_dbyte
- | c_addr
- | csr_dq_dqs_rcv_cntrl1_addr;
- phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1_1);
- }
- } else {
- addr = t_dbyte | c_addr | csr_dbyte_misc_mode_addr;
- phy_io_write16(phy, addr, dbyte_misc_mode);
- addr = t_dbyte | c_addr | csr_dq_dqs_rcv_cntrl1_addr;
- phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1);
- }
- }
- }
- static void prog_master_x4config(uint16_t *phy,
- const struct input *input)
- {
- int master_x4config;
- int x4tg;
- uint32_t addr = t_master | csr_master_x4config_addr;
- x4tg = input->basic.dram_data_width == 4 ? 0xf : 0;
- master_x4config = x4tg << csr_x4tg_lsb;
- phy_io_write16(phy, addr, master_x4config);
- }
- static void prog_dmipin_present(uint16_t *phy,
- const struct input *input,
- const struct ddr4u1d *msg)
- {
- int dmipin_present;
- uint32_t addr = t_master | csr_dmipin_present_addr;
- dmipin_present = (msg->mr5 >> 12) & 0x1;
- phy_io_write16(phy, addr, dmipin_present);
- }
- static void prog_dfi_phyupd(uint16_t *phy,
- const struct input *input)
- {
- int dfiphyupd_dat;
- uint32_t addr;
- addr = t_master | (csr_dfiphyupd_addr);
- dfiphyupd_dat = phy_io_read16(phy, addr) &
- ~csr_dfiphyupd_threshold_mask;
- phy_io_write16(phy, addr, dfiphyupd_dat);
- }
- static void prog_cal_misc2(uint16_t *phy,
- const struct input *input)
- {
- int cal_misc2_dat, cal_drv_pdth_data, cal_offsets_dat;
- uint32_t addr;
- addr = t_master | (csr_cal_misc2_addr);
- cal_misc2_dat = phy_io_read16(phy, addr) |
- (1 << csr_cal_misc2_err_dis);
- phy_io_write16(phy, addr, cal_misc2_dat);
- addr = t_master | (csr_cal_offsets_addr);
- cal_drv_pdth_data = 0x9 << 6;
- cal_offsets_dat = (phy_io_read16(phy, addr) & ~csr_cal_drv_pdth_mask)
- | cal_drv_pdth_data;
- phy_io_write16(phy, addr, cal_offsets_dat);
- }
- static int c_init_phy_config(uint16_t **phy_ptr,
- unsigned int ip_rev,
- const struct input *input,
- const void *msg)
- {
- int i;
- uint16_t *phy;
- __unused const soc_info_t *soc_info;
- for (i = 0; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- debug("Initialize PHY %d config\n", i);
- prog_dfi_phyupd(phy, input);
- prog_cal_misc2(phy, input);
- prog_tx_pre_drv_mode(phy, input);
- prog_atx_pre_drv_mode(phy, input);
- prog_enable_cs_multicast(phy, input); /* rdimm and lrdimm */
- prog_dfi_rd_data_cs_dest_map(phy, ip_rev, input, msg);
- prog_pll_ctrl2(phy, input);
- #ifdef DDR_PLL_FIX
- soc_info = get_soc_info();
- debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver);
- if (soc_info->svr_reg.bf.maj_ver == 1) {
- prog_pll_pwr_dn(phy, input);
- /*Enable FFE aka TxEqualizationMode for rev1 SI*/
- phy_io_write16(phy, 0x010048, 0x1);
- }
- #endif
- prog_ard_ptr_init_val(phy, input);
- prog_dqs_preamble_control(phy, input);
- prog_dll_lck_param(phy, input);
- prog_dll_gain_ctl(phy, input);
- prog_proc_odt_time_ctl(phy, input);
- prog_tx_odt_drv_stren(phy, input);
- prog_tx_impedance_ctrl1(phy, input);
- prog_atx_impedance(phy, input);
- prog_dfi_mode(phy, input);
- prog_dfi_camode(phy, input);
- prog_cal_drv_str0(phy, input);
- prog_cal_uclk_info(phy, input);
- prog_cal_rate(phy, input);
- prog_vref_in_global(phy, input, msg);
- prog_dq_dqs_rcv_cntrl(phy, input);
- prog_mem_alert_control(phy, input);
- prog_dfi_freq_ratio(phy, input);
- prog_tristate_mode_ca(phy, input);
- prog_dfi_xlat(phy, input);
- prog_dbyte_misc_mode(phy, input, msg);
- prog_master_x4config(phy, input);
- prog_dmipin_present(phy, input, msg);
- prog_acx4_anib_dis(phy, input);
- }
- return 0;
- }
- static uint32_t get_mail(uint16_t *phy, int stream)
- {
- int timeout;
- uint32_t mail = 0U;
- timeout = TIMEOUTDEFAULT;
- while (((--timeout) != 0) &&
- ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs)
- & uct_write_prot_shadow_mask) != 0)) {
- mdelay(10);
- }
- if (timeout == 0) {
- ERROR("Timeout getting mail from PHY\n");
- return 0xFFFF;
- }
- mail = phy_io_read16(phy, t_apbonly |
- csr_uct_write_only_shadow);
- if (stream != 0) {
- mail |= phy_io_read16(phy, t_apbonly |
- csr_uct_dat_write_only_shadow) << 16;
- }
- /* Ack */
- phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 0);
- timeout = TIMEOUTDEFAULT;
- while (((--timeout) != 0) &&
- ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs)
- & uct_write_prot_shadow_mask) == 0)) {
- mdelay(1);
- }
- if (timeout == 0) {
- ERROR("Timeout ack PHY mail\n");
- }
- /* completed */
- phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 1U);
- return mail;
- }
- #ifdef DDR_PHY_DEBUG
- static const char *lookup_msg(uint32_t index, int train2d)
- {
- int i;
- int size;
- const struct phy_msg *messages;
- const char *ptr = NULL;
- if (train2d != 0) {
- messages = messages_2d;
- size = ARRAY_SIZE(messages_2d);
- } else {
- messages = messages_1d;
- size = ARRAY_SIZE(messages_1d);
- }
- for (i = 0; i < size; i++) {
- if (messages[i].index == index) {
- ptr = messages[i].msg;
- break;
- }
- }
- return ptr;
- }
- #endif
- #define MAX_ARGS 32
- static void decode_stream_message(uint16_t *phy, int train2d)
- {
- uint32_t index __unused;
- __unused const char *format;
- __unused uint32_t args[MAX_ARGS];
- __unused int i;
- #ifdef DDR_PHY_DEBUG
- index = get_mail(phy, 1);
- if ((index & 0xffff) > MAX_ARGS) { /* up to MAX_ARGS args so far */
- printf("Program error in %s\n", __func__);
- }
- for (i = 0; i < (index & 0xffff) && i < MAX_ARGS; i++) {
- args[i] = get_mail(phy, 1);
- }
- format = lookup_msg(index, train2d);
- if (format != NULL) {
- printf("0x%08x: ", index);
- printf(format, args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8], args[9], args[10],
- args[11], args[12], args[13], args[14], args[15],
- args[16], args[17], args[18], args[19], args[20],
- args[21], args[22], args[23], args[24], args[25],
- args[26], args[27], args[28], args[29], args[30],
- args[31]);
- }
- #endif
- }
- static int wait_fw_done(uint16_t *phy, int train2d)
- {
- uint32_t mail = 0U;
- while (mail == U(0x0)) {
- mail = get_mail(phy, 0);
- switch (mail) {
- case U(0x7):
- debug("%s Training completed\n", train2d ? "2D" : "1D");
- break;
- case U(0xff):
- debug("%s Training failure\n", train2d ? "2D" : "1D");
- break;
- case U(0x0):
- debug("End of initialization\n");
- mail = 0U;
- break;
- case U(0x1):
- debug("End of fine write leveling\n");
- mail = 0U;
- break;
- case U(0x2):
- debug("End of read enable training\n");
- mail = 0U;
- break;
- case U(0x3):
- debug("End of read delay center optimization\n");
- mail = 0U;
- break;
- case U(0x4):
- debug("End of write delay center optimization\n");
- mail = 0U;
- break;
- case U(0x5):
- debug("End of 2D read delay/voltage center optimztn\n");
- mail = 0U;
- break;
- case U(0x6):
- debug("End of 2D write delay/voltage center optmztn\n");
- mail = 0U;
- break;
- case U(0x8):
- decode_stream_message(phy, train2d);
- mail = 0U;
- break;
- case U(0x9):
- debug("End of max read latency training\n");
- mail = 0U;
- break;
- case U(0xa):
- debug("End of read dq deskew training\n");
- mail = 0U;
- break;
- case U(0xc):
- debug("End of LRDIMM Specific training, including:\n");
- debug("/tDWL, MREP, MRD and MWD\n");
- mail = 0U;
- break;
- case U(0xd):
- debug("End of CA training\n");
- mail = 0U;
- break;
- case U(0xfd):
- debug("End of MPR read delay center optimization\n");
- mail = 0U;
- break;
- case U(0xfe):
- debug("End of Write leveling coarse delay\n");
- mail = 0U;
- break;
- case U(0xffff):
- debug("Timed out\n");
- break;
- default:
- mail = 0U;
- break;
- }
- }
- if (mail == U(0x7)) {
- return 0;
- } else if (mail == U(0xff)) {
- return -EIO;
- } else if (mail == U(0xffff)) {
- return -ETIMEDOUT;
- }
- debug("PHY_GEN2 FW: Unxpected mail = 0x%x\n", mail);
- return -EINVAL;
- }
- static int g_exec_fw(uint16_t **phy_ptr, int train2d, struct input *input)
- {
- int ret = -EINVAL;
- int i;
- uint16_t *phy;
- for (i = 0; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- debug("Applying PLL optimal settings\n");
- prog_pll_ctrl2(phy, input);
- prog_pll_ctrl(phy, input);
- phy_io_write16(phy,
- t_apbonly | csr_micro_cont_mux_sel_addr,
- 0x1);
- phy_io_write16(phy,
- t_apbonly | csr_micro_reset_addr,
- csr_reset_to_micro_mask |
- csr_stall_to_micro_mask);
- phy_io_write16(phy,
- t_apbonly | csr_micro_reset_addr,
- csr_stall_to_micro_mask);
- phy_io_write16(phy,
- t_apbonly | csr_micro_reset_addr,
- 0);
- ret = wait_fw_done(phy, train2d);
- if (ret == -ETIMEDOUT) {
- ERROR("Wait timed out: Firmware execution on PHY %d\n",
- i);
- }
- }
- return ret;
- }
- static inline int send_fw(uint16_t *phy,
- uint32_t dst,
- uint16_t *img,
- uint32_t size)
- {
- uint32_t i;
- if ((size % 2U) != 0U) {
- ERROR("Wrong image size 0x%x\n", size);
- return -EINVAL;
- }
- for (i = 0U; i < size / 2; i++) {
- phy_io_write16(phy, dst + i, *(img + i));
- }
- return 0;
- }
- static int load_fw(uint16_t **phy_ptr,
- struct input *input,
- int train2d,
- void *msg,
- size_t len,
- uintptr_t phy_gen2_fw_img_buf,
- int (*img_loadr)(unsigned int, uintptr_t *, uint32_t *),
- uint32_t warm_boot_flag)
- {
- uint32_t imem_id, dmem_id;
- uintptr_t image_buf;
- uint32_t size;
- int ret;
- int i;
- uint16_t *phy;
- switch (input->basic.dimm_type) {
- case UDIMM:
- case SODIMM:
- case NODIMM:
- imem_id = train2d ? DDR_IMEM_UDIMM_2D_IMAGE_ID :
- DDR_IMEM_UDIMM_1D_IMAGE_ID;
- dmem_id = train2d ? DDR_DMEM_UDIMM_2D_IMAGE_ID :
- DDR_DMEM_UDIMM_1D_IMAGE_ID;
- break;
- case RDIMM:
- imem_id = train2d ? DDR_IMEM_RDIMM_2D_IMAGE_ID :
- DDR_IMEM_RDIMM_1D_IMAGE_ID;
- dmem_id = train2d ? DDR_DMEM_RDIMM_2D_IMAGE_ID :
- DDR_DMEM_RDIMM_1D_IMAGE_ID;
- break;
- default:
- ERROR("Unsupported DIMM type\n");
- return -EINVAL;
- }
- size = PHY_GEN2_MAX_IMAGE_SIZE;
- image_buf = (uintptr_t)phy_gen2_fw_img_buf;
- ret = img_loadr(imem_id, &image_buf, &size);
- if (ret != 0) {
- ERROR("Failed to load %d firmware.\n", imem_id);
- return ret;
- }
- debug("Loaded Imaged id %d of size %x at address %lx\n",
- imem_id, size, image_buf);
- for (i = 0; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- if (warm_boot_flag != DDR_WARM_BOOT) {
- if (train2d == 0) {
- phy_io_write16(phy, t_master |
- csr_mem_reset_l_addr,
- csr_protect_mem_reset_mask);
- }
- }
- /* Enable access to the internal CSRs */
- phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 0);
- ret = send_fw(phy, PHY_GEN2_IMEM_ADDR,
- (uint16_t *)image_buf, size);
- if (ret != 0) {
- return ret;
- }
- }
- size = PHY_GEN2_MAX_IMAGE_SIZE;
- image_buf = (uintptr_t)phy_gen2_fw_img_buf;
- ret = img_loadr(dmem_id, &image_buf, &size);
- if (ret != 0) {
- ERROR("Failed to load %d firmware.\n", dmem_id);
- return ret;
- }
- debug("Loaded Imaged id %d of size %x at address %lx\n",
- dmem_id, size, image_buf);
- image_buf += len;
- size -= len;
- for (i = 0; i < NUM_OF_DDRC; i++) {
- phy = phy_ptr[i];
- if (phy == NULL) {
- continue;
- }
- ret = send_fw(phy, PHY_GEN2_DMEM_ADDR, msg, len);
- if (ret != 0) {
- return ret;
- }
- ret = send_fw(phy, PHY_GEN2_DMEM_ADDR + len / 2,
- (uint16_t *)image_buf, size);
- if (ret != 0) {
- return ret;
- }
- }
- return ret;
- }
- static void parse_odt(const unsigned int val,
- const int read,
- const int i,
- const unsigned int cs_d0,
- const unsigned int cs_d1,
- unsigned int *odt)
- {
- int shift = read ? 4 : 0;
- int j;
- if (i < 0 || i > 3) {
- printf("Error: invalid chip-select value\n");
- return;
- }
- switch (val) {
- case DDR_ODT_CS:
- odt[i] |= (1 << i) << shift;
- break;
- case DDR_ODT_ALL_OTHER_CS:
- for (j = 0; j < DDRC_NUM_CS; j++) {
- if (i == j) {
- continue;
- }
- if (((cs_d0 | cs_d1) & (1 << j)) == 0) {
- continue;
- }
- odt[j] |= (1 << i) << shift;
- }
- break;
- case DDR_ODT_CS_AND_OTHER_DIMM:
- odt[i] |= (1 << i) << 4;
- /* fallthrough */
- case DDR_ODT_OTHER_DIMM:
- for (j = 0; j < DDRC_NUM_CS; j++) {
- if ((((cs_d0 & (1 << i)) != 0) &&
- ((cs_d1 & (1 << j)) != 0)) ||
- (((cs_d1 & (1 << i)) != 0) &&
- ((cs_d0 & (1 << j)) != 0))) {
- odt[j] |= (1 << i) << shift;
- }
- }
- break;
- case DDR_ODT_ALL:
- for (j = 0; j < DDRC_NUM_CS; j++) {
- if (((cs_d0 | cs_d1) & (1 << j)) == 0) {
- continue;
- }
- odt[j] |= (1 << i) << shift;
- }
- break;
- case DDR_ODT_SAME_DIMM:
- for (j = 0; j < DDRC_NUM_CS; j++) {
- if ((((cs_d0 & (1 << i)) != 0) &&
- ((cs_d0 & (1 << j)) != 0)) ||
- (((cs_d1 & (1 << i)) != 0) &&
- ((cs_d1 & (1 << j)) != 0))) {
- odt[j] |= (1 << i) << shift;
- }
- }
- break;
- case DDR_ODT_OTHER_CS_ONSAMEDIMM:
- for (j = 0; j < DDRC_NUM_CS; j++) {
- if (i == j) {
- continue;
- }
- if ((((cs_d0 & (1 << i)) != 0) &&
- ((cs_d0 & (1 << j)) != 0)) ||
- (((cs_d1 & (1 << i)) != 0) &&
- ((cs_d1 & (1 << j)) != 0))) {
- odt[j] |= (1 << i) << shift;
- }
- }
- break;
- case DDR_ODT_NEVER:
- break;
- default:
- break;
- }
- }
- #ifdef DEBUG_DDR_INPUT_CONFIG
- char *dram_types_str[] = {
- "DDR4",
- "DDR3",
- "LDDDR4",
- "LPDDR3",
- "LPDDR2",
- "DDR5"
- };
- char *dimm_types_str[] = {
- "UDIMM",
- "SODIMM",
- "RDIMM",
- "LRDIMM",
- "NODIMM",
- };
- static void print_jason_format(struct input *input,
- struct ddr4u1d *msg_1d,
- struct ddr4u2d *msg_2d)
- {
- printf("\n{");
- printf("\n \"dram_type\": \"%s\",", dram_types_str[input->basic.dram_type]);
- printf("\n \"dimm_type\": \"%s\",", dimm_types_str[input->basic.dimm_type]);
- printf("\n \"hard_macro_ver\": \"%d\",", input->basic.hard_macro_ver);
- printf("\n \"num_dbyte\": \"0x%04x\",", (unsigned int)input->basic.num_dbyte);
- printf("\n \"num_active_dbyte_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_active_dbyte_dfi0);
- printf("\n \"num_anib\": \"0x%04x\",", (unsigned int)input->basic.num_anib);
- printf("\n \"num_rank_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_rank_dfi0);
- printf("\n \"num_pstates\": \"0x%04x\",", (unsigned int)input->basic.num_pstates);
- printf("\n \"frequency\": \"%d\",", input->basic.frequency);
- printf("\n \"pll_bypass\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio);
- printf("\n \"dfi_freq_ratio\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio);
- printf("\n \"dfi1_exists\": \"0x%04x\",", (unsigned int)input->basic.dfi1exists);
- printf("\n \"dram_data_width\": \"0x%04x\",", (unsigned int)input->basic.dram_data_width);
- printf("\n \"dram_byte_swap\": \"0x%04x\",", (unsigned int)input->adv.dram_byte_swap);
- printf("\n \"ext_cal_res_val\": \"0x%04x\",", (unsigned int)input->adv.ext_cal_res_val);
- printf("\n \"tx_slew_rise_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_dq);
- printf("\n \"tx_slew_fall_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_dq);
- printf("\n \"tx_slew_rise_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_ac);
- printf("\n \"tx_slew_fall_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_ac);
- printf("\n \"odt_impedance\": \"%d\",", input->adv.odtimpedance);
- printf("\n \"tx_impedance\": \"%d\",", input->adv.tx_impedance);
- printf("\n \"atx_impedance\": \"%d\",", input->adv.atx_impedance);
- printf("\n \"mem_alert_en\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_en);
- printf("\n \"mem_alert_pu_imp\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_puimp);
- printf("\n \"mem_alert_vref_level\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_vref_level);
- printf("\n \"mem_alert_sync_bypass\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_sync_bypass);
- printf("\n \"cal_interval\": \"0x%04x\",", (unsigned int)input->adv.cal_interval);
- printf("\n \"cal_once\": \"0x%04x\",", (unsigned int)input->adv.cal_once);
- printf("\n \"dis_dyn_adr_tri\": \"0x%04x\",", (unsigned int)input->adv.dis_dyn_adr_tri);
- printf("\n \"is2t_timing\": \"0x%04x\",", (unsigned int)input->adv.is2ttiming);
- printf("\n \"d4rx_preabmle_length\": \"0x%04x\",", (unsigned int)input->adv.d4rx_preamble_length);
- printf("\n \"d4tx_preamble_length\": \"0x%04x\",", (unsigned int)input->adv.d4tx_preamble_length);
- printf("\n \"msg_misc\": \"0x%02x\",", (unsigned int)msg_1d->msg_misc);
- printf("\n \"reserved00\": \"0x%01x\",", (unsigned int)msg_1d->reserved00);
- printf("\n \"hdt_ctrl\": \"0x%02x\",", (unsigned int)msg_1d->hdt_ctrl);
- printf("\n \"cs_present\": \"0x%02x\",", (unsigned int)msg_1d->cs_present);
- printf("\n \"phy_vref\": \"0x%02x\",", (unsigned int)msg_1d->phy_vref);
- printf("\n \"dfi_mrl_margin\": \"0x%02x\",", (unsigned int)msg_1d->dfimrlmargin);
- printf("\n \"addr_mirror\": \"0x%02x\",", (unsigned int)msg_1d->addr_mirror);
- printf("\n \"wr_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0x0f));
- printf("\n \"wr_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0x0f));
- printf("\n \"wr_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0x0f));
- printf("\n \"wr_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0x0f));
- printf("\n \"rd_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0xf0));
- printf("\n \"rd_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0xf0));
- printf("\n \"rd_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0xf0));
- printf("\n \"rd_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0xf0));
- printf("\n \"d4_misc\": \"0x%01x\",", (unsigned int)msg_1d->d4misc);
- printf("\n \"share_2d_vref_results\": \"0x%01x\",", (unsigned int)msg_1d->share2dvref_result);
- printf("\n \"sequence_ctrl\": \"0x%04x\",", (unsigned int)msg_1d->sequence_ctrl);
- printf("\n \"mr0\": \"0x%04x\",", (unsigned int)msg_1d->mr0);
- printf("\n \"mr1\": \"0x%04x\",", (unsigned int)msg_1d->mr1);
- printf("\n \"mr2\": \"0x%04x\",", (unsigned int)msg_1d->mr2);
- printf("\n \"mr3\": \"0x%04x\",", (unsigned int)msg_1d->mr3);
- printf("\n \"mr4\": \"0x%04x\",", (unsigned int)msg_1d->mr4);
- printf("\n \"mr5\": \"0x%04x\",", (unsigned int)msg_1d->mr5);
- printf("\n \"mr6\": \"0x%04x\",", (unsigned int)msg_1d->mr6);
- printf("\n \"alt_cal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_cas_l);
- printf("\n \"alt_wcal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_wcas_l);
- printf("\n \"sequence_ctrl_2d\": \"0x%04x\",", (unsigned int)msg_2d->sequence_ctrl);
- printf("\n \"rtt_nom_wr_park0\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park0);
- printf("\n \"rtt_nom_wr_park1\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park1);
- printf("\n \"rtt_nom_wr_park2\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park2);
- printf("\n \"rtt_nom_wr_park3\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park3);
- printf("\n \"rtt_nom_wr_park4\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park4);
- printf("\n \"rtt_nom_wr_park5\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park5);
- printf("\n \"rtt_nom_wr_park6\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park6);
- printf("\n \"rtt_nom_wr_park7\": \"0x%01x\"", (unsigned int)msg_1d->rtt_nom_wr_park7);
- printf("\n}");
- printf("\n");
- }
- #endif
- int compute_ddr_phy(struct ddr_info *priv)
- {
- const unsigned long clk = priv->clk;
- const struct memctl_opt *popts = &priv->opt;
- const struct ddr_conf *conf = &priv->conf;
- const struct dimm_params *dimm_param = &priv->dimm;
- struct ddr_cfg_regs *regs = &priv->ddr_reg;
- int ret;
- static struct input input;
- static struct ddr4u1d msg_1d;
- static struct ddr4u2d msg_2d;
- unsigned int i;
- unsigned int odt_rd, odt_wr;
- __unused const soc_info_t *soc_info;
- #ifdef NXP_APPLY_MAX_CDD
- unsigned int tcfg0, tcfg4, rank;
- #ifdef NXP_WARM_BOOT
- struct ddr_ctrl_reg_values ddrctrl_regs;
- #endif
- #endif
- if (dimm_param == NULL) {
- ERROR("Empty DIMM parameters.\n");
- return -EINVAL;
- }
- zeromem(&input, sizeof(input));
- zeromem(&msg_1d, sizeof(msg_1d));
- zeromem(&msg_2d, sizeof(msg_2d));
- input.basic.dram_type = DDR4;
- /* FIXME: Add condition for LRDIMM */
- input.basic.dimm_type = (dimm_param->rdimm != 0) ? RDIMM : UDIMM;
- input.basic.num_dbyte = dimm_param->primary_sdram_width / 8 +
- dimm_param->ec_sdram_width / 8;
- input.basic.num_active_dbyte_dfi0 = input.basic.num_dbyte;
- input.basic.num_rank_dfi0 = dimm_param->n_ranks;
- input.basic.dram_data_width = dimm_param->device_width;
- input.basic.hard_macro_ver = 0xa;
- input.basic.num_pstates = 1;
- input.basic.dfi_freq_ratio = 1;
- input.basic.num_anib = 0xc;
- input.basic.train2d = popts->skip2d ? 0 : 1;
- input.basic.frequency = (int) (clk / 2000000ul);
- debug("frequency = %dMHz\n", input.basic.frequency);
- input.cs_d0 = conf->cs_on_dimm[0];
- #if DDRC_NUM_DIMM > 1
- input.cs_d1 = conf->cs_on_dimm[1];
- #endif
- input.mirror = dimm_param->mirrored_dimm;
- input.mr[0] = regs->sdram_mode[0] & U(0xffff);
- input.mr[1] = regs->sdram_mode[0] >> 16U;
- input.mr[2] = regs->sdram_mode[1] >> 16U;
- input.mr[3] = regs->sdram_mode[1] & U(0xffff);
- input.mr[4] = regs->sdram_mode[8] >> 16U;
- input.mr[5] = regs->sdram_mode[8] & U(0xffff);
- input.mr[6] = regs->sdram_mode[9] >> 16U;
- input.vref = popts->vref_phy;
- debug("Vref_phy = %d percent\n", (input.vref * 100U) >> 7U);
- for (i = 0U; i < DDRC_NUM_CS; i++) {
- if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0U) {
- continue;
- }
- odt_rd = (regs->cs[i].config >> 20U) & U(0x7);
- odt_wr = (regs->cs[i].config >> 16U) & U(0x7);
- parse_odt(odt_rd, true, i, input.cs_d0, input.cs_d1,
- input.odt);
- parse_odt(odt_wr, false, i, input.cs_d0, input.cs_d1,
- input.odt);
- }
- /* Do not set sdram_cfg[RD_EN] or sdram_cfg2[RCW_EN] for RDIMM */
- if (dimm_param->rdimm != 0U) {
- regs->sdram_cfg[0] &= ~(1 << 28U);
- regs->sdram_cfg[1] &= ~(1 << 2U);
- input.rcw[0] = (regs->sdram_rcw[0] >> 28U) & U(0xf);
- input.rcw[1] = (regs->sdram_rcw[0] >> 24U) & U(0xf);
- input.rcw[2] = (regs->sdram_rcw[0] >> 20U) & U(0xf);
- input.rcw[3] = (regs->sdram_rcw[0] >> 16U) & U(0xf);
- input.rcw[4] = (regs->sdram_rcw[0] >> 12U) & U(0xf);
- input.rcw[5] = (regs->sdram_rcw[0] >> 8U) & U(0xf);
- input.rcw[6] = (regs->sdram_rcw[0] >> 4U) & U(0xf);
- input.rcw[7] = (regs->sdram_rcw[0] >> 0U) & U(0xf);
- input.rcw[8] = (regs->sdram_rcw[1] >> 28U) & U(0xf);
- input.rcw[9] = (regs->sdram_rcw[1] >> 24U) & U(0xf);
- input.rcw[10] = (regs->sdram_rcw[1] >> 20U) & U(0xf);
- input.rcw[11] = (regs->sdram_rcw[1] >> 16U) & U(0xf);
- input.rcw[12] = (regs->sdram_rcw[1] >> 12U) & U(0xf);
- input.rcw[13] = (regs->sdram_rcw[1] >> 8U) & U(0xf);
- input.rcw[14] = (regs->sdram_rcw[1] >> 4U) & U(0xf);
- input.rcw[15] = (regs->sdram_rcw[1] >> 0U) & U(0xf);
- input.rcw3x = (regs->sdram_rcw[2] >> 8U) & U(0xff);
- }
- input.adv.odtimpedance = popts->odt ? popts->odt : 60;
- input.adv.tx_impedance = popts->phy_tx_impedance ?
- popts->phy_tx_impedance : 28;
- input.adv.atx_impedance = popts->phy_atx_impedance ?
- popts->phy_atx_impedance : 30;
- debug("Initializing input adv data structure\n");
- phy_gen2_init_input(&input);
- debug("Initializing message block\n");
- ret = phy_gen2_msg_init(&msg_1d, &msg_2d, &input);
- if (ret != 0) {
- ERROR("Init msg failed (error code %d)\n", ret);
- return ret;
- }
- ret = c_init_phy_config(priv->phy, priv->ip_rev, &input, &msg_1d);
- if (ret != 0) {
- ERROR("Init PHY failed (error code %d)\n", ret);
- return ret;
- }
- #ifdef NXP_WARM_BOOT
- debug("Warm boot flag value %0x\n", priv->warm_boot_flag);
- if (priv->warm_boot_flag == DDR_WARM_BOOT) {
- debug("Restoring the Phy training data\n");
- // Restore the training data
- ret = restore_phy_training_values(priv->phy,
- PHY_TRAINING_REGS_ON_FLASH,
- priv->num_ctlrs,
- input.basic.train2d
- #ifdef NXP_APPLY_MAX_CDD
- , &ddrctrl_regs
- #endif
- );
- if (ret != 0) {
- ERROR("Restoring of training data failed %d\n", ret);
- return ret;
- }
- #ifdef NXP_APPLY_MAX_CDD
- regs->timing_cfg[0] = ddrctrl_regs.timing_cfg0;
- regs->timing_cfg[4] = ddrctrl_regs.timing_cfg4;
- #endif
- } else {
- #endif
- /* Mapping IMG buffer firstly */
- ret = mmap_add_dynamic_region(priv->phy_gen2_fw_img_buf,
- priv->phy_gen2_fw_img_buf,
- PHY_GEN2_MAX_IMAGE_SIZE,
- MT_MEMORY | MT_RW | MT_SECURE);
- if (ret != 0) {
- ERROR("Failed to add dynamic memory region.\n");
- return ret;
- }
- debug("Load 1D firmware\n");
- ret = load_fw(priv->phy, &input, 0, &msg_1d,
- sizeof(struct ddr4u1d), priv->phy_gen2_fw_img_buf,
- priv->img_loadr, priv->warm_boot_flag);
- if (ret != 0) {
- ERROR("Loading firmware failed (error code %d)\n", ret);
- return ret;
- }
- debug("Execute firmware\n");
- ret = g_exec_fw(priv->phy, 0, &input);
- if (ret != 0) {
- ERROR("Execution FW failed (error code %d)\n", ret);
- }
- #ifdef NXP_APPLY_MAX_CDD
- soc_info = get_soc_info();
- if (soc_info->svr_reg.bf.maj_ver == 2) {
- tcfg0 = regs->timing_cfg[0];
- tcfg4 = regs->timing_cfg[4];
- rank = findrank(conf->cs_in_use);
- get_cdd_val(priv->phy, rank, input.basic.frequency,
- &tcfg0, &tcfg4);
- regs->timing_cfg[0] = tcfg0;
- regs->timing_cfg[4] = tcfg4;
- }
- #endif
- if ((ret == 0) && (input.basic.train2d != 0)) {
- /* 2D training starts here */
- debug("Load 2D firmware\n");
- ret = load_fw(priv->phy, &input, 1, &msg_2d,
- sizeof(struct ddr4u2d),
- priv->phy_gen2_fw_img_buf,
- priv->img_loadr,
- priv->warm_boot_flag);
- if (ret != 0) {
- ERROR("Loading fw failed (err code %d)\n", ret);
- } else {
- debug("Execute 2D firmware\n");
- ret = g_exec_fw(priv->phy, 1, &input);
- if (ret != 0) {
- ERROR("Execution FW failed (err %d)\n",
- ret);
- }
- }
- }
- #ifdef NXP_WARM_BOOT
- if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED &&
- ret == 0) {
- #ifdef NXP_APPLY_MAX_CDD
- ddrctrl_regs.timing_cfg0 = regs->timing_cfg[0];
- ddrctrl_regs.timing_cfg4 = regs->timing_cfg[4];
- #endif
- debug("save the phy training data\n");
- //Save training data TBD
- ret = save_phy_training_values(priv->phy,
- PHY_TRAINING_REGS_ON_FLASH,
- priv->num_ctlrs,
- input.basic.train2d
- #ifdef NXP_APPLY_MAX_CDD
- , &ddrctrl_regs
- #endif
- );
- if (ret != 0) {
- ERROR("Saving training data failed.");
- ERROR("Warm boot will fail. Error=%d.\n", ret);
- }
- }
- } /* else */
- #endif
- if (ret == 0) {
- debug("Load PIE\n");
- i_load_pie(priv->phy, &input, &msg_1d);
- NOTICE("DDR4 %s with %d-rank %d-bit bus (x%d)\n",
- input.basic.dimm_type == RDIMM ? "RDIMM" :
- input.basic.dimm_type == LRDIMM ? "LRDIMM" :
- "UDIMM",
- dimm_param->n_ranks,
- dimm_param->primary_sdram_width,
- dimm_param->device_width);
- }
- #ifdef DEBUG_DDR_INPUT_CONFIG
- print_jason_format(&input, &msg_1d, &msg_2d);
- #endif
- return ret;
- }
|