driver/4-device-tree/led.c

213 lines
5.6 KiB
C

/*
* @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
* @Date: 2023-08-19 09:31:52
* @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
* @LastEditTime: 2023-09-16 17:08:09
* @FilePath: /3-new-led/led.c
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/***
* configuration
*/
// DEV_NAME
#define dev_name "newchr"
// DEV_ID配置
#define DEV_ID_STATIC 1
#if DEV_ID_STATIC
#define DEV_ID_MAJOR 80
#define DEV_ID_MINOR 0
#endif
/**
* GPIO Control Code
*/
/* 映射后的寄存器虚拟地址指针 */
static void __iomem *MPU_AHB4_PERIPH_RCC_PI;
static void __iomem *GPIOI_MODER_PI;
static void __iomem *GPIOI_OTYPER_PI;
static void __iomem *GPIOI_OSPEEDR_PI;
static void __iomem *GPIOI_PUPDR_PI;
static void __iomem *GPIOI_BSRR_PI;
void led_unmap(void)
{
/* 取消映射 */
iounmap(MPU_AHB4_PERIPH_RCC_PI);
iounmap(GPIOI_MODER_PI);
iounmap(GPIOI_OTYPER_PI);
iounmap(GPIOI_OSPEEDR_PI);
iounmap(GPIOI_PUPDR_PI);
iounmap(GPIOI_BSRR_PI);
}
void led_switch(u8 sta)
{
u32 val = 0;
if(sta == '1') {
val = readl(GPIOI_BSRR_PI);
val |= (1 << 16);
writel(val, GPIOI_BSRR_PI);
}else if(sta == '0') {
val = readl(GPIOI_BSRR_PI);
val|= (1 << 0);
writel(val, GPIOI_BSRR_PI);
}
}
struct _dev_info
{
dev_t dev_id;
struct cdev cdev;
struct class *class;
struct device *device;
} dev_info = {0};
/***
* code
*/
static ssize_t tis_module_read(struct file *file, char __user *out, size_t size, loff_t *offt)
{
printk("%s: module read\n", dev_name);
return 0;
}
static ssize_t tis_module_write(struct file *file, const char __user *in, size_t size, loff_t *offt)
{
// printk("%s: module write\n", dev_name);
char ch[1];
copy_from_user(ch,in,1);
printk("get data:%d",ch[0]);
led_switch(ch[0]);
return 0;
}
static int tis_module_open(struct inode *inode, struct file *file)
{
printk("%s: module open\n", dev_name);
return 0;
}
static int tis_module_release(struct inode *inode, struct file *file)
{
printk("%s: module release\n", dev_name);
return 0;
}
static struct file_operations tis_module_f = {
.owner = THIS_MODULE,
.write = tis_module_write,
.read = tis_module_read,
.open = tis_module_open,
.release = tis_module_release,
};
void device_tree_test(void){
struct device_node *node;
node = of_find_node_by_path("/tree-test");
if(node == NULL){
printk(" device no find tree-test\n");
}
printk("this node is %s\n",node->full_name);
node = of_find_node_by_path("/tree-test/dev1");
if(node == NULL){
printk(" device no find tree-test/device1\n");
}
struct property *prop ;
prop = of_find_property(node, "compatible", NULL);
if(prop == NULL){
printk("no find property\n");
return ;
}
printk(" device1 compatible is %s\n",(char *)prop->value);
node = of_find_node_by_path("/tree-test/dev2@1122");
if(node == NULL){
printk(" device no find tree-test/device2\n");
}
printk("device found dev2:%s\n",node->name);
}
static int __init tis_module_init(void)
{
int ret;
device_tree_test();
return 0;
// 申请dev id
#if (DEV_ID_STATIC)
dev_info.dev_id = MKDEV(DEV_ID_MAJOR, DEV_ID_MINOR);
ret = register_chrdev_region(dev_info.dev_id, 1, dev_name);
if (ret < 0)
{
printk("[%s] dev_id get failed\n",dev_name);
return ret;
}
#else
ret = alloc_chrdev_region(&dev_info.dev_id, 0, 1, dev_name);
if (ret)
{
printk("[%s] dev_id get failed\n");
return ret;
}
#endif
// 注册设备
dev_info.cdev.owner = THIS_MODULE;
cdev_init(&dev_info.cdev, &tis_module_f);
ret = cdev_add(&dev_info.cdev, dev_info.dev_id, 1);
if (ret < 0)
{
printk("[%s] cdev_add failed\n", dev_name);
goto del_unregister;
}
// 创建设备
dev_info.class = class_create(THIS_MODULE, dev_name);
if (IS_ERR(dev_info.class))
{
printk("[%s] class create failed\n", dev_name);
goto del_cdev;
}
dev_info.device = device_create(dev_info.class, NULL, dev_info.dev_id, NULL, dev_name);
if (IS_ERR(dev_info.device))
{
printk("[%s] dev create failed\n", dev_name);
goto destroy_class;
}
printk("[%s] init success\n", dev_name);
return 0;
destroy_class:
class_destroy(dev_info.class);
del_cdev:
cdev_del(&dev_info.cdev);
del_unregister:
unregister_chrdev_region(dev_info.dev_id, 1);
return -EIO;
}
static void __exit tis_module_exit(void)
{
return;
/* 注销字符设备驱动 */
cdev_del(&dev_info.cdev); /* 删除cdev */
unregister_chrdev_region(dev_info.dev_id, 1); /* 注销设备号 */
device_destroy(dev_info.class, dev_info.dev_id);
class_destroy(dev_info.class);
printk("[%s] exit success\n", dev_name);
}
module_init(tis_module_init);
module_exit(tis_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chenyf");
MODULE_INFO(intree, "Y");