1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2020 NXP
4  */
5 
6 #include <common.h>
7 #include <miiphy.h>
8 #include <netdev.h>
9 #include <asm/arch/imx8ulp-pins.h>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/pcc.h>
12 #include <asm/arch/sys_proto.h>
13 #include <miiphy.h>
14 #include <netdev.h>
15 #include <asm/gpio.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 #if IS_ENABLED(CONFIG_FEC_MXC)
20 #define ENET_CLK_PAD_CTRL	(PAD_CTL_PUS_UP | PAD_CTL_DSE | PAD_CTL_IBE_ENABLE)
21 static iomux_cfg_t const enet_clk_pads[] = {
22 	IMX8ULP_PAD_PTE19__ENET0_REFCLK | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
23 	IMX8ULP_PAD_PTF10__ENET0_1588_CLKIN | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
24 };
25 
setup_fec(void)26 static int setup_fec(void)
27 {
28 	/*
29 	 * Since ref clock and timestamp clock are from external,
30 	 * set the iomux prior the clock enablement
31 	 */
32 	imx8ulp_iomux_setup_multiple_pads(enet_clk_pads, ARRAY_SIZE(enet_clk_pads));
33 
34 	/* Select enet time stamp clock: 001 - External Timestamp Clock */
35 	cgc1_enet_stamp_sel(1);
36 
37 	/* enable FEC PCC */
38 	pcc_clock_enable(4, ENET_PCC4_SLOT, true);
39 	pcc_reset_peripheral(4, ENET_PCC4_SLOT, false);
40 
41 	return 0;
42 }
43 
board_phy_config(struct phy_device * phydev)44 int board_phy_config(struct phy_device *phydev)
45 {
46 	if (phydev->drv->config)
47 		phydev->drv->config(phydev);
48 	return 0;
49 }
50 #endif
51 
52 #define I2C_PAD_CTRL	(PAD_CTL_ODE)
53 static const iomux_cfg_t lpi2c0_pads[] = {
54 	IMX8ULP_PAD_PTA8__LPI2C0_SCL | MUX_PAD_CTRL(I2C_PAD_CTRL),
55 	IMX8ULP_PAD_PTA9__LPI2C0_SDA | MUX_PAD_CTRL(I2C_PAD_CTRL),
56 };
57 
58 #define TPM_PAD_CTRL	(PAD_CTL_DSE)
59 static const iomux_cfg_t tpm0_pads[] = {
60 	IMX8ULP_PAD_PTA3__TPM0_CH2 | MUX_PAD_CTRL(TPM_PAD_CTRL),
61 };
62 
mipi_dsi_mux_panel(void)63 void mipi_dsi_mux_panel(void)
64 {
65 	int ret;
66 	struct gpio_desc desc;
67 
68 	/* It is temp solution to directly access i2c, need change to rpmsg later */
69 
70 	/* enable lpi2c0 clock and iomux */
71 	imx8ulp_iomux_setup_multiple_pads(lpi2c0_pads, ARRAY_SIZE(lpi2c0_pads));
72 	writel(0xD2000000, 0x28091060);
73 
74 	ret = dm_gpio_lookup_name("gpio@20_9", &desc);
75 	if (ret) {
76 		printf("%s lookup gpio@20_9 failed ret = %d\n", __func__, ret);
77 		return;
78 	}
79 
80 	ret = dm_gpio_request(&desc, "dsi_mux");
81 	if (ret) {
82 		printf("%s request dsi_mux failed ret = %d\n", __func__, ret);
83 		return;
84 	}
85 
86 	dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
87 }
88 
mipi_dsi_panel_backlight(void)89 void mipi_dsi_panel_backlight(void)
90 {
91 	/* It is temp solution to directly access pwm, need change to rpmsg later */
92 	imx8ulp_iomux_setup_multiple_pads(tpm0_pads, ARRAY_SIZE(tpm0_pads));
93 	writel(0xD4000001, 0x28091054);
94 
95 	/* Use center-aligned PWM mode, CPWMS=1, MSnB:MSnA = 10, ELSnB:ELSnA = 00 */
96 	writel(1000, 0x28095018);
97 	writel(1000, 0x28095034); /* MOD = CV, full duty */
98 	writel(0x28, 0x28095010);
99 	writel(0x20, 0x28095030);
100 }
101 
board_init(void)102 int board_init(void)
103 {
104 
105 	if (IS_ENABLED(CONFIG_FEC_MXC))
106 		setup_fec();
107 
108 	/* When sync with M33 is failed, use local driver to set for video */
109 	if (!is_m33_handshake_necessary() && IS_ENABLED(CONFIG_VIDEO)) {
110 		mipi_dsi_mux_panel();
111 		mipi_dsi_panel_backlight();
112 	}
113 
114 	return 0;
115 }
116 
board_early_init_f(void)117 int board_early_init_f(void)
118 {
119 	return 0;
120 }
121 
board_late_init(void)122 int board_late_init(void)
123 {
124 	ulong addr;
125 
126 #if CONFIG_IS_ENABLED(ENV_IS_IN_MMC)
127 	board_late_mmc_env_init();
128 #endif
129 
130 	/* clear fdtaddr to avoid obsolete data */
131 	addr = env_get_hex("fdt_addr_r", 0);
132 	if (addr)
133 		memset((void *)addr, 0, 0x400);
134 
135 	return 0;
136 }
137