MC3302_SDK_V1.1.9_202507281.../bsp/ramboot/common/sdl/sdl.c
2025-11-11 12:08:31 +08:00

449 lines
11 KiB
C
Executable File

/*
* (C) Copyright 2019-2020
* Stelian Pop <junbao.zhang@molchip.com>
* Lead Tech Design <www.molchip.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <mach/clk.h>
#include <mach/spl.h>
#include <mach/uart_drv.h>
#include <mach/uart.h>
#include <mach/spic.h>
#include <mach/norflash.h>
#include <mach/nandflash.h>
#include <mach/download.h>
#include <mach/board.h>
#include <mach/dma.h>
#include <mach/ddr.h>
#include <nand.h>
#include "../../board/molchip/board/system.h"
#ifdef CONFIG_SDL_MMC_SUPPORT
#include "mach/sd_mmc.h"
#endif
#ifdef CONFIG_ARM64
void hang(void)
{
while(1);
}
#endif
void s_init(void)
{
//timer clk init
molchip_systimer_clk_enable();
//uart0 clk init
molchip_uart_clk_enable(REG_UART0_BASE);
//uart1 clk init
molchip_uart_clk_enable(REG_UART1_BASE);
//spic clk enable
molchip_spic_clk_enable();
#ifndef CONFIG_TARGET_TS01
//dma clk enable
molchip_dma_clk_enable();
#endif
}
/* This function prepares the hardware for
* execution from system RAM (DRAM, DDR...) As system RAM may not
* be available yet, , board_init_f() must use the current GD to
* store any data which must be passed on to later stages. These
* data include the relocation destination, the future stack, and
* the future GD location.
*
* bss data not init
*/
void board_init_f(ulong dummy)
{
/* CPU/BUS CLK config if needed*/
/* hardware init */
//uart_hw_init();
board_spic_init();
}
#ifdef CONFIG_SDL_MMC_SUPPORT
u32 rd_buf = 0x70000000;
void emmc_mini_init(void)
{
u32 i;
int err = false;
u32 rca = 1;
u32 csd[4] = {0};
mmc_clk_set();
mmc_phy_init();
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
sdhci_init(0, freqs[i]);
get_rom_version();
err = init_emmc(&rca, csd);
if(err == true)
break;
}
if(err == false) {
printf("emmc init fail!!!\n");
}
sdhci_set_ios(TRANS_DATA_FREQS);
}
int sdhci_all_data_tran_done(void)
{
u32 val;
val = sdhci_readl(SDHCI_INT_STATUS);
if(val & SDHCI_INT_ERROR){
return -1;
}
if (val & SDHCI_INT_RESPONSE) {
if(val & SDHCI_INT_DATA_END) {
sdhci_writel(val, SDHCI_INT_STATUS);
return 0;
}
else {
if(val & SDHCI_INT_DMA_END){
int start_addr;
start_addr = sdhci_readl(SDHCI_ADMA_ADDRESS);
sdhci_writel(SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
sdhci_writel(start_addr, SDHCI_ADMA_ADDRESS);
}
}
}
return 1;
}
int sdl_emmc_program_image( u32 dest, u32 len, u32 addr)
{
int err;
u32 size;
u8 boot_partition;
u32 sector;
struct mmc_command stop = {0};
boot_partition = ext_csd[EXT_CSD_PART_CONFIG];
boot_partition &= EXT_CSD_PART_CONFIG_BOOT_MASK;
size = ALIGN(len, 512);
sector = ALIGN(dest, 512)/512;
boot_partition &= ~0x07;
boot_partition |= 1;
err = emmc_switch(EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, boot_partition);
emmc_get_ext_csd((u8 **)ext_csd);
err = emmc_blk_mq_issue_rw_rq(WRITE, addr, sector, size);
while(0 != sdhci_all_data_tran_done());
stop.opcode = MMC_STOP_TRANSMISSION;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
err = mmc_start_request(&stop);
boot_partition &= ~0x07;
boot_partition |= 2;
err = emmc_switch(EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, boot_partition);
err = emmc_blk_mq_issue_rw_rq(WRITE, addr, sector, size);
while(0 != sdhci_all_data_tran_done());
stop.opcode = MMC_STOP_TRANSMISSION;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
err = mmc_start_request(&stop);
if(err == 1)
return 0;
return 0;
}
int sdl_emmc_program_user_part(u32 dest, u32 len, u32 addr)
{
int err;
u8 boot_partition;
u32 sector;
u32 size;
struct mmc_command stop = {0};
size = ALIGN(len, 512);
sector = ALIGN(dest, 512)/512;
boot_partition = ext_csd[EXT_CSD_PART_CONFIG];
boot_partition &= EXT_CSD_PART_CONFIG_BOOT_MASK;
boot_partition &= ~0x07;
err = emmc_switch(EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, boot_partition);
emmc_get_ext_csd((u8 **)ext_csd);
//while(sdhci_all_data_tran_done() != 0);
err = emmc_blk_mq_issue_rw_rq(WRITE, addr, sector, size);
while(sdhci_all_data_tran_done() != 0);
stop.opcode = MMC_STOP_TRANSMISSION;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
err = mmc_start_request(&stop);
if(err == 1){
return 0;
}
return 0;
}
#endif
#ifdef CONFIG_SDL_NAND_SUPPORT
int spi_nand_program_image(u32 dest, u32 len, u8 *buf)
{
nand_erase_options_t opts;
int ret;
struct mtd_info *mtd;
u32 actual;
loff_t lim;
struct spi_nand_info *nand_info;
struct nand_chip *chip ;
u32 length = (64<<11);
u8 *buf_tmp;
buf_tmp = buf + 0x1000000;
mtd = get_nand_dev_by_index(0);
chip = mtd_to_nand(mtd);
if(len <length){
length = mtd->erasesize ;
memset(buf_tmp, 0xff, length);
memcpy(buf_tmp, buf, len);
}
else{
if(dest == 0){
length = mtd->erasesize + UBOOT_MAX_SIZE;
memset(buf_tmp, 0xff, length);
memcpy(buf_tmp, buf, (32<<10));
memcpy(buf_tmp + mtd->erasesize, buf+(32<<10), len-(32<<10));
}
else{
memset(buf_tmp, 0xff, len);
memcpy(buf_tmp, buf, len);
length = len;
}
}
if(dest == 0)
{
nand_info = (struct spi_nand_info *)(buf_tmp + NAND_INFO_OFFSET);
memset(nand_info, 0,sizeof(struct spi_nand_info));
sfc_write_data((u8 *)buf_tmp, 512);
sfc_all_clr();
sfc_data_length(512);
sfc_spare_length(0);
sfc_ecc_mode(ECC_24BIT);
sfc_ecc_pos(0x0);
sfc_ecc_enc_mode(true);
sfc_access_start();
sfc_read_spare(nand_info->ecc,44,1);
nand_info->main_size = 2048;
if(mtd->writesize == 4096)
nand_info->oob_size = mtd->oobsize/2;
else
nand_info->oob_size = mtd->oobsize;
nand_info->sector_num = nand_info->main_size >> 10;
nand_info->block_page = mtd->erasesize / mtd->writesize;
if (chip->options & SPINAND_ECC_MODE_24_bit) {
nand_info->ecc_mode = 1;
nand_info->ecc_pos = nand_info->oob_size / nand_info->sector_num - 42;
nand_info->spare_size = nand_info->ecc_pos;
} else {
nand_info->ecc_mode = 0;
nand_info->ecc_pos = nand_info->oob_size / nand_info->sector_num - 14;
nand_info->spare_size = nand_info->ecc_pos;
}
// memcpy(buf_tmp + mtd->erasesize, buf_tmp, (32<<10));
}
lim = chip->chipsize;
memset(&opts, 0, sizeof(opts));
opts.offset = dest;
opts.length = length;
opts.quiet = 1;
ret = nand_erase_opts(mtd, &opts);
if (ret){
return ret;
}
if((mtd->writesize == 4096) && (dest == 0)){
int temp_len = 32*1024;
ret = nand_write_skip_bad(mtd, dest, (size_t *)&temp_len, &actual,
lim, buf_tmp, WITH_WR_VERIFY);
if(ret){
return ret;
}
temp_len = length - mtd->erasesize;
ret = nand_write_skip_bad(mtd, dest+256*1024, (size_t *)&temp_len, &actual,
lim, (buf_tmp + 256*1024) , WITH_WR_VERIFY);
if(ret){
return ret;
}
}
else{
ret = nand_write_skip_bad(mtd, dest, (size_t *)&length, &actual,
lim, buf_tmp, WITH_WR_VERIFY);
if(ret){
return ret;
}
}
return 0;
}
#endif
#if 1
static void boot_mode_pinmux_set(unsigned int boot_mode, unsigned int group_id)
{
switch (boot_mode) {
case 1:
*(volatile unsigned int*)0x10200110 = 0; /* EMMC D0 */
*(volatile unsigned int*)0x10200114 = 0; /* EMMC D1 */
*(volatile unsigned int*)0x10200118 = 0; /* EMMC D2 */
*(volatile unsigned int*)0x1020011C = 0; /* EMMC D3 */
*(volatile unsigned int*)0x10200130 = 0; /* EMMC CMD */
*(volatile unsigned int*)0x10200134 = 0; /* EMMC CLK */
*(volatile unsigned int*)0x10200138 = 0; /* EMMC RSTN */
if(group_id == 0) {
*(volatile unsigned int*)0x1020013C = 0; /* EMMC DS */
*(volatile unsigned int*)0x10200120 = 0; /* EMMC D4 */
*(volatile unsigned int*)0x10200124 = 0; /* EMMC D5 */
*(volatile unsigned int*)0x10200128 = 0; /* EMMC D6 */
*(volatile unsigned int*)0x1020012C = 0; /* EMMC D7 */
} else {
*(volatile unsigned int*)0x10200144 = 5; /* EMMC DS */
*(volatile unsigned int*)0x10200148 = 5; /* EMMC D4 */
*(volatile unsigned int*)0x1020014C = 5; /* EMMC D5 */
*(volatile unsigned int*)0x10200150 = 5; /* EMMC D6 */
*(volatile unsigned int*)0x10200154 = 5; /* EMMC D7 */
}
break;
case 5:
*(volatile unsigned int*)0x10200140 = 0; /* SFC CLK */
*(volatile unsigned int*)0x10200144 = 0; /* SFC CS0N */
*(volatile unsigned int*)0x10200148 = 0; /* SFC MOSI IO0 */
*(volatile unsigned int*)0x1020014C = 0; /* SFC MISO IO1 */
*(volatile unsigned int*)0x10200150 = 0; /* SFC WP IO2 */
*(volatile unsigned int*)0x10200154 = 0; /* SFC HOLD IO3 */
*(volatile unsigned int*)0x10200158 = 0; /* SFC CS1N */
*(volatile unsigned int*)0x1c700014 = 0x10; /*sfc boa */
*(volatile unsigned int*)0x10300228 = 0x0; /*sfc boa */
break;
default:
break;
}
}
#endif
void board_init_r(gd_t *gd, ulong dest_addr)
{
u32 uart_port = 0;
u32 nvm_mod;
u32 idx;
struct down_info *d_info;
u32 ram_downaddr,nvm_downaddr,image_id;
u32 i=0;
int ret = 0;
struct boot_image *images= (struct boot_image *)(CONFIG_SPL_TEXT_BASE - BOOT_INFO_OFFSET);
nvm_mod = images->nvm_class;
struct boot_image_info *info = (struct boot_image_info *)(&images->data[0]);
timer_enable();
mem_malloc_init(AON_SHARE_SRAM, (64<<10));
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#ifdef CONFIG_SDL_NAND_SUPPORT
if(nvm_mod == BOOT_DEVICE_NAND)
nand_init();
#endif
#ifdef CONFIG_SDL_MMC_SUPPORT
if(nvm_mod == BOOT_DEVICE_EMMC)
emmc_mini_init();
#endif
#ifdef CONFIG_TARGET_TS01
//store ddr parameter
DRAM_param_store(nvm_mod);
#endif
boot_mode_pinmux_set(nvm_mod,0);
uart_port = uart_identify();
uart_preboot(uart_port);
while(1)
{
uart_boot(uart_port);
d_info = get_cur_downinfo();
image_id = get_downmap_info(d_info,IMGID_CMD);
idx = image_id - 1;
switch(nvm_mod)
{
case BOOT_DEVICE_NAND:
#ifdef CONFIG_SDL_NAND_SUPPORT
ram_downaddr = get_downmap_info(d_info,IMGRAMADDR_CMD);
nvm_downaddr = info[idx].nvm_base;
ret = spi_nand_program_image(nvm_downaddr,d_info->total_len,(u8*)(unsigned long)ram_downaddr);
//mark,just for debug
*((volatile u32 *)(unsigned long)(0x47FFFF00+i * 4)) = d_info->imageid | (i<< 16);
*((volatile u32 *)(unsigned long)(0x47FFFF20+i * 4)) = nvm_downaddr;
*((volatile u32 *)(unsigned long)(0x47FFFF40+i * 4)) = d_info->total_len;
*((volatile u32 *)(unsigned long)(0x47FFFF60+i * 4)) = ram_downaddr;
i++;
#endif
break;
case BOOT_DEVICE_NOR:
ram_downaddr = get_downmap_info(d_info,IMGRAMADDR_CMD);
nvm_downaddr = info[idx].nvm_base;
ret = spi_nor_program_image(nvm_downaddr,d_info->total_len,(u8*)(unsigned long)ram_downaddr);
//mark,just for debug
*((volatile u32 *)(unsigned long)(0x47FFFF00+i * 4)) = d_info->imageid | (i<< 16);
*((volatile u32 *)(unsigned long)(0x47FFFF20+i * 4)) = nvm_downaddr;
*((volatile u32 *)(unsigned long)(0x47FFFF40+i * 4)) = d_info->total_len;
*((volatile u32 *)(unsigned long)(0x47FFFF60+i * 4)) = ram_downaddr;
i++;
break;
#ifdef CONFIG_SDL_MMC_SUPPORT
case BOOT_DEVICE_EMMC:
ram_downaddr = get_downmap_info(d_info,IMGRAMADDR_CMD);
nvm_downaddr = info[idx].nvm_base;
if(image_id == Kernel_IMG_ID || image_id == Uboot_IMG_ID)
{
ret = sdl_emmc_program_user_part( nvm_downaddr,d_info->total_len, ram_downaddr);
}
else
{
ret = sdl_emmc_program_image( nvm_downaddr,d_info->total_len, ram_downaddr);
}
break;
#endif
}
if (ret == 0){
complete_info(INFO_OK, uart_port);
}
else{
complete_info(INFO_OTHER, uart_port);
}
}
}