GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
SDK_DIR ?= $(shell cd $(CURDIR)/../../../.. && /bin/pwd)
|
||||
|
||||
include $(SDK_DIR)/build/base.mk
|
||||
|
||||
PM_ROOT_USR := $(GMP_DIR)/usr/pm
|
||||
PM_ROOT_DRV := $(GMP_DIR)/drv/pm
|
||||
|
||||
LIB_NAME := libxmedia_pm
|
||||
|
||||
SRCS := $(wildcard ./*.c)
|
||||
|
||||
SDK_USR_CFLAGS += -I$(GMP_DIR)/include \
|
||||
-I$(PM_ROOT_USR) \
|
||||
-I$(PM_ROOT_DRV)/include \
|
||||
-I$(GMP_DIR)/drv/include \
|
||||
-I$(GMP_DIR)/usr/include \
|
||||
-I$(GMP_DIR)/drv/osal/include
|
||||
|
||||
SDK_USR_CFLAGS += -DUSER_BIT_32 -DKERNEL_BIT_32 -Wno-date-time -D_GNU_SOURCE
|
||||
SDK_USR_CFLAGS += -DAMP_NONSECURE_VERSION
|
||||
|
||||
SDK_USR_CFLAGS += -DCHIP_TYPE_$(CHIPARCH)
|
||||
|
||||
include $(SDK_DIR)/build/sdk_lib_rules.mk
|
||||
@@ -0,0 +1,176 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include "xmedia_mmz.h"
|
||||
#include "pm_aux.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "pm_flash.h"
|
||||
|
||||
/* note: size must be 2k alignment */
|
||||
#define AUX_TOTAL_MEM_SIZE (UBOOT_HEADER_PARAM_LEN + AUX_AREA_SIZE)
|
||||
#define AUX_TOTAL_MEM_NAME "AUX_MEM"
|
||||
static xmedia_u64 aux_mem_addr = XMEDIA_NULL;
|
||||
|
||||
const char nand_uboot_part[] = "/dev/mtd0";
|
||||
const char spi_uboot_part[] = "/dev/mtd0";
|
||||
const char emmc_uboot_part[] = "/dev/mmcblk0p0";
|
||||
|
||||
const char *uboot_name[PM_FLASH_TYPE_MAX] = {spi_uboot_part, nand_uboot_part, emmc_uboot_part};
|
||||
|
||||
static struct flash_part_dev *flash_uboot_init(void)
|
||||
{
|
||||
struct flash_part_dev *uboot_part_dev;
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
uboot_part_dev = alloc_flash_part();
|
||||
if (uboot_part_dev == XMEDIA_NULL)
|
||||
return XMEDIA_NULL;
|
||||
|
||||
memcpy(uboot_part_dev->part.devname, uboot_name[uboot_part_dev->part.flash_type], strlen(uboot_name[uboot_part_dev->part.flash_type]));
|
||||
|
||||
ret = flash_open(uboot_part_dev, ACCESS_RD);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "open error\n");
|
||||
free_flash_part(uboot_part_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
ret = flash_get_info(uboot_part_dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "get info err\n");
|
||||
uboot_part_dev->part_opt->close(uboot_part_dev);
|
||||
free_flash_part(uboot_part_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
ret = flash_init(uboot_part_dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "flash init err\n");
|
||||
uboot_part_dev->part_opt->close(uboot_part_dev);
|
||||
free_flash_part(uboot_part_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
return uboot_part_dev;
|
||||
}
|
||||
|
||||
static xmedia_s32 flash_uboot_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
return flash_read(part_dev, addr, size, buf);
|
||||
}
|
||||
|
||||
static xmedia_s32 flash_uboot_deinit(struct flash_part_dev *part_dev)
|
||||
{
|
||||
flash_close(part_dev);
|
||||
free_flash_part(part_dev);
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_s32 aux_free_mem(void)
|
||||
{
|
||||
if (aux_mem_addr != XMEDIA_NULL) {
|
||||
xmedia_mmz_free(aux_mem_addr);
|
||||
aux_mem_addr = XMEDIA_NULL;
|
||||
}
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_s32 aux_read(xmedia_char *buf, xmedia_u32 size)
|
||||
{
|
||||
struct flash_part_dev *uboot_part_dev;
|
||||
xmedia_u32 aux_len;
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
uboot_part_dev = flash_uboot_init();
|
||||
if (uboot_part_dev == XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "uboot init error\n");
|
||||
return XMEDIA_ERRCODE_OPEN_FAILED;
|
||||
}
|
||||
|
||||
if (size < UBOOT_HEADER_PARAM_LEN) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s bufsize(0x%x) < headersize(0x%x)\n", __func__, size, UBOOT_HEADER_PARAM_LEN);
|
||||
flash_uboot_deinit(uboot_part_dev);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret = flash_uboot_read(uboot_part_dev, 0, UBOOT_HEADER_PARAM_LEN, buf);
|
||||
if (ret != UBOOT_HEADER_PARAM_LEN) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s read header error ret:%d\n", __func__, ret);
|
||||
flash_uboot_deinit(uboot_part_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
aux_len = *(xmedia_u32 *)(buf + AUX_LEN_POS);
|
||||
if (aux_len > size - UBOOT_HEADER_PARAM_LEN) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s aux len(0x%x) > bufsize(0x%x) - headersize(0x%x)\n", __func__, aux_len, size, UBOOT_HEADER_PARAM_LEN);
|
||||
flash_uboot_deinit(uboot_part_dev);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret = flash_uboot_read(uboot_part_dev, UBOOT_HEADER_PARAM_LEN, aux_len, buf + UBOOT_HEADER_PARAM_LEN);
|
||||
if (ret != aux_len) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s read aux len(0x%x) error ret:%d\n", __func__, aux_len, ret);
|
||||
flash_uboot_deinit(uboot_part_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
flash_uboot_deinit(uboot_part_dev);
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_s32 read_aux_to_ddr(struct aux_mem *paux)
|
||||
{
|
||||
xmedia_void *pbuf = NULL;
|
||||
|
||||
if (aux_mem_addr != XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "aux exist in ddr now\n");
|
||||
paux->phy_addr = aux_mem_addr;
|
||||
paux->size = AUX_TOTAL_MEM_SIZE;
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
aux_mem_addr = xmedia_mmz_alloc(NULL, AUX_TOTAL_MEM_NAME, AUX_TOTAL_MEM_SIZE);
|
||||
if (aux_mem_addr == XMEDIA_NULL)
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
|
||||
pbuf = xmedia_mmz_map(aux_mem_addr, AUX_TOTAL_MEM_SIZE, XMEDIA_TRUE);
|
||||
if (pbuf == XMEDIA_NULL) {
|
||||
aux_free_mem();
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
PM_USR_TRACE(MODULE_DBG_INFO, "aux_mem phy addr:0x%llx vir addr: 0x%x\n", aux_mem_addr, (xmedia_u32)paux);
|
||||
|
||||
if (aux_read(pbuf, AUX_TOTAL_MEM_SIZE) != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "read aux error\n");
|
||||
xmedia_mmz_unmap(pbuf);
|
||||
aux_free_mem();
|
||||
return XMEDIA_ERRCODE_COPY_DATA_ERROR;
|
||||
}
|
||||
|
||||
xmedia_mmz_flush_cache(aux_mem_addr, pbuf, AUX_TOTAL_MEM_SIZE);
|
||||
|
||||
xmedia_mmz_unmap(pbuf);
|
||||
|
||||
paux->phy_addr = aux_mem_addr;
|
||||
paux->size = AUX_TOTAL_MEM_SIZE;
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef H_PM_AUX_H
|
||||
#define H_PM_AUX_H
|
||||
|
||||
#include "xmedia_type.h"
|
||||
#include "xmedia_errcode.h"
|
||||
|
||||
#define UBOOT_HEADER_PARAM_LEN 0x2800
|
||||
#define AUX_AREA_SIZE 0x5000
|
||||
|
||||
#define AUX_LEN_POS 0x400
|
||||
|
||||
struct aux_mem {
|
||||
xmedia_u64 phy_addr;
|
||||
xmedia_u32 size;
|
||||
};
|
||||
|
||||
xmedia_s32 aux_read(xmedia_char *buf, xmedia_u32 size);
|
||||
|
||||
xmedia_s32 read_aux_to_ddr(struct aux_mem *paux);
|
||||
|
||||
xmedia_s32 aux_free_mem(void);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,289 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "xmedia_type.h"
|
||||
#include "pm_flash.h"
|
||||
#include "pm_ddr.h"
|
||||
#include "xmedia_cipher.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define SHA256_SUPPORT
|
||||
|
||||
static const xmedia_char nand_ddr_param_part[] = "/dev/mtd2";
|
||||
static const xmedia_char spi_ddr_param_part[] = "/dev/mtd2";
|
||||
static const xmedia_char emmc_ddr_param_part[] = "/dev/mmcblk0p2";
|
||||
|
||||
static const xmedia_char ddr_param_part_name[] = "ddr_param";
|
||||
|
||||
static const xmedia_char *ddr_param_dev_name[PM_FLASH_TYPE_MAX] = {spi_ddr_param_part, nand_ddr_param_part, emmc_ddr_param_part};
|
||||
|
||||
xmedia_u32 checksum(xmedia_u8 *data, size_t length)
|
||||
{
|
||||
xmedia_u32 sum = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
xmedia_s32 hash_calc(xmedia_u8 *data, size_t length, xmedia_u8 *result)
|
||||
{
|
||||
xmedia_handle handle;
|
||||
xmedia_cipher_hash_attr hash_attr;
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
ret = xmedia_cipher_init();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "cipher init err\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&hash_attr, 0, sizeof(xmedia_cipher_hash_attr));
|
||||
hash_attr.type = XMEDIA_CIPHER_HASH_TYPE_SHA256;
|
||||
ret = xmedia_cipher_hash_init(&hash_attr, &handle);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
xmedia_cipher_exit();
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "cipher hash init err\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = xmedia_cipher_hash_update(handle, data, length);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
xmedia_cipher_exit();
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "cipher hash update err\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = xmedia_cipher_hash_final(handle, result);
|
||||
|
||||
xmedia_cipher_exit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct flash_part_dev *ddr_param_part_init(void)
|
||||
{
|
||||
struct flash_part_dev *ddr_param_dev;
|
||||
xmedia_s32 ret;
|
||||
|
||||
ddr_param_dev = alloc_flash_part();
|
||||
if (ddr_param_dev == XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "alloc part dev err\n");
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
memcpy(ddr_param_dev->part.devname, ddr_param_dev_name[ddr_param_dev->part.flash_type], strlen(ddr_param_dev_name[ddr_param_dev->part.flash_type]));
|
||||
memcpy(ddr_param_dev->part.partname, ddr_param_part_name, strlen(ddr_param_part_name));
|
||||
|
||||
ret = flash_open(ddr_param_dev, ACCESS_RD);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "open part:%s err\n", ddr_param_dev->part.devname);
|
||||
free_flash_part(ddr_param_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
ret = flash_init(ddr_param_dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "flash init err ret = %d\n", ret);
|
||||
goto ERR_RET;
|
||||
}
|
||||
memset(ddr_param_dev->part.partname, 0, FLASH_NAME_LEN);
|
||||
|
||||
ret = flash_get_info(ddr_param_dev);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "flash get info err ret = %d\n", ret);
|
||||
goto ERR_RET;
|
||||
}
|
||||
|
||||
if (strncmp(ddr_param_dev->part.partname, ddr_param_part_name, strlen(ddr_param_part_name)) != 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "mtd part name(%s) err\n", ddr_param_dev->part.partname);
|
||||
goto ERR_RET;
|
||||
}
|
||||
|
||||
return ddr_param_dev;
|
||||
|
||||
ERR_RET:
|
||||
ddr_param_dev->part_opt->close(ddr_param_dev);
|
||||
free_flash_part(ddr_param_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
static xmedia_s32 ddr_param_part_deinit(struct flash_part_dev *part_dev)
|
||||
{
|
||||
flash_close(part_dev);
|
||||
free_flash_part(part_dev);
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 ddr_param_get(struct lpds_param *lpds_parm)
|
||||
{
|
||||
return xmedia_pm_get_ddr_param(lpds_parm);
|
||||
}
|
||||
|
||||
#define RAM_OFF_CHECK_FILE "/sys/module/pm/parameters/ram_power_off"
|
||||
#define RAM_OFF_ENABLE_FLAG "Y"
|
||||
#define RAM_OFF_FLAG_SIZE (1)
|
||||
xmedia_bool is_ram_off_str(void)
|
||||
{
|
||||
xmedia_char buf[8];
|
||||
xmedia_s32 fd;
|
||||
xmedia_u32 size = sizeof(buf);
|
||||
|
||||
fd = open(RAM_OFF_CHECK_FILE, O_RDWR | O_SYNC);
|
||||
if (fd < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "open %s err, ret:%d \n", RAM_OFF_CHECK_FILE, fd);
|
||||
return XMEDIA_FALSE;
|
||||
}
|
||||
|
||||
size = read(fd, buf, size);
|
||||
if (size <= 0) {
|
||||
close(fd);
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s get ram off flag err\n", __func__);
|
||||
return XMEDIA_FALSE;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (strncmp(buf, RAM_OFF_ENABLE_FLAG, RAM_OFF_FLAG_SIZE) == 0)
|
||||
return XMEDIA_TRUE;
|
||||
else
|
||||
return XMEDIA_FALSE;
|
||||
}
|
||||
|
||||
xmedia_s32 ddr_param_check_and_save(void)
|
||||
{
|
||||
struct flash_part_dev *ddr_param_dev;
|
||||
xmedia_char *buff;
|
||||
xmedia_s32 ret;
|
||||
struct lpds_param *lpds_parm;
|
||||
xmedia_u32 size;
|
||||
xmedia_u32 block_mask;
|
||||
#ifndef SHA256_SUPPORT
|
||||
xmedia_u32 checksum32;
|
||||
#else
|
||||
xmedia_u8 ddr_hash[HASH_SIZE_PER_BYTE];
|
||||
#endif
|
||||
struct timespec ts;
|
||||
struct ddr_calib_data *p_ddr_param;
|
||||
|
||||
PM_USR_TRACE(MODULE_DBG_INFO, "ram power off str\n");
|
||||
|
||||
ddr_param_dev = ddr_param_part_init();
|
||||
if (ddr_param_dev == XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s init err\n", __func__);
|
||||
return XMEDIA_ERRCODE_OPEN_FAILED;
|
||||
}
|
||||
|
||||
block_mask = (~(ddr_param_dev->flash.block_size - 1));
|
||||
|
||||
/* For nand, we must update the whole block to update the
|
||||
* bad flag/empty flag/ecc to the OOB region, which the FMC
|
||||
* boot mode need. If not, the FMC can not read the correct
|
||||
* ddr_param data in bootrom/auxcode stage.*/
|
||||
if (ddr_param_dev->flash.flash_type == PM_FLASH_TYPE_NAND)
|
||||
size = ((sizeof(struct lpds_param) + ddr_param_dev->flash.block_size - 1) & (~(ddr_param_dev->flash.block_size - 1)));
|
||||
else
|
||||
size = ((sizeof(struct lpds_param) + ddr_param_dev->flash.page_size - 1) & (~(ddr_param_dev->flash.page_size - 1)));
|
||||
|
||||
buff = (xmedia_char *)malloc(size);
|
||||
if (buff == XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s out of mem\n", __func__);
|
||||
ret = XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
goto DEINIT_RET;
|
||||
}
|
||||
|
||||
if (flash_read(ddr_param_dev, 0, size, buff) != size) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s flash read error\n", __func__);
|
||||
ret = XMEDIA_ERRCODE_COPY_DATA_ERROR;
|
||||
goto FREE_RET;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
lpds_parm = (struct lpds_param *)buff;
|
||||
p_ddr_param = (struct ddr_calib_data *)lpds_parm->ddr_calib;
|
||||
|
||||
#ifdef SHA256_SUPPORT
|
||||
ret = hash_calc(lpds_parm->ddr_calib + sizeof(xmedia_u32), (sizeof(struct ddr_calib_data) - sizeof(xmedia_u32)), ddr_hash);
|
||||
if (ret) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s hash calc error ret=%d\n", __func__, ret);
|
||||
ret = XMEDIA_ERRCODE_NOT_SUPPORT;
|
||||
goto FREE_RET;
|
||||
}
|
||||
if (memcmp(ddr_hash, lpds_parm->ddr_hash, HASH_SIZE_PER_BYTE) != 0 || (ts.tv_sec - p_ddr_param->time_sec >= DDR_PARAM_UPDATE_CYCLE)) {
|
||||
#else
|
||||
checksum32 = checksum(lpds_parm->ddr_calib + sizeof(xmedia_u32), (sizeof(struct ddr_calib_data) - sizeof(xmedia_u32)));
|
||||
if (checksum32 != *((xmedia_u32 *)lpds_parm->ddr_calib) || (ts.tv_sec - p_ddr_param->time_sec >= DDR_PARAM_UPDATE_CYCLE)) {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ddr param in flah is error
|
||||
* save new training result
|
||||
*/
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "ddr paramter err or too old, update now\n");
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "now time %lu s save time %u s \n", ts.tv_sec, p_ddr_param->time_sec);
|
||||
|
||||
ret = ddr_param_get(lpds_parm);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s read ddr param error ret=%d\n", __func__, ret);
|
||||
goto FREE_RET;
|
||||
}
|
||||
|
||||
p_ddr_param->time_sec = ts.tv_sec;
|
||||
|
||||
/* calc checksum */
|
||||
#ifdef SHA256_SUPPORT
|
||||
ret = hash_calc(lpds_parm->ddr_calib + sizeof(xmedia_u32), (sizeof(struct ddr_calib_data) - sizeof(xmedia_u32)), lpds_parm->ddr_hash);
|
||||
if (ret) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s hash calc for save error ret=%d\n", __func__, ret);
|
||||
ret = XMEDIA_ERRCODE_NOT_SUPPORT;
|
||||
goto FREE_RET;
|
||||
}
|
||||
#else
|
||||
*((xmedia_u32 *)lpds_parm->ddr_calib) = checksum(lpds_parm->ddr_calib + sizeof(xmedia_u32), (sizeof(struct ddr_calib_data) - sizeof(xmedia_u32)));
|
||||
#endif
|
||||
|
||||
/* erase first */
|
||||
ret = flash_erase(ddr_param_dev, 0, (size + (ddr_param_dev->flash.block_size - 1)) & block_mask);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s erase error ret=%d\n", __func__, ret);
|
||||
ret = XMEDIA_ERRCODE_NOT_SUPPORT;
|
||||
goto FREE_RET;
|
||||
}
|
||||
|
||||
/* write */
|
||||
if (flash_write(ddr_param_dev, 0, size, buff) != size) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s write error ret=%d\n", __func__, ret);
|
||||
ret = XMEDIA_ERRCODE_NOT_SUPPORT;
|
||||
goto FREE_RET;
|
||||
}
|
||||
}
|
||||
|
||||
ret = XMEDIA_SUCCESS;
|
||||
|
||||
FREE_RET:
|
||||
free(buff);
|
||||
DEINIT_RET:
|
||||
ddr_param_part_deinit(ddr_param_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef H_PM_DDR_H
|
||||
#define H_PM_DDR_H
|
||||
|
||||
#define HASH_SIZE_PER_BYTE 32
|
||||
#define DDR_CALIB_SIZE 832
|
||||
|
||||
#define DDR_PARAM_UPDATE_CYCLE (7 * 24 * 60 * 60)
|
||||
|
||||
struct lpds_param {
|
||||
xmedia_u8 lpds_hash[HASH_SIZE_PER_BYTE];
|
||||
xmedia_u8 ddr_hash[HASH_SIZE_PER_BYTE];
|
||||
xmedia_u32 data_start;
|
||||
xmedia_u32 data_size;
|
||||
xmedia_u32 hash_flag;
|
||||
xmedia_u32 str_flag;
|
||||
xmedia_u32 resume_addr;
|
||||
xmedia_u32 resume_addr_backup;
|
||||
xmedia_u8 reserve0[24];
|
||||
xmedia_u8 scrambling_key[16];
|
||||
xmedia_u8 ddr_calib[DDR_CALIB_SIZE];
|
||||
xmedia_u32 ddr_size;
|
||||
xmedia_u32 hpm_state;
|
||||
xmedia_u32 power_state;
|
||||
xmedia_u8 reserve1[20];
|
||||
xmedia_u32 ddr_suspend_crc;
|
||||
xmedia_u32 ddr_resume_crc;
|
||||
};
|
||||
|
||||
struct ddr_calib_data {
|
||||
xmedia_u32 checksum;
|
||||
|
||||
xmedia_u32 gate_dqs0_result;
|
||||
xmedia_u32 gate_dqs1_result;
|
||||
|
||||
xmedia_u32 rx_dqs0_result;
|
||||
xmedia_u32 rx_dqsb0_result;
|
||||
xmedia_u32 rx_dqs1_result;
|
||||
xmedia_u32 rx_dqsb1_result;
|
||||
|
||||
xmedia_u32 rx_dm0_result;
|
||||
xmedia_u32 rx_dm1_result;
|
||||
|
||||
xmedia_u32 rx_dq_result[16];
|
||||
|
||||
xmedia_u32 tx_dqs0_result;
|
||||
xmedia_u32 tx_dqsb0_result;
|
||||
xmedia_u32 tx_dqs1_result;
|
||||
xmedia_u32 tx_dqsb1_result;
|
||||
|
||||
xmedia_u32 tx_dm0_result;
|
||||
xmedia_u32 tx_dm1_result;
|
||||
|
||||
xmedia_u32 tx_dq_result[16];
|
||||
xmedia_u32 time_sec;
|
||||
};
|
||||
|
||||
xmedia_bool is_ram_off_str(void);
|
||||
|
||||
xmedia_s32 ddr_param_check_and_save(void);
|
||||
|
||||
xmedia_s32 xmedia_pm_get_ddr_param(struct lpds_param *p_lpds_param);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "pm_flash.h"
|
||||
|
||||
static xmedia_s32 emmc_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static struct flash_opt emmc_opt = {
|
||||
.read = emmc_read,
|
||||
};
|
||||
|
||||
struct flash_opt *get_emmc_opt(void)
|
||||
{
|
||||
return &emmc_opt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include "pm_flash.h"
|
||||
|
||||
struct flash_opt *get_nand_opt(void);
|
||||
struct flash_opt *get_emmc_opt(void);
|
||||
struct flash_opt *get_spi_opt(void);
|
||||
|
||||
static xmedia_flash_type get_flashtype_by_bootargs(const xmedia_char *bootargs)
|
||||
{
|
||||
xmedia_s32 i;
|
||||
xmedia_flash_type flash_type = PM_FLASH_TYPE_MAX;
|
||||
xmedia_char type_str[PM_FLASH_TYPE_MAX][16] = {"sfc:", "nand:", "mmcblk0:"};
|
||||
|
||||
for (i = 0; i < PM_FLASH_TYPE_MAX; i++) {
|
||||
if (strstr((xmedia_char *)bootargs, type_str[i]) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
flash_type = (xmedia_flash_type)i;
|
||||
|
||||
return flash_type;
|
||||
}
|
||||
|
||||
static xmedia_flash_type get_flashtype(void)
|
||||
{
|
||||
xmedia_char bootargs[512];
|
||||
FILE *pf;
|
||||
|
||||
pf = fopen("/proc/cmdline", "r");
|
||||
if (pf == XMEDIA_NULL) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "Failed to open '/proc/cmdline'.\n");
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
if (XMEDIA_NULL == fgets((xmedia_char *)bootargs, 512, pf)) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "Failed to fgets string.\n");
|
||||
fclose(pf);
|
||||
return XMEDIA_FAILURE;
|
||||
}
|
||||
|
||||
fclose(pf);
|
||||
|
||||
return get_flashtype_by_bootargs(bootargs);
|
||||
}
|
||||
|
||||
struct flash_part_dev *alloc_flash_part(void)
|
||||
{
|
||||
struct flash_part_dev *part_dev = (struct flash_part_dev *)malloc(sizeof(struct flash_part_dev));
|
||||
|
||||
if (part_dev == XMEDIA_NULL)
|
||||
return XMEDIA_NULL;
|
||||
|
||||
memset(part_dev, 0, sizeof(struct flash_part_dev));
|
||||
|
||||
part_dev->flash.flash_type = get_flashtype();
|
||||
|
||||
if (part_dev->flash.flash_type == PM_FLASH_TYPE_SPI)
|
||||
part_dev->part_opt = get_spi_opt();
|
||||
else if (part_dev->flash.flash_type == PM_FLASH_TYPE_NAND)
|
||||
part_dev->part_opt = get_nand_opt();
|
||||
else if (part_dev->flash.flash_type == PM_FLASH_TYPE_EMMC)
|
||||
part_dev->part_opt = get_emmc_opt();
|
||||
else {
|
||||
free(part_dev);
|
||||
return XMEDIA_NULL;
|
||||
}
|
||||
|
||||
part_dev->part.flash_type = part_dev->flash.flash_type;
|
||||
return part_dev;
|
||||
}
|
||||
|
||||
void free_flash_part(struct flash_part_dev *part_dev)
|
||||
{
|
||||
free(part_dev);
|
||||
}
|
||||
|
||||
xmedia_s32 flash_open(struct flash_part_dev *part_dev, xmedia_u32 flag)
|
||||
{
|
||||
if (part_dev->part_opt->open)
|
||||
part_dev->part_fd = part_dev->part_opt->open(part_dev, flag);
|
||||
|
||||
if (part_dev->part_fd == -1)
|
||||
return -1;
|
||||
else
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_close(struct flash_part_dev *part_dev)
|
||||
{
|
||||
if (part_dev->part_opt->close)
|
||||
return part_dev->part_opt->close(part_dev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_get_info(struct flash_part_dev *part_dev)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
if (part_dev->part_opt->get_info)
|
||||
ret = part_dev->part_opt->get_info(part_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
if (part_dev->part_opt->read)
|
||||
ret = part_dev->part_opt->read(part_dev, addr, size, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_write(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
if (part_dev->part_opt->write)
|
||||
ret = part_dev->part_opt->write(part_dev, addr, size, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_erase(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
if (part_dev->part_opt->erase)
|
||||
ret = part_dev->part_opt->erase(part_dev, addr, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 flash_init(struct flash_part_dev *part_dev)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
if (part_dev->part_opt->init)
|
||||
ret = part_dev->part_opt->init(part_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef H_PM_FLASH_H
|
||||
#define H_PM_FLASH_H
|
||||
|
||||
#include "common.h"
|
||||
#include "xmedia_debug.h"
|
||||
#include "xmedia_type.h"
|
||||
#include "xmedia_errcode.h"
|
||||
|
||||
#define PM_USR_TRACE(level, fmt, ...) \
|
||||
do { \
|
||||
MODULE_TRACE(level, MOD_ID_PM, "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define FLASH_NAME_LEN 32 /** Flash Name max length */
|
||||
|
||||
/** Flash partition access permission type */
|
||||
typedef enum access_perm {
|
||||
ACCESS_NONE = 0,
|
||||
ACCESS_RD = (1 << 1),
|
||||
ACCESS_WR = (1 << 2),
|
||||
ACCESS_RDWR = (ACCESS_RD | ACCESS_WR),
|
||||
ACCESS_BUTT
|
||||
} xmedia_access_perm;
|
||||
|
||||
/** flash type */
|
||||
typedef enum flash_type {
|
||||
PM_FLASH_TYPE_SPI, /**< SPI flash type */
|
||||
PM_FLASH_TYPE_NAND, /**< NAND flash type */
|
||||
PM_FLASH_TYPE_EMMC, /**< eMMC flash type */
|
||||
PM_FLASH_TYPE_MAX /**< Invalid flash type */
|
||||
} xmedia_flash_type;
|
||||
|
||||
typedef struct flash_part_dev flash_part_device;
|
||||
|
||||
struct flash_opt {
|
||||
int (*read)(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf);
|
||||
int (*write)(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf);
|
||||
int (*erase)(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size);
|
||||
int (*init)(struct flash_part_dev *part_dev);
|
||||
int (*open)(struct flash_part_dev *part_dev, xmedia_u32 flag);
|
||||
int (*close)(struct flash_part_dev *part_dev);
|
||||
int (*get_info)(struct flash_part_dev *part_dev);
|
||||
};
|
||||
|
||||
/** Flash partition descriptions */
|
||||
struct part_info {
|
||||
xmedia_u64 start; /**< Partiton start address */
|
||||
xmedia_u64 size; /**< Partition size */
|
||||
xmedia_u32 block_size; /**< The Block size of the flash where this partition at */
|
||||
xmedia_flash_type flash_type; /**< The flash type where this partition at */
|
||||
xmedia_char devname[FLASH_NAME_LEN]; /**< The device node name where this partition relate to */
|
||||
xmedia_char partname[FLASH_NAME_LEN]; /**< The partition name of this partition */
|
||||
xmedia_access_perm perm; /**< The partition access permission type */
|
||||
};
|
||||
|
||||
/** Flash Infomation */
|
||||
struct flash_info {
|
||||
xmedia_u64 total_size; /**< flash total size */
|
||||
xmedia_u64 part_size; /**< flash partition size */
|
||||
xmedia_u32 block_size; /**< flash block size */
|
||||
xmedia_u32 page_size; /**< flash page size */
|
||||
xmedia_u32 oob_size; /**< flash OOB size */
|
||||
xmedia_s32 fd; /**< file handle */ /**<CNcomment:�ļ����(����ַ���ܵõ���ʵ���)*/
|
||||
xmedia_u64 open_addr; /**< flash open address */
|
||||
xmedia_u64 open_leng; /**< flash open length */
|
||||
xmedia_flash_type flash_type; /**< flash type */
|
||||
};
|
||||
|
||||
struct flash_part_dev {
|
||||
xmedia_s32 part_fd;
|
||||
struct flash_opt *part_opt;
|
||||
struct part_info part;
|
||||
struct flash_info flash;
|
||||
};
|
||||
|
||||
struct flash_part_dev *alloc_flash_part(void);
|
||||
void free_flash_part(struct flash_part_dev *part_dev);
|
||||
xmedia_s32 flash_open(struct flash_part_dev *part_dev, xmedia_u32 flag);
|
||||
xmedia_s32 flash_close(struct flash_part_dev *part_dev);
|
||||
xmedia_s32 flash_get_info(struct flash_part_dev *part_dev);
|
||||
xmedia_s32 flash_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf);
|
||||
xmedia_s32 flash_write(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf);
|
||||
xmedia_s32 flash_erase(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size);
|
||||
xmedia_s32 flash_init(struct flash_part_dev *part_dev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef H_PM_MTD_H
|
||||
#define H_PM_MTD_H
|
||||
|
||||
struct mtd_info_user {
|
||||
xmedia_u8 type;
|
||||
xmedia_u32 flags;
|
||||
xmedia_u32 size;
|
||||
xmedia_u32 erasesize;
|
||||
xmedia_u32 writesize;
|
||||
xmedia_u32 oobsize;
|
||||
xmedia_u32 ecctype;
|
||||
xmedia_u32 eccsize;
|
||||
};
|
||||
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
|
||||
|
||||
struct erase_info_user64 {
|
||||
xmedia_u64 start;
|
||||
xmedia_u64 length;
|
||||
};
|
||||
#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
|
||||
|
||||
|
||||
struct mtd_oob_buf {
|
||||
xmedia_u32 start;
|
||||
xmedia_u32 length;
|
||||
xmedia_u8 *ptr;
|
||||
};
|
||||
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
|
||||
|
||||
/**
|
||||
* struct mtd_write_req - data structure for requesting a write operation
|
||||
*
|
||||
* @start: start address
|
||||
* @len: length of data buffer
|
||||
* @ooblen: length of OOB buffer
|
||||
* @usr_data: user-provided data buffer
|
||||
* @usr_oob: user-provided OOB buffer
|
||||
* @mode: MTD mode (see "MTD operation modes")
|
||||
* @padding: reserved, must be set to 0
|
||||
*
|
||||
* This structure supports ioctl(MEMWRITE) operations, allowing data and/or OOB
|
||||
* writes in various modes. To write to OOB-only, set @usr_data == NULL, and to
|
||||
* write data-only, set @usr_oob == NULL. However, setting both @usr_data and
|
||||
* @usr_oob to NULL is not allowed.
|
||||
*/
|
||||
struct mtd_write_req {
|
||||
xmedia_u64 start;
|
||||
xmedia_u64 len;
|
||||
xmedia_u64 ooblen;
|
||||
xmedia_u64 usr_data;
|
||||
xmedia_u64 usr_oob;
|
||||
xmedia_u8 mode;
|
||||
xmedia_u8 padding[7];
|
||||
};
|
||||
|
||||
#define MEMWRITE _IOWR('M', 24, struct mtd_write_req)
|
||||
|
||||
#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t)
|
||||
|
||||
#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t)
|
||||
|
||||
#define MEMFORCEERASEBLOCK _IOW('M', 128, __kernel_loff_t)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,363 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "pm_flash.h"
|
||||
#include "pm_mtd.h"
|
||||
|
||||
#define MAX_PARTS 32 /* Flash max partition number*/
|
||||
#define MAX_MTD_PARTITION (MAX_PARTS)
|
||||
|
||||
#define TMP_READ_BUF_SIZE 512
|
||||
#define MTD_INFO_DEV "/proc/mtd"
|
||||
|
||||
static xmedia_char *skip_space(xmedia_char *line)
|
||||
{
|
||||
xmedia_char *p = line;
|
||||
while (*p == ' ' || *p == '\t') {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static xmedia_char *get_word(xmedia_char *line, xmedia_char *value)
|
||||
{
|
||||
xmedia_char *p = line;
|
||||
p = skip_space(p);
|
||||
while (*p != '\t' && *p != ' ' && *p != '\n' && *p != 0) {
|
||||
*value++ = *p++;
|
||||
}
|
||||
*value = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
static xmedia_u32 file_name_start(xmedia_char *name)
|
||||
{
|
||||
xmedia_u32 size = 0;
|
||||
|
||||
if (name) {
|
||||
size = strlen(name);
|
||||
if (size == 0)
|
||||
return size;
|
||||
|
||||
while (size--) {
|
||||
if (name[size] == '/')
|
||||
return size + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static xmedia_s32 get_dname_from_pname(struct flash_part_dev *part_dev)
|
||||
{
|
||||
FILE *fd;
|
||||
xmedia_char *buff;
|
||||
xmedia_s32 ret = -1;
|
||||
xmedia_s32 i = 0;
|
||||
xmedia_char *p;
|
||||
xmedia_char devname[FLASH_NAME_LEN];
|
||||
xmedia_char tmp[32];
|
||||
|
||||
buff = (xmedia_char *)malloc(TMP_READ_BUF_SIZE);
|
||||
if (buff == XMEDIA_NULL)
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
|
||||
fd = fopen(MTD_INFO_DEV, "r");
|
||||
if (fd) {
|
||||
if (NULL == fgets(buff, TMP_READ_BUF_SIZE, fd)) {//skip first line
|
||||
fclose(fd);
|
||||
goto ERR_END;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MTD_PARTITION; i++) {
|
||||
if (fgets(buff, TMP_READ_BUF_SIZE, fd) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
p = &buff[0];
|
||||
p = get_word(p, devname);
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.block_size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
if (strncmp(&tmp[1], part_dev->part.partname, strlen(part_dev->part.partname)) == 0){
|
||||
|
||||
/* delete ':' */
|
||||
devname[strlen(devname) - 1] = 0;
|
||||
strncpy(part_dev->part.devname + file_name_start(part_dev->part.devname), devname, FLASH_NAME_LEN);
|
||||
printf("use new devname: %s\n", part_dev->part.devname);
|
||||
ret = XMEDIA_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
ERR_END:
|
||||
free(buff);
|
||||
return ret;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* > 0 skip bad block num.
|
||||
* = 0 no bad block.
|
||||
* < 0 error.
|
||||
*/
|
||||
static xmedia_s32 check_skip_badblock(struct flash_part_dev *part_dev, xmedia_s32 *blockindex, xmedia_s32 blocksize)
|
||||
{
|
||||
xmedia_s32 rel = 0;
|
||||
xmedia_s32 badblock;
|
||||
xmedia_u64 size = part_dev->flash.part_size + 1;
|
||||
loff_t offset = ((loff_t)(*blockindex) * (loff_t)blocksize);
|
||||
|
||||
if (part_dev->part_fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
badblock = ioctl(part_dev->part_fd, MEMGETBADBLOCK, &offset);
|
||||
if (badblock < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "Get nand badblock fail. error(%d)\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (badblock == 1) {
|
||||
PM_USR_TRACE(MODULE_DBG_INFO, "Skip bad block at address: 0x%llX\n",
|
||||
(xmedia_u64)offset);
|
||||
(*blockindex)++;
|
||||
rel++;
|
||||
}
|
||||
|
||||
offset = (loff_t)(*blockindex) * (loff_t)blocksize;
|
||||
} while (badblock == 1 && offset < (loff_t)size);
|
||||
|
||||
if (offset >= (loff_t)size)
|
||||
return -1;
|
||||
|
||||
return rel;
|
||||
}
|
||||
static xmedia_s32 nand_rw(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf, xmedia_s32 w)
|
||||
{
|
||||
xmedia_s32 total = 0;
|
||||
xmedia_u32 cur_offset = addr;
|
||||
xmedia_u32 remaining_len = size;
|
||||
xmedia_char *cur_buf = buf;
|
||||
xmedia_u32 page_size = part_dev->flash.page_size;
|
||||
xmedia_u32 page_mask = page_size - 1;
|
||||
xmedia_u32 block_size = part_dev->flash.block_size;
|
||||
|
||||
if ((addr & page_mask) || (size & page_mask)) {
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* check addr and size */
|
||||
if (addr > part_dev->flash.part_size || addr + size > part_dev->flash.part_size)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
while (remaining_len && remaining_len <= size) {
|
||||
xmedia_s32 ret = 0;
|
||||
xmedia_s32 block_index, bad_skipped;
|
||||
xmedia_u32 rw_size;
|
||||
|
||||
block_index = cur_offset / block_size;
|
||||
bad_skipped = check_skip_badblock(part_dev, &block_index, block_size);
|
||||
if (bad_skipped < 0) {
|
||||
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
||||
} else {
|
||||
cur_offset += bad_skipped * block_size;
|
||||
}
|
||||
|
||||
if (lseek(part_dev->part_fd, cur_offset, SEEK_SET) < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "Fail to seek to 0x%x\n", addr);
|
||||
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (remaining_len > block_size)
|
||||
rw_size = block_size;
|
||||
else
|
||||
rw_size = remaining_len;
|
||||
|
||||
if (w)
|
||||
ret = write(part_dev->part_fd, cur_buf, rw_size);
|
||||
else
|
||||
ret = read(part_dev->part_fd, cur_buf, rw_size);
|
||||
|
||||
if (ret < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "Fail to %s at 0x%x\n", w ? "write" : "read", addr);
|
||||
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
||||
}
|
||||
cur_buf += rw_size;
|
||||
cur_offset += rw_size;
|
||||
remaining_len -= rw_size;
|
||||
total += ret;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
static xmedia_s32 nand_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
return nand_rw(part_dev, addr, size, buf, 0);
|
||||
}
|
||||
|
||||
static xmedia_s32 nand_write(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
return nand_rw(part_dev, addr, size, buf, 1);
|
||||
}
|
||||
|
||||
static xmedia_s32 nand_erase(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size)
|
||||
{
|
||||
xmedia_u32 cur_offset = addr;
|
||||
xmedia_u32 remaining_len = size;
|
||||
xmedia_u32 block_size = part_dev->flash.block_size;
|
||||
xmedia_u32 block_mask = block_size - 1;
|
||||
struct erase_info_user64 eraseinfo;
|
||||
xmedia_s32 ret;
|
||||
|
||||
if ((addr & block_mask) || (size & block_mask)) {
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* check addr and size */
|
||||
if (addr > part_dev->flash.part_size || addr + size > part_dev->flash.part_size)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
while (remaining_len && remaining_len <= size) {
|
||||
xmedia_s32 block_index, bad_skipped;
|
||||
|
||||
block_index = cur_offset / block_size;
|
||||
bad_skipped = check_skip_badblock(part_dev, &block_index, block_size);
|
||||
if (bad_skipped < 0) {
|
||||
return XMEDIA_ERRCODE_BAD_ADDRESS;
|
||||
} else {
|
||||
cur_offset += bad_skipped * block_size;
|
||||
}
|
||||
|
||||
eraseinfo.start = cur_offset;
|
||||
eraseinfo.length = block_size;
|
||||
|
||||
ret = ioctl(part_dev->part_fd, MEMERASE64, &eraseinfo);
|
||||
if (ret != 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s erase error ret:%d\n", __func__, ret);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cur_offset += block_size;
|
||||
remaining_len -= block_size;
|
||||
}
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
static xmedia_s32 nand_open(struct flash_part_dev *part_dev, unsigned int flag)
|
||||
{
|
||||
if (part_dev->part.partname[0] != 0)
|
||||
get_dname_from_pname(part_dev);
|
||||
|
||||
part_dev->part_fd = open(part_dev->part.devname, flag);
|
||||
return part_dev->part_fd;
|
||||
}
|
||||
|
||||
static xmedia_s32 nand_close(struct flash_part_dev *part_dev)
|
||||
{
|
||||
close(part_dev->part_fd);
|
||||
part_dev->part_fd = -1;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 nand_init(struct flash_part_dev *part_dev)
|
||||
{
|
||||
struct mtd_info_user mtdinfo;
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = ioctl(part_dev->part_fd, MEMGETINFO, &mtdinfo);
|
||||
if (ret != 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s mem get info error ret:%d\n", __func__, ret);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
part_dev->flash.block_size = mtdinfo.erasesize;
|
||||
part_dev->flash.page_size = mtdinfo.writesize;
|
||||
part_dev->flash.oob_size = mtdinfo.oobsize;
|
||||
part_dev->flash.part_size = mtdinfo.size;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 nand_getinfo(struct flash_part_dev *part_dev)
|
||||
{
|
||||
xmedia_s32 ret = -1;
|
||||
xmedia_s32 i = 0;
|
||||
xmedia_char *buff;
|
||||
FILE *fd;
|
||||
xmedia_char *p;
|
||||
xmedia_char tmp[32];
|
||||
|
||||
buff = (xmedia_char *)malloc(TMP_READ_BUF_SIZE);
|
||||
if (buff == XMEDIA_NULL)
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
|
||||
fd = fopen(MTD_INFO_DEV, "r");
|
||||
if (fd) {
|
||||
if (NULL == fgets(buff, TMP_READ_BUF_SIZE, fd)) {//skip first line
|
||||
fclose(fd);
|
||||
goto ERR_END;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MTD_PARTITION; i++) {
|
||||
if (fgets(buff, TMP_READ_BUF_SIZE, fd) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
p = &buff[0];
|
||||
p = get_word(p, tmp);
|
||||
if (strncmp(tmp, &part_dev->part.devname[5], strlen(&part_dev->part.devname[5])) == 0) {
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.block_size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
strncpy(part_dev->part.partname, &tmp[1], (strlen(&tmp[1]) - 1) < FLASH_NAME_LEN ? (strlen(&tmp[1]) - 1) : FLASH_NAME_LEN);
|
||||
|
||||
ret = XMEDIA_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
ERR_END:
|
||||
free(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct flash_opt nand_opt = {
|
||||
.read = nand_read,
|
||||
.write = nand_write,
|
||||
.erase = nand_erase,
|
||||
.init = nand_init,
|
||||
.open = nand_open,
|
||||
.close = nand_close,
|
||||
.get_info = nand_getinfo,
|
||||
};
|
||||
|
||||
struct flash_opt *get_nand_opt(void)
|
||||
{
|
||||
return &nand_opt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "pm_flash.h"
|
||||
#include "pm_mtd.h"
|
||||
|
||||
#define MAX_PARTS 32 /* Flash max partition number*/
|
||||
#define MAX_MTD_PARTITION (MAX_PARTS)
|
||||
|
||||
#define TMP_READ_BUF_SIZE 512
|
||||
#define MTD_INFO_DEV "/proc/mtd"
|
||||
|
||||
static xmedia_char *skip_space(xmedia_char *line)
|
||||
{
|
||||
xmedia_char *p = line;
|
||||
while (*p == ' ' || *p == '\t') {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static xmedia_char *get_word(xmedia_char *line, xmedia_char *value)
|
||||
{
|
||||
xmedia_char *p = line;
|
||||
p = skip_space(p);
|
||||
while (*p != '\t' && *p != ' ' && *p != '\n' && *p != 0) {
|
||||
*value++ = *p++;
|
||||
}
|
||||
*value = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
static xmedia_u32 file_name_start(xmedia_char *name)
|
||||
{
|
||||
xmedia_u32 size = 0;
|
||||
|
||||
if (name) {
|
||||
size = strlen(name);
|
||||
if (size == 0)
|
||||
return size;
|
||||
|
||||
while (size--) {
|
||||
if (name[size] == '/')
|
||||
return size + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static xmedia_s32 get_dname_from_pname(struct flash_part_dev *part_dev)
|
||||
{
|
||||
FILE *fd;
|
||||
xmedia_char *buff;
|
||||
xmedia_s32 ret = -1;
|
||||
xmedia_s32 i = 0;
|
||||
xmedia_char *p;
|
||||
xmedia_char devname[FLASH_NAME_LEN];
|
||||
xmedia_char tmp[32];
|
||||
|
||||
buff = (xmedia_char *)malloc(TMP_READ_BUF_SIZE);
|
||||
if (buff == XMEDIA_NULL)
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
|
||||
fd = fopen(MTD_INFO_DEV, "r");
|
||||
if (fd) {
|
||||
if (NULL == fgets(buff, TMP_READ_BUF_SIZE, fd)) {//skip first line
|
||||
fclose(fd);
|
||||
goto ERR_END;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MTD_PARTITION; i++) {
|
||||
if (fgets(buff, TMP_READ_BUF_SIZE, fd) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
p = &buff[0];
|
||||
p = get_word(p, devname);
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.block_size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
if (strncmp(&tmp[1], part_dev->part.partname, strlen(part_dev->part.partname)) == 0){
|
||||
|
||||
/* delete ':' */
|
||||
devname[strlen(devname) - 1] = 0;
|
||||
strncpy(part_dev->part.devname + file_name_start(part_dev->part.devname), devname, FLASH_NAME_LEN);
|
||||
printf("use new devname: %s\n", part_dev->part.devname);
|
||||
ret = XMEDIA_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
ERR_END:
|
||||
free(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_read(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
/* check addr and size */
|
||||
if (addr > part_dev->flash.part_size || addr + size > part_dev->flash.part_size)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
lseek(part_dev->part_fd, addr, SEEK_SET);
|
||||
return read(part_dev->part_fd, buf, size);
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_write(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size, xmedia_char *buf)
|
||||
{
|
||||
xmedia_u32 page_mask = part_dev->flash.page_size - 1;
|
||||
|
||||
if ((addr & page_mask) || (size & page_mask)) {
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* check addr and size */
|
||||
if (addr > part_dev->flash.part_size || addr + size > part_dev->flash.part_size)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
lseek(part_dev->part_fd, addr, SEEK_SET);
|
||||
return write(part_dev->part_fd, buf, size);
|
||||
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_erase(struct flash_part_dev *part_dev, xmedia_u32 addr, xmedia_u32 size)
|
||||
{
|
||||
xmedia_u32 block_mask = part_dev->flash.block_size - 1;
|
||||
struct erase_info_user64 eraseinfo;
|
||||
xmedia_s32 ret;
|
||||
|
||||
if ((addr & block_mask) || (size & block_mask)) {
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* check addr and size */
|
||||
if (addr > part_dev->flash.part_size || addr + size > part_dev->flash.part_size)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
eraseinfo.start = addr;
|
||||
eraseinfo.length = size;
|
||||
|
||||
ret = ioctl(part_dev->part_fd, MEMERASE64, &eraseinfo);
|
||||
if (ret != 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s erase error ret:%d\n", __func__, ret);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_open(struct flash_part_dev *part_dev, unsigned int flag)
|
||||
{
|
||||
if (part_dev->part.partname[0] != 0)
|
||||
get_dname_from_pname(part_dev);
|
||||
|
||||
part_dev->part_fd = open(part_dev->part.devname, flag);
|
||||
return part_dev->part_fd;
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_close(struct flash_part_dev *part_dev)
|
||||
{
|
||||
close(part_dev->part_fd);
|
||||
part_dev->part_fd = -1;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_init(struct flash_part_dev *part_dev)
|
||||
{
|
||||
struct mtd_info_user mtdinfo;
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = ioctl(part_dev->part_fd, MEMGETINFO, &mtdinfo);
|
||||
if (ret != 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "%s mem get info error ret:%d\n", __func__, ret);
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
}
|
||||
|
||||
part_dev->flash.block_size = mtdinfo.erasesize;
|
||||
part_dev->flash.page_size = mtdinfo.writesize;
|
||||
part_dev->flash.oob_size = mtdinfo.oobsize;
|
||||
part_dev->flash.part_size = mtdinfo.size;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 spi_getinfo(struct flash_part_dev *part_dev)
|
||||
{
|
||||
xmedia_s32 ret = -1;
|
||||
xmedia_s32 i = 0;
|
||||
xmedia_char *buff;
|
||||
FILE *fd;
|
||||
xmedia_char *p;
|
||||
xmedia_char tmp[32];
|
||||
|
||||
buff = (xmedia_char *)malloc(TMP_READ_BUF_SIZE);
|
||||
if (buff == XMEDIA_NULL)
|
||||
return XMEDIA_ERRCODE_NOT_ENOUGH_MEMORY;
|
||||
|
||||
fd = fopen(MTD_INFO_DEV, "r");
|
||||
if (fd) {
|
||||
if (NULL == fgets(buff, TMP_READ_BUF_SIZE, fd)) {//skip first line
|
||||
fclose(fd);
|
||||
goto ERR_END;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MTD_PARTITION; i++) {
|
||||
if (fgets(buff, TMP_READ_BUF_SIZE, fd) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
p = &buff[0];
|
||||
p = get_word(p, tmp);
|
||||
if (strncmp(tmp, &part_dev->part.devname[5], strlen(&part_dev->part.devname[5])) == 0) {
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
part_dev->part.block_size = (xmedia_u32)strtoull(tmp, NULL, 16);
|
||||
|
||||
p = get_word(p, tmp);
|
||||
strncpy(part_dev->part.partname, &tmp[1], FLASH_NAME_LEN);
|
||||
|
||||
ret = XMEDIA_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
ERR_END:
|
||||
free(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct flash_opt spi_opt = {
|
||||
.read = spi_read,
|
||||
.write = spi_write,
|
||||
.erase = spi_erase,
|
||||
.init = spi_init,
|
||||
.open = spi_open,
|
||||
.close = spi_close,
|
||||
.get_info = spi_getinfo,
|
||||
};
|
||||
|
||||
struct flash_opt *get_spi_opt(void)
|
||||
{
|
||||
return &spi_opt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "xmedia_debug.h"
|
||||
#include "xmedia_errcode.h"
|
||||
#include "xmedia_pm.h"
|
||||
|
||||
#include "pm_aux.h"
|
||||
#include "pm_ddr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define PM_USR_TRACE(level, fmt, ...) \
|
||||
do { \
|
||||
MODULE_TRACE(level, MOD_ID_PM, "[Func]:%s [Line]:%d [Info]:" fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define XMEDIA_PM_INIT _IO('n', CMD_PM_INIT)
|
||||
#define XMEDIA_PM_DEINIT _IO('n', CMD_PM_DEINIT)
|
||||
#define XMEDIA_PM_GET_WAKEUP_SOURCE _IOWR('n', CMD_PM_GET_WK_SOURCE, xmedia_pm_wakeup_source)
|
||||
#define XMEDIA_PM_GET_ATTR _IOWR('n', CMD_PM_GET_ALL_ATTR, xmedia_pm_attr)
|
||||
#define XMEDIA_PM_SET_ATTR _IOWR('n', CMD_PM_SET_ALL_ATTR, xmedia_pm_attr)
|
||||
#define XMEDIA_PM_SET_AUX _IOWR('n', CMD_PM_SET_AUX, struct aux_mem)
|
||||
#define XMEDIA_PM_GET_DDR_PARAM _IOR('n', CMD_PM_GET_DDR_PARAM, struct lpds_param)
|
||||
#define XMEDIA_PM_GET_WAKEUP_INFO _IOWR('n', CMD_PM_GET_WK_INFO, xmedia_pm_wakeup_info)
|
||||
#define XMEDIA_PM_GET_RTC_INFO _IOR('n', CMD_PM_GET_RTC_INFO, xmedia_pm_rtc_info)
|
||||
|
||||
typedef enum {
|
||||
CMD_PM_INIT = 0,
|
||||
CMD_PM_DEINIT,
|
||||
CMD_PM_SET_ALL_ATTR,
|
||||
CMD_PM_GET_ALL_ATTR,
|
||||
CMD_PM_GET_RTC_ATTR,
|
||||
CMD_PM_SET_RTC_ATTR,
|
||||
CMD_PM_GET_WK_ATTR,
|
||||
CMD_PM_SET_WK_ATTR,
|
||||
CMD_PM_GET_WK_SOURCE,
|
||||
CMD_PM_SET_AUX,
|
||||
CMD_PM_GET_DDR_PARAM,
|
||||
CMD_PM_GET_RTC_INFO,
|
||||
CMD_PM_GET_WK_INFO,
|
||||
CMD_PM_END = 0xFFFF,
|
||||
} xmedia_pm_ioctl_cmd;
|
||||
|
||||
static xmedia_s32 g_pm_mod_fd = -1;
|
||||
static xmedia_s32 g_suspend_fd = -1;
|
||||
|
||||
static pthread_mutex_t g_pm_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static bool g_pm_init = XMEDIA_FALSE;
|
||||
|
||||
#define PM_MUTEX_LOCK() \
|
||||
do { \
|
||||
(void)pthread_mutex_lock(&g_pm_mutex); \
|
||||
} while (0)
|
||||
|
||||
#define PM_MUTEX_UNLOCK() \
|
||||
do { \
|
||||
(void)pthread_mutex_unlock(&g_pm_mutex); \
|
||||
} while (0)
|
||||
|
||||
#define PM_CHECK_INIT_RETURN() \
|
||||
do { \
|
||||
PM_MUTEX_LOCK(); \
|
||||
if (g_pm_init != XMEDIA_TRUE) { \
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "pm not init!\n"); \
|
||||
PM_MUTEX_UNLOCK(); \
|
||||
return XMEDIA_ERRCODE_NOT_INIT; \
|
||||
} \
|
||||
PM_MUTEX_UNLOCK(); \
|
||||
} while (0)
|
||||
|
||||
xmedia_s32 xmedia_pm_init(xmedia_void)
|
||||
{
|
||||
xmedia_pm_init_param param;
|
||||
|
||||
param.type = PM_INIT_TYPE_NORMAL;
|
||||
return xmedia_pm_init_ext(¶m);
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_init_ext(xmedia_pm_init_param *param)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
struct aux_mem aux;
|
||||
|
||||
if (param == NULL)
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
|
||||
if (param->type >= PM_INIT_TYPE_MAX)
|
||||
return XMEDIA_ERRCODE_INVALID_PARAM;
|
||||
|
||||
if (g_pm_init == XMEDIA_TRUE)
|
||||
return XMEDIA_ERRCODE_BUSY;
|
||||
|
||||
if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) {
|
||||
if (read_aux_to_ddr(&aux) != XMEDIA_SUCCESS)
|
||||
return XMEDIA_ERRCODE_NOT_READY;
|
||||
}
|
||||
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (param->type == PM_INIT_TYPE_STR) {
|
||||
if (g_suspend_fd < 0) {
|
||||
g_suspend_fd = open("/sys/power/state", O_RDWR | O_SYNC);
|
||||
if (g_suspend_fd < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/power/state err, ret:%d \n", g_suspend_fd);
|
||||
ret = XMEDIA_ERRCODE_OPEN_FAILED;
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pm_mod_fd < 0) {
|
||||
g_pm_mod_fd = open("/dev/pm", O_RDONLY);
|
||||
if (g_pm_mod_fd < 0) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "open /dev/pm err, ret:%d \n", g_pm_mod_fd);
|
||||
ret = XMEDIA_ERRCODE_OPEN_FAILED;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_INIT, NULL, NULL);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "drv pm init err\n");
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
if ((!is_ram_off_str()) && (param->type == PM_INIT_TYPE_STR)) {
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_AUX, &aux, NULL);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL);
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "drv set aux err\n");
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_pm_init = XMEDIA_TRUE;
|
||||
|
||||
UNLOCK:
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
if (is_ram_off_str() && (param->type == PM_INIT_TYPE_STR)) {
|
||||
|
||||
if (ret == XMEDIA_SUCCESS) {
|
||||
|
||||
ret = ddr_param_check_and_save();
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
PM_USR_TRACE(MODULE_DBG_ERR, "ddr param check/save err ret=%d\n", ret);
|
||||
PM_MUTEX_LOCK();
|
||||
g_pm_init = XMEDIA_FALSE;
|
||||
PM_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ret != XMEDIA_SUCCESS)
|
||||
aux_free_mem();
|
||||
}
|
||||
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
|
||||
PM_MUTEX_LOCK();
|
||||
if (g_suspend_fd >= 0) {
|
||||
close(g_suspend_fd);
|
||||
g_suspend_fd = -1;
|
||||
}
|
||||
|
||||
if (g_pm_mod_fd >= 0) {
|
||||
close(g_pm_mod_fd);
|
||||
g_pm_mod_fd = -1;
|
||||
}
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_deinit(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_DEINIT, NULL, NULL);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
close(g_pm_mod_fd);
|
||||
g_pm_mod_fd = -1;
|
||||
|
||||
close(g_suspend_fd);
|
||||
g_suspend_fd = -1;
|
||||
|
||||
g_pm_init = XMEDIA_FALSE;
|
||||
|
||||
UNLOCK:
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
if (!is_ram_off_str()) {
|
||||
aux_free_mem();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_get_wakeup_source(xmedia_pm_wakeup_source *source)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (source == XMEDIA_NULL) {
|
||||
PM_MUTEX_UNLOCK();
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_WAKEUP_SOURCE, (unsigned int)source, NULL);
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_get_attr(xmedia_pm_attr *attr)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (attr == XMEDIA_NULL) {
|
||||
PM_MUTEX_UNLOCK();
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_ATTR, (unsigned int)attr, NULL);
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_set_attr(xmedia_pm_attr *attr)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (attr == XMEDIA_NULL) {
|
||||
PM_MUTEX_UNLOCK();
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_SET_ATTR, (unsigned int)attr, NULL);
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_get_ddr_param(struct lpds_param *p_lpds_param)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (p_lpds_param == XMEDIA_NULL) {
|
||||
PM_MUTEX_UNLOCK();
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_DDR_PARAM, (unsigned int)p_lpds_param, NULL);
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_suspend(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_FAILURE;
|
||||
xmedia_char suspend_str[] = "mem";
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (g_suspend_fd >= 0) {
|
||||
if (write(g_suspend_fd, suspend_str, strlen(suspend_str)) == strlen(suspend_str)) {
|
||||
ret = XMEDIA_SUCCESS;
|
||||
} else {
|
||||
ret = XMEDIA_ERRCODE_COPY_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmedia_s32 xmedia_pm_get_rtc_info(xmedia_pm_rtc_info *rtc_info)
|
||||
{
|
||||
xmedia_s32 ret = XMEDIA_SUCCESS;
|
||||
|
||||
PM_CHECK_INIT_RETURN();
|
||||
PM_MUTEX_LOCK();
|
||||
|
||||
if (rtc_info == XMEDIA_NULL) {
|
||||
PM_MUTEX_UNLOCK();
|
||||
return XMEDIA_ERRCODE_NULL_PTR;
|
||||
}
|
||||
ret = ioctl(g_pm_mod_fd, XMEDIA_PM_GET_RTC_INFO, (unsigned int)rtc_info, NULL);
|
||||
|
||||
PM_MUTEX_UNLOCK();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
Reference in New Issue
Block a user