一个简单的platfrom框架的LED驱动
参考了这位网友的博文。
我的是基于100ask的板子--imx6ull mini。整个程序写的非常简略,出错处理部分都省略了。头文件省略了下面是 led_platform_dev.c,用来描述设备情况的。这几个寄存器是用来配置gpio的。
static struct resource led_resource[] = {
[0] = {
.start = 0x02290000 + 0x14,
.end = 0x02290000 + 0x14+0x4,
.flags = IORESOURCE_MEM
},
[1] = {
.start = 0x020AC004,
.end = 0x020AC004 + 0x4,
.flags = IORESOURCE_MEM
},
[2] = {
.start = 0x020AC000,
.end = 0x020AC000 + 0x3,
.flags = IORESOURCE_MEM
},
}; // 设备信息
static void my_led_platform_device_release(struct device * dev)
{
return ;
}
static struct platform_device my_platform_devcie = {
.name = "my_led_platform_device",
.id = -1,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev = {
.release = my_led_platform_device_release,
},
};
static int __init led_pdev_init(void)
{
platform_device_register(&my_platform_devcie);//注册一个platform设备
printk("led_dev initted!\n");
return 0;
}
static void __exit led_pdev_exit(void)
{
platform_device_unregister(&my_platform_devcie);//释放一个platform设备
printk("led_dev exited!\n");
}
module_init(led_pdev_init);
module_exit(led_pdev_exit);
MODULE_LICENSE("GPL");
下面是platform_driver部分。头文件是省略的。下面是 led_platform_drv.c 。其中 在probe函数中获取关于platform_device的信息led_resource--我这里是配置GPIO的寄存器地址。获取后进行ioremap然后进行配置寄存器,控制GPIO输出来点亮LED.这个程序只是简单展示platform驱动怎么用。上层测试的应用程序就省略了。
static int major;
static struct class *led_class;
/* registers */
// IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 地址:0x02290000 + 0x14
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
// GPIO5_GDIR 地址:0x020AC004
static volatile unsigned int *GPIO5_GDIR;
//GPIO5_DR 地址:0x020AC000
static volatile unsigned int *GPIO5_DR;
static ssize_t led_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
char val;
int ret;
/* copy_from_user : get data from app */
ret = copy_from_user(&val, buf, 1);
/* to set gpio register: out 1/0 */
if (val)
{
/* set gpio to let led on */
*GPIO5_DR &= ~(1<<3);
}
else
{
/* set gpio to let led off */
*GPIO5_DR |= (1<<3);
}
return 1;
}
static int led_open(struct inode *inode, struct file *filp)
{
/* enable gpio5
* configure gpio5_io3 as gpio
* configure gpio5_io3 as output
*/
*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 &= ~0xf;
*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 |= 0x5;
*GPIO5_GDIR |= (1<<3);
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.write = led_write,
.open = led_open,
};
static int my_platform_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *pIORESOURCE_MEM;
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
pIORESOURCE_MEM = platform_get_resource(pdev, IORESOURCE_MEM, 0);
IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(pIORESOURCE_MEM->start, 4);
pIORESOURCE_MEM = platform_get_resource(pdev, IORESOURCE_MEM, 1);
GPIO5_GDIR = ioremap(pIORESOURCE_MEM->start, 4);
pIORESOURCE_MEM = platform_get_resource(pdev, IORESOURCE_MEM, 2);
GPIO5_DR = ioremap(pIORESOURCE_MEM->start, 4);
major = register_chrdev(0, "100ask_led", &led_fops);
device_create(led_class, NULL, MKDEV(major, 0), NULL, "myled"); /* /dev/myled */
return ret;
}
static int my_platform_remove(struct platform_device *pdev)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
iounmap(GPIO5_GDIR);
iounmap(GPIO5_DR);
device_destroy(led_class, MKDEV(major, 0));
unregister_chrdev(major, "100ask_led");
return 0;
}
static struct platform_driver my_led_platform_driver = {
.probe = my_platform_probe,
.remove = my_platform_remove,
.driver = {
.name = "my_led_platform_device",
.owner = THIS_MODULE,
}
};
/* 入口函数 */
static int __init led_init(void)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
led_class = class_create(THIS_MODULE, "myled");
platform_driver_register(&my_led_platform_driver);
return 0;
}
static void __exit led_exit(void)
{
platform_driver_unregister(&my_led_platform_driver);
class_destroy(led_class);
printk("led platform driver exited!\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");`
浙公网安备 33010602011771号