xref: /openbmc/u-boot/board/ti/am43xx/board.c (revision 965de8b9)
1 /*
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>
12 #include <i2c.h>
13 #include <asm/errno.h>
14 #include <spl.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/sys_proto.h>
17 #include <asm/arch/mux.h>
18 #include "board.h"
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 /*
23  * Read header information from EEPROM into global structure.
24  */
25 static int read_eeprom(struct am43xx_board_id *header)
26 {
27 	/* Check if baseboard eeprom is available */
28 	if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) {
29 		printf("Could not probe the EEPROM at 0x%x\n",
30 		       CONFIG_SYS_I2C_EEPROM_ADDR);
31 		return -ENODEV;
32 	}
33 
34 	/* read the eeprom using i2c */
35 	if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)header,
36 		     sizeof(struct am43xx_board_id))) {
37 		printf("Could not read the EEPROM\n");
38 		return -EIO;
39 	}
40 
41 	if (header->magic != 0xEE3355AA) {
42 		/*
43 		 * read the eeprom using i2c again,
44 		 * but use only a 1 byte address
45 		 */
46 		if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1, (uchar *)header,
47 			     sizeof(struct am43xx_board_id))) {
48 			printf("Could not read the EEPROM at 0x%x\n",
49 			       CONFIG_SYS_I2C_EEPROM_ADDR);
50 			return -EIO;
51 		}
52 
53 		if (header->magic != 0xEE3355AA) {
54 			printf("Incorrect magic number (0x%x) in EEPROM\n",
55 			       header->magic);
56 			return -EINVAL;
57 		}
58 	}
59 
60 	strncpy(am43xx_board_name, (char *)header->name, sizeof(header->name));
61 	am43xx_board_name[sizeof(header->name)] = 0;
62 
63 	return 0;
64 }
65 
66 #ifdef CONFIG_SPL_BUILD
67 
68 #define NUM_OPPS	6
69 
70 const struct dpll_params dpll_mpu[NUM_CRYSTAL_FREQ][NUM_OPPS] = {
71 	{	/* 19.2 MHz */
72 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 50 */
73 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/
74 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 100 */
75 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 120 */
76 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP TB */
77 		{-1, -1, -1, -1, -1, -1, -1}	/* OPP NT */
78 	},
79 	{	/* 24 MHz */
80 		{300, 23, 1, -1, -1, -1, -1},	/* OPP 50 */
81 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/
82 		{600, 23, 1, -1, -1, -1, -1},	/* OPP 100 */
83 		{720, 23, 1, -1, -1, -1, -1},	/* OPP 120 */
84 		{800, 23, 1, -1, -1, -1, -1},	/* OPP TB */
85 		{1000, 23, 1, -1, -1, -1, -1}	/* OPP NT */
86 	},
87 	{	/* 25 MHz */
88 		{300, 24, 1, -1, -1, -1, -1},	/* OPP 50 */
89 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/
90 		{600, 24, 1, -1, -1, -1, -1},	/* OPP 100 */
91 		{720, 24, 1, -1, -1, -1, -1},	/* OPP 120 */
92 		{800, 24, 1, -1, -1, -1, -1},	/* OPP TB */
93 		{1000, 24, 1, -1, -1, -1, -1}	/* OPP NT */
94 	},
95 	{	/* 26 MHz */
96 		{300, 25, 1, -1, -1, -1, -1},	/* OPP 50 */
97 		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/
98 		{600, 25, 1, -1, -1, -1, -1},	/* OPP 100 */
99 		{720, 25, 1, -1, -1, -1, -1},	/* OPP 120 */
100 		{800, 25, 1, -1, -1, -1, -1},	/* OPP TB */
101 		{1000, 25, 1, -1, -1, -1, -1}	/* OPP NT */
102 	},
103 };
104 
105 const struct dpll_params dpll_core[NUM_CRYSTAL_FREQ] = {
106 		{-1, -1, -1, -1, -1, -1, -1},	/* 19.2 MHz */
107 		{1000, 23, -1, -1, 10, 8, 4},	/* 24 MHz */
108 		{1000, 24, -1, -1, 10, 8, 4},	/* 25 MHz */
109 		{1000, 25, -1, -1, 10, 8, 4}	/* 26 MHz */
110 };
111 
112 const struct dpll_params dpll_per[NUM_CRYSTAL_FREQ] = {
113 		{-1, -1, -1, -1, -1, -1, -1},	/* 19.2 MHz */
114 		{960, 23, 5, -1, -1, -1, -1},	/* 24 MHz */
115 		{960, 24, 5, -1, -1, -1, -1},	/* 25 MHz */
116 		{960, 25, 5, -1, -1, -1, -1}	/* 26 MHz */
117 };
118 
119 const struct dpll_params epos_evm_dpll_ddr = {
120 		266, 24, 1, -1, 1, -1, -1};
121 
122 const struct dpll_params gp_evm_dpll_ddr = {
123 		400, 23, 1, -1, 1, -1, -1};
124 
125 const struct dpll_params *get_dpll_ddr_params(void)
126 {
127 	struct am43xx_board_id header;
128 
129 	enable_i2c0_pin_mux();
130 	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
131 	if (read_eeprom(&header) < 0)
132 		puts("Could not get board ID.\n");
133 
134 	if (board_is_eposevm())
135 		return &epos_evm_dpll_ddr;
136 	else if (board_is_gpevm())
137 		return &gp_evm_dpll_ddr;
138 
139 	puts(" Board not supported\n");
140 	return NULL;
141 }
142 
143 /*
144  * get_sys_clk_index : returns the index of the sys_clk read from
145  *			ctrl status register. This value is either
146  *			read from efuse or sysboot pins.
147  */
148 static u32 get_sys_clk_index(void)
149 {
150 	struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
151 	u32 ind = readl(&ctrl->statusreg), src;
152 
153 	src = (ind & CTRL_CRYSTAL_FREQ_SRC_MASK) >> CTRL_CRYSTAL_FREQ_SRC_SHIFT;
154 	if (src == CTRL_CRYSTAL_FREQ_SRC_EFUSE) /* Value read from EFUSE */
155 		return ((ind & CTRL_CRYSTAL_FREQ_SELECTION_MASK) >>
156 			CTRL_CRYSTAL_FREQ_SELECTION_SHIFT);
157 	else /* Value read from SYS BOOT pins */
158 		return ((ind & CTRL_SYSBOOT_15_14_MASK) >>
159 			CTRL_SYSBOOT_15_14_SHIFT);
160 }
161 
162 /*
163  * get_opp_offset:
164  * Returns the index for safest OPP of the device to boot.
165  * max_off:	Index of the MAX OPP in DEV ATTRIBUTE register.
166  * min_off:	Index of the MIN OPP in DEV ATTRIBUTE register.
167  * This data is read from dev_attribute register which is e-fused.
168  * A'1' in bit indicates OPP disabled and not available, a '0' indicates
169  * OPP available. Lowest OPP starts with min_off. So returning the
170  * bit with rightmost '0'.
171  */
172 static int get_opp_offset(int max_off, int min_off)
173 {
174 	struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
175 	int opp = readl(&ctrl->dev_attr), offset, i;
176 
177 	for (i = max_off; i >= min_off; i--) {
178 		offset = opp & (1 << i);
179 		if (!offset)
180 			return i;
181 	}
182 
183 	return min_off;
184 }
185 
186 const struct dpll_params *get_dpll_mpu_params(void)
187 {
188 	int opp = get_opp_offset(DEV_ATTR_MAX_OFFSET, DEV_ATTR_MIN_OFFSET);
189 	u32 ind = get_sys_clk_index();
190 
191 	return &dpll_mpu[ind][opp];
192 }
193 
194 const struct dpll_params *get_dpll_core_params(void)
195 {
196 	int ind = get_sys_clk_index();
197 
198 	return &dpll_core[ind];
199 }
200 
201 const struct dpll_params *get_dpll_per_params(void)
202 {
203 	int ind = get_sys_clk_index();
204 
205 	return &dpll_per[ind];
206 }
207 
208 void set_uart_mux_conf(void)
209 {
210 	enable_uart0_pin_mux();
211 }
212 
213 void set_mux_conf_regs(void)
214 {
215 	enable_board_pin_mux();
216 }
217 
218 void sdram_init(void)
219 {
220 }
221 #endif
222 
223 int board_init(void)
224 {
225 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
226 
227 	return 0;
228 }
229 
230 #ifdef CONFIG_BOARD_LATE_INIT
231 int board_late_init(void)
232 {
233 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
234 	char safe_string[HDR_NAME_LEN + 1];
235 	struct am43xx_board_id header;
236 
237 	if (read_eeprom(&header) < 0)
238 		puts("Could not get board ID.\n");
239 
240 	/* Now set variables based on the header. */
241 	strncpy(safe_string, (char *)header.name, sizeof(header.name));
242 	safe_string[sizeof(header.name)] = 0;
243 	setenv("board_name", safe_string);
244 
245 	strncpy(safe_string, (char *)header.version, sizeof(header.version));
246 	safe_string[sizeof(header.version)] = 0;
247 	setenv("board_rev", safe_string);
248 #endif
249 	return 0;
250 }
251 #endif
252