欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 5.4 platform总线编写LED驱动

5.4 platform总线编写LED驱动

2025/6/23 2:24:47 来源:https://blog.csdn.net/weixin_45523296/article/details/148814585  浏览:    关键词:5.4 platform总线编写LED驱动

1. platform总线

CPU和外部通信的2种方式:地址总线式连接和专用接口式连接。平台总线对应地址总线式连接设备。相比于usb、pci、i2c等物理总线来说,platform总线是虚拟的、抽象出来的。platform总线工作体系在kernel/drivers/base/platform.c中。

1.1 platform_device结构体

platform_device结构体定义在kernel/include/linux/platform_device.h中

struct platform_device {const char	* name;int		id;struct device	dev;u32		num_resources;struct resource	* resource;const struct platform_device_id	*id_entry;/* arch specific additions */struct pdev_archdata	archdata;
};

1.2 platform_driver结构体

platform_driver结构体也定义在/kernel/include/linux/platform_device.h中

struct platform_driver {int (*probe)(struct platform_device *);int (*remove)(struct platform_device *);void (*shutdown)(struct platform_device *);int (*suspend)(struct platform_device *, pm_message_t state);int (*resume)(struct platform_device *);struct device_driver driver;const struct platform_device_id *id_table;
};

1.3 platform总线工作原理

linux系统启动时会在bus系统中注册platform,platform的match函数遍历匹配驱动中的platform_device和platform_driver,将匹配到的驱动调用platform_driver中的probe函数完成驱动的初始化和安装。

static int of_platform_device_probe(struct device *dev)
{int error = -ENODEV;struct of_platform_driver *drv;struct of_device *of_dev;const struct of_device_id *match;drv = to_of_platform_driver(dev->driver);of_dev = to_of_device(dev);if (!drv->probe)return error;of_dev_get(of_dev);match = of_match_device(drv->driver.of_match_table, dev);if (match)error = drv->probe(of_dev, match);if (error)of_dev_put(of_dev);return error;
}

2. 使用platform总线编写LED驱动

2.1 在内核源码中添加led对应的platform_device和platform_driver实例

(1)定义s5pv210_led_platfata结构体,新建kernel/arch/arm/mach-s5pv210/include/mach/leds-gpio.h文件,内容如下:

/* arch/arm/mach-s5pv210/include/mach/leds-gpio.h** Copyright (c) 2006 Simtec Electronics*	http://armlinux.simtec.co.uk/*	Ben Dooks <ben@simtec.co.uk>** S5PV210 - LEDs GPIO connector** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.
*/#ifndef __ASM_ARCH_LEDSGPIO_H
#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"#define S5PV210_LEDF_ACTLOW	(1<<0)		/* LED is on when GPIO low */
#define S5PV210_LEDF_TRISTATE	(1<<1)		/* tristate to turn off */struct s5pv210_led_platdata {unsigned int		 gpio;unsigned int		 flags;char			*name;char			*def_trigger;
};#endif /* __ASM_ARCH_LEDSGPIO_H */

(2)s5pv210开发板在kernel/arch/arm/mach-s5pv210/mach-x210.c中:

// x210添加led的platform_device
static struct s5pv210_led_platdata s5pv210_led1_pdata = 
{.name 			= "led1",.gpio			= S5PV210_GPJ0(3),.flags			= S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger	= "",
};static struct s5pv210_led_platdata s5pv210_led2_pdata = 
{.name 			= "led2",.gpio			= S5PV210_GPJ0(4),.flags			= S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger	= "",
};static struct s5pv210_led_platdata s5pv210_led3_pdata = 
{.name 			= "led3",.gpio			= S5PV210_GPJ0(5),.flags			= S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger	= "",
};static struct s5pv210_led_platdata s5pv210_led4_pdata = 
{.name 			= "led4",.gpio			= S5PV210_GPD0(1),.flags			= S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger	= "",
};static struct platform_device s5pv210_led1_device =
{.name 	= "s5pv210_led",.id		= 1,.dev	= {.platform_data = &s5pv210_led1_pdata,},
};static struct platform_device s5pv210_led2_device =
{.name 	= "s5pv210_led",.id		= 2,.dev	= {.platform_data = &s5pv210_led2_pdata,},
};static struct platform_device s5pv210_led3_device =
{.name 	= "s5pv210_led",.id		= 3,.dev	= {.platform_data = &s5pv210_led3_pdata,},
};static struct platform_device s5pv210_led4_device =
{.name 	= "s5pv210_led",.id		= 4,.dev	= {.platform_data = &s5pv210_led4_pdata,},
};

(3)在platform_device数组中添加上自己编写的device

static struct platform_device *smdkc110_devices[] __initdata = {
#ifdef CONFIG_FIQ_DEBUGGER&s5pv210_device_fiqdbg_uart2,
#endif
#ifdef CONFIG_MTD_ONENAND&s5pc110_device_onenand,
#endif
#ifdef CONFIG_MTD_NAND&s3c_device_nand,
#endif&s5p_device_rtc,
#ifdef CONFIG_SND_S3C64XX_SOC_I2S_V4&s5pv210_device_iis0,&s5pv210_device_iis1,
#endif
#ifdef CONFIG_SND_S3C_SOC_AC97&s5pv210_device_ac97,
#endif
#ifdef CONFIG_SND_S3C_SOC_PCM&s5pv210_device_pcm0,
#endif
#ifdef CONFIG_SND_SOC_SPDIF&s5pv210_device_spdif,
#endif&s3c_device_wdt,#ifdef CONFIG_FB_S3C&s3c_device_fb,
#endif
#ifdef CONFIG_DM9000&s5p_device_dm9000,
#endif#ifdef CONFIG_VIDEO_MFC50&s3c_device_mfc,
#endif
#ifdef CONFIG_TOUCHSCREEN_S3C&s3c_device_ts,
#endif&s3c_device_keypad,
#ifdef CONFIG_S5P_ADC&s3c_device_adc,
#endif
#ifdef CONFIG_VIDEO_FIMC&s3c_device_fimc0,&s3c_device_fimc1,&s3c_device_fimc2,
#endif
#ifdef CONFIG_VIDEO_FIMC_MIPI&s3c_device_csis,
#endif
#ifdef CONFIG_VIDEO_JPEG_V2&s3c_device_jpeg,
#endif
#ifdef CONFIG_VIDEO_G2D&s3c_device_g2d,
#endif
#ifdef CONFIG_VIDEO_TV20&s5p_device_tvout,&s5p_device_cec,&s5p_device_hpd,
#endif&s3c_device_g3d,&s3c_device_lcd,&s3c_device_i2c0,
#ifdef CONFIG_S3C_DEV_I2C1&s3c_device_i2c1,
#endif
#ifdef CONFIG_S3C_DEV_I2C2&s3c_device_i2c2,
#endif#ifdef CONFIG_USB_EHCI_HCD&s3c_device_usb_ehci,
#endif
#ifdef CONFIG_USB_OHCI_HCD&s3c_device_usb_ohci,
#endif#ifdef CONFIG_USB_GADGET&s3c_device_usbgadget,
#endif
#ifdef CONFIG_USB_ANDROID&s3c_device_android_usb,
#ifdef CONFIG_USB_ANDROID_MASS_STORAGE&s3c_device_usb_mass_storage,
#endif
#ifdef CONFIG_USB_ANDROID_RNDIS&s3c_device_rndis,
#endif
#endif
#ifdef CONFIG_BATTERY_S3C&sec_device_battery,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC&s3c_device_hsmmc0,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC1&s3c_device_hsmmc1,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC2&s3c_device_hsmmc2,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC3&s3c_device_hsmmc3,
#endif#ifdef CONFIG_S3C64XX_DEV_SPI&s5pv210_device_spi0,&s5pv210_device_spi1,
#endif
#ifdef CONFIG_S5PV210_POWER_DOMAIN&s5pv210_pd_audio,&s5pv210_pd_cam,&s5pv210_pd_tv,&s5pv210_pd_lcd,&s5pv210_pd_g3d,&s5pv210_pd_mfc,
#endif#ifdef CONFIG_HAVE_PWM&s3c_device_timer[0],&s3c_device_timer[1],&s3c_device_timer[2],&s3c_device_timer[3],
#endif//	&timed_gpio_device,&headset_switch_device,&s5pv210_led1_device,&s5pv210_led2_device,&s5pv210_led3_device,&s5pv210_led4_device,
};

 2.2 编写led驱动

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <mach/gpio.h>
#include <linux/platform_device.h>
#include <mach/leds-gpio.h>
#include <linux/slab.h>struct s5pv210_gpio_led
{struct led_classdev cdev;struct s5pv210_led_platdata* pdata;
};static inline struct s5pv210_gpio_led* pdev_to_gpio(struct platform_device* dev)
{return platform_get_drvdata(dev);
}static inline struct s5pv210_gpio_led* to_gpio(struct led_classdev* led_cdev)
{return container_of(led_cdev, struct s5pv210_gpio_led, cdev);
}static void s5pv210_led_set(struct led_classdev* led_cdev, enum led_brightness value)
{struct s5pv210_gpio_led* s5pv210_led = to_gpio(led_cdev);if (value == LED_OFF){gpio_set_value(s5pv210_led->pdata->gpio, 1);}else{gpio_set_value(s5pv210_led->pdata->gpio, 0);}
}static int s5pv210_led_probe(struct platform_device* dev)
{int ret = 0;struct s5pv210_led_platdata* pdata = dev->dev.platform_data;struct s5pv210_gpio_led* s5pv210_led;s5pv210_led = kzalloc(sizeof(struct s5pv210_gpio_led), GFP_KERNEL);if (s5pv210_led == NULL) {dev_err(&dev->dev, "No memory for device\n");return -ENOMEM;}platform_set_drvdata(dev, s5pv210_led);if (gpio_request(pdata->gpio, pdata->name)){printk(KERN_ERR "gpio_request failed, pdata->gpio = %d, pdata->name = %s\n", pdata->gpio, pdata->name);}else{gpio_direction_output(pdata->gpio, 1);}s5pv210_led->cdev.name = pdata->name;s5pv210_led->cdev.brightness = 0;s5pv210_led->cdev.brightness_set = s5pv210_led_set;s5pv210_led->pdata = pdata;ret = led_classdev_register(&dev->dev, &s5pv210_led->cdev);if (ret < 0) {dev_err(&dev->dev, "led_classdev_register failed\n");kfree(s5pv210_led);return ret;}return 0;
}static int s5pv210_led_remove(struct platform_device* dev)
{struct s5pv210_gpio_led* s5pv210_led = pdev_to_gpio(dev);led_classdev_unregister(&s5pv210_led->cdev);gpio_free(p->pdata->gpio);kfree(s5pv210_led);return 0;
}static struct platform_driver s5pv210_led_driver =
{.probe = s5pv210_led_probe,.remove = s5pv210_led_remove,.driver ={.name = "s5pv210_led",.owner = THIS_MODULE,}
};static int __init led_driver_framework_init(void)
{return platform_driver_register(&s5pv210_led_driver);
}static void __exit led_driver_framework_exit(void)
{platform_driver_unregister(&s5pv210_led_driver);
}module_init(led_driver_framework_init);
module_exit(led_driver_framework_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("xy_L");
MODULE_DESCRIPTION("led_driver_framework");
MODULE_ALIAS("led_driver_framework_test");

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词