GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
|
||||
#include "emmc_config.h"
|
||||
#include "emmc_def.h"
|
||||
#include "emmc_hal.h"
|
||||
#include "emmc_std.h"
|
||||
#include "io_common.h"
|
||||
#include "io_emmcdrv.h"
|
||||
#include "io_private.h"
|
||||
|
||||
static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)),
|
||||
io_dev_info_t **dev_info);
|
||||
static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info);
|
||||
|
||||
typedef struct {
|
||||
uint32_t in_use;
|
||||
uintptr_t base;
|
||||
signed long long file_pos;
|
||||
EMMC_PARTITION_ID partition;
|
||||
} file_state_t;
|
||||
|
||||
static file_state_t current_file = { 0 };
|
||||
|
||||
static EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER;
|
||||
|
||||
static io_type_t device_type_emmcdrv(void)
|
||||
{
|
||||
return IO_TYPE_MEMMAP;
|
||||
}
|
||||
|
||||
static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode,
|
||||
signed long long offset)
|
||||
{
|
||||
if (mode != IO_SEEK_SET) {
|
||||
return IO_FAIL;
|
||||
}
|
||||
|
||||
((file_state_t *) entity->info)->file_pos = offset;
|
||||
|
||||
return IO_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer,
|
||||
size_t length, size_t *length_read)
|
||||
{
|
||||
file_state_t *fp = (file_state_t *) entity->info;
|
||||
uint32_t sector_add, sector_num, emmc_dma = 0;
|
||||
int32_t result = IO_SUCCESS;
|
||||
|
||||
sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT;
|
||||
sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT;
|
||||
|
||||
NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n",
|
||||
buffer,
|
||||
current_file.partition, current_file.file_pos,
|
||||
sector_add, length, sector_num);
|
||||
|
||||
if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) {
|
||||
emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE;
|
||||
}
|
||||
|
||||
if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num,
|
||||
emmc_dma) != EMMC_SUCCESS) {
|
||||
result = IO_FAIL;
|
||||
}
|
||||
|
||||
*length_read = length;
|
||||
fp->file_pos += (signed long long)length;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int32_t emmcdrv_block_open(io_dev_info_t *dev_info,
|
||||
const uintptr_t spec, io_entity_t *entity)
|
||||
{
|
||||
const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec;
|
||||
|
||||
if (current_file.in_use != 0U) {
|
||||
WARN("mmc_block: Only one open spec at a time\n");
|
||||
return IO_RESOURCES_EXHAUSTED;
|
||||
}
|
||||
|
||||
current_file.file_pos = 0;
|
||||
current_file.in_use = 1;
|
||||
|
||||
if (emmcdrv_bootpartition == PARTITION_ID_USER) {
|
||||
emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en;
|
||||
if ((emmcdrv_bootpartition == PARTITION_ID_BOOT_1) ||
|
||||
(emmcdrv_bootpartition == PARTITION_ID_BOOT_2)) {
|
||||
current_file.partition = emmcdrv_bootpartition;
|
||||
|
||||
NOTICE("BL2: eMMC boot from partition %d\n",
|
||||
emmcdrv_bootpartition);
|
||||
goto done;
|
||||
}
|
||||
return IO_FAIL;
|
||||
}
|
||||
|
||||
if ((block_spec->partition == PARTITION_ID_USER) ||
|
||||
(block_spec->partition == PARTITION_ID_BOOT_1) ||
|
||||
(block_spec->partition == PARTITION_ID_BOOT_2)) {
|
||||
current_file.partition = block_spec->partition;
|
||||
} else {
|
||||
current_file.partition = emmcdrv_bootpartition;
|
||||
}
|
||||
|
||||
done:
|
||||
if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS) {
|
||||
return IO_FAIL;
|
||||
}
|
||||
|
||||
entity->info = (uintptr_t) ¤t_file;
|
||||
|
||||
return IO_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t emmcdrv_block_close(io_entity_t *entity)
|
||||
{
|
||||
memset((void *)¤t_file, 0, sizeof(current_file));
|
||||
entity->info = 0U;
|
||||
|
||||
return IO_SUCCESS;
|
||||
}
|
||||
|
||||
static const io_dev_funcs_t emmcdrv_dev_funcs = {
|
||||
.type = &device_type_emmcdrv,
|
||||
.open = &emmcdrv_block_open,
|
||||
.seek = &emmcdrv_block_seek,
|
||||
.size = NULL,
|
||||
.read = &emmcdrv_block_read,
|
||||
.write = NULL,
|
||||
.close = &emmcdrv_block_close,
|
||||
.dev_init = NULL,
|
||||
.dev_close = &emmcdrv_dev_close
|
||||
};
|
||||
|
||||
static const io_dev_info_t emmcdrv_dev_info = {
|
||||
.funcs = &emmcdrv_dev_funcs,
|
||||
.info = (uintptr_t) 0
|
||||
};
|
||||
|
||||
static const io_dev_connector_t emmcdrv_dev_connector = {
|
||||
&emmcdrv_dev_open,
|
||||
};
|
||||
|
||||
static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)),
|
||||
io_dev_info_t **dev_info)
|
||||
{
|
||||
*dev_info = (io_dev_info_t *) &emmcdrv_dev_info;
|
||||
|
||||
return IO_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info)
|
||||
{
|
||||
return IO_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **dev_con)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
rc = io_register_device(&emmcdrv_dev_info);
|
||||
if (rc == IO_SUCCESS) {
|
||||
*dev_con = &emmcdrv_dev_connector;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
Reference in New Issue
Block a user