rk3326下调试ap6265记录-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 263902
  • 博文数量: 90
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 665
  • 用 户 组: 普通用户
  • 注册时间: 2018-10-15 14:13
个人简介

搭建一个和linux开发者知识共享和学习的平台

文章分类

全部博文(90)

文章存档

2024年(4)

2023年(24)

2022年(27)

2019年(8)

2018年(27)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: linux

2022-12-16 11:31:35

 sdio wi-fi 配置




wi-fi/bt硬件管脚的配置主要有以下几点:
切记一定要对照原理图进行配置,且确保使用的dts/dtsi里面包含以下节点!
sdio 接口wi-fi:wl_reg_on由sdio_pwrseq节点进行管理控制,不需要在wireless-wlan节点下面重复
添加wifi,poweren_gpio配置;




/* sdio接口wi-fi专用配置: wifi_reg_on: wi-fi的电源使能pin脚 */
sdio_pwrseq: sdio-pwrseq 
{
compatible = "mmc-pwrseq-simple";
pinctrl-names = "default";
pinctrl-0 = <&wifi_enable_h>;
/* 特别注意:wifi_reg_on gpio_active 配置跟使能状态恰好是相反的,
* 高有效为low,低有效则为high
* 切记:这个配置跟下面的wifi,poweren_gpio是互斥的,不能同时配置!!!
*/
reset-gpios = <&gpio0 rk_pa2 gpio_active_low>;
};




/* sdio接口wi-fi专用配置:wifi_reg_on脚的pinctrl的配置 */
&pinctrl {
sdio-pwrseq {
wifi_enable_h: wifi-enable-h {
rockchip,pins =
/* 对应上面的wifi_reg_on,关掉上下拉,防止不能拉高或拉低 */
<0 rk_pa2 rk_func_gpio &pcfg_pull_none>;
};
};
};




/* sdio接口wi-fi专用配置:sdio接口节点 */
&sdio {
max-frequency = <150000000>; /* sdio接口的{banned}最佳大频率,可调整 */
bus-width = <4>; /* 4线模式,可调整1线模式 */
sd-uhs-sdr104; /* 支持sdio3.0 */
… …
status = "okay";
};




/* wi-fi节点 */
wireless-wlan {
compatible = "wlan-platdata";
rockchip,grf = <&grf>;




/* 注意:如果排查发现wi-fi模块没有32.768k波形,且硬件上是有
* rk pmu供给的,则打开下面的clock属性,按照实际使用的pmu型号填写,
* 否在sdio/wi-fi无法使用.
*/
clocks = <&rk809 1>; //如果使用rk809,只能配置一个
clocks = <&hym8563>; //如果使用hym8563,只能配置一个
clock-names = "ext_clock";
/* 按实际名字填写 */
wifi_chip_type = "ap6255";
/* wifi_wake_host: wi-fi中断通知主控的pin脚。
* 特别注意:确认下这个wi-fi pin脚跟主控的pin的
* 硬件连接关系,直连的话就是gpio_active_high;
* 如果中间加了一个反向管就要改成低电平gpio_active_low触发
*/
wifi,host_wake_irq = <&gpio0 rk_pa0 gpio_active_high>;
//sdio wi-fi 无需此配置,除非有动态加载协助驱动ko的需求,参考11.8章节
//wifi,poweren_gpio = <&gpio0 rk_pa2 gpio_active_high>;
status = "okay";
};




/* wifi_wake_host脚的pinctrl的配置 */
wireless-wlan {
/omit-if-no-ref/
wifi_wake_host: wifi-wake-host {
/* 注意一般wi-fi的wake host pin都是高电平触发,
* 所以默认这里要配置为下拉; 如果客户的硬件设计
* 是反向的则要改为上拉,总之要初始化为与触发电平
* 相反的状态
*/
rockchip,pins = <0 rk_pa0 0 &pcfg_pull_down>;
};
}






rk3326的sdio控制器驱动

drivers/mmc/host/dw_mmc-rockchip.c


ap6265驱动


drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd






drivers\mmc\host\dw_mmc-rockchip.c
dw_mci_rockchip_probe(struct platform_device *pdev)
--> dw_mci_pltfm_register(pdev, drv_data); //解析设备树信息,用来构造一个dw_mci *host;
--> dw_mci_probe(dw_mci *host); //将上面构造好的dw_mci *host结构体传参进来;
--> setup_timer(&host->cmd11_timer,dw_mci_cmd11_timer, (unsigned long)host); //设置一些定时器,定时发送一些命令
--> host->dma_ops = host->pdata->dma_ops;
--> ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
//这个dw_mci_interrupt中断函数会被注册两次,一次是emmc(irq=25),一次是sd卡(irq=26),所以源码虽然只注册了一次,但是实际上注册了两次,用的都是同一个中断处理函数
//这个是mci寄存器的中断,我们的这款soc可以根据这个寄存器来判断发送,接收,sd卡热拔插的行为,都会触发这个中断,在这个中断处理函数里面再细分是什么操作触发的中断,进行处理,比如热拔插:
--> dw_mci_init_slot(dw_mci *host, i); // 定义了mmc_host *mmc;,用我们封装了一层的dw_mci *host去填充注册他
--> mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
--> init_delayed_work(&host->detect, mmc_rescan); //初始化工作队列,里面有扫描sd卡的函数
--> mmc->ops = &dw_mci_ops; //mmc_host_ops类型的变量,用于定义本mmc_host的操作接口(包括与mmc card通信的接口request、卡检测相关的接口等)
--> mmc_add_host(mmc);
--> mmc_start_host(mmc_host *host);
--> mmc_schedule_delayed_work(&host->detect, delay); //上电添加mmc_host的时候,先主动执行一次mmc_rescan函数
--> dw_mci_enable_cd(host); //cd = card detect ≠ sdmmc_cd 引脚中断,主要看函数内容,像这款soc就是在里面开启mci寄存器的sd卡热拔插中断
--> temp = mci_readl(host, intmask); temp  |= sdmmc_int_cd; mci_writel(host, intmask, temp); //开启mci寄存器的sd卡热拔插中断






dw_mci_interrupt()
if (pending & sdmmc_int_cd)
dw_mci_handle_cd(dw_mci *host);
--> mmc_detect_change(slot->mmc,msecs_to_jiffies(host->pdata->detect_delay_ms));
--> _mmc_detect_change(host, delay, true);
--> mmc_schedule_delayed_work(&host->detect, delay); //开启工作队列
--> mmc_rescan() //{banned}最佳终会调用此函数
 
重点看看mmc_rescan检测sd卡热拔插的函数,我们在设备树中的sd卡定义了 supports-sd 所以:
drivers\mmc\core\host.c 
mmc_of_parse
if (of_property_read_bool(np, "supports-sd"))
host->restrict_caps |= restrict_card_type_sd; 
 
mmc_rescan()
if (host->bus_ops && !host->bus_dead && !(host->caps & mmc_cap_nonremovable)) //上电{banned}中国第一次调用这个函数时候,还没有设置host->bus_ops,所以会执行后面的语句来设置host->bus_ops
host->bus_ops->detect(host);
--> mmc_rescan_try_freq(host, max(freqs[i], host->f_min)) //以各种频率给host发,选择{banned}最佳合适的频率
if ((host->restrict_caps & restrict_card_type_sd) && !mmc_attach_sd(host)) return 0; 所以就会调用mmc_attach_sd
--> mmc_attach_sd(host)
--> mmc_attach_bus(host, &mmc_sd_ops);
--> host->bus_ops = ops; //这里的ops就是上面的mmc_ops参数
--> mmc_sd_init_card(host, rocr, null);
--> card = mmc_alloc_card(host, &sd_type);
--> mmc_add_card(host->card);
--> device_add(&card->dev);
--> bus_add_device(dev); //add the device to its bus's list of devices, 会给mmc_bus注册一个devices,会和系统自动注册的mmc_driver匹配,调用它的probe函数
                        ......
                        --> mmc_driver->probe
                        --> mmc_blk_probe() //如上分析的,会读取sd卡的寄存器获取分区信息,根据分区信息注册block等。






mmc card: 
①host完成mmc_card与mmc_host的绑定;
②dev完成将该mmc_card与系统中的设备、总线、驱动的关联(即完成与系统设备驱动总线的关联与绑定操作);
③卡类型与卡状态记录
④卡相关的寄存器信息记录(主要从mmc card中读取),包括cid、csd、scr、ssr等内容
⑤mmc card的分区信息,主要完成块设备的创建(由mmc driver实现)若为sdio设备,则有cccr、cis等(关于sdio的部分,请参考sdio协议相关的文档)






mmc_ios:
该结构体主要定义mmc总线相关的参数,主要包括时钟频率、电源、总线模式、电源状态、总线带宽、支持的信号电压值等等这些参数的设置可通过mmc_host_ops->set_ios实现。


mmc_host_ops:
该数据结构定义了mmc_host的操作方法


mmc_bus_ops:
该接口主要是针对mmc card的sleep/awake的操作,因mmc card也需要进行sleep/awake等接口,这些接口类似于设备驱动的电源管理(suspend/resume)相关的接口。该结构体中的成员,不需要我们进行实现,mmc子系统已经完成,mmc子系统根据mmc各协议版本针对sleep/awake的支持情况,实现对应的操作。










wifi调试


查看rk3326的sdio属性
cat /sys/kernel/debug/mmc2/ios




阅读(956) | 评论(0) | 转发(0) |
0

上一篇:

下一篇:

给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图