// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2022 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include "../common/tcpc.h" #include #include #include #include DECLARE_GLOBAL_DATA_PTR; #define UART_PAD_CTRL (PAD_CTL_DSE(6) | PAD_CTL_FSEL2) #define WDOG_PAD_CTRL (PAD_CTL_DSE(6) | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE) static iomux_v3_cfg_t const uart_pads[] = { MX93_PAD_UART1_RXD__LPUART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL), MX93_PAD_UART1_TXD__LPUART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL), }; int board_early_init_f(void) { imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads)); init_uart_clk(LPUART1_CLK_ROOT); return 0; } #ifdef CONFIG_USB_TCPC struct tcpc_port port1; struct tcpc_port port2; struct tcpc_port portpd; static int setup_pd_switch(uint8_t i2c_bus, uint8_t addr) { struct udevice *bus; struct udevice *i2c_dev = NULL; int ret; uint8_t valb; ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus); if (ret) { printf("%s: Can't find bus\n", __func__); return -EINVAL; } ret = dm_i2c_probe(bus, addr, 0, &i2c_dev); if (ret) { printf("%s: Can't find device id=0x%x\n", __func__, addr); return -ENODEV; } ret = dm_i2c_read(i2c_dev, 0xB, &valb, 1); if (ret) { printf("%s dm_i2c_read failed, err %d\n", __func__, ret); return -EIO; } valb |= 0x4; /* Set DB_EXIT to exit dead battery mode */ ret = dm_i2c_write(i2c_dev, 0xB, (const uint8_t *)&valb, 1); if (ret) { printf("%s dm_i2c_write failed, err %d\n", __func__, ret); return -EIO; } /* Set OVP threshold to 23V */ valb = 0x6; ret = dm_i2c_write(i2c_dev, 0x8, (const uint8_t *)&valb, 1); if (ret) { printf("%s dm_i2c_write failed, err %d\n", __func__, ret); return -EIO; } return 0; } int pd_switch_snk_enable(struct tcpc_port *port) { if (port == &port1) { debug("Setup pd switch on port 1\n"); return setup_pd_switch(2, 0x71); } else if (port == &port2) { debug("Setup pd switch on port 2\n"); return setup_pd_switch(2, 0x73); } else return -EINVAL; } struct tcpc_port_config portpd_config = { .i2c_bus = 2, /*i2c3*/ .addr = 0x52, .port_type = TYPEC_PORT_UFP, .max_snk_mv = 20000, .max_snk_ma = 3000, .max_snk_mw = 15000, .op_snk_mv = 9000, }; struct tcpc_port_config port1_config = { .i2c_bus = 2, /*i2c3*/ .addr = 0x50, .port_type = TYPEC_PORT_UFP, .max_snk_mv = 5000, .max_snk_ma = 3000, .max_snk_mw = 40000, .op_snk_mv = 9000, .switch_setup_func = &pd_switch_snk_enable, .disable_pd = true, }; struct tcpc_port_config port2_config = { .i2c_bus = 2, /*i2c3*/ .addr = 0x51, .port_type = TYPEC_PORT_UFP, .max_snk_mv = 9000, .max_snk_ma = 3000, .max_snk_mw = 40000, .op_snk_mv = 9000, .switch_setup_func = &pd_switch_snk_enable, .disable_pd = true, }; static int setup_typec(void) { int ret; debug("tcpc_init port pd\n"); ret = tcpc_init(&portpd, portpd_config, NULL); if (ret) { printf("%s: tcpc portpd init failed, err=%d\n", __func__, ret); } debug("tcpc_init port 2\n"); ret = tcpc_init(&port2, port2_config, NULL); if (ret) { printf("%s: tcpc port2 init failed, err=%d\n", __func__, ret); } debug("tcpc_init port 1\n"); ret = tcpc_init(&port1, port1_config, NULL); if (ret) { printf("%s: tcpc port1 init failed, err=%d\n", __func__, ret); } return ret; } int board_usb_init(int index, enum usb_init_type init) { int ret = 0; struct tcpc_port *port_ptr; debug("board_usb_init %d, type %d\n", index, init); if (index == 0) port_ptr = &port1; else port_ptr = &port2; if (init == USB_INIT_HOST) tcpc_setup_dfp_mode(port_ptr); else tcpc_setup_ufp_mode(port_ptr); return ret; } int board_usb_cleanup(int index, enum usb_init_type init) { int ret = 0; debug("board_usb_cleanup %d, type %d\n", index, init); if (init == USB_INIT_HOST) { if (index == 0) ret = tcpc_disable_src_vbus(&port1); else ret = tcpc_disable_src_vbus(&port2); } return ret; } int board_ehci_usb_phy_mode(struct udevice *dev) { int ret = 0; enum typec_cc_polarity pol; enum typec_cc_state state; struct tcpc_port *port_ptr; debug("%s %d\n", __func__, dev_seq(dev)); if (dev_seq(dev) == 0) port_ptr = &port1; else port_ptr = &port2; tcpc_setup_ufp_mode(port_ptr); ret = tcpc_get_cc_status(port_ptr, &pol, &state); tcpc_print_log(port_ptr); if (!ret) { if (state == TYPEC_STATE_SRC_RD_RA || state == TYPEC_STATE_SRC_RD) return USB_INIT_HOST; } return USB_INIT_DEVICE; } #endif static int setup_fec(void) { return set_clk_enet(ENET_125MHZ); } int board_phy_config(struct phy_device *phydev) { if (phydev->drv->config) phydev->drv->config(phydev); return 0; } static int setup_eqos(void) { struct blk_ctrl_wakeupmix_regs *bctrl = (struct blk_ctrl_wakeupmix_regs *)BLK_CTRL_WAKEUPMIX_BASE_ADDR; /* set INTF as RGMII, enable RGMII TXC clock */ clrsetbits_le32(&bctrl->eqos_gpr, BCTRL_GPR_ENET_QOS_INTF_MODE_MASK, BCTRL_GPR_ENET_QOS_INTF_SEL_RGMII | BCTRL_GPR_ENET_QOS_CLK_GEN_EN); return set_clk_eqos(ENET_125MHZ); } int board_init(void) { #ifdef CONFIG_USB_TCPC setup_typec(); #endif if (CONFIG_IS_ENABLED(FEC_MXC)) setup_fec(); if (CONFIG_IS_ENABLED(DWC_ETH_QOS)) setup_eqos(); return 0; } int board_late_init(void) { #ifdef CONFIG_ENV_IS_IN_MMC board_late_mmc_env_init(); #endif env_set("sec_boot", "no"); #ifdef CONFIG_AHAB_BOOT env_set("sec_boot", "yes"); #endif #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG env_set("board_name", "11X11_EVK"); env_set("board_rev", "iMX93"); #endif return 0; }