blob: 8a5b5cc40f79663bf4972e680126a86ed8c866a5 [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell Commercial License Option
If you received this File from Marvell and you have entered into a commercial
license agreement (a "Commercial License") with Marvell, the File is licensed
to you under the terms of the applicable Commercial License.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
********************************************************************************
Marvell BSD License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File under the following licensing terms.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Marvell nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include <common.h>
#include <config.h>
#include <common.h>
#include <command.h>
#include <pci.h>
#include <net.h>
#include <spi_flash.h>
#include <bzlib.h>
#include <fs.h>
#ifdef MV_INCLUDE_USB
#include <usb.h>
#endif
#ifdef CONFIG_MMC
#include <mmc.h>
#endif
#include "mvCommon.h"
#include "ctrlEnv/mvCtrlEnvLib.h"
#include "boardEnv/mvBoardEnvLib.h"
#include "cpu/mvCpu.h"
#if defined(MV_INC_BOARD_NOR_FLASH)
#include "norflash/mvFlash.h"
#endif
#if defined(MV_INCLUDE_GIG_ETH)
#include "eth-phy/mvEthPhy.h"
#endif
#if defined(MV_INCLUDE_PEX)
#include "pex/mvPex.h"
#endif
#if defined(MV_INCLUDE_PDMA)
#include "pdma/mvPdma.h"
#include "mvSysPdmaApi.h"
#endif
#if defined(MV_INCLUDE_XOR)
#include "xor/mvXorRegs.h"
#include "xor/mvXor.h"
#endif
#if defined(MV_INCLUDE_PMU)
#include "pmu/mvPmuRegs.h"
#endif
#include "cntmr/mvCntmrRegs.h"
#include "switchingServices.h"
MV_BOOL mvVerifyRequest(void)
{
printf("\nDo you want to continue ? [Y/n]");
readline(" ");
if(strlen(console_buffer) == 0 || /* if pressed Enter */
strcmp(console_buffer,"y") == 0 ||
strcmp(console_buffer,"Yes") == 0 ||
strcmp(console_buffer,"Y") == 0 ) {
printf("\n");
return MV_TRUE;
}
return MV_FALSE;
}
int mvLoadFile4cpss(int loadfrom, const char* file_name, char * devPart, int fstype)
{
MV_U32 filesize;
char interface[4] = "mmc";
switch(loadfrom) {
case 0:
if ((filesize = NetLoop(TFTPGET)) < 0)
return 0;
return filesize;;
case 1:
#ifdef MV_INCLUDE_USB
usb_stop();
printf("(Re)start USB...\n");
if (usb_init() < 0) {
printf("usb_init failed\n");
return 0;
}
/* try to recognize storage devices immediately */
if (-1 == usb_stor_scan(1)) {
printf("USB storage device not found\n");
return 0;
}
strcpy(interface, "usb");
break;
#else
printf("USB is not supported\n");
return 0;
#endif
case 2:
#ifdef CONFIG_MMC
run_command("mmc rescan", 0);
break;
#else
printf("MMC is not supported\n");
return 0;
#endif
}
/* always load from usb 0 */
if (fs_set_blk_dev(interface, devPart, fstype))
{
printf("%s %s not found\n", interface, (devPart != NULL) ? devPart: "0");
return 0;
}
return (fs_read(file_name, load_addr, 0, 0));
}
/*******************************************************************************
* mv_print_appl_partitions - Print u-boot partitions on SPI flash
*******************************************************************************/
static int do_print_flash_part ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] ) {
#ifdef MV_INCLUDE_SPI
run_command("sf probe 0", 0);
printf("\n");
printf("%s partitions on spi flash\n", CFG_APPL_SPI_FLASH_PARTITIONS_NAME);
printf("--------------------------------------\n\n");
printf("Spi flash Address (rx) : 0x%08x\n", CFG_APPL_SPI_FLASH_START_DIRECT);
printf("Spi flash size : %dMB\n", CFG_APPL_SPI_FLASH_SIZE/(1<<20));
printf("u-boot : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_FLASH_PART_UBOOT_START,
CFG_APPL_FLASH_PART_UBOOT_SIZE,
CFG_APPL_FLASH_PART_UBOOT_SIZE/(_1M));
printf("kernel/vxWorks-image : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_SPI_FLASH_PART_KERNEL_START,
CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE,
CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE/(_1M));
printf("Linux rootfs : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_SPI_FLASH_PART_ROOTFS_START,
CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE,
CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE/(_1M));
printf("\n");
printf("Single Image : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_SPI_FLASH_PART_KERNEL_START,
CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE + CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE,
(CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE + CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE)/(_1M));
#endif /* MV_INCLUDE_SPI */
#ifdef MV_NAND
run_command("nand info", 0);
printf("\n");
printf("%s partitions on nand flash\n", CFG_APPL_SPI_FLASH_PARTITIONS_NAME);
printf("--------------------------------------\n\n");
printf("Nand flash size : %dMB\n", CFG_APPL_NAND_FLASH_SIZE/(1<<20));
printf("kernel/vxWorks-image : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_NAND_FLASH_PART_KERNEL_START,
CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE,
CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE/(_1M));
printf("Linux rootfs : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_NAND_FLASH_PART_ROOTFS_START,
CFG_APPL_NAND_FLASH_PART_ROOTFS_SIZE,
CFG_APPL_NAND_FLASH_PART_ROOTFS_SIZE/(_1M));
printf("\n");
printf("Single Image : offset=0x%08x, size=0x%08x (%dMB)\n",
CFG_APPL_NAND_FLASH_PART_KERNEL_START,
CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE + CFG_APPL_NAND_FLASH_PART_ROOTFS_SIZE,
(CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE + CFG_APPL_NAND_FLASH_PART_ROOTFS_SIZE)/(_1M));
#endif
printf("\n");
return 1;
}
U_BOOT_CMD(
flash_part_print, 2, 1, do_print_flash_part,
"flash_part_print - print spi/nand FLASH memory information\n",
"\n - print information for all SPI FLASH memory banks\n"
);
static int isSwitchingServicesSupported(void)
{
MV_U32 family = mvCtrlDevFamilyIdGet(0);
/* enable command only for AC3 & BC2 & AMC boards */
if (!((family >= MV_ALLEYCAT3_DEV_ID && family <= MV_ALLEYCAT3_MAX_DEV_ID)
|| family == MV_BOBCAT2_DEV_ID || mvBoardisAmc())) {
printf("Command not supported for this SoC/Board\n");
return 0;
}
return 1;
}
/*******************************************************************************
* do_cpss_env - Save CPSS enviroment on flash
*
* DESCRIPTION:
*
* INPUT: None
*
* OUTPUT: None,
*
* RETURN:
* None
*
*******************************************************************************/
static int do_cpss_env( cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[] )
{
char buf[1024];
if (!isSwitchingServicesSupported())
return 0;
printf("Saving cpss environment variable\n");
setenv("standalone", "");
setenv("bootcmd", "run standalone_mtd");
setenv("consoledev","ttyS0");
setenv("linux_loadaddr","0x2000000");
setenv("netdev","eth0");
setenv("rootpath","/tftpboot/rootfs_arm-mv7sft");
setenv("othbootargs","null=null");
setenv("nfsboot","setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} "
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off "
"console=${consoledev},${baudrate} ${othbootargs} ${linux_parts}; tftp ${linux_loadaddr} "
"${image_name};bootm ${linux_loadaddr}");
sprintf(buf,"'mtdparts=spi_flash:%dm(spi_uboot)ro,%dm(spi_kernel),%dm(spi_rootfs),-(remainder)"
";armada-nand:%dm(nand_kernel),-(nand_rootfs)'", CFG_APPL_FLASH_PART_UBOOT_SIZE / _1M,
CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE / _1M, CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE / _1M,
CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE / _1M);
setenv("mtdparts", buf);
printf("mtdparts = %s\n", buf);
setenv("linux_parts", buf);
#ifdef MV_INCLUDE_SPI
sprintf(buf,
"sf probe; sf read ${loadaddr} 0x%x 0x%x; setenv bootargs ${console} "
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off "
"root=/dev/mtdblock2 rw init=/linuxrc rootfstype=jffs2 rootwait ${mtdparts} "
"${mvNetConfig}; bootm ${loadaddr} ",
CFG_APPL_SPI_FLASH_PART_KERNEL_START, CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE);
#ifndef MV_NAND
setenv("standalone_mtd", buf);
printf("standalone_mtd = %s\n", buf);
#else
setenv("standalone_mtd_spi", buf);
printf("standalone_mtd_spi = %s\n", buf);
#endif
#endif /* MV_INCLUDE_SPI */
#ifdef MV_NAND
sprintf(buf,
"nand read ${loadaddr} 0x%x 0x%x; setenv bootargs ${console} ${mtdparts} "
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off "
"ubi.mtd=5 root=ubi0:rootfs_nand ro rootfstype=ubifs ${mvNetConfig}; bootm 0x2000000;" ,
CFG_APPL_NAND_FLASH_PART_KERNEL_START,
CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE);
setenv("standalone_mtd", buf);
printf("standalone_mtd = %s\n", buf);
#endif
run_command("saveenv", 0);
printf("\nboot command prepared: run 'boot' to load kernel and file system from flash.\n");
return 1;
}
U_BOOT_CMD(
cpss_env, 2, 1, do_cpss_env,
"set cpss environment variables permanently\n",
""
);
#if defined(MV_INCLUDE_SPI)
extern struct spi_flash *flash;
#endif
struct partitionInformation nandInfo = {
.defaultImage = "ubifs_arm_nand.image",
.FLASH_SIZE = CFG_APPL_NAND_FLASH_SIZE,
.KERNEL_SIZE = CFG_APPL_NAND_FLASH_PART_KERNEL_SIZE,
.ROOTFS_SIZE = CFG_APPL_NAND_FLASH_PART_ROOTFS_SIZE,
.KERNEL_START = CFG_APPL_NAND_FLASH_PART_KERNEL_START,
.BLOCK_ALIMENT = CFG_APPL_NAND_FLASH_BLOCK_ALIMENT,
.ROOTFS_START = CFG_APPL_NAND_FLASH_PART_ROOTFS_START,
};
struct partitionInformation spiInfo = {
.defaultImage = "jffs2_arm.image",
.FLASH_SIZE = CFG_APPL_SPI_FLASH_SIZE,
.KERNEL_SIZE = CFG_APPL_SPI_FLASH_PART_KERNEL_SIZE,
.ROOTFS_SIZE = CFG_APPL_SPI_FLASH_PART_ROOTFS_SIZE,
.KERNEL_START = CFG_APPL_SPI_FLASH_PART_KERNEL_START,
.BLOCK_ALIMENT = CFG_APPL_SPI_FLASH_BLOCK_ALIMENT,
.ROOTFS_START = CFG_APPL_SPI_FLASH_PART_ROOTFS_START,
};
void flashWrite (MV_U32 destination, MV_U32 len, MV_U32 source, MV_BOOL isNand)
{
char cmdBuf[128];
if (isNand == MV_TRUE) {
sprintf(cmdBuf, "nand write.trimffs %x %x %x\n", source, destination, len);
printf(cmdBuf);
run_command(cmdBuf, 0);
}
#if defined(MV_INCLUDE_SPI)
else
spi_flash_write(flash, destination, len, (const void *)source);
#endif
}
void flashErase (MV_U32 destination, MV_U32 len, MV_BOOL isNand)
{
char cmdBuf[128];
if (isNand == MV_TRUE) {
sprintf(cmdBuf, "nand erase %x %x\n", destination, len);
printf(cmdBuf);
run_command(cmdBuf, 0);
}
#if defined(MV_INCLUDE_SPI)
else
spi_flash_erase(flash, destination, len);
#endif
}
static int do_mtdburn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
MV_U32 i, addr, src_addr, dest_addr;
MV_U32 kernel_unc_len, rootfs_unc_len = 0, unc_len, src_len;
MV_U32 kernel_addr = CFG_DEF_KERNEL_DEST_ADDR;
MV_U32 rootfs_addr = CFG_DEF_ROOTFS_DEST_ADDR;
MV_U32 total_in, rc, single_file = 0, bz2_file = 0;
char *from[] = {"tftp","usb","mmc", "ram"};
struct partitionInformation *partitionInfo = &nandInfo; /* default destination = NAND */
MV_U32 loadfrom = 0; /* Default source = tftp */
char * devPart = NULL;
MV_U32 fsys = FS_TYPE_FAT; /* default FS = FAT */
MV_BOOL isNand = MV_TRUE; /* default destination = NAND */
addr = load_addr = CFG_DEF_SOURCE_LOAD_ADDR;
int filesize, fileSizeFromRam = -1;
if (!isSwitchingServicesSupported())
return 0;
/* scan for flash destination in arguments (allowing usage of only 'mtdburn spi') */
for (i = 1 ; i < argc ; i++) {
if ((strcmp(argv[i], "spi") == 0) || (strcmp(argv[i], "SPI") == 0)) {
isNand = MV_FALSE;
partitionInfo = &spiInfo;
argc--; /* disregard 'spi' for next steps */
}
if ((strcmp(argv[i], "nand") == 0) || (strcmp(argv[i], "NAND") == 0))
argc--; /* disregard 'nand' for next steps */
}
switch(argc) {
case 7:
fileSizeFromRam = simple_strtoul(argv[6], NULL, 16);
case 6:/* arg#6 is flash destination, scanned previously --> fall to 5*/
case 5:
if(strcmp(argv[4], "EXT2") == 0)
fsys = FS_TYPE_EXT;
/* fall to 4*/
case 4:
devPart = argv[3];
/* fall to 3*/
case 3:
if(strcmp(argv[2], "usb") == 0)
loadfrom = 1;
else if(strcmp(argv[2], "mmc") == 0)
loadfrom = 2;
else if(strcmp(argv[2], "ram") == 0) {
loadfrom = 3;
if (devPart != NULL)
addr = load_addr = (unsigned int)simple_strtoul(devPart, NULL, 16);
}
if ((loadfrom == 1 || loadfrom == 2) && devPart == NULL) /* if using USB/MMC, and not selected interface num */
devPart = "0"; /* default interface number is 0 */
/* fall to 2*/
case 2:
copy_filename (BootFile, argv[1], sizeof(BootFile));
case 1: /* no parameter all default */
if (argc < 2)
copy_filename (BootFile, partitionInfo->defaultImage, sizeof(BootFile));
break;
default:
return 0;
}
printf(" - Load from device \t: %s", from[loadfrom]);
if (devPart != NULL) {
printf(", Interface :%s" ,devPart);
if (fsys == FS_TYPE_FAT)
printf("\n - File System \t\t: FAT");
else if (fsys == FS_TYPE_EXT)
printf("\n - File System \t\t: EXT2");
} else {
if (loadfrom == 3) /* source = DRAM */
printf(", load from :%#lx" ,load_addr);
}
printf("\n - Filename\t\t: %s \n" ,BootFile);
printf(" - Flash destination\t: %s\n" , isNand == MV_TRUE ? "NAND" : "SPI");
if (mvVerifyRequest() == MV_FALSE)
return 0;
if (isNand == MV_FALSE) {
#if defined(MV_INCLUDE_SPI)
if (!flash) {
flash = spi_flash_probe(0, 0, CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
if (!flash) {
printf("Failed to probe SPI Flash\n");
return 0;
}
}
#else
printf("SPI Flash is not supported\n");
return 0;
#endif
}
/* Fetch requested file, filesize is needed for single image only */
if (loadfrom < 3) /* if Source is not RAM, fetch file (if source = RAM, file should be ready */
filesize = mvLoadFile4cpss(loadfrom, BootFile, devPart, fsys);
else if (fileSizeFromRam != -1) /* if specified a specific file size for single image file on ram */
filesize = fileSizeFromRam;
else /* if filesize not specified, try maximum limit for single image */
filesize = partitionInfo->KERNEL_SIZE + partitionInfo->ROOTFS_SIZE;
if(filesize <=0 )
return 0;
if (filesize > partitionInfo->FLASH_SIZE) {
printf("file too big\n");
return 0;
}
printf("\nTrying separation of kernel/vxWorks-image and root_fs. Work areas=0x%08x,0x%08x\n",
kernel_addr, rootfs_addr);
dest_addr = kernel_addr; // uncompress the kernel here.
src_addr = addr;
src_len = unc_len = kernel_addr - addr;
rc = BZ2_bzBuffToBuffDecompress_extended ((char*)dest_addr, &unc_len,
(char *)src_addr, src_len,
&total_in, 0, 0);
printf("\n");
kernel_unc_len = unc_len;
if (rc == 0) {
printf("kernel separation ended ok. unc_len=%d, total_in=%d\n",unc_len, total_in);
bz2_file++;
} else if (rc == -5) {
printf("Not a valid bz2 file, assume plain single image file ?");
if (mvVerifyRequest() == MV_FALSE)
return 0;
single_file = 1;
kernel_unc_len = filesize;
kernel_addr = load_addr;
} else {
printf("Uncompress of kernel ended with error. rc=%d\n", rc);
return 0;
}
if (!single_file) {
/* now try to separate the rootfs. If we get -5 then we have a single file. */
dest_addr = rootfs_addr; // uncompress the rootfs here.
src_addr += total_in;
src_len = unc_len = kernel_addr - addr - total_in;
rc = BZ2_bzBuffToBuffDecompress_extended ((char*)dest_addr, &unc_len, (char *)src_addr,
src_len, &total_in, 0, 0);
printf("\n");
rootfs_unc_len = unc_len;
if (rc == 0) {
bz2_file++;
printf("rootfs separation ended ok. unc_len=%d, total_in=%d\n", unc_len, total_in);
if (unc_len > partitionInfo->ROOTFS_SIZE) {
printf("rootfs too big\n");
return 0;
}
} else if (rc == -5) {
printf("One single bz2 file detected\n");
single_file = 1;
} else {
printf("Uncompress of rootfs ended with error. rc=%d\n", rc);
return 0;
}
}
if (!single_file && kernel_unc_len > partitionInfo->KERNEL_SIZE) {
printf("kernel too big to fit in flash\n");
return 0;
} else if (kernel_unc_len > (partitionInfo->KERNEL_SIZE + partitionInfo->ROOTFS_SIZE)) {
// we are now dealing with single file
printf("Single image too big to fit in flash\n");
if (bz2_file) {
printf("Trying to fit the compressed image on flash\n");
if (filesize > (partitionInfo->KERNEL_SIZE + partitionInfo->ROOTFS_SIZE)) {
printf("Single image compressed format too big to fit in flash\n");
return 0;
}
/* point to the bz2 image in memory */
kernel_unc_len = filesize;
kernel_addr = load_addr;
} else
return 0;
}
/* Erase entire NAND flash - avoid invalid file system preparations */
if (isNand == MV_TRUE) {
printf("\nGoing to erase the entire NAND flash. ");
if (mvVerifyRequest() == MV_TRUE)
run_command("nand erase.chip", 0);
}
printf("\nBurning %s on flash at 0x%08x, length=%dK\n",
(single_file) ? "single image" : "kernel",
partitionInfo->KERNEL_START, kernel_unc_len/_1K);
printf("Erasing 0x%x - 0x%x: (%dMB)\n", partitionInfo->KERNEL_START,
partitionInfo->KERNEL_START + partitionInfo->KERNEL_SIZE,
partitionInfo->KERNEL_SIZE / _1M);
flashErase(partitionInfo->KERNEL_START, partitionInfo->KERNEL_SIZE, isNand);
printf("\t\t[Done]\n");
printf("\nCopy to Flash\n");
flashWrite(partitionInfo->KERNEL_START, kernel_unc_len, kernel_addr, isNand);
printf("\n");
if (!single_file) {
printf("Erasing 0x%x - 0x%x: (%dMB)\n", partitionInfo->ROOTFS_START,
partitionInfo->ROOTFS_START + partitionInfo->ROOTFS_SIZE,
partitionInfo->ROOTFS_SIZE / _1M);
flashErase(partitionInfo->ROOTFS_START, partitionInfo->ROOTFS_SIZE, isNand);
printf("\nBurning rootfs on flash at 0x%08x, length=%dK\n",
partitionInfo->ROOTFS_START, (rootfs_unc_len / _1K));
printf("\nCopy to Flash\n");
flashWrite(partitionInfo->ROOTFS_START, rootfs_unc_len, rootfs_addr, isNand);
printf("\n");
}
printf("\nDo you want to prepare CPSS environment variables (mtdparts & bootcmd) ? [y/N]");
if (mvVerifyRequest() == MV_TRUE)
run_command("cpss_env", 0);
return 1;
}
U_BOOT_CMD(
mtdburn, 6, 1, do_mtdburn,
"Burn a Linux image and Filesystem` on the NAND/SPI flash.\n",
"[filename [interface [<dev[:part]> [File system]]]] [flash destination] [single file size on RAM]\n"
"\tinterface : ram <load address>, tftp, or mmc/usb <interface_num> (default is tftp)\n"
"\tFile system: FAT or EXT2 (default is FAT).\n"
"\tNAND default file-name is ubifs_arm_nand.image.\n"
"\tSPI default file-name is jffs2_arm.image.\n"
"\tFlash Destination: nand or spi (default is nand). \n"
"\te.g. TFTP: 'mtdburn ubifs_arm_nand.image'\n"
"\te.g. MMC: 'mtdburn ubifs_arm_nand.image mmc 0 FAT nand'\n"
"\te.g. RAM: 'mtdburn ubifs_arm_nand.image ram 5000000 nand'\n"
);
#define SMI_WRITE_ADDRESS_MSB_REGISTER (0x00)
#define SMI_WRITE_ADDRESS_LSB_REGISTER (0x01)
#define SMI_WRITE_DATA_MSB_REGISTER (0x02)
#define SMI_WRITE_DATA_LSB_REGISTER (0x03)
#define SMI_READ_ADDRESS_MSB_REGISTER (0x04)
#define SMI_READ_ADDRESS_LSB_REGISTER (0x05)
#define SMI_READ_DATA_MSB_REGISTER (0x06)
#define SMI_READ_DATA_LSB_REGISTER (0x07)
#define SMI_STATUS_REGISTER (0x1f)
#define SMI_STATUS_WRITE_DONE (0x02)
#define SMI_STATUS_READ_READY (0x01)
//#define SMI_WAIT_FOR_STATUS_DONE
#define SMI_TIMEOUT_COUNTER 10000
static int phy_in_use(MV_U32 phy_addr)
{
int i;
for (i = 0; i < mvCtrlEthMaxPortGet(); i++) {
if (mvBoardPhyAddrGet(i) == phy_addr)
return 1;
}
return 0;
}
static inline void smiWaitForStatus(MV_U32 phyAddr)
{
#ifdef SMI_WAIT_FOR_STATUS_DONE
volatile unsigned int stat;
unsigned int timeOut;
MV_STATUS rc;
/* wait for write done */
timeOut = SMI_TIMEOUT_COUNTER;
do {
rc = mvEthPhyRegRead(phyAddr, SMI_STATUS_REGISTER, &stat);
if (rc != MV_OK)
return;
if (--timeOut < 1) {
printf("bspSmiWaitForStatus timeout !\n");
return;
}
} while ((stat & SMI_STATUS_WRITE_DONE) == 0);
#endif
}
int bspSmiReadReg(MV_U32 phyAddr, MV_U32 actSmiAddr, MV_U32 regAddr, MV_U32 *valuePtr)
{
/* Perform indirect smi read reg */
MV_STATUS rc;
MV_U16 msb, lsb;
/* write addr to read */
msb = regAddr >> 16;
lsb = regAddr & 0xFFFF;
rc = mvEthPhyRegWrite(phyAddr, SMI_READ_ADDRESS_MSB_REGISTER,msb);
if (rc != MV_OK)
return rc;
rc = mvEthPhyRegWrite(phyAddr, SMI_READ_ADDRESS_LSB_REGISTER,lsb);
if (rc != MV_OK)
return rc;
smiWaitForStatus(phyAddr);
/* read data */
rc = mvEthPhyRegRead(phyAddr, SMI_READ_DATA_MSB_REGISTER, &msb);
if (rc != MV_OK)
return rc;
rc = mvEthPhyRegRead(phyAddr, SMI_READ_DATA_LSB_REGISTER, &lsb);
if (rc != MV_OK)
return rc;
*valuePtr = ((msb & 0xFFFF) << 16) | (lsb & 0xFFFF);
return 0;
}
int bspSmiScan(int instance, int noisy)
{
int found1 = 0;
int found2 = 0;
int i;
unsigned int data;
/* scan for SMI devices */
for (i = 0; i < 32; i++) {
bspSmiReadReg(i, 0, 0x3, &data);
if (data != 0xffffffff && data != 0xffff) {
bspSmiReadReg(i, 0, 0x50, &data);
if (data == 0x000011ab || data == 0xab110000) {
if (instance == found1++) {
bspSmiReadReg(i, 0, 0x4c, &data);
printf("Smi Scan found Marvell device at smi_addr 0x%x, "
"reg 0x4c=0x%08x\n", i, data);
found2 = 1;
break;
}
}
}
}
if (!found2) {
if (noisy)
printf("Smi scan found no device\n");
return 0;
}
return i;
}
static int do_smi_scan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
int rc = 0;
printf("Performing SMI scan\n");
for (i = 0; i < 32; i++) {
if (!phy_in_use(i))
rc += bspSmiScan(i, 0);
}
if (rc == 0)
printf("smiscan found not device\n");
return 1;
}
U_BOOT_CMD(
smiscan, 1, 1, do_smi_scan,
"smiscan - Scan for marvell smi devices.\n",
""
);
SILICON_TYPE get_attached_silicon_type(void)
{
int Device;
int Function;
int BusNum;
unsigned char HeaderType;
unsigned short VendorID;
unsigned short DeviceID;
pci_dev_t dev;
SILICON_TYPE silt = SILT_OTHER;
for (BusNum = 0; BusNum < 10; BusNum ++)
for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) {
HeaderType = 0;
VendorID = 0;
for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) {
/*
* If this is not a multi-function device, we skip the rest.
*/
if (Function && !(HeaderType & 0x80))
break;
dev = PCI_BDF(BusNum, Device, Function);
pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
continue;
pci_read_config_word(dev, PCI_DEVICE_ID, &DeviceID);
if ((DeviceID == 0xFFFF) || (DeviceID == 0x0000))
continue;
if ( (VendorID == MARVELL_VENDOR_ID) &&
(((DeviceID & MV_PP_CHIP_TYPE_MASK) >> MV_PP_CHIP_TYPE_OFFSET) ==
MV_PP_CHIP_TYPE_XCAT2)
)
silt = SILT_XCAT2;
else if ((VendorID == MARVELL_VENDOR_ID) && (DeviceID == NP5_DEVICE_ID))
silt = SILT_NP5;
else if ((VendorID == MARVELL_VENDOR_ID) && ( (DeviceID & 0xffe0) == BC2_DEVICE_ID))
silt = SILT_BC2;
return silt;
}
}
return silt;
}
#ifdef MV_MSYS
static int do_qsgmii_sel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int bit_mask, rc;
if (argc < 2)
goto usage;
bit_mask = (simple_strtoul(argv[1], NULL, 16) & 0x0000ffff);
rc = mvBoardTwsiWrite(BOARD_DEV_TWSI_PCA9555_IO_EXPANDER, 0, 2, (MV_U8)((bit_mask >> 0) & 0xff));
if(rc == MV_OK) {
mvBoardTwsiWrite(BOARD_DEV_TWSI_PCA9555_IO_EXPANDER, 0, 3, (MV_U8)((bit_mask >> 8) & 0xff));
mvBoardTwsiWrite(BOARD_DEV_TWSI_PCA9555_IO_EXPANDER, 0, 6, 0);
mvBoardTwsiWrite(BOARD_DEV_TWSI_PCA9555_IO_EXPANDER, 0, 7, 0);
return 1;
}
usage:
cmd_usage(cmdtp);
return 1;
}
U_BOOT_CMD(
qsgmii_sel, 2, 1, do_qsgmii_sel,
" Select SFP or QSGMII modes on bc2.\n",
" apply 16 bit array to select SFP or QSGMII modes"
);
#endif
void hwServicesLateInit(void)
{
char *env;
char buf[128];
printf("hwServices late init: ");
if ((env = getenv("qsgmii_ports_def"))) {
sprintf(buf, "qsgmii_sel %s\n", env);
printf(buf);
run_command(buf, 0);
}
printf("\n");
}