//yled.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <asm/io.h>
#include "ypublic.h"
MODULE_LICENSE("Dual BSD/GPL");
#define YMAJOR 100
#define YMINOR 1
#define YDEVICENAME "uartdriver"
#define YBUFSIZE 10
#define UBRDIVn(baud) ()
#define SETB(n) (1<<(n))
#define CLRB(n) (~ SETB(n))
#define SETN(v,n) (v<<n)
#define SETNB(v,d,n,w)\
({\
ulong rs;\
rs=0xffffffff;\
rs=rs<<(32-n-w);\
rs=rs>>(32-w);\
rs=~(rs<<n);\
rs=n&rs|(v<<n);\
rs;\
})
#if 0
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#endif
//io
#define UARTBASE(n) (0x50000000+(0x00004000<<(n)))
#define UARTREGNUM 3
#define YUART0 UARTBASE(0)
#define YUART1 UARTBASE(1)
#define YUART2 UARTBASE(2)
#define YINFRARED_MODE SETB(6)
#define YNOPARITY 0
#define Y2STOPBIT SETB(2)
#define Y8BITS SETN(3,0)
typedef struct {
struct cdev dev;
uchar inbuf[YBUFSIZE];
uchar outbuf[YBUFSIZE];
}ycdev;
ycdev *_pdev;
static int _major=YMAJOR;
static struct timer_list _tm;
//io regs
#define GPBBASE 0x56000010
ulong rgpbcon,rgpbdat,rgpbup;
static void* initio(void)
{
if(request_mem_region(UARTBASE(0),sizeof(YRUart),"UART")==NULL)
return NULL;
_uart=(YRUart *)ioremap(UARTBASE(0),sizeof(YRUart));
return (void*)_uart;
}
void releaseio(void)
{
if(_uart!=NULL){
iounmap((void*)UARTBASE(0));
release_mem_region(UARTBASE(0),sizeof(YRUart));
}
}
irqreturn_t onIrq(int irq,void *dev_id)
{
_tm.expires=MS(2000);
add_timer(&_tm);
return IRQ_HANDLED;
}
void initUart(void)
{
iowrite32(Y8BITS,&_uart->ULCON);
}
static void onTime(ulong arg)
{
uint dat;
dat=ioread32(rgpbdat);
if(dat&SETB(10)){
iowrite32((~(SETB(7)|SETB(10)))&dat,rgpbdat);
}
else{
iowrite32(SETB(7)|SETB(10)|dat,rgpbdat);
}
_tm.expires=MS(2000);
printk(KERN_INFO "on time:%u\n",dat);
add_timer(&_tm);
}
int yopen(struct inode *pinode,struct file *pfile)
{
return 0;
}
int yrelease(struct inode *pinode,struct file *pfile)
{
return 0;
}
static struct file_operations _fops={
.open=yopen,
.release=yrelease,
};
int __init yinit(void)
{
dev_t devno=MKDEV(YMAJOR,YMINOR);
int rs;
uint tmp;
if(_major){
rs=register_chrdev_region(devno,1,YDEVICENAME);
}
else{
rs=alloc_chrdev_region(&devno,YMINOR,1,YDEVICENAME);
_major=MAJOR(devno);
}
if(rs<0)return rs;
_pdev=kmalloc(sizeof(ycdev),GFP_KERNEL);
if(!_pdev){
rs= -ENOMEM;
goto fail1;
}
cdev_init(&_pdev->dev,&_fops);
_pdev->dev.owner=THIS_MODULE;
rs=cdev_add(&_pdev->dev,MKDEV(_major,YMINOR),0);
if(rs){
rs=-EBUSY;
goto fail2;
}
#if 0
if(initio()==NULL)
printk(KERN_ERR"ioremap failed\n");
else printk(KERN_ERR"ioremap success\n");
#endif
rgpbcon=yioremap(GPBBASE,12,"gpbreg");
rgpgcon=yioremap(GPBGASE,12,"gpgreg");
if(rgpbcon==NULL||rgpgcon==NULL)goto fail2;
else{
rgpbdat=rgpbcon+4;
rgpbup=rgpbcon+8;
iowrite32(SETN(1,14)|SETN(1,20)|ioread32(rgpbcon),rgpbcon);
iowrite32(SETB(7)|SETB(10)|ioread32(rgpbup),rgpbup);
iowrite32(SETB(7)|SETB(10)|ioread32(rgpbdat),rgpbdat);
if(rs)printk(KERN_INFO"irq failed");
}
setup_timer(&_tm,onTime,1);
printk(KERN_INFO "driver ok\n");
return 0;
fail2:
kfree(_pdev);
fail1:
unregister_chrdev_region(devno,1);
return -EBUSY;
}
void __exit yexit(void)
{
del_timer(&_tm);
yiounmap(GPBBASE,12);
cdev_del(&_pdev->dev);
kfree(_pdev);
unregister_chrdev_region(MKDEV(_major,YMINOR),1);
}
MODULE_AUTHOR("MrY");
module_init(yinit);
module_exit(yexit);
|