1*b35ce0c4SPankaj Gupta /* 2*b35ce0c4SPankaj Gupta * Copyright 2021 NXP 3*b35ce0c4SPankaj Gupta * SPDX-License-Identifier: BSD-3-Clause 4*b35ce0c4SPankaj Gupta * 5*b35ce0c4SPankaj Gupta */ 6*b35ce0c4SPankaj Gupta 7*b35ce0c4SPankaj Gupta #include <errno.h> 8*b35ce0c4SPankaj Gupta #include <stdint.h> 9*b35ce0c4SPankaj Gupta #include <stdio.h> 10*b35ce0c4SPankaj Gupta #include <stdlib.h> 11*b35ce0c4SPankaj Gupta #include <string.h> 12*b35ce0c4SPankaj Gupta 13*b35ce0c4SPankaj Gupta #include <common/debug.h> 14*b35ce0c4SPankaj Gupta #include "csr.h" 15*b35ce0c4SPankaj Gupta #include <ddr.h> 16*b35ce0c4SPankaj Gupta #include "ddr4fw.h" 17*b35ce0c4SPankaj Gupta #include <drivers/delay_timer.h> 18*b35ce0c4SPankaj Gupta #ifdef NXP_WARM_BOOT 19*b35ce0c4SPankaj Gupta #include <fspi_api.h> 20*b35ce0c4SPankaj Gupta #endif 21*b35ce0c4SPankaj Gupta #include "input.h" 22*b35ce0c4SPankaj Gupta #include <lib/mmio.h> 23*b35ce0c4SPankaj Gupta #include <lib/utils.h> 24*b35ce0c4SPankaj Gupta #include <lib/xlat_tables/xlat_tables_v2.h> 25*b35ce0c4SPankaj Gupta #ifdef DDR_PHY_DEBUG 26*b35ce0c4SPankaj Gupta #include "messages.h" 27*b35ce0c4SPankaj Gupta #endif 28*b35ce0c4SPankaj Gupta #ifdef NXP_WARM_BOOT 29*b35ce0c4SPankaj Gupta #include "phy.h" 30*b35ce0c4SPankaj Gupta #endif 31*b35ce0c4SPankaj Gupta #include "pie.h" 32*b35ce0c4SPankaj Gupta 33*b35ce0c4SPankaj Gupta #define TIMEOUTDEFAULT 500 34*b35ce0c4SPankaj Gupta #define MAP_PHY_ADDR(pstate, n, instance, offset, c) \ 35*b35ce0c4SPankaj Gupta ((((pstate * n) + instance + c) << 12) + offset) 36*b35ce0c4SPankaj Gupta 37*b35ce0c4SPankaj Gupta static uint32_t map_phy_addr_space(uint32_t addr) 38*b35ce0c4SPankaj Gupta { 39*b35ce0c4SPankaj Gupta /* 23 bit addressing */ 40*b35ce0c4SPankaj Gupta uint32_t pstate = (addr & U(0x700000)) >> 20U; /* bit 22:20 */ 41*b35ce0c4SPankaj Gupta uint32_t block_type = (addr & U(0x0f0000)) >> 16U; /* bit 19:16 */ 42*b35ce0c4SPankaj Gupta uint32_t instance = (addr & U(0x00f000)) >> 12U; /* bit 15:12 */ 43*b35ce0c4SPankaj Gupta uint32_t offset = (addr & U(0x000fff)); /* bit 11:0 */ 44*b35ce0c4SPankaj Gupta 45*b35ce0c4SPankaj Gupta switch (block_type) { 46*b35ce0c4SPankaj Gupta case 0x0: /* 0x0 : ANIB */ 47*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 12, instance, offset, 0); 48*b35ce0c4SPankaj Gupta case 0x1: /* 0x1 : DBYTE */ 49*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 10, instance, offset, 0x30); 50*b35ce0c4SPankaj Gupta case 0x2: /* 0x2 : MASTER */ 51*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x58); 52*b35ce0c4SPankaj Gupta case 0x4: /* 0x4 : ACSM */ 53*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x5c); 54*b35ce0c4SPankaj Gupta case 0x5: /* 0x5 : μCTL Memory */ 55*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 0, instance, offset, 0x60); 56*b35ce0c4SPankaj Gupta case 0x7: /* 0x7 : PPGC */ 57*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x68); 58*b35ce0c4SPankaj Gupta case 0x9: /* 0x9 : INITENG */ 59*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x69); 60*b35ce0c4SPankaj Gupta case 0xc: /* 0xC : DRTUB */ 61*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6d); 62*b35ce0c4SPankaj Gupta case 0xd: /* 0xD : APB Only */ 63*b35ce0c4SPankaj Gupta return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6e); 64*b35ce0c4SPankaj Gupta default: 65*b35ce0c4SPankaj Gupta printf("ERR: Invalid block_type = 0x%x\n", block_type); 66*b35ce0c4SPankaj Gupta return 0; 67*b35ce0c4SPankaj Gupta } 68*b35ce0c4SPankaj Gupta } 69*b35ce0c4SPankaj Gupta 70*b35ce0c4SPankaj Gupta static inline uint16_t *phy_io_addr(void *phy, uint32_t addr) 71*b35ce0c4SPankaj Gupta { 72*b35ce0c4SPankaj Gupta return phy + (map_phy_addr_space(addr) << 2); 73*b35ce0c4SPankaj Gupta } 74*b35ce0c4SPankaj Gupta 75*b35ce0c4SPankaj Gupta static inline void phy_io_write16(uint16_t *phy, uint32_t addr, uint16_t data) 76*b35ce0c4SPankaj Gupta { 77*b35ce0c4SPankaj Gupta mmio_write_16((uintptr_t)phy_io_addr(phy, addr), data); 78*b35ce0c4SPankaj Gupta #ifdef DEBUG_PHY_IO 79*b35ce0c4SPankaj Gupta printf("0x%06x,0x%x\n", addr, data); 80*b35ce0c4SPankaj Gupta #endif 81*b35ce0c4SPankaj Gupta } 82*b35ce0c4SPankaj Gupta 83*b35ce0c4SPankaj Gupta static inline uint16_t phy_io_read16(uint16_t *phy, uint32_t addr) 84*b35ce0c4SPankaj Gupta { 85*b35ce0c4SPankaj Gupta uint16_t reg = mmio_read_16((uintptr_t) phy_io_addr(phy, addr)); 86*b35ce0c4SPankaj Gupta 87*b35ce0c4SPankaj Gupta #ifdef DEBUG_PHY_IO 88*b35ce0c4SPankaj Gupta printf("R: 0x%06x,0x%x\n", addr, reg); 89*b35ce0c4SPankaj Gupta #endif 90*b35ce0c4SPankaj Gupta 91*b35ce0c4SPankaj Gupta return reg; 92*b35ce0c4SPankaj Gupta } 93*b35ce0c4SPankaj Gupta 94*b35ce0c4SPankaj Gupta #ifdef NXP_APPLY_MAX_CDD 95*b35ce0c4SPankaj Gupta 96*b35ce0c4SPankaj Gupta #define CDD_VAL_READ_ADDR (0x054012) 97*b35ce0c4SPankaj Gupta #define CDD_DATA_LEN (60) 98*b35ce0c4SPankaj Gupta 99*b35ce0c4SPankaj Gupta static void read_phy_reg(uint16_t *phy, uint32_t addr, 100*b35ce0c4SPankaj Gupta uint16_t *buf, uint32_t len) 101*b35ce0c4SPankaj Gupta { 102*b35ce0c4SPankaj Gupta uint32_t i = 0U; 103*b35ce0c4SPankaj Gupta 104*b35ce0c4SPankaj Gupta for (i = 0U; i < len/2; i++) { 105*b35ce0c4SPankaj Gupta buf[i] = phy_io_read16(phy, (addr + i)); 106*b35ce0c4SPankaj Gupta } 107*b35ce0c4SPankaj Gupta } 108*b35ce0c4SPankaj Gupta 109*b35ce0c4SPankaj Gupta static uint32_t findrank(uint32_t cs_in_use) 110*b35ce0c4SPankaj Gupta { 111*b35ce0c4SPankaj Gupta uint32_t val = 0U; 112*b35ce0c4SPankaj Gupta 113*b35ce0c4SPankaj Gupta switch (cs_in_use) { 114*b35ce0c4SPankaj Gupta case U(0xf): 115*b35ce0c4SPankaj Gupta val = 4U; 116*b35ce0c4SPankaj Gupta break; 117*b35ce0c4SPankaj Gupta case U(0x3): 118*b35ce0c4SPankaj Gupta val = 2U; 119*b35ce0c4SPankaj Gupta break; 120*b35ce0c4SPankaj Gupta case U(0x1): 121*b35ce0c4SPankaj Gupta val = 1U; 122*b35ce0c4SPankaj Gupta break; 123*b35ce0c4SPankaj Gupta default: 124*b35ce0c4SPankaj Gupta printf("Error - Invalid cs_in_use value\n"); 125*b35ce0c4SPankaj Gupta } 126*b35ce0c4SPankaj Gupta return val; 127*b35ce0c4SPankaj Gupta } 128*b35ce0c4SPankaj Gupta 129*b35ce0c4SPankaj Gupta static uint8_t findmax(uint8_t *buf, uint32_t len) 130*b35ce0c4SPankaj Gupta { 131*b35ce0c4SPankaj Gupta uint8_t max = 0U; 132*b35ce0c4SPankaj Gupta uint32_t i = 0U; 133*b35ce0c4SPankaj Gupta 134*b35ce0c4SPankaj Gupta for (i = 0U; i < len; i++) { 135*b35ce0c4SPankaj Gupta if (buf[i] > max) { 136*b35ce0c4SPankaj Gupta max = buf[i]; 137*b35ce0c4SPankaj Gupta } 138*b35ce0c4SPankaj Gupta } 139*b35ce0c4SPankaj Gupta 140*b35ce0c4SPankaj Gupta return max; 141*b35ce0c4SPankaj Gupta } 142*b35ce0c4SPankaj Gupta 143*b35ce0c4SPankaj Gupta static void get_cdd_val(uint16_t **phy_ptr, uint32_t rank, uint32_t freq, 144*b35ce0c4SPankaj Gupta uint32_t *tcfg0, uint32_t *tcfg4) 145*b35ce0c4SPankaj Gupta { 146*b35ce0c4SPankaj Gupta uint8_t cdd[CDD_DATA_LEN+4] = {0U}; 147*b35ce0c4SPankaj Gupta uint32_t i, val = 0U; 148*b35ce0c4SPankaj Gupta uint16_t *phy; 149*b35ce0c4SPankaj Gupta uint8_t buf[16] = {U(0x0)}; 150*b35ce0c4SPankaj Gupta uint8_t trr = 0U, tww = 0U, trw = 0U, twr = 0U; 151*b35ce0c4SPankaj Gupta uint8_t rrmax = 0U, wwmax = 0U, rwmax = 0U, wrmax = 0U; 152*b35ce0c4SPankaj Gupta uint8_t tmp = U(0x0); 153*b35ce0c4SPankaj Gupta uint8_t *c = NULL; 154*b35ce0c4SPankaj Gupta 155*b35ce0c4SPankaj Gupta for (i = 0U; i < NUM_OF_DDRC; i++) { 156*b35ce0c4SPankaj Gupta 157*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 158*b35ce0c4SPankaj Gupta if (phy == NULL) { 159*b35ce0c4SPankaj Gupta continue; 160*b35ce0c4SPankaj Gupta } 161*b35ce0c4SPankaj Gupta 162*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 163*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, U(0x0)); 164*b35ce0c4SPankaj Gupta 165*b35ce0c4SPankaj Gupta read_phy_reg(phy, CDD_VAL_READ_ADDR, 166*b35ce0c4SPankaj Gupta (uint16_t *)&cdd, CDD_DATA_LEN); 167*b35ce0c4SPankaj Gupta 168*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 169*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, U(0x1)); 170*b35ce0c4SPankaj Gupta 171*b35ce0c4SPankaj Gupta /* CDD values and address 172*b35ce0c4SPankaj Gupta * 173*b35ce0c4SPankaj Gupta * 0x054012 0x24 cdd[0] CDD[X][X] 174*b35ce0c4SPankaj Gupta * 0x054012 0x25 cdd[1] RR[3][2] 175*b35ce0c4SPankaj Gupta * 0x054013 0x26 cdd[2] RR[3][1] 176*b35ce0c4SPankaj Gupta * 0x054013 0x27 cdd[3] RR[3][0] 177*b35ce0c4SPankaj Gupta * 0x054014 0x28 cdd[4] RR[2][3] 178*b35ce0c4SPankaj Gupta * 0x054014 0x29 cdd[5] RR[2][1] 179*b35ce0c4SPankaj Gupta * 0x054015 0x2a cdd[6] RR[2][0] 180*b35ce0c4SPankaj Gupta * 0x054015 0x2b cdd[7] RR[1][3] 181*b35ce0c4SPankaj Gupta * 0x054016 0x2c cdd[8] RR[1][2] 182*b35ce0c4SPankaj Gupta * 0x054016 0x2d cdd[9] RR[1][0] 183*b35ce0c4SPankaj Gupta * 0x054017 0x2e cdd[10] RR[0][3] 184*b35ce0c4SPankaj Gupta * 0x054017 0x2f cdd[11] RR[0][2] 185*b35ce0c4SPankaj Gupta * 0x054018 0x30 cdd[12] RR[0][1] 186*b35ce0c4SPankaj Gupta 187*b35ce0c4SPankaj Gupta * 0x054018 0x31 cdd[13] WW[3][2] 188*b35ce0c4SPankaj Gupta * 0x054019 0x32 cdd[14] WW[3][1] 189*b35ce0c4SPankaj Gupta * 0x054019 0x33 cdd[15] WW[3][0] 190*b35ce0c4SPankaj Gupta * 0x05401a 0x34 cdd[16] WW[2][3] 191*b35ce0c4SPankaj Gupta * 0x05401a 0x35 cdd[17] WW[2][1] 192*b35ce0c4SPankaj Gupta * 0x05401b 0x36 cdd[18] WW[2][0] 193*b35ce0c4SPankaj Gupta * 0x05401b 0x37 cdd[19] WW[1][3] 194*b35ce0c4SPankaj Gupta * 0x05401c 0x38 cdd[20] WW[1][2] 195*b35ce0c4SPankaj Gupta * 0x05401c 0x39 cdd[21] WW[1][0] 196*b35ce0c4SPankaj Gupta * 0x05401d 0x3a cdd[22] WW[0][3] 197*b35ce0c4SPankaj Gupta * 0x05401d 0x3b cdd[23] WW[0][2] 198*b35ce0c4SPankaj Gupta * 0x05401e 0x3c cdd[24] WW[0][1] 199*b35ce0c4SPankaj Gupta 200*b35ce0c4SPankaj Gupta * 0x05401e 0x3d cdd[25] RW[3][3] 201*b35ce0c4SPankaj Gupta * 0x05401f 0x3e cdd[26] RW[3][2] 202*b35ce0c4SPankaj Gupta * 0x05401f 0x3f cdd[27] RW[3][1] 203*b35ce0c4SPankaj Gupta * 0x054020 0x40 cdd[28] RW[3][0] 204*b35ce0c4SPankaj Gupta * 0x054020 0x41 cdd[29] RW[2][3] 205*b35ce0c4SPankaj Gupta * 0x054021 0x42 cdd[30] RW[2][2] 206*b35ce0c4SPankaj Gupta * 0x054021 0x43 cdd[31] RW[2][1] 207*b35ce0c4SPankaj Gupta * 0x054022 0x44 cdd[32] RW[2][0] 208*b35ce0c4SPankaj Gupta * 0x054022 0x45 cdd[33] RW[1][3] 209*b35ce0c4SPankaj Gupta * 0x054023 0x46 cdd[34] RW[1][2] 210*b35ce0c4SPankaj Gupta * 0x054023 0x47 cdd[35] RW[1][1] 211*b35ce0c4SPankaj Gupta * 0x054024 0x48 cdd[36] RW[1][0] 212*b35ce0c4SPankaj Gupta * 0x054024 0x49 cdd[37] RW[0][3] 213*b35ce0c4SPankaj Gupta * 0x054025 0x4a cdd[38] RW[0][2] 214*b35ce0c4SPankaj Gupta * 0x054025 0x4b cdd[39] RW[0][1] 215*b35ce0c4SPankaj Gupta * 0x054026 0x4c cdd[40] RW[0][0] 216*b35ce0c4SPankaj Gupta 217*b35ce0c4SPankaj Gupta * 0x054026 0x4d cdd[41] WR[3][3] 218*b35ce0c4SPankaj Gupta * 0x054027 0x4e cdd[42] WR[3][2] 219*b35ce0c4SPankaj Gupta * 0x054027 0x4f cdd[43] WR[3][1] 220*b35ce0c4SPankaj Gupta * 0x054028 0x50 cdd[44] WR[3][0] 221*b35ce0c4SPankaj Gupta * 0x054028 0x51 cdd[45] WR[2][3] 222*b35ce0c4SPankaj Gupta * 0x054029 0x52 cdd[46] WR[2][2] 223*b35ce0c4SPankaj Gupta * 0x054029 0x53 cdd[47] WR[2][1] 224*b35ce0c4SPankaj Gupta * 0x05402a 0x54 cdd[48] WR[2][0] 225*b35ce0c4SPankaj Gupta * 0x05402a 0x55 cdd[49] WR[1][3] 226*b35ce0c4SPankaj Gupta * 0x05402b 0x56 cdd[50] WR[1][2] 227*b35ce0c4SPankaj Gupta * 0x05402b 0x57 cdd[51] WR[1][1] 228*b35ce0c4SPankaj Gupta * 0x05402c 0x58 cdd[52] WR[1][0] 229*b35ce0c4SPankaj Gupta * 0x05402c 0x59 cdd[53] WR[0][3] 230*b35ce0c4SPankaj Gupta * 0x05402d 0x5a cdd[54] WR[0][2] 231*b35ce0c4SPankaj Gupta * 0x05402d 0x5b cdd[55] WR[0][1] 232*b35ce0c4SPankaj Gupta * 0x05402e 0x5c cdd[56] WR[0][0] 233*b35ce0c4SPankaj Gupta * 0x05402e 0x5d cdd[57] CDD[Y][Y] 234*b35ce0c4SPankaj Gupta */ 235*b35ce0c4SPankaj Gupta 236*b35ce0c4SPankaj Gupta switch (rank) { 237*b35ce0c4SPankaj Gupta case 1U: 238*b35ce0c4SPankaj Gupta tmp = rwmax; 239*b35ce0c4SPankaj Gupta rwmax = cdd[40]; 240*b35ce0c4SPankaj Gupta if (tmp > rwmax) { 241*b35ce0c4SPankaj Gupta rwmax = tmp; 242*b35ce0c4SPankaj Gupta } 243*b35ce0c4SPankaj Gupta 244*b35ce0c4SPankaj Gupta tmp = wrmax; 245*b35ce0c4SPankaj Gupta wrmax = cdd[56]; 246*b35ce0c4SPankaj Gupta if (tmp > wrmax) { 247*b35ce0c4SPankaj Gupta wrmax = tmp; 248*b35ce0c4SPankaj Gupta } 249*b35ce0c4SPankaj Gupta 250*b35ce0c4SPankaj Gupta break; 251*b35ce0c4SPankaj Gupta 252*b35ce0c4SPankaj Gupta case 2U: 253*b35ce0c4SPankaj Gupta buf[0] = cdd[12]; 254*b35ce0c4SPankaj Gupta buf[1] = cdd[9]; 255*b35ce0c4SPankaj Gupta tmp = rrmax; 256*b35ce0c4SPankaj Gupta rrmax = findmax(buf, 2U); 257*b35ce0c4SPankaj Gupta if (tmp > rrmax) { 258*b35ce0c4SPankaj Gupta rrmax = tmp; 259*b35ce0c4SPankaj Gupta } 260*b35ce0c4SPankaj Gupta 261*b35ce0c4SPankaj Gupta buf[0] = cdd[24]; 262*b35ce0c4SPankaj Gupta buf[1] = cdd[21]; 263*b35ce0c4SPankaj Gupta tmp = wwmax; 264*b35ce0c4SPankaj Gupta wwmax = findmax(buf, 2U); 265*b35ce0c4SPankaj Gupta if (tmp > wwmax) { 266*b35ce0c4SPankaj Gupta wwmax = tmp; 267*b35ce0c4SPankaj Gupta } 268*b35ce0c4SPankaj Gupta 269*b35ce0c4SPankaj Gupta buf[0] = cdd[40]; 270*b35ce0c4SPankaj Gupta buf[1] = cdd[39]; 271*b35ce0c4SPankaj Gupta buf[2] = cdd[36]; 272*b35ce0c4SPankaj Gupta buf[3] = cdd[35]; 273*b35ce0c4SPankaj Gupta tmp = rwmax; 274*b35ce0c4SPankaj Gupta rwmax = findmax(buf, 4U); 275*b35ce0c4SPankaj Gupta if (tmp > rwmax) { 276*b35ce0c4SPankaj Gupta rwmax = tmp; 277*b35ce0c4SPankaj Gupta } 278*b35ce0c4SPankaj Gupta 279*b35ce0c4SPankaj Gupta buf[0] = cdd[56]; 280*b35ce0c4SPankaj Gupta buf[1] = cdd[55]; 281*b35ce0c4SPankaj Gupta buf[2] = cdd[52]; 282*b35ce0c4SPankaj Gupta buf[3] = cdd[51]; 283*b35ce0c4SPankaj Gupta tmp = wrmax; 284*b35ce0c4SPankaj Gupta wrmax = findmax(buf, 4U); 285*b35ce0c4SPankaj Gupta if (tmp > wrmax) { 286*b35ce0c4SPankaj Gupta wrmax = tmp; 287*b35ce0c4SPankaj Gupta } 288*b35ce0c4SPankaj Gupta 289*b35ce0c4SPankaj Gupta break; 290*b35ce0c4SPankaj Gupta 291*b35ce0c4SPankaj Gupta case 4U: 292*b35ce0c4SPankaj Gupta tmp = rrmax; 293*b35ce0c4SPankaj Gupta c = &cdd[1]; 294*b35ce0c4SPankaj Gupta rrmax = findmax(c, 12U); 295*b35ce0c4SPankaj Gupta if (tmp > rrmax) { 296*b35ce0c4SPankaj Gupta rrmax = tmp; 297*b35ce0c4SPankaj Gupta } 298*b35ce0c4SPankaj Gupta 299*b35ce0c4SPankaj Gupta tmp = wwmax; 300*b35ce0c4SPankaj Gupta c = &cdd[13]; 301*b35ce0c4SPankaj Gupta wwmax = findmax(c, 12U); 302*b35ce0c4SPankaj Gupta if (tmp > wwmax) { 303*b35ce0c4SPankaj Gupta wwmax = tmp; 304*b35ce0c4SPankaj Gupta } 305*b35ce0c4SPankaj Gupta 306*b35ce0c4SPankaj Gupta tmp = rwmax; 307*b35ce0c4SPankaj Gupta c = &cdd[25]; 308*b35ce0c4SPankaj Gupta rwmax = findmax(c, 16U); 309*b35ce0c4SPankaj Gupta if (tmp > rwmax) { 310*b35ce0c4SPankaj Gupta rwmax = tmp; 311*b35ce0c4SPankaj Gupta } 312*b35ce0c4SPankaj Gupta 313*b35ce0c4SPankaj Gupta tmp = wrmax; 314*b35ce0c4SPankaj Gupta c = &cdd[41]; 315*b35ce0c4SPankaj Gupta wrmax = findmax(c, 16U); 316*b35ce0c4SPankaj Gupta if (tmp > wrmax) { 317*b35ce0c4SPankaj Gupta wrmax = tmp; 318*b35ce0c4SPankaj Gupta } 319*b35ce0c4SPankaj Gupta 320*b35ce0c4SPankaj Gupta break; 321*b35ce0c4SPankaj Gupta 322*b35ce0c4SPankaj Gupta } 323*b35ce0c4SPankaj Gupta } 324*b35ce0c4SPankaj Gupta 325*b35ce0c4SPankaj Gupta rrmax += 3U; 326*b35ce0c4SPankaj Gupta wwmax += 4U; 327*b35ce0c4SPankaj Gupta 328*b35ce0c4SPankaj Gupta if (wwmax > 7U) { 329*b35ce0c4SPankaj Gupta wwmax = 7U; 330*b35ce0c4SPankaj Gupta } 331*b35ce0c4SPankaj Gupta 332*b35ce0c4SPankaj Gupta if (rrmax > 7U) { 333*b35ce0c4SPankaj Gupta rrmax = 7U; 334*b35ce0c4SPankaj Gupta } 335*b35ce0c4SPankaj Gupta 336*b35ce0c4SPankaj Gupta if (wrmax > U(0xf)) { 337*b35ce0c4SPankaj Gupta wrmax = 0U; 338*b35ce0c4SPankaj Gupta } 339*b35ce0c4SPankaj Gupta 340*b35ce0c4SPankaj Gupta if (rwmax > U(0x7)) { 341*b35ce0c4SPankaj Gupta rwmax = U(0x7); 342*b35ce0c4SPankaj Gupta } 343*b35ce0c4SPankaj Gupta 344*b35ce0c4SPankaj Gupta val = *tcfg0; 345*b35ce0c4SPankaj Gupta tww = (val >> 24U) & U(0x3); 346*b35ce0c4SPankaj Gupta trr = (val >> 26U) & U(0x3); 347*b35ce0c4SPankaj Gupta twr = (val >> 28U) & U(0x3); 348*b35ce0c4SPankaj Gupta trw = (val >> 30U) & U(0x3); 349*b35ce0c4SPankaj Gupta 350*b35ce0c4SPankaj Gupta val = *tcfg4; 351*b35ce0c4SPankaj Gupta tww = tww | (((val >> 8U) & U(0x1)) << 2U); 352*b35ce0c4SPankaj Gupta trr = trr | (((val >> 10U) & U(0x1)) << 2U); 353*b35ce0c4SPankaj Gupta twr = twr | (((val >> 12U) & U(0x1)) << 2U); 354*b35ce0c4SPankaj Gupta trw = trw | (((val >> 14U) & U(0x3)) << 2U); 355*b35ce0c4SPankaj Gupta 356*b35ce0c4SPankaj Gupta if (trr > rrmax) { 357*b35ce0c4SPankaj Gupta rrmax = trr; 358*b35ce0c4SPankaj Gupta } 359*b35ce0c4SPankaj Gupta 360*b35ce0c4SPankaj Gupta if (tww > wwmax) { 361*b35ce0c4SPankaj Gupta wwmax = tww; 362*b35ce0c4SPankaj Gupta } 363*b35ce0c4SPankaj Gupta 364*b35ce0c4SPankaj Gupta if (trw > rwmax) { 365*b35ce0c4SPankaj Gupta rwmax = trw; 366*b35ce0c4SPankaj Gupta } 367*b35ce0c4SPankaj Gupta 368*b35ce0c4SPankaj Gupta if (twr > wrmax) { 369*b35ce0c4SPankaj Gupta wrmax = twr; 370*b35ce0c4SPankaj Gupta } 371*b35ce0c4SPankaj Gupta 372*b35ce0c4SPankaj Gupta debug("CDD rrmax %x wwmax %x rwmax %x wrmax %x\n", 373*b35ce0c4SPankaj Gupta rrmax, wwmax, rwmax, wrmax); 374*b35ce0c4SPankaj Gupta 375*b35ce0c4SPankaj Gupta val = ((wwmax & U(0x3)) << 24U) 376*b35ce0c4SPankaj Gupta | ((rrmax & U(0x3)) << 26U) 377*b35ce0c4SPankaj Gupta | ((wrmax & U(0x3)) << 28U) 378*b35ce0c4SPankaj Gupta | ((rwmax & U(0x3)) << 30U); 379*b35ce0c4SPankaj Gupta 380*b35ce0c4SPankaj Gupta *tcfg0 = (*tcfg0 & U(0x00FFFFFF)) | (val); 381*b35ce0c4SPankaj Gupta 382*b35ce0c4SPankaj Gupta val = (((wwmax >> 2U) & U(0x1)) << 8U) 383*b35ce0c4SPankaj Gupta | (((rrmax >> 2U) & U(0x1)) << 10U) 384*b35ce0c4SPankaj Gupta | (((wrmax >> 2U) & U(0x1)) << 12U) 385*b35ce0c4SPankaj Gupta | (((rwmax >> 2U) & U(0x3)) << 14U); 386*b35ce0c4SPankaj Gupta 387*b35ce0c4SPankaj Gupta *tcfg4 = (*tcfg4 & U(0xffff00ff)) | val; 388*b35ce0c4SPankaj Gupta } 389*b35ce0c4SPankaj Gupta #endif 390*b35ce0c4SPankaj Gupta 391*b35ce0c4SPankaj Gupta #ifdef NXP_WARM_BOOT 392*b35ce0c4SPankaj Gupta int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store, 393*b35ce0c4SPankaj Gupta uint32_t num_of_phy, int train2d) 394*b35ce0c4SPankaj Gupta { 395*b35ce0c4SPankaj Gupta uint16_t *phy = NULL, value = 0x0; 396*b35ce0c4SPankaj Gupta uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; 397*b35ce0c4SPankaj Gupta int i = 0, j = 0, ret = -EINVAL; 398*b35ce0c4SPankaj Gupta 399*b35ce0c4SPankaj Gupta ret = xspi_sector_erase(address_to_store, PHY_ERASE_SIZE); 400*b35ce0c4SPankaj Gupta if (ret != 0) { 401*b35ce0c4SPankaj Gupta return -EINVAL; 402*b35ce0c4SPankaj Gupta } 403*b35ce0c4SPankaj Gupta 404*b35ce0c4SPankaj Gupta for (j = 0; j < num_of_phy; j++) { 405*b35ce0c4SPankaj Gupta /* Save training values of all PHYs */ 406*b35ce0c4SPankaj Gupta phy = phy_ptr[j]; 407*b35ce0c4SPankaj Gupta size = sizeof(training_1D_values); 408*b35ce0c4SPankaj Gupta num_of_regs = ARRAY_SIZE(training_1D_values); 409*b35ce0c4SPankaj Gupta 410*b35ce0c4SPankaj Gupta /* Enable access to the internal CSRs */ 411*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 412*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, 0x0); 413*b35ce0c4SPankaj Gupta /* Enable clocks in case they were disabled. */ 414*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_drtub | 415*b35ce0c4SPankaj Gupta csr_ucclk_hclk_enables_addr, 0x3); 416*b35ce0c4SPankaj Gupta if (train2d != 0) { 417*b35ce0c4SPankaj Gupta /* Address to store training values is 418*b35ce0c4SPankaj Gupta * to be appended for next PHY 419*b35ce0c4SPankaj Gupta */ 420*b35ce0c4SPankaj Gupta phy_store = address_to_store + (j * 421*b35ce0c4SPankaj Gupta (sizeof(training_1D_values) + 422*b35ce0c4SPankaj Gupta sizeof(training_2D_values))); 423*b35ce0c4SPankaj Gupta } else { 424*b35ce0c4SPankaj Gupta phy_store = address_to_store + (j * 425*b35ce0c4SPankaj Gupta (sizeof(training_1D_values))); 426*b35ce0c4SPankaj Gupta } 427*b35ce0c4SPankaj Gupta debug("Saving 1D Training reg val at: %d\n", phy_store); 428*b35ce0c4SPankaj Gupta for (i = 0; i < num_of_regs; i++) { 429*b35ce0c4SPankaj Gupta value = phy_io_read16(phy, training_1D_values[i].addr); 430*b35ce0c4SPankaj Gupta #ifdef DEBUG_WARM_RESET 431*b35ce0c4SPankaj Gupta debug("%d. Reg: %x, value: %x PHY: %p\n", i, 432*b35ce0c4SPankaj Gupta training_1D_values[i].addr, value, 433*b35ce0c4SPankaj Gupta phy_io_addr(phy, 434*b35ce0c4SPankaj Gupta training_1D_values[i].addr)); 435*b35ce0c4SPankaj Gupta #endif 436*b35ce0c4SPankaj Gupta training_1D_values[i].data = value; 437*b35ce0c4SPankaj Gupta } 438*b35ce0c4SPankaj Gupta /* Storing 1D training values on flash */ 439*b35ce0c4SPankaj Gupta ret = xspi_write(phy_store, (void *)training_1D_values, size); 440*b35ce0c4SPankaj Gupta if (train2d != 0) { 441*b35ce0c4SPankaj Gupta phy_store = phy_store+size; 442*b35ce0c4SPankaj Gupta size = sizeof(training_2D_values); 443*b35ce0c4SPankaj Gupta num_of_regs = ARRAY_SIZE(training_2D_values); 444*b35ce0c4SPankaj Gupta debug("Saving 2D Training reg val at:%d\n", phy_store); 445*b35ce0c4SPankaj Gupta for (i = 0; i < num_of_regs; i++) { 446*b35ce0c4SPankaj Gupta value = phy_io_read16(phy, 447*b35ce0c4SPankaj Gupta training_2D_values[i].addr); 448*b35ce0c4SPankaj Gupta training_2D_values[i].data = value; 449*b35ce0c4SPankaj Gupta #ifdef DEBUG_WARM_RESET 450*b35ce0c4SPankaj Gupta debug("%d.2D addr:0x%x,val:0x%x,PHY:0x%p\n", 451*b35ce0c4SPankaj Gupta i, training_2D_values[i].addr, 452*b35ce0c4SPankaj Gupta value, phy_io_addr(phy, 453*b35ce0c4SPankaj Gupta training_2D_values[i].addr)); 454*b35ce0c4SPankaj Gupta #endif 455*b35ce0c4SPankaj Gupta } 456*b35ce0c4SPankaj Gupta /* Storing 2D training values on flash */ 457*b35ce0c4SPankaj Gupta ret = xspi_write(phy_store, training_2D_values, 458*b35ce0c4SPankaj Gupta size); 459*b35ce0c4SPankaj Gupta } 460*b35ce0c4SPankaj Gupta /* Disable clocks in case they were disabled. */ 461*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_drtub | 462*b35ce0c4SPankaj Gupta csr_ucclk_hclk_enables_addr, 0x0); 463*b35ce0c4SPankaj Gupta /* Disable access to the internal CSRs */ 464*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 465*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, 0x1); 466*b35ce0c4SPankaj Gupta } 467*b35ce0c4SPankaj Gupta if (ret != 0) { 468*b35ce0c4SPankaj Gupta return -EINVAL; 469*b35ce0c4SPankaj Gupta } 470*b35ce0c4SPankaj Gupta 471*b35ce0c4SPankaj Gupta return 0; 472*b35ce0c4SPankaj Gupta } 473*b35ce0c4SPankaj Gupta 474*b35ce0c4SPankaj Gupta int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore, 475*b35ce0c4SPankaj Gupta uint32_t num_of_phy, int train2d) 476*b35ce0c4SPankaj Gupta { 477*b35ce0c4SPankaj Gupta uint16_t *phy = NULL; 478*b35ce0c4SPankaj Gupta uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; 479*b35ce0c4SPankaj Gupta int i = 0, j = 0, ret = -EINVAL; 480*b35ce0c4SPankaj Gupta 481*b35ce0c4SPankaj Gupta debug("Restoring Training register values\n"); 482*b35ce0c4SPankaj Gupta for (j = 0; j < num_of_phy; j++) { 483*b35ce0c4SPankaj Gupta phy = phy_ptr[j]; 484*b35ce0c4SPankaj Gupta size = sizeof(training_1D_values); 485*b35ce0c4SPankaj Gupta num_of_regs = ARRAY_SIZE(training_1D_values); 486*b35ce0c4SPankaj Gupta if (train2d != 0) { 487*b35ce0c4SPankaj Gupta /* The address to restore training values is 488*b35ce0c4SPankaj Gupta * to be appended for next PHY 489*b35ce0c4SPankaj Gupta */ 490*b35ce0c4SPankaj Gupta phy_store = address_to_restore + (j * 491*b35ce0c4SPankaj Gupta (sizeof(training_1D_values) + 492*b35ce0c4SPankaj Gupta sizeof(training_2D_values))); 493*b35ce0c4SPankaj Gupta } else { 494*b35ce0c4SPankaj Gupta phy_store = address_to_restore + (j * 495*b35ce0c4SPankaj Gupta (sizeof(training_1D_values))); 496*b35ce0c4SPankaj Gupta } 497*b35ce0c4SPankaj Gupta /* Enable access to the internal CSRs */ 498*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 499*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, 0x0); 500*b35ce0c4SPankaj Gupta /* Enable clocks in case they were disabled. */ 501*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_drtub | 502*b35ce0c4SPankaj Gupta csr_ucclk_hclk_enables_addr, 0x3); 503*b35ce0c4SPankaj Gupta 504*b35ce0c4SPankaj Gupta /* Reading 1D training values from flash*/ 505*b35ce0c4SPankaj Gupta ret = xspi_read(phy_store, (uint32_t *)training_1D_values, 506*b35ce0c4SPankaj Gupta size); 507*b35ce0c4SPankaj Gupta debug("Restoring 1D Training reg val at:%08x\n", phy_store); 508*b35ce0c4SPankaj Gupta for (i = 0; i < num_of_regs; i++) { 509*b35ce0c4SPankaj Gupta phy_io_write16(phy, training_1D_values[i].addr, 510*b35ce0c4SPankaj Gupta training_1D_values[i].data); 511*b35ce0c4SPankaj Gupta #ifdef DEBUG_WARM_RESET 512*b35ce0c4SPankaj Gupta debug("%d. Reg: %x, value: %x PHY: %p\n", i, 513*b35ce0c4SPankaj Gupta training_1D_values[i].addr, 514*b35ce0c4SPankaj Gupta training_1D_values[i].data, 515*b35ce0c4SPankaj Gupta phy_io_addr(phy, 516*b35ce0c4SPankaj Gupta training_1D_values[i].addr)); 517*b35ce0c4SPankaj Gupta #endif 518*b35ce0c4SPankaj Gupta } 519*b35ce0c4SPankaj Gupta if (train2d != 0) { 520*b35ce0c4SPankaj Gupta phy_store = phy_store + size; 521*b35ce0c4SPankaj Gupta size = sizeof(training_2D_values); 522*b35ce0c4SPankaj Gupta num_of_regs = ARRAY_SIZE(training_2D_values); 523*b35ce0c4SPankaj Gupta /* Reading 2D training values from flash */ 524*b35ce0c4SPankaj Gupta ret = xspi_read(phy_store, 525*b35ce0c4SPankaj Gupta (uint32_t *)training_2D_values, size); 526*b35ce0c4SPankaj Gupta debug("Restoring 2D Training reg val at:%08x\n", 527*b35ce0c4SPankaj Gupta phy_store); 528*b35ce0c4SPankaj Gupta for (i = 0; i < num_of_regs; i++) { 529*b35ce0c4SPankaj Gupta phy_io_write16(phy, training_2D_values[i].addr, 530*b35ce0c4SPankaj Gupta training_2D_values[i].data); 531*b35ce0c4SPankaj Gupta #ifdef DEBUG_WARM_RESET 532*b35ce0c4SPankaj Gupta debug("%d. Reg: %x, value: %x PHY: %p\n", i, 533*b35ce0c4SPankaj Gupta training_2D_values[i].addr, 534*b35ce0c4SPankaj Gupta training_2D_values[i].data, 535*b35ce0c4SPankaj Gupta phy_io_addr(phy, 536*b35ce0c4SPankaj Gupta training_1D_values[i].addr)); 537*b35ce0c4SPankaj Gupta #endif 538*b35ce0c4SPankaj Gupta } 539*b35ce0c4SPankaj Gupta } 540*b35ce0c4SPankaj Gupta /* Disable clocks in case they were disabled. */ 541*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_drtub | 542*b35ce0c4SPankaj Gupta csr_ucclk_hclk_enables_addr, 0x0); 543*b35ce0c4SPankaj Gupta /* Disable access to the internal CSRs */ 544*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | 545*b35ce0c4SPankaj Gupta csr_micro_cont_mux_sel_addr, 0x1); 546*b35ce0c4SPankaj Gupta } 547*b35ce0c4SPankaj Gupta if (ret != 0) { 548*b35ce0c4SPankaj Gupta return -EINVAL; 549*b35ce0c4SPankaj Gupta } 550*b35ce0c4SPankaj Gupta return 0; 551*b35ce0c4SPankaj Gupta } 552*b35ce0c4SPankaj Gupta #endif 553*b35ce0c4SPankaj Gupta 554*b35ce0c4SPankaj Gupta static void load_pieimage(uint16_t *phy, 555*b35ce0c4SPankaj Gupta enum dimm_types dimm_type) 556*b35ce0c4SPankaj Gupta { 557*b35ce0c4SPankaj Gupta int i; 558*b35ce0c4SPankaj Gupta int size; 559*b35ce0c4SPankaj Gupta const struct pie *image = NULL; 560*b35ce0c4SPankaj Gupta 561*b35ce0c4SPankaj Gupta switch (dimm_type) { 562*b35ce0c4SPankaj Gupta case UDIMM: 563*b35ce0c4SPankaj Gupta case SODIMM: 564*b35ce0c4SPankaj Gupta case NODIMM: 565*b35ce0c4SPankaj Gupta image = pie_udimm; 566*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(pie_udimm); 567*b35ce0c4SPankaj Gupta break; 568*b35ce0c4SPankaj Gupta case RDIMM: 569*b35ce0c4SPankaj Gupta image = pie_rdimm; 570*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(pie_rdimm); 571*b35ce0c4SPankaj Gupta break; 572*b35ce0c4SPankaj Gupta case LRDIMM: 573*b35ce0c4SPankaj Gupta image = pie_lrdimm; 574*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(pie_lrdimm); 575*b35ce0c4SPankaj Gupta break; 576*b35ce0c4SPankaj Gupta default: 577*b35ce0c4SPankaj Gupta printf("Unsupported DIMM type\n"); 578*b35ce0c4SPankaj Gupta break; 579*b35ce0c4SPankaj Gupta } 580*b35ce0c4SPankaj Gupta 581*b35ce0c4SPankaj Gupta if (image != NULL) { 582*b35ce0c4SPankaj Gupta for (i = 0; i < size; i++) 583*b35ce0c4SPankaj Gupta phy_io_write16(phy, image[i].addr, image[i].data); 584*b35ce0c4SPankaj Gupta } 585*b35ce0c4SPankaj Gupta } 586*b35ce0c4SPankaj Gupta 587*b35ce0c4SPankaj Gupta static void prog_acsm_playback(uint16_t *phy, 588*b35ce0c4SPankaj Gupta const struct input *input, const void *msg) 589*b35ce0c4SPankaj Gupta { 590*b35ce0c4SPankaj Gupta int vec; 591*b35ce0c4SPankaj Gupta const struct ddr4r1d *msg_blk; 592*b35ce0c4SPankaj Gupta uint16_t acsmplayback[2][3]; 593*b35ce0c4SPankaj Gupta uint32_t f0rc0a; 594*b35ce0c4SPankaj Gupta uint32_t f0rc3x; 595*b35ce0c4SPankaj Gupta uint32_t f0rc5x; 596*b35ce0c4SPankaj Gupta 597*b35ce0c4SPankaj Gupta if (input->basic.dimm_type != RDIMM) { 598*b35ce0c4SPankaj Gupta return; 599*b35ce0c4SPankaj Gupta } 600*b35ce0c4SPankaj Gupta 601*b35ce0c4SPankaj Gupta msg_blk = msg; 602*b35ce0c4SPankaj Gupta f0rc0a = (msg_blk->f0rc0a_d0 & U(0xf)) | U(0xa0); 603*b35ce0c4SPankaj Gupta f0rc3x = (msg_blk->f0rc3x_d0 & U(0xff)) | U(0x300); 604*b35ce0c4SPankaj Gupta f0rc5x = (input->adv.phy_gen2_umctl_f0rc5x & U(0xff)) | U(0x500); 605*b35ce0c4SPankaj Gupta 606*b35ce0c4SPankaj Gupta acsmplayback[0][0] = U(0x3ff) & f0rc0a; 607*b35ce0c4SPankaj Gupta acsmplayback[1][0] = (U(0x1c00) & f0rc0a) >> 10U; 608*b35ce0c4SPankaj Gupta acsmplayback[0][1] = U(0x3ff) & f0rc3x; 609*b35ce0c4SPankaj Gupta acsmplayback[1][1] = (U(0x1c00) & f0rc3x) >> 10U; 610*b35ce0c4SPankaj Gupta acsmplayback[0][2] = U(0x3ff) & f0rc5x; 611*b35ce0c4SPankaj Gupta acsmplayback[1][2] = (U(0x1c00) & f0rc5x) >> 10U; 612*b35ce0c4SPankaj Gupta for (vec = 0; vec < 3; vec++) { 613*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_acsm | (csr_acsm_playback0x0_addr + 614*b35ce0c4SPankaj Gupta (vec << 1)), acsmplayback[0][vec]); 615*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_acsm | (csr_acsm_playback1x0_addr + 616*b35ce0c4SPankaj Gupta (vec << 1)), acsmplayback[1][vec]); 617*b35ce0c4SPankaj Gupta } 618*b35ce0c4SPankaj Gupta } 619*b35ce0c4SPankaj Gupta 620*b35ce0c4SPankaj Gupta static void prog_acsm_ctr(uint16_t *phy, 621*b35ce0c4SPankaj Gupta const struct input *input) 622*b35ce0c4SPankaj Gupta { 623*b35ce0c4SPankaj Gupta if (input->basic.dimm_type != RDIMM) { 624*b35ce0c4SPankaj Gupta return; 625*b35ce0c4SPankaj Gupta } 626*b35ce0c4SPankaj Gupta 627*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_acsm | csr_acsm_ctrl13_addr, 628*b35ce0c4SPankaj Gupta 0xf << csr_acsm_cke_enb_lsb); 629*b35ce0c4SPankaj Gupta 630*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_acsm | csr_acsm_ctrl0_addr, 631*b35ce0c4SPankaj Gupta csr_acsm_par_mode_mask | csr_acsm_2t_mode_mask); 632*b35ce0c4SPankaj Gupta } 633*b35ce0c4SPankaj Gupta 634*b35ce0c4SPankaj Gupta static void prog_cal_rate_run(uint16_t *phy, 635*b35ce0c4SPankaj Gupta const struct input *input) 636*b35ce0c4SPankaj Gupta { 637*b35ce0c4SPankaj Gupta int cal_rate; 638*b35ce0c4SPankaj Gupta int cal_interval; 639*b35ce0c4SPankaj Gupta int cal_once; 640*b35ce0c4SPankaj Gupta uint32_t addr; 641*b35ce0c4SPankaj Gupta 642*b35ce0c4SPankaj Gupta cal_interval = input->adv.cal_interval; 643*b35ce0c4SPankaj Gupta cal_once = input->adv.cal_once; 644*b35ce0c4SPankaj Gupta cal_rate = 0x1 << csr_cal_run_lsb | 645*b35ce0c4SPankaj Gupta cal_once << csr_cal_once_lsb | 646*b35ce0c4SPankaj Gupta cal_interval << csr_cal_interval_lsb; 647*b35ce0c4SPankaj Gupta addr = t_master | csr_cal_rate_addr; 648*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_rate); 649*b35ce0c4SPankaj Gupta } 650*b35ce0c4SPankaj Gupta 651*b35ce0c4SPankaj Gupta static void prog_seq0bdly0(uint16_t *phy, 652*b35ce0c4SPankaj Gupta const struct input *input) 653*b35ce0c4SPankaj Gupta { 654*b35ce0c4SPankaj Gupta int ps_count[4]; 655*b35ce0c4SPankaj Gupta int frq; 656*b35ce0c4SPankaj Gupta uint32_t addr; 657*b35ce0c4SPankaj Gupta int lower_freq_opt = 0; 658*b35ce0c4SPankaj Gupta 659*b35ce0c4SPankaj Gupta __unused const soc_info_t *soc_info; 660*b35ce0c4SPankaj Gupta 661*b35ce0c4SPankaj Gupta frq = input->basic.frequency >> 1; 662*b35ce0c4SPankaj Gupta ps_count[0] = frq >> 3; /* 0.5 * frq / 4*/ 663*b35ce0c4SPankaj Gupta if (input->basic.frequency < 400) { 664*b35ce0c4SPankaj Gupta lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 7 : 3; 665*b35ce0c4SPankaj Gupta } else if (input->basic.frequency < 533) { 666*b35ce0c4SPankaj Gupta lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 14 : 11; 667*b35ce0c4SPankaj Gupta } 668*b35ce0c4SPankaj Gupta 669*b35ce0c4SPankaj Gupta /* 1.0 * frq / 4 - lower_freq */ 670*b35ce0c4SPankaj Gupta ps_count[1] = (frq >> 2) - lower_freq_opt; 671*b35ce0c4SPankaj Gupta ps_count[2] = (frq << 1) + (frq >> 1); /* 10.0 * frq / 4 */ 672*b35ce0c4SPankaj Gupta 673*b35ce0c4SPankaj Gupta #ifdef DDR_PLL_FIX 674*b35ce0c4SPankaj Gupta soc_info = get_soc_info(); 675*b35ce0c4SPankaj Gupta if (soc_info->maj_ver == 1) { 676*b35ce0c4SPankaj Gupta ps_count[0] = 0x520; /* seq0bdly0 */ 677*b35ce0c4SPankaj Gupta ps_count[1] = 0xa41; /* seq0bdly1 */ 678*b35ce0c4SPankaj Gupta ps_count[2] = 0x668a; /* seq0bdly2 */ 679*b35ce0c4SPankaj Gupta } 680*b35ce0c4SPankaj Gupta #endif 681*b35ce0c4SPankaj Gupta if (frq > 266) { 682*b35ce0c4SPankaj Gupta ps_count[3] = 44; 683*b35ce0c4SPankaj Gupta } else if (frq > 200) { 684*b35ce0c4SPankaj Gupta ps_count[3] = 33; 685*b35ce0c4SPankaj Gupta } else { 686*b35ce0c4SPankaj Gupta ps_count[3] = 16; 687*b35ce0c4SPankaj Gupta } 688*b35ce0c4SPankaj Gupta 689*b35ce0c4SPankaj Gupta addr = t_master | csr_seq0bdly0_addr; 690*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, ps_count[0]); 691*b35ce0c4SPankaj Gupta 692*b35ce0c4SPankaj Gupta debug("seq0bdly0 = 0x%x\n", phy_io_read16(phy, addr)); 693*b35ce0c4SPankaj Gupta 694*b35ce0c4SPankaj Gupta addr = t_master | csr_seq0bdly1_addr; 695*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, ps_count[1]); 696*b35ce0c4SPankaj Gupta 697*b35ce0c4SPankaj Gupta debug("seq0bdly1 = 0x%x\n", phy_io_read16(phy, addr)); 698*b35ce0c4SPankaj Gupta 699*b35ce0c4SPankaj Gupta addr = t_master | csr_seq0bdly2_addr; 700*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, ps_count[2]); 701*b35ce0c4SPankaj Gupta 702*b35ce0c4SPankaj Gupta debug("seq0bdly2 = 0x%x\n", phy_io_read16(phy, addr)); 703*b35ce0c4SPankaj Gupta 704*b35ce0c4SPankaj Gupta addr = t_master | csr_seq0bdly3_addr; 705*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, ps_count[3]); 706*b35ce0c4SPankaj Gupta 707*b35ce0c4SPankaj Gupta debug("seq0bdly3 = 0x%x\n", phy_io_read16(phy, addr)); 708*b35ce0c4SPankaj Gupta } 709*b35ce0c4SPankaj Gupta 710*b35ce0c4SPankaj Gupta /* Only RDIMM requires msg_blk */ 711*b35ce0c4SPankaj Gupta static void i_load_pie(uint16_t **phy_ptr, 712*b35ce0c4SPankaj Gupta const struct input *input, 713*b35ce0c4SPankaj Gupta const void *msg) 714*b35ce0c4SPankaj Gupta { 715*b35ce0c4SPankaj Gupta int i; 716*b35ce0c4SPankaj Gupta uint16_t *phy; 717*b35ce0c4SPankaj Gupta 718*b35ce0c4SPankaj Gupta for (i = 0; i < NUM_OF_DDRC; i++) { 719*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 720*b35ce0c4SPankaj Gupta if (phy == NULL) { 721*b35ce0c4SPankaj Gupta continue; 722*b35ce0c4SPankaj Gupta } 723*b35ce0c4SPankaj Gupta 724*b35ce0c4SPankaj Gupta phy_io_write16(phy, 725*b35ce0c4SPankaj Gupta t_apbonly | csr_micro_cont_mux_sel_addr, 726*b35ce0c4SPankaj Gupta 0U); 727*b35ce0c4SPankaj Gupta 728*b35ce0c4SPankaj Gupta load_pieimage(phy, input->basic.dimm_type); 729*b35ce0c4SPankaj Gupta 730*b35ce0c4SPankaj Gupta prog_seq0bdly0(phy, input); 731*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag0_addr, 732*b35ce0c4SPankaj Gupta U(0x0000)); 733*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag1_addr, 734*b35ce0c4SPankaj Gupta U(0x0173)); 735*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag2_addr, 736*b35ce0c4SPankaj Gupta U(0x0060)); 737*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag3_addr, 738*b35ce0c4SPankaj Gupta U(0x6110)); 739*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag4_addr, 740*b35ce0c4SPankaj Gupta U(0x2152)); 741*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag5_addr, 742*b35ce0c4SPankaj Gupta U(0xdfbd)); 743*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag6_addr, 744*b35ce0c4SPankaj Gupta input->basic.dimm_type == RDIMM && 745*b35ce0c4SPankaj Gupta input->adv.phy_gen2_umctl_opt == 1U ? 746*b35ce0c4SPankaj Gupta U(0x6000) : U(0xffff)); 747*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag7_addr, 748*b35ce0c4SPankaj Gupta U(0x6152)); 749*b35ce0c4SPankaj Gupta prog_acsm_playback(phy, input, msg); /* rdimm */ 750*b35ce0c4SPankaj Gupta prog_acsm_ctr(phy, input); /* rdimm */ 751*b35ce0c4SPankaj Gupta 752*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_master | csr_cal_zap_addr, U(0x1)); 753*b35ce0c4SPankaj Gupta prog_cal_rate_run(phy, input); 754*b35ce0c4SPankaj Gupta 755*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_drtub | csr_ucclk_hclk_enables_addr, 756*b35ce0c4SPankaj Gupta input->basic.dimm_type == RDIMM ? U(0x2) : 0U); 757*b35ce0c4SPankaj Gupta 758*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 1U); 759*b35ce0c4SPankaj Gupta } 760*b35ce0c4SPankaj Gupta } 761*b35ce0c4SPankaj Gupta 762*b35ce0c4SPankaj Gupta static void phy_gen2_init_input(struct input *input) 763*b35ce0c4SPankaj Gupta { 764*b35ce0c4SPankaj Gupta int i; 765*b35ce0c4SPankaj Gupta 766*b35ce0c4SPankaj Gupta input->adv.dram_byte_swap = 0; 767*b35ce0c4SPankaj Gupta input->adv.ext_cal_res_val = 0; 768*b35ce0c4SPankaj Gupta input->adv.tx_slew_rise_dq = 0xf; 769*b35ce0c4SPankaj Gupta input->adv.tx_slew_fall_dq = 0xf; 770*b35ce0c4SPankaj Gupta input->adv.tx_slew_rise_ac = 0xf; 771*b35ce0c4SPankaj Gupta input->adv.tx_slew_fall_ac = 0xf; 772*b35ce0c4SPankaj Gupta input->adv.mem_alert_en = 0; 773*b35ce0c4SPankaj Gupta input->adv.mem_alert_puimp = 5; 774*b35ce0c4SPankaj Gupta input->adv.mem_alert_vref_level = 0x29; 775*b35ce0c4SPankaj Gupta input->adv.mem_alert_sync_bypass = 0; 776*b35ce0c4SPankaj Gupta input->adv.cal_interval = 0x9; 777*b35ce0c4SPankaj Gupta input->adv.cal_once = 0; 778*b35ce0c4SPankaj Gupta input->adv.dis_dyn_adr_tri = 0; 779*b35ce0c4SPankaj Gupta input->adv.is2ttiming = 0; 780*b35ce0c4SPankaj Gupta input->adv.d4rx_preamble_length = 0; 781*b35ce0c4SPankaj Gupta input->adv.d4tx_preamble_length = 0; 782*b35ce0c4SPankaj Gupta 783*b35ce0c4SPankaj Gupta for (i = 0; i < 7; i++) { 784*b35ce0c4SPankaj Gupta debug("mr[%d] = 0x%x\n", i, input->mr[i]); 785*b35ce0c4SPankaj Gupta } 786*b35ce0c4SPankaj Gupta 787*b35ce0c4SPankaj Gupta debug("input->cs_d0 = 0x%x\n", input->cs_d0); 788*b35ce0c4SPankaj Gupta debug("input->cs_d1 = 0x%x\n", input->cs_d1); 789*b35ce0c4SPankaj Gupta debug("input->mirror = 0x%x\n", input->mirror); 790*b35ce0c4SPankaj Gupta debug("PHY ODT impedance = %d ohm\n", input->adv.odtimpedance); 791*b35ce0c4SPankaj Gupta debug("PHY DQ driver impedance = %d ohm\n", input->adv.tx_impedance); 792*b35ce0c4SPankaj Gupta debug("PHY Addr driver impedance = %d ohm\n", input->adv.atx_impedance); 793*b35ce0c4SPankaj Gupta 794*b35ce0c4SPankaj Gupta for (i = 0; i < 4; i++) { 795*b35ce0c4SPankaj Gupta debug("odt[%d] = 0x%x\n", i, input->odt[i]); 796*b35ce0c4SPankaj Gupta } 797*b35ce0c4SPankaj Gupta 798*b35ce0c4SPankaj Gupta if (input->basic.dimm_type == RDIMM) { 799*b35ce0c4SPankaj Gupta for (i = 0; i < 16; i++) { 800*b35ce0c4SPankaj Gupta debug("input->rcw[%d] = 0x%x\n", i, input->rcw[i]); 801*b35ce0c4SPankaj Gupta } 802*b35ce0c4SPankaj Gupta debug("input->rcw3x = 0x%x\n", input->rcw3x); 803*b35ce0c4SPankaj Gupta } 804*b35ce0c4SPankaj Gupta } 805*b35ce0c4SPankaj Gupta 806*b35ce0c4SPankaj Gupta /* 807*b35ce0c4SPankaj Gupta * All protocols share the same base structure of message block. 808*b35ce0c4SPankaj Gupta * RDIMM and LRDIMM have more entries defined than UDIMM. 809*b35ce0c4SPankaj Gupta * Create message blocks for 1D and 2D training. 810*b35ce0c4SPankaj Gupta * Update len with message block size. 811*b35ce0c4SPankaj Gupta */ 812*b35ce0c4SPankaj Gupta static int phy_gen2_msg_init(void *msg_1d, 813*b35ce0c4SPankaj Gupta void *msg_2d, 814*b35ce0c4SPankaj Gupta const struct input *input) 815*b35ce0c4SPankaj Gupta { 816*b35ce0c4SPankaj Gupta struct ddr4u1d *msg_blk = msg_1d; 817*b35ce0c4SPankaj Gupta struct ddr4u2d *msg_blk_2d = msg_2d; 818*b35ce0c4SPankaj Gupta struct ddr4r1d *msg_blk_r; 819*b35ce0c4SPankaj Gupta struct ddr4lr1d *msg_blk_lr; 820*b35ce0c4SPankaj Gupta 821*b35ce0c4SPankaj Gupta switch (input->basic.dimm_type) { 822*b35ce0c4SPankaj Gupta case UDIMM: 823*b35ce0c4SPankaj Gupta case SODIMM: 824*b35ce0c4SPankaj Gupta case NODIMM: 825*b35ce0c4SPankaj Gupta msg_blk->dram_type = U(0x2); 826*b35ce0c4SPankaj Gupta break; 827*b35ce0c4SPankaj Gupta case RDIMM: 828*b35ce0c4SPankaj Gupta msg_blk->dram_type = U(0x4); 829*b35ce0c4SPankaj Gupta break; 830*b35ce0c4SPankaj Gupta case LRDIMM: 831*b35ce0c4SPankaj Gupta msg_blk->dram_type = U(0x5); 832*b35ce0c4SPankaj Gupta break; 833*b35ce0c4SPankaj Gupta default: 834*b35ce0c4SPankaj Gupta ERROR("Unsupported DIMM type\n"); 835*b35ce0c4SPankaj Gupta return -EINVAL; 836*b35ce0c4SPankaj Gupta } 837*b35ce0c4SPankaj Gupta msg_blk->pstate = 0U; 838*b35ce0c4SPankaj Gupta 839*b35ce0c4SPankaj Gupta /*Enable quickRd2D, a substage of read deskew, to 1D training.*/ 840*b35ce0c4SPankaj Gupta msg_blk->reserved00 = U(0x20); 841*b35ce0c4SPankaj Gupta 842*b35ce0c4SPankaj Gupta /*Enable High-Effort WrDQ1D.*/ 843*b35ce0c4SPankaj Gupta msg_blk->reserved00 |= U(0x40); 844*b35ce0c4SPankaj Gupta 845*b35ce0c4SPankaj Gupta /* Enable 1D extra effort training.*/ 846*b35ce0c4SPankaj Gupta msg_blk->reserved1c[3] = U(0x3); 847*b35ce0c4SPankaj Gupta 848*b35ce0c4SPankaj Gupta if (input->basic.dimm_type == LRDIMM) { 849*b35ce0c4SPankaj Gupta msg_blk->sequence_ctrl = U(0x3f1f); 850*b35ce0c4SPankaj Gupta } else { 851*b35ce0c4SPankaj Gupta msg_blk->sequence_ctrl = U(0x031f); 852*b35ce0c4SPankaj Gupta } 853*b35ce0c4SPankaj Gupta msg_blk->phy_config_override = 0U; 854*b35ce0c4SPankaj Gupta #ifdef DDR_PHY_DEBUG 855*b35ce0c4SPankaj Gupta msg_blk->hdt_ctrl = U(0x5); 856*b35ce0c4SPankaj Gupta #else 857*b35ce0c4SPankaj Gupta msg_blk->hdt_ctrl = U(0xc9); 858*b35ce0c4SPankaj Gupta #endif 859*b35ce0c4SPankaj Gupta msg_blk->msg_misc = U(0x0); 860*b35ce0c4SPankaj Gupta msg_blk->dfimrlmargin = U(0x1); 861*b35ce0c4SPankaj Gupta msg_blk->phy_vref = input->vref ? input->vref : U(0x61); 862*b35ce0c4SPankaj Gupta msg_blk->cs_present = input->cs_d0 | input->cs_d1; 863*b35ce0c4SPankaj Gupta msg_blk->cs_present_d0 = input->cs_d0; 864*b35ce0c4SPankaj Gupta msg_blk->cs_present_d1 = input->cs_d1; 865*b35ce0c4SPankaj Gupta if (input->mirror != 0) { 866*b35ce0c4SPankaj Gupta msg_blk->addr_mirror = U(0x0a); /* odd CS are mirrored */ 867*b35ce0c4SPankaj Gupta } 868*b35ce0c4SPankaj Gupta msg_blk->share2dvref_result = 1U; 869*b35ce0c4SPankaj Gupta 870*b35ce0c4SPankaj Gupta msg_blk->acsm_odt_ctrl0 = input->odt[0]; 871*b35ce0c4SPankaj Gupta msg_blk->acsm_odt_ctrl1 = input->odt[1]; 872*b35ce0c4SPankaj Gupta msg_blk->acsm_odt_ctrl2 = input->odt[2]; 873*b35ce0c4SPankaj Gupta msg_blk->acsm_odt_ctrl3 = input->odt[3]; 874*b35ce0c4SPankaj Gupta msg_blk->enabled_dqs = (input->basic.num_active_dbyte_dfi0 + 875*b35ce0c4SPankaj Gupta input->basic.num_active_dbyte_dfi1) * 8; 876*b35ce0c4SPankaj Gupta msg_blk->x16present = input->basic.dram_data_width == 0x10 ? 877*b35ce0c4SPankaj Gupta msg_blk->cs_present : 0; 878*b35ce0c4SPankaj Gupta msg_blk->d4misc = U(0x1); 879*b35ce0c4SPankaj Gupta msg_blk->cs_setup_gddec = U(0x1); 880*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park0 = 0U; 881*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park1 = 0U; 882*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park2 = 0U; 883*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park3 = 0U; 884*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park4 = 0U; 885*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park5 = 0U; 886*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park6 = 0U; 887*b35ce0c4SPankaj Gupta msg_blk->rtt_nom_wr_park7 = 0U; 888*b35ce0c4SPankaj Gupta msg_blk->mr0 = input->mr[0]; 889*b35ce0c4SPankaj Gupta msg_blk->mr1 = input->mr[1]; 890*b35ce0c4SPankaj Gupta msg_blk->mr2 = input->mr[2]; 891*b35ce0c4SPankaj Gupta msg_blk->mr3 = input->mr[3]; 892*b35ce0c4SPankaj Gupta msg_blk->mr4 = input->mr[4]; 893*b35ce0c4SPankaj Gupta msg_blk->mr5 = input->mr[5]; 894*b35ce0c4SPankaj Gupta msg_blk->mr6 = input->mr[6]; 895*b35ce0c4SPankaj Gupta if ((msg_blk->mr4 & U(0x1c0)) != 0U) { 896*b35ce0c4SPankaj Gupta ERROR("Setting DRAM CAL mode is not supported\n"); 897*b35ce0c4SPankaj Gupta } 898*b35ce0c4SPankaj Gupta 899*b35ce0c4SPankaj Gupta msg_blk->alt_cas_l = 0U; 900*b35ce0c4SPankaj Gupta msg_blk->alt_wcas_l = 0U; 901*b35ce0c4SPankaj Gupta 902*b35ce0c4SPankaj Gupta msg_blk->dramfreq = input->basic.frequency * 2U; 903*b35ce0c4SPankaj Gupta msg_blk->pll_bypass_en = input->basic.pll_bypass; 904*b35ce0c4SPankaj Gupta msg_blk->dfi_freq_ratio = input->basic.dfi_freq_ratio == 0U ? 1U : 905*b35ce0c4SPankaj Gupta input->basic.dfi_freq_ratio == 1U ? 2U : 906*b35ce0c4SPankaj Gupta 4U; 907*b35ce0c4SPankaj Gupta msg_blk->bpznres_val = input->adv.ext_cal_res_val; 908*b35ce0c4SPankaj Gupta msg_blk->disabled_dbyte = 0U; 909*b35ce0c4SPankaj Gupta 910*b35ce0c4SPankaj Gupta debug("msg_blk->dram_type = 0x%x\n", msg_blk->dram_type); 911*b35ce0c4SPankaj Gupta debug("msg_blk->sequence_ctrl = 0x%x\n", msg_blk->sequence_ctrl); 912*b35ce0c4SPankaj Gupta debug("msg_blk->phy_cfg = 0x%x\n", msg_blk->phy_cfg); 913*b35ce0c4SPankaj Gupta debug("msg_blk->x16present = 0x%x\n", msg_blk->x16present); 914*b35ce0c4SPankaj Gupta debug("msg_blk->dramfreq = 0x%x\n", msg_blk->dramfreq); 915*b35ce0c4SPankaj Gupta debug("msg_blk->pll_bypass_en = 0x%x\n", msg_blk->pll_bypass_en); 916*b35ce0c4SPankaj Gupta debug("msg_blk->dfi_freq_ratio = 0x%x\n", msg_blk->dfi_freq_ratio); 917*b35ce0c4SPankaj Gupta debug("msg_blk->phy_odt_impedance = 0x%x\n", 918*b35ce0c4SPankaj Gupta msg_blk->phy_odt_impedance); 919*b35ce0c4SPankaj Gupta debug("msg_blk->phy_drv_impedance = 0x%x\n", 920*b35ce0c4SPankaj Gupta msg_blk->phy_drv_impedance); 921*b35ce0c4SPankaj Gupta debug("msg_blk->bpznres_val = 0x%x\n", msg_blk->bpznres_val); 922*b35ce0c4SPankaj Gupta debug("msg_blk->enabled_dqs = 0x%x\n", msg_blk->enabled_dqs); 923*b35ce0c4SPankaj Gupta debug("msg_blk->acsm_odt_ctrl0 = 0x%x\n", msg_blk->acsm_odt_ctrl0); 924*b35ce0c4SPankaj Gupta debug("msg_blk->acsm_odt_ctrl1 = 0x%x\n", msg_blk->acsm_odt_ctrl1); 925*b35ce0c4SPankaj Gupta debug("msg_blk->acsm_odt_ctrl2 = 0x%x\n", msg_blk->acsm_odt_ctrl2); 926*b35ce0c4SPankaj Gupta debug("msg_blk->acsm_odt_ctrl3 = 0x%x\n", msg_blk->acsm_odt_ctrl3); 927*b35ce0c4SPankaj Gupta 928*b35ce0c4SPankaj Gupta /* RDIMM only */ 929*b35ce0c4SPankaj Gupta if (input->basic.dimm_type == RDIMM || 930*b35ce0c4SPankaj Gupta input->basic.dimm_type == LRDIMM) { 931*b35ce0c4SPankaj Gupta msg_blk_r = (struct ddr4r1d *)msg_blk; 932*b35ce0c4SPankaj Gupta if (msg_blk_r->cs_present_d0 != 0U) { 933*b35ce0c4SPankaj Gupta msg_blk_r->f0rc00_d0 = input->rcw[0]; 934*b35ce0c4SPankaj Gupta msg_blk_r->f0rc01_d0 = input->rcw[1]; 935*b35ce0c4SPankaj Gupta msg_blk_r->f0rc02_d0 = input->rcw[2]; 936*b35ce0c4SPankaj Gupta msg_blk_r->f0rc03_d0 = input->rcw[3]; 937*b35ce0c4SPankaj Gupta msg_blk_r->f0rc04_d0 = input->rcw[4]; 938*b35ce0c4SPankaj Gupta msg_blk_r->f0rc05_d0 = input->rcw[5]; 939*b35ce0c4SPankaj Gupta msg_blk_r->f0rc06_d0 = input->rcw[6]; 940*b35ce0c4SPankaj Gupta msg_blk_r->f0rc07_d0 = input->rcw[7]; 941*b35ce0c4SPankaj Gupta msg_blk_r->f0rc08_d0 = input->rcw[8]; 942*b35ce0c4SPankaj Gupta msg_blk_r->f0rc09_d0 = input->rcw[9]; 943*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0a_d0 = input->rcw[10]; 944*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0b_d0 = input->rcw[11]; 945*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0c_d0 = input->rcw[12]; 946*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0d_d0 = input->rcw[13]; 947*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0e_d0 = input->rcw[14]; 948*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0f_d0 = input->rcw[15]; 949*b35ce0c4SPankaj Gupta msg_blk_r->f0rc3x_d0 = input->rcw3x; 950*b35ce0c4SPankaj Gupta } 951*b35ce0c4SPankaj Gupta if (msg_blk_r->cs_present_d1 != 0) { 952*b35ce0c4SPankaj Gupta msg_blk_r->f0rc00_d1 = input->rcw[0]; 953*b35ce0c4SPankaj Gupta msg_blk_r->f0rc01_d1 = input->rcw[1]; 954*b35ce0c4SPankaj Gupta msg_blk_r->f0rc02_d1 = input->rcw[2]; 955*b35ce0c4SPankaj Gupta msg_blk_r->f0rc03_d1 = input->rcw[3]; 956*b35ce0c4SPankaj Gupta msg_blk_r->f0rc04_d1 = input->rcw[4]; 957*b35ce0c4SPankaj Gupta msg_blk_r->f0rc05_d1 = input->rcw[5]; 958*b35ce0c4SPankaj Gupta msg_blk_r->f0rc06_d1 = input->rcw[6]; 959*b35ce0c4SPankaj Gupta msg_blk_r->f0rc07_d1 = input->rcw[7]; 960*b35ce0c4SPankaj Gupta msg_blk_r->f0rc08_d1 = input->rcw[8]; 961*b35ce0c4SPankaj Gupta msg_blk_r->f0rc09_d1 = input->rcw[9]; 962*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0a_d1 = input->rcw[10]; 963*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0b_d1 = input->rcw[11]; 964*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0c_d1 = input->rcw[12]; 965*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0d_d1 = input->rcw[13]; 966*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0e_d1 = input->rcw[14]; 967*b35ce0c4SPankaj Gupta msg_blk_r->f0rc0f_d1 = input->rcw[15]; 968*b35ce0c4SPankaj Gupta msg_blk_r->f0rc3x_d1 = input->rcw3x; 969*b35ce0c4SPankaj Gupta } 970*b35ce0c4SPankaj Gupta if (input->basic.dimm_type == LRDIMM) { 971*b35ce0c4SPankaj Gupta msg_blk_lr = (struct ddr4lr1d *)msg_blk; 972*b35ce0c4SPankaj Gupta msg_blk_lr->bc0a_d0 = msg_blk_lr->f0rc0a_d0; 973*b35ce0c4SPankaj Gupta msg_blk_lr->bc0a_d1 = msg_blk_lr->f0rc0a_d1; 974*b35ce0c4SPankaj Gupta msg_blk_lr->f0bc6x_d0 = msg_blk_lr->f0rc3x_d0; 975*b35ce0c4SPankaj Gupta msg_blk_lr->f0bc6x_d1 = msg_blk_lr->f0rc3x_d1; 976*b35ce0c4SPankaj Gupta } 977*b35ce0c4SPankaj Gupta } 978*b35ce0c4SPankaj Gupta 979*b35ce0c4SPankaj Gupta /* below is different for 1D and 2D message block */ 980*b35ce0c4SPankaj Gupta if (input->basic.train2d != 0) { 981*b35ce0c4SPankaj Gupta memcpy(msg_blk_2d, msg_blk, sizeof(struct ddr4u1d)); 982*b35ce0c4SPankaj Gupta /*High-Effort WrDQ1D is applicable to 2D traning also*/ 983*b35ce0c4SPankaj Gupta msg_blk_2d->reserved00 |= U(0x40); 984*b35ce0c4SPankaj Gupta msg_blk_2d->sequence_ctrl = U(0x0061); 985*b35ce0c4SPankaj Gupta msg_blk_2d->rx2d_train_opt = 0U; 986*b35ce0c4SPankaj Gupta msg_blk_2d->tx2d_train_opt = 0U; 987*b35ce0c4SPankaj Gupta msg_blk_2d->share2dvref_result = 1U; 988*b35ce0c4SPankaj Gupta msg_blk_2d->delay_weight2d = U(0x20); 989*b35ce0c4SPankaj Gupta msg_blk_2d->voltage_weight2d = U(0x80); 990*b35ce0c4SPankaj Gupta debug("rx2d_train_opt %d, tx2d_train_opt %d\n", 991*b35ce0c4SPankaj Gupta msg_blk_2d->rx2d_train_opt, 992*b35ce0c4SPankaj Gupta msg_blk_2d->tx2d_train_opt); 993*b35ce0c4SPankaj Gupta } 994*b35ce0c4SPankaj Gupta 995*b35ce0c4SPankaj Gupta msg_blk->phy_cfg = (((msg_blk->mr3 & U(0x8)) != 0U) || 996*b35ce0c4SPankaj Gupta ((msg_blk_2d->mr3 & 0x8) != 0U)) ? 0U 997*b35ce0c4SPankaj Gupta : input->adv.is2ttiming; 998*b35ce0c4SPankaj Gupta 999*b35ce0c4SPankaj Gupta return 0; 1000*b35ce0c4SPankaj Gupta } 1001*b35ce0c4SPankaj Gupta 1002*b35ce0c4SPankaj Gupta static void prog_tx_pre_drv_mode(uint16_t *phy, 1003*b35ce0c4SPankaj Gupta const struct input *input) 1004*b35ce0c4SPankaj Gupta { 1005*b35ce0c4SPankaj Gupta int lane, byte, b_addr, c_addr, p_addr; 1006*b35ce0c4SPankaj Gupta int tx_slew_rate, tx_pre_p, tx_pre_n; 1007*b35ce0c4SPankaj Gupta int tx_pre_drv_mode = 0x2; 1008*b35ce0c4SPankaj Gupta uint32_t addr; 1009*b35ce0c4SPankaj Gupta 1010*b35ce0c4SPankaj Gupta /* Program TxPreDrvMode with 0x2 */ 1011*b35ce0c4SPankaj Gupta /* FIXME: TxPreDrvMode depends on DramType? */ 1012*b35ce0c4SPankaj Gupta tx_pre_p = input->adv.tx_slew_rise_dq; 1013*b35ce0c4SPankaj Gupta tx_pre_n = input->adv.tx_slew_fall_dq; 1014*b35ce0c4SPankaj Gupta tx_slew_rate = tx_pre_drv_mode << csr_tx_pre_drv_mode_lsb | 1015*b35ce0c4SPankaj Gupta tx_pre_p << csr_tx_pre_p_lsb | 1016*b35ce0c4SPankaj Gupta tx_pre_n << csr_tx_pre_n_lsb; 1017*b35ce0c4SPankaj Gupta p_addr = 0; 1018*b35ce0c4SPankaj Gupta for (byte = 0; byte < input->basic.num_dbyte; byte++) { 1019*b35ce0c4SPankaj Gupta c_addr = byte << 12; 1020*b35ce0c4SPankaj Gupta for (lane = 0; lane <= 1; lane++) { 1021*b35ce0c4SPankaj Gupta b_addr = lane << 8; 1022*b35ce0c4SPankaj Gupta addr = p_addr | t_dbyte | c_addr | b_addr | 1023*b35ce0c4SPankaj Gupta csr_tx_slew_rate_addr; 1024*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, tx_slew_rate); 1025*b35ce0c4SPankaj Gupta } 1026*b35ce0c4SPankaj Gupta } 1027*b35ce0c4SPankaj Gupta } 1028*b35ce0c4SPankaj Gupta 1029*b35ce0c4SPankaj Gupta static void prog_atx_pre_drv_mode(uint16_t *phy, 1030*b35ce0c4SPankaj Gupta const struct input *input) 1031*b35ce0c4SPankaj Gupta { 1032*b35ce0c4SPankaj Gupta int anib, c_addr; 1033*b35ce0c4SPankaj Gupta int atx_slew_rate, atx_pre_p, atx_pre_n, atx_pre_drv_mode, 1034*b35ce0c4SPankaj Gupta ck_anib_inst[2]; 1035*b35ce0c4SPankaj Gupta uint32_t addr; 1036*b35ce0c4SPankaj Gupta 1037*b35ce0c4SPankaj Gupta atx_pre_n = input->adv.tx_slew_fall_ac; 1038*b35ce0c4SPankaj Gupta atx_pre_p = input->adv.tx_slew_rise_ac; 1039*b35ce0c4SPankaj Gupta 1040*b35ce0c4SPankaj Gupta if (input->basic.num_anib == 8) { 1041*b35ce0c4SPankaj Gupta ck_anib_inst[0] = 1; 1042*b35ce0c4SPankaj Gupta ck_anib_inst[1] = 1; 1043*b35ce0c4SPankaj Gupta } else if (input->basic.num_anib == 10 || input->basic.num_anib == 12 || 1044*b35ce0c4SPankaj Gupta input->basic.num_anib == 13) { 1045*b35ce0c4SPankaj Gupta ck_anib_inst[0] = 4; 1046*b35ce0c4SPankaj Gupta ck_anib_inst[1] = 5; 1047*b35ce0c4SPankaj Gupta } else { 1048*b35ce0c4SPankaj Gupta ERROR("Invalid number of aNIBs: %d\n", input->basic.num_anib); 1049*b35ce0c4SPankaj Gupta return; 1050*b35ce0c4SPankaj Gupta } 1051*b35ce0c4SPankaj Gupta 1052*b35ce0c4SPankaj Gupta for (anib = 0; anib < input->basic.num_anib; anib++) { 1053*b35ce0c4SPankaj Gupta c_addr = anib << 12; 1054*b35ce0c4SPankaj Gupta if (anib == ck_anib_inst[0] || anib == ck_anib_inst[1]) { 1055*b35ce0c4SPankaj Gupta atx_pre_drv_mode = 0; 1056*b35ce0c4SPankaj Gupta } else { 1057*b35ce0c4SPankaj Gupta atx_pre_drv_mode = 3; 1058*b35ce0c4SPankaj Gupta } 1059*b35ce0c4SPankaj Gupta atx_slew_rate = atx_pre_drv_mode << csr_atx_pre_drv_mode_lsb | 1060*b35ce0c4SPankaj Gupta atx_pre_n << csr_atx_pre_n_lsb | 1061*b35ce0c4SPankaj Gupta atx_pre_p << csr_atx_pre_p_lsb; 1062*b35ce0c4SPankaj Gupta addr = t_anib | c_addr | csr_atx_slew_rate_addr; 1063*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, atx_slew_rate); 1064*b35ce0c4SPankaj Gupta } 1065*b35ce0c4SPankaj Gupta } 1066*b35ce0c4SPankaj Gupta 1067*b35ce0c4SPankaj Gupta static void prog_enable_cs_multicast(uint16_t *phy, 1068*b35ce0c4SPankaj Gupta const struct input *input) 1069*b35ce0c4SPankaj Gupta { 1070*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_enable_cs_multicast_addr; 1071*b35ce0c4SPankaj Gupta 1072*b35ce0c4SPankaj Gupta if (input->basic.dimm_type != RDIMM && 1073*b35ce0c4SPankaj Gupta input->basic.dimm_type != LRDIMM) { 1074*b35ce0c4SPankaj Gupta return; 1075*b35ce0c4SPankaj Gupta } 1076*b35ce0c4SPankaj Gupta 1077*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, input->adv.cast_cs_to_cid); 1078*b35ce0c4SPankaj Gupta } 1079*b35ce0c4SPankaj Gupta 1080*b35ce0c4SPankaj Gupta static void prog_dfi_rd_data_cs_dest_map(uint16_t *phy, 1081*b35ce0c4SPankaj Gupta unsigned int ip_rev, 1082*b35ce0c4SPankaj Gupta const struct input *input, 1083*b35ce0c4SPankaj Gupta const struct ddr4lr1d *msg) 1084*b35ce0c4SPankaj Gupta { 1085*b35ce0c4SPankaj Gupta const struct ddr4lr1d *msg_blk; 1086*b35ce0c4SPankaj Gupta uint16_t dfi_xxdestm0 = 0U; 1087*b35ce0c4SPankaj Gupta uint16_t dfi_xxdestm1 = 0U; 1088*b35ce0c4SPankaj Gupta uint16_t dfi_xxdestm2 = 0U; 1089*b35ce0c4SPankaj Gupta uint16_t dfi_xxdestm3 = 0U; 1090*b35ce0c4SPankaj Gupta uint16_t dfi_rd_data_cs_dest_map; 1091*b35ce0c4SPankaj Gupta uint16_t dfi_wr_data_cs_dest_map; 1092*b35ce0c4SPankaj Gupta __unused const soc_info_t *soc_info; 1093*b35ce0c4SPankaj Gupta 1094*b35ce0c4SPankaj Gupta #ifdef ERRATA_DDR_A011396 1095*b35ce0c4SPankaj Gupta /* Only apply to DDRC 5.05.00 */ 1096*b35ce0c4SPankaj Gupta soc_info = get_soc_info(NXP_DCFG_ADDR); 1097*b35ce0c4SPankaj Gupta if ((soc_info->maj_ver == 1U) && (ip_rev == U(0x50500))) { 1098*b35ce0c4SPankaj Gupta phy_io_write16(phy, 1099*b35ce0c4SPankaj Gupta t_master | csr_dfi_rd_data_cs_dest_map_addr, 1100*b35ce0c4SPankaj Gupta 0U); 1101*b35ce0c4SPankaj Gupta return; 1102*b35ce0c4SPankaj Gupta } 1103*b35ce0c4SPankaj Gupta #endif 1104*b35ce0c4SPankaj Gupta 1105*b35ce0c4SPankaj Gupta msg_blk = msg; 1106*b35ce0c4SPankaj Gupta 1107*b35ce0c4SPankaj Gupta switch (input->basic.dimm_type) { 1108*b35ce0c4SPankaj Gupta case UDIMM: 1109*b35ce0c4SPankaj Gupta case SODIMM: 1110*b35ce0c4SPankaj Gupta case NODIMM: 1111*b35ce0c4SPankaj Gupta if ((msg_blk->msg_misc & U(0x40)) != 0U) { 1112*b35ce0c4SPankaj Gupta dfi_rd_data_cs_dest_map = U(0xa0); 1113*b35ce0c4SPankaj Gupta dfi_wr_data_cs_dest_map = U(0xa0); 1114*b35ce0c4SPankaj Gupta 1115*b35ce0c4SPankaj Gupta phy_io_write16(phy, 1116*b35ce0c4SPankaj Gupta t_master | csr_dfi_rd_data_cs_dest_map_addr, 1117*b35ce0c4SPankaj Gupta dfi_rd_data_cs_dest_map); 1118*b35ce0c4SPankaj Gupta phy_io_write16(phy, 1119*b35ce0c4SPankaj Gupta t_master | csr_dfi_wr_data_cs_dest_map_addr, 1120*b35ce0c4SPankaj Gupta dfi_wr_data_cs_dest_map); 1121*b35ce0c4SPankaj Gupta } 1122*b35ce0c4SPankaj Gupta break; 1123*b35ce0c4SPankaj Gupta case LRDIMM: 1124*b35ce0c4SPankaj Gupta if (msg->cs_present_d1 != 0U) { 1125*b35ce0c4SPankaj Gupta dfi_xxdestm2 = 1U; 1126*b35ce0c4SPankaj Gupta dfi_xxdestm3 = 1U; 1127*b35ce0c4SPankaj Gupta } 1128*b35ce0c4SPankaj Gupta 1129*b35ce0c4SPankaj Gupta dfi_rd_data_cs_dest_map = 1130*b35ce0c4SPankaj Gupta dfi_xxdestm0 << csr_dfi_rd_destm0_lsb | 1131*b35ce0c4SPankaj Gupta dfi_xxdestm1 << csr_dfi_rd_destm1_lsb | 1132*b35ce0c4SPankaj Gupta dfi_xxdestm2 << csr_dfi_rd_destm2_lsb | 1133*b35ce0c4SPankaj Gupta dfi_xxdestm3 << csr_dfi_rd_destm3_lsb; 1134*b35ce0c4SPankaj Gupta dfi_wr_data_cs_dest_map = 1135*b35ce0c4SPankaj Gupta dfi_xxdestm0 << csr_dfi_wr_destm0_lsb | 1136*b35ce0c4SPankaj Gupta dfi_xxdestm1 << csr_dfi_wr_destm1_lsb | 1137*b35ce0c4SPankaj Gupta dfi_xxdestm2 << csr_dfi_wr_destm2_lsb | 1138*b35ce0c4SPankaj Gupta dfi_xxdestm3 << csr_dfi_wr_destm3_lsb; 1139*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_master | csr_dfi_rd_data_cs_dest_map_addr, 1140*b35ce0c4SPankaj Gupta dfi_rd_data_cs_dest_map); 1141*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_master | csr_dfi_wr_data_cs_dest_map_addr, 1142*b35ce0c4SPankaj Gupta dfi_wr_data_cs_dest_map); 1143*b35ce0c4SPankaj Gupta 1144*b35ce0c4SPankaj Gupta break; 1145*b35ce0c4SPankaj Gupta default: 1146*b35ce0c4SPankaj Gupta break; 1147*b35ce0c4SPankaj Gupta } 1148*b35ce0c4SPankaj Gupta } 1149*b35ce0c4SPankaj Gupta 1150*b35ce0c4SPankaj Gupta static void prog_pll_ctrl(uint16_t *phy, 1151*b35ce0c4SPankaj Gupta const struct input *input) 1152*b35ce0c4SPankaj Gupta { 1153*b35ce0c4SPankaj Gupta uint32_t addr; 1154*b35ce0c4SPankaj Gupta int pll_ctrl1 = 0x21; /* 000100001b */ 1155*b35ce0c4SPankaj Gupta int pll_ctrl4 = 0x17f; /* 101111111b */ 1156*b35ce0c4SPankaj Gupta int pll_test_mode = 0x24; /* 00100100b */ 1157*b35ce0c4SPankaj Gupta 1158*b35ce0c4SPankaj Gupta addr = t_master | csr_pll_ctrl1_addr; 1159*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, pll_ctrl1); 1160*b35ce0c4SPankaj Gupta 1161*b35ce0c4SPankaj Gupta debug("pll_ctrl1 = 0x%x\n", phy_io_read16(phy, addr)); 1162*b35ce0c4SPankaj Gupta 1163*b35ce0c4SPankaj Gupta addr = t_master | csr_pll_test_mode_addr; 1164*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, pll_test_mode); 1165*b35ce0c4SPankaj Gupta 1166*b35ce0c4SPankaj Gupta debug("pll_test_mode = 0x%x\n", phy_io_read16(phy, addr)); 1167*b35ce0c4SPankaj Gupta 1168*b35ce0c4SPankaj Gupta addr = t_master | csr_pll_ctrl4_addr; 1169*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, pll_ctrl4); 1170*b35ce0c4SPankaj Gupta 1171*b35ce0c4SPankaj Gupta debug("pll_ctrl4 = 0x%x\n", phy_io_read16(phy, addr)); 1172*b35ce0c4SPankaj Gupta } 1173*b35ce0c4SPankaj Gupta 1174*b35ce0c4SPankaj Gupta static void prog_pll_ctrl2(uint16_t *phy, 1175*b35ce0c4SPankaj Gupta const struct input *input) 1176*b35ce0c4SPankaj Gupta { 1177*b35ce0c4SPankaj Gupta int pll_ctrl2; 1178*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_pll_ctrl2_addr; 1179*b35ce0c4SPankaj Gupta 1180*b35ce0c4SPankaj Gupta if (input->basic.frequency / 2 < 235) { 1181*b35ce0c4SPankaj Gupta pll_ctrl2 = 0x7; 1182*b35ce0c4SPankaj Gupta } else if (input->basic.frequency / 2 < 313) { 1183*b35ce0c4SPankaj Gupta pll_ctrl2 = 0x6; 1184*b35ce0c4SPankaj Gupta } else if (input->basic.frequency / 2 < 469) { 1185*b35ce0c4SPankaj Gupta pll_ctrl2 = 0xb; 1186*b35ce0c4SPankaj Gupta } else if (input->basic.frequency / 2 < 625) { 1187*b35ce0c4SPankaj Gupta pll_ctrl2 = 0xa; 1188*b35ce0c4SPankaj Gupta } else if (input->basic.frequency / 2 < 938) { 1189*b35ce0c4SPankaj Gupta pll_ctrl2 = 0x19; 1190*b35ce0c4SPankaj Gupta } else if (input->basic.frequency / 2 < 1067) { 1191*b35ce0c4SPankaj Gupta pll_ctrl2 = 0x18; 1192*b35ce0c4SPankaj Gupta } else { 1193*b35ce0c4SPankaj Gupta pll_ctrl2 = 0x19; 1194*b35ce0c4SPankaj Gupta } 1195*b35ce0c4SPankaj Gupta 1196*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, pll_ctrl2); 1197*b35ce0c4SPankaj Gupta 1198*b35ce0c4SPankaj Gupta debug("pll_ctrl2 = 0x%x\n", phy_io_read16(phy, addr)); 1199*b35ce0c4SPankaj Gupta } 1200*b35ce0c4SPankaj Gupta 1201*b35ce0c4SPankaj Gupta static void prog_dll_lck_param(uint16_t *phy, const struct input *input) 1202*b35ce0c4SPankaj Gupta { 1203*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dll_lockparam_addr; 1204*b35ce0c4SPankaj Gupta 1205*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, U(0x212)); 1206*b35ce0c4SPankaj Gupta debug("dll_lck_param = 0x%x\n", phy_io_read16(phy, addr)); 1207*b35ce0c4SPankaj Gupta } 1208*b35ce0c4SPankaj Gupta 1209*b35ce0c4SPankaj Gupta static void prog_dll_gain_ctl(uint16_t *phy, const struct input *input) 1210*b35ce0c4SPankaj Gupta { 1211*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dll_gain_ctl_addr; 1212*b35ce0c4SPankaj Gupta 1213*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, U(0x61)); 1214*b35ce0c4SPankaj Gupta debug("dll_gain_ctl = 0x%x\n", phy_io_read16(phy, addr)); 1215*b35ce0c4SPankaj Gupta } 1216*b35ce0c4SPankaj Gupta 1217*b35ce0c4SPankaj Gupta static void prog_pll_pwr_dn(uint16_t *phy, 1218*b35ce0c4SPankaj Gupta const struct input *input) 1219*b35ce0c4SPankaj Gupta { 1220*b35ce0c4SPankaj Gupta uint32_t addr; 1221*b35ce0c4SPankaj Gupta 1222*b35ce0c4SPankaj Gupta addr = t_master | csr_pll_pwr_dn_addr; 1223*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, 0U); 1224*b35ce0c4SPankaj Gupta 1225*b35ce0c4SPankaj Gupta debug("pll_pwrdn = 0x%x\n", phy_io_read16(phy, addr)); 1226*b35ce0c4SPankaj Gupta } 1227*b35ce0c4SPankaj Gupta 1228*b35ce0c4SPankaj Gupta static void prog_ard_ptr_init_val(uint16_t *phy, 1229*b35ce0c4SPankaj Gupta const struct input *input) 1230*b35ce0c4SPankaj Gupta { 1231*b35ce0c4SPankaj Gupta int ard_ptr_init_val; 1232*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_ard_ptr_init_val_addr; 1233*b35ce0c4SPankaj Gupta 1234*b35ce0c4SPankaj Gupta if (input->basic.frequency >= 933) { 1235*b35ce0c4SPankaj Gupta ard_ptr_init_val = 0x2; 1236*b35ce0c4SPankaj Gupta } else { 1237*b35ce0c4SPankaj Gupta ard_ptr_init_val = 0x1; 1238*b35ce0c4SPankaj Gupta } 1239*b35ce0c4SPankaj Gupta 1240*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, ard_ptr_init_val); 1241*b35ce0c4SPankaj Gupta } 1242*b35ce0c4SPankaj Gupta 1243*b35ce0c4SPankaj Gupta static void prog_dqs_preamble_control(uint16_t *phy, 1244*b35ce0c4SPankaj Gupta const struct input *input) 1245*b35ce0c4SPankaj Gupta { 1246*b35ce0c4SPankaj Gupta int data; 1247*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dqs_preamble_control_addr; 1248*b35ce0c4SPankaj Gupta const int wdqsextension = 0; 1249*b35ce0c4SPankaj Gupta const int lp4sttc_pre_bridge_rx_en = 0; 1250*b35ce0c4SPankaj Gupta const int lp4postamble_ext = 0; 1251*b35ce0c4SPankaj Gupta const int lp4tgl_two_tck_tx_dqs_pre = 0; 1252*b35ce0c4SPankaj Gupta const int position_dfe_init = 2; 1253*b35ce0c4SPankaj Gupta const int dll_rx_preamble_mode = 1; 1254*b35ce0c4SPankaj Gupta int two_tck_tx_dqs_pre = input->adv.d4tx_preamble_length; 1255*b35ce0c4SPankaj Gupta int two_tck_rx_dqs_pre = input->adv.d4rx_preamble_length; 1256*b35ce0c4SPankaj Gupta 1257*b35ce0c4SPankaj Gupta data = wdqsextension << csr_wdqsextension_lsb | 1258*b35ce0c4SPankaj Gupta lp4sttc_pre_bridge_rx_en << csr_lp4sttc_pre_bridge_rx_en_lsb | 1259*b35ce0c4SPankaj Gupta lp4postamble_ext << csr_lp4postamble_ext_lsb | 1260*b35ce0c4SPankaj Gupta lp4tgl_two_tck_tx_dqs_pre << csr_lp4tgl_two_tck_tx_dqs_pre_lsb | 1261*b35ce0c4SPankaj Gupta position_dfe_init << csr_position_dfe_init_lsb | 1262*b35ce0c4SPankaj Gupta two_tck_tx_dqs_pre << csr_two_tck_tx_dqs_pre_lsb | 1263*b35ce0c4SPankaj Gupta two_tck_rx_dqs_pre << csr_two_tck_rx_dqs_pre_lsb; 1264*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, data); 1265*b35ce0c4SPankaj Gupta 1266*b35ce0c4SPankaj Gupta data = dll_rx_preamble_mode << csr_dll_rx_preamble_mode_lsb; 1267*b35ce0c4SPankaj Gupta addr = t_master | csr_dbyte_dll_mode_cntrl_addr; 1268*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, data); 1269*b35ce0c4SPankaj Gupta } 1270*b35ce0c4SPankaj Gupta 1271*b35ce0c4SPankaj Gupta static void prog_proc_odt_time_ctl(uint16_t *phy, 1272*b35ce0c4SPankaj Gupta const struct input *input) 1273*b35ce0c4SPankaj Gupta { 1274*b35ce0c4SPankaj Gupta int proc_odt_time_ctl; 1275*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_proc_odt_time_ctl_addr; 1276*b35ce0c4SPankaj Gupta 1277*b35ce0c4SPankaj Gupta if (input->adv.wdqsext != 0) { 1278*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0x3; 1279*b35ce0c4SPankaj Gupta } else if (input->basic.frequency <= 933) { 1280*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0xa; 1281*b35ce0c4SPankaj Gupta } else if (input->basic.frequency <= 1200) { 1282*b35ce0c4SPankaj Gupta if (input->adv.d4rx_preamble_length == 1) { 1283*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0x2; 1284*b35ce0c4SPankaj Gupta } else { 1285*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0x6; 1286*b35ce0c4SPankaj Gupta } 1287*b35ce0c4SPankaj Gupta } else { 1288*b35ce0c4SPankaj Gupta if (input->adv.d4rx_preamble_length == 1) { 1289*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0x3; 1290*b35ce0c4SPankaj Gupta } else { 1291*b35ce0c4SPankaj Gupta proc_odt_time_ctl = 0x7; 1292*b35ce0c4SPankaj Gupta } 1293*b35ce0c4SPankaj Gupta } 1294*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, proc_odt_time_ctl); 1295*b35ce0c4SPankaj Gupta } 1296*b35ce0c4SPankaj Gupta 1297*b35ce0c4SPankaj Gupta static const struct impedance_mapping map[] = { 1298*b35ce0c4SPankaj Gupta { 29, 0x3f }, 1299*b35ce0c4SPankaj Gupta { 31, 0x3e }, 1300*b35ce0c4SPankaj Gupta { 33, 0x3b }, 1301*b35ce0c4SPankaj Gupta { 36, 0x3a }, 1302*b35ce0c4SPankaj Gupta { 39, 0x39 }, 1303*b35ce0c4SPankaj Gupta { 42, 0x38 }, 1304*b35ce0c4SPankaj Gupta { 46, 0x1b }, 1305*b35ce0c4SPankaj Gupta { 51, 0x1a }, 1306*b35ce0c4SPankaj Gupta { 57, 0x19 }, 1307*b35ce0c4SPankaj Gupta { 64, 0x18 }, 1308*b35ce0c4SPankaj Gupta { 74, 0x0b }, 1309*b35ce0c4SPankaj Gupta { 88, 0x0a }, 1310*b35ce0c4SPankaj Gupta { 108, 0x09 }, 1311*b35ce0c4SPankaj Gupta { 140, 0x08 }, 1312*b35ce0c4SPankaj Gupta { 200, 0x03 }, 1313*b35ce0c4SPankaj Gupta { 360, 0x02 }, 1314*b35ce0c4SPankaj Gupta { 481, 0x01 }, 1315*b35ce0c4SPankaj Gupta {} 1316*b35ce0c4SPankaj Gupta }; 1317*b35ce0c4SPankaj Gupta 1318*b35ce0c4SPankaj Gupta static int map_impedance(int strength) 1319*b35ce0c4SPankaj Gupta { 1320*b35ce0c4SPankaj Gupta const struct impedance_mapping *tbl = map; 1321*b35ce0c4SPankaj Gupta int val = 0; 1322*b35ce0c4SPankaj Gupta 1323*b35ce0c4SPankaj Gupta if (strength == 0) { 1324*b35ce0c4SPankaj Gupta return 0; 1325*b35ce0c4SPankaj Gupta } 1326*b35ce0c4SPankaj Gupta 1327*b35ce0c4SPankaj Gupta while (tbl->ohm != 0U) { 1328*b35ce0c4SPankaj Gupta if (strength < tbl->ohm) { 1329*b35ce0c4SPankaj Gupta val = tbl->code; 1330*b35ce0c4SPankaj Gupta break; 1331*b35ce0c4SPankaj Gupta } 1332*b35ce0c4SPankaj Gupta tbl++; 1333*b35ce0c4SPankaj Gupta } 1334*b35ce0c4SPankaj Gupta 1335*b35ce0c4SPankaj Gupta return val; 1336*b35ce0c4SPankaj Gupta } 1337*b35ce0c4SPankaj Gupta 1338*b35ce0c4SPankaj Gupta static int map_odtstren_p(int strength, int hard_macro_ver) 1339*b35ce0c4SPankaj Gupta { 1340*b35ce0c4SPankaj Gupta int val = -1; 1341*b35ce0c4SPankaj Gupta 1342*b35ce0c4SPankaj Gupta if (hard_macro_ver == 4) { 1343*b35ce0c4SPankaj Gupta if (strength == 0) { 1344*b35ce0c4SPankaj Gupta val = 0; 1345*b35ce0c4SPankaj Gupta } else if (strength == 120) { 1346*b35ce0c4SPankaj Gupta val = 0x8; 1347*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1348*b35ce0c4SPankaj Gupta val = 0x18; 1349*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1350*b35ce0c4SPankaj Gupta val = 0x38; 1351*b35ce0c4SPankaj Gupta } else { 1352*b35ce0c4SPankaj Gupta printf("error: unsupported ODTStrenP %d\n", strength); 1353*b35ce0c4SPankaj Gupta } 1354*b35ce0c4SPankaj Gupta } else { 1355*b35ce0c4SPankaj Gupta val = map_impedance(strength); 1356*b35ce0c4SPankaj Gupta } 1357*b35ce0c4SPankaj Gupta 1358*b35ce0c4SPankaj Gupta return val; 1359*b35ce0c4SPankaj Gupta } 1360*b35ce0c4SPankaj Gupta 1361*b35ce0c4SPankaj Gupta static void prog_tx_odt_drv_stren(uint16_t *phy, 1362*b35ce0c4SPankaj Gupta const struct input *input) 1363*b35ce0c4SPankaj Gupta { 1364*b35ce0c4SPankaj Gupta int lane, byte, b_addr, c_addr; 1365*b35ce0c4SPankaj Gupta int tx_odt_drv_stren; 1366*b35ce0c4SPankaj Gupta int odtstren_p, odtstren_n; 1367*b35ce0c4SPankaj Gupta uint32_t addr; 1368*b35ce0c4SPankaj Gupta 1369*b35ce0c4SPankaj Gupta odtstren_p = map_odtstren_p(input->adv.odtimpedance, 1370*b35ce0c4SPankaj Gupta input->basic.hard_macro_ver); 1371*b35ce0c4SPankaj Gupta if (odtstren_p < 0) { 1372*b35ce0c4SPankaj Gupta return; 1373*b35ce0c4SPankaj Gupta } 1374*b35ce0c4SPankaj Gupta 1375*b35ce0c4SPankaj Gupta odtstren_n = 0; /* always high-z */ 1376*b35ce0c4SPankaj Gupta tx_odt_drv_stren = odtstren_n << csr_odtstren_n_lsb | odtstren_p; 1377*b35ce0c4SPankaj Gupta for (byte = 0; byte < input->basic.num_dbyte; byte++) { 1378*b35ce0c4SPankaj Gupta c_addr = byte << 12; 1379*b35ce0c4SPankaj Gupta for (lane = 0; lane <= 1; lane++) { 1380*b35ce0c4SPankaj Gupta b_addr = lane << 8; 1381*b35ce0c4SPankaj Gupta addr = t_dbyte | c_addr | b_addr | 1382*b35ce0c4SPankaj Gupta csr_tx_odt_drv_stren_addr; 1383*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, tx_odt_drv_stren); 1384*b35ce0c4SPankaj Gupta } 1385*b35ce0c4SPankaj Gupta } 1386*b35ce0c4SPankaj Gupta } 1387*b35ce0c4SPankaj Gupta 1388*b35ce0c4SPankaj Gupta static int map_drvstren_fsdq_p(int strength, int hard_macro_ver) 1389*b35ce0c4SPankaj Gupta { 1390*b35ce0c4SPankaj Gupta int val = -1; 1391*b35ce0c4SPankaj Gupta 1392*b35ce0c4SPankaj Gupta if (hard_macro_ver == 4) { 1393*b35ce0c4SPankaj Gupta if (strength == 0) { 1394*b35ce0c4SPankaj Gupta val = 0x07; 1395*b35ce0c4SPankaj Gupta } else if (strength == 120) { 1396*b35ce0c4SPankaj Gupta val = 0x0F; 1397*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1398*b35ce0c4SPankaj Gupta val = 0x1F; 1399*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1400*b35ce0c4SPankaj Gupta val = 0x3F; 1401*b35ce0c4SPankaj Gupta } else { 1402*b35ce0c4SPankaj Gupta printf("error: unsupported drv_stren_fSDq_p %d\n", 1403*b35ce0c4SPankaj Gupta strength); 1404*b35ce0c4SPankaj Gupta } 1405*b35ce0c4SPankaj Gupta } else { 1406*b35ce0c4SPankaj Gupta val = map_impedance(strength); 1407*b35ce0c4SPankaj Gupta } 1408*b35ce0c4SPankaj Gupta 1409*b35ce0c4SPankaj Gupta return val; 1410*b35ce0c4SPankaj Gupta } 1411*b35ce0c4SPankaj Gupta 1412*b35ce0c4SPankaj Gupta static int map_drvstren_fsdq_n(int strength, int hard_macro_ver) 1413*b35ce0c4SPankaj Gupta { 1414*b35ce0c4SPankaj Gupta int val = -1; 1415*b35ce0c4SPankaj Gupta 1416*b35ce0c4SPankaj Gupta if (hard_macro_ver == 4) { 1417*b35ce0c4SPankaj Gupta if (strength == 0) { 1418*b35ce0c4SPankaj Gupta val = 0x00; 1419*b35ce0c4SPankaj Gupta } else if (strength == 120) { 1420*b35ce0c4SPankaj Gupta val = 0x08; 1421*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1422*b35ce0c4SPankaj Gupta val = 0x18; 1423*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1424*b35ce0c4SPankaj Gupta val = 0x38; 1425*b35ce0c4SPankaj Gupta } else { 1426*b35ce0c4SPankaj Gupta printf("error: unsupported drvStrenFSDqN %d\n", 1427*b35ce0c4SPankaj Gupta strength); 1428*b35ce0c4SPankaj Gupta } 1429*b35ce0c4SPankaj Gupta } else { 1430*b35ce0c4SPankaj Gupta val = map_impedance(strength); 1431*b35ce0c4SPankaj Gupta } 1432*b35ce0c4SPankaj Gupta 1433*b35ce0c4SPankaj Gupta return val; 1434*b35ce0c4SPankaj Gupta } 1435*b35ce0c4SPankaj Gupta 1436*b35ce0c4SPankaj Gupta static void prog_tx_impedance_ctrl1(uint16_t *phy, 1437*b35ce0c4SPankaj Gupta const struct input *input) 1438*b35ce0c4SPankaj Gupta { 1439*b35ce0c4SPankaj Gupta int lane, byte, b_addr, c_addr; 1440*b35ce0c4SPankaj Gupta int tx_impedance_ctrl1; 1441*b35ce0c4SPankaj Gupta int drv_stren_fsdq_p, drv_stren_fsdq_n; 1442*b35ce0c4SPankaj Gupta uint32_t addr; 1443*b35ce0c4SPankaj Gupta 1444*b35ce0c4SPankaj Gupta drv_stren_fsdq_p = map_drvstren_fsdq_p(input->adv.tx_impedance, 1445*b35ce0c4SPankaj Gupta input->basic.hard_macro_ver); 1446*b35ce0c4SPankaj Gupta drv_stren_fsdq_n = map_drvstren_fsdq_n(input->adv.tx_impedance, 1447*b35ce0c4SPankaj Gupta input->basic.hard_macro_ver); 1448*b35ce0c4SPankaj Gupta tx_impedance_ctrl1 = drv_stren_fsdq_n << csr_drv_stren_fsdq_n_lsb | 1449*b35ce0c4SPankaj Gupta drv_stren_fsdq_p << csr_drv_stren_fsdq_p_lsb; 1450*b35ce0c4SPankaj Gupta 1451*b35ce0c4SPankaj Gupta for (byte = 0; byte < input->basic.num_dbyte; byte++) { 1452*b35ce0c4SPankaj Gupta c_addr = byte << 12; 1453*b35ce0c4SPankaj Gupta for (lane = 0; lane <= 1; lane++) { 1454*b35ce0c4SPankaj Gupta b_addr = lane << 8; 1455*b35ce0c4SPankaj Gupta addr = t_dbyte | c_addr | b_addr | 1456*b35ce0c4SPankaj Gupta csr_tx_impedance_ctrl1_addr; 1457*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, tx_impedance_ctrl1); 1458*b35ce0c4SPankaj Gupta } 1459*b35ce0c4SPankaj Gupta } 1460*b35ce0c4SPankaj Gupta } 1461*b35ce0c4SPankaj Gupta 1462*b35ce0c4SPankaj Gupta static int map_adrv_stren_p(int strength, int hard_macro_ver) 1463*b35ce0c4SPankaj Gupta { 1464*b35ce0c4SPankaj Gupta int val = -1; 1465*b35ce0c4SPankaj Gupta 1466*b35ce0c4SPankaj Gupta if (hard_macro_ver == 4) { 1467*b35ce0c4SPankaj Gupta if (strength == 120) { 1468*b35ce0c4SPankaj Gupta val = 0x1c; 1469*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1470*b35ce0c4SPankaj Gupta val = 0x1d; 1471*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1472*b35ce0c4SPankaj Gupta val = 0x1f; 1473*b35ce0c4SPankaj Gupta } else { 1474*b35ce0c4SPankaj Gupta printf("error: unsupported aDrv_stren_p %d\n", 1475*b35ce0c4SPankaj Gupta strength); 1476*b35ce0c4SPankaj Gupta } 1477*b35ce0c4SPankaj Gupta } else { 1478*b35ce0c4SPankaj Gupta if (strength == 120) { 1479*b35ce0c4SPankaj Gupta val = 0x00; 1480*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1481*b35ce0c4SPankaj Gupta val = 0x01; 1482*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1483*b35ce0c4SPankaj Gupta val = 0x03; 1484*b35ce0c4SPankaj Gupta } else if (strength == 30) { 1485*b35ce0c4SPankaj Gupta val = 0x07; 1486*b35ce0c4SPankaj Gupta } else if (strength == 24) { 1487*b35ce0c4SPankaj Gupta val = 0x0f; 1488*b35ce0c4SPankaj Gupta } else if (strength == 20) { 1489*b35ce0c4SPankaj Gupta val = 0x1f; 1490*b35ce0c4SPankaj Gupta } else { 1491*b35ce0c4SPankaj Gupta printf("error: unsupported aDrv_stren_p %d\n", 1492*b35ce0c4SPankaj Gupta strength); 1493*b35ce0c4SPankaj Gupta } 1494*b35ce0c4SPankaj Gupta } 1495*b35ce0c4SPankaj Gupta 1496*b35ce0c4SPankaj Gupta return val; 1497*b35ce0c4SPankaj Gupta } 1498*b35ce0c4SPankaj Gupta 1499*b35ce0c4SPankaj Gupta static int map_adrv_stren_n(int strength, int hard_macro_ver) 1500*b35ce0c4SPankaj Gupta { 1501*b35ce0c4SPankaj Gupta int val = -1; 1502*b35ce0c4SPankaj Gupta 1503*b35ce0c4SPankaj Gupta if (hard_macro_ver == 4) { 1504*b35ce0c4SPankaj Gupta if (strength == 120) { 1505*b35ce0c4SPankaj Gupta val = 0x00; 1506*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1507*b35ce0c4SPankaj Gupta val = 0x01; 1508*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1509*b35ce0c4SPankaj Gupta val = 0x03; 1510*b35ce0c4SPankaj Gupta } else { 1511*b35ce0c4SPankaj Gupta printf("Error: unsupported ADrvStrenP %d\n", strength); 1512*b35ce0c4SPankaj Gupta } 1513*b35ce0c4SPankaj Gupta } else { 1514*b35ce0c4SPankaj Gupta if (strength == 120) { 1515*b35ce0c4SPankaj Gupta val = 0x00; 1516*b35ce0c4SPankaj Gupta } else if (strength == 60) { 1517*b35ce0c4SPankaj Gupta val = 0x01; 1518*b35ce0c4SPankaj Gupta } else if (strength == 40) { 1519*b35ce0c4SPankaj Gupta val = 0x03; 1520*b35ce0c4SPankaj Gupta } else if (strength == 30) { 1521*b35ce0c4SPankaj Gupta val = 0x07; 1522*b35ce0c4SPankaj Gupta } else if (strength == 24) { 1523*b35ce0c4SPankaj Gupta val = 0x0f; 1524*b35ce0c4SPankaj Gupta } else if (strength == 20) { 1525*b35ce0c4SPankaj Gupta val = 0x1f; 1526*b35ce0c4SPankaj Gupta } else { 1527*b35ce0c4SPankaj Gupta printf("Error: unsupported ADrvStrenP %d\n", strength); 1528*b35ce0c4SPankaj Gupta } 1529*b35ce0c4SPankaj Gupta } 1530*b35ce0c4SPankaj Gupta 1531*b35ce0c4SPankaj Gupta return val; 1532*b35ce0c4SPankaj Gupta } 1533*b35ce0c4SPankaj Gupta 1534*b35ce0c4SPankaj Gupta static void prog_atx_impedance(uint16_t *phy, 1535*b35ce0c4SPankaj Gupta const struct input *input) 1536*b35ce0c4SPankaj Gupta { 1537*b35ce0c4SPankaj Gupta int anib, c_addr; 1538*b35ce0c4SPankaj Gupta int atx_impedance; 1539*b35ce0c4SPankaj Gupta int adrv_stren_p; 1540*b35ce0c4SPankaj Gupta int adrv_stren_n; 1541*b35ce0c4SPankaj Gupta uint32_t addr; 1542*b35ce0c4SPankaj Gupta 1543*b35ce0c4SPankaj Gupta if (input->basic.hard_macro_ver == 4 && 1544*b35ce0c4SPankaj Gupta input->adv.atx_impedance == 20) { 1545*b35ce0c4SPankaj Gupta printf("Error:ATxImpedance has to be 40 for HardMacroVer 4\n"); 1546*b35ce0c4SPankaj Gupta return; 1547*b35ce0c4SPankaj Gupta } 1548*b35ce0c4SPankaj Gupta 1549*b35ce0c4SPankaj Gupta adrv_stren_p = map_adrv_stren_p(input->adv.atx_impedance, 1550*b35ce0c4SPankaj Gupta input->basic.hard_macro_ver); 1551*b35ce0c4SPankaj Gupta adrv_stren_n = map_adrv_stren_n(input->adv.atx_impedance, 1552*b35ce0c4SPankaj Gupta input->basic.hard_macro_ver); 1553*b35ce0c4SPankaj Gupta atx_impedance = adrv_stren_n << csr_adrv_stren_n_lsb | 1554*b35ce0c4SPankaj Gupta adrv_stren_p << csr_adrv_stren_p_lsb; 1555*b35ce0c4SPankaj Gupta for (anib = 0; anib < input->basic.num_anib; anib++) { 1556*b35ce0c4SPankaj Gupta c_addr = anib << 12; 1557*b35ce0c4SPankaj Gupta addr = t_anib | c_addr | csr_atx_impedance_addr; 1558*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, atx_impedance); 1559*b35ce0c4SPankaj Gupta } 1560*b35ce0c4SPankaj Gupta } 1561*b35ce0c4SPankaj Gupta 1562*b35ce0c4SPankaj Gupta static void prog_dfi_mode(uint16_t *phy, 1563*b35ce0c4SPankaj Gupta const struct input *input) 1564*b35ce0c4SPankaj Gupta { 1565*b35ce0c4SPankaj Gupta int dfi_mode; 1566*b35ce0c4SPankaj Gupta uint32_t addr; 1567*b35ce0c4SPankaj Gupta 1568*b35ce0c4SPankaj Gupta if (input->basic.dfi1exists == 1) { 1569*b35ce0c4SPankaj Gupta dfi_mode = 0x5; /* DFI1 exists but disabled */ 1570*b35ce0c4SPankaj Gupta } else { 1571*b35ce0c4SPankaj Gupta dfi_mode = 0x1; /* DFI1 does not physically exists */ 1572*b35ce0c4SPankaj Gupta } 1573*b35ce0c4SPankaj Gupta addr = t_master | csr_dfi_mode_addr; 1574*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dfi_mode); 1575*b35ce0c4SPankaj Gupta } 1576*b35ce0c4SPankaj Gupta 1577*b35ce0c4SPankaj Gupta static void prog_acx4_anib_dis(uint16_t *phy, const struct input *input) 1578*b35ce0c4SPankaj Gupta { 1579*b35ce0c4SPankaj Gupta uint32_t addr; 1580*b35ce0c4SPankaj Gupta 1581*b35ce0c4SPankaj Gupta addr = t_master | csr_acx4_anib_dis_addr; 1582*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, 0x0); 1583*b35ce0c4SPankaj Gupta debug("%s 0x%x\n", __func__, phy_io_read16(phy, addr)); 1584*b35ce0c4SPankaj Gupta } 1585*b35ce0c4SPankaj Gupta 1586*b35ce0c4SPankaj Gupta static void prog_dfi_camode(uint16_t *phy, 1587*b35ce0c4SPankaj Gupta const struct input *input) 1588*b35ce0c4SPankaj Gupta { 1589*b35ce0c4SPankaj Gupta int dfi_camode = 2; 1590*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dfi_camode_addr; 1591*b35ce0c4SPankaj Gupta 1592*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dfi_camode); 1593*b35ce0c4SPankaj Gupta } 1594*b35ce0c4SPankaj Gupta 1595*b35ce0c4SPankaj Gupta static void prog_cal_drv_str0(uint16_t *phy, 1596*b35ce0c4SPankaj Gupta const struct input *input) 1597*b35ce0c4SPankaj Gupta { 1598*b35ce0c4SPankaj Gupta int cal_drv_str0; 1599*b35ce0c4SPankaj Gupta int cal_drv_str_pd50; 1600*b35ce0c4SPankaj Gupta int cal_drv_str_pu50; 1601*b35ce0c4SPankaj Gupta uint32_t addr; 1602*b35ce0c4SPankaj Gupta 1603*b35ce0c4SPankaj Gupta cal_drv_str_pu50 = input->adv.ext_cal_res_val; 1604*b35ce0c4SPankaj Gupta cal_drv_str_pd50 = cal_drv_str_pu50; 1605*b35ce0c4SPankaj Gupta cal_drv_str0 = cal_drv_str_pu50 << csr_cal_drv_str_pu50_lsb | 1606*b35ce0c4SPankaj Gupta cal_drv_str_pd50; 1607*b35ce0c4SPankaj Gupta addr = t_master | csr_cal_drv_str0_addr; 1608*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_drv_str0); 1609*b35ce0c4SPankaj Gupta } 1610*b35ce0c4SPankaj Gupta 1611*b35ce0c4SPankaj Gupta static void prog_cal_uclk_info(uint16_t *phy, 1612*b35ce0c4SPankaj Gupta const struct input *input) 1613*b35ce0c4SPankaj Gupta { 1614*b35ce0c4SPankaj Gupta int cal_uclk_ticks_per1u_s; 1615*b35ce0c4SPankaj Gupta uint32_t addr; 1616*b35ce0c4SPankaj Gupta 1617*b35ce0c4SPankaj Gupta cal_uclk_ticks_per1u_s = input->basic.frequency >> 1; 1618*b35ce0c4SPankaj Gupta if (cal_uclk_ticks_per1u_s < 24) { 1619*b35ce0c4SPankaj Gupta cal_uclk_ticks_per1u_s = 24; 1620*b35ce0c4SPankaj Gupta } 1621*b35ce0c4SPankaj Gupta 1622*b35ce0c4SPankaj Gupta addr = t_master | csr_cal_uclk_info_addr; 1623*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_uclk_ticks_per1u_s); 1624*b35ce0c4SPankaj Gupta } 1625*b35ce0c4SPankaj Gupta 1626*b35ce0c4SPankaj Gupta static void prog_cal_rate(uint16_t *phy, 1627*b35ce0c4SPankaj Gupta const struct input *input) 1628*b35ce0c4SPankaj Gupta { 1629*b35ce0c4SPankaj Gupta int cal_rate; 1630*b35ce0c4SPankaj Gupta int cal_interval; 1631*b35ce0c4SPankaj Gupta int cal_once; 1632*b35ce0c4SPankaj Gupta uint32_t addr; 1633*b35ce0c4SPankaj Gupta 1634*b35ce0c4SPankaj Gupta cal_interval = input->adv.cal_interval; 1635*b35ce0c4SPankaj Gupta cal_once = input->adv.cal_once; 1636*b35ce0c4SPankaj Gupta cal_rate = cal_once << csr_cal_once_lsb | 1637*b35ce0c4SPankaj Gupta cal_interval << csr_cal_interval_lsb; 1638*b35ce0c4SPankaj Gupta addr = t_master | csr_cal_rate_addr; 1639*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_rate); 1640*b35ce0c4SPankaj Gupta } 1641*b35ce0c4SPankaj Gupta 1642*b35ce0c4SPankaj Gupta static void prog_vref_in_global(uint16_t *phy, 1643*b35ce0c4SPankaj Gupta const struct input *input, 1644*b35ce0c4SPankaj Gupta const struct ddr4u1d *msg) 1645*b35ce0c4SPankaj Gupta { 1646*b35ce0c4SPankaj Gupta int vref_in_global; 1647*b35ce0c4SPankaj Gupta int global_vref_in_dac = 0; 1648*b35ce0c4SPankaj Gupta int global_vref_in_sel = 0; 1649*b35ce0c4SPankaj Gupta uint32_t addr; 1650*b35ce0c4SPankaj Gupta 1651*b35ce0c4SPankaj Gupta /* 1652*b35ce0c4SPankaj Gupta * phy_vref_prcnt = msg->phy_vref / 128.0 1653*b35ce0c4SPankaj Gupta * global_vref_in_dac = (phy_vref_prcnt - 0.345) / 0.005; 1654*b35ce0c4SPankaj Gupta */ 1655*b35ce0c4SPankaj Gupta global_vref_in_dac = (msg->phy_vref * 1000 - 345 * 128 + 320) / 1656*b35ce0c4SPankaj Gupta (5 * 128); 1657*b35ce0c4SPankaj Gupta 1658*b35ce0c4SPankaj Gupta vref_in_global = global_vref_in_dac << csr_global_vref_in_dac_lsb | 1659*b35ce0c4SPankaj Gupta global_vref_in_sel; 1660*b35ce0c4SPankaj Gupta addr = t_master | csr_vref_in_global_addr; 1661*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, vref_in_global); 1662*b35ce0c4SPankaj Gupta } 1663*b35ce0c4SPankaj Gupta 1664*b35ce0c4SPankaj Gupta static void prog_dq_dqs_rcv_cntrl(uint16_t *phy, 1665*b35ce0c4SPankaj Gupta const struct input *input) 1666*b35ce0c4SPankaj Gupta { 1667*b35ce0c4SPankaj Gupta int lane, byte, b_addr, c_addr; 1668*b35ce0c4SPankaj Gupta int dq_dqs_rcv_cntrl; 1669*b35ce0c4SPankaj Gupta int gain_curr_adj_defval = 0xb; 1670*b35ce0c4SPankaj Gupta int major_mode_dbyte = 3; 1671*b35ce0c4SPankaj Gupta int dfe_ctrl_defval = 0; 1672*b35ce0c4SPankaj Gupta int ext_vref_range_defval = 0; 1673*b35ce0c4SPankaj Gupta int sel_analog_vref = 1; 1674*b35ce0c4SPankaj Gupta uint32_t addr; 1675*b35ce0c4SPankaj Gupta 1676*b35ce0c4SPankaj Gupta dq_dqs_rcv_cntrl = gain_curr_adj_defval << csr_gain_curr_adj_lsb | 1677*b35ce0c4SPankaj Gupta major_mode_dbyte << csr_major_mode_dbyte_lsb | 1678*b35ce0c4SPankaj Gupta dfe_ctrl_defval << csr_dfe_ctrl_lsb | 1679*b35ce0c4SPankaj Gupta ext_vref_range_defval << csr_ext_vref_range_lsb | 1680*b35ce0c4SPankaj Gupta sel_analog_vref << csr_sel_analog_vref_lsb; 1681*b35ce0c4SPankaj Gupta for (byte = 0; byte < input->basic.num_dbyte; byte++) { 1682*b35ce0c4SPankaj Gupta c_addr = byte << 12; 1683*b35ce0c4SPankaj Gupta for (lane = 0; lane <= 1; lane++) { 1684*b35ce0c4SPankaj Gupta b_addr = lane << 8; 1685*b35ce0c4SPankaj Gupta addr = t_dbyte | c_addr | b_addr | 1686*b35ce0c4SPankaj Gupta csr_dq_dqs_rcv_cntrl_addr; 1687*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dq_dqs_rcv_cntrl); 1688*b35ce0c4SPankaj Gupta } 1689*b35ce0c4SPankaj Gupta } 1690*b35ce0c4SPankaj Gupta } 1691*b35ce0c4SPankaj Gupta 1692*b35ce0c4SPankaj Gupta static void prog_mem_alert_control(uint16_t *phy, 1693*b35ce0c4SPankaj Gupta const struct input *input) 1694*b35ce0c4SPankaj Gupta { 1695*b35ce0c4SPankaj Gupta int mem_alert_control; 1696*b35ce0c4SPankaj Gupta int mem_alert_control2; 1697*b35ce0c4SPankaj Gupta int malertpu_en; 1698*b35ce0c4SPankaj Gupta int malertrx_en; 1699*b35ce0c4SPankaj Gupta int malertvref_level; 1700*b35ce0c4SPankaj Gupta int malertpu_stren; 1701*b35ce0c4SPankaj Gupta int malertsync_bypass; 1702*b35ce0c4SPankaj Gupta int malertdisable_val_defval = 1; 1703*b35ce0c4SPankaj Gupta uint32_t addr; 1704*b35ce0c4SPankaj Gupta 1705*b35ce0c4SPankaj Gupta if (input->basic.dram_type == DDR4 && input->adv.mem_alert_en == 1) { 1706*b35ce0c4SPankaj Gupta malertpu_en = 1; 1707*b35ce0c4SPankaj Gupta malertrx_en = 1; 1708*b35ce0c4SPankaj Gupta malertpu_stren = input->adv.mem_alert_puimp; 1709*b35ce0c4SPankaj Gupta malertvref_level = input->adv.mem_alert_vref_level; 1710*b35ce0c4SPankaj Gupta malertsync_bypass = input->adv.mem_alert_sync_bypass; 1711*b35ce0c4SPankaj Gupta mem_alert_control = malertdisable_val_defval << 14 | 1712*b35ce0c4SPankaj Gupta malertrx_en << 13 | 1713*b35ce0c4SPankaj Gupta malertpu_en << 12 | 1714*b35ce0c4SPankaj Gupta malertpu_stren << 8 | 1715*b35ce0c4SPankaj Gupta malertvref_level; 1716*b35ce0c4SPankaj Gupta mem_alert_control2 = malertsync_bypass << 1717*b35ce0c4SPankaj Gupta csr_malertsync_bypass_lsb; 1718*b35ce0c4SPankaj Gupta addr = t_master | csr_mem_alert_control_addr; 1719*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, mem_alert_control); 1720*b35ce0c4SPankaj Gupta addr = t_master | csr_mem_alert_control2_addr; 1721*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, mem_alert_control2); 1722*b35ce0c4SPankaj Gupta } 1723*b35ce0c4SPankaj Gupta } 1724*b35ce0c4SPankaj Gupta 1725*b35ce0c4SPankaj Gupta static void prog_dfi_freq_ratio(uint16_t *phy, 1726*b35ce0c4SPankaj Gupta const struct input *input) 1727*b35ce0c4SPankaj Gupta { 1728*b35ce0c4SPankaj Gupta int dfi_freq_ratio; 1729*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dfi_freq_ratio_addr; 1730*b35ce0c4SPankaj Gupta 1731*b35ce0c4SPankaj Gupta dfi_freq_ratio = input->basic.dfi_freq_ratio; 1732*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dfi_freq_ratio); 1733*b35ce0c4SPankaj Gupta } 1734*b35ce0c4SPankaj Gupta 1735*b35ce0c4SPankaj Gupta static void prog_tristate_mode_ca(uint16_t *phy, 1736*b35ce0c4SPankaj Gupta const struct input *input) 1737*b35ce0c4SPankaj Gupta { 1738*b35ce0c4SPankaj Gupta int tristate_mode_ca; 1739*b35ce0c4SPankaj Gupta int dis_dyn_adr_tri; 1740*b35ce0c4SPankaj Gupta int ddr2tmode; 1741*b35ce0c4SPankaj Gupta int ck_dis_val_def = 1; 1742*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_tristate_mode_ca_addr; 1743*b35ce0c4SPankaj Gupta 1744*b35ce0c4SPankaj Gupta dis_dyn_adr_tri = input->adv.dis_dyn_adr_tri; 1745*b35ce0c4SPankaj Gupta ddr2tmode = input->adv.is2ttiming; 1746*b35ce0c4SPankaj Gupta tristate_mode_ca = ck_dis_val_def << csr_ck_dis_val_lsb | 1747*b35ce0c4SPankaj Gupta ddr2tmode << csr_ddr2tmode_lsb | 1748*b35ce0c4SPankaj Gupta dis_dyn_adr_tri << csr_dis_dyn_adr_tri_lsb; 1749*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, tristate_mode_ca); 1750*b35ce0c4SPankaj Gupta } 1751*b35ce0c4SPankaj Gupta 1752*b35ce0c4SPankaj Gupta static void prog_dfi_xlat(uint16_t *phy, 1753*b35ce0c4SPankaj Gupta const struct input *input) 1754*b35ce0c4SPankaj Gupta { 1755*b35ce0c4SPankaj Gupta uint16_t loop_vector; 1756*b35ce0c4SPankaj Gupta int dfifreqxlat_dat; 1757*b35ce0c4SPankaj Gupta int pllbypass_dat; 1758*b35ce0c4SPankaj Gupta uint32_t addr; 1759*b35ce0c4SPankaj Gupta 1760*b35ce0c4SPankaj Gupta /* fIXME: Shall unused P1, P2, P3 be bypassed? */ 1761*b35ce0c4SPankaj Gupta pllbypass_dat = input->basic.pll_bypass; /* only [0] is used */ 1762*b35ce0c4SPankaj Gupta for (loop_vector = 0; loop_vector < 8; loop_vector++) { 1763*b35ce0c4SPankaj Gupta if (loop_vector == 0) { 1764*b35ce0c4SPankaj Gupta dfifreqxlat_dat = pllbypass_dat + 0x5555; 1765*b35ce0c4SPankaj Gupta } else if (loop_vector == 7) { 1766*b35ce0c4SPankaj Gupta dfifreqxlat_dat = 0xf000; 1767*b35ce0c4SPankaj Gupta } else { 1768*b35ce0c4SPankaj Gupta dfifreqxlat_dat = 0x5555; 1769*b35ce0c4SPankaj Gupta } 1770*b35ce0c4SPankaj Gupta addr = t_master | (csr_dfi_freq_xlat0_addr + loop_vector); 1771*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dfifreqxlat_dat); 1772*b35ce0c4SPankaj Gupta } 1773*b35ce0c4SPankaj Gupta } 1774*b35ce0c4SPankaj Gupta 1775*b35ce0c4SPankaj Gupta static void prog_dbyte_misc_mode(uint16_t *phy, 1776*b35ce0c4SPankaj Gupta const struct input *input, 1777*b35ce0c4SPankaj Gupta const struct ddr4u1d *msg) 1778*b35ce0c4SPankaj Gupta { 1779*b35ce0c4SPankaj Gupta int dbyte_misc_mode; 1780*b35ce0c4SPankaj Gupta int dq_dqs_rcv_cntrl1; 1781*b35ce0c4SPankaj Gupta int dq_dqs_rcv_cntrl1_1; 1782*b35ce0c4SPankaj Gupta int byte, c_addr; 1783*b35ce0c4SPankaj Gupta uint32_t addr; 1784*b35ce0c4SPankaj Gupta 1785*b35ce0c4SPankaj Gupta dbyte_misc_mode = 0x1 << csr_dbyte_disable_lsb; 1786*b35ce0c4SPankaj Gupta dq_dqs_rcv_cntrl1 = 0x1ff << csr_power_down_rcvr_lsb | 1787*b35ce0c4SPankaj Gupta 0x1 << csr_power_down_rcvr_dqs_lsb | 1788*b35ce0c4SPankaj Gupta 0x1 << csr_rx_pad_standby_en_lsb; 1789*b35ce0c4SPankaj Gupta dq_dqs_rcv_cntrl1_1 = (0x100 << csr_power_down_rcvr_lsb | 1790*b35ce0c4SPankaj Gupta csr_rx_pad_standby_en_mask); 1791*b35ce0c4SPankaj Gupta for (byte = 0; byte < input->basic.num_dbyte; byte++) { 1792*b35ce0c4SPankaj Gupta c_addr = byte << 12; 1793*b35ce0c4SPankaj Gupta if (byte <= input->basic.num_active_dbyte_dfi0 - 1) { 1794*b35ce0c4SPankaj Gupta /* disable RDBI lane if not used. */ 1795*b35ce0c4SPankaj Gupta if ((input->basic.dram_data_width != 4) && 1796*b35ce0c4SPankaj Gupta (((msg->mr5 >> 12) & 0x1) == 0)) { 1797*b35ce0c4SPankaj Gupta addr = t_dbyte 1798*b35ce0c4SPankaj Gupta | c_addr 1799*b35ce0c4SPankaj Gupta | csr_dq_dqs_rcv_cntrl1_addr; 1800*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1_1); 1801*b35ce0c4SPankaj Gupta } 1802*b35ce0c4SPankaj Gupta } else { 1803*b35ce0c4SPankaj Gupta addr = t_dbyte | c_addr | csr_dbyte_misc_mode_addr; 1804*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dbyte_misc_mode); 1805*b35ce0c4SPankaj Gupta addr = t_dbyte | c_addr | csr_dq_dqs_rcv_cntrl1_addr; 1806*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1); 1807*b35ce0c4SPankaj Gupta } 1808*b35ce0c4SPankaj Gupta } 1809*b35ce0c4SPankaj Gupta } 1810*b35ce0c4SPankaj Gupta 1811*b35ce0c4SPankaj Gupta static void prog_master_x4config(uint16_t *phy, 1812*b35ce0c4SPankaj Gupta const struct input *input) 1813*b35ce0c4SPankaj Gupta { 1814*b35ce0c4SPankaj Gupta int master_x4config; 1815*b35ce0c4SPankaj Gupta int x4tg; 1816*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_master_x4config_addr; 1817*b35ce0c4SPankaj Gupta 1818*b35ce0c4SPankaj Gupta x4tg = input->basic.dram_data_width == 4 ? 0xf : 0; 1819*b35ce0c4SPankaj Gupta master_x4config = x4tg << csr_x4tg_lsb; 1820*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, master_x4config); 1821*b35ce0c4SPankaj Gupta } 1822*b35ce0c4SPankaj Gupta 1823*b35ce0c4SPankaj Gupta static void prog_dmipin_present(uint16_t *phy, 1824*b35ce0c4SPankaj Gupta const struct input *input, 1825*b35ce0c4SPankaj Gupta const struct ddr4u1d *msg) 1826*b35ce0c4SPankaj Gupta { 1827*b35ce0c4SPankaj Gupta int dmipin_present; 1828*b35ce0c4SPankaj Gupta uint32_t addr = t_master | csr_dmipin_present_addr; 1829*b35ce0c4SPankaj Gupta 1830*b35ce0c4SPankaj Gupta dmipin_present = (msg->mr5 >> 12) & 0x1; 1831*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dmipin_present); 1832*b35ce0c4SPankaj Gupta } 1833*b35ce0c4SPankaj Gupta 1834*b35ce0c4SPankaj Gupta static void prog_dfi_phyupd(uint16_t *phy, 1835*b35ce0c4SPankaj Gupta const struct input *input) 1836*b35ce0c4SPankaj Gupta { 1837*b35ce0c4SPankaj Gupta int dfiphyupd_dat; 1838*b35ce0c4SPankaj Gupta uint32_t addr; 1839*b35ce0c4SPankaj Gupta 1840*b35ce0c4SPankaj Gupta addr = t_master | (csr_dfiphyupd_addr); 1841*b35ce0c4SPankaj Gupta dfiphyupd_dat = phy_io_read16(phy, addr) & 1842*b35ce0c4SPankaj Gupta ~csr_dfiphyupd_threshold_mask; 1843*b35ce0c4SPankaj Gupta 1844*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, dfiphyupd_dat); 1845*b35ce0c4SPankaj Gupta } 1846*b35ce0c4SPankaj Gupta 1847*b35ce0c4SPankaj Gupta static void prog_cal_misc2(uint16_t *phy, 1848*b35ce0c4SPankaj Gupta const struct input *input) 1849*b35ce0c4SPankaj Gupta { 1850*b35ce0c4SPankaj Gupta int cal_misc2_dat, cal_drv_pdth_data, cal_offsets_dat; 1851*b35ce0c4SPankaj Gupta uint32_t addr; 1852*b35ce0c4SPankaj Gupta 1853*b35ce0c4SPankaj Gupta addr = t_master | (csr_cal_misc2_addr); 1854*b35ce0c4SPankaj Gupta cal_misc2_dat = phy_io_read16(phy, addr) | 1855*b35ce0c4SPankaj Gupta (1 << csr_cal_misc2_err_dis); 1856*b35ce0c4SPankaj Gupta 1857*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_misc2_dat); 1858*b35ce0c4SPankaj Gupta 1859*b35ce0c4SPankaj Gupta addr = t_master | (csr_cal_offsets_addr); 1860*b35ce0c4SPankaj Gupta 1861*b35ce0c4SPankaj Gupta cal_drv_pdth_data = 0x9 << 6; 1862*b35ce0c4SPankaj Gupta cal_offsets_dat = (phy_io_read16(phy, addr) & ~csr_cal_drv_pdth_mask) 1863*b35ce0c4SPankaj Gupta | cal_drv_pdth_data; 1864*b35ce0c4SPankaj Gupta 1865*b35ce0c4SPankaj Gupta phy_io_write16(phy, addr, cal_offsets_dat); 1866*b35ce0c4SPankaj Gupta } 1867*b35ce0c4SPankaj Gupta 1868*b35ce0c4SPankaj Gupta static int c_init_phy_config(uint16_t **phy_ptr, 1869*b35ce0c4SPankaj Gupta unsigned int ip_rev, 1870*b35ce0c4SPankaj Gupta const struct input *input, 1871*b35ce0c4SPankaj Gupta const void *msg) 1872*b35ce0c4SPankaj Gupta { 1873*b35ce0c4SPankaj Gupta int i; 1874*b35ce0c4SPankaj Gupta uint16_t *phy; 1875*b35ce0c4SPankaj Gupta __unused const soc_info_t *soc_info; 1876*b35ce0c4SPankaj Gupta 1877*b35ce0c4SPankaj Gupta for (i = 0; i < NUM_OF_DDRC; i++) { 1878*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 1879*b35ce0c4SPankaj Gupta if (phy == NULL) { 1880*b35ce0c4SPankaj Gupta continue; 1881*b35ce0c4SPankaj Gupta } 1882*b35ce0c4SPankaj Gupta 1883*b35ce0c4SPankaj Gupta debug("Initialize PHY %d config\n", i); 1884*b35ce0c4SPankaj Gupta prog_dfi_phyupd(phy, input); 1885*b35ce0c4SPankaj Gupta prog_cal_misc2(phy, input); 1886*b35ce0c4SPankaj Gupta prog_tx_pre_drv_mode(phy, input); 1887*b35ce0c4SPankaj Gupta prog_atx_pre_drv_mode(phy, input); 1888*b35ce0c4SPankaj Gupta prog_enable_cs_multicast(phy, input); /* rdimm and lrdimm */ 1889*b35ce0c4SPankaj Gupta prog_dfi_rd_data_cs_dest_map(phy, ip_rev, input, msg); 1890*b35ce0c4SPankaj Gupta prog_pll_ctrl2(phy, input); 1891*b35ce0c4SPankaj Gupta #ifdef DDR_PLL_FIX 1892*b35ce0c4SPankaj Gupta soc_info = get_soc_info(); 1893*b35ce0c4SPankaj Gupta debug("SOC_SI_REV = %x\n", soc_info->maj_ver); 1894*b35ce0c4SPankaj Gupta if (soc_info->maj_ver == 1) { 1895*b35ce0c4SPankaj Gupta prog_pll_pwr_dn(phy, input); 1896*b35ce0c4SPankaj Gupta 1897*b35ce0c4SPankaj Gupta /*Enable FFE aka TxEqualizationMode for rev1 SI*/ 1898*b35ce0c4SPankaj Gupta phy_io_write16(phy, 0x010048, 0x1); 1899*b35ce0c4SPankaj Gupta } 1900*b35ce0c4SPankaj Gupta #endif 1901*b35ce0c4SPankaj Gupta prog_ard_ptr_init_val(phy, input); 1902*b35ce0c4SPankaj Gupta prog_dqs_preamble_control(phy, input); 1903*b35ce0c4SPankaj Gupta prog_dll_lck_param(phy, input); 1904*b35ce0c4SPankaj Gupta prog_dll_gain_ctl(phy, input); 1905*b35ce0c4SPankaj Gupta prog_proc_odt_time_ctl(phy, input); 1906*b35ce0c4SPankaj Gupta prog_tx_odt_drv_stren(phy, input); 1907*b35ce0c4SPankaj Gupta prog_tx_impedance_ctrl1(phy, input); 1908*b35ce0c4SPankaj Gupta prog_atx_impedance(phy, input); 1909*b35ce0c4SPankaj Gupta prog_dfi_mode(phy, input); 1910*b35ce0c4SPankaj Gupta prog_dfi_camode(phy, input); 1911*b35ce0c4SPankaj Gupta prog_cal_drv_str0(phy, input); 1912*b35ce0c4SPankaj Gupta prog_cal_uclk_info(phy, input); 1913*b35ce0c4SPankaj Gupta prog_cal_rate(phy, input); 1914*b35ce0c4SPankaj Gupta prog_vref_in_global(phy, input, msg); 1915*b35ce0c4SPankaj Gupta prog_dq_dqs_rcv_cntrl(phy, input); 1916*b35ce0c4SPankaj Gupta prog_mem_alert_control(phy, input); 1917*b35ce0c4SPankaj Gupta prog_dfi_freq_ratio(phy, input); 1918*b35ce0c4SPankaj Gupta prog_tristate_mode_ca(phy, input); 1919*b35ce0c4SPankaj Gupta prog_dfi_xlat(phy, input); 1920*b35ce0c4SPankaj Gupta prog_dbyte_misc_mode(phy, input, msg); 1921*b35ce0c4SPankaj Gupta prog_master_x4config(phy, input); 1922*b35ce0c4SPankaj Gupta prog_dmipin_present(phy, input, msg); 1923*b35ce0c4SPankaj Gupta prog_acx4_anib_dis(phy, input); 1924*b35ce0c4SPankaj Gupta } 1925*b35ce0c4SPankaj Gupta 1926*b35ce0c4SPankaj Gupta return 0; 1927*b35ce0c4SPankaj Gupta } 1928*b35ce0c4SPankaj Gupta 1929*b35ce0c4SPankaj Gupta static uint32_t get_mail(uint16_t *phy, int stream) 1930*b35ce0c4SPankaj Gupta { 1931*b35ce0c4SPankaj Gupta int timeout; 1932*b35ce0c4SPankaj Gupta uint32_t mail = 0U; 1933*b35ce0c4SPankaj Gupta 1934*b35ce0c4SPankaj Gupta timeout = TIMEOUTDEFAULT; 1935*b35ce0c4SPankaj Gupta while (((--timeout) != 0) && 1936*b35ce0c4SPankaj Gupta ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) 1937*b35ce0c4SPankaj Gupta & uct_write_prot_shadow_mask) != 0)) { 1938*b35ce0c4SPankaj Gupta mdelay(10); 1939*b35ce0c4SPankaj Gupta } 1940*b35ce0c4SPankaj Gupta if (timeout == 0) { 1941*b35ce0c4SPankaj Gupta ERROR("Timeout getting mail from PHY\n"); 1942*b35ce0c4SPankaj Gupta return 0xFFFF; 1943*b35ce0c4SPankaj Gupta } 1944*b35ce0c4SPankaj Gupta 1945*b35ce0c4SPankaj Gupta mail = phy_io_read16(phy, t_apbonly | 1946*b35ce0c4SPankaj Gupta csr_uct_write_only_shadow); 1947*b35ce0c4SPankaj Gupta if (stream != 0) { 1948*b35ce0c4SPankaj Gupta mail |= phy_io_read16(phy, t_apbonly | 1949*b35ce0c4SPankaj Gupta csr_uct_dat_write_only_shadow) << 16; 1950*b35ce0c4SPankaj Gupta } 1951*b35ce0c4SPankaj Gupta 1952*b35ce0c4SPankaj Gupta /* Ack */ 1953*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 0); 1954*b35ce0c4SPankaj Gupta 1955*b35ce0c4SPankaj Gupta timeout = TIMEOUTDEFAULT; 1956*b35ce0c4SPankaj Gupta while (((--timeout) != 0) && 1957*b35ce0c4SPankaj Gupta ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) 1958*b35ce0c4SPankaj Gupta & uct_write_prot_shadow_mask) == 0)) { 1959*b35ce0c4SPankaj Gupta mdelay(1); 1960*b35ce0c4SPankaj Gupta } 1961*b35ce0c4SPankaj Gupta if (timeout == 0) { 1962*b35ce0c4SPankaj Gupta ERROR("Timeout ack PHY mail\n"); 1963*b35ce0c4SPankaj Gupta } 1964*b35ce0c4SPankaj Gupta 1965*b35ce0c4SPankaj Gupta /* completed */ 1966*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 1U); 1967*b35ce0c4SPankaj Gupta 1968*b35ce0c4SPankaj Gupta return mail; 1969*b35ce0c4SPankaj Gupta } 1970*b35ce0c4SPankaj Gupta 1971*b35ce0c4SPankaj Gupta #ifdef DDR_PHY_DEBUG 1972*b35ce0c4SPankaj Gupta static const char *lookup_msg(uint32_t index, int train2d) 1973*b35ce0c4SPankaj Gupta { 1974*b35ce0c4SPankaj Gupta int i; 1975*b35ce0c4SPankaj Gupta int size; 1976*b35ce0c4SPankaj Gupta const struct phy_msg *messages; 1977*b35ce0c4SPankaj Gupta const char *ptr = NULL; 1978*b35ce0c4SPankaj Gupta 1979*b35ce0c4SPankaj Gupta if (train2d != 0) { 1980*b35ce0c4SPankaj Gupta messages = messages_2d; 1981*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(messages_2d); 1982*b35ce0c4SPankaj Gupta } else { 1983*b35ce0c4SPankaj Gupta messages = messages_1d; 1984*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(messages_1d); 1985*b35ce0c4SPankaj Gupta } 1986*b35ce0c4SPankaj Gupta for (i = 0; i < size; i++) { 1987*b35ce0c4SPankaj Gupta if (messages[i].index == index) { 1988*b35ce0c4SPankaj Gupta ptr = messages[i].msg; 1989*b35ce0c4SPankaj Gupta break; 1990*b35ce0c4SPankaj Gupta } 1991*b35ce0c4SPankaj Gupta } 1992*b35ce0c4SPankaj Gupta 1993*b35ce0c4SPankaj Gupta return ptr; 1994*b35ce0c4SPankaj Gupta } 1995*b35ce0c4SPankaj Gupta #endif 1996*b35ce0c4SPankaj Gupta 1997*b35ce0c4SPankaj Gupta #define MAX_ARGS 32 1998*b35ce0c4SPankaj Gupta static void decode_stream_message(uint16_t *phy, int train2d) 1999*b35ce0c4SPankaj Gupta { 2000*b35ce0c4SPankaj Gupta uint32_t index __unused; 2001*b35ce0c4SPankaj Gupta 2002*b35ce0c4SPankaj Gupta __unused const char *format; 2003*b35ce0c4SPankaj Gupta __unused uint32_t args[MAX_ARGS]; 2004*b35ce0c4SPankaj Gupta __unused int i; 2005*b35ce0c4SPankaj Gupta 2006*b35ce0c4SPankaj Gupta #ifdef DDR_PHY_DEBUG 2007*b35ce0c4SPankaj Gupta index = get_mail(phy, 1); 2008*b35ce0c4SPankaj Gupta if ((index & 0xffff) > MAX_ARGS) { /* up to MAX_ARGS args so far */ 2009*b35ce0c4SPankaj Gupta printf("Program error in %s\n", __func__); 2010*b35ce0c4SPankaj Gupta } 2011*b35ce0c4SPankaj Gupta for (i = 0; i < (index & 0xffff) && i < MAX_ARGS; i++) { 2012*b35ce0c4SPankaj Gupta args[i] = get_mail(phy, 1); 2013*b35ce0c4SPankaj Gupta } 2014*b35ce0c4SPankaj Gupta 2015*b35ce0c4SPankaj Gupta format = lookup_msg(index, train2d); 2016*b35ce0c4SPankaj Gupta if (format != NULL) { 2017*b35ce0c4SPankaj Gupta printf("0x%08x: ", index); 2018*b35ce0c4SPankaj Gupta printf(format, args[0], args[1], args[2], args[3], args[4], 2019*b35ce0c4SPankaj Gupta args[5], args[6], args[7], args[8], args[9], args[10], 2020*b35ce0c4SPankaj Gupta args[11], args[12], args[13], args[14], args[15], 2021*b35ce0c4SPankaj Gupta args[16], args[17], args[18], args[19], args[20], 2022*b35ce0c4SPankaj Gupta args[21], args[22], args[23], args[24], args[25], 2023*b35ce0c4SPankaj Gupta args[26], args[27], args[28], args[29], args[30], 2024*b35ce0c4SPankaj Gupta args[31]); 2025*b35ce0c4SPankaj Gupta } 2026*b35ce0c4SPankaj Gupta #endif 2027*b35ce0c4SPankaj Gupta } 2028*b35ce0c4SPankaj Gupta 2029*b35ce0c4SPankaj Gupta static int wait_fw_done(uint16_t *phy, int train2d) 2030*b35ce0c4SPankaj Gupta { 2031*b35ce0c4SPankaj Gupta uint32_t mail = 0U; 2032*b35ce0c4SPankaj Gupta 2033*b35ce0c4SPankaj Gupta while (mail == U(0x0)) { 2034*b35ce0c4SPankaj Gupta mail = get_mail(phy, 0); 2035*b35ce0c4SPankaj Gupta switch (mail) { 2036*b35ce0c4SPankaj Gupta case U(0x7): 2037*b35ce0c4SPankaj Gupta debug("%s Training completed\n", train2d ? "2D" : "1D"); 2038*b35ce0c4SPankaj Gupta break; 2039*b35ce0c4SPankaj Gupta case U(0xff): 2040*b35ce0c4SPankaj Gupta debug("%s Training failure\n", train2d ? "2D" : "1D"); 2041*b35ce0c4SPankaj Gupta break; 2042*b35ce0c4SPankaj Gupta case U(0x0): 2043*b35ce0c4SPankaj Gupta debug("End of initialization\n"); 2044*b35ce0c4SPankaj Gupta mail = 0U; 2045*b35ce0c4SPankaj Gupta break; 2046*b35ce0c4SPankaj Gupta case U(0x1): 2047*b35ce0c4SPankaj Gupta debug("End of fine write leveling\n"); 2048*b35ce0c4SPankaj Gupta mail = 0U; 2049*b35ce0c4SPankaj Gupta break; 2050*b35ce0c4SPankaj Gupta case U(0x2): 2051*b35ce0c4SPankaj Gupta debug("End of read enable training\n"); 2052*b35ce0c4SPankaj Gupta mail = 0U; 2053*b35ce0c4SPankaj Gupta break; 2054*b35ce0c4SPankaj Gupta case U(0x3): 2055*b35ce0c4SPankaj Gupta debug("End of read delay center optimization\n"); 2056*b35ce0c4SPankaj Gupta mail = 0U; 2057*b35ce0c4SPankaj Gupta break; 2058*b35ce0c4SPankaj Gupta case U(0x4): 2059*b35ce0c4SPankaj Gupta debug("End of write delay center optimization\n"); 2060*b35ce0c4SPankaj Gupta mail = 0U; 2061*b35ce0c4SPankaj Gupta break; 2062*b35ce0c4SPankaj Gupta case U(0x5): 2063*b35ce0c4SPankaj Gupta debug("End of 2D read delay/voltage center optimztn\n"); 2064*b35ce0c4SPankaj Gupta mail = 0U; 2065*b35ce0c4SPankaj Gupta break; 2066*b35ce0c4SPankaj Gupta case U(0x6): 2067*b35ce0c4SPankaj Gupta debug("End of 2D write delay/voltage center optmztn\n"); 2068*b35ce0c4SPankaj Gupta mail = 0U; 2069*b35ce0c4SPankaj Gupta break; 2070*b35ce0c4SPankaj Gupta case U(0x8): 2071*b35ce0c4SPankaj Gupta decode_stream_message(phy, train2d); 2072*b35ce0c4SPankaj Gupta mail = 0U; 2073*b35ce0c4SPankaj Gupta break; 2074*b35ce0c4SPankaj Gupta case U(0x9): 2075*b35ce0c4SPankaj Gupta debug("End of max read latency training\n"); 2076*b35ce0c4SPankaj Gupta mail = 0U; 2077*b35ce0c4SPankaj Gupta break; 2078*b35ce0c4SPankaj Gupta case U(0xa): 2079*b35ce0c4SPankaj Gupta debug("End of read dq deskew training\n"); 2080*b35ce0c4SPankaj Gupta mail = 0U; 2081*b35ce0c4SPankaj Gupta break; 2082*b35ce0c4SPankaj Gupta case U(0xc): 2083*b35ce0c4SPankaj Gupta debug("End of LRDIMM Specific training, including:\n"); 2084*b35ce0c4SPankaj Gupta debug("/tDWL, MREP, MRD and MWD\n"); 2085*b35ce0c4SPankaj Gupta mail = 0U; 2086*b35ce0c4SPankaj Gupta break; 2087*b35ce0c4SPankaj Gupta case U(0xd): 2088*b35ce0c4SPankaj Gupta debug("End of CA training\n"); 2089*b35ce0c4SPankaj Gupta mail = 0U; 2090*b35ce0c4SPankaj Gupta break; 2091*b35ce0c4SPankaj Gupta case U(0xfd): 2092*b35ce0c4SPankaj Gupta debug("End of MPR read delay center optimization\n"); 2093*b35ce0c4SPankaj Gupta mail = 0U; 2094*b35ce0c4SPankaj Gupta break; 2095*b35ce0c4SPankaj Gupta case U(0xfe): 2096*b35ce0c4SPankaj Gupta debug("End of Write leveling coarse delay\n"); 2097*b35ce0c4SPankaj Gupta mail = 0U; 2098*b35ce0c4SPankaj Gupta break; 2099*b35ce0c4SPankaj Gupta case U(0xffff): 2100*b35ce0c4SPankaj Gupta debug("Timed out\n"); 2101*b35ce0c4SPankaj Gupta break; 2102*b35ce0c4SPankaj Gupta default: 2103*b35ce0c4SPankaj Gupta mail = 0U; 2104*b35ce0c4SPankaj Gupta break; 2105*b35ce0c4SPankaj Gupta } 2106*b35ce0c4SPankaj Gupta } 2107*b35ce0c4SPankaj Gupta 2108*b35ce0c4SPankaj Gupta if (mail == U(0x7)) { 2109*b35ce0c4SPankaj Gupta return 0; 2110*b35ce0c4SPankaj Gupta } else if (mail == U(0xff)) { 2111*b35ce0c4SPankaj Gupta return -EIO; 2112*b35ce0c4SPankaj Gupta } else if (mail == U(0xffff)) { 2113*b35ce0c4SPankaj Gupta return -ETIMEDOUT; 2114*b35ce0c4SPankaj Gupta } 2115*b35ce0c4SPankaj Gupta 2116*b35ce0c4SPankaj Gupta debug("PHY_GEN2 FW: Unxpected mail = 0x%x\n", mail); 2117*b35ce0c4SPankaj Gupta 2118*b35ce0c4SPankaj Gupta return -EINVAL; 2119*b35ce0c4SPankaj Gupta } 2120*b35ce0c4SPankaj Gupta 2121*b35ce0c4SPankaj Gupta static int g_exec_fw(uint16_t **phy_ptr, int train2d, struct input *input) 2122*b35ce0c4SPankaj Gupta { 2123*b35ce0c4SPankaj Gupta int ret = -EINVAL; 2124*b35ce0c4SPankaj Gupta int i; 2125*b35ce0c4SPankaj Gupta uint16_t *phy; 2126*b35ce0c4SPankaj Gupta 2127*b35ce0c4SPankaj Gupta for (i = 0; i < NUM_OF_DDRC; i++) { 2128*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 2129*b35ce0c4SPankaj Gupta if (phy == NULL) { 2130*b35ce0c4SPankaj Gupta continue; 2131*b35ce0c4SPankaj Gupta } 2132*b35ce0c4SPankaj Gupta debug("Applying PLL optimal settings\n"); 2133*b35ce0c4SPankaj Gupta prog_pll_ctrl2(phy, input); 2134*b35ce0c4SPankaj Gupta prog_pll_ctrl(phy, input); 2135*b35ce0c4SPankaj Gupta phy_io_write16(phy, 2136*b35ce0c4SPankaj Gupta t_apbonly | csr_micro_cont_mux_sel_addr, 2137*b35ce0c4SPankaj Gupta 0x1); 2138*b35ce0c4SPankaj Gupta phy_io_write16(phy, 2139*b35ce0c4SPankaj Gupta t_apbonly | csr_micro_reset_addr, 2140*b35ce0c4SPankaj Gupta csr_reset_to_micro_mask | 2141*b35ce0c4SPankaj Gupta csr_stall_to_micro_mask); 2142*b35ce0c4SPankaj Gupta phy_io_write16(phy, 2143*b35ce0c4SPankaj Gupta t_apbonly | csr_micro_reset_addr, 2144*b35ce0c4SPankaj Gupta csr_stall_to_micro_mask); 2145*b35ce0c4SPankaj Gupta phy_io_write16(phy, 2146*b35ce0c4SPankaj Gupta t_apbonly | csr_micro_reset_addr, 2147*b35ce0c4SPankaj Gupta 0); 2148*b35ce0c4SPankaj Gupta 2149*b35ce0c4SPankaj Gupta ret = wait_fw_done(phy, train2d); 2150*b35ce0c4SPankaj Gupta if (ret == -ETIMEDOUT) { 2151*b35ce0c4SPankaj Gupta ERROR("Wait timed out: Firmware execution on PHY %d\n", 2152*b35ce0c4SPankaj Gupta i); 2153*b35ce0c4SPankaj Gupta } 2154*b35ce0c4SPankaj Gupta } 2155*b35ce0c4SPankaj Gupta return ret; 2156*b35ce0c4SPankaj Gupta } 2157*b35ce0c4SPankaj Gupta 2158*b35ce0c4SPankaj Gupta static inline int send_fw(uint16_t *phy, 2159*b35ce0c4SPankaj Gupta uint32_t dst, 2160*b35ce0c4SPankaj Gupta uint16_t *img, 2161*b35ce0c4SPankaj Gupta uint32_t size) 2162*b35ce0c4SPankaj Gupta { 2163*b35ce0c4SPankaj Gupta uint32_t i; 2164*b35ce0c4SPankaj Gupta 2165*b35ce0c4SPankaj Gupta if ((size % 2U) != 0U) { 2166*b35ce0c4SPankaj Gupta ERROR("Wrong image size 0x%x\n", size); 2167*b35ce0c4SPankaj Gupta return -EINVAL; 2168*b35ce0c4SPankaj Gupta } 2169*b35ce0c4SPankaj Gupta 2170*b35ce0c4SPankaj Gupta for (i = 0U; i < size / 2; i++) { 2171*b35ce0c4SPankaj Gupta phy_io_write16(phy, dst + i, *(img + i)); 2172*b35ce0c4SPankaj Gupta } 2173*b35ce0c4SPankaj Gupta 2174*b35ce0c4SPankaj Gupta return 0; 2175*b35ce0c4SPankaj Gupta } 2176*b35ce0c4SPankaj Gupta 2177*b35ce0c4SPankaj Gupta static int load_fw(uint16_t **phy_ptr, 2178*b35ce0c4SPankaj Gupta struct input *input, 2179*b35ce0c4SPankaj Gupta int train2d, 2180*b35ce0c4SPankaj Gupta void *msg, 2181*b35ce0c4SPankaj Gupta size_t len, 2182*b35ce0c4SPankaj Gupta uintptr_t phy_gen2_fw_img_buf, 2183*b35ce0c4SPankaj Gupta int (*img_loadr)(unsigned int, uintptr_t *, uint32_t *), 2184*b35ce0c4SPankaj Gupta uint32_t warm_boot_flag) 2185*b35ce0c4SPankaj Gupta { 2186*b35ce0c4SPankaj Gupta uint32_t imem_id, dmem_id; 2187*b35ce0c4SPankaj Gupta uintptr_t image_buf; 2188*b35ce0c4SPankaj Gupta uint32_t size; 2189*b35ce0c4SPankaj Gupta int ret; 2190*b35ce0c4SPankaj Gupta int i; 2191*b35ce0c4SPankaj Gupta uint16_t *phy; 2192*b35ce0c4SPankaj Gupta 2193*b35ce0c4SPankaj Gupta switch (input->basic.dimm_type) { 2194*b35ce0c4SPankaj Gupta case UDIMM: 2195*b35ce0c4SPankaj Gupta case SODIMM: 2196*b35ce0c4SPankaj Gupta case NODIMM: 2197*b35ce0c4SPankaj Gupta imem_id = train2d ? DDR_IMEM_UDIMM_2D_IMAGE_ID : 2198*b35ce0c4SPankaj Gupta DDR_IMEM_UDIMM_1D_IMAGE_ID; 2199*b35ce0c4SPankaj Gupta dmem_id = train2d ? DDR_DMEM_UDIMM_2D_IMAGE_ID : 2200*b35ce0c4SPankaj Gupta DDR_DMEM_UDIMM_1D_IMAGE_ID; 2201*b35ce0c4SPankaj Gupta break; 2202*b35ce0c4SPankaj Gupta case RDIMM: 2203*b35ce0c4SPankaj Gupta imem_id = train2d ? DDR_IMEM_RDIMM_2D_IMAGE_ID : 2204*b35ce0c4SPankaj Gupta DDR_IMEM_RDIMM_1D_IMAGE_ID; 2205*b35ce0c4SPankaj Gupta dmem_id = train2d ? DDR_DMEM_RDIMM_2D_IMAGE_ID : 2206*b35ce0c4SPankaj Gupta DDR_DMEM_RDIMM_1D_IMAGE_ID; 2207*b35ce0c4SPankaj Gupta break; 2208*b35ce0c4SPankaj Gupta default: 2209*b35ce0c4SPankaj Gupta ERROR("Unsupported DIMM type\n"); 2210*b35ce0c4SPankaj Gupta return -EINVAL; 2211*b35ce0c4SPankaj Gupta } 2212*b35ce0c4SPankaj Gupta 2213*b35ce0c4SPankaj Gupta size = PHY_GEN2_MAX_IMAGE_SIZE; 2214*b35ce0c4SPankaj Gupta image_buf = (uintptr_t)phy_gen2_fw_img_buf; 2215*b35ce0c4SPankaj Gupta mmap_add_dynamic_region(phy_gen2_fw_img_buf, 2216*b35ce0c4SPankaj Gupta phy_gen2_fw_img_buf, 2217*b35ce0c4SPankaj Gupta PHY_GEN2_MAX_IMAGE_SIZE, 2218*b35ce0c4SPankaj Gupta MT_MEMORY | MT_RW | MT_SECURE); 2219*b35ce0c4SPankaj Gupta ret = img_loadr(imem_id, &image_buf, &size); 2220*b35ce0c4SPankaj Gupta if (ret != 0) { 2221*b35ce0c4SPankaj Gupta ERROR("Failed to load %d firmware.\n", imem_id); 2222*b35ce0c4SPankaj Gupta return ret; 2223*b35ce0c4SPankaj Gupta } 2224*b35ce0c4SPankaj Gupta debug("Loaded Imaged id %d of size %x at address %lx\n", 2225*b35ce0c4SPankaj Gupta imem_id, size, image_buf); 2226*b35ce0c4SPankaj Gupta 2227*b35ce0c4SPankaj Gupta for (i = 0; i < NUM_OF_DDRC; i++) { 2228*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 2229*b35ce0c4SPankaj Gupta if (phy == NULL) { 2230*b35ce0c4SPankaj Gupta continue; 2231*b35ce0c4SPankaj Gupta } 2232*b35ce0c4SPankaj Gupta 2233*b35ce0c4SPankaj Gupta if (warm_boot_flag != DDR_WARM_BOOT) { 2234*b35ce0c4SPankaj Gupta if (train2d == 0) { 2235*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_master | 2236*b35ce0c4SPankaj Gupta csr_mem_reset_l_addr, 2237*b35ce0c4SPankaj Gupta csr_protect_mem_reset_mask); 2238*b35ce0c4SPankaj Gupta } 2239*b35ce0c4SPankaj Gupta } 2240*b35ce0c4SPankaj Gupta /* Enable access to the internal CSRs */ 2241*b35ce0c4SPankaj Gupta phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 0); 2242*b35ce0c4SPankaj Gupta 2243*b35ce0c4SPankaj Gupta ret = send_fw(phy, PHY_GEN2_IMEM_ADDR, 2244*b35ce0c4SPankaj Gupta (uint16_t *)image_buf, size); 2245*b35ce0c4SPankaj Gupta if (ret != 0) { 2246*b35ce0c4SPankaj Gupta return ret; 2247*b35ce0c4SPankaj Gupta } 2248*b35ce0c4SPankaj Gupta } 2249*b35ce0c4SPankaj Gupta 2250*b35ce0c4SPankaj Gupta size = PHY_GEN2_MAX_IMAGE_SIZE; 2251*b35ce0c4SPankaj Gupta image_buf = (uintptr_t)phy_gen2_fw_img_buf; 2252*b35ce0c4SPankaj Gupta ret = img_loadr(dmem_id, &image_buf, &size); 2253*b35ce0c4SPankaj Gupta if (ret != 0) { 2254*b35ce0c4SPankaj Gupta ERROR("Failed to load %d firmware.\n", dmem_id); 2255*b35ce0c4SPankaj Gupta return ret; 2256*b35ce0c4SPankaj Gupta } 2257*b35ce0c4SPankaj Gupta debug("Loaded Imaged id %d of size %x at address %lx\n", 2258*b35ce0c4SPankaj Gupta dmem_id, size, image_buf); 2259*b35ce0c4SPankaj Gupta image_buf += len; 2260*b35ce0c4SPankaj Gupta size -= len; 2261*b35ce0c4SPankaj Gupta 2262*b35ce0c4SPankaj Gupta for (i = 0; i < NUM_OF_DDRC; i++) { 2263*b35ce0c4SPankaj Gupta phy = phy_ptr[i]; 2264*b35ce0c4SPankaj Gupta if (phy == NULL) { 2265*b35ce0c4SPankaj Gupta continue; 2266*b35ce0c4SPankaj Gupta } 2267*b35ce0c4SPankaj Gupta 2268*b35ce0c4SPankaj Gupta ret = send_fw(phy, PHY_GEN2_DMEM_ADDR, msg, len); 2269*b35ce0c4SPankaj Gupta if (ret != 0) { 2270*b35ce0c4SPankaj Gupta return ret; 2271*b35ce0c4SPankaj Gupta } 2272*b35ce0c4SPankaj Gupta 2273*b35ce0c4SPankaj Gupta ret = send_fw(phy, PHY_GEN2_DMEM_ADDR + len / 2, 2274*b35ce0c4SPankaj Gupta (uint16_t *)image_buf, size); 2275*b35ce0c4SPankaj Gupta if (ret != 0) { 2276*b35ce0c4SPankaj Gupta return ret; 2277*b35ce0c4SPankaj Gupta } 2278*b35ce0c4SPankaj Gupta } 2279*b35ce0c4SPankaj Gupta 2280*b35ce0c4SPankaj Gupta return ret; 2281*b35ce0c4SPankaj Gupta } 2282*b35ce0c4SPankaj Gupta 2283*b35ce0c4SPankaj Gupta static void parse_odt(const unsigned int val, 2284*b35ce0c4SPankaj Gupta const int read, 2285*b35ce0c4SPankaj Gupta const int i, 2286*b35ce0c4SPankaj Gupta const unsigned int cs_d0, 2287*b35ce0c4SPankaj Gupta const unsigned int cs_d1, 2288*b35ce0c4SPankaj Gupta unsigned int *odt) 2289*b35ce0c4SPankaj Gupta { 2290*b35ce0c4SPankaj Gupta int shift = read ? 4 : 0; 2291*b35ce0c4SPankaj Gupta int j; 2292*b35ce0c4SPankaj Gupta 2293*b35ce0c4SPankaj Gupta if (i < 0 || i > 3) { 2294*b35ce0c4SPankaj Gupta printf("Error: invalid chip-select value\n"); 2295*b35ce0c4SPankaj Gupta } 2296*b35ce0c4SPankaj Gupta switch (val) { 2297*b35ce0c4SPankaj Gupta case DDR_ODT_CS: 2298*b35ce0c4SPankaj Gupta odt[i] |= (1 << i) << shift; 2299*b35ce0c4SPankaj Gupta break; 2300*b35ce0c4SPankaj Gupta case DDR_ODT_ALL_OTHER_CS: 2301*b35ce0c4SPankaj Gupta for (j = 0; j < DDRC_NUM_CS; j++) { 2302*b35ce0c4SPankaj Gupta if (i == j) { 2303*b35ce0c4SPankaj Gupta continue; 2304*b35ce0c4SPankaj Gupta } 2305*b35ce0c4SPankaj Gupta if (((cs_d0 | cs_d1) & (1 << j)) == 0) { 2306*b35ce0c4SPankaj Gupta continue; 2307*b35ce0c4SPankaj Gupta } 2308*b35ce0c4SPankaj Gupta odt[j] |= (1 << i) << shift; 2309*b35ce0c4SPankaj Gupta } 2310*b35ce0c4SPankaj Gupta break; 2311*b35ce0c4SPankaj Gupta case DDR_ODT_CS_AND_OTHER_DIMM: 2312*b35ce0c4SPankaj Gupta odt[i] |= (1 << i) << 4; 2313*b35ce0c4SPankaj Gupta /* fallthrough */ 2314*b35ce0c4SPankaj Gupta case DDR_ODT_OTHER_DIMM: 2315*b35ce0c4SPankaj Gupta for (j = 0; j < DDRC_NUM_CS; j++) { 2316*b35ce0c4SPankaj Gupta if ((((cs_d0 & (1 << i)) != 0) && 2317*b35ce0c4SPankaj Gupta ((cs_d1 & (1 << j)) != 0)) || 2318*b35ce0c4SPankaj Gupta (((cs_d1 & (1 << i)) != 0) && 2319*b35ce0c4SPankaj Gupta ((cs_d0 & (1 << j)) != 0))) { 2320*b35ce0c4SPankaj Gupta odt[j] |= (1 << i) << shift; 2321*b35ce0c4SPankaj Gupta } 2322*b35ce0c4SPankaj Gupta } 2323*b35ce0c4SPankaj Gupta break; 2324*b35ce0c4SPankaj Gupta case DDR_ODT_ALL: 2325*b35ce0c4SPankaj Gupta for (j = 0; j < DDRC_NUM_CS; j++) { 2326*b35ce0c4SPankaj Gupta if (((cs_d0 | cs_d1) & (1 << j)) == 0) { 2327*b35ce0c4SPankaj Gupta continue; 2328*b35ce0c4SPankaj Gupta } 2329*b35ce0c4SPankaj Gupta odt[j] |= (1 << i) << shift; 2330*b35ce0c4SPankaj Gupta } 2331*b35ce0c4SPankaj Gupta break; 2332*b35ce0c4SPankaj Gupta case DDR_ODT_SAME_DIMM: 2333*b35ce0c4SPankaj Gupta for (j = 0; j < DDRC_NUM_CS; j++) { 2334*b35ce0c4SPankaj Gupta if ((((cs_d0 & (1 << i)) != 0) && 2335*b35ce0c4SPankaj Gupta ((cs_d0 & (1 << j)) != 0)) || 2336*b35ce0c4SPankaj Gupta (((cs_d1 & (1 << i)) != 0) && 2337*b35ce0c4SPankaj Gupta ((cs_d1 & (1 << j)) != 0))) { 2338*b35ce0c4SPankaj Gupta odt[j] |= (1 << i) << shift; 2339*b35ce0c4SPankaj Gupta } 2340*b35ce0c4SPankaj Gupta } 2341*b35ce0c4SPankaj Gupta break; 2342*b35ce0c4SPankaj Gupta case DDR_ODT_OTHER_CS_ONSAMEDIMM: 2343*b35ce0c4SPankaj Gupta for (j = 0; j < DDRC_NUM_CS; j++) { 2344*b35ce0c4SPankaj Gupta if (i == j) { 2345*b35ce0c4SPankaj Gupta continue; 2346*b35ce0c4SPankaj Gupta } 2347*b35ce0c4SPankaj Gupta if ((((cs_d0 & (1 << i)) != 0) && 2348*b35ce0c4SPankaj Gupta ((cs_d0 & (1 << j)) != 0)) || 2349*b35ce0c4SPankaj Gupta (((cs_d1 & (1 << i)) != 0) && 2350*b35ce0c4SPankaj Gupta ((cs_d1 & (1 << j)) != 0))) { 2351*b35ce0c4SPankaj Gupta odt[j] |= (1 << i) << shift; 2352*b35ce0c4SPankaj Gupta } 2353*b35ce0c4SPankaj Gupta } 2354*b35ce0c4SPankaj Gupta break; 2355*b35ce0c4SPankaj Gupta case DDR_ODT_NEVER: 2356*b35ce0c4SPankaj Gupta break; 2357*b35ce0c4SPankaj Gupta default: 2358*b35ce0c4SPankaj Gupta break; 2359*b35ce0c4SPankaj Gupta } 2360*b35ce0c4SPankaj Gupta } 2361*b35ce0c4SPankaj Gupta 2362*b35ce0c4SPankaj Gupta #ifdef DEBUG_DDR_INPUT_CONFIG 2363*b35ce0c4SPankaj Gupta char *dram_types_str[] = { 2364*b35ce0c4SPankaj Gupta "DDR4", 2365*b35ce0c4SPankaj Gupta "DDR3", 2366*b35ce0c4SPankaj Gupta "LDDDR4", 2367*b35ce0c4SPankaj Gupta "LPDDR3", 2368*b35ce0c4SPankaj Gupta "LPDDR2", 2369*b35ce0c4SPankaj Gupta "DDR5" 2370*b35ce0c4SPankaj Gupta }; 2371*b35ce0c4SPankaj Gupta 2372*b35ce0c4SPankaj Gupta char *dimm_types_str[] = { 2373*b35ce0c4SPankaj Gupta "UDIMM", 2374*b35ce0c4SPankaj Gupta "SODIMM", 2375*b35ce0c4SPankaj Gupta "RDIMM", 2376*b35ce0c4SPankaj Gupta "LRDIMM", 2377*b35ce0c4SPankaj Gupta "NODIMM", 2378*b35ce0c4SPankaj Gupta }; 2379*b35ce0c4SPankaj Gupta 2380*b35ce0c4SPankaj Gupta 2381*b35ce0c4SPankaj Gupta static void print_jason_format(struct input *input, 2382*b35ce0c4SPankaj Gupta struct ddr4u1d *msg_1d, 2383*b35ce0c4SPankaj Gupta struct ddr4u2d *msg_2d) 2384*b35ce0c4SPankaj Gupta { 2385*b35ce0c4SPankaj Gupta 2386*b35ce0c4SPankaj Gupta printf("\n{"); 2387*b35ce0c4SPankaj Gupta printf("\n \"dram_type\": \"%s\",", dram_types_str[input->basic.dram_type]); 2388*b35ce0c4SPankaj Gupta printf("\n \"dimm_type\": \"%s\",", dimm_types_str[input->basic.dimm_type]); 2389*b35ce0c4SPankaj Gupta printf("\n \"hard_macro_ver\": \"%d\",", input->basic.hard_macro_ver); 2390*b35ce0c4SPankaj Gupta printf("\n \"num_dbyte\": \"0x%04x\",", (unsigned int)input->basic.num_dbyte); 2391*b35ce0c4SPankaj Gupta printf("\n \"num_active_dbyte_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_active_dbyte_dfi0); 2392*b35ce0c4SPankaj Gupta printf("\n \"num_anib\": \"0x%04x\",", (unsigned int)input->basic.num_anib); 2393*b35ce0c4SPankaj Gupta printf("\n \"num_rank_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_rank_dfi0); 2394*b35ce0c4SPankaj Gupta printf("\n \"num_pstates\": \"0x%04x\",", (unsigned int)input->basic.num_pstates); 2395*b35ce0c4SPankaj Gupta printf("\n \"frequency\": \"%d\",", input->basic.frequency); 2396*b35ce0c4SPankaj Gupta printf("\n \"pll_bypass\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); 2397*b35ce0c4SPankaj Gupta printf("\n \"dfi_freq_ratio\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); 2398*b35ce0c4SPankaj Gupta printf("\n \"dfi1_exists\": \"0x%04x\",", (unsigned int)input->basic.dfi1exists); 2399*b35ce0c4SPankaj Gupta printf("\n \"dram_data_width\": \"0x%04x\",", (unsigned int)input->basic.dram_data_width); 2400*b35ce0c4SPankaj Gupta printf("\n \"dram_byte_swap\": \"0x%04x\",", (unsigned int)input->adv.dram_byte_swap); 2401*b35ce0c4SPankaj Gupta printf("\n \"ext_cal_res_val\": \"0x%04x\",", (unsigned int)input->adv.ext_cal_res_val); 2402*b35ce0c4SPankaj Gupta printf("\n \"tx_slew_rise_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_dq); 2403*b35ce0c4SPankaj Gupta printf("\n \"tx_slew_fall_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_dq); 2404*b35ce0c4SPankaj Gupta printf("\n \"tx_slew_rise_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_ac); 2405*b35ce0c4SPankaj Gupta printf("\n \"tx_slew_fall_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_ac); 2406*b35ce0c4SPankaj Gupta printf("\n \"odt_impedance\": \"%d\",", input->adv.odtimpedance); 2407*b35ce0c4SPankaj Gupta printf("\n \"tx_impedance\": \"%d\",", input->adv.tx_impedance); 2408*b35ce0c4SPankaj Gupta printf("\n \"atx_impedance\": \"%d\",", input->adv.atx_impedance); 2409*b35ce0c4SPankaj Gupta printf("\n \"mem_alert_en\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_en); 2410*b35ce0c4SPankaj Gupta printf("\n \"mem_alert_pu_imp\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_puimp); 2411*b35ce0c4SPankaj Gupta printf("\n \"mem_alert_vref_level\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_vref_level); 2412*b35ce0c4SPankaj Gupta printf("\n \"mem_alert_sync_bypass\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_sync_bypass); 2413*b35ce0c4SPankaj Gupta printf("\n \"cal_interval\": \"0x%04x\",", (unsigned int)input->adv.cal_interval); 2414*b35ce0c4SPankaj Gupta printf("\n \"cal_once\": \"0x%04x\",", (unsigned int)input->adv.cal_once); 2415*b35ce0c4SPankaj Gupta printf("\n \"dis_dyn_adr_tri\": \"0x%04x\",", (unsigned int)input->adv.dis_dyn_adr_tri); 2416*b35ce0c4SPankaj Gupta printf("\n \"is2t_timing\": \"0x%04x\",", (unsigned int)input->adv.is2ttiming); 2417*b35ce0c4SPankaj Gupta printf("\n \"d4rx_preabmle_length\": \"0x%04x\",", (unsigned int)input->adv.d4rx_preamble_length); 2418*b35ce0c4SPankaj Gupta printf("\n \"d4tx_preamble_length\": \"0x%04x\",", (unsigned int)input->adv.d4tx_preamble_length); 2419*b35ce0c4SPankaj Gupta printf("\n \"msg_misc\": \"0x%02x\",", (unsigned int)msg_1d->msg_misc); 2420*b35ce0c4SPankaj Gupta printf("\n \"reserved00\": \"0x%01x\",", (unsigned int)msg_1d->reserved00); 2421*b35ce0c4SPankaj Gupta printf("\n \"hdt_ctrl\": \"0x%02x\",", (unsigned int)msg_1d->hdt_ctrl); 2422*b35ce0c4SPankaj Gupta printf("\n \"cs_present\": \"0x%02x\",", (unsigned int)msg_1d->cs_present); 2423*b35ce0c4SPankaj Gupta printf("\n \"phy_vref\": \"0x%02x\",", (unsigned int)msg_1d->phy_vref); 2424*b35ce0c4SPankaj Gupta printf("\n \"dfi_mrl_margin\": \"0x%02x\",", (unsigned int)msg_1d->dfimrlmargin); 2425*b35ce0c4SPankaj Gupta printf("\n \"addr_mirror\": \"0x%02x\",", (unsigned int)msg_1d->addr_mirror); 2426*b35ce0c4SPankaj Gupta printf("\n \"wr_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0x0f)); 2427*b35ce0c4SPankaj Gupta printf("\n \"wr_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0x0f)); 2428*b35ce0c4SPankaj Gupta printf("\n \"wr_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0x0f)); 2429*b35ce0c4SPankaj Gupta printf("\n \"wr_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0x0f)); 2430*b35ce0c4SPankaj Gupta printf("\n \"rd_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0xf0)); 2431*b35ce0c4SPankaj Gupta printf("\n \"rd_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0xf0)); 2432*b35ce0c4SPankaj Gupta printf("\n \"rd_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0xf0)); 2433*b35ce0c4SPankaj Gupta printf("\n \"rd_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0xf0)); 2434*b35ce0c4SPankaj Gupta printf("\n \"d4_misc\": \"0x%01x\",", (unsigned int)msg_1d->d4misc); 2435*b35ce0c4SPankaj Gupta printf("\n \"share_2d_vref_results\": \"0x%01x\",", (unsigned int)msg_1d->share2dvref_result); 2436*b35ce0c4SPankaj Gupta printf("\n \"sequence_ctrl\": \"0x%04x\",", (unsigned int)msg_1d->sequence_ctrl); 2437*b35ce0c4SPankaj Gupta printf("\n \"mr0\": \"0x%04x\",", (unsigned int)msg_1d->mr0); 2438*b35ce0c4SPankaj Gupta printf("\n \"mr1\": \"0x%04x\",", (unsigned int)msg_1d->mr1); 2439*b35ce0c4SPankaj Gupta printf("\n \"mr2\": \"0x%04x\",", (unsigned int)msg_1d->mr2); 2440*b35ce0c4SPankaj Gupta printf("\n \"mr3\": \"0x%04x\",", (unsigned int)msg_1d->mr3); 2441*b35ce0c4SPankaj Gupta printf("\n \"mr4\": \"0x%04x\",", (unsigned int)msg_1d->mr4); 2442*b35ce0c4SPankaj Gupta printf("\n \"mr5\": \"0x%04x\",", (unsigned int)msg_1d->mr5); 2443*b35ce0c4SPankaj Gupta printf("\n \"mr6\": \"0x%04x\",", (unsigned int)msg_1d->mr6); 2444*b35ce0c4SPankaj Gupta printf("\n \"alt_cal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_cas_l); 2445*b35ce0c4SPankaj Gupta printf("\n \"alt_wcal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_wcas_l); 2446*b35ce0c4SPankaj Gupta printf("\n \"sequence_ctrl_2d\": \"0x%04x\",", (unsigned int)msg_2d->sequence_ctrl); 2447*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park0\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park0); 2448*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park1\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park1); 2449*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park2\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park2); 2450*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park3\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park3); 2451*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park4\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park4); 2452*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park5\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park5); 2453*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park6\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park6); 2454*b35ce0c4SPankaj Gupta printf("\n \"rtt_nom_wr_park7\": \"0x%01x\"", (unsigned int)msg_1d->rtt_nom_wr_park7); 2455*b35ce0c4SPankaj Gupta printf("\n}"); 2456*b35ce0c4SPankaj Gupta printf("\n"); 2457*b35ce0c4SPankaj Gupta } 2458*b35ce0c4SPankaj Gupta #endif 2459*b35ce0c4SPankaj Gupta 2460*b35ce0c4SPankaj Gupta int compute_ddr_phy(struct ddr_info *priv) 2461*b35ce0c4SPankaj Gupta { 2462*b35ce0c4SPankaj Gupta const unsigned long clk = priv->clk; 2463*b35ce0c4SPankaj Gupta const struct memctl_opt *popts = &priv->opt; 2464*b35ce0c4SPankaj Gupta const struct ddr_conf *conf = &priv->conf; 2465*b35ce0c4SPankaj Gupta const struct dimm_params *dimm_param = &priv->dimm; 2466*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs = &priv->ddr_reg; 2467*b35ce0c4SPankaj Gupta int ret; 2468*b35ce0c4SPankaj Gupta static struct input input; 2469*b35ce0c4SPankaj Gupta static struct ddr4u1d msg_1d; 2470*b35ce0c4SPankaj Gupta static struct ddr4u2d msg_2d; 2471*b35ce0c4SPankaj Gupta unsigned int i; 2472*b35ce0c4SPankaj Gupta unsigned int odt_rd, odt_wr; 2473*b35ce0c4SPankaj Gupta __unused const soc_info_t *soc_info; 2474*b35ce0c4SPankaj Gupta #ifdef NXP_APPLY_MAX_CDD 2475*b35ce0c4SPankaj Gupta unsigned int tcfg0, tcfg4, rank; 2476*b35ce0c4SPankaj Gupta #endif 2477*b35ce0c4SPankaj Gupta 2478*b35ce0c4SPankaj Gupta if (dimm_param == NULL) { 2479*b35ce0c4SPankaj Gupta ERROR("Empty DIMM parameters.\n"); 2480*b35ce0c4SPankaj Gupta return -EINVAL; 2481*b35ce0c4SPankaj Gupta } 2482*b35ce0c4SPankaj Gupta 2483*b35ce0c4SPankaj Gupta zeromem(&input, sizeof(input)); 2484*b35ce0c4SPankaj Gupta zeromem(&msg_1d, sizeof(msg_1d)); 2485*b35ce0c4SPankaj Gupta zeromem(&msg_2d, sizeof(msg_2d)); 2486*b35ce0c4SPankaj Gupta 2487*b35ce0c4SPankaj Gupta input.basic.dram_type = DDR4; 2488*b35ce0c4SPankaj Gupta /* FIXME: Add condition for LRDIMM */ 2489*b35ce0c4SPankaj Gupta input.basic.dimm_type = (dimm_param->rdimm != 0) ? RDIMM : UDIMM; 2490*b35ce0c4SPankaj Gupta input.basic.num_dbyte = dimm_param->primary_sdram_width / 8 + 2491*b35ce0c4SPankaj Gupta dimm_param->ec_sdram_width / 8; 2492*b35ce0c4SPankaj Gupta input.basic.num_active_dbyte_dfi0 = input.basic.num_dbyte; 2493*b35ce0c4SPankaj Gupta input.basic.num_rank_dfi0 = dimm_param->n_ranks; 2494*b35ce0c4SPankaj Gupta input.basic.dram_data_width = dimm_param->device_width; 2495*b35ce0c4SPankaj Gupta input.basic.hard_macro_ver = 0xa; 2496*b35ce0c4SPankaj Gupta input.basic.num_pstates = 1; 2497*b35ce0c4SPankaj Gupta input.basic.dfi_freq_ratio = 1; 2498*b35ce0c4SPankaj Gupta input.basic.num_anib = 0xc; 2499*b35ce0c4SPankaj Gupta input.basic.train2d = popts->skip2d ? 0 : 1; 2500*b35ce0c4SPankaj Gupta input.basic.frequency = (int) (clk / 2000000ul); 2501*b35ce0c4SPankaj Gupta debug("frequency = %dMHz\n", input.basic.frequency); 2502*b35ce0c4SPankaj Gupta input.cs_d0 = conf->cs_on_dimm[0]; 2503*b35ce0c4SPankaj Gupta #if DDRC_NUM_DIMM > 1 2504*b35ce0c4SPankaj Gupta input.cs_d1 = conf->cs_on_dimm[1]; 2505*b35ce0c4SPankaj Gupta #endif 2506*b35ce0c4SPankaj Gupta input.mirror = dimm_param->mirrored_dimm; 2507*b35ce0c4SPankaj Gupta input.mr[0] = regs->sdram_mode[0] & U(0xffff); 2508*b35ce0c4SPankaj Gupta input.mr[1] = regs->sdram_mode[0] >> 16U; 2509*b35ce0c4SPankaj Gupta input.mr[2] = regs->sdram_mode[1] >> 16U; 2510*b35ce0c4SPankaj Gupta input.mr[3] = regs->sdram_mode[1] & U(0xffff); 2511*b35ce0c4SPankaj Gupta input.mr[4] = regs->sdram_mode[8] >> 16U; 2512*b35ce0c4SPankaj Gupta input.mr[5] = regs->sdram_mode[8] & U(0xffff); 2513*b35ce0c4SPankaj Gupta input.mr[6] = regs->sdram_mode[9] >> 16U; 2514*b35ce0c4SPankaj Gupta input.vref = popts->vref_phy; 2515*b35ce0c4SPankaj Gupta debug("Vref_phy = %d percent\n", (input.vref * 100U) >> 7U); 2516*b35ce0c4SPankaj Gupta for (i = 0U; i < DDRC_NUM_CS; i++) { 2517*b35ce0c4SPankaj Gupta if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0U) { 2518*b35ce0c4SPankaj Gupta continue; 2519*b35ce0c4SPankaj Gupta } 2520*b35ce0c4SPankaj Gupta odt_rd = (regs->cs[i].config >> 20U) & U(0x7); 2521*b35ce0c4SPankaj Gupta odt_wr = (regs->cs[i].config >> 16U) & U(0x7); 2522*b35ce0c4SPankaj Gupta parse_odt(odt_rd, true, i, input.cs_d0, input.cs_d1, 2523*b35ce0c4SPankaj Gupta input.odt); 2524*b35ce0c4SPankaj Gupta parse_odt(odt_wr, false, i, input.cs_d0, input.cs_d1, 2525*b35ce0c4SPankaj Gupta input.odt); 2526*b35ce0c4SPankaj Gupta } 2527*b35ce0c4SPankaj Gupta 2528*b35ce0c4SPankaj Gupta /* Do not set sdram_cfg[RD_EN] or sdram_cfg2[RCW_EN] for RDIMM */ 2529*b35ce0c4SPankaj Gupta if (dimm_param->rdimm != 0U) { 2530*b35ce0c4SPankaj Gupta regs->sdram_cfg[0] &= ~(1 << 28U); 2531*b35ce0c4SPankaj Gupta regs->sdram_cfg[1] &= ~(1 << 2U); 2532*b35ce0c4SPankaj Gupta input.rcw[0] = (regs->sdram_rcw[0] >> 28U) & U(0xf); 2533*b35ce0c4SPankaj Gupta input.rcw[1] = (regs->sdram_rcw[0] >> 24U) & U(0xf); 2534*b35ce0c4SPankaj Gupta input.rcw[2] = (regs->sdram_rcw[0] >> 20U) & U(0xf); 2535*b35ce0c4SPankaj Gupta input.rcw[3] = (regs->sdram_rcw[0] >> 16U) & U(0xf); 2536*b35ce0c4SPankaj Gupta input.rcw[4] = (regs->sdram_rcw[0] >> 12U) & U(0xf); 2537*b35ce0c4SPankaj Gupta input.rcw[5] = (regs->sdram_rcw[0] >> 8U) & U(0xf); 2538*b35ce0c4SPankaj Gupta input.rcw[6] = (regs->sdram_rcw[0] >> 4U) & U(0xf); 2539*b35ce0c4SPankaj Gupta input.rcw[7] = (regs->sdram_rcw[0] >> 0U) & U(0xf); 2540*b35ce0c4SPankaj Gupta input.rcw[8] = (regs->sdram_rcw[1] >> 28U) & U(0xf); 2541*b35ce0c4SPankaj Gupta input.rcw[9] = (regs->sdram_rcw[1] >> 24U) & U(0xf); 2542*b35ce0c4SPankaj Gupta input.rcw[10] = (regs->sdram_rcw[1] >> 20U) & U(0xf); 2543*b35ce0c4SPankaj Gupta input.rcw[11] = (regs->sdram_rcw[1] >> 16U) & U(0xf); 2544*b35ce0c4SPankaj Gupta input.rcw[12] = (regs->sdram_rcw[1] >> 12U) & U(0xf); 2545*b35ce0c4SPankaj Gupta input.rcw[13] = (regs->sdram_rcw[1] >> 8U) & U(0xf); 2546*b35ce0c4SPankaj Gupta input.rcw[14] = (regs->sdram_rcw[1] >> 4U) & U(0xf); 2547*b35ce0c4SPankaj Gupta input.rcw[15] = (regs->sdram_rcw[1] >> 0U) & U(0xf); 2548*b35ce0c4SPankaj Gupta input.rcw3x = (regs->sdram_rcw[2] >> 8U) & U(0xff); 2549*b35ce0c4SPankaj Gupta } 2550*b35ce0c4SPankaj Gupta 2551*b35ce0c4SPankaj Gupta input.adv.odtimpedance = popts->odt ? popts->odt : 60; 2552*b35ce0c4SPankaj Gupta input.adv.tx_impedance = popts->phy_tx_impedance ? 2553*b35ce0c4SPankaj Gupta popts->phy_tx_impedance : 28; 2554*b35ce0c4SPankaj Gupta input.adv.atx_impedance = popts->phy_atx_impedance ? 2555*b35ce0c4SPankaj Gupta popts->phy_atx_impedance : 30; 2556*b35ce0c4SPankaj Gupta 2557*b35ce0c4SPankaj Gupta debug("Initializing input adv data structure\n"); 2558*b35ce0c4SPankaj Gupta phy_gen2_init_input(&input); 2559*b35ce0c4SPankaj Gupta 2560*b35ce0c4SPankaj Gupta debug("Initializing message block\n"); 2561*b35ce0c4SPankaj Gupta ret = phy_gen2_msg_init(&msg_1d, &msg_2d, &input); 2562*b35ce0c4SPankaj Gupta if (ret != 0) { 2563*b35ce0c4SPankaj Gupta ERROR("Init msg failed (error code %d)\n", ret); 2564*b35ce0c4SPankaj Gupta return ret; 2565*b35ce0c4SPankaj Gupta } 2566*b35ce0c4SPankaj Gupta 2567*b35ce0c4SPankaj Gupta ret = c_init_phy_config(priv->phy, priv->ip_rev, &input, &msg_1d); 2568*b35ce0c4SPankaj Gupta if (ret != 0) { 2569*b35ce0c4SPankaj Gupta ERROR("Init PHY failed (error code %d)\n", ret); 2570*b35ce0c4SPankaj Gupta return ret; 2571*b35ce0c4SPankaj Gupta } 2572*b35ce0c4SPankaj Gupta #ifdef NXP_WARM_BOOT 2573*b35ce0c4SPankaj Gupta debug("Warm boot flag value %0x\n", priv->warm_boot_flag); 2574*b35ce0c4SPankaj Gupta if (priv->warm_boot_flag == DDR_WARM_BOOT) { 2575*b35ce0c4SPankaj Gupta debug("Restoring the Phy training data\n"); 2576*b35ce0c4SPankaj Gupta // Restore the training data 2577*b35ce0c4SPankaj Gupta ret = restore_phy_training_values(priv->phy, 2578*b35ce0c4SPankaj Gupta PHY_TRAINING_REGS_ON_FLASH, 2579*b35ce0c4SPankaj Gupta priv->num_ctlrs, 2580*b35ce0c4SPankaj Gupta input.basic.train2d); 2581*b35ce0c4SPankaj Gupta if (ret != 0) { 2582*b35ce0c4SPankaj Gupta ERROR("Restoring of training data failed %d\n", ret); 2583*b35ce0c4SPankaj Gupta return ret; 2584*b35ce0c4SPankaj Gupta } 2585*b35ce0c4SPankaj Gupta } else { 2586*b35ce0c4SPankaj Gupta #endif 2587*b35ce0c4SPankaj Gupta 2588*b35ce0c4SPankaj Gupta debug("Load 1D firmware\n"); 2589*b35ce0c4SPankaj Gupta ret = load_fw(priv->phy, &input, 0, &msg_1d, 2590*b35ce0c4SPankaj Gupta sizeof(struct ddr4u1d), priv->phy_gen2_fw_img_buf, 2591*b35ce0c4SPankaj Gupta priv->img_loadr, priv->warm_boot_flag); 2592*b35ce0c4SPankaj Gupta if (ret != 0) { 2593*b35ce0c4SPankaj Gupta ERROR("Loading firmware failed (error code %d)\n", ret); 2594*b35ce0c4SPankaj Gupta return ret; 2595*b35ce0c4SPankaj Gupta } 2596*b35ce0c4SPankaj Gupta 2597*b35ce0c4SPankaj Gupta debug("Execute firmware\n"); 2598*b35ce0c4SPankaj Gupta ret = g_exec_fw(priv->phy, 0, &input); 2599*b35ce0c4SPankaj Gupta if (ret != 0) { 2600*b35ce0c4SPankaj Gupta ERROR("Execution FW failed (error code %d)\n", ret); 2601*b35ce0c4SPankaj Gupta } 2602*b35ce0c4SPankaj Gupta 2603*b35ce0c4SPankaj Gupta #ifdef NXP_APPLY_MAX_CDD 2604*b35ce0c4SPankaj Gupta soc_info = get_soc_info(NXP_DCFG_ADDR); 2605*b35ce0c4SPankaj Gupta if (soc_info->maj_ver == 2) { 2606*b35ce0c4SPankaj Gupta tcfg0 = regs->timing_cfg[0]; 2607*b35ce0c4SPankaj Gupta tcfg4 = regs->timing_cfg[4]; 2608*b35ce0c4SPankaj Gupta rank = findrank(conf->cs_in_use); 2609*b35ce0c4SPankaj Gupta get_cdd_val(priv->phy, rank, input.basic.frequency, 2610*b35ce0c4SPankaj Gupta &tcfg0, &tcfg4); 2611*b35ce0c4SPankaj Gupta regs->timing_cfg[0] = tcfg0; 2612*b35ce0c4SPankaj Gupta regs->timing_cfg[4] = tcfg4; 2613*b35ce0c4SPankaj Gupta } 2614*b35ce0c4SPankaj Gupta #endif 2615*b35ce0c4SPankaj Gupta 2616*b35ce0c4SPankaj Gupta if ((ret == 0) && (input.basic.train2d != 0)) { 2617*b35ce0c4SPankaj Gupta /* 2D training starts here */ 2618*b35ce0c4SPankaj Gupta debug("Load 2D firmware\n"); 2619*b35ce0c4SPankaj Gupta ret = load_fw(priv->phy, &input, 1, &msg_2d, 2620*b35ce0c4SPankaj Gupta sizeof(struct ddr4u2d), 2621*b35ce0c4SPankaj Gupta priv->phy_gen2_fw_img_buf, 2622*b35ce0c4SPankaj Gupta priv->img_loadr, 2623*b35ce0c4SPankaj Gupta priv->warm_boot_flag); 2624*b35ce0c4SPankaj Gupta if (ret != 0) { 2625*b35ce0c4SPankaj Gupta ERROR("Loading fw failed (err code %d)\n", ret); 2626*b35ce0c4SPankaj Gupta } else { 2627*b35ce0c4SPankaj Gupta debug("Execute 2D firmware\n"); 2628*b35ce0c4SPankaj Gupta ret = g_exec_fw(priv->phy, 1, &input); 2629*b35ce0c4SPankaj Gupta if (ret != 0) { 2630*b35ce0c4SPankaj Gupta ERROR("Execution FW failed (err %d)\n", 2631*b35ce0c4SPankaj Gupta ret); 2632*b35ce0c4SPankaj Gupta } 2633*b35ce0c4SPankaj Gupta } 2634*b35ce0c4SPankaj Gupta } 2635*b35ce0c4SPankaj Gupta #ifdef NXP_WARM_BOOT 2636*b35ce0c4SPankaj Gupta if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED && 2637*b35ce0c4SPankaj Gupta ret == 0) { 2638*b35ce0c4SPankaj Gupta debug("save the phy training data\n"); 2639*b35ce0c4SPankaj Gupta //Save training data TBD 2640*b35ce0c4SPankaj Gupta ret = save_phy_training_values(priv->phy, 2641*b35ce0c4SPankaj Gupta PHY_TRAINING_REGS_ON_FLASH, 2642*b35ce0c4SPankaj Gupta priv->num_ctlrs, 2643*b35ce0c4SPankaj Gupta input.basic.train2d); 2644*b35ce0c4SPankaj Gupta if (ret != 0) { 2645*b35ce0c4SPankaj Gupta ERROR("Saving training data failed."); 2646*b35ce0c4SPankaj Gupta ERROR("Warm boot will fail. Error=%d.\n", ret); 2647*b35ce0c4SPankaj Gupta } 2648*b35ce0c4SPankaj Gupta } 2649*b35ce0c4SPankaj Gupta } /* else */ 2650*b35ce0c4SPankaj Gupta #endif 2651*b35ce0c4SPankaj Gupta 2652*b35ce0c4SPankaj Gupta if (ret == 0) { 2653*b35ce0c4SPankaj Gupta debug("Load PIE\n"); 2654*b35ce0c4SPankaj Gupta i_load_pie(priv->phy, &input, &msg_1d); 2655*b35ce0c4SPankaj Gupta 2656*b35ce0c4SPankaj Gupta NOTICE("DDR4 %s with %d-rank %d-bit bus (x%d)\n", 2657*b35ce0c4SPankaj Gupta input.basic.dimm_type == RDIMM ? "RDIMM" : 2658*b35ce0c4SPankaj Gupta input.basic.dimm_type == LRDIMM ? "LRDIMM" : 2659*b35ce0c4SPankaj Gupta "UDIMM", 2660*b35ce0c4SPankaj Gupta dimm_param->n_ranks, 2661*b35ce0c4SPankaj Gupta dimm_param->primary_sdram_width, 2662*b35ce0c4SPankaj Gupta dimm_param->device_width); 2663*b35ce0c4SPankaj Gupta } 2664*b35ce0c4SPankaj Gupta #ifdef DEBUG_DDR_INPUT_CONFIG 2665*b35ce0c4SPankaj Gupta print_jason_format(&input, &msg_1d, &msg_2d); 2666*b35ce0c4SPankaj Gupta #endif 2667*b35ce0c4SPankaj Gupta 2668*b35ce0c4SPankaj Gupta return ret; 2669*b35ce0c4SPankaj Gupta } 2670