blob: 4e6846a50a921c3c826630ffc4e8ee17efab51a7 [file] [log] [blame]
Lokesh Vutlafaa680f2013-07-30 11:36:27 +05301/*
2 * board.c
3 *
4 * Board functions for TI AM43XX based boards
5 *
6 * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <common.h>
Sekhar Nori2ab3c492013-12-10 15:02:15 +053012#include <i2c.h>
13#include <asm/errno.h>
Lokesh Vutlafaa680f2013-07-30 11:36:27 +053014#include <spl.h>
Lokesh Vutla85b59362013-07-30 11:36:29 +053015#include <asm/arch/clock.h>
Lokesh Vutlafaa680f2013-07-30 11:36:27 +053016#include <asm/arch/sys_proto.h>
17#include <asm/arch/mux.h>
Lokesh Vutlaa82d4e12013-12-10 15:02:22 +053018#include <asm/arch/ddr_defs.h>
Lokesh Vutladd0037a2013-12-10 15:02:23 +053019#include <asm/arch/gpio.h>
Lokesh Vutlaa82d4e12013-12-10 15:02:22 +053020#include <asm/emif.h>
Lokesh Vutlafaa680f2013-07-30 11:36:27 +053021#include "board.h"
22
23DECLARE_GLOBAL_DATA_PTR;
24
Sekhar Nori2ab3c492013-12-10 15:02:15 +053025/*
26 * Read header information from EEPROM into global structure.
27 */
28static int read_eeprom(struct am43xx_board_id *header)
29{
30 /* Check if baseboard eeprom is available */
31 if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) {
32 printf("Could not probe the EEPROM at 0x%x\n",
33 CONFIG_SYS_I2C_EEPROM_ADDR);
34 return -ENODEV;
35 }
36
37 /* read the eeprom using i2c */
38 if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)header,
39 sizeof(struct am43xx_board_id))) {
40 printf("Could not read the EEPROM\n");
41 return -EIO;
42 }
43
44 if (header->magic != 0xEE3355AA) {
45 /*
46 * read the eeprom using i2c again,
47 * but use only a 1 byte address
48 */
49 if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1, (uchar *)header,
50 sizeof(struct am43xx_board_id))) {
51 printf("Could not read the EEPROM at 0x%x\n",
52 CONFIG_SYS_I2C_EEPROM_ADDR);
53 return -EIO;
54 }
55
56 if (header->magic != 0xEE3355AA) {
57 printf("Incorrect magic number (0x%x) in EEPROM\n",
58 header->magic);
59 return -EINVAL;
60 }
61 }
62
63 strncpy(am43xx_board_name, (char *)header->name, sizeof(header->name));
64 am43xx_board_name[sizeof(header->name)] = 0;
65
66 return 0;
67}
68
Lokesh Vutlafaa680f2013-07-30 11:36:27 +053069#ifdef CONFIG_SPL_BUILD
70
Lokesh Vutla42c213a2013-12-10 15:02:20 +053071#define NUM_OPPS 6
72
73const struct dpll_params dpll_mpu[NUM_CRYSTAL_FREQ][NUM_OPPS] = {
74 { /* 19.2 MHz */
75 {-1, -1, -1, -1, -1, -1, -1}, /* OPP 50 */
76 {-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
77 {-1, -1, -1, -1, -1, -1, -1}, /* OPP 100 */
78 {-1, -1, -1, -1, -1, -1, -1}, /* OPP 120 */
79 {-1, -1, -1, -1, -1, -1, -1}, /* OPP TB */
80 {-1, -1, -1, -1, -1, -1, -1} /* OPP NT */
81 },
82 { /* 24 MHz */
83 {300, 23, 1, -1, -1, -1, -1}, /* OPP 50 */
84 {-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
85 {600, 23, 1, -1, -1, -1, -1}, /* OPP 100 */
86 {720, 23, 1, -1, -1, -1, -1}, /* OPP 120 */
87 {800, 23, 1, -1, -1, -1, -1}, /* OPP TB */
88 {1000, 23, 1, -1, -1, -1, -1} /* OPP NT */
89 },
90 { /* 25 MHz */
91 {300, 24, 1, -1, -1, -1, -1}, /* OPP 50 */
92 {-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
93 {600, 24, 1, -1, -1, -1, -1}, /* OPP 100 */
94 {720, 24, 1, -1, -1, -1, -1}, /* OPP 120 */
95 {800, 24, 1, -1, -1, -1, -1}, /* OPP TB */
96 {1000, 24, 1, -1, -1, -1, -1} /* OPP NT */
97 },
98 { /* 26 MHz */
99 {300, 25, 1, -1, -1, -1, -1}, /* OPP 50 */
100 {-1, -1, -1, -1, -1, -1, -1}, /* OPP RESERVED */
101 {600, 25, 1, -1, -1, -1, -1}, /* OPP 100 */
102 {720, 25, 1, -1, -1, -1, -1}, /* OPP 120 */
103 {800, 25, 1, -1, -1, -1, -1}, /* OPP TB */
104 {1000, 25, 1, -1, -1, -1, -1} /* OPP NT */
105 },
106};
107
108const struct dpll_params dpll_core[NUM_CRYSTAL_FREQ] = {
109 {-1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
110 {1000, 23, -1, -1, 10, 8, 4}, /* 24 MHz */
111 {1000, 24, -1, -1, 10, 8, 4}, /* 25 MHz */
112 {1000, 25, -1, -1, 10, 8, 4} /* 26 MHz */
113};
114
115const struct dpll_params dpll_per[NUM_CRYSTAL_FREQ] = {
116 {-1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
117 {960, 23, 5, -1, -1, -1, -1}, /* 24 MHz */
118 {960, 24, 5, -1, -1, -1, -1}, /* 25 MHz */
119 {960, 25, 5, -1, -1, -1, -1} /* 26 MHz */
120};
121
122const struct dpll_params epos_evm_dpll_ddr = {
123 266, 24, 1, -1, 1, -1, -1};
124
125const struct dpll_params gp_evm_dpll_ddr = {
126 400, 23, 1, -1, 1, -1, -1};
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530127
Lokesh Vutlaa82d4e12013-12-10 15:02:22 +0530128const struct ctrl_ioregs ioregs_lpddr2 = {
129 .cm0ioctl = LPDDR2_ADDRCTRL_IOCTRL_VALUE,
130 .cm1ioctl = LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE,
131 .cm2ioctl = LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE,
132 .dt0ioctl = LPDDR2_DATA0_IOCTRL_VALUE,
133 .dt1ioctl = LPDDR2_DATA0_IOCTRL_VALUE,
134 .dt2ioctrl = LPDDR2_DATA0_IOCTRL_VALUE,
135 .dt3ioctrl = LPDDR2_DATA0_IOCTRL_VALUE,
136 .emif_sdram_config_ext = 0x1,
137};
138
139const struct emif_regs emif_regs_lpddr2 = {
140 .sdram_config = 0x808012BA,
141 .ref_ctrl = 0x0000040D,
142 .sdram_tim1 = 0xEA86B411,
143 .sdram_tim2 = 0x103A094A,
144 .sdram_tim3 = 0x0F6BA37F,
145 .read_idle_ctrl = 0x00050000,
146 .zq_config = 0x50074BE4,
147 .temp_alert_config = 0x0,
148 .emif_rd_wr_lvl_rmp_win = 0x0,
149 .emif_rd_wr_lvl_rmp_ctl = 0x0,
150 .emif_rd_wr_lvl_ctl = 0x0,
151 .emif_ddr_phy_ctlr_1 = 0x0E084006,
152 .emif_rd_wr_exec_thresh = 0x00000405,
153 .emif_ddr_ext_phy_ctrl_1 = 0x04010040,
154 .emif_ddr_ext_phy_ctrl_2 = 0x00500050,
155 .emif_ddr_ext_phy_ctrl_3 = 0x00500050,
156 .emif_ddr_ext_phy_ctrl_4 = 0x00500050,
157 .emif_ddr_ext_phy_ctrl_5 = 0x00500050
158};
159
160const u32 ext_phy_ctrl_const_base_lpddr2[] = {
161 0x00500050,
162 0x00350035,
163 0x00350035,
164 0x00350035,
165 0x00350035,
166 0x00350035,
167 0x00000000,
168 0x00000000,
169 0x00000000,
170 0x00000000,
171 0x00000000,
172 0x00000000,
173 0x00000000,
174 0x00000000,
175 0x00000000,
176 0x00000000,
177 0x00000000,
178 0x00000000,
179 0x40001000,
180 0x08102040
181};
182
Lokesh Vutladd0037a2013-12-10 15:02:23 +0530183const struct ctrl_ioregs ioregs_ddr3 = {
184 .cm0ioctl = DDR3_ADDRCTRL_IOCTRL_VALUE,
185 .cm1ioctl = DDR3_ADDRCTRL_WD0_IOCTRL_VALUE,
186 .cm2ioctl = DDR3_ADDRCTRL_WD1_IOCTRL_VALUE,
187 .dt0ioctl = DDR3_DATA0_IOCTRL_VALUE,
188 .dt1ioctl = DDR3_DATA0_IOCTRL_VALUE,
189 .dt2ioctrl = DDR3_DATA0_IOCTRL_VALUE,
190 .dt3ioctrl = DDR3_DATA0_IOCTRL_VALUE,
Lokesh Vutla9fc00292013-12-19 10:00:28 +0530191 .emif_sdram_config_ext = 0x0143,
Lokesh Vutladd0037a2013-12-10 15:02:23 +0530192};
193
194const struct emif_regs ddr3_emif_regs_400Mhz = {
195 .sdram_config = 0x638413B2,
196 .ref_ctrl = 0x00000C30,
197 .sdram_tim1 = 0xEAAAD4DB,
198 .sdram_tim2 = 0x266B7FDA,
199 .sdram_tim3 = 0x107F8678,
200 .read_idle_ctrl = 0x00050000,
201 .zq_config = 0x50074BE4,
202 .temp_alert_config = 0x0,
203 .emif_ddr_phy_ctlr_1 = 0x0E084008,
204 .emif_ddr_ext_phy_ctrl_1 = 0x08020080,
205 .emif_ddr_ext_phy_ctrl_2 = 0x00400040,
206 .emif_ddr_ext_phy_ctrl_3 = 0x00400040,
207 .emif_ddr_ext_phy_ctrl_4 = 0x00400040,
208 .emif_ddr_ext_phy_ctrl_5 = 0x00400040,
209 .emif_rd_wr_lvl_rmp_win = 0x0,
210 .emif_rd_wr_lvl_rmp_ctl = 0x0,
211 .emif_rd_wr_lvl_ctl = 0x0,
212 .emif_rd_wr_exec_thresh = 0x00000405
213};
214
215const u32 ext_phy_ctrl_const_base_ddr3[] = {
216 0x00400040,
217 0x00350035,
218 0x00350035,
219 0x00350035,
220 0x00350035,
221 0x00350035,
222 0x00000000,
223 0x00000000,
224 0x00000000,
225 0x00000000,
226 0x00000000,
227 0x00340034,
228 0x00340034,
229 0x00340034,
230 0x00340034,
231 0x00340034,
232 0x0,
233 0x0,
234 0x40000000,
235 0x08102040
236};
237
Lokesh Vutlaa82d4e12013-12-10 15:02:22 +0530238void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
239{
Lokesh Vutladd0037a2013-12-10 15:02:23 +0530240 if (board_is_eposevm()) {
241 *regs = ext_phy_ctrl_const_base_lpddr2;
242 *size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2);
243 } else if (board_is_gpevm()) {
244 *regs = ext_phy_ctrl_const_base_ddr3;
245 *size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3);
246 }
Lokesh Vutlaa82d4e12013-12-10 15:02:22 +0530247
248 return;
249}
250
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530251const struct dpll_params *get_dpll_ddr_params(void)
252{
Lokesh Vutla42c213a2013-12-10 15:02:20 +0530253 struct am43xx_board_id header;
254
255 enable_i2c0_pin_mux();
256 i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
257 if (read_eeprom(&header) < 0)
258 puts("Could not get board ID.\n");
259
260 if (board_is_eposevm())
261 return &epos_evm_dpll_ddr;
262 else if (board_is_gpevm())
263 return &gp_evm_dpll_ddr;
264
265 puts(" Board not supported\n");
266 return NULL;
267}
268
269/*
270 * get_sys_clk_index : returns the index of the sys_clk read from
271 * ctrl status register. This value is either
272 * read from efuse or sysboot pins.
273 */
274static u32 get_sys_clk_index(void)
275{
276 struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
277 u32 ind = readl(&ctrl->statusreg), src;
278
279 src = (ind & CTRL_CRYSTAL_FREQ_SRC_MASK) >> CTRL_CRYSTAL_FREQ_SRC_SHIFT;
280 if (src == CTRL_CRYSTAL_FREQ_SRC_EFUSE) /* Value read from EFUSE */
281 return ((ind & CTRL_CRYSTAL_FREQ_SELECTION_MASK) >>
282 CTRL_CRYSTAL_FREQ_SELECTION_SHIFT);
283 else /* Value read from SYS BOOT pins */
284 return ((ind & CTRL_SYSBOOT_15_14_MASK) >>
285 CTRL_SYSBOOT_15_14_SHIFT);
286}
287
288/*
289 * get_opp_offset:
290 * Returns the index for safest OPP of the device to boot.
291 * max_off: Index of the MAX OPP in DEV ATTRIBUTE register.
292 * min_off: Index of the MIN OPP in DEV ATTRIBUTE register.
293 * This data is read from dev_attribute register which is e-fused.
294 * A'1' in bit indicates OPP disabled and not available, a '0' indicates
295 * OPP available. Lowest OPP starts with min_off. So returning the
296 * bit with rightmost '0'.
297 */
298static int get_opp_offset(int max_off, int min_off)
299{
300 struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
301 int opp = readl(&ctrl->dev_attr), offset, i;
302
303 for (i = max_off; i >= min_off; i--) {
304 offset = opp & (1 << i);
305 if (!offset)
306 return i;
307 }
308
309 return min_off;
310}
311
312const struct dpll_params *get_dpll_mpu_params(void)
313{
314 int opp = get_opp_offset(DEV_ATTR_MAX_OFFSET, DEV_ATTR_MIN_OFFSET);
315 u32 ind = get_sys_clk_index();
316
317 return &dpll_mpu[ind][opp];
318}
319
320const struct dpll_params *get_dpll_core_params(void)
321{
322 int ind = get_sys_clk_index();
323
324 return &dpll_core[ind];
325}
326
327const struct dpll_params *get_dpll_per_params(void)
328{
329 int ind = get_sys_clk_index();
330
331 return &dpll_per[ind];
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530332}
333
334void set_uart_mux_conf(void)
335{
336 enable_uart0_pin_mux();
337}
338
339void set_mux_conf_regs(void)
340{
341 enable_board_pin_mux();
342}
343
Lokesh Vutladd0037a2013-12-10 15:02:23 +0530344static void enable_vtt_regulator(void)
345{
346 u32 temp;
347
348 /* enable module */
349 writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
350
351 /* enable output for GPIO0_22 */
352 writel(GPIO_SETDATAOUT(GPIO_22),
353 AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
354 temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
355 temp = temp & ~(GPIO_OE_ENABLE(GPIO_22));
356 writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
357}
358
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530359void sdram_init(void)
360{
Lokesh Vutladd0037a2013-12-10 15:02:23 +0530361 /*
362 * EPOS EVM has 1GB LPDDR2 connected to EMIF.
363 * GP EMV has 1GB DDR3 connected to EMIF
364 * along with VTT regulator.
365 */
366 if (board_is_eposevm()) {
367 config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0);
368 } else if (board_is_gpevm()) {
369 enable_vtt_regulator();
370 config_ddr(0, &ioregs_ddr3, NULL, NULL,
371 &ddr3_emif_regs_400Mhz, 0);
372 }
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530373}
374#endif
375
376int board_init(void)
377{
Lokesh Vutlab82e6e92013-12-10 15:02:12 +0530378 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530379
380 return 0;
381}
382
383#ifdef CONFIG_BOARD_LATE_INIT
384int board_late_init(void)
385{
Sekhar Nori00dc07d2013-12-10 15:02:16 +0530386#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
387 char safe_string[HDR_NAME_LEN + 1];
388 struct am43xx_board_id header;
389
390 if (read_eeprom(&header) < 0)
391 puts("Could not get board ID.\n");
392
393 /* Now set variables based on the header. */
394 strncpy(safe_string, (char *)header.name, sizeof(header.name));
395 safe_string[sizeof(header.name)] = 0;
396 setenv("board_name", safe_string);
397
398 strncpy(safe_string, (char *)header.version, sizeof(header.version));
399 safe_string[sizeof(header.version)] = 0;
400 setenv("board_rev", safe_string);
401#endif
Lokesh Vutlafaa680f2013-07-30 11:36:27 +0530402 return 0;
403}
404#endif