From d3cefa47c516db3ea865a13dbf5731df43c992ff Mon Sep 17 00:00:00 2001 From: Akila N Date: Tue, 30 Aug 2016 19:23:21 +0530 Subject: [PATCH] ipq40xx: Adding ethernet init sequence Change-Id: I3401f99e89e9dd3af952f70437524eadf3a1a80a Signed-off-by: Akila N --- arch/arm/include/asm/arch-qcom-common/gpio.h | 2 + board/qca/common/Makefile | 3 +- board/qca/common/ethaddr.c | 119 +++++++++++++++++++ board/qca/common/qca_common.h | 3 + board/qca/ipq40xx/Makefile | 2 +- board/qca/ipq40xx/ipq40xx.c | 88 +++++++++++++- drivers/net/Makefile | 7 ++ drivers/net/ipq40xx/ipq40xx_edma_eth.c | 5 +- drivers/net/ipq40xx/ipq40xx_ess_sw.c | 7 +- include/configs/ipq40xx.h | 4 + 10 files changed, 232 insertions(+), 8 deletions(-) create mode 100644 board/qca/common/ethaddr.c diff --git a/arch/arm/include/asm/arch-qcom-common/gpio.h b/arch/arm/include/asm/arch-qcom-common/gpio.h index e6820b739b..d82131a8fe 100644 --- a/arch/arm/include/asm/arch-qcom-common/gpio.h +++ b/arch/arm/include/asm/arch-qcom-common/gpio.h @@ -31,6 +31,8 @@ #ifndef GPIO_H #define GPIO_H +#define GPIO_OUT (1 << 1) + struct qca_gpio_config { unsigned int gpio; unsigned int func; diff --git a/board/qca/common/Makefile b/board/qca/common/Makefile index 7dafe616eb..6349717de9 100644 --- a/board/qca/common/Makefile +++ b/board/qca/common/Makefile @@ -2,4 +2,5 @@ obj-y := cmd_bootqca.o obj-y += fdt_info.o obj-y += board_init.o obj-y += env.o -obj-y += fdt_fixup.o \ No newline at end of file +obj-y += fdt_fixup.o +obj-y += ethaddr.o diff --git a/board/qca/common/ethaddr.c b/board/qca/common/ethaddr.c new file mode 100644 index 0000000000..cc5208f51f --- /dev/null +++ b/board/qca/common/ethaddr.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include "qca_common.h" + +#ifdef CONFIG_QCA_MMC +extern qca_mmc mmc_host; +#endif + +/* + * Gets the ethernet address from the ART partition table and return the value + */ +int get_eth_mac_address(uchar *enetaddr, uint no_of_macs) +{ + s32 ret = 0 ; + u32 start_blocks; + u32 size_blocks; + u32 length = (6 * no_of_macs); + u32 flash_type; + loff_t art_offset; + qca_smem_flash_info_t *sfi = &qca_smem_flash_info; +#ifdef CONFIG_QCA_MMC + block_dev_desc_t *blk_dev; + disk_partition_t disk_info; + struct mmc *mmc; + char mmc_blks[512]; +#endif + if (sfi->flash_type != SMEM_BOOT_MMC_FLASH) { + if (qca_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH) + flash_type = CONFIG_IPQ_SPI_NOR_INFO_IDX; + else if (qca_smem_flash_info.flash_type == SMEM_BOOT_NAND_FLASH) + flash_type = CONFIG_IPQ_NAND_NAND_INFO_IDX; + else { + printf("Unknown flash type\n"); + return -EINVAL; + } + + ret = smem_getpart("0:ART", &start_blocks, &size_blocks); + if (ret < 0) { + printf("No ART partition found\n"); + return ret; + } + + /* + * ART partition 0th position will contain Mac address. + */ + art_offset = + ((loff_t) qca_smem_flash_info.flash_block_size * start_blocks); + + ret = nand_read(&nand_info[flash_type], + art_offset, &length, enetaddr); + if (ret < 0) + printf("ART partition read failed..\n"); +#ifdef CONFIG_QCA_MMC + } else { + blk_dev = mmc_get_dev(mmc_host.dev_num); + ret = get_partition_info_efi_by_name(blk_dev, "0:ART", &disk_info); + /* + * ART partition 0th position will contain MAC address. + * Read 1 block. + */ + if (ret == 0) { + mmc = mmc_host.mmc; + ret = mmc->block_dev.block_read + (mmc_host.dev_num, disk_info.start, + 1, mmc_blks); + memcpy(enetaddr, mmc_blks, length); + } + if (ret < 0) + printf("ART partition read failed..\n"); +#endif + } + return ret; +} + +void set_ethmac_addr(void) +{ + int i, ret; + uchar enetaddr[CONFIG_IPQ_NO_MACS * 6]; + uchar *mac_addr; + char ethaddr[16] = "ethaddr"; + char mac[64]; + /* Get the MAC address from ART partition */ + ret = get_eth_mac_address(enetaddr, CONFIG_IPQ_NO_MACS); + for (i = 0; (ret >= 0) && (i < CONFIG_IPQ_NO_MACS); i++) { + mac_addr = &enetaddr[i * 6]; + if (!is_valid_ethaddr(mac_addr)) { + printf("eth%d MAC Address from ART is not valid\n", i); + } else { + /* + * U-Boot uses these to patch the 'local-mac-address' + * dts entry for the ethernet entries, which in turn + * will be picked up by the HLOS driver + */ + sprintf(mac, "%x:%x:%x:%x:%x:%x", + mac_addr[0], mac_addr[1], + mac_addr[2], mac_addr[3], + mac_addr[4], mac_addr[5]); + setenv(ethaddr, mac); + } + sprintf(ethaddr, "eth%daddr", (i + 1)); + } +} diff --git a/board/qca/common/qca_common.h b/board/qca/common/qca_common.h index 6762fabb4b..666a1e57e8 100644 --- a/board/qca/common/qca_common.h +++ b/board/qca/common/qca_common.h @@ -25,6 +25,9 @@ typedef struct { int qca_mmc_init(bd_t *, qca_mmc *); void board_mmc_deinit(void); +int get_eth_mac_address(uchar *enetaddr, uint no_of_macs); +void set_ethmac_addr(void); + #define MSM_SDC1_BASE 0x7824000 #define MMC_IDENTIFY_MODE 0 #define MMC_DATA_TRANSFER_MODE 1 diff --git a/board/qca/ipq40xx/Makefile b/board/qca/ipq40xx/Makefile index 2ad7af35bd..76e1f5e9e3 100644 --- a/board/qca/ipq40xx/Makefile +++ b/board/qca/ipq40xx/Makefile @@ -1,4 +1,4 @@ -ccflags-y += -I$(srctree)/board/qca/common/ +ccflags-y += -I$(srctree)/board/qca/common/ -I$(srctree)/drivers/net/ipq40xx/ obj-y := ipq40xx.o obj-y += clock.o diff --git a/board/qca/ipq40xx/ipq40xx.c b/board/qca/ipq40xx/ipq40xx.c index 861a071450..746c3487c8 100644 --- a/board/qca/ipq40xx/ipq40xx.c +++ b/board/qca/ipq40xx/ipq40xx.c @@ -26,6 +26,10 @@ #include #include #include "fdt_info.h" +#include +#include +#include "ipq40xx_edma_eth.h" +#include "qca_common.h" DECLARE_GLOBAL_DATA_PTR; @@ -54,6 +58,12 @@ extern int ipq_spi_init(u16); extern int mmc_env_init(void); extern void mmc_env_relocate_spec(void); +extern int ipq40xx_edma_init(ipq40xx_edma_board_cfg_t *edma_cfg); +extern int ipq40xx_qca8075_phy_init(struct ipq40xx_eth_dev *cfg); +extern int ipq40xx_qca8033_phy_init(struct ipq40xx_eth_dev *cfg); +extern void ipq40xx_register_switch( + int (*sw_init)(struct ipq40xx_eth_dev *cfg)); + void qca_serial_init(struct ipq_serial_platdata *plat) { int node; @@ -129,9 +139,85 @@ void board_nand_init(void) #endif } +static void ipq40xx_edma_common_init(void) +{ + writel(1, GCC_ESS_BCR); + mdelay(10); + writel(0, GCC_ESS_BCR); + mdelay(100); + + writel(1, GCC_MDIO_AHB_CBCR); + writel(MDIO_CTRL_0_DIV(0xff) | + MDIO_CTRL_0_MDC_MODE | + MDIO_CTRL_0_GPHY(0xa), MDIO_CTRL_0_REG); +} + int board_eth_init(bd_t *bis) { - return 0; + u32 status; + int gpio_node, node, len; + ipq40xx_edma_board_cfg_t* edma_cfg = + (ipq40xx_edma_board_cfg_t*)malloc(sizeof(ipq40xx_edma_board_cfg_t)); + + gpio_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/sw_gpio"); + if (gpio_node >= 0) + qca_gpio_init(gpio_node); + + ipq40xx_edma_common_init(); + switch (gd->bd->bi_arch_number) { + case MACH_TYPE_IPQ40XX_AP_DK01_1_S1: + case MACH_TYPE_IPQ40XX_AP_DK01_1_C2: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(62, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + case MACH_TYPE_IPQ40XX_AP_DK01_1_C1: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(59, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + case MACH_TYPE_IPQ40XX_AP_DK04_1_C4: + case MACH_TYPE_IPQ40XX_AP_DK04_1_C1: + case MACH_TYPE_IPQ40XX_AP_DK04_1_C3: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(47, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + case MACH_TYPE_IPQ40XX_AP_DK04_1_C2: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(67, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + case MACH_TYPE_IPQ40XX_AP_DK06_1_C1: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(19, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + case MACH_TYPE_IPQ40XX_AP_DK07_1_C1: + /* 8075 out of reset */ + mdelay(100); + gpio_set_value(41, 1); + ipq40xx_register_switch(ipq40xx_qca8075_phy_init); + break; + default: + break; + } + node = fdt_path_offset(gd->fdt_blob, "/edma_cfg"); + if (node < 0) { + printf("Error: edma_cfg not specified in dts"); + return -1; + } + edma_cfg->unit = fdtdec_get_uint(gd->fdt_blob, node, "unit", 0); + edma_cfg->phy = fdtdec_get_uint(gd->fdt_blob, node, "phy", 0); + strcpy(edma_cfg->phy_name, fdt_getprop(gd->fdt_blob, node, "phy_name", &len)); + + status = ipq40xx_edma_init(edma_cfg); + return status; } #ifdef CONFIG_QCA_MMC diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 150470c24b..edca474e26 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ # +ccflags-y += -I$(srctree)/board/qca/ipq40xx -I$(srctree)/board/qca/common + obj-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o obj-$(CONFIG_ALTERA_TSE) += altera_tse.o obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o @@ -72,3 +74,8 @@ obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/ obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o +obj-$(CONFIG_IPQ40XX_EDMA) += ipq40xx/ipq40xx_edma_eth.o +obj-$(CONFIG_IPQ40XX_ESS) += ipq40xx/ipq40xx_ess_sw.o +obj-$(CONFIG_QCA8075_PHY) += ipq40xx/ipq40xx_qca8075.o +obj-$(CONFIG_QCA8033_PHY) += ipq40xx/ipq40xx_qca8033.o +obj-$(CONFIG_IPQ40XX_MDIO) += ipq40xx/ipq40xx_mdio.o diff --git a/drivers/net/ipq40xx/ipq40xx_edma_eth.c b/drivers/net/ipq40xx/ipq40xx_edma_eth.c index d4b17430d1..bc4049f11b 100755 --- a/drivers/net/ipq40xx/ipq40xx_edma_eth.c +++ b/drivers/net/ipq40xx/ipq40xx_edma_eth.c @@ -22,6 +22,7 @@ #include #include "ipq40xx_edma_eth.h" #include "ipq40xx.h" +#include "qca_common.h" #ifdef DEBUG #define debugf(fmt, args...) printf(fmt, ##args); #else @@ -832,8 +833,8 @@ int ipq40xx_edma_init(ipq40xx_edma_board_cfg_t *edma_cfg) memset(c_info, 0, (sizeof(c_info) * IPQ40XX_EDMA_DEV)); memset(enet_addr, 0, sizeof(enet_addr)); /* Getting the MAC address from ART partition */ - ret = -1; - /* ret = get_eth_mac_address(enet_addr, IPQ40XX_EDMA_DEV); */ + ret = get_eth_mac_address(enet_addr, IPQ40XX_EDMA_DEV); + /* * Register EDMA as single ethernet * interface. diff --git a/drivers/net/ipq40xx/ipq40xx_ess_sw.c b/drivers/net/ipq40xx/ipq40xx_ess_sw.c index feea90d366..95c9693729 100644 --- a/drivers/net/ipq40xx/ipq40xx_ess_sw.c +++ b/drivers/net/ipq40xx/ipq40xx_ess_sw.c @@ -19,7 +19,8 @@ #include "ipq40xx_ess_sw.h" #include "ipq40xx.h" -extern board_ipq40xx_params_t *gboard_param; +DECLARE_GLOBAL_DATA_PTR; + static inline void ipq40xx_ess_sw_rd(u32 addr, u32 * data) { *data = readl((void __iomem *)(IPQ40XX_NSS_BASE + addr)); @@ -65,7 +66,7 @@ int ipq40xx_ess_sw_init(ipq40xx_edma_board_cfg_t *cfg) S17_TX_FLOW_EN | S17_RX_FLOW_EN); - switch(gboard_param->machid) { + switch(gd->bd->bi_arch_number) { case MACH_TYPE_IPQ40XX_AP_DK01_1_S1: case MACH_TYPE_IPQ40XX_AP_DK01_1_C1: case MACH_TYPE_IPQ40XX_AP_DK01_1_C2: @@ -132,7 +133,7 @@ int ipq40xx_ess_sw_init(ipq40xx_edma_board_cfg_t *cfg) break; default: printf("ess cfg not supported for %x machid\n", - gboard_param->machid); + gd->bd->bi_arch_number); return -1; } mdelay(1); diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h index 0a3b48643a..2dbb33b25b 100644 --- a/include/configs/ipq40xx.h +++ b/include/configs/ipq40xx.h @@ -191,6 +191,10 @@ typedef struct { #define CONFIG_SF_DEFAULT_SPEED (48 * 1000 * 1000) #define CONFIG_SPI_FLASH_BAR 1 +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_IPQ40XX_ESS 1 #define CONFIG_IPQ40XX_EDMA 1 #define CONFIG_NET_RETRY_COUNT 5 #define CONFIG_SYS_RX_ETH_BUFFER 16