踩坑记录 君正T23移植RTL8189FTV

踩坑记录,君正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也出现了,成功解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangzn2016

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值