blob: 924c88e8fab39a177d972631a6338734c855315f [file] [log] [blame]
Anatolij Gustschin49234a32020-01-07 16:37:42 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2017-2019 NXP
4 *
5 * Copyright 2019 Siemens AG
6 *
7 */
8#include <common.h>
Simon Glassed38aef2020-05-10 11:40:03 -06009#include <command.h>
Anatolij Gustschin49234a32020-01-07 16:37:42 +010010#include <dm.h>
Simon Glassed38aef2020-05-10 11:40:03 -060011#include <env.h>
Anatolij Gustschin49234a32020-01-07 16:37:42 +010012#include <errno.h>
Simon Glass97589732020-05-10 11:40:02 -060013#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Anatolij Gustschin49234a32020-01-07 16:37:42 +010015#include <netdev.h>
16#include <env_internal.h>
17#include <fsl_esdhc_imx.h>
18#include <i2c.h>
19#include <led.h>
20#include <pca953x.h>
21#include <power-domain.h>
22#include <asm/gpio.h>
23#include <asm/arch/imx8-pins.h>
24#include <asm/arch/iomux.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080025#include <firmware/imx/sci/sci.h>
Anatolij Gustschin49234a32020-01-07 16:37:42 +010026#include <asm/arch/sys_proto.h>
27#ifndef CONFIG_SPL
28#include <asm/arch-imx8/clock.h>
29#endif
Simon Glassdbd79542020-05-10 11:40:11 -060030#include <linux/delay.h>
Anatolij Gustschin49234a32020-01-07 16:37:42 +010031#include "../common/factoryset.h"
32
33#define GPIO_PAD_CTRL \
34 ((SC_PAD_CONFIG_NORMAL << PADRING_CONFIG_SHIFT) | \
35 (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
36 (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT) | \
37 (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
38
39#define ENET_NORMAL_PAD_CTRL \
40 ((SC_PAD_CONFIG_NORMAL << PADRING_CONFIG_SHIFT) | \
41 (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
42 (SC_PAD_28FDSOI_DSE_18V_10MA << PADRING_DSE_SHIFT) | \
43 (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
44
45#define UART_PAD_CTRL \
46 ((SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
47 (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
48 (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT) | \
49 (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
50
51static iomux_cfg_t uart2_pads[] = {
52 SC_P_UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
53 SC_P_UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
54};
55
56static void setup_iomux_uart(void)
57{
58 imx8_iomux_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
59}
60
61int board_early_init_f(void)
62{
63 /* Set UART clock root to 80 MHz */
64 sc_pm_clock_rate_t rate = SC_80MHZ;
65 int ret;
66
67 ret = sc_pm_setup_uart(SC_R_UART_0, rate);
68 ret |= sc_pm_setup_uart(SC_R_UART_2, rate);
69 if (ret)
70 return ret;
71
72 setup_iomux_uart();
73
74 return 0;
75}
76
77#define ENET_PHY_RESET IMX_GPIO_NR(0, 3)
78#define ENET_TEST_1 IMX_GPIO_NR(0, 8)
79#define ENET_TEST_2 IMX_GPIO_NR(0, 9)
80
81/*#define ETH_IO_TEST*/
82static iomux_cfg_t enet_reset[] = {
83 SC_P_ESAI0_SCKT | MUX_MODE_ALT(4) | MUX_PAD_CTRL(GPIO_PAD_CTRL),
84#ifdef ETH_IO_TEST
85 /* GPIO0.IO08 MODE3: TXD0 */
86 SC_P_ESAI0_TX4_RX1 | MUX_MODE_ALT(4) |
87 MUX_PAD_CTRL(ENET_NORMAL_PAD_CTRL),
88 /* GPIO0.IO09 MODE3: TXD1 */
89 SC_P_ESAI0_TX5_RX0 | MUX_MODE_ALT(4) |
90 MUX_PAD_CTRL(ENET_NORMAL_PAD_CTRL),
91#endif
92};
93
94static void enet_device_phy_reset(void)
95{
96 int ret = 0;
97
98 imx8_iomux_setup_multiple_pads(enet_reset, ARRAY_SIZE(enet_reset));
99
100 ret = gpio_request(ENET_PHY_RESET, "enet_phy_reset");
101 if (!ret) {
102 gpio_direction_output(ENET_PHY_RESET, 1);
103 gpio_set_value(ENET_PHY_RESET, 0);
104 /* SMSC9303 TRM chapter 14.5.2 */
105 udelay(200);
106 gpio_set_value(ENET_PHY_RESET, 1);
107 } else {
108 printf("ENET RESET failed!\n");
109 }
110
111#ifdef ETH_IO_TEST
112 ret = gpio_request(ENET_TEST_1, "enet_test1");
113 if (!ret) {
114 int i;
115
116 printf("ENET TEST 1!\n");
117 for (i = 0; i < 20; i++) {
118 gpio_direction_output(ENET_TEST_1, 1);
119 gpio_set_value(ENET_TEST_1, 0);
120 udelay(50);
121 gpio_set_value(ENET_TEST_1, 1);
122 udelay(50);
123 }
124 gpio_free(ENET_TEST_1);
125 } else {
126 printf("GPIO for ENET TEST 1 failed!\n");
127 }
128 ret = gpio_request(ENET_TEST_2, "enet_test2");
129 if (!ret) {
130 int i;
131
132 printf("ENET TEST 2!\n");
133 for (i = 0; i < 20; i++) {
134 gpio_direction_output(ENET_TEST_2, 1);
135 gpio_set_value(ENET_TEST_2, 0);
136 udelay(50);
137 gpio_set_value(ENET_TEST_2, 1);
138 udelay(50);
139 }
140 gpio_free(ENET_TEST_2);
141 } else {
142 printf("GPIO for ENET TEST 2 failed!\n");
143 }
144#endif
145}
146
147int setup_gpr_fec(void)
148{
149 sc_ipc_t ipc_handle = -1;
Peng Fan6d96f002023-06-15 18:09:01 +0800150 int err = 0;
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100151 unsigned int test;
152
153 /*
154 * TX_CLK_SEL: it controls a mux between clock coming from the pad 50M
155 * input pin and clock generated internally to connectivity subsystem
156 * 0: internal clock
157 * 1: external clock ---> your choice for RMII
158 *
159 * CLKDIV_SEL: it controls a div by 2 on the internal clock path à
160 * it should be don’t care when using external clock
161 * 0: non-divided clock
162 * 1: clock divided by 2
163 * 50_DISABLE or 125_DISABLE:
164 * it’s used to disable the clock tree going outside the chip
165 * when reference clock is generated internally.
166 * It should be don’t care when reference clock is provided
167 * externally.
168 * 0: clock is enabled
169 * 1: clock is disabled
170 *
171 * SC_C_TXCLK = 24,
172 * SC_C_CLKDIV = 25,
173 * SC_C_DISABLE_50 = 26,
174 * SC_C_DISABLE_125 = 27,
175 */
176
177 err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, 1);
Peng Fan6d96f002023-06-15 18:09:01 +0800178 if (err)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100179 printf("Error in setting up SC_C %d\n\r", SC_C_TXCLK);
180
181 sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test);
182 debug("TEST SC_C %d-->%d\n\r", SC_C_TXCLK, test);
183
184 err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_CLKDIV, 0);
Peng Fan6d96f002023-06-15 18:09:01 +0800185 if (err)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100186 printf("Error in setting up SC_C %d\n\r", SC_C_CLKDIV);
187
188 sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_CLKDIV, &test);
189 debug("TEST SC_C %d-->%d\n\r", SC_C_CLKDIV, test);
190
191 err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_DISABLE_50, 0);
Peng Fan6d96f002023-06-15 18:09:01 +0800192 if (err)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100193 printf("Error in setting up SC_C %d\n\r", SC_C_DISABLE_50);
194
195 sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test);
196 debug("TEST SC_C %d-->%d\n\r", SC_C_DISABLE_50, test);
197
198 err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_DISABLE_125, 1);
Peng Fan6d96f002023-06-15 18:09:01 +0800199 if (err)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100200 printf("Error in setting up SC_C %d\n\r", SC_C_DISABLE_125);
201
202 sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_TXCLK, &test);
203 debug("TEST SC_C %d-->%d\n\r", SC_C_DISABLE_125, test);
204
205 err = sc_misc_set_control(ipc_handle, SC_R_ENET_1, SC_C_SEL_125, 1);
Peng Fan6d96f002023-06-15 18:09:01 +0800206 if (err)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100207 printf("Error in setting up SC_C %d\n\r", SC_C_SEL_125);
208
209 sc_misc_get_control(ipc_handle, SC_R_ENET_1, SC_C_SEL_125, &test);
210 debug("TEST SC_C %d-->%d\n\r", SC_C_SEL_125, test);
211
212 return 0;
213}
214
215#if IS_ENABLED(CONFIG_FEC_MXC)
216#include <miiphy.h>
217int board_phy_config(struct phy_device *phydev)
218{
219 if (phydev->drv->config)
220 phydev->drv->config(phydev);
221
222 return 0;
223}
224
225#endif
226
227static int setup_fec(void)
228{
229 setup_gpr_fec();
230 /* Reset ENET PHY */
231 enet_device_phy_reset();
232 return 0;
233}
234
Harald Seiler6f14d5f2020-12-15 16:47:52 +0100235void reset_cpu(void)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100236{
237}
238
239#ifndef CONFIG_SPL_BUILD
240/* LED's */
241static int board_led_init(void)
242{
243 struct udevice *bus, *dev;
244 u8 pca_led[2] = { 0x00, 0x00 };
245 int ret;
246
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100247 /* enable all leds on PCA9552 */
248 ret = uclass_get_device_by_seq(UCLASS_I2C, PCA9552_1_I2C_BUS, &bus);
249 if (ret) {
250 printf("ERROR: I2C get %d\n", ret);
251 return ret;
252 }
253
254 ret = dm_i2c_probe(bus, PCA9552_1_I2C_ADDR, 0, &dev);
255 if (ret) {
256 printf("ERROR: PCA9552 probe failed\n");
257 return ret;
258 }
259
260 ret = dm_i2c_write(dev, 0x16, pca_led, sizeof(pca_led));
261 if (ret) {
262 printf("ERROR: PCA9552 write failed\n");
263 return ret;
264 }
265
266 mdelay(1);
267 return ret;
268}
269#endif /* !CONFIG_SPL_BUILD */
270
271int checkboard(void)
272{
273 puts("Board: Capricorn\n");
274
275 /*
276 * Running build_info() doesn't work with current SCFW blob.
277 * Uncomment below call when new blob is available.
278 */
279 /*build_info();*/
280
281 print_bootinfo();
282 return 0;
283}
284
285int board_init(void)
286{
287 setup_fec();
288 return 0;
289}
290
291#ifdef CONFIG_OF_BOARD_SETUP
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900292int ft_board_setup(void *blob, struct bd_info *bd)
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100293{
294 return 0;
295}
296#endif
297
298int board_mmc_get_env_dev(int devno)
299{
300 return devno;
301}
302
303static int check_mmc_autodetect(void)
304{
305 char *autodetect_str = env_get("mmcautodetect");
306
307 if (autodetect_str && (strcmp(autodetect_str, "yes") == 0))
308 return 1;
309
310 return 0;
311}
312
313/* This should be defined for each board */
314__weak int mmc_map_to_kernel_blk(int dev_no)
315{
316 return dev_no;
317}
318
319void board_late_mmc_env_init(void)
320{
321 char cmd[32];
322 char mmcblk[32];
323 u32 dev_no = mmc_get_env_dev();
324
325 if (!check_mmc_autodetect())
326 return;
327
328 env_set_ulong("mmcdev", dev_no);
329
330 /* Set mmcblk env */
331 sprintf(mmcblk, "/dev/mmcblk%dp2 rootwait rw",
332 mmc_map_to_kernel_blk(dev_no));
333 env_set("mmcroot", mmcblk);
334
335 sprintf(cmd, "mmc dev %d", dev_no);
336 run_command(cmd, 0);
337}
338
339#ifndef CONFIG_SPL_BUILD
340int factoryset_read_eeprom(int i2c_addr);
341
342static int load_parameters_from_factoryset(void)
343{
344 int ret;
345
346 ret = factoryset_read_eeprom(EEPROM_I2C_ADDR);
347 if (ret)
348 return ret;
349
350 return factoryset_env_set();
351}
352
353int board_late_init(void)
354{
355 env_set("sec_boot", "no");
356#ifdef CONFIG_AHAB_BOOT
357 env_set("sec_boot", "yes");
358#endif
359
360#ifdef CONFIG_ENV_IS_IN_MMC
361 board_late_mmc_env_init();
362#endif
363 /* Init LEDs */
364 if (board_led_init())
365 printf("I2C LED init failed\n");
366
367 /* Set environment from factoryset */
368 if (load_parameters_from_factoryset())
369 printf("Loading factoryset parameters failed!\n");
370
371 return 0;
372}
373
374/* Service button */
375#define MAX_PIN_NUMBER 128
376#define BOARD_DEFAULT_BUTTON_GPIO IMX_GPIO_NR(1, 31)
377
378unsigned char get_button_state(char * const envname, unsigned char def)
379{
380 int button = 0;
381 int gpio;
382 char *ptr_env;
383
384 /* If button is not found we take default */
385 ptr_env = env_get(envname);
386 if (!ptr_env) {
387 printf("Using default: %u\n", def);
388 gpio = def;
389 } else {
390 gpio = (unsigned char)simple_strtoul(ptr_env, NULL, 0);
391 if (gpio > MAX_PIN_NUMBER)
392 gpio = def;
393 }
394
395 gpio_request(gpio, "");
396 gpio_direction_input(gpio);
397 if (gpio_get_value(gpio))
398 button = 1;
399 else
400 button = 0;
401
402 gpio_free(gpio);
403
404 return button;
405}
406
407/*
408 * This command returns the status of the user button on
409 * Input - none
410 * Returns - 1 if button is held down
411 * 0 if button is not held down
412 */
413static int
Simon Glassed38aef2020-05-10 11:40:03 -0600414do_userbutton(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100415{
416 int button = 0;
417
418 button = get_button_state("button_usr1", BOARD_DEFAULT_BUTTON_GPIO);
419
420 if (argc > 1)
421 printf("Button state: %u\n", button);
422
423 return button;
424}
425
426U_BOOT_CMD(
427 usrbutton, CONFIG_SYS_MAXARGS, 2, do_userbutton,
428 "Return the status of user button",
429 "[print]"
430);
431
432#define ERST IMX_GPIO_NR(0, 3)
433
434static int
Simon Glassed38aef2020-05-10 11:40:03 -0600435do_eth_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Anatolij Gustschin49234a32020-01-07 16:37:42 +0100436{
437 gpio_request(ERST, "ERST");
438 gpio_direction_output(ERST, 0);
439 udelay(200);
440 gpio_set_value(ERST, 1);
441 return 0;
442}
443
444U_BOOT_CMD(
445 switch_rst, CONFIG_SYS_MAXARGS, 2, do_eth_reset,
446 "Reset eth phy",
447 "[print]"
448);
449#endif /* ! CONFIG_SPL_BUILD */