]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
arm: mvebu: Add Armada 38x SERDES / PHY init code from Marvell bin_hdr
[karo-tx-uboot.git] / arch / arm / mach-mvebu / serdes / a38x / sys_env_lib.c
1 /*
2  * Copyright (C) Marvell International Ltd. and its affiliates
3  *
4  * SPDX-License-Identifier:     GPL-2.0
5  */
6
7 #include <common.h>
8 #include <i2c.h>
9 #include <spl.h>
10 #include <asm/io.h>
11 #include <asm/arch/cpu.h>
12 #include <asm/arch/soc.h>
13
14 #include "seq_exec.h"
15 #include "sys_env_lib.h"
16
17 #include "../../../drivers/ddr/marvell/a38x/ddr3_a38x.h"
18
19 #ifdef CONFIG_ARMADA_38X
20 enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
21 /*                     6820    6810     6811     6828     */
22 /* PEX_UNIT_ID      */ { 4,     3,       3,       4},
23 /* ETH_GIG_UNIT_ID  */ { 3,     2,       3,       3},
24 /* USB3H_UNIT_ID    */ { 2,     2,       2,       2},
25 /* USB3D_UNIT_ID    */ { 1,     1,       1,       1},
26 /* SATA_UNIT_ID     */ { 2,     2,       2,       4},
27 /* QSGMII_UNIT_ID   */ { 1,     0,       0,       1},
28 /* XAUI_UNIT_ID     */ { 0,     0,       0,       0},
29 /* RXAUI_UNIT_ID    */ { 0,     0,       0,       0}
30 };
31 #else  /* if (CONFIG_ARMADA_39X) */
32 enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
33 /*                      6920     6928     */
34 /* PEX_UNIT_ID      */ { 4,       4},
35 /* ETH_GIG_UNIT_ID  */ { 3,       4},
36 /* USB3H_UNIT_ID    */ { 1,       2},
37 /* USB3D_UNIT_ID    */ { 0,       1},
38 /* SATA_UNIT_ID     */ { 0,       4},
39 /* QSGMII_UNIT_ID   */ { 0,       1},
40 /* XAUI_UNIT_ID     */ { 1,       1},
41 /* RXAUI_UNIT_ID    */ { 1,       1}
42 };
43 #endif
44
45 u32 g_dev_id = -1;
46
47 u32 mv_board_id_get(void)
48 {
49 #if defined(CONFIG_DB_88F6820_GP)
50         return DB_GP_68XX_ID;
51 #else
52         /*
53          * Return 0 here for custom board as this should not be used
54          * for custom boards.
55          */
56         return 0;
57 #endif
58 }
59
60 u32 mv_board_tclk_get(void)
61 {
62         u32 value;
63
64         value = (reg_read(DEVICE_SAMPLE_AT_RESET1_REG) >> 15) & 0x1;
65
66         switch (value) {
67         case (0x0):
68                 return 250000000;
69         case (0x1):
70                 return 200000000;
71         default:
72                 return 0xffffffff;
73         }
74 }
75
76 u32 mv_board_id_index_get(u32 board_id)
77 {
78         /*
79          * Marvell Boards use 0x10 as base for Board ID:
80          * mask MSB to receive index for board ID
81          */
82         return board_id & (MARVELL_BOARD_ID_MASK - 1);
83 }
84
85 /*
86  * sys_env_suspend_wakeup_check
87  * DESCRIPTION:         Reads GPIO input for suspend-wakeup indication.
88  * INPUT:               None.
89  * OUTPUT:
90  * RETURNS:             u32 indicating suspend wakeup status:
91  * 0 - Not supported,
92  * 1 - supported: read magic word detect wakeup,
93  * 2 - detected wakeup from GPIO.
94  */
95 enum suspend_wakeup_status sys_env_suspend_wakeup_check(void)
96 {
97         u32 reg, board_id_index, gpio;
98         struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO;
99
100         board_id_index = mv_board_id_index_get(mv_board_id_get());
101         if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) >
102               board_id_index)) {
103                 printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n");
104                 return SUSPEND_WAKEUP_DISABLED;
105         }
106
107         /*
108          * - Detect if Suspend-Wakeup is supported on current board
109          * - Fetch the GPIO number for wakeup status input indication
110          */
111         if (board_gpio[board_id_index].gpio_num == -1) {
112                 /* Suspend to RAM is not supported */
113                 return SUSPEND_WAKEUP_DISABLED;
114         } else if (board_gpio[board_id_index].gpio_num == -2) {
115                 /*
116                  * Suspend to RAM is supported but GPIO indication is
117                  * not implemented - Skip
118                  */
119                 return SUSPEND_WAKEUP_ENABLED;
120         } else {
121                 gpio = board_gpio[board_id_index].gpio_num;
122         }
123
124         /* Initialize MPP for GPIO (set MPP = 0x0) */
125         reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio)));
126         /* reset MPP21 to 0x0, keep rest of MPP settings*/
127         reg &= ~MPP_MASK(gpio);
128         reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg);
129
130         /* Initialize GPIO as input */
131         reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)));
132         reg |= GPP_MASK(gpio);
133         reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg);
134
135         /*
136          * Check GPP for input status from PIC: 0 - regular init,
137          * 1 - suspend wakeup
138          */
139         reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio)));
140
141         /* if GPIO is ON: wakeup from S2RAM indication detected */
142         return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED :
143                 SUSPEND_WAKEUP_DISABLED;
144 }
145
146 /*
147  * mv_ctrl_dev_id_index_get
148  *
149  * DESCRIPTION: return SOC device index
150  * INPUT: None
151  * OUTPUT: None
152  * RETURN:
153  *        return SOC device index
154  */
155 u32 sys_env_id_index_get(u32 ctrl_model)
156 {
157         switch (ctrl_model) {
158         case MV_6820_DEV_ID:
159                 return MV_6820_INDEX;
160         case MV_6810_DEV_ID:
161                 return MV_6810_INDEX;
162         case MV_6811_DEV_ID:
163                 return MV_6811_INDEX;
164         case MV_6828_DEV_ID:
165                 return MV_6828_INDEX;
166         case MV_6920_DEV_ID:
167                 return MV_6920_INDEX;
168         case MV_6928_DEV_ID:
169                 return MV_6928_INDEX;
170         default:
171                 return MV_6820_INDEX;
172         }
173 }
174
175 u32 sys_env_unit_max_num_get(enum unit_id unit)
176 {
177         u32 dev_id_index;
178
179         if (unit >= MAX_UNITS_ID) {
180                 printf("%s: Error: Wrong unit type (%u)\n", __func__, unit);
181                 return 0;
182         }
183
184         dev_id_index = sys_env_id_index_get(sys_env_model_get());
185         return sys_env_soc_unit_nums[unit][dev_id_index];
186 }
187
188 /*
189  * sys_env_model_get
190  * DESCRIPTION: Returns 16bit describing the device model (ID) as defined
191  *              in Vendor ID configuration register
192  */
193 u16 sys_env_model_get(void)
194 {
195         u32 default_ctrl_id, ctrl_id = reg_read(DEV_ID_REG);
196         ctrl_id = (ctrl_id & (DEV_ID_REG_DEVICE_ID_MASK)) >>
197                 DEV_ID_REG_DEVICE_ID_OFFS;
198
199         switch (ctrl_id) {
200         case MV_6820_DEV_ID:
201         case MV_6810_DEV_ID:
202         case MV_6811_DEV_ID:
203         case MV_6828_DEV_ID:
204         case MV_6920_DEV_ID:
205         case MV_6928_DEV_ID:
206                 return ctrl_id;
207         default:
208                 /* Device ID Default for A38x: 6820 , for A39x: 6920 */
209         #ifdef CONFIG_ARMADA_38X
210                 default_ctrl_id =  MV_6820_DEV_ID;
211         #else
212                 default_ctrl_id = MV_6920_DEV_ID;
213         #endif
214                 printf("%s: Error retrieving device ID (%x), using default ID = %x\n",
215                        __func__, ctrl_id, default_ctrl_id);
216                 return default_ctrl_id;
217         }
218 }
219
220 /*
221  * sys_env_device_id_get
222  * DESCRIPTION: Returns enum (0..7) index of the device model (ID)
223  */
224 u32 sys_env_device_id_get(void)
225 {
226         char *device_id_str[7] = {
227                 "6810", "6820", "6811", "6828", "NONE", "6920", "6928"
228         };
229
230         if (g_dev_id != -1)
231                 return g_dev_id;
232
233         g_dev_id = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
234         g_dev_id = g_dev_id >> SAR_DEV_ID_OFFS & SAR_DEV_ID_MASK;
235         printf("Detected Device ID %s\n", device_id_str[g_dev_id]);
236
237         return g_dev_id;
238 }
239
240 #ifdef MV_DDR_TOPOLOGY_UPDATE_FROM_TWSI
241 /*
242 * sys_env_get_topology_update_info
243 * DESCRIPTION: Read TWSI fields to update DDR topology structure
244 * INPUT: None
245 * OUTPUT: None, 0 means no topology update
246 * RETURN:
247 *       Bit mask of changes topology features
248 */
249 #ifdef CONFIG_ARMADA_39X
250 u32 sys_env_get_topology_update_info(
251         struct topology_update_info *tui)
252 {
253         /* Set 16/32 bit configuration*/
254         tui->update_width = 1;
255         tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
256
257 #ifdef CONFIG_DDR3
258         if (1 == sys_env_config_get(MV_CONFIG_DDR_BUSWIDTH)) {
259                 /* 16bit */
260                 tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
261         } else {
262                 /* 32bit */
263                 tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
264         }
265 #endif
266
267         /* Set ECC/no ECC bit configuration */
268         tui->update_ecc = 1;
269         if (0 == sys_env_config_get(MV_CONFIG_DDR_ECC_EN)) {
270                 /* NO ECC */
271                 tui->ecc = TOPOLOGY_UPDATE_ECC_OFF;
272         } else {
273                 /* ECC */
274                 tui->ecc = TOPOLOGY_UPDATE_ECC_ON;
275         }
276
277         tui->update_ecc_pup3_mode = 1;
278         tui->ecc_pup_mode_offset = TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
279
280         return MV_OK;
281 }
282 #else /*CONFIG_ARMADA_38X*/
283 u32 sys_env_get_topology_update_info(
284         struct topology_update_info *tui)
285 {
286         u8 config_val;
287         u8 ecc_mode[A38X_MV_MAX_MARVELL_BOARD_ID -
288                     A38X_MARVELL_BOARD_ID_BASE][5] = TOPOLOGY_UPDATE;
289         u8 board_id = mv_board_id_get();
290         int ret;
291
292         board_id = mv_board_id_index_get(board_id);
293         ret = i2c_read(EEPROM_I2C_ADDR, 0, 2, &config_val, 1);
294         if (ret) {
295                 DEBUG_INIT_S("sys_env_get_topology_update_info: TWSI Read failed\n");
296                 return 0;
297         }
298
299         /* Set 16/32 bit configuration */
300         if ((0 == (config_val & DDR_SATR_CONFIG_MASK_WIDTH)) ||
301             (ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT] == 0)) {
302                 /* 16bit by SatR of 32bit mode not supported for the board */
303                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT] != 0)) {
304                         tui->update_width = 1;
305                         tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
306                 }
307         } else {
308                 /* 32bit */
309                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT] != 0)) {
310                         tui->update_width = 1;
311                         tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
312                 }
313         }
314
315         /* Set ECC/no ECC bit configuration */
316         if (0 == (config_val & DDR_SATR_CONFIG_MASK_ECC)) {
317                 /* NO ECC */
318                 tui->update_ecc = 1;
319                 tui->ecc = TOPOLOGY_UPDATE_ECC_OFF;
320         } else {
321                 /* ECC */
322                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0) ||
323                     (ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] != 0) ||
324                     (ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC_PUP3] != 0)) {
325                         tui->update_ecc = 1;
326                         tui->ecc = TOPOLOGY_UPDATE_ECC_ON;
327                 }
328         }
329
330         /* Set ECC pup bit configuration */
331         if (0 == (config_val & DDR_SATR_CONFIG_MASK_ECC_PUP)) {
332                 /* PUP3 */
333                 /*
334                  * Check if PUP3 configuration allowed, if not -
335                  * force Pup4 with warning message
336                  */
337                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC_PUP3] != 0)) {
338                         if (tui->width == TOPOLOGY_UPDATE_WIDTH_16BIT) {
339                                 tui->update_ecc_pup3_mode = 1;
340                                 tui->ecc_pup_mode_offset =
341                                         TOPOLOGY_UPDATE_ECC_OFFSET_PUP3;
342                         } else {
343                                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0)) {
344                                         printf("DDR Topology Update: ECC PUP3 not valid for 32bit mode, force ECC in PUP4\n");
345                                         tui->update_ecc_pup3_mode = 1;
346                                         tui->ecc_pup_mode_offset =
347                                                 TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
348                                 }
349                         }
350                 } else {
351                         if (ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] !=
352                             0) {
353                                 printf("DDR Topology Update: ECC on PUP3 not supported, force ECC on PUP4\n");
354                                 tui->update_ecc_pup3_mode = 1;
355                                 tui->ecc_pup_mode_offset =
356                                         TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
357                         }
358                 }
359         } else {
360                 /* PUP4 */
361                 if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0) ||
362                     (ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] != 0)) {
363                         tui->update_ecc_pup3_mode = 1;
364                         tui->ecc_pup_mode_offset =
365                                 TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
366                 }
367         }
368
369         /*
370          * Check for forbidden ECC mode,
371          * if by default width and pup selection set 32bit ECC mode and this
372          * mode not supported for the board - config 16bit with ECC on PUP3
373          */
374         if ((tui->ecc == TOPOLOGY_UPDATE_ECC_ON) &&
375             (tui->width == TOPOLOGY_UPDATE_WIDTH_32BIT)) {
376                 if (ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] == 0) {
377                         printf("DDR Topology Update: 32bit mode with ECC not allowed on this board, forced  16bit with ECC on PUP3\n");
378                         tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
379                         tui->update_ecc_pup3_mode = 1;
380                         tui->ecc_pup_mode_offset =
381                                 TOPOLOGY_UPDATE_ECC_OFFSET_PUP3;
382                 }
383         }
384
385         return MV_OK;
386 }
387 #endif /* CONFIG_ARMADA_38X */
388 #endif /* MV_DDR_TOPOLOGY_UPDATE_FROM_TWSI */