/* * board.c * * Board functions for TI AM335X based boards * * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "board_descriptor.h" #include "board.h" DECLARE_GLOBAL_DATA_PTR; /* GPIO that controls power to DDR on EVM-SK */ #define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) #define GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 7) #define ICE_GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 18) #define GPIO_PR1_MII_CTRL GPIO_TO_PIN(3, 4) #define GPIO_MUX_MII_CTRL GPIO_TO_PIN(3, 10) #define GPIO_FET_SWITCH_CTRL GPIO_TO_PIN(0, 7) #define GPIO_PHY_RESET GPIO_TO_PIN(2, 5) #define NETBIRD_GPIO_RST_PHY_N GPIO_TO_PIN(0, 16) #define NETBIRD_GPIO_PWR_GSM GPIO_TO_PIN(1, 22) #define NETBIRD_GPIO_RST_GSM GPIO_TO_PIN(1, 24) #define NETBIRD_GPIO_WLAN_EN GPIO_TO_PIN(3, 10) #define NETBIRD_GPIO_BT_EN GPIO_TO_PIN(3, 4) #define NETBIRD_GPIO_EN_GPS_ANT GPIO_TO_PIN(2, 24) #define NETBIRD_GPIO_LED_A GPIO_TO_PIN(1, 14) #define NETBIRD_GPIO_LED_B GPIO_TO_PIN(1, 15) #if defined(CONFIG_SPL_BUILD) || \ (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_DM_ETH)) static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; #endif /* * Read header information from EEPROM into global structure. */ static inline int __maybe_unused read_eeprom(void) { return bd_read(-1, CONFIG_SYS_I2C_EEPROM_ADDR); } struct serial_device *default_serial_console(void) { return &eserial1_device; } #ifndef CONFIG_SKIP_LOWLEVEL_INIT static const struct ddr_data ddr3_netbird_data = { /* Ratios were optimized by DDR3 training software from TI */ .datardsratio0 = 0x37, .datawdsratio0 = 0x42, .datafwsratio0 = 0x98, .datawrsratio0 = 0x7a, }; static const struct cmd_control ddr3_netbird_cmd_ctrl_data = { .cmd0csratio = MT41K256M16HA125E_RATIO, .cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT, .cmd1csratio = MT41K256M16HA125E_RATIO, .cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT, .cmd2csratio = MT41K256M16HA125E_RATIO, .cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT, }; static struct emif_regs ddr3_netbird_emif_reg_data = { .sdram_config = MT41K256M16HA125E_EMIF_SDCFG, .ref_ctrl = MT41K256M16HA125E_EMIF_SDREF, .sdram_tim1 = 0x0aaae51b, /* From AM335x_DDR_register_calc_tool.xls */ .sdram_tim2 = 0x24437fda, /* From AM335x_DDR_register_calc_tool.xls */ .sdram_tim3 = 0x50ffe3ff, /* From AM335x_DDR_register_calc_tool.xls */ .zq_config = MT41K256M16HA125E_ZQ_CFG, .emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY, }; #ifdef CONFIG_SPL_OS_BOOT int spl_start_uboot(void) { /* break into full u-boot on 'c' */ if (serial_tstc() && serial_getc() == 'c') return 1; #ifdef CONFIG_SPL_ENV_SUPPORT env_init(); env_relocate_spec(); if (getenv_yesno("boot_os") != 1) return 1; #endif return 0; } #endif #define OSC (V_OSCK/1000000) const struct dpll_params dpll_ddr_nbhw16= { 400, OSC-1, 1, -1, -1, -1, -1}; void am33xx_spl_board_init(void) { /* Get the frequency */ dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev); /* Set CPU speed to 600 MHZ */ dpll_mpu_opp100.m = MPUPLL_M_600; /* Set CORE Frequencies to OPP100 */ do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); /* Clear th PFM Flag on DCDC4 */ if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_DCDC4, 0x00, 0x80)) { puts ("tps65218_reg_write failure\n"); }; /* Set MPU Frequency to what we detected now that voltages are set */ do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); if (read_eeprom() < 0) puts("Could not get board ID.\n"); } const struct dpll_params *get_dpll_ddr_params(void) { return &dpll_ddr_nbhw16; } void set_uart_mux_conf(void) { enable_uart0_pin_mux(); } void set_mux_conf_regs(void) { enable_board_pin_mux(); } const struct ctrl_ioregs ioregs_netbird = { .cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, .cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, .cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE, .dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, .dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, }; void sdram_init(void) { config_ddr(400, &ioregs_netbird, &ddr3_netbird_data, &ddr3_netbird_cmd_ctrl_data, &ddr3_netbird_emif_reg_data, 0); } #endif static void request_and_set_gpio(int gpio, char *name, int value) { int ret; ret = gpio_request(gpio, name); if (ret < 0) { printf("%s: Unable to request %s\n", __func__, name); return; } ret = gpio_direction_output(gpio, 0); if (ret < 0) { printf("%s: Unable to set %s as output\n", __func__, name); goto err_free_gpio; } gpio_set_value(gpio, value); return; err_free_gpio: gpio_free(gpio); } #define REQUEST_AND_SET_GPIO(N) request_and_set_gpio(N, #N, 1); #define REQUEST_AND_CLEAR_GPIO(N) request_and_set_gpio(N, #N, 0); /* * Basic board specific setup. Pinmux has been handled already. */ int board_init(void) { #if defined(CONFIG_HW_WATCHDOG) hw_watchdog_init(); #endif gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; #if defined(CONFIG_NOR) || defined(CONFIG_NAND) gpmc_init(); #endif REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_RST_GSM); udelay(10000); REQUEST_AND_SET_GPIO(NETBIRD_GPIO_PWR_GSM); mdelay(1200); gpio_set_value(NETBIRD_GPIO_PWR_GSM, 0); REQUEST_AND_SET_GPIO(NETBIRD_GPIO_LED_A); REQUEST_AND_SET_GPIO(NETBIRD_GPIO_RST_PHY_N); REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_WLAN_EN); REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_BT_EN); /* There are two funcions on the same mux mode for MMC2_DAT7 we want * to use RMII2_CRS_DV so we need to set SMA2 Register to 1 * See SPRS717J site 49 (10)*/ #define SMA2_REGISTER (CTRL_BASE + 0x1320) writel(0x01, SMA2_REGISTER); /* Select RMII2_CRS_DV instead of MMC2_DAT7 */ return 0; } #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG int rc; char *name = NULL; set_board_info_env(name); #endif return 0; } #endif #ifndef CONFIG_DM_ETH #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) static void cpsw_control(int enabled) { /* VTP can be added here */ return; } static struct cpsw_slave_data cpsw_slaves[] = { { .slave_reg_ofs = 0x208, .sliver_reg_ofs = 0xd80, .phy_addr = 0, }, { .slave_reg_ofs = 0x308, .sliver_reg_ofs = 0xdc0, .phy_addr = 1, }, }; static struct cpsw_platform_data cpsw_data = { .mdio_base = CPSW_MDIO_BASE, .cpsw_base = CPSW_BASE, .mdio_div = 0xff, .channels = 8, .cpdma_reg_ofs = 0x800, .slaves = 1, .slave_data = cpsw_slaves, .ale_reg_ofs = 0xd00, .ale_entries = 1024, .host_port_reg_ofs = 0x108, .hw_stats_reg_ofs = 0x900, .bd_ram_ofs = 0x2000, .mac_control = (1 << 5), .control = cpsw_control, .host_port_num = 0, .version = CPSW_CTRL_VERSION_2, }; #endif #if ((defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USBETH_SUPPORT)) &&\ defined(CONFIG_SPL_BUILD)) || \ ((defined(CONFIG_DRIVER_TI_CPSW) || \ defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) && \ !defined(CONFIG_SPL_BUILD)) static void set_mac_address(int index, uchar mac[6]) { /* Then take mac from bd */ if (is_valid_ethaddr(mac)) { eth_setenv_enetaddr_by_index("eth", index, mac); } else { printf("Trying to set invalid MAC address"); } } /* * This function will: * Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr * in the environment * Perform fixups to the PHY present on certain boards. We only need this * function in: * - SPL with either CPSW or USB ethernet support * - Full U-Boot, with either CPSW or USB ethernet * Build in only these cases to avoid warnings about unused variables * when we build an SPL that has neither option but full U-Boot will. */ int board_eth_init(bd_t *bis) { int rv, n = 0; uint8_t mac_addr0[6] = {02,00,00,00,00,01}; uint8_t mac_addr1[6] = {02,00,00,00,00,02}; __maybe_unused struct ti_am_eeprom *header; int boot_partition; #if !defined(CONFIG_SPL_BUILD) #ifdef CONFIG_DRIVER_TI_CPSW cpsw_data.mdio_div = 0x3E; if (read_eeprom() < 0) puts("Could not get board ID.\n"); bd_get_mac_address(0, mac_addr0, sizeof(mac_addr0)); set_mac_address(0, mac_addr0); bd_get_mac_address(1, mac_addr1, sizeof(mac_addr1)); set_mac_address(1, mac_addr1); boot_partition = bd_get_boot_partition(); if (boot_partition > 1) { boot_partition = 0; } /* mmcblk0p1 => u-boot, mmcblk0p2 => root0 so +2 */ setenv_ulong("root_part", boot_partition + 2); writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel); cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RMII; cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_RMII; cpsw_slaves[0].phy_addr = 0; cpsw_slaves[1].phy_addr = 1; rv = cpsw_register(&cpsw_data); if (rv < 0) printf("Error %d registering CPSW switch\n", rv); else n += rv; #endif #endif #if defined(CONFIG_USB_ETHER) && \ (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT)) if (is_valid_ethaddr(mac_addr0)) eth_setenv_enetaddr("usbnet_devaddr", mac_addr0); rv = usb_eth_initialize(bis); if (rv < 0) printf("Error %d registering USB_ETHER\n", rv); else n += rv; #endif return n; } #endif #endif /* CONFIG_DM_ETH */ #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { return 0; } #endif