|
【Linux】
RK3288 通过控制寄存器实现LED灯控制
发表于 2019-11-18 17:41:00
浏览:5274
|
回复:1
打印
只看该作者
[复制链接]
楼主
麻烦帮我看一下,通过设置power led的寄存器来控制其亮灭,编译安装后,发现无效,麻烦大神指点。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/rockchip/iomap.h>
#define DEVICE_NUM 1
#define DEVICE_NAME "rockled"
#define LEDOFF 0
#define LEDON 1
#define RK_SW_GPIO8_DR_BASE (0xFF7F0000)
#define RK_SW_GPIO8_GRF_BASE (0xFF770080)
#define RK_SW_GPIO8_GDIR_BASE (0xFF7F0004)
static void __iomem *SW_GPIO8_2_DR;
static void __iomem *SW_GPIO8_2_GDIR;
static void __iomem *SW_GPIO8_MUX;
struct rockled_dev {
dev_t devid;
struct cdev cdev;
struct class *class;
struct device *device;
int major;
int minor;
};
struct rockled_dev rockled;
static int rockled_open(struct inode *inode, struct file *filp)
{
filp->private_data = &rockled;
printk("rockled open\r\n");
return 0;
}
static int rockled_release(struct inode *inode, struct file *filp)
{
printk("rockled release\r\n");
return 0;
}
static ssize_t rockled_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
printk("rockled read\r\n");
return 0;
}
static void led_switch(unsigned char state)
{
u32 val;
if(state == LEDON) {
val = readl(SW_GPIO8_2_DR);
val &= ~(1<<2);
writel(val,SW_GPIO8_2_DR);
} else if( state == LEDOFF ) {
val = readl(SW_GPIO8_2_DR);
val |= (1<<2);
writel(val,SW_GPIO8_2_DR);
}
}
static ssize_t rockled_write(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
int retvalue;
unsigned char databuf[10];
unsigned char ledstat;
retvalue = copy_from_user(databuf, buf, size);
if(retvalue < 0) {
printk("rockled write failed\r\n");
return -EFAULT;
}
ledstat = databuf[0];
if(ledstat == LEDON) {
led_switch(LEDON);
} else if (ledstat = LEDOFF) {
led_switch(LEDOFF);
}
printk("rockled write success\r\n");
return 0;
}
static const struct file_operations rockled_fops = {
.owner = THIS_MODULE,
.read = rockled_read,
.write = rockled_write,
.open = rockled_open,
.release = rockled_release,
};
static int __init rockled_init(void)
{
unsigned long val;
SW_GPIO8_2_DR = ioremap(RK_SW_GPIO8_DR_BASE,4);
SW_GPIO8_2_GDIR = ioremap(RK_SW_GPIO8_GDIR_BASE,4);
SW_GPIO8_MUX = ioremap(RK_SW_GPIO8_GRF_BASE,4);
val = readl(SW_GPIO8_MUX);
val &= ~(1<<4);
writel(val,SW_GPIO8_MUX);
val = readl(SW_GPIO8_2_GDIR);
val |= (1<<2);
writel(val,SW_GPIO8_2_GDIR);
val = readl(SW_GPIO8_2_DR);
val |= (1<<2);
writel(val,SW_GPIO8_2_DR);
if(rockled.major) {
rockled.devid = MKDEV(rockled.major,0);
register_chrdev_region(rockled.devid,DEVICE_NUM,DEVICE_NAME);
} else {
alloc_chrdev_region(&rockled.devid,0,DEVICE_NUM,DEVICE_NAME);
rockled.major = MAJOR(rockled.devid);
rockled.minor = MINOR(rockled.devid);
}
printk("rockled init, major=%d,minor=%d\r\n", rockled.major, rockled.minor);
rockled.cdev.owner = THIS_MODULE;
cdev_init(&rockled.cdev, &rockled_fops);
cdev_add(&rockled.cdev,rockled.devid,DEVICE_NUM);
rockled.class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(rockled.class)) {
return PTR_ERR(rockled.class);
}
rockled.device = device_create(rockled.class,NULL,rockled.devid,NULL,DEVICE_NAME);
if(IS_ERR(rockled.device)) {
return PTR_ERR(rockled.device);
}
return 0;
}
module_init(rockled_init);
static void __exit rockled_exit(void)
{
iounmap(SW_GPIO8_2_GDIR);
iounmap(SW_GPIO8_2_DR);
iounmap(SW_GPIO8_MUX);
device_destroy(rockled.class,rockled.devid);
class_destroy(rockled.class);
cdev_del(&rockled.cdev);
unregister_chrdev_region(rockled.devid,DEVICE_NUM);
}
module_exit(rockled_exit);
MODULE_AUTHOR("rockled");
MODULE_LICENSE("GPL"); |
|