修改设备树
在根节点下添加led节点
ss_led@0{
compatible="ss,leddrv";
pin=<GROUP_PIN(5,3)>;
};
ss_led@1{
compatible="ss,leddrv";
pin=<GROUP_PIN(4,3)>;
};
在设备树文件下添加GROUP_PIN宏
#define GROUP_PIN(g,p) ((g<<16) | (p))
编译设备树
在源码目录下执行
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make dtbs
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
CHK include/generated/bounds.h
CHK include/generated/timeconst.h
CHK include/generated/asm-offsets.h
CALL scripts/checksyscalls.sh
DTC arch/arm/boot/dts/100ask_imx6ull-14x14.dtb
把得到的arch/arm/boot/dts/100ask_imx6ull-14x14.dtb文件传输到imx6ull板子上,这里采用nfs
cp ./arch/arm/boot/dts/100ask_imx6ull-14x14.dtb /home/book/nfs/
开发板上执行
cp ./nfs/100ask_imx6ull-14x14.dtb /boot/
重启板子就可以观察到设备树新加入的信息
[root@imx6ull:/sys/firmware/devicetree/base]# ls | grep ss
#address-cells
ss_led@0
ss_led@1
修改驱动文件
需要先学习platform_device与platform_driver是如何配对
修改platform_driver对象
static const struct of_device_id ss_led_match[] = {
{ .compatible = "ss,leddrv" },//与设备树的节点定义一样
{},
};
static struct platform_driver chip_demo_gpio_drv={
.probe=chip_demo_gpio_drv_probe,
.remove=chip_demo_gpio_drv_remove,
.driver={
.name="ss_led",
.of_match_table=ss_led_match,
}
};
修改probe函数
int chip_demo_gpio_drv_probe(struct platform_device *pdev){
struct device_node* np = pdev->dev. of_node;
int led_pin;
int err;
if(np==NULL) return -1;
//获取led引脚信息
err = of_property_read_u32(np, "pin", &led_pin);
pin[pin_num]=led_pin; //存储信息
led_device_create(pin_num); //创建设备
pin_num++;
return 0;
}
platform_device和platform_driver的每一次配对都会调用probe函数,我们在设备树中定义了两个设备节点,所以会有两次调用。probe函数需要做的是引脚信息的存储和创建设备。
修改remove函数
int chip_demo_gpio_drv_remove(struct platform_device *pdev){
struct device_node* np = pdev->dev. of_node;
int led_pin;
int err;
int i;
if(np==NULL) return -1;
err = of_property_read_u32(np,"pin", &led_pin);
//找到要注销的设备注销
for(i=0;i<pin_num;++i){
if(pin[i]==led_pin) {
led_device_destroy(i);
pin[i]=-1;
break;
}
}
//宏观上,本来是怎么样,就恢复成怎么样
for(i=0;i<pin_num;++i){
if(pin[i]!=-1) break;
}
if(i==pin_num) pin_num=0;
return 0;
}