1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2017-2019 NXP
4  *
5  * Copyright 2019 Siemens AG
6  *
7  */
8 #include <common.h>
9 #include <command.h>
10 #include <dm.h>
11 #include <env.h>
12 #include <errno.h>
13 #include <init.h>
14 #include <log.h>
15 #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>
25 #include <firmware/imx/sci/sci.h>
26 #include <asm/arch/sys_proto.h>
27 #ifndef CONFIG_SPL
28 #include <asm/arch-imx8/clock.h>
29 #endif
30 #include <linux/delay.h>
31 #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 
51 static 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 
setup_iomux_uart(void)56 static void setup_iomux_uart(void)
57 {
58 	imx8_iomux_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
59 }
60 
board_early_init_f(void)61 int 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*/
82 static 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 
enet_device_phy_reset(void)94 static 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 
setup_gpr_fec(void)147 int setup_gpr_fec(void)
148 {
149 	sc_ipc_t ipc_handle = -1;
150 	sc_err_t err = 0;
151 	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);
178 	if (err != SC_ERR_NONE)
179 		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);
185 	if (err != SC_ERR_NONE)
186 		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);
192 	if (err != SC_ERR_NONE)
193 		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);
199 	if (err != SC_ERR_NONE)
200 		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);
206 	if (err != SC_ERR_NONE)
207 		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>
board_phy_config(struct phy_device * phydev)217 int 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 
setup_fec(void)227 static int setup_fec(void)
228 {
229 	setup_gpr_fec();
230 	/* Reset ENET PHY */
231 	enet_device_phy_reset();
232 	return 0;
233 }
234 
reset_cpu(void)235 void reset_cpu(void)
236 {
237 }
238 
239 #ifndef CONFIG_SPL_BUILD
240 /* LED's */
board_led_init(void)241 static int board_led_init(void)
242 {
243 	struct udevice *bus, *dev;
244 	u8 pca_led[2] = { 0x00, 0x00 };
245 	int ret;
246 
247 	/* 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 
checkboard(void)271 int 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 
board_init(void)285 int board_init(void)
286 {
287 	setup_fec();
288 	return 0;
289 }
290 
291 #ifdef CONFIG_OF_BOARD_SETUP
ft_board_setup(void * blob,struct bd_info * bd)292 int ft_board_setup(void *blob, struct bd_info *bd)
293 {
294 	return 0;
295 }
296 #endif
297 
board_mmc_get_env_dev(int devno)298 int board_mmc_get_env_dev(int devno)
299 {
300 	return devno;
301 }
302 
check_mmc_autodetect(void)303 static 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 */
mmc_map_to_kernel_blk(int dev_no)314 __weak int mmc_map_to_kernel_blk(int dev_no)
315 {
316 	return dev_no;
317 }
318 
board_late_mmc_env_init(void)319 void 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
340 int factoryset_read_eeprom(int i2c_addr);
341 
load_parameters_from_factoryset(void)342 static 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 
board_late_init(void)353 int 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 
get_button_state(char * const envname,unsigned char def)378 unsigned 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  */
413 static int
do_userbutton(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])414 do_userbutton(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
415 {
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 
426 U_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 
434 static int
do_eth_reset(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])435 do_eth_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
436 {
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 
444 U_BOOT_CMD(
445 	switch_rst, CONFIG_SYS_MAXARGS, 2, do_eth_reset,
446 	"Reset eth phy",
447 	"[print]"
448 );
449 #endif /* ! CONFIG_SPL_BUILD */
450