进入内核 make menuconfig
输入 /led 回车搜索到
│ Location: │
│ -> Device Drivers │
│ -> LED Support (NEW_LEDS [=y])
进入LED Support发现有这一项 []LED Support for GPIO connected LEDs
在内核搜索该字符串 grep "LED Support for GPIO connected LEDs" * -nR
搜索到 drivers/leds/Kconfig:166: tristate "LED Support for GPIO connected LEDs"
打开 Kconfig查看,里面这样描述
config LEDS_GPIO
tristate "LED Support for GPIO connected LEDs"
depends on LEDS_CLASS
depends on GENERIC_GPIO
help
This option enables support for the LEDs connected to GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines. The LEDs must be
defined as platform devices and/or OpenFirmware platform devices.
The code to use these bindings can be selected below.
接着在内核搜索 grep "LEDS_GPIO" * -nR
搜索到 drivers/leds/Makefile:25:obj-$(CONFIG_LEDS_GPIO)
进入makefile 查看 发现内核会编译该文件
25 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
分析 leds-gpip.c
gpio_led_init(void)
platform_driver_register(&gpio_led_driver); //说明内核把led当作平台设备来处理,并注册进平台总线
分析gpio_led_driver
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.remove = __devexit_p(gpio_led_remove),
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
.of_match_table = of_gpio_leds_match,
},
};
//从结构体的类型struct platform_driver可知,这属于平台驱动
//该平台驱动名字“leds-gpio”,那么还有个平台设备 名字应该也为“leds-gpio”
在内核搜索“leds-gpio”
Leds.c (arch\arm\mach-at91): .name = "leds-gpio",
进入分析 leds.c
static struct platform_device at91_gpio_leds_device = {
.name = "leds-gpio",
.id = -1,
.dev.platform_data = &led_data,
};
//从结构体的类型struct platform_device可知,这属于平台设备
at91_gpio_leds(struct gpio_led *leds, int nr)
{
led_data.leds = leds;
led_data.num_leds = nr;
platform_device_register(&at91_gpio_leds_device);
}
//at91_gpio_leds,提供了一个注册led的函数入口,他里面调用platform_device_register(&at91_gpio_leds_device);
//但是at91_gpio_leds_device这个结构体只是提供了平台设备的名字,不对应实际的led设备,所以at91_gpio_leds需要我们传入一个
//led实际设备的数据结构,和led的个数
在内核搜索at91_gpio_leds
发现调用者非常多,我暂时就取arch\arm\mach-at91\Board-stamp9g20.c分析
/*
* LEDs
*/
static struct gpio_led portuxg20_leds[] = {
{
.name = "LED2",
.gpio = AT91_PIN_PC5,
.default_trigger = "none",
}, {
.name = "LED3",
.gpio = AT91_PIN_PC4,
.default_trigger = "none",
}, {
.name = "LED4",
.gpio = AT91_PIN_PC10,
.default_trigger = "heartbeat",
}
};
static void __init portuxg20_board_init(void)
{
/* LEDs */
at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
}
仿照该文件写一个led驱动
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <mach/hardware.h>
#include <mach/board.h>
#include <mach/gpio.h>
#include "generic.h"
/*配置led 引脚 lsh 2016.07.13*/
static struct gpio_led bdth_leds[] = {
{ /* led1 心跳闪烁*/
.name = "led1",
.gpio = AT91_PIN_PB14,
.active_low = 1,
.default_trigger = "heartbeat",
},
{ /* led2 */
.name = "led2",
.gpio = AT91_PIN_PB15,
.active_low = 1,
.default_trigger = "none",
},
{ /* led3 */
.name = "led3",
.gpio = AT91_PIN_PB12,
.active_low = 1,
.default_trigger = "none",
},
};
static int __init bdth_leds_init(void)
{
at91_gpio_leds(bdth_leds, ARRAY_SIZE(bdth_leds));
}
static int __exit bdth_leds_exit(void)
{
printk(KERN_ERR "cannot del led devices ! :bdth lsh 2016.07.13\n");
}
module_init(bdth_leds_init);
module_exit(bdth_leds_exit);
MODULE_LICENSE("GPL");
测试:
make menuconfig里面配置,如下
Device Driversà[*]LED Supportà[*]LED class support
[*]LED support for GPIO connected LEDS
[*]LED Trigger support
[*]LED heartbeat trigger
测试下led1,如下
led1,是配置的心跳功能,他会自己闪烁
测试下led2,如下
# echo 1 > /sys/class/leds/led2/brightness
led2会亮。
继续测试
# echo 0 > /sys/class/leds/led2/brightness
led2会灭掉。
led3同理
原文地址:https://www.cnblogs.com/liushuhe1990/p/9608991.html