]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
6b0071c1 PST |
2 | /* |
3 | * Copyright 2017 General Electric Company | |
4 | * | |
5 | * Based on board/freescale/mx53loco/mx53loco.c: | |
6 | * | |
7 | * Copyright (C) 2011 Freescale Semiconductor, Inc. | |
8 | * Jason Liu <[email protected]> | |
6b0071c1 PST |
9 | */ |
10 | ||
11 | #include <common.h> | |
12 | #include <asm/io.h> | |
13 | #include <asm/arch/imx-regs.h> | |
14 | #include <asm/arch/sys_proto.h> | |
15 | #include <asm/arch/crm_regs.h> | |
16 | #include <asm/arch/clock.h> | |
17 | #include <asm/arch/iomux-mx53.h> | |
18 | #include <asm/arch/clock.h> | |
19 | #include <linux/errno.h> | |
61c4c2bf | 20 | #include <linux/libfdt.h> |
6b0071c1 PST |
21 | #include <asm/mach-imx/mxc_i2c.h> |
22 | #include <asm/mach-imx/mx5_video.h> | |
9925f1db | 23 | #include <environment.h> |
6b0071c1 PST |
24 | #include <netdev.h> |
25 | #include <i2c.h> | |
26 | #include <mmc.h> | |
27 | #include <fsl_esdhc.h> | |
28 | #include <asm/gpio.h> | |
29 | #include <power/pmic.h> | |
30 | #include <dialog_pmic.h> | |
31 | #include <fsl_pmic.h> | |
32 | #include <linux/fb.h> | |
33 | #include <ipu_pixfmt.h> | |
61c4c2bf | 34 | #include <version.h> |
6b0071c1 PST |
35 | #include <watchdog.h> |
36 | #include "ppd_gpio.h" | |
37 | #include <stdlib.h> | |
647155bc | 38 | #include "../../ge/common/ge_common.h" |
6b0071c1 | 39 | #include "../../ge/common/vpd_reader.h" |
6b0071c1 PST |
40 | |
41 | #define MX53PPD_LCD_POWER IMX_GPIO_NR(3, 24) | |
42 | ||
43 | DECLARE_GLOBAL_DATA_PTR; | |
44 | ||
6b0071c1 PST |
45 | static u32 mx53_dram_size[2]; |
46 | ||
47 | phys_size_t get_effective_memsize(void) | |
48 | { | |
49 | /* | |
50 | * WARNING: We must override get_effective_memsize() function here | |
51 | * to report only the size of the first DRAM bank. This is to make | |
52 | * U-Boot relocator place U-Boot into valid memory, that is, at the | |
53 | * end of the first DRAM bank. If we did not override this function | |
54 | * like so, U-Boot would be placed at the address of the first DRAM | |
55 | * bank + total DRAM size - sizeof(uboot), which in the setup where | |
56 | * each DRAM bank contains 512MiB of DRAM would result in placing | |
57 | * U-Boot into invalid memory area close to the end of the first | |
58 | * DRAM bank. | |
59 | */ | |
60 | return mx53_dram_size[0]; | |
61 | } | |
62 | ||
63 | int dram_init(void) | |
64 | { | |
65 | mx53_dram_size[0] = get_ram_size((void *)PHYS_SDRAM_1, 1 << 30); | |
66 | mx53_dram_size[1] = get_ram_size((void *)PHYS_SDRAM_2, 1 << 30); | |
67 | ||
68 | gd->ram_size = mx53_dram_size[0] + mx53_dram_size[1]; | |
69 | ||
70 | return 0; | |
71 | } | |
72 | ||
73 | int dram_init_banksize(void) | |
74 | { | |
75 | gd->bd->bi_dram[0].start = PHYS_SDRAM_1; | |
76 | gd->bd->bi_dram[0].size = mx53_dram_size[0]; | |
77 | ||
78 | gd->bd->bi_dram[1].start = PHYS_SDRAM_2; | |
79 | gd->bd->bi_dram[1].size = mx53_dram_size[1]; | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | u32 get_board_rev(void) | |
85 | { | |
86 | return get_cpu_rev() & ~(0xF << 8); | |
87 | } | |
88 | ||
89 | #define UART_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_DSE_HIGH | \ | |
90 | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE) | |
91 | ||
92 | #ifdef CONFIG_USB_EHCI_MX5 | |
93 | int board_ehci_hcd_init(int port) | |
94 | { | |
95 | /* request VBUS power enable pin, GPIO7_8 */ | |
96 | imx_iomux_v3_setup_pad(MX53_PAD_PATA_DA_2__GPIO7_8); | |
97 | gpio_direction_output(IMX_GPIO_NR(7, 8), 1); | |
98 | return 0; | |
99 | } | |
100 | #endif | |
101 | ||
102 | static void setup_iomux_fec(void) | |
103 | { | |
104 | static const iomux_v3_cfg_t fec_pads[] = { | |
105 | NEW_PAD_CTRL(MX53_PAD_FEC_MDIO__FEC_MDIO, PAD_CTL_HYS | | |
106 | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_22K_UP | | |
107 | PAD_CTL_ODE), | |
108 | NEW_PAD_CTRL(MX53_PAD_FEC_MDC__FEC_MDC, PAD_CTL_DSE_HIGH), | |
109 | NEW_PAD_CTRL(MX53_PAD_FEC_RXD1__FEC_RDATA_1, | |
110 | PAD_CTL_HYS | PAD_CTL_PKE), | |
111 | NEW_PAD_CTRL(MX53_PAD_FEC_RXD0__FEC_RDATA_0, | |
112 | PAD_CTL_HYS | PAD_CTL_PKE), | |
113 | NEW_PAD_CTRL(MX53_PAD_FEC_TXD1__FEC_TDATA_1, PAD_CTL_DSE_HIGH), | |
114 | NEW_PAD_CTRL(MX53_PAD_FEC_TXD0__FEC_TDATA_0, PAD_CTL_DSE_HIGH), | |
115 | NEW_PAD_CTRL(MX53_PAD_FEC_TX_EN__FEC_TX_EN, PAD_CTL_DSE_HIGH), | |
116 | NEW_PAD_CTRL(MX53_PAD_FEC_REF_CLK__FEC_TX_CLK, | |
117 | PAD_CTL_HYS | PAD_CTL_PKE), | |
118 | NEW_PAD_CTRL(MX53_PAD_FEC_RX_ER__FEC_RX_ER, | |
119 | PAD_CTL_HYS | PAD_CTL_PKE), | |
120 | NEW_PAD_CTRL(MX53_PAD_FEC_CRS_DV__FEC_RX_DV, | |
121 | PAD_CTL_HYS | PAD_CTL_PKE), | |
122 | }; | |
123 | ||
124 | imx_iomux_v3_setup_multiple_pads(fec_pads, ARRAY_SIZE(fec_pads)); | |
125 | } | |
126 | ||
6b0071c1 PST |
127 | #define I2C_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \ |
128 | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE) | |
129 | ||
130 | static void setup_iomux_i2c(void) | |
131 | { | |
132 | static const iomux_v3_cfg_t i2c1_pads[] = { | |
133 | NEW_PAD_CTRL(MX53_PAD_CSI0_DAT8__I2C1_SDA, I2C_PAD_CTRL), | |
134 | NEW_PAD_CTRL(MX53_PAD_CSI0_DAT9__I2C1_SCL, I2C_PAD_CTRL), | |
135 | }; | |
136 | ||
137 | imx_iomux_v3_setup_multiple_pads(i2c1_pads, ARRAY_SIZE(i2c1_pads)); | |
138 | } | |
139 | ||
140 | #define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL) | |
141 | ||
142 | static struct i2c_pads_info i2c_pad_info1 = { | |
143 | .scl = { | |
144 | .i2c_mode = MX53_PAD_EIM_D21__I2C1_SCL | I2C_PAD, | |
145 | .gpio_mode = MX53_PAD_EIM_D28__GPIO3_28 | I2C_PAD, | |
146 | .gp = IMX_GPIO_NR(3, 28) | |
147 | }, | |
148 | .sda = { | |
149 | .i2c_mode = MX53_PAD_EIM_D28__I2C1_SDA | I2C_PAD, | |
150 | .gpio_mode = MX53_PAD_EIM_D21__GPIO3_21 | I2C_PAD, | |
151 | .gp = IMX_GPIO_NR(3, 21) | |
152 | } | |
153 | }; | |
154 | ||
155 | static int clock_1GHz(void) | |
156 | { | |
157 | int ret; | |
158 | u32 ref_clk = MXC_HCLK; | |
159 | /* | |
160 | * After increasing voltage to 1.25V, we can switch | |
161 | * CPU clock to 1GHz and DDR to 400MHz safely | |
162 | */ | |
163 | ret = mxc_set_clock(ref_clk, 1000, MXC_ARM_CLK); | |
164 | if (ret) { | |
165 | printf("CPU: Switch CPU clock to 1GHZ failed\n"); | |
166 | return -1; | |
167 | } | |
168 | ||
169 | ret = mxc_set_clock(ref_clk, 400, MXC_PERIPH_CLK); | |
170 | ret |= mxc_set_clock(ref_clk, 400, MXC_DDR_CLK); | |
171 | if (ret) { | |
172 | printf("CPU: Switch DDR clock to 400MHz failed\n"); | |
173 | return -1; | |
174 | } | |
175 | ||
176 | return 0; | |
177 | } | |
178 | ||
179 | void ppd_gpio_init(void) | |
180 | { | |
181 | int i; | |
182 | ||
183 | imx_iomux_v3_setup_multiple_pads(ppd_pads, ARRAY_SIZE(ppd_pads)); | |
184 | for (i = 0; i < ARRAY_SIZE(ppd_gpios); ++i) | |
185 | gpio_direction_output(ppd_gpios[i].gpio, ppd_gpios[i].value); | |
186 | } | |
187 | ||
188 | int board_early_init_f(void) | |
189 | { | |
190 | setup_iomux_fec(); | |
191 | setup_iomux_lcd(); | |
192 | ppd_gpio_init(); | |
193 | ||
194 | return 0; | |
195 | } | |
196 | ||
197 | /* | |
198 | * Do not overwrite the console | |
199 | * Use always serial for U-Boot console | |
200 | */ | |
201 | int overwrite_console(void) | |
202 | { | |
203 | return 1; | |
204 | } | |
205 | ||
206 | #define VPD_TYPE_INVALID 0x00 | |
207 | #define VPD_BLOCK_NETWORK 0x20 | |
208 | #define VPD_BLOCK_HWID 0x44 | |
209 | #define VPD_PRODUCT_PPD 4 | |
210 | #define VPD_HAS_MAC1 0x1 | |
211 | #define VPD_MAC_ADDRESS_LENGTH 6 | |
212 | ||
213 | struct vpd_cache { | |
214 | u8 product_id; | |
215 | u8 has; | |
216 | unsigned char mac1[VPD_MAC_ADDRESS_LENGTH]; | |
217 | }; | |
218 | ||
219 | /* | |
220 | * Extracts MAC and product information from the VPD. | |
221 | */ | |
f026c1d9 PF |
222 | static int vpd_callback(struct vpd_cache *userdata, u8 id, u8 version, |
223 | u8 type, size_t size, u8 const *data) | |
6b0071c1 | 224 | { |
f026c1d9 | 225 | struct vpd_cache *vpd = userdata; |
6b0071c1 PST |
226 | |
227 | if (id == VPD_BLOCK_HWID && version == 1 && type != VPD_TYPE_INVALID && | |
228 | size >= 1) { | |
229 | vpd->product_id = data[0]; | |
230 | ||
231 | } else if (id == VPD_BLOCK_NETWORK && version == 1 && | |
232 | type != VPD_TYPE_INVALID) { | |
233 | if (size >= 6) { | |
234 | vpd->has |= VPD_HAS_MAC1; | |
235 | memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH); | |
236 | } | |
237 | } | |
238 | ||
239 | return 0; | |
240 | } | |
241 | ||
242 | static void process_vpd(struct vpd_cache *vpd) | |
243 | { | |
244 | int fec_index = -1; | |
245 | ||
246 | if (vpd->product_id == VPD_PRODUCT_PPD) | |
247 | fec_index = 0; | |
248 | ||
249 | if (fec_index >= 0 && (vpd->has & VPD_HAS_MAC1)) | |
250 | eth_env_set_enetaddr("ethaddr", vpd->mac1); | |
251 | } | |
252 | ||
6b0071c1 PST |
253 | int board_init(void) |
254 | { | |
255 | gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; | |
256 | ||
257 | mxc_set_sata_internal_clock(); | |
258 | setup_iomux_i2c(); | |
259 | ||
260 | setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); | |
261 | ||
262 | return 0; | |
263 | } | |
264 | ||
265 | int misc_init_r(void) | |
266 | { | |
267 | const char *cause; | |
268 | ||
269 | /* We care about WDOG only, treating everything else as | |
270 | * a power-on-reset. | |
271 | */ | |
272 | if (get_imx_reset_cause() & 0x0010) | |
273 | cause = "WDOG"; | |
274 | else | |
275 | cause = "POR"; | |
276 | ||
277 | env_set("bootcause", cause); | |
278 | ||
279 | return 0; | |
280 | } | |
281 | ||
282 | int board_late_init(void) | |
283 | { | |
284 | int res; | |
4dcbccf7 | 285 | struct vpd_cache vpd; |
6b0071c1 | 286 | |
4dcbccf7 DZ |
287 | memset(&vpd, 0, sizeof(vpd)); |
288 | res = read_vpd(&vpd, vpd_callback); | |
289 | if (!res) | |
290 | process_vpd(&vpd); | |
291 | else | |
292 | printf("Can't read VPD"); | |
6b0071c1 PST |
293 | |
294 | res = clock_1GHz(); | |
295 | if (res != 0) | |
296 | return res; | |
297 | ||
298 | print_cpuinfo(); | |
299 | hw_watchdog_init(); | |
300 | ||
301 | check_time(); | |
302 | ||
303 | return 0; | |
304 | } | |
305 | ||
306 | int checkboard(void) | |
307 | { | |
308 | puts("Board: GE PPD\n"); | |
309 | ||
310 | return 0; | |
311 | } | |
61c4c2bf IR |
312 | |
313 | #ifdef CONFIG_OF_BOARD_SETUP | |
314 | int ft_board_setup(void *blob, bd_t *bd) | |
315 | { | |
316 | fdt_setprop(blob, 0, "ge,boot-ver", version_string, | |
317 | strlen(version_string) + 1); | |
318 | return 0; | |
319 | } | |
320 | #endif |