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
17DECLARE_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)
21static 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
26static 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
44int 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)
53static 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)
59static const iomux_cfg_t tpm0_pads[] = {
60	IMX8ULP_PAD_PTA3__TPM0_CH2 | MUX_PAD_CTRL(TPM_PAD_CTRL),
61};
62
63void 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
89void 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
102int 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
117int board_early_init_f(void)
118{
119	return 0;
120}
121
122int 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