From fc300e2c5d9b6217400d89a58e35a69b362ad288 Mon Sep 17 00:00:00 2001 From: Dmitry Lifshitz Date: Wed, 28 Dec 2016 18:28:35 +0200 Subject: [PATCH] arm: am57xx: cl-som-am57x: add ETH support Add MAC support. Use PHY, connected to RGMII1 as a default Eth adapter, by appropriate setting of 'cpsw_data.active_slave'. 'cpsw_phy' env variable can override this setting. Set the MAC addresses in the U-Boot environment. The addresses are retrieved from the on-board EEPROM or from the SOC's MAC fuses. Set the following PHYs RGMII clock delays: - Enable RX delay - Disable TX delay Signed-off-by: Dmitry Lifshitz [uri.mashiach@compulab.co.il: add RGMII clock delays] Signed-off-by: Uri Mashiach Acked-by: Igor Grinberg Reviewed-by: Tom Rini --- board/compulab/cl-som-am57x/Makefile | 2 + board/compulab/cl-som-am57x/eth.c | 198 +++++++++++++++++++++++++++ board/compulab/cl-som-am57x/mux.c | 23 ++++ include/configs/cl-som-am57x.h | 17 +++ 4 files changed, 240 insertions(+) create mode 100644 board/compulab/cl-som-am57x/eth.c diff --git a/board/compulab/cl-som-am57x/Makefile b/board/compulab/cl-som-am57x/Makefile index 0c59781a8b..566366bf6e 100644 --- a/board/compulab/cl-som-am57x/Makefile +++ b/board/compulab/cl-som-am57x/Makefile @@ -13,3 +13,5 @@ obj-y += spl.o mux.o else obj-y += cl-som-am57x.o mux.o endif + +obj-$(CONFIG_DRIVER_TI_CPSW) += eth.o diff --git a/board/compulab/cl-som-am57x/eth.c b/board/compulab/cl-som-am57x/eth.c new file mode 100644 index 0000000000..0c4bf91c13 --- /dev/null +++ b/board/compulab/cl-som-am57x/eth.c @@ -0,0 +1,198 @@ +/* + * Ethernet specific code for CompuLab CL-SOM-AM57x module + * + * (C) Copyright 2016 CompuLab, Ltd. http://compulab.co.il/ + * + * Author: Uri Mashiach + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include "../common/eeprom.h" + +static void cpsw_control(int enabled) +{ + /* VTP can be added here */ +} + +static struct cpsw_slave_data cl_som_am57x_cpsw_slaves[] = { + { + .slave_reg_ofs = 0x208, + .sliver_reg_ofs = 0xd80, + .phy_addr = 0, + .phy_if = PHY_INTERFACE_MODE_RMII, + }, + { + .slave_reg_ofs = 0x308, + .sliver_reg_ofs = 0xdc0, + .phy_addr = 1, + .phy_if = PHY_INTERFACE_MODE_RMII, + + }, +}; + +static struct cpsw_platform_data cl_som_am57_cpsw_data = { + .mdio_base = CPSW_MDIO_BASE, + .cpsw_base = CPSW_BASE, + .mdio_div = 0xff, + .channels = 8, + .cpdma_reg_ofs = 0x800, + .slaves = 2, + .slave_data = cl_som_am57x_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, +}; + +/* + * cl_som_am57x_efuse_read_mac_addr() - read Ethernet port MAC address. + * The information is retrieved from the SOC's registers. + * @buff: read buffer. + * @port_num: port number. + */ +static void cl_som_am57x_efuse_read_mac_addr(uchar *buff, uint port_num) +{ + uint32_t mac_hi, mac_lo; + + if (port_num) { + mac_lo = readl((*ctrl)->control_core_mac_id_1_lo); + mac_hi = readl((*ctrl)->control_core_mac_id_1_hi); + } else { + mac_lo = readl((*ctrl)->control_core_mac_id_0_lo); + mac_hi = readl((*ctrl)->control_core_mac_id_0_hi); + } + + buff[0] = (mac_hi & 0xFF0000) >> 16; + buff[1] = (mac_hi & 0xFF00) >> 8; + buff[2] = mac_hi & 0xFF; + buff[3] = (mac_lo & 0xFF0000) >> 16; + buff[4] = (mac_lo & 0xFF00) >> 8; + buff[5] = mac_lo & 0xFF; +} + +/* + * cl_som_am57x_handle_mac_address() - set MAC address in the U-Boot + * environment. + * The address is retrieved retrieved from an EEPROM field or from the + * SOC's registers. + * @env_name: U-Boot environment name. + * @field_name: EEPROM field name. + * @port_num: SOC's port number. + */ +static int cl_som_am57x_handle_mac_address(char *env_name, uint port_num) +{ + int ret; + uint8_t enetaddr[6]; + + ret = eth_getenv_enetaddr(env_name, enetaddr); + if (ret) + return 0; + + ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS); + + if (ret || !is_valid_ethaddr(enetaddr)) + cl_som_am57x_efuse_read_mac_addr(enetaddr, port_num); + + if (!is_valid_ethaddr(enetaddr)) + return -1; + + ret = eth_setenv_enetaddr(env_name, enetaddr); + if (ret) + printf("cl-som-am57x: Failed to set Eth port %d MAC address\n", + port_num); + + return ret; +} + +#define CL_SOM_AM57X_PHY_ADDR2 0x01 +#define AR8033_PHY_DEBUG_ADDR_REG 0x1d +#define AR8033_PHY_DEBUG_DATA_REG 0x1e +#define AR8033_DEBUG_RGMII_RX_CLK_DLY_REG 0x00 +#define AR8033_DEBUG_RGMII_TX_CLK_DLY_REG 0x05 +#define AR8033_DEBUG_RGMII_RX_CLK_DLY_MASK (1 << 15) +#define AR8033_DEBUG_RGMII_TX_CLK_DLY_MASK (1 << 8) + +/* + * cl_som_am57x_rgmii_clk_delay() - Set RGMII clock delay. + * Enable RX delay, disable TX delay. + */ +static void cl_som_am57x_rgmii_clk_delay(void) +{ + uint16_t mii_reg_val; + const char *devname; + + devname = miiphy_get_current_dev(); + /* PHY 2 */ + miiphy_write(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_ADDR_REG, + AR8033_DEBUG_RGMII_RX_CLK_DLY_REG); + miiphy_read(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_DATA_REG, + &mii_reg_val); + mii_reg_val |= AR8033_DEBUG_RGMII_RX_CLK_DLY_MASK; + miiphy_write(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_DATA_REG, + mii_reg_val); + + miiphy_write(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_ADDR_REG, + AR8033_DEBUG_RGMII_TX_CLK_DLY_REG); + miiphy_read(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_DATA_REG, + &mii_reg_val); + mii_reg_val &= ~AR8033_DEBUG_RGMII_TX_CLK_DLY_MASK; + miiphy_write(devname, CL_SOM_AM57X_PHY_ADDR2, AR8033_PHY_DEBUG_DATA_REG, + mii_reg_val); +} + +#define CL_SOM_AM57X_GPIO_PHY1_RST 92 /* GPIO3_28 */ +#define CL_SOM_AM57X_RGMII_PORT1 1 + +int board_eth_init(bd_t *bis) +{ + int ret; + uint32_t ctrl_val; + char *cpsw_phy_envval; + int cpsw_act_phy = 1; + + /* SB-SOM-AM57x primary Eth (P21) is routed to RGMII1 */ + ret = cl_som_am57x_handle_mac_address("ethaddr", + CL_SOM_AM57X_RGMII_PORT1); + + if (ret) + return -1; + + /* Select RGMII for GMII1_SEL */ + ctrl_val = readl((*ctrl)->control_core_control_io1) & (~0x33); + ctrl_val |= 0x22; + writel(ctrl_val, (*ctrl)->control_core_control_io1); + mdelay(10); + + gpio_request(CL_SOM_AM57X_GPIO_PHY1_RST, "phy1_rst"); + gpio_direction_output(CL_SOM_AM57X_GPIO_PHY1_RST, 0); + mdelay(20); + + gpio_set_value(CL_SOM_AM57X_GPIO_PHY1_RST, 1); + mdelay(20); + + cpsw_phy_envval = getenv("cpsw_phy"); + if (cpsw_phy_envval != NULL) + cpsw_act_phy = simple_strtoul(cpsw_phy_envval, NULL, 0); + + cl_som_am57_cpsw_data.active_slave = cpsw_act_phy; + + ret = cpsw_register(&cl_som_am57_cpsw_data); + if (ret < 0) + printf("Error %d registering CPSW switch\n", ret); + + /* Set RGMII clock delay */ + cl_som_am57x_rgmii_clk_delay(); + + return ret; +} diff --git a/board/compulab/cl-som-am57x/mux.c b/board/compulab/cl-som-am57x/mux.c index 625cbc1dbd..5b7197578c 100644 --- a/board/compulab/cl-som-am57x/mux.c +++ b/board/compulab/cl-som-am57x/mux.c @@ -83,6 +83,28 @@ static const struct pad_conf_entry cl_som_am57x_padconf_usb[] = { {USB1_DRVVBUS, (M0 | FSC) }, /* USB1_DRVVBUS.USB1_DRVVBUS */ }; +/* Ethernet */ +static const struct pad_conf_entry cl_som_am57x_padconf_ethernet[] = { + /* MDIO bus */ + {VIN2A_D10, (PDIS | PTU | M3) }, /* VIN2A_D10.MDIO_MCLK */ + {VIN2A_D11, (IEN | PDIS | PTU | M3) }, /* VIN2A_D11.MDIO_D */ + /* EMAC Slave 1 at addr 0x1 - Default interface */ + {VIN2A_D12, (IDIS | PEN | M3) }, /* VIN2A_D12.RGMII1_TXC */ + {VIN2A_D13, (IDIS | PEN | M3) }, /* VIN2A_D13.RGMII1_TXCTL */ + {VIN2A_D14, (IDIS | PEN | M3) }, /* VIN2A_D14.RGMII1_TXD3 */ + {VIN2A_D15, (IDIS | PEN | M3) }, /* VIN2A_D15.RGMII1_TXD2 */ + {VIN2A_D16, (IDIS | PEN | M3) }, /* VIN2A_D16.RGMII1_TXD1 */ + {VIN2A_D17, (IDIS | PEN | M3) }, /* VIN2A_D17.RGMII1_TXD0 */ + {VIN2A_D18, (IEN | PDIS | PTD | M3) }, /* VIN2A_D18.RGMII1_RXC */ + {VIN2A_D19, (IEN | PDIS | PTD | M3) }, /* VIN2A_D19.RGMII1_RXCTL */ + {VIN2A_D20, (IEN | PDIS | PTD | M3) }, /* VIN2A_D20.RGMII1_RXD3 */ + {VIN2A_D21, (IEN | PDIS | PTD | M3) }, /* VIN2A_D21.RGMII1_RXD2 */ + {VIN2A_D22, (IEN | PDIS | PTD | M3) }, /* VIN2A_D22.RGMII1_RXD1 */ + {VIN2A_D23, (IEN | PDIS | PTD | M3) }, /* VIN2A_D23.RGMII1_RXD0 */ + /* Eth PHY1 reset GPIOs*/ + {VIN1B_CLK1, (IDIS | PDIS | PTD | M14)}, /* VIN1B_CLK1.GPIO2_31 */ +}; + #define SET_MUX(mux_array) do_set_mux32((*ctrl)->control_padconf_core_base, \ mux_array, ARRAY_SIZE(mux_array)) @@ -97,4 +119,5 @@ void set_muxconf_regs(void) SET_MUX(cl_som_am57x_padconf_i2c_gpio); SET_MUX(cl_som_am57x_padconf_emmc); SET_MUX(cl_som_am57x_padconf_usb); + SET_MUX(cl_som_am57x_padconf_ethernet); } diff --git a/include/configs/cl-som-am57x.h b/include/configs/cl-som-am57x.h index 48c0f7f044..2001b0c9db 100644 --- a/include/configs/cl-som-am57x.h +++ b/include/configs/cl-som-am57x.h @@ -114,6 +114,23 @@ #define CONFIG_USB_ETHER_ASIX #define CONFIG_USB_ETHER_MCS7830 +/* CPSW Ethernet */ +#define CONFIG_DRIVER_TI_CPSW +#define CONFIG_MII +#define CONFIG_BOOTP_DEFAULT +#define CONFIG_BOOTP_SEND_HOSTNAME +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_PHY_GIGE +#define CONFIG_PHY_ATHEROS +#define CONFIG_PHYLIB +#define CONFIG_SYS_RX_ETH_BUFFER 64 +#define PHY_ANEG_TIMEOUT 8000 + +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_DNS2 +#define CONFIG_BOOTP_SUBNETMASK +#define CONFIG_NET_RETRY_COUNT 10 + #endif /* !CONFIG_SPL_BUILD */ #endif /* __CONFIG_CL_SOM_AM57X_H */ -- 2.39.5