Linux 驱动的注册过程:
https://www.cnblogs.com/haimeng2010/p/3582403.html
通过 Platform 机制开发发底层驱动的大致流程为: 定义platform_add_devices --> 注册platform_device --> 定义platform_add_driver --> 注册platform_driver 。
platform_device 和 platform_driver 通过.name 关联, 名字需要一样。
- dev.c -- arch\arm\mach-nuc970, 添加platform_device
#if defined(CONFIG_LEDS_TRIGGERS) || defined(CONFIG_LEDS_TRIGGERS_MODULE)
#if defined(CONFIG_LEDS_TRIGGER_HEARTBEAT)
static struct gpio_led gpio_leds[] = {
{
.name = "led0",
.default_trigger = "heartbeat",
.gpio = NUC970_PI2,
},
};
static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
.num_leds = ARRAY_SIZE(gpio_leds),
};
static struct platform_device leds_gpio = {
.name = "leds-nuc970",
.id = -1,
.dev = {
.platform_data = &gpio_led_info,
},
};
#endif
#endif
2. 添加platform_driver
leds-nuc970.c -- drivers\leds,
leds-nuc970.h -- include\linux\platform_data
static void nuc970_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct nuc970_gpio_led *led = to_gpio(led_cdev);
struct gpio_led *pd = led->pdata;
int state = (value ? 1 : 0);
/* there will be a short delay between setting the output and
* going from output to input when using tristate. */
pr_notice("nuc970_led_set: GPIO%d = %d\n", pd->gpio, state);
gpio_set_value(pd->gpio, state);
/*if (pd->flags & NUC970_LEDF_TRISTATE) {
if (value)
gpio_direction_output(pd->gpio, state);
else
gpio_direction_input(pd->gpio);
} */
}
static int nuc970_led_probe(struct platform_device *dev)
{
struct gpio_led_platform_data *pdata_a = dev->dev.platform_data;
struct gpio_led *pdata;
struct nuc970_gpio_led *led;
int ret;
pdata = &(pdata_a->leds[0]);
led = devm_kzalloc(&dev->dev, sizeof(struct nuc970_gpio_led),
GFP_KERNEL);
if (led == NULL) {
dev_err(&dev->dev, "No memory for device\n");
return -ENOMEM;
}
pr_notice("nuc970_led_probe\n");
platform_set_drvdata(dev, led);
led->cdev.brightness_set = nuc970_led_set;
led->cdev.default_trigger = pdata->default_trigger;
led->cdev.name = pdata->name;
led->cdev.flags |= LED_CORE_SUSPENDRESUME;
led->pdata = pdata;
ret = devm_gpio_request(&dev->dev, pdata->gpio, "NUC970_LED");
if (ret < 0)
return ret;
/* no point in having a pull-up if we are always driving */
//s3c_gpio_setpull(pdata->gpio, S3C_GPIO_PULL_NONE);
pr_notice("leds-nuc970: set(%s)(%d) output\n", pdata->name, pdata->gpio);
gpio_direction_output(pdata->gpio, 1);
/* register our new led device */
ret = led_classdev_register(&dev->dev, &led->cdev);
if (ret < 0)
dev_err(&dev->dev, "led_classdev_register failed\n");
return ret;
}
static struct platform_driver nuc970_led_driver = {
.probe = nuc970_led_probe,
.remove = nuc970_led_remove,
.driver = {
.name = "leds-nuc970",
.owner = THIS_MODULE,
},
};
3. platform_driver 的 Kconfig 和 Makefile 修改
Kconfig:
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
depends on LEDS_CLASS
depends on ARCH_S3C24XX
help
This option enables support for LEDs connected to GPIO lines
on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
++config LEDS_NUC970
++ tristate "LED Support for nuc970 LEDs (PI2)"
++ depends on LEDS_CLASS
++ depends on MACH_NUC970
++ default y
++ help
++ nuc970 trigger led .
Makefile:
obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
++obj-$(CONFIG_LEDS_NUC970) += leds-nuc970.o
4. Make menuconfig
Device drivers -> LED Support->
5. Trigger 间隔修改(没试),
ledtrig-heartbeat.c ->
static void led_heartbeat_function(unsigned long data)