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