#include #include #include #include #include #include #include #include #include static dev_t led_dev; static struct cdev *led_cdev; static struct class *led_class; static struct device *led_device; static volatile uint32_t *RCC_PLL4CR; static volatile uint32_t *RCC_MP_AHB4ENSETR; static volatile uint32_t *GPIOA_MODER; static volatile uint32_t *GPIOA_BSRR; static int led_open(struct inode *inode, struct file *filp) { *RCC_PLL4CR |= (1 << 0); while ((*RCC_PLL4CR & (1 << 1)) == 0); *RCC_MP_AHB4ENSETR |= (1 << 0); *GPIOA_MODER &= ~(3 << 20); *GPIOA_MODER |= (1 << 20); printk(KERN_DEBUG "LED device opened.\r\n"); return 0; } static int led_close(struct inode *inode, struct file *filp) { printk(KERN_DEBUG "LED device closed.\r\n"); return 0; } static int led_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp) { char val; copy_from_user(&val, buff, 1); if (val) { *GPIOA_BSRR = (1 << 26); } else { *GPIOA_BSRR = (1 << 10); } return 0; } static int led_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { return 0; } static struct file_operations led_ops = { .owner = THIS_MODULE, .open = led_open, .release = led_close, .write = led_write, .read = led_read, }; static int __init led_init(void) { int ret; struct device_node *led_node; uint32_t addr_rcc_pll4cr; uint32_t addr_rcc_mp_ahb4ensetr; uint32_t addr_gpioa_moder; uint32_t addr_gpioa_bsrr; led_cdev = cdev_alloc(); if (led_cdev == NULL) { printk(KERN_ERR "Failed to allocate cdev\r\n"); return -ENOMEM; } ret = alloc_chrdev_region(&led_dev, 0, 1, "led"); if (ret != 0) { printk(KERN_ERR "Failed to allocate chrdev region\r\n"); return ret; } led_cdev->owner = THIS_MODULE; led_cdev->ops = &led_ops; cdev_add(led_cdev, led_dev, 1); led_class = class_create(THIS_MODULE, "led_class"); if (led_class == NULL) { printk(KERN_ERR "Failed to create class\r\n"); return -1; } led_device = device_create(led_class, NULL, led_dev, NULL, "led0"); if (IS_ERR(led_device)) { printk(KERN_ERR "Failed to create device\r\n"); return -1; } led_node = of_find_node_by_path("/jzhled"); if (led_node == NULL) { printk(KERN_ERR "file=%s, line=%d\r\n", __FILE__, __LINE__); goto no_led_node; } if (of_property_read_u32_index(led_node, "reg", 0, &addr_rcc_pll4cr)) { printk(KERN_ERR "file=%s, line=%d\r\n", __FILE__, __LINE__); goto of_error; } if (of_property_read_u32_index(led_node, "reg", 2, &addr_rcc_mp_ahb4ensetr)) { printk(KERN_ERR "file=%s, line=%d\r\n", __FILE__, __LINE__); goto of_error; } if (of_property_read_u32_index(led_node, "reg", 4, &addr_gpioa_moder)) { printk(KERN_ERR "file=%s, line=%d\r\n", __FILE__, __LINE__); goto of_error; } if (of_property_read_u32_index(led_node, "reg", 6, &addr_gpioa_bsrr)) { printk(KERN_ERR "file=%s, line=%d\r\n", __FILE__, __LINE__); goto of_error; } RCC_PLL4CR = ioremap(addr_rcc_pll4cr, 4); RCC_MP_AHB4ENSETR = ioremap(addr_rcc_mp_ahb4ensetr, 4); GPIOA_MODER = ioremap(addr_gpioa_moder, 4); GPIOA_BSRR = ioremap(addr_gpioa_bsrr, 4); return 0; of_error: printk(KERN_ERR "Failed to get led node reg\r\n"); return -1; no_led_node: printk(KERN_ERR "No led node found\r\n"); return -1; } static void __exit led_exit(void) { cdev_del(led_cdev); unregister_chrdev_region(led_dev, 1); device_destroy(led_class, led_dev); class_destroy(led_class); iounmap(RCC_PLL4CR); iounmap(RCC_MP_AHB4ENSETR); iounmap(GPIOA_MODER); iounmap(GPIOA_BSRR); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("jzhgonha@163.com"); MODULE_VERSION("V0.1"); MODULE_DESCRIPTION("A simple LED driver for STM32MP157");