]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
f9162b15 AB |
2 | /* |
3 | * Copyright 2015 Timesys Corporation | |
4 | * Copyright 2015 General Electric Company | |
5 | * Copyright 2012 Freescale Semiconductor, Inc. | |
f9162b15 AB |
6 | */ |
7 | ||
4d72caa5 | 8 | #include <image.h> |
5255932f | 9 | #include <init.h> |
f9162b15 AB |
10 | #include <asm/arch/clock.h> |
11 | #include <asm/arch/imx-regs.h> | |
12 | #include <asm/arch/iomux.h> | |
13 | #include <asm/arch/mx6-pins.h> | |
9fb625ce | 14 | #include <env.h> |
401d1c4f | 15 | #include <asm/global_data.h> |
c05ed00a | 16 | #include <linux/delay.h> |
1221ce45 | 17 | #include <linux/errno.h> |
61c4c2bf | 18 | #include <linux/libfdt.h> |
f9162b15 | 19 | #include <asm/gpio.h> |
552a848e SB |
20 | #include <asm/mach-imx/iomux-v3.h> |
21 | #include <asm/mach-imx/boot_mode.h> | |
22 | #include <asm/mach-imx/video.h> | |
f9162b15 | 23 | #include <mmc.h> |
e37ac717 | 24 | #include <fsl_esdhc_imx.h> |
f9162b15 | 25 | #include <miiphy.h> |
cf678b31 | 26 | #include <net.h> |
f9162b15 AB |
27 | #include <netdev.h> |
28 | #include <asm/arch/mxc_hdmi.h> | |
29 | #include <asm/arch/crm_regs.h> | |
30 | #include <asm/io.h> | |
31 | #include <asm/arch/sys_proto.h> | |
1dec7fa7 RB |
32 | #include <power/regulator.h> |
33 | #include <power/da9063_pmic.h> | |
512bda95 | 34 | #include <power/pmic.h> |
7594c51a | 35 | #include <input.h> |
54971ac6 | 36 | #include <pwm.h> |
bdfb6d70 | 37 | #include <version_string.h> |
be2808c3 | 38 | #include <stdlib.h> |
8c267398 | 39 | #include <dm/root.h> |
36e3e7de | 40 | #include "../common/ge_rtc.h" |
b418dfe1 | 41 | #include "../common/vpd_reader.h" |
2850645c | 42 | #include "../../../drivers/net/e1000.h" |
b565b18a | 43 | #include <pci.h> |
92faf43b | 44 | #include <panel.h> |
b565b18a | 45 | |
f9162b15 AB |
46 | DECLARE_GLOBAL_DATA_PTR; |
47 | ||
2d86fb31 SR |
48 | #define VPD_PRODUCT_B850 1 |
49 | #define VPD_PRODUCT_B650 2 | |
50 | #define VPD_PRODUCT_B450 3 | |
51 | ||
717bf50f SR |
52 | #define AR8033_DBG_REG_ADDR 0x1d |
53 | #define AR8033_DBG_REG_DATA 0x1e | |
54 | #define AR8033_SERDES_REG 0x5 | |
55 | ||
2d86fb31 | 56 | static int productid; /* Default to generic. */ |
5e604e2c NH |
57 | static struct vpd_cache vpd; |
58 | ||
7d0b8cfe JW |
59 | #define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ |
60 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ | |
61 | PAD_CTL_HYS) | |
62 | ||
f9162b15 AB |
63 | int dram_init(void) |
64 | { | |
c6a51bab | 65 | gd->ram_size = imx_ddr_size(); |
f9162b15 AB |
66 | |
67 | return 0; | |
68 | } | |
69 | ||
f9162b15 AB |
70 | int board_phy_config(struct phy_device *phydev) |
71 | { | |
717bf50f SR |
72 | /* |
73 | * Set reserved bits to avoid board specific voltage peak issue. The | |
74 | * value is a magic number provided directly by Qualcomm. Note, that | |
75 | * PHY driver will take control of BIT(8) in this register to control | |
76 | * TX clock delay, so we do not initialize that bit here. | |
77 | */ | |
78 | phy_write(phydev, MDIO_DEVAD_NONE, AR8033_DBG_REG_ADDR, AR8033_SERDES_REG); | |
79 | phy_write(phydev, MDIO_DEVAD_NONE, AR8033_DBG_REG_DATA, 0x3c47); | |
f9162b15 AB |
80 | |
81 | if (phydev->drv->config) | |
82 | phydev->drv->config(phydev); | |
83 | ||
84 | return 0; | |
85 | } | |
86 | ||
87 | #if defined(CONFIG_VIDEO_IPUV3) | |
92faf43b RB |
88 | static void do_enable_backlight(struct display_info_t const *dev) |
89 | { | |
90 | struct udevice *panel; | |
91 | int ret; | |
92 | ||
93 | ret = uclass_get_device(UCLASS_PANEL, 0, &panel); | |
94 | if (ret) { | |
95 | printf("Could not find panel: %d\n", ret); | |
96 | return; | |
97 | } | |
98 | ||
99 | panel_set_backlight(panel, 100); | |
100 | panel_enable_backlight(panel); | |
101 | } | |
f9162b15 AB |
102 | |
103 | static void do_enable_hdmi(struct display_info_t const *dev) | |
104 | { | |
105 | imx_enable_hdmi_phy(); | |
106 | } | |
107 | ||
7927ff7a | 108 | static int is_b850v3(void) |
f9162b15 | 109 | { |
2d86fb31 | 110 | return productid == VPD_PRODUCT_B850; |
7927ff7a | 111 | } |
f9162b15 | 112 | |
7927ff7a IR |
113 | static int detect_lcd(struct display_info_t const *dev) |
114 | { | |
115 | return !is_b850v3(); | |
f9162b15 AB |
116 | } |
117 | ||
118 | struct display_info_t const displays[] = {{ | |
119 | .bus = -1, | |
120 | .addr = -1, | |
121 | .pixfmt = IPU_PIX_FMT_RGB24, | |
63f0ec57 | 122 | .detect = detect_lcd, |
92faf43b | 123 | .enable = do_enable_backlight, |
f9162b15 AB |
124 | .mode = { |
125 | .name = "G121X1-L03", | |
126 | .refresh = 60, | |
127 | .xres = 1024, | |
128 | .yres = 768, | |
129 | .pixclock = 15385, | |
130 | .left_margin = 20, | |
131 | .right_margin = 300, | |
132 | .upper_margin = 30, | |
133 | .lower_margin = 8, | |
134 | .hsync_len = 1, | |
135 | .vsync_len = 1, | |
136 | .sync = FB_SYNC_EXT, | |
137 | .vmode = FB_VMODE_NONINTERLACED | |
138 | } }, { | |
139 | .bus = -1, | |
140 | .addr = 3, | |
141 | .pixfmt = IPU_PIX_FMT_RGB24, | |
142 | .detect = detect_hdmi, | |
143 | .enable = do_enable_hdmi, | |
144 | .mode = { | |
145 | .name = "HDMI", | |
146 | .refresh = 60, | |
147 | .xres = 1024, | |
148 | .yres = 768, | |
149 | .pixclock = 15385, | |
150 | .left_margin = 220, | |
151 | .right_margin = 40, | |
152 | .upper_margin = 21, | |
153 | .lower_margin = 7, | |
154 | .hsync_len = 60, | |
155 | .vsync_len = 10, | |
156 | .sync = FB_SYNC_EXT, | |
157 | .vmode = FB_VMODE_NONINTERLACED | |
158 | } } }; | |
159 | size_t display_count = ARRAY_SIZE(displays); | |
160 | ||
494d43ec AB |
161 | static void enable_videopll(void) |
162 | { | |
163 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
164 | s32 timeout = 100000; | |
165 | ||
166 | setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); | |
167 | ||
d9ea0d77 IR |
168 | /* PLL_VIDEO 455MHz (24MHz * (37+11/12) / 2) |
169 | * | | |
170 | * PLL5 | |
171 | * | | |
172 | * CS2CDR[LDB_DI0_CLK_SEL] | |
173 | * | | |
174 | * +----> LDB_DI0_SERIAL_CLK_ROOT | |
175 | * | | |
176 | * +--> CSCMR2[LDB_DI0_IPU_DIV] --> LDB_DI0_IPU 455 / 7 = 65 MHz | |
177 | */ | |
178 | ||
494d43ec AB |
179 | clrsetbits_le32(&ccm->analog_pll_video, |
180 | BM_ANADIG_PLL_VIDEO_DIV_SELECT | | |
181 | BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT, | |
182 | BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) | | |
d9ea0d77 | 183 | BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1)); |
494d43ec AB |
184 | |
185 | writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num); | |
186 | writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom); | |
187 | ||
188 | clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); | |
189 | ||
190 | while (timeout--) | |
191 | if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK) | |
192 | break; | |
193 | ||
194 | if (timeout < 0) | |
195 | printf("Warning: video pll lock timeout!\n"); | |
196 | ||
197 | clrsetbits_le32(&ccm->analog_pll_video, | |
198 | BM_ANADIG_PLL_VIDEO_BYPASS, | |
199 | BM_ANADIG_PLL_VIDEO_ENABLE); | |
200 | } | |
201 | ||
de708da0 | 202 | static void setup_display_b850v3(void) |
f9162b15 AB |
203 | { |
204 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
205 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
f9162b15 | 206 | |
494d43ec AB |
207 | enable_videopll(); |
208 | ||
d9ea0d77 IR |
209 | /* IPU1 DI0 clock is 455MHz / 7 = 65MHz */ |
210 | setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV); | |
de708da0 | 211 | |
f9162b15 AB |
212 | imx_setup_hdmi(); |
213 | ||
de708da0 AB |
214 | /* Set LDB_DI0 as clock source for IPU_DI0 */ |
215 | clrsetbits_le32(&mxc_ccm->chsccdr, | |
216 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK, | |
217 | (CHSCCDR_CLK_SEL_LDB_DI0 << | |
218 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)); | |
219 | ||
220 | /* Turn on IPU LDB DI0 clocks */ | |
221 | setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
222 | ||
223 | enable_ipu_clock(); | |
224 | ||
225 | writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES | | |
226 | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW | | |
227 | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW | | |
228 | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG | | |
229 | IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT | | |
230 | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | | |
231 | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | | |
232 | IOMUXC_GPR2_SPLIT_MODE_EN_MASK | | |
233 | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 | | |
234 | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0, | |
235 | &iomux->gpr[2]); | |
236 | ||
237 | clrbits_le32(&iomux->gpr[3], | |
238 | IOMUXC_GPR3_LVDS0_MUX_CTL_MASK | | |
239 | IOMUXC_GPR3_LVDS1_MUX_CTL_MASK | | |
240 | IOMUXC_GPR3_HDMI_MUX_CTL_MASK); | |
241 | } | |
242 | ||
243 | static void setup_display_bx50v3(void) | |
244 | { | |
245 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
246 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
247 | ||
70168a73 IR |
248 | enable_videopll(); |
249 | ||
8d293f49 AB |
250 | /* When a reset/reboot is performed the display power needs to be turned |
251 | * off for atleast 500ms. The boot time is ~300ms, we need to wait for | |
252 | * an additional 200ms here. Unfortunately we use external PMIC for | |
253 | * doing the reset, so can not differentiate between POR vs soft reset | |
254 | */ | |
255 | mdelay(200); | |
256 | ||
d9ea0d77 | 257 | /* IPU1 DI0 clock is 455MHz / 7 = 65MHz */ |
de708da0 AB |
258 | setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV); |
259 | ||
260 | /* Set LDB_DI0 as clock source for IPU_DI0 */ | |
261 | clrsetbits_le32(&mxc_ccm->chsccdr, | |
262 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK, | |
263 | (CHSCCDR_CLK_SEL_LDB_DI0 << | |
264 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)); | |
265 | ||
266 | /* Turn on IPU LDB DI0 clocks */ | |
267 | setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
268 | ||
269 | enable_ipu_clock(); | |
270 | ||
271 | writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES | | |
272 | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW | | |
273 | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | | |
274 | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | | |
275 | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0, | |
276 | &iomux->gpr[2]); | |
277 | ||
278 | clrsetbits_le32(&iomux->gpr[3], | |
279 | IOMUXC_GPR3_LVDS0_MUX_CTL_MASK, | |
280 | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 << | |
281 | IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)); | |
f9162b15 AB |
282 | } |
283 | #endif /* CONFIG_VIDEO_IPUV3 */ | |
284 | ||
285 | /* | |
286 | * Do not overwrite the console | |
287 | * Use always serial for U-Boot console | |
288 | */ | |
289 | int overwrite_console(void) | |
290 | { | |
291 | return 1; | |
292 | } | |
293 | ||
be2808c3 IR |
294 | #define VPD_TYPE_INVALID 0x00 |
295 | #define VPD_BLOCK_NETWORK 0x20 | |
296 | #define VPD_BLOCK_HWID 0x44 | |
cf678b31 | 297 | #define VPD_HAS_MAC1 0x1 |
2850645c | 298 | #define VPD_HAS_MAC2 0x2 |
cf678b31 | 299 | #define VPD_MAC_ADDRESS_LENGTH 6 |
be2808c3 IR |
300 | |
301 | struct vpd_cache { | |
4dcbccf7 | 302 | bool is_read; |
cf678b31 MW |
303 | u8 product_id; |
304 | u8 has; | |
305 | unsigned char mac1[VPD_MAC_ADDRESS_LENGTH]; | |
2850645c | 306 | unsigned char mac2[VPD_MAC_ADDRESS_LENGTH]; |
be2808c3 IR |
307 | }; |
308 | ||
309 | /* | |
310 | * Extracts MAC and product information from the VPD. | |
311 | */ | |
4dcbccf7 | 312 | static int vpd_callback(struct vpd_cache *vpd, u8 id, u8 version, u8 type, |
cf678b31 | 313 | size_t size, u8 const *data) |
be2808c3 | 314 | { |
cf678b31 MW |
315 | if (id == VPD_BLOCK_HWID && version == 1 && type != VPD_TYPE_INVALID && |
316 | size >= 1) { | |
be2808c3 | 317 | vpd->product_id = data[0]; |
cf678b31 MW |
318 | } else if (id == VPD_BLOCK_NETWORK && version == 1 && |
319 | type != VPD_TYPE_INVALID) { | |
320 | if (size >= 6) { | |
321 | vpd->has |= VPD_HAS_MAC1; | |
322 | memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH); | |
323 | } | |
2850645c HL |
324 | if (size >= 12) { |
325 | vpd->has |= VPD_HAS_MAC2; | |
326 | memcpy(vpd->mac2, data + 6, VPD_MAC_ADDRESS_LENGTH); | |
327 | } | |
be2808c3 IR |
328 | } |
329 | ||
330 | return 0; | |
331 | } | |
332 | ||
be2808c3 IR |
333 | static void process_vpd(struct vpd_cache *vpd) |
334 | { | |
b565b18a | 335 | int fec_index = 0; |
2850645c | 336 | int i210_index = -1; |
cf678b31 | 337 | |
4dcbccf7 DZ |
338 | if (!vpd->is_read) { |
339 | printf("VPD wasn't read"); | |
340 | return; | |
341 | } | |
342 | ||
b565b18a DZ |
343 | if (vpd->has & VPD_HAS_MAC1) |
344 | eth_env_set_enetaddr_by_index("eth", fec_index, vpd->mac1); | |
345 | ||
346 | env_set("ethact", "eth0"); | |
347 | ||
f07b3148 IR |
348 | switch (vpd->product_id) { |
349 | case VPD_PRODUCT_B450: | |
b565b18a | 350 | i210_index = 1; |
f07b3148 IR |
351 | break; |
352 | case VPD_PRODUCT_B650: | |
b565b18a | 353 | i210_index = 1; |
cf678b31 MW |
354 | break; |
355 | case VPD_PRODUCT_B850: | |
b565b18a | 356 | i210_index = 2; |
cf678b31 | 357 | break; |
be2808c3 | 358 | } |
cf678b31 | 359 | |
2850645c HL |
360 | if (i210_index >= 0 && (vpd->has & VPD_HAS_MAC2)) |
361 | eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2); | |
be2808c3 IR |
362 | } |
363 | ||
f9162b15 AB |
364 | static iomux_v3_cfg_t const misc_pads[] = { |
365 | MX6_PAD_KEY_ROW2__GPIO4_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
7d0b8cfe JW |
366 | MX6_PAD_EIM_A25__GPIO5_IO02 | MUX_PAD_CTRL(NC_PAD_CTRL), |
367 | MX6_PAD_EIM_CS0__GPIO2_IO23 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
368 | MX6_PAD_EIM_CS1__GPIO2_IO24 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
369 | MX6_PAD_EIM_OE__GPIO2_IO25 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
370 | MX6_PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
371 | MX6_PAD_GPIO_1__GPIO1_IO01 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
6d656495 | 372 | MX6_PAD_GPIO_9__WDOG1_B | MUX_PAD_CTRL(NC_PAD_CTRL), |
f9162b15 AB |
373 | }; |
374 | #define SUS_S3_OUT IMX_GPIO_NR(4, 11) | |
4f1970f4 | 375 | #define PWGIN_IN IMX_GPIO_NR(4, 14) |
f9162b15 AB |
376 | #define WIFI_EN IMX_GPIO_NR(6, 14) |
377 | ||
378 | int board_early_init_f(void) | |
379 | { | |
380 | imx_iomux_v3_setup_multiple_pads(misc_pads, | |
381 | ARRAY_SIZE(misc_pads)); | |
382 | ||
494d43ec | 383 | #if defined(CONFIG_VIDEO_IPUV3) |
d9ea0d77 IR |
384 | /* Set LDB clock to Video PLL */ |
385 | select_ldb_di_clock_source(MXC_PLL5_CLK); | |
494d43ec | 386 | #endif |
f9162b15 AB |
387 | return 0; |
388 | } | |
389 | ||
390 | int board_init(void) | |
391 | { | |
def6f53d | 392 | if (!read_i2c_vpd(&vpd, vpd_callback)) { |
8c267398 RB |
393 | int ret, rescan; |
394 | ||
4dcbccf7 | 395 | vpd.is_read = true; |
2d86fb31 | 396 | productid = vpd.product_id; |
8c267398 RB |
397 | |
398 | ret = fdtdec_resetup(&rescan); | |
399 | if (!ret && rescan) { | |
400 | dm_uninit(); | |
401 | dm_init_and_scan(false); | |
402 | } | |
4dcbccf7 | 403 | } |
5e604e2c | 404 | |
06f2e030 | 405 | gpio_request(SUS_S3_OUT, "sus_s3_out"); |
f9162b15 | 406 | gpio_direction_output(SUS_S3_OUT, 1); |
06f2e030 | 407 | |
4f1970f4 IR |
408 | gpio_request(PWGIN_IN, "pwgin_in"); |
409 | gpio_direction_input(PWGIN_IN); | |
410 | ||
06f2e030 | 411 | gpio_request(WIFI_EN, "wifi_en"); |
f9162b15 | 412 | gpio_direction_output(WIFI_EN, 1); |
06f2e030 | 413 | |
f9162b15 | 414 | #if defined(CONFIG_VIDEO_IPUV3) |
7927ff7a | 415 | if (is_b850v3()) |
de708da0 AB |
416 | setup_display_b850v3(); |
417 | else | |
418 | setup_display_bx50v3(); | |
f9162b15 | 419 | #endif |
06f2e030 | 420 | |
f9162b15 AB |
421 | /* address of boot parameters */ |
422 | gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; | |
423 | ||
f9162b15 AB |
424 | return 0; |
425 | } | |
426 | ||
427 | #ifdef CONFIG_CMD_BMODE | |
428 | static const struct boot_mode board_boot_modes[] = { | |
429 | /* 4 bit bus width */ | |
430 | {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, | |
431 | {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, | |
432 | {NULL, 0}, | |
433 | }; | |
434 | #endif | |
435 | ||
512bda95 SR |
436 | |
437 | /* | |
438 | * The SoM used by these boards has XTAL not connected despite datasheet | |
439 | * suggesting connecting unused XTAL pins to ground. Without explicitly | |
440 | * clearing the CRYSTAL bit the system runs unstable and sometimes reboots | |
441 | * unexpectedly. | |
442 | */ | |
443 | static void pmic_crystal_fix(void) | |
444 | { | |
445 | struct udevice *pmic; | |
446 | static const uint EN_32K_CRYSTAL = (1 << 3); | |
447 | ||
448 | if (pmic_get("pmic@58", &pmic)) { | |
449 | puts("failed to get device for PMIC\n"); | |
450 | return; | |
451 | } | |
452 | ||
453 | if (pmic_clrsetbits(pmic, DA9063_REG_EN_32K, EN_32K_CRYSTAL, 0) < 0) { | |
454 | puts("failed to clear CRYSTAL bit\n"); | |
455 | return; | |
456 | } | |
457 | } | |
458 | ||
22d358da KL |
459 | void pmic_init(void) |
460 | { | |
1dec7fa7 RB |
461 | struct udevice *reg; |
462 | int ret, i; | |
463 | static const char * const bucks[] = { | |
464 | "bcore1", | |
465 | "bcore2", | |
466 | "bpro", | |
467 | "bmem", | |
468 | "bio", | |
469 | "bperi", | |
470 | }; | |
471 | ||
512bda95 SR |
472 | pmic_crystal_fix(); |
473 | ||
1dec7fa7 RB |
474 | for (i = 0; i < ARRAY_SIZE(bucks); i++) { |
475 | ret = regulator_get_by_devname(bucks[i], ®); | |
476 | if (reg < 0) { | |
477 | printf("%s(): Unable to get regulator %s: %d\n", | |
478 | __func__, bucks[i], ret); | |
479 | continue; | |
480 | } | |
481 | regulator_set_mode(reg, DA9063_BUCKMODE_SYNC); | |
482 | } | |
22d358da KL |
483 | } |
484 | ||
4f1970f4 IR |
485 | static void detect_boot_cause(void) |
486 | { | |
487 | const char *cause = "POR"; | |
488 | ||
489 | if (is_b850v3()) | |
490 | if (!gpio_get_value(PWGIN_IN)) | |
491 | cause = "PM_WDOG"; | |
492 | ||
493 | env_set("bootcause", cause); | |
494 | } | |
495 | ||
f9162b15 AB |
496 | int board_late_init(void) |
497 | { | |
5e604e2c | 498 | process_vpd(&vpd); |
cf678b31 | 499 | |
f9162b15 AB |
500 | #ifdef CONFIG_CMD_BMODE |
501 | add_board_boot_modes(board_boot_modes); | |
502 | #endif | |
0c344e6e | 503 | |
06a3e438 IR |
504 | if (is_b850v3()) |
505 | env_set("videoargs", "video=DP-1:1024x768@60 video=HDMI-A-1:1024x768@60"); | |
9aa7c157 IR |
506 | else |
507 | env_set("videoargs", "video=LVDS-1:1024x768@65"); | |
06a3e438 | 508 | |
4f1970f4 IR |
509 | detect_boot_cause(); |
510 | ||
22d358da KL |
511 | /* board specific pmic init */ |
512 | pmic_init(); | |
513 | ||
886678fc NH |
514 | check_time(); |
515 | ||
b565b18a DZ |
516 | pci_init(); |
517 | ||
f9162b15 AB |
518 | return 0; |
519 | } | |
520 | ||
2850645c HL |
521 | /* |
522 | * Removes the 'eth[0-9]*addr' environment variable with the given index | |
523 | * | |
524 | * @param index [in] the index of the eth_device whose variable is to be removed | |
525 | */ | |
526 | static void remove_ethaddr_env_var(int index) | |
527 | { | |
528 | char env_var_name[9]; | |
529 | ||
530 | sprintf(env_var_name, index == 0 ? "ethaddr" : "eth%daddr", index); | |
531 | env_set(env_var_name, NULL); | |
532 | } | |
533 | ||
cf678b31 MW |
534 | int last_stage_init(void) |
535 | { | |
2850645c HL |
536 | int i; |
537 | ||
538 | /* | |
539 | * Remove first three ethaddr which may have been created by | |
540 | * function process_vpd(). | |
541 | */ | |
542 | for (i = 0; i < 3; ++i) | |
543 | remove_ethaddr_env_var(i); | |
cf678b31 MW |
544 | |
545 | return 0; | |
546 | } | |
547 | ||
f9162b15 AB |
548 | int checkboard(void) |
549 | { | |
47267f82 | 550 | printf("BOARD: General Electric Bx50v3\n"); |
f9162b15 AB |
551 | return 0; |
552 | } | |
6c0e6b45 | 553 | |
61c4c2bf | 554 | #ifdef CONFIG_OF_BOARD_SETUP |
b75d8dc5 | 555 | int ft_board_setup(void *blob, struct bd_info *bd) |
61c4c2bf | 556 | { |
b186cfa1 IR |
557 | char *rtc_status = env_get("rtc_status"); |
558 | ||
61c4c2bf | 559 | fdt_setprop(blob, 0, "ge,boot-ver", version_string, |
b186cfa1 IR |
560 | strlen(version_string) + 1); |
561 | ||
562 | fdt_setprop(blob, 0, "ge,rtc-status", rtc_status, | |
563 | strlen(rtc_status) + 1); | |
61c4c2bf IR |
564 | return 0; |
565 | } | |
566 | #endif | |
567 | ||
8c267398 RB |
568 | int board_fit_config_name_match(const char *name) |
569 | { | |
c44d374b SR |
570 | const char *machine = name; |
571 | ||
8c267398 RB |
572 | if (!vpd.is_read) |
573 | return strcmp(name, "imx6q-bx50v3"); | |
574 | ||
c44d374b SR |
575 | if (!strncmp(machine, "Boot ", 5)) |
576 | machine += 5; | |
577 | if (!strncmp(machine, "imx6q-", 6)) | |
578 | machine += 6; | |
579 | ||
8c267398 RB |
580 | switch (vpd.product_id) { |
581 | case VPD_PRODUCT_B450: | |
c44d374b | 582 | return strcasecmp(machine, "b450v3"); |
8c267398 | 583 | case VPD_PRODUCT_B650: |
c44d374b | 584 | return strcasecmp(machine, "b650v3"); |
8c267398 | 585 | case VPD_PRODUCT_B850: |
c44d374b | 586 | return strcasecmp(machine, "b850v3"); |
8c267398 RB |
587 | default: |
588 | return -1; | |
589 | } | |
590 | } | |
591 | ||
592 | int embedded_dtb_select(void) | |
593 | { | |
594 | vpd.is_read = false; | |
595 | return fdtdec_setup(); | |
596 | } |