android13/external/wifi_driver/aic8800/aic8800_bsp/aic_bsp_main.c

358 lines
9.7 KiB
C

#include <linux/module.h>
#include <linux/inetdevice.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#include "aic_bsp_driver.h"
#include "rwnx_version_gen.h"
#include "aicwf_txq_prealloc.h"
#define DRV_DESCRIPTION "AIC BSP"
#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi"
#define DRV_AUTHOR "AICSemi"
#define DRV_VERS_MOD "1.0"
int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE;
static struct platform_device *aicbsp_pdev;
const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02;
const struct aicbsp_firmware fw_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u02)",
.bt_adid = "fw_adid.bin",
.bt_patch = "fw_patch.bin",
.bt_table = "fw_patch_table.bin",
.wl_fw = "fmacfw.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u02)",
.bt_adid = "fw_adid.bin",
.bt_patch = "fw_patch.bin",
.bt_table = "fw_patch_table.bin",
.wl_fw = "fmacfw_rf.bin"
},
};
const struct aicbsp_firmware fw_u03[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u03/u04)",
.bt_adid = "fw_adid_u03.bin",
.bt_patch = "fw_patch_u03.bin",
.bt_table = "fw_patch_table_u03.bin",
#ifdef CONFIG_MCU_MESSAGE
.wl_fw = "fmacfw_8800m_custmsg.bin"
#else
.wl_fw = "fmacfw.bin"
#endif
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u03/u04)",
.bt_adid = "fw_adid_u03.bin",
.bt_patch = "fw_patch_u03.bin",
.bt_table = "fw_patch_table_u03.bin",
.wl_fw = "fmacfw_rf.bin"
},
};
const struct aicbsp_firmware fw_8800dc_u01[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(sdio u01)",
.bt_adid = "fw_adid_8800dc.bin",
.bt_patch = "fw_patch_8800dc.bin",
.bt_table = "fw_patch_table_8800dc.bin",
.wl_fw = "fmacfw_8800dc.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(sdio u01)",
.bt_adid = "fw_adid_8800dc.bin",
.bt_patch = "fw_patch_8800dc.bin",
.bt_table = "fw_patch_table_8800dc.bin",
.wl_fw = "fmacfw_rf_8800dc.bin"
},
};
const struct aicbsp_firmware fw_8800dc_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800dc sdio u02)",
.bt_adid = "fw_adid_8800dc_u02.bin",
.bt_patch = "fw_patch_8800dc_u02.bin",
.bt_table = "fw_patch_table_8800dc_u02.bin",
.wl_fw = "fmacfw_patch_8800dc_u02.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800dc sdio u02)",
.bt_adid = "fw_adid_8800dc_u02.bin",
.bt_patch = "fw_patch_8800dc_u02.bin",
.bt_table = "fw_patch_table_8800dc_u02.bin",
.wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin
},
};
const struct aicbsp_firmware fw_8800d80_u01[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800d80 sdio u01)",
.bt_adid = "fw_adid_8800d80.bin",
.bt_patch = "fw_patch_8800d80.bin",
.bt_table = "fw_patch_table_8800d80.bin",
.wl_fw = "fmacfw_8800d80.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800d80 sdio u01)",
.bt_adid = "fw_adid_8800d80.bin",
.bt_patch = "fw_patch_8800d80.bin",
.bt_table = "fw_patch_table_8800d80.bin",
.wl_fw = "lmacfw_rf_8800d80.bin"
},
};
const struct aicbsp_firmware fw_8800d80_u02[] = {
[AICBSP_CPMODE_WORK] = {
.desc = "normal work mode(8800d80 sdio u02)",
.bt_adid = "fw_adid_8800d80_u02.bin",
.bt_patch = "fw_patch_8800d80_u02.bin",
.bt_table = "fw_patch_table_8800d80_u02.bin",
.wl_fw = "fmacfw_8800d80_u02.bin"
},
[AICBSP_CPMODE_TEST] = {
.desc = "rf test mode(8800d80 sdio u02)",
.bt_adid = "fw_adid_8800d80_u02.bin",
.bt_patch = "fw_patch_8800d80_u02.bin",
.bt_table = "fw_patch_table_8800d80_u02.bin",
.wl_fw = "lmacfw_rf_8800d80_u02.bin"
},
};
struct aicbsp_info_t aicbsp_info = {
.hwinfo_r = AICBSP_HWINFO_DEFAULT,
.hwinfo = AICBSP_HWINFO_DEFAULT,
.cpmode = AICBSP_CPMODE_DEFAULT,
.fwlog_en = AICBSP_FWLOG_EN_DEFAULT,
};
struct mutex aicbsp_power_lock;
static struct platform_driver aicbsp_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "aic_bsp",
},
//.probe = aicbsp_probe,
//.remove = aicbsp_remove,
};
static ssize_t cpmode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
uint8_t i = 0;
count += sprintf(&buf[count], "Support mode value:\n");
for (i = 0; i < AICBSP_CPMODE_MAX; i++) {
if (aicbsp_firmware_list[i].desc)
count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc);
}
count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode);
count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid);
count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch);
count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table);
count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw);
return count;
}
static ssize_t cpmode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long val;
int err = kstrtoul(buf, 0, &val);
if (err)
return err;
if (val >= AICBSP_CPMODE_MAX) {
pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX);
return -EINVAL;
}
aicbsp_info.cpmode = val;
printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc);
return count;
}
static ssize_t hwinfo_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
count += sprintf(&buf[count], "chip hw rev: ");
if (aicbsp_info.hwinfo_r < 0)
count += sprintf(&buf[count], "-1(not avalible)\n");
else
count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev);
count += sprintf(&buf[count], "hwinfo read: ");
if (aicbsp_info.hwinfo_r < 0)
count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r);
else
count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r);
if (aicbsp_info.hwinfo < 0)
count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo);
else
count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo);
return count;
}
static ssize_t hwinfo_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
long val;
int err = kstrtol(buf, 0, &val);
if (err) {
pr_err("invalid input\n");
return err;
}
if ((val == -1) || (val >= 0 && val <= 0xFF)) {
aicbsp_info.hwinfo = val;
} else {
pr_err("invalid values\n");
return -EINVAL;
}
return count;
}
static ssize_t fwdebug_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t count = 0;
count += sprintf(&buf[count], "fw log status: %s\n",
aicbsp_info.fwlog_en ? "on" : "off");
return count;
}
static ssize_t fwdebug_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
long val;
int err = kstrtol(buf, 0, &val);
if (err) {
pr_err("invalid input\n");
return err;
}
if (val > 1 || val < 0) {
pr_err("must be 0 or 1\n");
return -EINVAL;
}
aicbsp_info.fwlog_en = val;
return count;
}
static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR,
cpmode_show, cpmode_store);
static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR,
hwinfo_show, hwinfo_store);
static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR,
fwdebug_show, fwdebug_store);
static struct attribute *aicbsp_attributes[] = {
&dev_attr_cpmode.attr,
&dev_attr_hwinfo.attr,
&dev_attr_fwdebug.attr,
NULL,
};
static struct attribute_group aicbsp_attribute_group = {
.name = "aicbsp_info",
.attrs = aicbsp_attributes,
};
int testmode = AICBSP_CPMODE_DEFAULT;
int adap_test = 0;
module_param(testmode, int, 0660);
module_param(adap_test, int, 0660);
static int __init aicbsp_init(void)
{
int ret;
printk("%s\n", __func__);
printk("RELEASE_DATE:%s\r\n", RELEASE_DATE);
aicbsp_info.cpmode = testmode;
ret = platform_driver_register(&aicbsp_driver);
if (ret) {
pr_err("register platform driver failed: %d\n", ret);
return ret;
}
aicbsp_pdev = platform_device_alloc("aic-bsp", -1);
ret = platform_device_add(aicbsp_pdev);
if (ret) {
pr_err("register platform device failed: %d\n", ret);
return ret;
}
ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
if (ret) {
pr_err("register sysfs create group failed!\n");
return ret;
}
mutex_init(&aicbsp_power_lock);
#ifdef CONFIG_PLATFORM_ROCKCHIP
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
#endif
return 0;
}
void aicbsp_sdio_exit(void);
extern struct aic_sdio_dev *aicbsp_sdiodev;
static void __exit aicbsp_exit(void)
{
#ifdef CONFIG_PLATFORM_ROCKCHIP
if(aicbsp_sdiodev){
aicbsp_sdio_exit();
}
#endif
sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
platform_device_del(aicbsp_pdev);
platform_driver_unregister(&aicbsp_driver);
mutex_destroy(&aicbsp_power_lock);
#ifdef CONFIG_PREALLOC_TXQ
aicwf_prealloc_txq_free();
#endif
printk("%s\n", __func__);
}
module_init(aicbsp_init);
module_exit(aicbsp_exit);
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERS_MOD);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");