154e7445dSIlya Ledvich /* 254e7445dSIlya Ledvich * Board functions for Compulab CM-T335 board 354e7445dSIlya Ledvich * 454e7445dSIlya Ledvich * Copyright (C) 2013, Compulab Ltd - http://compulab.co.il/ 554e7445dSIlya Ledvich * 654e7445dSIlya Ledvich * Author: Ilya Ledvich <ilya@compulab.co.il> 754e7445dSIlya Ledvich * 854e7445dSIlya Ledvich * SPDX-License-Identifier: GPL-2.0+ 954e7445dSIlya Ledvich */ 1054e7445dSIlya Ledvich 1154e7445dSIlya Ledvich #include <common.h> 1254e7445dSIlya Ledvich #include <errno.h> 1354e7445dSIlya Ledvich #include <miiphy.h> 1454e7445dSIlya Ledvich #include <cpsw.h> 1554e7445dSIlya Ledvich 1654e7445dSIlya Ledvich #include <asm/arch/sys_proto.h> 1754e7445dSIlya Ledvich #include <asm/arch/hardware_am33xx.h> 1854e7445dSIlya Ledvich #include <asm/io.h> 1954e7445dSIlya Ledvich #include <asm/gpio.h> 2054e7445dSIlya Ledvich 2154e7445dSIlya Ledvich #include "../common/eeprom.h" 2254e7445dSIlya Ledvich 2354e7445dSIlya Ledvich DECLARE_GLOBAL_DATA_PTR; 2454e7445dSIlya Ledvich 2554e7445dSIlya Ledvich /* 2654e7445dSIlya Ledvich * Basic board specific setup. Pinmux has been handled already. 2754e7445dSIlya Ledvich */ 2854e7445dSIlya Ledvich int board_init(void) 2954e7445dSIlya Ledvich { 3054e7445dSIlya Ledvich gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 3154e7445dSIlya Ledvich 3254e7445dSIlya Ledvich gpmc_init(); 3354e7445dSIlya Ledvich 34*2d8d190cSUri Mashiach #if defined(CONFIG_LED_STATUS) && defined(CONFIG_LED_STATUS_BOOT_ENABLE) 35*2d8d190cSUri Mashiach status_led_set(CONFIG_LED_STATUS_BOOT, CONFIG_LED_STATUS_OFF); 36e8ac22beSIlya Ledvich #endif 3754e7445dSIlya Ledvich return 0; 3854e7445dSIlya Ledvich } 3954e7445dSIlya Ledvich 4054e7445dSIlya Ledvich #if defined (CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD) 4154e7445dSIlya Ledvich static void cpsw_control(int enabled) 4254e7445dSIlya Ledvich { 4354e7445dSIlya Ledvich /* VTP can be added here */ 4454e7445dSIlya Ledvich return; 4554e7445dSIlya Ledvich } 4654e7445dSIlya Ledvich 4754e7445dSIlya Ledvich static struct cpsw_slave_data cpsw_slave = { 4854e7445dSIlya Ledvich .slave_reg_ofs = 0x208, 4954e7445dSIlya Ledvich .sliver_reg_ofs = 0xd80, 509c653aadSMugunthan V N .phy_addr = 0, 5154e7445dSIlya Ledvich .phy_if = PHY_INTERFACE_MODE_RGMII, 5254e7445dSIlya Ledvich }; 5354e7445dSIlya Ledvich 5454e7445dSIlya Ledvich static struct cpsw_platform_data cpsw_data = { 5554e7445dSIlya Ledvich .mdio_base = CPSW_MDIO_BASE, 5654e7445dSIlya Ledvich .cpsw_base = CPSW_BASE, 5754e7445dSIlya Ledvich .mdio_div = 0xff, 5854e7445dSIlya Ledvich .channels = 8, 5954e7445dSIlya Ledvich .cpdma_reg_ofs = 0x800, 6054e7445dSIlya Ledvich .slaves = 1, 6154e7445dSIlya Ledvich .slave_data = &cpsw_slave, 6254e7445dSIlya Ledvich .ale_reg_ofs = 0xd00, 6354e7445dSIlya Ledvich .ale_entries = 1024, 6454e7445dSIlya Ledvich .host_port_reg_ofs = 0x108, 6554e7445dSIlya Ledvich .hw_stats_reg_ofs = 0x900, 6654e7445dSIlya Ledvich .bd_ram_ofs = 0x2000, 6754e7445dSIlya Ledvich .mac_control = (1 << 5), 6854e7445dSIlya Ledvich .control = cpsw_control, 6954e7445dSIlya Ledvich .host_port_num = 0, 7054e7445dSIlya Ledvich .version = CPSW_CTRL_VERSION_2, 7154e7445dSIlya Ledvich }; 7254e7445dSIlya Ledvich 7354e7445dSIlya Ledvich /* PHY reset GPIO */ 7454e7445dSIlya Ledvich #define GPIO_PHY_RST GPIO_PIN(3, 7) 7554e7445dSIlya Ledvich 7654e7445dSIlya Ledvich static void board_phy_init(void) 7754e7445dSIlya Ledvich { 7854e7445dSIlya Ledvich gpio_request(GPIO_PHY_RST, "phy_rst"); 7954e7445dSIlya Ledvich gpio_direction_output(GPIO_PHY_RST, 0); 8054e7445dSIlya Ledvich mdelay(2); 8154e7445dSIlya Ledvich gpio_set_value(GPIO_PHY_RST, 1); 8254e7445dSIlya Ledvich mdelay(2); 8354e7445dSIlya Ledvich } 8454e7445dSIlya Ledvich 8554e7445dSIlya Ledvich static void get_efuse_mac_addr(uchar *enetaddr) 8654e7445dSIlya Ledvich { 8754e7445dSIlya Ledvich uint32_t mac_hi, mac_lo; 8854e7445dSIlya Ledvich struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; 8954e7445dSIlya Ledvich 9054e7445dSIlya Ledvich mac_lo = readl(&cdev->macid0l); 9154e7445dSIlya Ledvich mac_hi = readl(&cdev->macid0h); 9254e7445dSIlya Ledvich enetaddr[0] = mac_hi & 0xFF; 9354e7445dSIlya Ledvich enetaddr[1] = (mac_hi & 0xFF00) >> 8; 9454e7445dSIlya Ledvich enetaddr[2] = (mac_hi & 0xFF0000) >> 16; 9554e7445dSIlya Ledvich enetaddr[3] = (mac_hi & 0xFF000000) >> 24; 9654e7445dSIlya Ledvich enetaddr[4] = mac_lo & 0xFF; 9754e7445dSIlya Ledvich enetaddr[5] = (mac_lo & 0xFF00) >> 8; 9854e7445dSIlya Ledvich } 9954e7445dSIlya Ledvich 10054e7445dSIlya Ledvich /* 10154e7445dSIlya Ledvich * Routine: handle_mac_address 10254e7445dSIlya Ledvich * Description: prepare MAC address for on-board Ethernet. 10354e7445dSIlya Ledvich */ 10454e7445dSIlya Ledvich static int handle_mac_address(void) 10554e7445dSIlya Ledvich { 10654e7445dSIlya Ledvich uchar enetaddr[6]; 10754e7445dSIlya Ledvich int rv; 10854e7445dSIlya Ledvich 10954e7445dSIlya Ledvich rv = eth_getenv_enetaddr("ethaddr", enetaddr); 11054e7445dSIlya Ledvich if (rv) 11154e7445dSIlya Ledvich return 0; 11254e7445dSIlya Ledvich 113e7a2447bSNikita Kiryanov rv = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS); 11454e7445dSIlya Ledvich if (rv) 11554e7445dSIlya Ledvich get_efuse_mac_addr(enetaddr); 11654e7445dSIlya Ledvich 1170adb5b76SJoe Hershberger if (!is_valid_ethaddr(enetaddr)) 11854e7445dSIlya Ledvich return -1; 11954e7445dSIlya Ledvich 12054e7445dSIlya Ledvich return eth_setenv_enetaddr("ethaddr", enetaddr); 12154e7445dSIlya Ledvich } 12254e7445dSIlya Ledvich 12354e7445dSIlya Ledvich #define AR8051_PHY_DEBUG_ADDR_REG 0x1d 12454e7445dSIlya Ledvich #define AR8051_PHY_DEBUG_DATA_REG 0x1e 12554e7445dSIlya Ledvich #define AR8051_DEBUG_RGMII_CLK_DLY_REG 0x5 12654e7445dSIlya Ledvich #define AR8051_RGMII_TX_CLK_DLY 0x100 12754e7445dSIlya Ledvich 12854e7445dSIlya Ledvich int board_eth_init(bd_t *bis) 12954e7445dSIlya Ledvich { 13054e7445dSIlya Ledvich int rv, n = 0; 13154e7445dSIlya Ledvich const char *devname; 13254e7445dSIlya Ledvich struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; 13354e7445dSIlya Ledvich 13454e7445dSIlya Ledvich rv = handle_mac_address(); 13554e7445dSIlya Ledvich if (rv) 13654e7445dSIlya Ledvich printf("No MAC address found!\n"); 13754e7445dSIlya Ledvich 13854e7445dSIlya Ledvich writel(RGMII_MODE_ENABLE | RGMII_INT_DELAY, &cdev->miisel); 13954e7445dSIlya Ledvich 14054e7445dSIlya Ledvich board_phy_init(); 14154e7445dSIlya Ledvich 14254e7445dSIlya Ledvich rv = cpsw_register(&cpsw_data); 14354e7445dSIlya Ledvich if (rv < 0) 14454e7445dSIlya Ledvich printf("Error %d registering CPSW switch\n", rv); 14554e7445dSIlya Ledvich else 14654e7445dSIlya Ledvich n += rv; 14754e7445dSIlya Ledvich 14854e7445dSIlya Ledvich /* 14954e7445dSIlya Ledvich * CPSW RGMII Internal Delay Mode is not supported in all PVT 15054e7445dSIlya Ledvich * operating points. So we must set the TX clock delay feature 15154e7445dSIlya Ledvich * in the AR8051 PHY. Since we only support a single ethernet 15254e7445dSIlya Ledvich * device, we only do this for the first instance. 15354e7445dSIlya Ledvich */ 15454e7445dSIlya Ledvich devname = miiphy_get_current_dev(); 15554e7445dSIlya Ledvich 15654e7445dSIlya Ledvich miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_ADDR_REG, 15754e7445dSIlya Ledvich AR8051_DEBUG_RGMII_CLK_DLY_REG); 15854e7445dSIlya Ledvich miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_DATA_REG, 15954e7445dSIlya Ledvich AR8051_RGMII_TX_CLK_DLY); 16054e7445dSIlya Ledvich return n; 16154e7445dSIlya Ledvich } 16254e7445dSIlya Ledvich #endif /* CONFIG_DRIVER_TI_CPSW && !CONFIG_SPL_BUILD */ 163