/*********************************************************************** * * Function: c_entry * * Purpose: Application entry point from the startup code * * Processing: * See function. * * Parameters: None * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ void c_entry(void) { UNS_8 *p8; INT_32 toread, idx; PFV execa = (PFV) STAGE1_LOAD_ADDR; /* Force SSP configuration, use GPIO_05 (SSP0_CS) in software control mode */ GPIO->p2_dir_set = P2_DIR_GPIO(5); GPIO->p2_mux_clr = P2_GPIO05_SSEL0; GPIO->p_mux_set = P_SPI1CLK_SCK0 | P_SPI1DATAIN_SSP0_MISO | P_SPI1DATAIO_SSP0_MOSI; board_spi_config(); /* Read data into memory */ toread = STAGE1_LOAD_SIZE; p8 = (UNS_8 *) STAGE1_LOAD_ADDR; idx = SPI_S1APP_OFFSET; while (toread > 0) { *p8 = board_spi_read(idx); p8++; idx++; toread--; } #ifdef USE_MMU dcache_flush(); dcache_inval(); icache_inval(); #endif execa(); }
void dcache_disable(void) { dcache_flush(); #ifndef CONFIG_SYS_NO_DCACHE cp15_dcache_disable(); #endif #ifdef CONFIG_CACHE_L2X0 l2x0_disable(); #endif }
//============================================================== unsigned test_w_l1cache(unsigned fill_value, unsigned modify_value) { unsigned *addr; unsigned size, err_addr, val; int i; // current dcache is disable // clear no-cache memory block addr = (unsigned*)no_cache_mem_start; size = (cache_size)/sizeof(unsigned); for(i=0; i<size; i++, addr++) *addr = fill_value; // asm("dmb"); // asm("isb"); // map cache-memory data to cache addr = (unsigned*)cache_mem_start; size = cache_size/CONFIG_SYS_CACHE_LINE_SIZE; dcache_enable(); // asm("dmb"); // asm("isb"); for(i=0; i<size; i++, addr+=CONFIG_SYS_CACHE_LINE_SIZE) val = *addr; // write to cache addr = (unsigned*)cache_mem_start; size = cache_size/sizeof(unsigned); for(i=0; i<size; i++, addr++){ *addr = modify_value; } dcache_flush(); dcache_clean(); dcache_disable(); dcache_invalid(); asm("mov r0, r0"); asm("mov r0, r0"); asm("mov r0, r0"); err_addr = 0; addr = (unsigned*)no_cache_mem_start; for(i=0; i<size; i++, addr++){ if(*addr != modify_value){ err_addr = (unsigned)addr; break; } } return err_addr; }
/*********************************************************************** * * Function: c_entry * * Purpose: Application entry point from the startup code * * Processing: * See function. * * Parameters: None * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ void c_entry(void) { UNS_8 *p8, ret; INT_32 toread, idx, blk, page, sector; PFV execa = (PFV) STAGE1_LOAD_ADDR; /* Initialize NAND FLASH */ if (nand_sb_slc_init() != 1) { while (1); } /* Read data into memory */ toread = STAGE1_LOAD_SIZE; blk = 1; page = 0; p8 = (UNS_8 *) STAGE1_LOAD_ADDR; while (toread > 0) { ret = nand_sb_slc_is_block_bad(blk); if (ret == 0) { while(page < nandgeom.pages_per_block) { sector = nand_bp_to_sector(blk, page); nand_sb_slc_read_sector(sector, tmpbuff,NULL); for (idx = 0; idx < 512; idx++) { *p8 = tmpbuff [idx]; p8++; } page++; toread = toread - 512; } blk++; page = 0; } else { blk++; } } #ifdef USE_MMU dcache_flush(); dcache_inval(); icache_inval(); #endif execa(); }
//============================================================== int l1cache_post_test(int flags) { int i; unsigned result, pattern=0; int status; status = dcache_status(); if(dcache_status() == OFF) dcache_enable(); dcache_flush(); icache_invalid(); dcache_clean(); dcache_disable(); // must invalid dcache after dcache_disable // if no valid dcache, dcache_enable() will jump here dcache_invalid(); asm("mov r0, r0"); asm("mov r0, r0"); asm("mov r0, r0"); for(i=0; i<ARRAY_SIZE(L1_cache_pattern); i++){ result = test_w_l1cache(0x55555555, L1_cache_pattern[i]); if(result != 0){ pattern = L1_cache_pattern[i]; break; } result = test_w_l1cache(0x55555555, ~L1_cache_pattern[i]); if(result != 0){ pattern = ~L1_cache_pattern[i]; break; } } if(status == ON) dcache_enable(); if(i<ARRAY_SIZE(L1_cache_pattern)){ post_log("<%d>%s:%d: l1cache: test fail: Error address=0x%x, pattern=0x%x\n", SYSTEST_INFO_L2, __FUNCTION__, __LINE__, result, pattern); return -1; } else{ post_log("<%d>l1cache test pattern count=%d\n", SYSTEST_INFO_L2, ARRAY_SIZE(L1_cache_pattern)); return 0; } }
void flush_cache (unsigned long dummy1, unsigned long dummy2) { dcache_flush(); return; }
/* * Sends a command out on the bus. Takes the mmc pointer, * a command pointer, and an optional data pointer. */ int aml_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { int ret = SD_NO_ERROR, num_res; unsigned buffer = 0; unsigned int cmd_send = 0; SDHW_CMD_Send_Reg_t *cmd_send_reg = (void *)&cmd_send; sd_debug("cmd=%d",cmd->cmdidx); cmd_send_reg->cmd_data = 0x40 | cmd->cmdidx; cmd_send_reg->use_int_window = 1; unsigned int cmd_ext = 0; SDHW_Extension_Reg_t *cmd_ext_reg = (void *)&cmd_ext; /* check read/write address overflow */ switch (cmd->cmdidx) { case MMC_CMD_READ_SINGLE_BLOCK: case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: if(mmc->high_capacity) ret = mmc->capacity/mmc->read_bl_len <= cmd->cmdarg; else ret = mmc->capacity <= cmd->cmdarg; if(ret) return -1; else break; } sd_inand_clear_response(cmd->response); switch (cmd->resp_type) { case MMC_RSP_R1: case MMC_RSP_R1b: case MMC_RSP_R3: case MMC_RSP_R6: case MMC_RSP_R7: cmd_send_reg->cmd_res_bits = 45; // RESPONSE have 7(cmd)+32(respnse)+7(crc)-1 data break; case MMC_RSP_R2: cmd_send_reg->cmd_res_bits = 133; // RESPONSE have 7(cmd)+120(respnse)+7(crc)-1 data cmd_send_reg->res_crc7_from_8 = 1; break; default: cmd_send_reg->cmd_res_bits = 0; // NO_RESPONSE break; } switch (cmd->cmdidx) { case MMC_CMD_READ_SINGLE_BLOCK: case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_SEND_EXT_CSD: //same as: SD_CMD_SEND_IF_COND case SD_CMD_SWITCH_FUNC: //same as: MMC_CMD_SWITCH if(!data) break; // dcache_flush(); cmd_send_reg->res_with_data = 1; cmd_send_reg->repeat_package_times = data->blocks - 1; if(mmc->bus_width == SD_BUS_WIDE) cmd_ext_reg->data_rw_number = data->blocksize * 8 + (16 - 1) * 4; else cmd_ext_reg->data_rw_number = data->blocksize * 8 + 16 - 1; buffer = dma_map_single((void*)data->dest,data->blocks*data->blocksize,DMA_FROM_DEVICE); //buffer = data->dest; //dcache_invalid_range(buffer,data->blocks<<9); break; case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: cmd_send_reg->cmd_send_data = 1; cmd_send_reg->repeat_package_times = data->blocks - 1; if(mmc->bus_width == SD_BUS_WIDE) cmd_ext_reg->data_rw_number = data->blocksize * 8 + (16 - 1) * 4; else cmd_ext_reg->data_rw_number = data->blocksize * 8 + 16 - 1; buffer = dma_map_single((void*)data->src,data->blocks*data->blocksize,DMA_TO_DEVICE);//(char *)data->src; // dcache_clean_range(buffer,data->blocks<<9); // dcache_flush(); break; case SD_CMD_APP_SEND_SCR: cmd_send_reg->res_with_data = 1; if(mmc->bus_width == SD_BUS_WIDE) cmd_ext_reg->data_rw_number = data->blocksize * 8 + (16 - 1) * 4; else cmd_ext_reg->data_rw_number = data->blocksize * 8 + 16 - 1; //buffer = (char *)data->src; //dcache_flush(); buffer = dma_map_single(data->dest,cmd_ext_reg->data_rw_number,DMA_BIDIRECTIONAL);//(char *)data->src; break; default: break; } //cmd with R1b switch (cmd->cmdidx) { case MMC_CMD_STOP_TRANSMISSION: cmd_send_reg->check_dat0_busy = 1; break; default: break; } //cmd with R3 switch (cmd->cmdidx) { case MMC_CMD_SEND_OP_COND: case SD_CMD_APP_SEND_OP_COND: cmd_send_reg->res_without_crc7 = 1; break; default: break; } #define SD_READ_BUSY_COUNT 5000000//20 #define SD_WRITE_BUSY_COUNT 1000000//500000 #define SD_RETRY_COUNT 8 unsigned int timeout, timeout_count, repeat_time = 0; if(cmd_send_reg->cmd_send_data){ if(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK) timeout = SD_WRITE_BUSY_COUNT * (data->blocks); else timeout = SD_WRITE_BUSY_COUNT; } else { if(cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) timeout = SD_READ_BUSY_COUNT * (data->blocks); else timeout = SD_READ_BUSY_COUNT; } if(cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) timeout = 2000; unsigned int status_irq = 0; SDIO_Status_IRQ_Reg_t *status_irq_reg = (void *)&status_irq; unsigned int irq_config = 0; MSHW_IRQ_Config_Reg_t *irq_config_reg = (void *)&irq_config; CMD_RETRY: status_irq_reg->if_int = 1; status_irq_reg->cmd_int = 1; sd_debug("PREG_SDIO_STAT_IRQ=%x PREG_SDIO_MEM_ADDR=%x PREG_SDIO_CMD_SEND=%x",status_irq,buffer,cmd_send); sd_debug("PREG_SDIO_CMD_ARG =%x PREG_SDIO_EXT=%x",cmd->cmdarg,cmd_ext); writel(status_irq|(0x1fff<<19), PREG_SDIO_STAT_IRQ); writel(cmd->cmdarg, PREG_SDIO_CMD_ARG); writel(cmd_ext, PREG_SDIO_EXT); writel((unsigned int)buffer, PREG_SDIO_MEM_ADDR); writel(cmd_send, PREG_SDIO_CMD_SEND); timeout_count = 0; while (1) { status_irq = readl(PREG_SDIO_STAT_IRQ); if(!status_irq_reg->cmd_busy && status_irq_reg->cmd_int) break; if((++timeout_count) > timeout) { if(!cmd->flags) return TIMEOUT; irq_config_reg->soft_reset = 1; writel(irq_config, PREG_SDIO_IRQ_CFG); if((++repeat_time) > SD_RETRY_COUNT) return TIMEOUT; goto CMD_RETRY; } if(cmd_send_reg->cmd_send_data) udelay(100); if(cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) udelay(1000); } if(cmd_send_reg->cmd_res_bits && !cmd_send_reg->res_without_crc7 && !status_irq_reg->res_crc7_ok) return SD_ERROR_COM_CRC; switch (cmd->resp_type) { case MMC_RSP_R1: case MMC_RSP_R1b: case MMC_RSP_R3: case MMC_RSP_R6: case MMC_RSP_R7: num_res = RESPONSE_R1_R3_R6_R7_LENGTH; break; case MMC_RSP_R2: num_res = RESPONSE_R2_CID_CSD_LENGTH; break; default: num_res = RESPONSE_R4_R5_NONE_LENGTH; break; } /* switch (cmd->cmdidx) { case MMC_CMD_READ_SINGLE_BLOCK: case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_SEND_EXT_CSD: //same as: SD_CMD_SEND_IF_COND case SD_CMD_SWITCH_FUNC: //same as: MMC_CMD_SWITCH case SD_CMD_APP_SEND_SCR: if(!data) break; dma_unmap_single((void*)data->dest,data->blocks*data->blocksize,buffer); break; case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: dma_unmap_single((void*)data->src,data->blocks*data->blocksize,buffer); break; default: break; }*/ dcache_flush(); if (num_res > 0) { unsigned int multi_config = 0; SDIO_Multi_Config_Reg_t *multi_config_reg = (void *)&multi_config; multi_config_reg->write_read_out_index = 1; writel(multi_config, PREG_SDIO_MULT_CFG); num_res--; // Minus CRC byte } unsigned int data_temp; unsigned int loop_num = (num_res + 3 - 1) /4; while (num_res > 0) { data_temp = readl(PREG_SDIO_CMD_ARG); if(num_res <= 1) break; cmd->response[--num_res - 1] = data_temp & 0xFF; if(num_res <= 1) break; cmd->response[--num_res - 1] = (data_temp >> 8) & 0xFF; if(num_res <= 1) break; cmd->response[--num_res - 1] = (data_temp >> 16) & 0xFF; if(num_res <= 1) break; cmd->response[--num_res - 1] = (data_temp >> 24) & 0xFF; } while (loop_num--) { ((uint *)cmd->response)[loop_num] = __be32_to_cpu(((uint *)cmd->response)[loop_num]); } //check_response ret = sd_inand_check_response(cmd); if(ret) return ret; //cmd with adtc switch (cmd->cmdidx) { case MMC_CMD_READ_SINGLE_BLOCK: case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_SEND_EXT_CSD: //same as SD_CMD_SEND_IF_COND case SD_CMD_SWITCH_FUNC: //same as: MMC_CMD_SWITCH if(!data) break; if(!status_irq_reg->data_read_crc16_ok) return SD_ERROR_DATA_CRC; break; case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: if(!status_irq_reg->data_write_crc16_ok) return SD_ERROR_DATA_CRC; break; case SD_CMD_APP_SEND_SCR: if(!status_irq_reg->data_read_crc16_ok) return SD_ERROR_DATA_CRC; break; default: break; } return SD_NO_ERROR; }