blob: 4809f4c86b7aa5f9e5c089858150577e570d4aaa [file] [log] [blame]
/*
* Copyright (c) 2016-2017, 2020 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 <common.h>
#include <asm/errno.h>
#include <nand.h>
#include <part.h>
#include <mmc.h>
#include <asm/arch-qca-common/smem.h>
#include <asm/arch-qca-common/qca_common.h>
#include <sdhci.h>
#ifdef CONFIG_IPQ_TINY_SPI_NOR
#include <spi.h>
#include <spi_flash.h>
#endif
#if defined(CONFIG_ART_COMPRESSED) && \
(defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
#ifndef CONFIG_COMPRESSED_LOAD_ADDR
#define CONFIG_COMPRESSED_LOAD_ADDR CONFIG_SYS_LOAD_ADDR
#endif
#include <mapmem.h>
#include <lzma/LzmaTools.h>
#endif
#ifdef CONFIG_QCA_MMC
#ifndef CONFIG_SDHCI_SUPPORT
extern qca_mmc mmc_host;
#else
extern struct sdhci_host mmc_host;
#endif
#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
#ifdef CONFIG_IPQ_TINY_SPI_NOR
struct spi_flash *flash = NULL;
#if defined(CONFIG_ART_COMPRESSED) && (defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
void *load_buf, *image_buf;
unsigned long img_size;
unsigned long desMaxSize;
#endif
#endif
if (sfi->flash_type != SMEM_BOOT_MMC_FLASH) {
if (qca_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH)
flash_type = CONFIG_SPI_FLASH_INFO_IDX;
else if (qca_smem_flash_info.flash_type == SMEM_BOOT_NAND_FLASH)
flash_type = CONFIG_NAND_FLASH_INFO_IDX;
else if (qca_smem_flash_info.flash_type == SMEM_BOOT_QSPI_NAND_FLASH)
flash_type = CONFIG_NAND_FLASH_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);
#ifdef CONFIG_IPQ_TINY_SPI_NOR
flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
if (flash == NULL){
printf("No SPI flash device found\n");
ret = -1;
} else {
#if defined(CONFIG_ART_COMPRESSED) && (defined(CONFIG_GZIP) || defined(CONFIG_LZMA))
image_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR, 0);
load_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR + 0x100000, 0);
img_size = qca_smem_flash_info.flash_block_size * size_blocks;
desMaxSize = 0x100000;
ret = spi_flash_read(flash, art_offset, img_size, image_buf);
if (ret == 0) {
ret = -1;
#ifdef CONFIG_GZIP
ret = gunzip(load_buf, desMaxSize, image_buf, &img_size);
#endif
#ifdef CONFIG_LZMA
if (ret != 0)
ret = lzmaBuffToBuffDecompress(load_buf,
(SizeT *)&desMaxSize,
image_buf,
(SizeT)img_size);
#endif
if (ret == 0) {
memcpy(enetaddr, load_buf, length);
} else {
printf("Invalid compression type..\n");
ret = -1;
}
}
#else
ret = spi_flash_read(flash, art_offset, length, enetaddr);
#endif
}
/*
* Avoid unused warning
*/
(void)flash_type;
#else
ret = nand_read(&nand_info[flash_type],
art_offset, &length, enetaddr);
#endif
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
*/
snprintf(mac, sizeof(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);
}
snprintf(ethaddr, sizeof(ethaddr), "eth%daddr", (i + 1));
}
}