踩坑记录,君正T23移植RTL8189FTV
在platform.c文件配置好引脚之后,调用platform_wifi_power_on()函数,结果报了内存错误的日志,调用的函数是jzmmc_manual_detect()。
首先查看原理图,因为板子是公司自己设计的,SDIO_WiFi口是接在了MMC0上,而君正T23默认是接在了MMC1上,因此修改了jzmmc_manual_detect()函数的第一个参数。
重新编译,再次传入到开发板中,依旧报错,报错提示jzmmc_manual_detect()调用时发生内存错误,之后在jzmmc_manual_detect()里加入打印信息,方便我定位是哪一步出错了。
初步定位到是这一步出错了:
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
list_for_each(pos, &manual_list) {
host = list_entry(pos, struct jzmmc_host, list);
if (host->index == index)
break;
else
host = NULL;
}
看到这行代码,大致知道是什么问题了,驱动代码去访问MMC0设备,然后MMC0上没有设备,因此链表上没有元素。
上面说了SDIO_WiFi口是接在了MMC0上,而君正T23默认是接在了MMC1上,因此极大可能是还有地方没修改完。找到链表添加信息的部分:
static int __init jzmmc_gpio_init(struct jzmmc_host *host)
{
struct card_gpio *card_gpio = host->pdata->gpio;
int ret = 0;
if (card_gpio) {
if (gpio_request_one(card_gpio->cd.num,
GPIOF_DIR_IN, "mmc_detect")) {
dev_vdbg(host->dev, "no detect pin available\n");
card_gpio->cd.num = -EBUSY;
}
if (gpio_request_one(card_gpio->wp.num,
GPIOF_DIR_IN, "mmc_wp")) {
dev_vdbg(host->dev, "no WP pin available\n");
card_gpio->wp.num = -EBUSY;
}
if (gpio_request(card_gpio->pwr.num, "mmc_power")) {
dev_vdbg(host->dev, "no PWR pin available\n");
card_gpio->pwr.num = -EBUSY;
} else {
gpio_direction_output(card_gpio->pwr.num,
card_gpio->pwr.enable_level
? 0 : 1);
}
}
switch (host->pdata->removal) {
case NONREMOVABLE:
break;
case REMOVABLE:
if (gpio_is_valid(card_gpio->cd.num)) {
setup_timer(&host->detect_timer, jzmmc_detect_change,
(unsigned long)host);
ret = request_irq(gpio_to_irq(host->pdata->gpio->cd.num),
jzmmc_detect_interrupt,
IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
| IRQF_DISABLED ,
"mmc-insert-detect", host);
if (ret) {
dev_err(host->dev, "request detect irq-%d fail\n",
gpio_to_irq(host->pdata->gpio->cd.num));
break;
}
tasklet_disable(&host->tasklet);
clk_enable(host->clk);
clk_enable(host->clk_gate);
if(!timer_pending(&host->detect_timer)){
disable_irq_nosync(gpio_to_irq(host->pdata->gpio->cd.num));
mod_timer(&host->detect_timer, jiffies);
}
} else {
dev_err(host->dev, "card-detect pin must be valid "
"when host->pdata->removal = 1, errno=%d\n",
host->pdata->gpio->cd.num);
}
break;
case MANUAL:
list_add(&(host->list), &manual_list);
break;
default:
clk_enable(host->clk);
clk_enable(host->clk_gate);
set_bit(JZMMC_CARD_PRESENT, &host->flags);
break;
}
return ret;
}
发现链表添加信息是在这一块:
switch (host->pdata->removal) {
case NONREMOVABLE:
break;
case REMOVABLE:
// .......
break;
case MANUAL:
list_add(&(host->list), &manual_list);
break;
default:
clk_enable(host->clk);
clk_enable(host->clk_gate);
set_bit(JZMMC_CARD_PRESENT, &host->flags);
break;
}
很可能是因为host->pdata->removal的值并不是manual导致的,因此可以通过打日志的方式确认一下。
case MANUAL:
list_add(&(host->list), &manual_list);
printk("=============list_add===============\n");
break;
编译烧录,开发板启动后打印内核日志,发现确实host->pdata->removal的值确实不是manual。
接下来简单粗暴,直接搜索关键字"MANUAL",之后定位到/home/wangzhinan/ISVP_tmp/software/sdk/Ingenic-SDK-T23-1.1.0-20230726/opensource/kernel/arch/mips/xburst/soc-t23/chip-t23/isvp/common/mmc.c文件
#ifdef CONFIG_JZMMC_V12_MMC0
static struct card_gpio tf_gpio = {
.wp = {GPIO_MMC_WP_N, GPIO_MMC_WP_N_LEVEL},
.cd = {GPIO_MMC_CD_N, GPIO_MMC_CD_N_LEVEL},
.pwr = {GPIO_MMC_PWR, GPIO_MMC_PWR_LEVEL},
.rst = {GPIO_MMC_RST_N, GPIO_MMC_RST_N_LEVEL},
};
/* common pdata for both tf_card and sdio wifi on fpga board */
struct jzmmc_platform_data tf_pdata = {
#if 1
.removal = REMOVABLE,
.sdio_clk = 1,
.ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
.capacity = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_4_BIT_DATA,
.pm_flags = 0,
.recovery_info = NULL,
.gpio = &tf_gpio,
.max_freq = CONFIG_MMC0_MAX_FREQ,
#ifdef CONFIG_MMC0_PIO_MODE
.pio_mode = 1,
#else
.pio_mode = 0,
#endif
#else
.removal = MANUAL,
.sdio_clk = 1,
.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31,
.capacity = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ,
.max_freq = CONFIG_MMC1_MAX_FREQ,
.recovery_info = NULL,
.gpio = NULL,
#ifdef CONFIG_MMC1_PIO_MODE
.pio_mode = 1,
#else
.pio_mode = 0,
#endif
#ifdef CONFIG_BCM_PM_CORE
.private_init = bcm_wlan_init,
#else
.private_init = NULL,
#endif
#endif
};
#endif
#ifdef CONFIG_JZMMC_V12_MMC1
#ifdef CONFIG_BCM_PM_CORE
extern int bcm_wlan_init(void);
#endif
struct jzmmc_platform_data sdio_pdata = {
#if 0
.removal = REMOVABLE,
.sdio_clk = 1,
.ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
.capacity = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_4_BIT_DATA,
.pm_flags = 0,
.recovery_info = NULL,
.gpio = &tf_gpio,
.max_freq = CONFIG_MMC0_MAX_FREQ,
#ifdef CONFIG_MMC0_PIO_MODE
.pio_mode = 1,
#else
.pio_mode = 0,
#endif
#else
.removal = MANUAL,
.sdio_clk = 1,
.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31,
.capacity = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ,
.max_freq = CONFIG_MMC1_MAX_FREQ,
.recovery_info = NULL,
.gpio = NULL,
#ifdef CONFIG_MMC1_PIO_MODE
.pio_mode = 1,
#else
.pio_mode = 0,
#endif
#ifdef CONFIG_BCM_PM_CORE
.private_init = bcm_wlan_init,
#else
.private_init = NULL,
#endif
#endif
};
#endif
解读代码,MMC0.removal的值为REMOVABLE,而MMC1.removal的值为MANUAL,上面说了SDIO_WiFi口是接在了MMC0上,而君正T23默认是接在了MMC1上,这下说得通了,
参照MMC1的jzmmc_platform_data sdio_pdata的定义修改MMC0的jzmmc_platform_data sdio_pdata,烧录编译
发现list_add()有调用,insmod驱动后依旧报错,但不是内存报错,提示状态不对,没有wlan0。
上万用表,量电压,发现电压不对,跟硬件的人一起解决。
insmod驱动,电压正常,wlan0也出现了,成功解决。