]>
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 | ||
8 | #include <asm/arch/clock.h> | |
9 | #include <asm/arch/imx-regs.h> | |
10 | #include <asm/arch/iomux.h> | |
11 | #include <asm/arch/mx6-pins.h> | |
1221ce45 | 12 | #include <linux/errno.h> |
61c4c2bf | 13 | #include <linux/libfdt.h> |
f9162b15 | 14 | #include <asm/gpio.h> |
552a848e SB |
15 | #include <asm/mach-imx/mxc_i2c.h> |
16 | #include <asm/mach-imx/iomux-v3.h> | |
17 | #include <asm/mach-imx/boot_mode.h> | |
18 | #include <asm/mach-imx/video.h> | |
f9162b15 AB |
19 | #include <mmc.h> |
20 | #include <fsl_esdhc.h> | |
21 | #include <miiphy.h> | |
cf678b31 | 22 | #include <net.h> |
f9162b15 AB |
23 | #include <netdev.h> |
24 | #include <asm/arch/mxc_hdmi.h> | |
25 | #include <asm/arch/crm_regs.h> | |
26 | #include <asm/io.h> | |
27 | #include <asm/arch/sys_proto.h> | |
28 | #include <i2c.h> | |
7594c51a | 29 | #include <input.h> |
54971ac6 | 30 | #include <pwm.h> |
61c4c2bf | 31 | #include <version.h> |
be2808c3 | 32 | #include <stdlib.h> |
886678fc | 33 | #include "../common/ge_common.h" |
b418dfe1 | 34 | #include "../common/vpd_reader.h" |
2850645c | 35 | #include "../../../drivers/net/e1000.h" |
f9162b15 AB |
36 | DECLARE_GLOBAL_DATA_PTR; |
37 | ||
5e604e2c NH |
38 | static int confidx = 3; /* Default to b850v3. */ |
39 | static struct vpd_cache vpd; | |
40 | ||
7d0b8cfe JW |
41 | #define NC_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ |
42 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ | |
43 | PAD_CTL_HYS) | |
44 | ||
f9162b15 AB |
45 | #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ |
46 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ | |
47 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
48 | ||
f9162b15 AB |
49 | #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE | \ |
50 | PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_48ohm | PAD_CTL_SRE_FAST) | |
51 | ||
52 | #define ENET_CLK_PAD_CTRL (PAD_CTL_SPEED_MED | \ | |
53 | PAD_CTL_DSE_120ohm | PAD_CTL_SRE_FAST) | |
54 | ||
55 | #define ENET_RX_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ | |
56 | PAD_CTL_SPEED_HIGH | PAD_CTL_SRE_FAST) | |
57 | ||
f9162b15 AB |
58 | #define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ |
59 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ | |
60 | PAD_CTL_ODE | PAD_CTL_SRE_FAST) | |
61 | ||
62 | #define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL) | |
63 | ||
64 | int dram_init(void) | |
65 | { | |
c6a51bab | 66 | gd->ram_size = imx_ddr_size(); |
f9162b15 AB |
67 | |
68 | return 0; | |
69 | } | |
70 | ||
71 | static iomux_v3_cfg_t const uart3_pads[] = { | |
72 | MX6_PAD_EIM_D31__UART3_RTS_B | MUX_PAD_CTRL(UART_PAD_CTRL), | |
73 | MX6_PAD_EIM_D23__UART3_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL), | |
74 | MX6_PAD_EIM_D24__UART3_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
75 | MX6_PAD_EIM_D25__UART3_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
76 | }; | |
77 | ||
78 | static iomux_v3_cfg_t const uart4_pads[] = { | |
79 | MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
80 | MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
81 | }; | |
82 | ||
83 | static iomux_v3_cfg_t const enet_pads[] = { | |
84 | MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
85 | MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
86 | MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
87 | MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
88 | MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
89 | MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
90 | MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
91 | MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
92 | MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL), | |
93 | MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
94 | MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
95 | MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
96 | MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
97 | MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
98 | MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_RX_PAD_CTRL), | |
99 | /* AR8033 PHY Reset */ | |
100 | MX6_PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
101 | }; | |
102 | ||
103 | static void setup_iomux_enet(void) | |
104 | { | |
105 | imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads)); | |
106 | ||
107 | /* Reset AR8033 PHY */ | |
06f2e030 | 108 | gpio_request(IMX_GPIO_NR(1, 28), "fec_rst"); |
f9162b15 | 109 | gpio_direction_output(IMX_GPIO_NR(1, 28), 0); |
d42db168 | 110 | mdelay(10); |
f9162b15 | 111 | gpio_set_value(IMX_GPIO_NR(1, 28), 1); |
d42db168 | 112 | mdelay(1); |
f9162b15 AB |
113 | } |
114 | ||
f9162b15 AB |
115 | static struct i2c_pads_info i2c_pad_info1 = { |
116 | .scl = { | |
117 | .i2c_mode = MX6_PAD_CSI0_DAT9__I2C1_SCL | I2C_PAD, | |
118 | .gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27 | I2C_PAD, | |
119 | .gp = IMX_GPIO_NR(5, 27) | |
120 | }, | |
121 | .sda = { | |
122 | .i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA | I2C_PAD, | |
123 | .gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26 | I2C_PAD, | |
124 | .gp = IMX_GPIO_NR(5, 26) | |
125 | } | |
126 | }; | |
127 | ||
128 | static struct i2c_pads_info i2c_pad_info2 = { | |
129 | .scl = { | |
130 | .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | I2C_PAD, | |
131 | .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | I2C_PAD, | |
132 | .gp = IMX_GPIO_NR(4, 12) | |
133 | }, | |
134 | .sda = { | |
135 | .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | I2C_PAD, | |
136 | .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | I2C_PAD, | |
137 | .gp = IMX_GPIO_NR(4, 13) | |
138 | } | |
139 | }; | |
140 | ||
141 | static struct i2c_pads_info i2c_pad_info3 = { | |
142 | .scl = { | |
143 | .i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | I2C_PAD, | |
144 | .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03 | I2C_PAD, | |
145 | .gp = IMX_GPIO_NR(1, 3) | |
146 | }, | |
147 | .sda = { | |
148 | .i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA | I2C_PAD, | |
149 | .gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06 | I2C_PAD, | |
150 | .gp = IMX_GPIO_NR(1, 6) | |
151 | } | |
152 | }; | |
153 | ||
f9162b15 AB |
154 | static iomux_v3_cfg_t const pcie_pads[] = { |
155 | MX6_PAD_GPIO_5__GPIO1_IO05 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
156 | MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
157 | }; | |
158 | ||
159 | static void setup_pcie(void) | |
160 | { | |
161 | imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads)); | |
162 | } | |
163 | ||
164 | static void setup_iomux_uart(void) | |
165 | { | |
166 | imx_iomux_v3_setup_multiple_pads(uart3_pads, ARRAY_SIZE(uart3_pads)); | |
167 | imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads)); | |
168 | } | |
169 | ||
f9162b15 AB |
170 | static int mx6_rgmii_rework(struct phy_device *phydev) |
171 | { | |
172 | /* Configure AR8033 to ouput a 125MHz clk from CLK_25M */ | |
173 | /* set device address 0x7 */ | |
174 | phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); | |
175 | /* offset 0x8016: CLK_25M Clock Select */ | |
176 | phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); | |
177 | /* enable register write, no post increment, address 0x7 */ | |
178 | phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); | |
179 | /* set to 125 MHz from local PLL source */ | |
180 | phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x18); | |
181 | ||
182 | /* rgmii tx clock delay enable */ | |
183 | /* set debug port address: SerDes Test and System Mode Control */ | |
184 | phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); | |
185 | /* enable rgmii tx clock delay */ | |
ec7aa8fd YCL |
186 | /* set the reserved bits to avoid board specific voltage peak issue*/ |
187 | phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47); | |
f9162b15 AB |
188 | |
189 | return 0; | |
190 | } | |
191 | ||
192 | int board_phy_config(struct phy_device *phydev) | |
193 | { | |
194 | mx6_rgmii_rework(phydev); | |
195 | ||
196 | if (phydev->drv->config) | |
197 | phydev->drv->config(phydev); | |
198 | ||
199 | return 0; | |
200 | } | |
201 | ||
202 | #if defined(CONFIG_VIDEO_IPUV3) | |
203 | static iomux_v3_cfg_t const backlight_pads[] = { | |
204 | /* Power for LVDS Display */ | |
205 | MX6_PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
206 | #define LVDS_POWER_GP IMX_GPIO_NR(3, 22) | |
207 | /* Backlight enable for LVDS display */ | |
208 | MX6_PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
209 | #define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 0) | |
54971ac6 AB |
210 | /* backlight PWM brightness control */ |
211 | MX6_PAD_SD1_DAT3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), | |
f9162b15 AB |
212 | }; |
213 | ||
214 | static void do_enable_hdmi(struct display_info_t const *dev) | |
215 | { | |
216 | imx_enable_hdmi_phy(); | |
217 | } | |
218 | ||
219 | int board_cfb_skip(void) | |
220 | { | |
221 | gpio_direction_output(LVDS_POWER_GP, 1); | |
222 | ||
223 | return 0; | |
224 | } | |
225 | ||
7927ff7a | 226 | static int is_b850v3(void) |
f9162b15 | 227 | { |
7927ff7a IR |
228 | return confidx == 3; |
229 | } | |
f9162b15 | 230 | |
7927ff7a IR |
231 | static int detect_lcd(struct display_info_t const *dev) |
232 | { | |
233 | return !is_b850v3(); | |
f9162b15 AB |
234 | } |
235 | ||
236 | struct display_info_t const displays[] = {{ | |
237 | .bus = -1, | |
238 | .addr = -1, | |
239 | .pixfmt = IPU_PIX_FMT_RGB24, | |
63f0ec57 | 240 | .detect = detect_lcd, |
f9162b15 AB |
241 | .enable = NULL, |
242 | .mode = { | |
243 | .name = "G121X1-L03", | |
244 | .refresh = 60, | |
245 | .xres = 1024, | |
246 | .yres = 768, | |
247 | .pixclock = 15385, | |
248 | .left_margin = 20, | |
249 | .right_margin = 300, | |
250 | .upper_margin = 30, | |
251 | .lower_margin = 8, | |
252 | .hsync_len = 1, | |
253 | .vsync_len = 1, | |
254 | .sync = FB_SYNC_EXT, | |
255 | .vmode = FB_VMODE_NONINTERLACED | |
256 | } }, { | |
257 | .bus = -1, | |
258 | .addr = 3, | |
259 | .pixfmt = IPU_PIX_FMT_RGB24, | |
260 | .detect = detect_hdmi, | |
261 | .enable = do_enable_hdmi, | |
262 | .mode = { | |
263 | .name = "HDMI", | |
264 | .refresh = 60, | |
265 | .xres = 1024, | |
266 | .yres = 768, | |
267 | .pixclock = 15385, | |
268 | .left_margin = 220, | |
269 | .right_margin = 40, | |
270 | .upper_margin = 21, | |
271 | .lower_margin = 7, | |
272 | .hsync_len = 60, | |
273 | .vsync_len = 10, | |
274 | .sync = FB_SYNC_EXT, | |
275 | .vmode = FB_VMODE_NONINTERLACED | |
276 | } } }; | |
277 | size_t display_count = ARRAY_SIZE(displays); | |
278 | ||
494d43ec AB |
279 | static void enable_videopll(void) |
280 | { | |
281 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
282 | s32 timeout = 100000; | |
283 | ||
284 | setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); | |
285 | ||
d9ea0d77 IR |
286 | /* PLL_VIDEO 455MHz (24MHz * (37+11/12) / 2) |
287 | * | | |
288 | * PLL5 | |
289 | * | | |
290 | * CS2CDR[LDB_DI0_CLK_SEL] | |
291 | * | | |
292 | * +----> LDB_DI0_SERIAL_CLK_ROOT | |
293 | * | | |
294 | * +--> CSCMR2[LDB_DI0_IPU_DIV] --> LDB_DI0_IPU 455 / 7 = 65 MHz | |
295 | */ | |
296 | ||
494d43ec AB |
297 | clrsetbits_le32(&ccm->analog_pll_video, |
298 | BM_ANADIG_PLL_VIDEO_DIV_SELECT | | |
299 | BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT, | |
300 | BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) | | |
d9ea0d77 | 301 | BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1)); |
494d43ec AB |
302 | |
303 | writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num); | |
304 | writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom); | |
305 | ||
306 | clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); | |
307 | ||
308 | while (timeout--) | |
309 | if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK) | |
310 | break; | |
311 | ||
312 | if (timeout < 0) | |
313 | printf("Warning: video pll lock timeout!\n"); | |
314 | ||
315 | clrsetbits_le32(&ccm->analog_pll_video, | |
316 | BM_ANADIG_PLL_VIDEO_BYPASS, | |
317 | BM_ANADIG_PLL_VIDEO_ENABLE); | |
318 | } | |
319 | ||
de708da0 | 320 | static void setup_display_b850v3(void) |
f9162b15 AB |
321 | { |
322 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
323 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
f9162b15 | 324 | |
494d43ec AB |
325 | enable_videopll(); |
326 | ||
d9ea0d77 IR |
327 | /* IPU1 DI0 clock is 455MHz / 7 = 65MHz */ |
328 | setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV); | |
de708da0 | 329 | |
f9162b15 AB |
330 | imx_setup_hdmi(); |
331 | ||
de708da0 AB |
332 | /* Set LDB_DI0 as clock source for IPU_DI0 */ |
333 | clrsetbits_le32(&mxc_ccm->chsccdr, | |
334 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK, | |
335 | (CHSCCDR_CLK_SEL_LDB_DI0 << | |
336 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)); | |
337 | ||
338 | /* Turn on IPU LDB DI0 clocks */ | |
339 | setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
340 | ||
341 | enable_ipu_clock(); | |
342 | ||
343 | writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES | | |
344 | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW | | |
345 | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW | | |
346 | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG | | |
347 | IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT | | |
348 | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | | |
349 | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | | |
350 | IOMUXC_GPR2_SPLIT_MODE_EN_MASK | | |
351 | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 | | |
352 | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0, | |
353 | &iomux->gpr[2]); | |
354 | ||
355 | clrbits_le32(&iomux->gpr[3], | |
356 | IOMUXC_GPR3_LVDS0_MUX_CTL_MASK | | |
357 | IOMUXC_GPR3_LVDS1_MUX_CTL_MASK | | |
358 | IOMUXC_GPR3_HDMI_MUX_CTL_MASK); | |
359 | } | |
360 | ||
361 | static void setup_display_bx50v3(void) | |
362 | { | |
363 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
364 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
365 | ||
70168a73 IR |
366 | enable_videopll(); |
367 | ||
8d293f49 AB |
368 | /* When a reset/reboot is performed the display power needs to be turned |
369 | * off for atleast 500ms. The boot time is ~300ms, we need to wait for | |
370 | * an additional 200ms here. Unfortunately we use external PMIC for | |
371 | * doing the reset, so can not differentiate between POR vs soft reset | |
372 | */ | |
373 | mdelay(200); | |
374 | ||
d9ea0d77 | 375 | /* IPU1 DI0 clock is 455MHz / 7 = 65MHz */ |
de708da0 AB |
376 | setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV); |
377 | ||
378 | /* Set LDB_DI0 as clock source for IPU_DI0 */ | |
379 | clrsetbits_le32(&mxc_ccm->chsccdr, | |
380 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK, | |
381 | (CHSCCDR_CLK_SEL_LDB_DI0 << | |
382 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)); | |
383 | ||
384 | /* Turn on IPU LDB DI0 clocks */ | |
385 | setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); | |
386 | ||
387 | enable_ipu_clock(); | |
388 | ||
389 | writel(IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES | | |
390 | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW | | |
391 | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | | |
392 | IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | | |
393 | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0, | |
394 | &iomux->gpr[2]); | |
395 | ||
396 | clrsetbits_le32(&iomux->gpr[3], | |
397 | IOMUXC_GPR3_LVDS0_MUX_CTL_MASK, | |
398 | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 << | |
399 | IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)); | |
f9162b15 AB |
400 | |
401 | /* backlights off until needed */ | |
402 | imx_iomux_v3_setup_multiple_pads(backlight_pads, | |
403 | ARRAY_SIZE(backlight_pads)); | |
06f2e030 | 404 | gpio_request(LVDS_POWER_GP, "lvds_power"); |
f9162b15 | 405 | gpio_direction_input(LVDS_POWER_GP); |
f9162b15 AB |
406 | } |
407 | #endif /* CONFIG_VIDEO_IPUV3 */ | |
408 | ||
409 | /* | |
410 | * Do not overwrite the console | |
411 | * Use always serial for U-Boot console | |
412 | */ | |
413 | int overwrite_console(void) | |
414 | { | |
415 | return 1; | |
416 | } | |
417 | ||
be2808c3 IR |
418 | #define VPD_TYPE_INVALID 0x00 |
419 | #define VPD_BLOCK_NETWORK 0x20 | |
420 | #define VPD_BLOCK_HWID 0x44 | |
421 | #define VPD_PRODUCT_B850 1 | |
422 | #define VPD_PRODUCT_B650 2 | |
423 | #define VPD_PRODUCT_B450 3 | |
cf678b31 | 424 | #define VPD_HAS_MAC1 0x1 |
2850645c | 425 | #define VPD_HAS_MAC2 0x2 |
cf678b31 | 426 | #define VPD_MAC_ADDRESS_LENGTH 6 |
be2808c3 IR |
427 | |
428 | struct vpd_cache { | |
4dcbccf7 | 429 | bool is_read; |
cf678b31 MW |
430 | u8 product_id; |
431 | u8 has; | |
432 | unsigned char mac1[VPD_MAC_ADDRESS_LENGTH]; | |
2850645c | 433 | unsigned char mac2[VPD_MAC_ADDRESS_LENGTH]; |
be2808c3 IR |
434 | }; |
435 | ||
436 | /* | |
437 | * Extracts MAC and product information from the VPD. | |
438 | */ | |
4dcbccf7 | 439 | static int vpd_callback(struct vpd_cache *vpd, u8 id, u8 version, u8 type, |
cf678b31 | 440 | size_t size, u8 const *data) |
be2808c3 | 441 | { |
cf678b31 MW |
442 | if (id == VPD_BLOCK_HWID && version == 1 && type != VPD_TYPE_INVALID && |
443 | size >= 1) { | |
be2808c3 | 444 | vpd->product_id = data[0]; |
cf678b31 MW |
445 | } else if (id == VPD_BLOCK_NETWORK && version == 1 && |
446 | type != VPD_TYPE_INVALID) { | |
447 | if (size >= 6) { | |
448 | vpd->has |= VPD_HAS_MAC1; | |
449 | memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH); | |
450 | } | |
2850645c HL |
451 | if (size >= 12) { |
452 | vpd->has |= VPD_HAS_MAC2; | |
453 | memcpy(vpd->mac2, data + 6, VPD_MAC_ADDRESS_LENGTH); | |
454 | } | |
be2808c3 IR |
455 | } |
456 | ||
457 | return 0; | |
458 | } | |
459 | ||
be2808c3 IR |
460 | static void process_vpd(struct vpd_cache *vpd) |
461 | { | |
cf678b31 | 462 | int fec_index = -1; |
2850645c | 463 | int i210_index = -1; |
cf678b31 | 464 | |
4dcbccf7 DZ |
465 | if (!vpd->is_read) { |
466 | printf("VPD wasn't read"); | |
467 | return; | |
468 | } | |
469 | ||
f07b3148 IR |
470 | switch (vpd->product_id) { |
471 | case VPD_PRODUCT_B450: | |
472 | env_set("confidx", "1"); | |
5ce9a1c8 NH |
473 | i210_index = 0; |
474 | fec_index = 1; | |
f07b3148 IR |
475 | break; |
476 | case VPD_PRODUCT_B650: | |
477 | env_set("confidx", "2"); | |
2850645c | 478 | i210_index = 0; |
cf678b31 MW |
479 | fec_index = 1; |
480 | break; | |
481 | case VPD_PRODUCT_B850: | |
5ce9a1c8 | 482 | env_set("confidx", "3"); |
2850645c | 483 | i210_index = 1; |
cf678b31 MW |
484 | fec_index = 2; |
485 | break; | |
be2808c3 | 486 | } |
cf678b31 MW |
487 | |
488 | if (fec_index >= 0 && (vpd->has & VPD_HAS_MAC1)) | |
489 | eth_env_set_enetaddr_by_index("eth", fec_index, vpd->mac1); | |
2850645c HL |
490 | |
491 | if (i210_index >= 0 && (vpd->has & VPD_HAS_MAC2)) | |
492 | eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2); | |
be2808c3 IR |
493 | } |
494 | ||
f9162b15 AB |
495 | int board_eth_init(bd_t *bis) |
496 | { | |
497 | setup_iomux_enet(); | |
498 | setup_pcie(); | |
499 | ||
2850645c HL |
500 | e1000_initialize(bis); |
501 | ||
f9162b15 AB |
502 | return cpu_eth_init(bis); |
503 | } | |
504 | ||
505 | static iomux_v3_cfg_t const misc_pads[] = { | |
506 | MX6_PAD_KEY_ROW2__GPIO4_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
7d0b8cfe JW |
507 | MX6_PAD_EIM_A25__GPIO5_IO02 | MUX_PAD_CTRL(NC_PAD_CTRL), |
508 | MX6_PAD_EIM_CS0__GPIO2_IO23 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
509 | MX6_PAD_EIM_CS1__GPIO2_IO24 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
510 | MX6_PAD_EIM_OE__GPIO2_IO25 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
511 | MX6_PAD_EIM_BCLK__GPIO6_IO31 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
512 | MX6_PAD_GPIO_1__GPIO1_IO01 | MUX_PAD_CTRL(NC_PAD_CTRL), | |
6d656495 | 513 | MX6_PAD_GPIO_9__WDOG1_B | MUX_PAD_CTRL(NC_PAD_CTRL), |
f9162b15 AB |
514 | }; |
515 | #define SUS_S3_OUT IMX_GPIO_NR(4, 11) | |
516 | #define WIFI_EN IMX_GPIO_NR(6, 14) | |
517 | ||
518 | int board_early_init_f(void) | |
519 | { | |
520 | imx_iomux_v3_setup_multiple_pads(misc_pads, | |
521 | ARRAY_SIZE(misc_pads)); | |
522 | ||
523 | setup_iomux_uart(); | |
524 | ||
494d43ec | 525 | #if defined(CONFIG_VIDEO_IPUV3) |
d9ea0d77 IR |
526 | /* Set LDB clock to Video PLL */ |
527 | select_ldb_di_clock_source(MXC_PLL5_CLK); | |
494d43ec | 528 | #endif |
f9162b15 AB |
529 | return 0; |
530 | } | |
531 | ||
5e604e2c NH |
532 | static void set_confidx(const struct vpd_cache* vpd) |
533 | { | |
534 | switch (vpd->product_id) { | |
535 | case VPD_PRODUCT_B450: | |
536 | confidx = 1; | |
537 | break; | |
538 | case VPD_PRODUCT_B650: | |
539 | confidx = 2; | |
540 | break; | |
541 | case VPD_PRODUCT_B850: | |
542 | confidx = 3; | |
543 | break; | |
544 | } | |
545 | } | |
546 | ||
f9162b15 AB |
547 | int board_init(void) |
548 | { | |
f767a4e8 DC |
549 | setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); |
550 | setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2); | |
551 | setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3); | |
5e604e2c | 552 | |
4dcbccf7 DZ |
553 | if (!read_vpd(&vpd, vpd_callback)) { |
554 | vpd.is_read = true; | |
555 | set_confidx(&vpd); | |
556 | } | |
5e604e2c | 557 | |
06f2e030 | 558 | gpio_request(SUS_S3_OUT, "sus_s3_out"); |
f9162b15 | 559 | gpio_direction_output(SUS_S3_OUT, 1); |
06f2e030 IR |
560 | |
561 | gpio_request(WIFI_EN, "wifi_en"); | |
f9162b15 | 562 | gpio_direction_output(WIFI_EN, 1); |
06f2e030 | 563 | |
f9162b15 | 564 | #if defined(CONFIG_VIDEO_IPUV3) |
7927ff7a | 565 | if (is_b850v3()) |
de708da0 AB |
566 | setup_display_b850v3(); |
567 | else | |
568 | setup_display_bx50v3(); | |
06f2e030 IR |
569 | |
570 | gpio_request(LVDS_BACKLIGHT_GP, "lvds_backlight"); | |
571 | gpio_direction_input(LVDS_BACKLIGHT_GP); | |
f9162b15 | 572 | #endif |
06f2e030 | 573 | |
f9162b15 AB |
574 | /* address of boot parameters */ |
575 | gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; | |
576 | ||
f9162b15 AB |
577 | return 0; |
578 | } | |
579 | ||
580 | #ifdef CONFIG_CMD_BMODE | |
581 | static const struct boot_mode board_boot_modes[] = { | |
582 | /* 4 bit bus width */ | |
583 | {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, | |
584 | {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, | |
585 | {NULL, 0}, | |
586 | }; | |
587 | #endif | |
588 | ||
22d358da KL |
589 | void pmic_init(void) |
590 | { | |
591 | #define I2C_PMIC 0x2 | |
592 | #define DA9063_I2C_ADDR 0x58 | |
593 | #define DA9063_REG_BCORE2_CFG 0x9D | |
594 | #define DA9063_REG_BCORE1_CFG 0x9E | |
595 | #define DA9063_REG_BPRO_CFG 0x9F | |
596 | #define DA9063_REG_BIO_CFG 0xA0 | |
597 | #define DA9063_REG_BMEM_CFG 0xA1 | |
598 | #define DA9063_REG_BPERI_CFG 0xA2 | |
599 | #define DA9063_BUCK_MODE_MASK 0xC0 | |
600 | #define DA9063_BUCK_MODE_MANUAL 0x00 | |
601 | #define DA9063_BUCK_MODE_SLEEP 0x40 | |
602 | #define DA9063_BUCK_MODE_SYNC 0x80 | |
603 | #define DA9063_BUCK_MODE_AUTO 0xC0 | |
604 | ||
605 | uchar val; | |
606 | ||
607 | i2c_set_bus_num(I2C_PMIC); | |
608 | ||
609 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BCORE2_CFG, 1, &val, 1); | |
610 | val &= ~DA9063_BUCK_MODE_MASK; | |
611 | val |= DA9063_BUCK_MODE_SYNC; | |
612 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BCORE2_CFG, 1, &val, 1); | |
613 | ||
614 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BCORE1_CFG, 1, &val, 1); | |
615 | val &= ~DA9063_BUCK_MODE_MASK; | |
616 | val |= DA9063_BUCK_MODE_SYNC; | |
617 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BCORE1_CFG, 1, &val, 1); | |
618 | ||
619 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BPRO_CFG, 1, &val, 1); | |
620 | val &= ~DA9063_BUCK_MODE_MASK; | |
621 | val |= DA9063_BUCK_MODE_SYNC; | |
622 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BPRO_CFG, 1, &val, 1); | |
623 | ||
624 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BIO_CFG, 1, &val, 1); | |
625 | val &= ~DA9063_BUCK_MODE_MASK; | |
626 | val |= DA9063_BUCK_MODE_SYNC; | |
627 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BIO_CFG, 1, &val, 1); | |
628 | ||
629 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BMEM_CFG, 1, &val, 1); | |
630 | val &= ~DA9063_BUCK_MODE_MASK; | |
631 | val |= DA9063_BUCK_MODE_SYNC; | |
632 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BMEM_CFG, 1, &val, 1); | |
633 | ||
634 | i2c_read(DA9063_I2C_ADDR, DA9063_REG_BPERI_CFG, 1, &val, 1); | |
635 | val &= ~DA9063_BUCK_MODE_MASK; | |
636 | val |= DA9063_BUCK_MODE_SYNC; | |
637 | i2c_write(DA9063_I2C_ADDR, DA9063_REG_BPERI_CFG, 1, &val, 1); | |
638 | } | |
639 | ||
f9162b15 AB |
640 | int board_late_init(void) |
641 | { | |
5e604e2c | 642 | process_vpd(&vpd); |
cf678b31 | 643 | |
f9162b15 AB |
644 | #ifdef CONFIG_CMD_BMODE |
645 | add_board_boot_modes(board_boot_modes); | |
646 | #endif | |
0c344e6e | 647 | |
06a3e438 IR |
648 | if (is_b850v3()) |
649 | env_set("videoargs", "video=DP-1:1024x768@60 video=HDMI-A-1:1024x768@60"); | |
9aa7c157 IR |
650 | else |
651 | env_set("videoargs", "video=LVDS-1:1024x768@65"); | |
06a3e438 | 652 | |
22d358da KL |
653 | /* board specific pmic init */ |
654 | pmic_init(); | |
655 | ||
886678fc NH |
656 | check_time(); |
657 | ||
f9162b15 AB |
658 | return 0; |
659 | } | |
660 | ||
2850645c HL |
661 | /* |
662 | * Removes the 'eth[0-9]*addr' environment variable with the given index | |
663 | * | |
664 | * @param index [in] the index of the eth_device whose variable is to be removed | |
665 | */ | |
666 | static void remove_ethaddr_env_var(int index) | |
667 | { | |
668 | char env_var_name[9]; | |
669 | ||
670 | sprintf(env_var_name, index == 0 ? "ethaddr" : "eth%daddr", index); | |
671 | env_set(env_var_name, NULL); | |
672 | } | |
673 | ||
cf678b31 MW |
674 | int last_stage_init(void) |
675 | { | |
2850645c HL |
676 | int i; |
677 | ||
678 | /* | |
679 | * Remove first three ethaddr which may have been created by | |
680 | * function process_vpd(). | |
681 | */ | |
682 | for (i = 0; i < 3; ++i) | |
683 | remove_ethaddr_env_var(i); | |
cf678b31 MW |
684 | |
685 | return 0; | |
686 | } | |
687 | ||
f9162b15 AB |
688 | int checkboard(void) |
689 | { | |
690 | printf("BOARD: %s\n", CONFIG_BOARD_NAME); | |
691 | return 0; | |
692 | } | |
6c0e6b45 | 693 | |
61c4c2bf IR |
694 | #ifdef CONFIG_OF_BOARD_SETUP |
695 | int ft_board_setup(void *blob, bd_t *bd) | |
696 | { | |
697 | fdt_setprop(blob, 0, "ge,boot-ver", version_string, | |
698 | strlen(version_string) + 1); | |
699 | return 0; | |
700 | } | |
701 | #endif | |
702 | ||
6c0e6b45 IR |
703 | static int do_backlight_enable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
704 | { | |
705 | #ifdef CONFIG_VIDEO_IPUV3 | |
706 | /* We need at least 200ms between power on and backlight on | |
707 | * as per specifications from CHI MEI */ | |
708 | mdelay(250); | |
709 | ||
710 | /* enable backlight PWM 1 */ | |
711 | pwm_init(0, 0, 0); | |
712 | ||
713 | /* duty cycle 5000000ns, period: 5000000ns */ | |
714 | pwm_config(0, 5000000, 5000000); | |
715 | ||
716 | /* Backlight Power */ | |
717 | gpio_direction_output(LVDS_BACKLIGHT_GP, 1); | |
718 | ||
719 | pwm_enable(0); | |
720 | #endif | |
721 | ||
722 | return 0; | |
723 | } | |
724 | ||
725 | U_BOOT_CMD( | |
726 | bx50_backlight_enable, 1, 1, do_backlight_enable, | |
727 | "enable Bx50 backlight", | |
728 | "" | |
729 | ); |