一个简单的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");`
posted @ 2026-03-09 22:31  michael2025  阅读(1)  评论(0)    收藏  举报