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