1、在OpenWrt系统上移植SPI驱动前,首先要确保SPI相关引脚未被复用为其他功能,比如GPIO;以下操作已假定该条件成立,否则请修改相关dts和c文件中复用配置;
2、打开dts配置文件进行修改,这里我是用的硬件为WRTNODE2R,所以文件路径为:/target/linux/ramips/dts/WRTNODE2R.dts。在SPI控制器节点下添加与我们要添加的SPI设备及驱动匹配的信息,如下所示:
要注意该段代码要添加到SPI控制器节点下,为防止添加错误后面会给出这部分整段的SPI配置。
Note1 配置中“reg”属性有2个CELL,第一个用于指定片选;
Note2 配置中“compatible”参数需要与SPI设备驱动中字段相匹配,如下为我使用的第三方SPI设备驱动中相关配置:
#define CH43X_NAME_SPI "ch43x_spi"static const struct of_device_id __maybe_unused ch43x_dt_ids[] = {{ .compatible = "wch,ch43x", .data = &ch43x_devtype, },{},
};
MODULE_DEVICE_TABLE(of, ch43x_dt_ids);static struct spi_driver ch43x_spi_uart_driver = {.driver = {.name = CH43X_NAME_SPI,.bus = &spi_bus_type,.owner = THIS_MODULE,.of_match_table = of_match_ptr(ch43x_dt_ids),},.probe = ch43x_spi_probe,.remove = ch43x_spi_remove,
};
在一般情况下,匹配的信息应该是代码中“compatible ”的字符串,也即“wch,ch43x”,但这里匹配的具有特殊性,原因可能为系统修改过有关。匹配的是spi_drvier中,driver的name字符串,也即:"ch43x_spi";
Note3 如上的dts配置中有2行信息,是与中断相关的。本意是想实现通过dts配置interrupts节点后,在spi设备驱动中通过struct spi_device *spi结构体中的spi->irq获取相应IO口的中断号实现中断功能,奈何在本硬件平台上用不了,之所以保留是因为很多其他平台可以通过这种方式来配置和获取中断。本平台使用中断方法会在其他博客中涉及。
完整SPI部分的dts配置:
spi0: spi@b00 {status = "okay";m25p80@0 {#address-cells = <1>;#size-cells = <1>;compatible = "w25q256";reg = <0 0>;linux,modalias = "m25p80", "w25q256";spi-max-frequency = <10000000>;m25p,chunked-io = <32>;partition@0 {label = "u-boot";reg = <0x0 0x30000>;read-only;};partition@30000 {label = "u-boot-env";reg = <0x30000 0x10000>;read-only;};factory: partition@40000 {label = "factory";reg = <0x40000 0x10000>;read-only;};partition@50000 {label = "firmware";reg = <0x50000 0x1fb0000>;};};spidev@1 {#address-cells = <1>;#size-cells = <1>;// compatible = "wch,ch43x";compatible = "ch43x_spi";reg = <1 0>;spi-max-frequency = <5000000>;interrupt-parent = <&gpio0>;interrupts = <0 2>;};};
3、OpenWrt系统中添加驱动模块
首先在目录package/kernel下创建自己的模块目录ch432,目录结构如下 :
rambo@ubuntu:~/OpenWrt/wrtnode/package/kernel$ tree ch432
ch432
├── Makefile
└── src├── ch432.c├── Kconfig└── Makefile1 directory, 4 files
至于里面的Makefile文件和Kconfig文件如何写,不建议照抄我的或网上找的,直接在package/kernel拷贝其他模块的,基于那个调整最快捷有效!而且拷贝那种最简单的就可以。这里拷贝button-hotplug这个驱动模块,然后照葫芦画瓢,修改成编译我们驱动的样式。(傻瓜式做法:直接把里面涉及到驱动文件名的统一换成你要编译的驱动文件名就可以)比如这里第一级的Makefile,如下:
#
# Copyright (C) 2008-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mkPKG_NAME:=ch432
PKG_RELEASE:=3include $(INCLUDE_DIR)/package.mkdefine KernelPackage/ch432SUBMENU:=Other modulesTITLE:=ch432 spi driverDEPENDS:=+kmod-input-coreFILES:=$(PKG_BUILD_DIR)/ch432.koAUTOLOAD:=$(call AutoLoad,30,ch432,1)KCONFIG:=
endefdefine KernelPackage/ch432/descriptionKernel module to generate button uevent-s from input subsystem events.If your device uses GPIO buttons, see gpio-button-hotplug.
endefEXTRA_KCONFIG:= \CONFIG_CH432=mEXTRA_CFLAGS:= \$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \MAKE_OPTS:= \ARCH="$(LINUX_KARCH)" \CROSS_COMPILE="$(TARGET_CROSS)" \SUBDIRS="$(PKG_BUILD_DIR)" \EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \$(EXTRA_KCONFIG)define Build/Preparemkdir -p $(PKG_BUILD_DIR)$(CP) ./src/* $(PKG_BUILD_DIR)/
endefdefine Build/Compile$(MAKE) -C "$(LINUX_DIR)" \$(MAKE_OPTS) \modules
endef$(eval $(call KernelPackage,ch432))
第二级src目录下的Kconfig文件如下:
config CH432tristate "This is CH432"
Makefile如下:
obj-$(CONFIG_CH432) += ch432.o
实际上我就把这3个文件中原有的字符串“button-hotplug”换成了“ch432”而已。
Note1 你要编译的驱动源文件和头文件一定也要放在这个src目录下。
4、下面配置内核,把我们添加到package中的模块选中就可以了。执行,“make menuconfig”:
然后在“Kernel Modules” -> "Other Modules"下找到我们添加的模块,选中它就可以了。
配置结束,下面只编译模块就可以了。不需要编译整个内核。编译命令为:
make package/kernel/ch432/compile V=s
Note1 因为spi驱动可以动态加载调试,所以建议编译成模块,不要静态编译,不然调试和看驱动log都不方便。
5、编译生成的驱动模块路径为:
ko原生驱动模块路径:
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7628/ch432/
ipk文件路径为:
bin/ramips/packages/base/
将如上ko文件或者ipk拷贝到硬件上面就可以正常使用了。记得SPI驱动调试第一步,insmod之后确认spi_probe有没有正常执行!!!