213 lines
5.6 KiB
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"); |