/*****************************************************************
|
*Copyright (C) 2021 Seekwave Tech Inc.
|
*Filename : skw_boot.c
|
*Authors:seekwave platform
|
*
|
* This software is licensed under the terms of the the GNU
|
* General Public License version 2, as published by the Free
|
* Software Foundation, and may be copied, distributed, and
|
* modified under those terms.
|
*
|
* This program is distributed in the hope that it will be usefull,
|
* but without any warranty;without even the implied warranty of
|
* merchantability or fitness for a partcular purpose. See the
|
* GUN General Public License for more details.
|
* **************************************************************/
|
|
#include <linux/kernel.h>
|
#include <linux/irq.h>
|
#include <linux/interrupt.h>
|
#include <linux/module.h>
|
#include <linux/gpio.h>
|
#include <linux/delay.h>
|
#include <linux/slab.h>
|
#include <linux/of_gpio.h>
|
#include <linux/completion.h>
|
#include <linux/moduleparam.h>
|
#include <linux/workqueue.h>
|
#include <linux/of.h>
|
#include <linux/device.h>
|
#include <linux/version.h>
|
#include <linux/debugfs.h>
|
#include <linux/fs.h>
|
#include <linux/ctype.h>
|
#include <linux/errno.h>
|
#include <linux/firmware.h>
|
#include <linux/mmc/sdio_func.h>
|
#include <linux/dma-mapping.h>
|
#include <linux/cdev.h>
|
#include <linux/uaccess.h>
|
#include <linux/workqueue.h>
|
#include <linux/scatterlist.h>
|
#include <linux/platform_device.h>
|
#include <linux/pci.h>
|
#include "skw_mem_map.h"
|
#include "skw_boot.h"
|
#include "boot_config.h"
|
/**************************sdio boot start******************************/
|
extern int cp_exception_sts;
|
unsigned int test_debug = 0;
|
unsigned char dl_signal_acount=0;
|
struct platform_device *btboot_pdev;
|
static u64 port_dmamask = DMA_BIT_MASK(32);
|
static struct mutex boot_mutex;
|
static char *local_chip_id = "SV6160LITE";
|
int g_chipen_pin = -1;//default chipen -1,need update by dts or CHIPEN MACRO
|
int skw_use_sdma = 0;//default use adma, 0:adma 1:sdma
|
|
|
//static char iram_image_buffer[360448];
|
//static char dram_image_buffer[206848];
|
#ifdef CONFIG_OF
|
#undef CONFIG_OF
|
#endif
|
//#define SDIO_BUFFER_SIZE (16*1024)
|
/*
|
*add the little endian
|
* */
|
#define _LITTLE_ENDIAN 1
|
|
#define CP_IMG_HEAD0 "kees" //"6B656573"
|
#define CP_IMG_HEAD1 "0616" //"30363136"
|
#define CP_IMG_TAIL0 "evaw" //"65766177"
|
#define CP_IMG_TAIL1 "0616" //"30363136" //ASCII code 36 31 36 30
|
#define CP_NV_HEAD "TSVN" //"5453564E" //ASCII code 36 31 36 30
|
#define CP_NV_TAIL "DEVN" //"4445564E" //ASCII code 36 31 36 30
|
|
#define CHIP_DEV_NAME "sv6160lite" //same with dts device
|
#define CHIP_DEV_NAME_COM "seekwave," CHIP_DEV_NAME
|
|
#define IMG_HEAD_OPS_LEN 4
|
#define RAM_ADDR_OPS_LEN 8
|
#define MODULE_INFO_LEN 12
|
|
#define IMG_HEAD_INFOR_RANGE 0x200 //10K Byte
|
|
static unsigned int EndianConv_32(unsigned int value);
|
/***********sdio drv extern interface **************/
|
/* driect mode,reg access.etc */
|
//extern int skw_get_chipid(char *chip_id);
|
extern int skw_boot_loader(struct seekwave_device *boot_data);
|
extern void *skw_get_bus_dev(void);
|
extern int skw_reset_bus_dev(void);
|
static int skw_first_boot(struct seekwave_device *boot_data);
|
static int skw_boot_init(struct seekwave_device *boot_data);
|
static int skw_download_signal_ops(void);
|
static int get_sleep_status(int portno, char *buffer, int size);
|
static int set_sleep_status(int portno, char *buffer, int size);
|
//int skw_cp_exception_reboot(void);
|
static int skw_start_bt_service(void);
|
static int skw_stop_bt_service(void);
|
/**************************sdio boot end********************************/
|
struct seekwave_device *boot_data;
|
|
//=======================================================
|
//debug sdio macro and Variable
|
//int glb_wifiready_done;
|
#define SKW_CPBOOT_DEBUG 0
|
//=======================================================
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
static unsigned int crc_16_l_calc(char *buf_ptr,unsigned int len)
|
{
|
unsigned int i;
|
unsigned short crc=0;
|
|
while(len--!=0)
|
{
|
for(i= CRC_16_L_SEED;i!=0;i=i>>1)
|
{
|
if((crc &CRC_16_L_POLYNOMIAL)!=0)
|
{
|
crc= crc<<1;
|
crc= crc ^ CRC_16_POLYNOMIAL;
|
}else{
|
crc = crc <<1;
|
}
|
|
if((*buf_ptr &i)!=0)
|
{
|
crc = crc ^ CRC_16_POLYNOMIAL;
|
}
|
}
|
buf_ptr++;
|
}
|
return (crc);
|
}
|
|
|
static int skw_request_firmwares(struct seekwave_device *boot_data,
|
const char *dram_image_name, const char *iram_image_name, const char *nv_mem_name)
|
{
|
int ret;
|
const struct firmware *fw = NULL;
|
|
skwboot_log("request_firmware %s\n", dram_image_name);
|
ret = request_firmware(&fw, dram_image_name, NULL);
|
if (ret < 0) {
|
skwboot_err("request_firmware %s fail\n", dram_image_name);
|
goto ret;
|
}
|
if(!boot_data->first_boot_flag && !boot_data->dram_img_data){
|
boot_data->dram_img_data = (char *)vmalloc( fw->size);
|
if (!boot_data->dram_img_data) {
|
skwboot_err("%s,line:%d the dram img data malloc fail \n",
|
__func__, __LINE__);
|
return -ENOMEM;
|
}
|
}
|
skwboot_log("boot data dram_img_data %p\n",boot_data->dram_img_data);
|
memset(boot_data->dram_img_data, 0, fw->size);
|
memcpy(boot_data->dram_img_data, fw->data, fw->size);
|
boot_data->dram_dl_size = fw->size;
|
release_firmware(fw);
|
//dram crc16
|
boot_data->dram_crc_en = 1;
|
boot_data->dram_crc_offset=0;
|
boot_data->dram_crc_val = crc_16_l_calc(boot_data->dram_img_data + boot_data->dram_crc_offset, boot_data->dram_dl_size);
|
|
skwboot_log("request_firmware %s\n", iram_image_name);
|
ret = request_firmware(&fw, iram_image_name, NULL);
|
if (ret < 0) {
|
skwboot_err("request_firmware %s fail\n", iram_image_name);
|
goto ret;
|
}
|
if(!boot_data->first_boot_flag &&!boot_data->iram_img_data){
|
boot_data->iram_img_data = (char *)vmalloc(fw->size);
|
if (!boot_data->iram_img_data) {
|
vfree(boot_data->dram_img_data);
|
boot_data->dram_img_data = NULL;
|
skwboot_err("%s,line:%d the iram img data malloc fail \n",
|
__func__, __LINE__);
|
return -ENOMEM;
|
}
|
}
|
memset(boot_data->iram_img_data, 0, fw->size);
|
memcpy(boot_data->iram_img_data, fw->data, fw->size);
|
boot_data->iram_dl_size = fw->size;
|
release_firmware(fw);
|
//iram crc16
|
boot_data->iram_crc_en = 1;
|
boot_data->iram_crc_offset=0;
|
boot_data->iram_crc_val = crc_16_l_calc(boot_data->iram_img_data + boot_data->iram_crc_offset, boot_data->iram_dl_size);
|
|
skwboot_log("boot data iram_img_data %p\n",boot_data->iram_img_data);
|
if(nv_mem_name == NULL) {
|
ret = 0;
|
skwboot_warn("nv_mem_name is NULL\n");
|
goto ret;
|
}
|
skwboot_log("request_firmware %s\n", nv_mem_name);
|
ret = request_firmware(&fw, nv_mem_name, NULL);
|
if (ret < 0) {
|
skwboot_err("request_firmware %s fail\n", nv_mem_name);
|
ret = ENOENT;
|
goto ret;
|
}
|
|
boot_data->nv_mem_data = (char *)kzalloc(fw->size, GFP_KERNEL);
|
if (boot_data->nv_mem_data == NULL) {
|
skwboot_err("alloc nv memory failed\n");
|
goto relese_fw;
|
}
|
memcpy(boot_data->nv_mem_data, fw->data, fw->size);
|
boot_data->nv_mem_size = fw->size;
|
if (boot_data->nv_mem_size > 20) {//new nv
|
boot_data->nv_mem_cmfg_data = boot_data->nv_mem_data + *(u32 *)(boot_data->nv_mem_data + NV_CMFG_OFFSET);
|
boot_data->nv_mem_cmfg_size = *(u32 *)(boot_data->nv_mem_data + NV_CMFG_SIZE);
|
|
if (*(u32 *)(boot_data->nv_mem_data + NV_PNFG_OFFSET) != 0)
|
boot_data->nv_mem_pnfg_data = boot_data->nv_mem_data + *(u32 *)(boot_data->nv_mem_data + NV_PNFG_OFFSET);
|
else
|
boot_data->nv_mem_pnfg_data = NULL;
|
boot_data->nv_mem_pnfg_size = *(u32 *)(boot_data->nv_mem_data + NV_PNFG_SIZE);
|
}
|
ret=0;
|
boot_data->nvmem_crc_en = 1;
|
boot_data->nvmem_crc_offset=0;
|
boot_data->nvmem_crc_val = crc_16_l_calc(boot_data->nv_mem_data + boot_data->nvmem_crc_offset, boot_data->nv_mem_size);
|
//print_hex_dump(KERN_ERR, "nvdata:", 0, 16, 1, boot_data->nv_mem_data, boot_data->nv_mem_size, 1);
|
|
relese_fw:
|
release_firmware(fw);
|
ret:
|
return ret;
|
}
|
static int skw_of_property_read(const struct device_node *np,
|
const char *propname, u32 *out_value)
|
{
|
#if KERNEL_VERSION(3, 1, 0) <= LINUX_VERSION_CODE
|
return of_property_read_u32(np, propname, out_value);
|
#else
|
#if 0
|
const unsigned int *value=NULL;
|
value = of_get_property(np, propname,out_value);
|
if (value == NULL){
|
return ENXIO;
|
}else{
|
return 0;
|
}
|
#endif
|
return ENXIO;
|
#endif
|
}
|
static int seekwave_boot_parse_dt(struct platform_device *pdev, struct seekwave_device *boot_data)
|
{
|
int ret = 0;
|
enum of_gpio_flags flags;
|
int tmp_gpio;
|
struct device_node *np = pdev->dev.of_node;
|
/*add the dma type dts config*/
|
if (skw_of_property_read(np, "bt_antenna", &(boot_data->bt_antenna))){
|
skwboot_warn("no BT_antenna setting\n");
|
boot_data->bt_antenna = SKW_BT_ANTENNA_CFG;
|
} else
|
skwboot_log("BT_antenna setting: %d\n", boot_data->bt_antenna);
|
|
if (skw_of_property_read(np, "dma_type", &(boot_data->dma_type))){
|
boot_data->dma_type = SKW_DMA_TYPE_CFG;
|
g_chipen_pin = boot_data->chip_en = MODEM_ENABLE_GPIO;
|
boot_data->host_gpio = HOST_WAKEUP_GPIO_IN;
|
boot_data->chip_gpio = MODEM_WAKEUP_GPIO_OUT;
|
skwboot_warn("no DTS setting\n");
|
} else {
|
#if KERNEL_VERSION(3, 1, 0) <= LINUX_VERSION_CODE
|
boot_data->host_gpio = of_get_named_gpio_flags(np, "gpio_host_wake", 0, &flags);
|
boot_data->chip_gpio = of_get_named_gpio_flags(np, "gpio_chip_wake",0, &flags);
|
g_chipen_pin = boot_data->chip_en = of_get_named_gpio_flags(np, "gpio_chip_en",0, &flags);
|
#endif
|
}
|
boot_data->dma_type = skw_use_sdma?SDMA:ADMA;
|
skwboot_log("%s,modem boot setting::=>\n", __func__);
|
skwboot_log("chipen=%d\n", boot_data->chip_en);
|
skwboot_log("hst_wak_wf=%d\n", boot_data->chip_gpio);
|
skwboot_log("wf_wak_hst=%d\n", boot_data->host_gpio);
|
skwboot_log("dma_type=%d\n", boot_data->dma_type);
|
skwboot_log("bt_antenna=%d\n", boot_data->bt_antenna);
|
|
if (test_debug) {
|
if ((test_debug & 0xF) == 0x1) {
|
boot_data->chip_gpio = -1;
|
boot_data->host_gpio = -1;
|
} else if (test_debug == 5)
|
boot_data->host_gpio = -1;
|
#if KERNEL_VERSION(3, 1, 0) <= LINUX_VERSION_CODE
|
if (boot_data->host_gpio >= 0) {
|
if ((test_debug & 0xF) == 0x2) {
|
skwboot_log("gpio in out swap\n");
|
tmp_gpio = boot_data->chip_gpio;
|
boot_data->chip_gpio = boot_data->host_gpio;
|
boot_data->host_gpio = tmp_gpio;
|
ret = devm_gpio_request_one(
|
&pdev->dev, boot_data->host_gpio,
|
GPIOF_IN, "WL_WAKE_HOST");
|
} else if ((test_debug & 0xF) == 0x3) {
|
skwboot_log("test_debug 3 = gpio in high\n");
|
ret = devm_gpio_request_one(
|
&pdev->dev, boot_data->host_gpio,
|
GPIOF_OUT_INIT_HIGH, "WL_WAKE_HOST");
|
} else if ((test_debug & 0xF) == 0x4) {
|
skwboot_log(
|
"test_debug 4 = gpio in out swap out low\n");
|
tmp_gpio = boot_data->chip_gpio;
|
boot_data->chip_gpio = boot_data->host_gpio;
|
boot_data->host_gpio = tmp_gpio;
|
ret = devm_gpio_request_one(
|
&pdev->dev, boot_data->host_gpio,
|
GPIOF_OUT_INIT_LOW, "WL_WAKE_HOST");
|
} else {
|
ret = devm_gpio_request_one(
|
&pdev->dev, boot_data->host_gpio,
|
GPIOF_IN, "WL_WAKE_HOST");
|
}
|
if (boot_data->chip_gpio >= 0)
|
ret = devm_gpio_request_one(
|
&pdev->dev, boot_data->chip_gpio,
|
GPIOF_OUT_INIT_HIGH, "HOST_WAKE_WL");
|
}
|
#endif
|
if (boot_data->chip_gpio >= 0 && boot_data->host_gpio >= 0) {
|
if (test_debug & 0xF0)
|
boot_data->slp_disable = 1;
|
else
|
boot_data->slp_disable = 0;
|
} else {
|
boot_data->slp_disable = 1;
|
}
|
} else {
|
#if KERNEL_VERSION(3, 1, 0) <= LINUX_VERSION_CODE
|
if (boot_data->host_gpio >= 0)
|
ret = devm_gpio_request_one(&pdev->dev,
|
boot_data->host_gpio,
|
GPIOF_IN, "WL_WAKE_HOST");
|
if (boot_data->chip_gpio >= 0)
|
ret = devm_gpio_request_one(&pdev->dev,
|
boot_data->chip_gpio,
|
GPIOF_OUT_INIT_HIGH,
|
"HOST_WAKE_WL");
|
#endif
|
if (boot_data->chip_gpio >= 0 && boot_data->host_gpio >= 0) {
|
boot_data->slp_disable = 0;
|
} else {
|
boot_data->slp_disable = 1;
|
}
|
}
|
skwboot_log("%s,chipen=%d, gpio_out:%d gpio_in:%d ret = %d\n", __func__,
|
boot_data->chip_en, boot_data->chip_gpio,
|
boot_data->host_gpio, ret);
|
#if KERNEL_VERSION(3, 1, 0) <= LINUX_VERSION_CODE
|
if (boot_data->chip_en >= 0)
|
ret = devm_gpio_request_one(&pdev->dev, boot_data->chip_en, GPIOF_OUT_INIT_HIGH,"CHIP_EN");
|
#endif
|
return ret;
|
}
|
|
/************************************************************************/
|
//Description: BT start service
|
//Func: BT start service
|
//Call:
|
//Author:junwei.jiang
|
//Date:2021-110
|
//Modify:
|
/************************************************************************/
|
static int bt_start_service(int id, void *callback, void *data)
|
{
|
int ret=0;
|
if(cp_exception_sts)
|
return -1;
|
|
skwboot_log("%s pid:%d %s\n", current->comm, current->pid, __func__);
|
ret = skw_start_bt_service();
|
if(ret < 0){
|
skwboot_err("%s boot bt fail \n", __func__);
|
return -1;
|
}
|
return 0;
|
}
|
|
/************************************************************************/
|
//Description: BT stop service
|
//Func: BT stop service
|
//Call:
|
//Author:junwei.jiang
|
//Date:2021-11-1
|
//Modify:
|
/************************************************************************/
|
static int bt_stop_service(int id)
|
{
|
int ret=0;
|
|
if(cp_exception_sts)
|
return 0;
|
|
ret = skw_stop_bt_service();
|
if(ret < 0){
|
skwboot_err("%s boot bt fail \n", __func__);
|
return -1;
|
}
|
skwboot_log("%s OK\n",__func__);
|
return 0;
|
}
|
static void seekwave_release(struct device *dev)
|
|
{
|
}
|
static struct platform_device seekwave_device ={
|
.name = CHIP_DEV_NAME,
|
.dev = {
|
.release = seekwave_release,
|
}
|
};
|
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
static int seekwave_boot_probe(struct platform_device *pdev)
|
{
|
int ret;
|
int time_count=0;
|
struct device *io_bus;
|
|
if (pdev != &seekwave_device)
|
seekwave_device.name = NULL;
|
boot_data = devm_kzalloc(&pdev->dev, sizeof(struct seekwave_device), GFP_KERNEL);
|
if (!boot_data) {
|
skwboot_err("%s :kzalloc error !\n", __func__);
|
return -ENOMEM;
|
}
|
mutex_init(&boot_mutex);
|
seekwave_boot_parse_dt(pdev, boot_data);
|
io_bus = skw_get_bus_dev();
|
if (!io_bus) {
|
skwboot_log("%s :CHIP_RESET AGAIN!\n", __func__);
|
skw_chip_power_reset();
|
do {
|
msleep(10);
|
io_bus = skw_get_bus_dev();
|
} while(!io_bus && time_count++ < 50);
|
}
|
if (!io_bus) {
|
devm_kfree(&pdev->dev, boot_data);
|
skwboot_err("%s get bus dev fail !\n",__func__);
|
return -ENODEV;
|
}
|
//get chip id
|
if (!strncmp(local_chip_id,"SV6160LITE",10)) {
|
if (!strncmp(io_bus->bus->name, "usb", 3)) {
|
boot_data->iram_file_path = "SWT6621S_IRAM_USB.bin";
|
boot_data->dram_file_path = "SWT6621S_DRAM_USB.bin";
|
boot_data->skw_nv_name = "SWT6621S_NV_USB.bin";
|
} else {
|
boot_data->iram_file_path = "SWT6621S_IRAM_SDIO.bin";
|
boot_data->dram_file_path = "SWT6621S_DRAM_SDIO.bin";
|
boot_data->skw_nv_name = "SWT6621S_NV_SDIO.bin";
|
}
|
} else if (!strncmp(local_chip_id,"SV6160",6)) {
|
if (!strncmp(io_bus->bus->name, "usb", 3)) {
|
boot_data->iram_file_path = "SWT6621_IRAM_USB.bin";
|
boot_data->dram_file_path = "SWT6621_DRAM_USB.bin";
|
} else {
|
boot_data->iram_file_path = "SWT6621_IRAM_SDIO.bin";
|
boot_data->dram_file_path = "SWT6621_DRAM_SDIO.bin";
|
}
|
boot_data->skw_nv_name = NULL;
|
} else if (!strncmp(local_chip_id,"SV6316",6)) {
|
if (!strncmp(io_bus->bus->name, "usb", 3)) {
|
boot_data->iram_file_path = "SWT6652_IRAM_USB.bin";
|
boot_data->dram_file_path = "SWT6652_DRAM_USB.bin";
|
} else if (!strncmp(io_bus->bus->name, "pci", 3)) {
|
boot_data->pdev = pdev;
|
if (container_of(io_bus, struct pci_dev, dev)->device == 0x6316) {
|
boot_data->iram_file_path = "SWT6652_IRAM_PCIE.bin";
|
boot_data->dram_file_path = "SWT6652_DRAM_PCIE.bin";
|
} else if (container_of(io_bus, struct pci_dev, dev)->device == 0x6315) {
|
boot_data->iram_file_path = "SWT6652S_IRAM_PCIE.bin";
|
boot_data->dram_file_path = "SWT6652S_DRAM_PCIE.bin";
|
}
|
} else {
|
boot_data->iram_file_path = "SWT6652_IRAM_SDIO.bin";
|
boot_data->dram_file_path = "SWT6652_DRAM_SDIO.bin";
|
}
|
boot_data->skw_nv_name = "SEEKWAVE_NV_SWT6652.bin";
|
} else {
|
skwboot_warn("%s:get chip id is NULL!!!\n", __func__);
|
}
|
ret = skw_boot_init(boot_data);
|
if (ret < 0) {
|
skwboot_err("%s:boot init fail\n", __func__);
|
return -1;
|
}
|
boot_data->pdev = pdev;
|
ret = skw_first_boot(boot_data);
|
if (strncmp(io_bus->bus->name, "usb", 3))
|
skw_bind_boot_driver(io_bus);
|
return ret;
|
}
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
static int seekwave_boot_remove(struct platform_device *pdev)
|
{
|
skwboot_log("%s the Enter \n", __func__);
|
|
if (btboot_pdev) {
|
platform_device_unregister(btboot_pdev);
|
btboot_pdev = NULL;
|
}
|
if (boot_data) {
|
if (!boot_data->iram_img_data) {
|
skwboot_log(":iram_img_data is NULL\n");
|
} else {
|
vfree(boot_data->iram_img_data);
|
boot_data->iram_img_data = NULL;
|
}
|
if (!boot_data->dram_img_data) {
|
skwboot_err(":dram_img_data is NULL\n");
|
} else {
|
vfree(boot_data->dram_img_data);
|
boot_data->dram_img_data = NULL;
|
}
|
if (boot_data->nv_mem_size > 20) { //new nv
|
skwboot_log(":free nv_mem_data\n");
|
if (boot_data->nv_mem_data) {
|
skwboot_log(":free 2 nv_mem_data\n");
|
kfree(boot_data->nv_mem_data);
|
boot_data->nv_mem_data = NULL;
|
}
|
}
|
boot_data->dl_base_img = NULL;
|
boot_data->skw_nv_name = NULL;
|
boot_data->iram_file_path = NULL;
|
boot_data->dram_file_path = NULL;
|
boot_data->wifi_start = NULL;
|
boot_data->wifi_stop = NULL;
|
boot_data->bt_start = NULL;
|
boot_data->bt_stop = NULL;
|
boot_data->skw_dloader_module = NULL;
|
devm_kfree(&pdev->dev, boot_data);
|
boot_data = NULL;
|
} else {
|
skwboot_err("%s:boot_data is NULL\n", __func__);
|
}
|
mutex_destroy(&boot_mutex);
|
return 0;
|
}
|
extern void skw_modem_log_stop_rec(void);
|
static void seekwave_boot_shutdown(struct platform_device *pdev)
|
{
|
skwboot_log("%s enter ...\n", __func__);
|
skw_modem_log_stop_rec();
|
skw_reset_bus_dev();
|
}
|
static const struct of_device_id seekwave_match_table[] ={
|
|
{ .compatible = CHIP_DEV_NAME_COM},
|
{ },
|
};
|
|
static struct platform_driver seekwave_driver ={
|
|
.driver = {
|
.owner = THIS_MODULE,
|
.name = CHIP_DEV_NAME,
|
.of_match_table = seekwave_match_table,
|
},
|
.probe = seekwave_boot_probe,
|
.remove = seekwave_boot_remove,
|
.shutdown = seekwave_boot_shutdown,
|
};
|
|
/***********************************************************************
|
*Description:chipen gpio pin reset
|
*Seekwave tech LTD
|
*Author:zongqiang.cheng
|
*Date:2025-3-18
|
*Modify:
|
***********************************************************************/
|
int skw_chipen_gpio_reset(int on)
|
{
|
int chip_en = g_chipen_pin;
|
if (chip_en < 0){
|
printk("chip_en need set !!\n");
|
return -1;
|
}
|
|
if(on) {
|
gpio_set_value(chip_en, 1);
|
printk("seekwave power on !!\n");
|
} else {
|
gpio_set_value(chip_en, 0);
|
printk("seekwave power down !!\n");
|
}
|
return 0;
|
}
|
|
/***********************************************************************
|
*Description:BT download boot pdata
|
*Seekwave tech LTD
|
*Author:junwei.jiang
|
*Date:2021-11-3
|
*Modify:
|
***********************************************************************/
|
static int get_sleep_status(int portno, char *buffer, int size)
|
{
|
memcpy(buffer, "WAKE", 4);
|
if (boot_data->host_gpio >=0) {
|
if (gpio_get_value(boot_data->host_gpio) == 0)
|
memcpy(buffer, "DOWN", 4);
|
}
|
return 4;
|
}
|
static int set_sleep_status(int portno, char *buffer, int size)
|
{
|
int i, count;
|
|
for(i=0; i<2; i++) {
|
if (gpio_get_value(boot_data->host_gpio))
|
return 1;
|
if(buffer && !strncmp(buffer, "WAKE", 4)) {
|
gpio_set_value(boot_data->chip_gpio, 0);
|
udelay(10);
|
gpio_set_value(boot_data->chip_gpio, 1);
|
}
|
count = 0;
|
do {
|
if (count++ < 100)
|
udelay(20);
|
} while(gpio_get_value(boot_data->host_gpio) ==0);
|
if (gpio_get_value(boot_data->host_gpio))
|
return 1;
|
udelay(100);
|
}
|
if (gpio_get_value(boot_data->host_gpio)==0)
|
skwboot_log("wakeup CHIP timeout!!! \n");
|
return 1;
|
}
|
struct sv6160_platform_data boot_pdata = {
|
.data_port = 8,
|
.bus_type = SDIO_LINK,
|
.max_buffer_size = 0x800,
|
.align_value = 4,
|
.hw_sdma_rx = get_sleep_status,
|
.hw_sdma_tx = set_sleep_status,
|
.open_port = bt_start_service,
|
.close_port = bt_stop_service,
|
};
|
|
/***************************************************************
|
*Description:BT bind boot driver
|
*Seekwave tech LTD
|
*Author:junwei.jiang
|
*Date:2021-11-3
|
*Modify:
|
***************************************************************/
|
int skw_bind_boot_driver(struct device *dev)
|
{
|
struct platform_device *pdev;
|
char pdev_name[32];
|
int ret = 0;
|
sprintf(pdev_name, "skw_ucom");
|
if(!dev){
|
skwboot_err("%s the dev fail \n", __func__);
|
return -1;
|
}
|
if (btboot_pdev)
|
return ret;
|
|
pdev = platform_device_alloc(pdev_name, PLATFORM_DEVID_AUTO);
|
if(!pdev)
|
return -ENOMEM;
|
pdev->dev.parent = dev;
|
pdev->dev.dma_mask = &port_dmamask;
|
pdev->dev.coherent_dma_mask = port_dmamask;
|
boot_pdata.port_name = "BTBOOT";
|
boot_pdata.data_port = 8;
|
//skw_get_chipid((char *)&boot_data->chip_id);
|
ret = platform_device_add_data(pdev, &boot_pdata, sizeof(boot_pdata));
|
if(ret) {
|
dev_err(dev, "failed to add boot data \n");
|
platform_device_put(pdev);
|
return ret;
|
}
|
ret = platform_device_add(pdev);
|
if(ret) {
|
platform_device_put(pdev);
|
skwboot_err("%s,line:%d the device add fail \n",__func__,__LINE__);
|
return ret;
|
}
|
btboot_pdev = pdev;
|
return ret;
|
}
|
/****************************************************************
|
*Description:the data Little Endian process interface
|
*Func:EndianConv_32
|
*Calls:None
|
*Call By:The img data process
|
*Input:value
|
*Output:the Endian data
|
*Return:value
|
*Others:
|
*Author:JUNWEI.JIANG
|
*Date:2021-08-26
|
* **************************************************************/
|
static unsigned int EndianConv_32(unsigned int value)
|
{
|
#ifdef _LITTLE_ENDIAN
|
unsigned int nTmp = (value >>24 | value <<24);
|
nTmp |= ((value >> 8) & 0x0000FF00);
|
nTmp |= ((value << 8) & 0x00FF0000);
|
return nTmp;
|
#else
|
return value;
|
#endif
|
}
|
|
/****************************************************************
|
*Description:dram read the double img file
|
*Func:
|
*Calls:
|
*Call By:
|
*Input:the file path
|
*Output:download data and the data size dl_data image_size
|
*Return:0:pass other fail
|
*Others:
|
*Author:JUNWEI.JIANG
|
*Date:2022-02-07
|
* **************************************************************/
|
static int skw_download_signal_ops(void)
|
{
|
unsigned int tmp_signal = 0;
|
//download done flag ++
|
boot_data->dl_done_signal ++;
|
tmp_signal = boot_data->dl_done_signal;
|
boot_data->dl_done_signal = 0xff&tmp_signal;
|
boot_data->dl_acount_addr = SKW_SDIO_PD_DL_AP2CP_BSP;
|
|
//gpio need set high or low power interrupt to cp wakeup
|
boot_data->gpio_out = boot_data->chip_gpio;
|
if(boot_data->gpio_val)
|
boot_data->gpio_val =0;
|
else
|
boot_data->gpio_val =1;
|
skwboot_log("%s line:%d download data ops done the dl_count=%d \n", __func__, __LINE__,boot_data->dl_done_signal);
|
return 0;
|
}
|
/****************************************************************
|
*Description:analysis the double img dram iram
|
*Func:
|
*Calls:
|
*Call By:
|
*Input:the file path
|
*Output:download data and the data size dl_data image_size
|
*Return:0:pass other fail
|
*Others:
|
*Author:JUNWEI.JIANG
|
*Date:2022-02-07
|
* **************************************************************/
|
static int skw_boot_init(struct seekwave_device *boot_data)
|
{
|
int i =0;
|
int k =0;
|
unsigned int head_offset=0;
|
unsigned int tail_offset=0;
|
int ret = 0;
|
struct img_head_data_t dl_data_info;
|
unsigned int *data=NULL;
|
unsigned int *nvdata=NULL;
|
unsigned int *dl_addr_data=NULL;
|
|
ret = skw_request_firmwares(boot_data, boot_data->dram_file_path,
|
boot_data->iram_file_path,
|
boot_data->skw_nv_name);
|
if (ret == ENOENT) {
|
ret = skw_request_firmwares(boot_data,
|
boot_data->dram_file_path,
|
boot_data->iram_file_path,
|
SEEKWAVE_NV_NAME);
|
}
|
skwboot_log("image_size=%d,%d, ret=%d\n", boot_data->iram_dl_size,
|
boot_data->dram_dl_size, ret);
|
if (ret < 0){
|
skwboot_err("request image fail\n");
|
return ret;
|
}
|
boot_data->head_addr = 0;
|
boot_data->tail_addr = 0;
|
boot_data->bsp_head_addr = 0;
|
boot_data->bsp_tail_addr = 0;
|
boot_data->wifi_head_addr =0;
|
boot_data->wifi_tail_addr = 0;
|
boot_data->bt_head_addr = 0;
|
boot_data->bt_tail_addr = 0;
|
boot_data->nv_head_addr = 0;
|
boot_data->nv_tail_addr = 0;
|
boot_data->nv_data_size = 0;
|
|
if(boot_data->iram_img_data!=NULL){
|
/*analysis the img*/
|
for(i=0; i*IMG_HEAD_OPS_LEN<IMG_HEAD_INFOR_RANGE; i++)
|
{
|
if(!head_offset)
|
{
|
if((0==memcmp(CP_IMG_HEAD0, boot_data->iram_img_data+i*IMG_HEAD_OPS_LEN,IMG_HEAD_OPS_LEN))&&
|
(0==memcmp(CP_IMG_HEAD1,boot_data->iram_img_data+(i+1)*IMG_HEAD_OPS_LEN,IMG_HEAD_OPS_LEN)))
|
head_offset = (i+1)*IMG_HEAD_OPS_LEN;
|
}else if(!tail_offset){
|
if((0==memcmp(CP_IMG_TAIL0, boot_data->iram_img_data+i*IMG_HEAD_OPS_LEN, IMG_HEAD_OPS_LEN))&&
|
(0==memcmp(CP_IMG_TAIL1, boot_data->iram_img_data+(i+1)*IMG_HEAD_OPS_LEN, IMG_HEAD_OPS_LEN))){
|
tail_offset = (i-1)*IMG_HEAD_OPS_LEN;
|
break;
|
}
|
}
|
}
|
|
/*analysis the nv*/
|
for(k=0; k*IMG_HEAD_OPS_LEN<IMG_HEAD_INFOR_RANGE; k++)
|
{
|
if(!boot_data->nv_head_addr)
|
{
|
if(0==memcmp(CP_NV_HEAD, boot_data->iram_img_data+k*IMG_HEAD_OPS_LEN,IMG_HEAD_OPS_LEN))
|
boot_data->nv_head_addr = k*IMG_HEAD_OPS_LEN;
|
}else if(!boot_data->nv_tail_addr){
|
if((0==memcmp(CP_NV_TAIL, boot_data->iram_img_data+k*IMG_HEAD_OPS_LEN, IMG_HEAD_OPS_LEN))){
|
boot_data->nv_tail_addr = k*IMG_HEAD_OPS_LEN;
|
boot_data->nv_data_size = boot_data->nv_tail_addr - boot_data->nv_head_addr - IMG_HEAD_OPS_LEN;
|
nvdata = (u32 *) &boot_data->iram_img_data[boot_data->nv_head_addr];
|
break;
|
}
|
}
|
}
|
if(!tail_offset){
|
skwboot_err("%s,%d,the iram_img not need analysis!!! or Fail!! \n",__func__,__LINE__);
|
return -1;
|
}else{
|
//get the iram img addr and dram img addr
|
dl_addr_data = (unsigned int *)(boot_data->iram_img_data+head_offset+IMG_HEAD_OPS_LEN);
|
boot_data->iram_dl_addr = dl_addr_data[0];
|
boot_data->dram_dl_addr = dl_addr_data[1];
|
head_offset = head_offset+RAM_ADDR_OPS_LEN;//jump the ram addr data;
|
|
skwboot_log("%s line:%d,the tail_offset ---0x%x, the head_offset --0x%x ,iram_addr=0x%x,dram_addr=0x%x, \
|
nv_head_addr:0x%x,nv_tail_addr:0x%x,nv_size=%d\n",__func__, __LINE__,tail_offset, head_offset,
|
boot_data->iram_dl_addr,boot_data->dram_dl_addr,boot_data->nv_head_addr,boot_data->nv_tail_addr,
|
boot_data->nv_data_size);
|
}
|
/*need download the img bin for WIFI or BT service dl_module >0*/
|
head_offset = head_offset +IMG_HEAD_OPS_LEN;
|
/*get the img head tail offset*/
|
boot_data->head_addr = head_offset;
|
boot_data->tail_addr = tail_offset;
|
|
skwboot_log("%s line:%d analysis the img module\n", __func__, __LINE__);
|
for(i=0; i*MODULE_INFO_LEN<=(tail_offset-head_offset); i++)
|
{
|
data = (unsigned int *)(boot_data->iram_img_data +head_offset+i*MODULE_INFO_LEN);
|
dl_data_info.dl_addr=data[0];
|
dl_data_info.write_addr =data[2];
|
dl_data_info.index = 0x000000FF&EndianConv_32(data[1]);
|
dl_data_info.data_size = 0x00FFFFFF&data[1];
|
if(dl_data_info.index==1){
|
boot_data->bsp_index_count +=1;
|
}else if(dl_data_info.index ==2){
|
boot_data->wifi_index_count +=1;
|
}else if(dl_data_info.index ==3){
|
boot_data->bt_index_count +=1;
|
}
|
skwboot_log("%s line:%d dl_addr=0x%x, write_addr=0x%x, index=0x%x,data_size=0x%x\n", __func__,
|
__LINE__, dl_data_info.dl_addr,dl_data_info.write_addr,dl_data_info.index,dl_data_info.data_size);
|
}
|
skwboot_log("%s line:%d bsp_index count:%d, bt_index_count=%d, wifi_index_count=%d \n",
|
__func__, __LINE__,boot_data->bsp_index_count,boot_data->bt_index_count,boot_data->wifi_index_count);
|
//get the dl count for the service download module img
|
boot_data->wifi_dl_count = boot_data->bsp_index_count + boot_data->wifi_index_count;
|
boot_data->all_dl_count = boot_data->bsp_index_count + boot_data->wifi_index_count + boot_data->bt_index_count;
|
boot_data->bt_dl_count = boot_data->bsp_index_count + boot_data->bt_index_count;
|
|
if (boot_data->nv_mem_size > 20) {//new nv
|
if(boot_data->nv_mem_cmfg_size && (boot_data->nv_mem_cmfg_size <= boot_data->nv_data_size)){
|
memcpy((boot_data->iram_img_data+boot_data->nv_head_addr+4),boot_data->nv_mem_cmfg_data,boot_data->nv_mem_cmfg_size);
|
//kfree(boot_data->nv_mem_data);
|
//boot_data->nv_mem_data = NULL;
|
}
|
} else {//old nv
|
if(boot_data->nv_mem_size && (boot_data->nv_mem_size <= boot_data->nv_data_size)){
|
memcpy((boot_data->iram_img_data+boot_data->nv_head_addr+4),boot_data->nv_mem_data,boot_data->nv_mem_size);
|
kfree(boot_data->nv_mem_data);
|
boot_data->nv_mem_data = NULL;
|
}
|
}
|
//print_hex_dump(KERN_ERR, "nvcom ", 0, 16, 1,boot_data->iram_img_data+boot_data->nv_head_addr, boot_data->nv_data_size+8, 1);
|
}
|
return 0;
|
}
|
//debug cp boot for setvalue
|
int gbl_count_flag=0;
|
/****************************************************************
|
*Description:download the wifi bt service img,
|
*Func:
|
*Calls:
|
*Call By:
|
*Input:the service index
|
*Output:download data
|
*Return:0:pass other fail
|
*Others:
|
*Author:JUNWEI.JIANG
|
*Date:2024-02-07
|
* **************************************************************/
|
static int skw_dloader_module(int service_index)
|
{
|
int i =0;
|
int ret = 0;
|
struct img_head_data_t dl_data_info;
|
unsigned int *data=NULL;
|
int tmp_count=0;
|
int total_count=0;
|
#if SKW_CPBOOT_DEBUG//for wifionly debug cp boot sleep no dl img setvalue 1;
|
skwboot_log("%s:the debug skw_dloader Enter \n",__func__);
|
return 0;
|
#endif
|
//dl count flag setvalue
|
if(service_index==SKW_WIFI){
|
tmp_count = boot_data->wifi_dl_count;
|
}else if(service_index == SKW_BT){
|
tmp_count = boot_data->bt_dl_count;
|
}else if(service_index == SKW_ALL){
|
tmp_count = boot_data->all_dl_count;
|
}else{
|
skwboot_warn("%s No service index ops!!!\n",__func__);
|
}
|
#if 1//debug cp boot for setvalue 1
|
if(gbl_count_flag==0){
|
boot_data->dl_done_signal=0;
|
gbl_count_flag=1;
|
}
|
#endif
|
skwboot_log("the dl_count ---dl_bin_counts ===%d\n",tmp_count);
|
boot_data->service_ops = SKW_NO_SERVICE;
|
if(boot_data->iram_img_data!=NULL){
|
for(i=0; i*MODULE_INFO_LEN<=(boot_data->tail_addr-boot_data->head_addr); i++)
|
{
|
data = (unsigned int *)(boot_data->iram_img_data +boot_data->head_addr+i*MODULE_INFO_LEN);
|
dl_data_info.dl_addr=data[0];
|
dl_data_info.write_addr =data[2];
|
dl_data_info.index = 0x000000FF&EndianConv_32(data[1]);
|
dl_data_info.data_size = 0x00FFFFFF&data[1];
|
skwboot_log("%s line:%d dl_addr=0x%x, write_addr=0x%x, index=0x%x,data_size=0x%x\n", __func__,
|
__LINE__, dl_data_info.dl_addr,dl_data_info.write_addr,dl_data_info.index,dl_data_info.data_size);
|
if(service_index ==dl_data_info.index || SKW_BSP== dl_data_info.index || service_index == SKW_ALL){
|
total_count +=1;
|
boot_data->dl_base_addr = dl_data_info.write_addr;
|
boot_data->dl_size = dl_data_info.data_size;
|
if(dl_data_info.dl_addr >= boot_data->dram_dl_addr){
|
//iram data dload img
|
boot_data->dl_offset_addr =dl_data_info.dl_addr- boot_data->dram_dl_addr;
|
boot_data->dl_base_img = boot_data->dram_img_data;
|
}else {
|
//dram data dload img
|
boot_data->dl_offset_addr =dl_data_info.dl_addr- boot_data->iram_dl_addr;
|
boot_data->dl_base_img = boot_data->iram_img_data;
|
}
|
if(tmp_count == total_count){
|
skw_download_signal_ops();
|
}
|
ret=skw_boot_loader(boot_data);
|
if(ret){
|
skwboot_err("%s the load module=%d, fail,ret=%d \n", __func__, dl_data_info.index, ret);
|
break;
|
}
|
}else{
|
skwboot_err("%s not need to load module_index=%d,ret=%d \n", __func__, dl_data_info.index, ret);
|
}
|
}
|
|
}
|
return ret;
|
}
|
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
int skw_start_wifi_service(void)
|
{
|
int ret =0;
|
|
skwboot_log("%s Enter cp_state =%d \n",__func__, cp_exception_sts);
|
mutex_lock(&boot_mutex);
|
boot_data->service_ops = SKW_WIFI_START;
|
#if defined(SKW_BOOT_MEMPOWERON)
|
boot_data->dl_module = NONE_BOOT;
|
boot_data->first_boot_flag =1;
|
boot_data->dl_base_img = NULL;
|
#else
|
boot_data->first_dl_flag = 1;
|
boot_data->dl_module = SKW_WIFI_BOOT;
|
//download done flag ++
|
skw_download_signal_ops();
|
#endif
|
ret = skw_boot_loader(boot_data);
|
mutex_unlock(&boot_mutex);
|
if(ret !=0)
|
{
|
skwboot_err("%s,line:%d boot fail \n", __func__,__LINE__);
|
return -1;
|
}
|
|
skwboot_log("%s wifi boot sucessfull\n", __func__);
|
return 0;
|
}
|
EXPORT_SYMBOL_GPL(skw_start_wifi_service);
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
int skw_stop_wifi_service(void)
|
{
|
int ret =0;
|
skwboot_log("%s Enter cp_state =%d \n",__func__, cp_exception_sts);
|
mutex_lock(&boot_mutex);
|
boot_data->service_ops = SKW_WIFI_STOP;
|
#if defined(SKW_BOOT_MEMPOWERON)
|
boot_data->dl_module = NONE_BOOT;
|
boot_data->first_boot_flag =1;
|
boot_data->dl_base_img = NULL;
|
#else
|
boot_data->dl_module = 0;
|
boot_data->first_dl_flag = 1;
|
#endif
|
//download done flag ++
|
//gpio need set high or low power interrupt to cp wakeup
|
boot_data->gpio_out = boot_data->chip_gpio;
|
if(boot_data->gpio_val)
|
boot_data->gpio_val =0;
|
else
|
boot_data->gpio_val =1;
|
ret = skw_boot_loader(boot_data);
|
mutex_unlock(&boot_mutex);
|
if(ret !=0)
|
{
|
skwboot_warn("dload the img fail \n");
|
return -1;
|
}
|
skwboot_log("seekwave boot stop done:%s\n",__func__);
|
return 0;
|
}
|
EXPORT_SYMBOL_GPL(skw_stop_wifi_service);
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
static int skw_start_bt_service(void)
|
{
|
int ret=0;
|
skwboot_log("%s Enter cp_state =%d \n",__func__, cp_exception_sts);
|
mutex_lock(&boot_mutex);
|
boot_data->service_ops = SKW_BT_START;
|
#if defined(SKW_BOOT_MEMPOWERON)
|
boot_data->first_boot_flag =1;
|
boot_data->dl_base_img = NULL;
|
boot_data->dl_module = NONE_BOOT;
|
#else
|
boot_data->first_dl_flag = 1;
|
boot_data->dl_module = SKW_BT_BOOT;
|
//download done flag ++
|
skw_download_signal_ops();
|
#endif
|
ret = skw_boot_loader(boot_data);
|
mutex_unlock(&boot_mutex);
|
if(ret !=0)
|
{
|
skwboot_err("%s boot fail \n", __func__);
|
return -1;
|
}
|
|
skwboot_log("%s line:%d , boot bt sucessfully!\n", __func__,__LINE__);
|
return 0;
|
}
|
|
/***************************************************************************
|
*Description:
|
*Seekwave tech LTD
|
*Author:
|
*Date:
|
*Modify:
|
**************************************************************************/
|
static int skw_stop_bt_service(void)
|
{
|
int ret =0;
|
skwboot_log("%s Enter cp_state =%d \n",__func__, cp_exception_sts);
|
mutex_lock(&boot_mutex);
|
boot_data->service_ops = SKW_BT_STOP;
|
#if defined(SKW_BOOT_MEMPOWERON)
|
boot_data->first_boot_flag = 1;
|
boot_data->dl_base_img = NULL;
|
#else
|
boot_data->dl_module = 0;
|
boot_data->first_dl_flag = 1;
|
#endif
|
//download done flag ++
|
boot_data->dl_module = NONE_BOOT;
|
//gpio need set high or low power interrupt to cp wakeup
|
boot_data->gpio_out = boot_data->chip_gpio;
|
if(boot_data->gpio_val)
|
boot_data->gpio_val =0;
|
else
|
boot_data->gpio_val =1;
|
ret = skw_boot_loader(boot_data);
|
mutex_unlock(&boot_mutex);
|
if(ret !=0)
|
{
|
skwboot_warn("dload the img fail \n");
|
return -1;
|
}
|
skwboot_log("seekwave boot stop done:%s\n",__func__);
|
return 0;
|
}
|
|
/****************************************************************
|
*Description:double iram dram img first boot cp
|
*Func:
|
*Calls:
|
*Call By:skw_first_boot
|
*Input:the file path
|
*Output:download data and the data size dl_data image_size
|
*Return:0:pass other fail
|
*Others:
|
*Author:JUNWEI.JIANG
|
*Date:2022-02-07
|
* **************************************************************/
|
static int skw_first_boot(struct seekwave_device *boot_data)
|
{
|
int ret =0;
|
//get the img data
|
#ifdef DEBUG_SKWBOOT_TIME
|
ktime_t cur_time,last_time;
|
cur_time = ktime_get();
|
#endif
|
//set download the value;
|
boot_data->service_ops = SKW_NO_SERVICE;
|
boot_data->save_setup_addr = SKW_SDIO_PD_DL_AP2CP_BSP; //160
|
boot_data->gpio_out = boot_data->chip_gpio;
|
boot_data->gpio_val = 0;
|
boot_data->dl_module = 0;
|
boot_data->first_dl_flag =0;
|
boot_data->gpio_in = boot_data->host_gpio;
|
boot_data->dma_type_addr = SKW_SDIO_PLD_DMA_TYPE;
|
boot_data->slp_disable_addr = SKW_SDIO_CP_SLP_SWITCH;
|
boot_data->wifi_start = skw_start_wifi_service;
|
boot_data->wifi_stop = skw_stop_wifi_service;
|
boot_data->bt_start = skw_start_bt_service;
|
boot_data->bt_stop = skw_stop_bt_service;
|
boot_data->skw_dloader_module = skw_dloader_module;
|
ret = skw_boot_loader(boot_data);
|
if(ret < 0){
|
skwboot_err("%s firt boot cp fail \n", __func__);
|
return -1;
|
}
|
//download done set the download flag;
|
boot_data->first_dl_flag =1;
|
boot_data->first_boot_flag =1;
|
|
//download done tall cp acount;
|
boot_data->dl_done_signal &= 0xFF;
|
boot_data->dl_done_signal +=1;
|
skwboot_log("%s first boot pass\n", __func__);
|
#ifdef DEBUG_SKWBOOT_TIME
|
last_time = ktime_get();
|
skwboot_log("%s,the download time start time %llu and the over time %llu \n",
|
__func__, cur_time, last_time);
|
#endif
|
return ret;
|
}
|
int seekwave_boot_init(char *chip_id)
|
{
|
int ret;
|
|
skwboot_log("%s: enter chip_id=%s\n",__func__,chip_id);
|
if(chip_id != NULL && strlen(chip_id)!=0){
|
local_chip_id = chip_id;
|
}
|
btboot_pdev = NULL;
|
skw_ucom_init();
|
ret = platform_driver_register(&seekwave_driver);
|
if (seekwave_device.name)
|
platform_device_register(&seekwave_device);
|
return ret;
|
}
|
void seekwave_boot_exit(void)
|
{
|
skw_ucom_exit();
|
|
if (seekwave_device.name)
|
platform_device_unregister(&seekwave_device);
|
platform_driver_unregister(&seekwave_driver);
|
}
|