1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018 Marvell International Ltd. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * https://spdx.org/licenses 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <arch_helpers.h> 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <drivers/mentor/mi2cv.h> 11*91f16700Schasinglulu #include <lib/mmio.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <mv_ddr_if.h> 14*91f16700Schasinglulu #include <mvebu_def.h> 15*91f16700Schasinglulu #include <plat_marvell.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #define MVEBU_CP_MPP_CTRL37_OFFS 20 18*91f16700Schasinglulu #define MVEBU_CP_MPP_CTRL38_OFFS 24 19*91f16700Schasinglulu #define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2 20*91f16700Schasinglulu #define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define MVEBU_MPP_CTRL_MASK 0xf 23*91f16700Schasinglulu 24*91f16700Schasinglulu /* 25*91f16700Schasinglulu * This struct provides the DRAM training code with 26*91f16700Schasinglulu * the appropriate board DRAM configuration 27*91f16700Schasinglulu */ 28*91f16700Schasinglulu struct mv_ddr_iface dram_iface_ap0 = { 29*91f16700Schasinglulu .ap_base = MVEBU_REGS_BASE_AP(0), 30*91f16700Schasinglulu .state = MV_DDR_IFACE_NRDY, 31*91f16700Schasinglulu .validation = MV_DDR_MEMORY_CHECK, 32*91f16700Schasinglulu .sscg = SSCG_EN, 33*91f16700Schasinglulu .id = 0, 34*91f16700Schasinglulu .iface_base_addr = 0, 35*91f16700Schasinglulu .tm = { 36*91f16700Schasinglulu DEBUG_LEVEL_ERROR, 37*91f16700Schasinglulu 0x1, /* active interfaces */ 38*91f16700Schasinglulu /* cs_mask, mirror, dqs_swap, ck_swap X subphys */ 39*91f16700Schasinglulu { { { {0x1, 0x0, 0, 0}, 40*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 41*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 42*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 43*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 44*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 45*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 46*91f16700Schasinglulu {0x1, 0x0, 0, 0}, 47*91f16700Schasinglulu {0x1, 0x0, 0, 0} }, 48*91f16700Schasinglulu SPEED_BIN_DDR_2400T, /* speed_bin */ 49*91f16700Schasinglulu MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */ 50*91f16700Schasinglulu MV_DDR_DIE_CAP_8GBIT, /* die capacity */ 51*91f16700Schasinglulu MV_DDR_FREQ_SAR, /* frequency */ 52*91f16700Schasinglulu 0, 0, /* cas_l, cas_wl */ 53*91f16700Schasinglulu MV_DDR_TEMP_LOW} }, /* temperature */ 54*91f16700Schasinglulu #if DDR32 55*91f16700Schasinglulu MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ 56*91f16700Schasinglulu #else 57*91f16700Schasinglulu MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */ 58*91f16700Schasinglulu #endif 59*91f16700Schasinglulu MV_DDR_CFG_SPD, /* ddr configuration data src */ 60*91f16700Schasinglulu NOT_COMBINED, /* ddr twin-die combined*/ 61*91f16700Schasinglulu { {0} }, /* raw spd data */ 62*91f16700Schasinglulu {0}, /* timing parameters */ 63*91f16700Schasinglulu { /* electrical configuration */ 64*91f16700Schasinglulu { /* memory electrical configuration */ 65*91f16700Schasinglulu MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */ 66*91f16700Schasinglulu { /* rtt_park 1cs */ 67*91f16700Schasinglulu MV_DDR_RTT_NOM_PARK_RZQ_DIV4, 68*91f16700Schasinglulu /* rtt_park 2cs */ 69*91f16700Schasinglulu MV_DDR_RTT_NOM_PARK_RZQ_DIV1 70*91f16700Schasinglulu }, 71*91f16700Schasinglulu { /* rtt_wr 1cs */ 72*91f16700Schasinglulu MV_DDR_RTT_WR_DYN_ODT_OFF, 73*91f16700Schasinglulu /* rtt_wr 2cs */ 74*91f16700Schasinglulu MV_DDR_RTT_WR_RZQ_DIV2 75*91f16700Schasinglulu }, 76*91f16700Schasinglulu MV_DDR_DIC_RZQ_DIV7 /* dic */ 77*91f16700Schasinglulu }, 78*91f16700Schasinglulu { /* phy electrical configuration */ 79*91f16700Schasinglulu MV_DDR_OHM_30, /* data_drv_p */ 80*91f16700Schasinglulu MV_DDR_OHM_30, /* data_drv_n */ 81*91f16700Schasinglulu MV_DDR_OHM_30, /* ctrl_drv_p */ 82*91f16700Schasinglulu MV_DDR_OHM_30, /* ctrl_drv_n */ 83*91f16700Schasinglulu { 84*91f16700Schasinglulu MV_DDR_OHM_60, /* odt_p 1cs */ 85*91f16700Schasinglulu MV_DDR_OHM_120 /* odt_p 2cs */ 86*91f16700Schasinglulu }, 87*91f16700Schasinglulu { 88*91f16700Schasinglulu MV_DDR_OHM_60, /* odt_n 1cs */ 89*91f16700Schasinglulu MV_DDR_OHM_120 /* odt_n 2cs */ 90*91f16700Schasinglulu }, 91*91f16700Schasinglulu }, 92*91f16700Schasinglulu { /* mac electrical configuration */ 93*91f16700Schasinglulu MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */ 94*91f16700Schasinglulu MV_DDR_ODT_CFG_ALWAYS_ON,/* odtcfg_write */ 95*91f16700Schasinglulu MV_DDR_ODT_CFG_NORMAL /* odtcfg_read */ 96*91f16700Schasinglulu }, 97*91f16700Schasinglulu }, 98*91f16700Schasinglulu }, 99*91f16700Schasinglulu }; 100*91f16700Schasinglulu 101*91f16700Schasinglulu /* Pointer to the first DRAM interface in the system */ 102*91f16700Schasinglulu struct mv_ddr_iface *ptr_iface = &dram_iface_ap0; 103*91f16700Schasinglulu 104*91f16700Schasinglulu struct mv_ddr_iface *mv_ddr_iface_get(void) 105*91f16700Schasinglulu { 106*91f16700Schasinglulu /* Return current ddr interface */ 107*91f16700Schasinglulu return ptr_iface; 108*91f16700Schasinglulu } 109*91f16700Schasinglulu 110*91f16700Schasinglulu struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) 111*91f16700Schasinglulu { 112*91f16700Schasinglulu /* Return the board topology as defined in the board code */ 113*91f16700Schasinglulu return &ptr_iface->tm; 114*91f16700Schasinglulu } 115*91f16700Schasinglulu 116*91f16700Schasinglulu static void mpp_config(void) 117*91f16700Schasinglulu { 118*91f16700Schasinglulu uintptr_t reg; 119*91f16700Schasinglulu uint32_t val; 120*91f16700Schasinglulu 121*91f16700Schasinglulu reg = MVEBU_CP_MPP_REGS(0, 4); 122*91f16700Schasinglulu /* configure CP0 MPP 37 and 38 to i2c */ 123*91f16700Schasinglulu val = mmio_read_32(reg); 124*91f16700Schasinglulu val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) | 125*91f16700Schasinglulu (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS)); 126*91f16700Schasinglulu val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << 127*91f16700Schasinglulu MVEBU_CP_MPP_CTRL37_OFFS) | 128*91f16700Schasinglulu (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << 129*91f16700Schasinglulu MVEBU_CP_MPP_CTRL38_OFFS); 130*91f16700Schasinglulu mmio_write_32(reg, val); 131*91f16700Schasinglulu } 132*91f16700Schasinglulu 133*91f16700Schasinglulu /* 134*91f16700Schasinglulu * This function may modify the default DRAM parameters 135*91f16700Schasinglulu * based on information received from SPD or bootloader 136*91f16700Schasinglulu * configuration located on non volatile storage 137*91f16700Schasinglulu */ 138*91f16700Schasinglulu void plat_marvell_dram_update_topology(void) 139*91f16700Schasinglulu { 140*91f16700Schasinglulu struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 141*91f16700Schasinglulu 142*91f16700Schasinglulu INFO("Gathering DRAM information\n"); 143*91f16700Schasinglulu 144*91f16700Schasinglulu if (tm->cfg_src == MV_DDR_CFG_SPD) { 145*91f16700Schasinglulu /* configure MPPs to enable i2c */ 146*91f16700Schasinglulu mpp_config(); 147*91f16700Schasinglulu 148*91f16700Schasinglulu /* initialize i2c */ 149*91f16700Schasinglulu i2c_init((void *)MVEBU_CP0_I2C_BASE); 150*91f16700Schasinglulu 151*91f16700Schasinglulu /* select SPD memory page 0 to access DRAM configuration */ 152*91f16700Schasinglulu i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0); 153*91f16700Schasinglulu 154*91f16700Schasinglulu /* read data from spd */ 155*91f16700Schasinglulu i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes, 156*91f16700Schasinglulu sizeof(tm->spd_data.all_bytes)); 157*91f16700Schasinglulu } 158*91f16700Schasinglulu } 159