171 lines
4.8 KiB
C
171 lines
4.8 KiB
C
#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 <asm/mach/map.h>
|
||
#include <asm/uaccess.h>
|
||
#include <asm/io.h>
|
||
/***************************************************************
|
||
Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
|
||
文件名 : chrdevbase.c
|
||
作者 : 正点原子
|
||
版本 : V1.0
|
||
描述 : chrdevbase驱动文件。
|
||
其他 : 无
|
||
论坛 : www.openedv.com
|
||
日志 : 初版V1.0 2020/12/26 正点原子创建
|
||
***************************************************************/
|
||
#define major_dev_id 80
|
||
#define dev_name "led"
|
||
|
||
#define PERIPH_BASE (0x40000000)
|
||
#define MPU_AHB4_PERIPH_BASE (PERIPH_BASE + 0x10000000)
|
||
#define RCC_BASE (MPU_AHB4_PERIPH_BASE + 0x0000)
|
||
#define RCC_MP_AHB4ENSETR (RCC_BASE + 0XA28)
|
||
#define GPIOI_BASE (MPU_AHB4_PERIPH_BASE + 0xA000)
|
||
#define GPIOI_MODER (GPIOI_BASE + 0x0000)
|
||
#define GPIOI_OTYPER (GPIOI_BASE + 0x0004)
|
||
#define GPIOI_OSPEEDR (GPIOI_BASE + 0x0008)
|
||
#define GPIOI_PUPDR (GPIOI_BASE + 0x000C)
|
||
#define GPIOI_BSRR (GPIOI_BASE + 0x0018)
|
||
/* 映射后的寄存器虚拟地址指针 */
|
||
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;
|
||
|
||
char led_sta = '0';
|
||
static ssize_t tis_module_read(struct file *file, char __user *out, size_t size, loff_t *offt)
|
||
{
|
||
int ret = 0;
|
||
ret = copy_to_user(out,&led_sta,1);
|
||
return 0;
|
||
}
|
||
static ssize_t tis_module_write(struct file *file, const char __user *in, size_t size, loff_t *offt)
|
||
{
|
||
int ret = 0;
|
||
char sta;
|
||
unsigned int val;
|
||
ret = copy_from_user(&sta, in, 1);
|
||
if (ret < 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (sta!='0'&&sta!='1')
|
||
{
|
||
printk("led module should input 0/1, your input is %c\n");
|
||
return 0;
|
||
}
|
||
led_sta = sta;
|
||
switch (sta)
|
||
{
|
||
case '1':
|
||
val = readl(GPIOI_BSRR_PI);
|
||
val |= (1 << 16);
|
||
writel(val, GPIOI_BSRR_PI);
|
||
break;
|
||
case '0':
|
||
val = readl(GPIOI_BSRR_PI);
|
||
val |= (1 << 0);
|
||
writel(val, GPIOI_BSRR_PI);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
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,
|
||
};
|
||
static void led_init(void)
|
||
{
|
||
MPU_AHB4_PERIPH_RCC_PI = ioremap(RCC_MP_AHB4ENSETR, 4);
|
||
GPIOI_MODER_PI = ioremap(GPIOI_MODER, 4);
|
||
GPIOI_OTYPER_PI = ioremap(GPIOI_OTYPER, 4);
|
||
GPIOI_OSPEEDR_PI = ioremap(GPIOI_OSPEEDR, 4);
|
||
GPIOI_PUPDR_PI = ioremap(GPIOI_PUPDR, 4);
|
||
GPIOI_BSRR_PI = ioremap(GPIOI_BSRR, 4);
|
||
unsigned int val;
|
||
/* 2、使能PI时钟 */
|
||
val = readl(MPU_AHB4_PERIPH_RCC_PI);
|
||
val &= ~(0X1 << 8); /* 清除以前的设置 */
|
||
val |= (0X1 << 8); /* 设置新值 */
|
||
writel(val, MPU_AHB4_PERIPH_RCC_PI);
|
||
|
||
/* 3、设置PI0通用的输出模式。*/
|
||
val = readl(GPIOI_MODER_PI);
|
||
val &= ~(0X3 << 0); /* bit0:1清零 */
|
||
val |= (0X1 << 0); /* bit0:1设置01 */
|
||
writel(val, GPIOI_MODER_PI);
|
||
|
||
/* 3、设置PI0为推挽模式。*/
|
||
val = readl(GPIOI_OTYPER_PI);
|
||
val &= ~(0X1 << 0); /* bit0清零,设置为上拉*/
|
||
writel(val, GPIOI_OTYPER_PI);
|
||
|
||
/* 4、设置PI0为高速。*/
|
||
val = readl(GPIOI_OSPEEDR_PI);
|
||
val &= ~(0X3 << 0); /* bit0:1 清零 */
|
||
val |= (0x2 << 0); /* bit0:1 设置为10*/
|
||
writel(val, GPIOI_OSPEEDR_PI);
|
||
|
||
/* 5、设置PI0为上拉。*/
|
||
val = readl(GPIOI_PUPDR_PI);
|
||
val &= ~(0X3 << 0); /* bit0:1 清零*/
|
||
val |= (0x1 << 0); /*bit0:1 设置为01*/
|
||
writel(val, GPIOI_PUPDR_PI);
|
||
|
||
/* 6、默认关闭LED */
|
||
val = readl(GPIOI_BSRR_PI);
|
||
val |= (0x1 << 0);
|
||
writel(val, GPIOI_BSRR_PI);
|
||
led_sta = '0';
|
||
}
|
||
static void led_io_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);
|
||
}
|
||
|
||
static int __init tis_module_init(void)
|
||
{
|
||
register_chrdev(major_dev_id, dev_name, &tis_module_f);
|
||
printk("%s init\n", dev_name);
|
||
led_init();
|
||
return 0;
|
||
}
|
||
static void __exit tis_module_exit(void)
|
||
{
|
||
unregister_chrdev(major_dev_id, dev_name);
|
||
led_io_unmap();
|
||
printk("%s exit\n", dev_name);
|
||
}
|
||
module_init(tis_module_init);
|
||
module_exit(tis_module_exit);
|
||
MODULE_LICENSE("GPL v3.0");
|
||
MODULE_AUTHOR("Chenyf"); |