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