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