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