某展锐平台有这样一个PCIe的客户需求:
通过执行 AT+QCFG=“pcie/mode” 查询模块当前模式,0 表示PCIe EP 模式;1 表示PCIe RC 模式。
若模块处于RC 模式,执行AT+QCFG=“pcie/mode”,0 并重启模块将PCIe 模式切换至EP 模式;同样,也可以通过命令由EP模式切换到RC模式。
通过验证,设计方案如下实现:
1.在atrouter中写标志到miscdata分区
2.uboot中读取miscdata中的标志,并添加cmdline,传递到内核
3.在设备树中添加RC和EP节点,在对应的驱动中解析cmdline,来区分是否加载对应的驱动
详细步骤如下:
1.在atrouter中写miscdata分区
本来是计划写item项的,但是后面读取时发现在uboot中并没有对应的接口,太麻烦。考虑到uboot中有对应的miscdata读取接口,于是用写miscdata分区方式实现。
数据写到768 * 1024+1024的位置,如果是EP模式,写入EP_mode,如果是RC模式,写入RC_mode。
代码片段如下:
//#include "ATSWDUMPHandler.h"
#include <stdbool.h>
#include <errno.h>
#include <time.h>
#include <getopt.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#define CONFIG_NAND
#ifdef CONFIG_NAND
#include <ubi-user.h>
#include <sys/ioctl.h>
#endif
#ifdef CONFIG_NAND
#define PATH_MISCDATA_PREFIX "/dev/ubi0_"
#else
#define PATH_MISCDATA_PREFIX "/dev/disk/by-partlabel/"
#define PATH_PROC_PREFIX "/etc/productinfo"
#endif
///source/unisoc/engpc/modules/libmiscdata/miscdata.c
#define NAND_MISCDATA_FILESIZE (1024 * 1024)
#define NAND_MISCDATA_CUSTOMER_START (768 * 1024)
#define NAND_MISCDATA_CUSTOMER_CAN_USR ((NAND_MISCDATA_FILESIZE) - (NAND_MISCDATA_CUSTOMER_START))
//下面这个宏定义为你要放的数据存在客户可用的区域的起始地址(至少为0),如果有多个量要存储,记住不要重叠,会覆盖
#define Nand_MISCDATA_INFO_OFFSET 1024
#define NAND_MISCDATA_SWDUMP ((NAND_MISCDATA_CUSTOMER_START)+(Nand_MISCDATA_INFO_OFFSET))
static int swdumplength = 7;
unsigned long get_file_size(const char *path) {
/*
unsigned long filesize = -1;
struct stat statbuff;
if(stat(path, &statbuff) < 0){
return filesize;
}else{
filesize = statbuff.st_size;
}
return filesize;
*/
return NAND_MISCDATA_FILESIZE;
}
int read_miscdata(char *databuf, int data_len) {
AT_LOGD("enter the function read_miscdata");
AT_LOGD("data_len is %d",data_len);
int ret = 0;
int len;
char prop[128] = {
0 };
char miscdata_path[128] = {
0 };
int fd = -1;
sprintf(prop, "%s", PATH_MISCDATA_PREFIX);
sprintf(miscdata_path, "%smiscdata", prop);
fd = open(miscdata_path, O_RDONLY);
if (fd >= 0) {
AT_LOGD("%s open Ok miscdata_path = %s ", __FUNCTION__, miscdata_path);
len = read(fd, databuf, data_len);
AT_LOGD("databuf is %s",databuf);
if (len <= 0) {
ret = -2;
AT_LOGD("%s read fail miscdata_path = %s ", __FUNCTION__, miscdata_path);
}
close(fd);
} else {
AT_LOGD("%s open fail miscdata_path = %s ", __FUNCTION__, miscdata_path);
ret = -3;
}
return ret;
}
int write_mis