本帖最后由 seven_spark 于 2024-7-28 10:20 编辑
就是GPIO的驱动,我没有参照现成的,没有使用设备树,为什么这种方式不行呢?
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
头文件,是与芯片物理属性相关的,寄存器值
*/
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)
/*
虚实映射的地址,是虚拟地址
*/
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;
/*
宏定义
*/
#define LED_NAME "led_us"
#define LEDOFF 0
#define LEDON 1
#define LED_NUM 1
static struct led_st
{
int major;
int minor;
int num;
char *name;
dev_t devno;
struct cdev cdev;
struct class *cls;
struct device *dvs;
unsigned char buf[1];
};
static struct led_st *led = NULL;
static void led_switch(unsigned char sta)
{
unsigned int val = 0;
if(sta == LEDON)
{
val = readl(GPIO1_DR);//GPIO_DR是控制电平的寄存器
val &= ~(1 i_cdev, struct led_st, cdev));
return 0;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static ssize_t led_write(struct file *pfilp, const char __user *buf, size_t cnt, loff_t *offt)
{
int retvalue;
unsigned char ledstat;
struct led_st *ptemp = (struct led_st *)pfilp->private_data;
retvalue = copy_from_user(ptemp->buf, buf, cnt);
if(retvalue < 0)
{
printk("kernel write failed.\n");
return -EFAULT;
}
ledstat = ptemp->buf[0];
if(ledstat == LEDON)
{
led_switch(LEDON);
}
else if(ledstat == LEDOFF)
{
led_switch(LEDOFF);
}
else
{
return -EFAULT;
}
*offt += cnt;
return cnt;
}
static int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
static int __init led_init(void)
{
int val = 0;
led = kzalloc(sizeof(struct led_st), GFP_KERNEL);
if(NULL == led)
{
printk("led kzalloc failed\n");
return -1;
}
else
{
led->major = 0;
led->minor = 0;
led->num = LED_NUM;
led->name = LED_NAME;
}
IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
val = readl(IMX6U_CCM_CCGR1);
val &= ~(3 cdev), led->devno, led->num))
{
unregister_chrdev_region(led->devno, led->num);
printk("cdev add failed\n");
return -2;
}
}
led->cls = class_create(THIS_MODULE, led->name);
if(led->cls == NULL)
{
printk("class create failed\n");
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
return -3;
}
led->dvs = device_create(led->cls, NULL, led->devno, NULL, led->name);
if(led->dvs == NULL)
{
printk("device create failed\n");
class_destroy(led->cls);
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
return -4;
}
return 0;
}
static void __exit led_exit(void)
{
iounmap(IMX6U_CCM_CCGR1);
iounmap(SW_MUX_GPIO1_IO03);
iounmap(SW_PAD_GPIO1_IO03);
iounmap(GPIO1_DR);
iounmap(GPIO1_GDIR);
device_destroy(led->cls, led->devno);
class_destroy(led->cls);
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
led = NULL;
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");