📄 ov_sensor.c
字号:
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <asm/bug.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include "ov_sensor.h"
//#define OV_DBG 1
#define malloc(x) kmalloc(x, GFP_KERNEL)
#define free(x) kfree(x)
#define printf(format, arg...) printk( format, ## arg)
#define assert_(x) BUG_ON(!(x))
#include <asm/irq.h>
#include <asm/blackfin.h>
#include <asm/dma.h>
#include <asm/cacheflush.h>
#include <asm-blackfin/mach-bf533/irq.h>
#define VIDEO_BUF_NUM 10
#define COL_NUM 320
#define ROW_NUM 240
#define PPI_DMA_IOBASE DMA0_NEXT_DESC_PTR
#define SSYNC __builtin_bfin_ssync()
#define I2C_CYCLE 0
#define SENSOR_CYCLE 1
static unsigned char ID_addr = 0x00;
static int current_cmd = SENSOR_CYCLE;
static unsigned char current_i2c_addr;
static long current_arg;
static dmasg_t VideoDmaPtr[VIDEO_BUF_NUM];
static char VideoDmaBuf[VIDEO_BUF_NUM][COL_NUM][ROW_NUM];
static dma_register_t* DmaRegPhy = (dma_register_t*)PPI_DMA_IOBASE;
#define HHBF_I2C_SCLK (1 << 11)
#define HHBF_I2C_SDATA (1 << 10)
#define I2C_HW_B_HHBF I2C_HW_B_FRODO /* 0x13 */
static void hhbf_setsda(int state)
{
#if 0 /* comment by mhfan */
if (state)
*pFIO_FLAG_D |= HHBF_I2C_SDATA;
else
*pFIO_FLAG_D &= ~HHBF_I2C_SDATA;
#else
if (state) {
*pFIO_DIR |= HHBF_I2C_SDATA;
SSYNC;
*pFIO_INEN &= ~HHBF_I2C_SDATA; //
SSYNC;
*pFIO_FLAG_D |= HHBF_I2C_SDATA;
SSYNC;
} else {
//*pFIO_INEN &= ~HHBF_I2C_SDATA; //
//SSYNC;
*pFIO_DIR |= HHBF_I2C_SDATA;
SSYNC;
*pFIO_INEN &= ~HHBF_I2C_SDATA; //
SSYNC;
*pFIO_FLAG_D &= ~HHBF_I2C_SDATA;
SSYNC;
}
udelay(80);
#endif /* comment by mhfan */
}
static void hhbf_setscl(int state)
{
if (state)
{
*pFIO_FLAG_D |= HHBF_I2C_SCLK;
SSYNC;
}
else
{
*pFIO_FLAG_D &= ~HHBF_I2C_SCLK;
SSYNC;
}
udelay(80);
}
static int hhbf_getsda(void)
{
unsigned int data_tmp;
*pFIO_DIR &= ~HHBF_I2C_SDATA;
SSYNC;
*pFIO_INEN |= HHBF_I2C_SDATA;
SSYNC;
data_tmp = *pFIO_FLAG_D & HHBF_I2C_SDATA;
udelay(80);
return (data_tmp);
}
void i2c_hhbf_init(void)
{
*pFIO_DIR |= HHBF_I2C_SCLK; // Set SCLK as output
SSYNC;
*pFIO_POLAR &= ~HHBF_I2C_SDATA; // Enable Active Hight
SSYNC;
*pFIO_EDGE &= ~HHBF_I2C_SDATA; // Enable Level Sensitivity
SSYNC;
*pFIO_INEN |= HHBF_I2C_SDATA; // Enable SDATA Input Buffer
SSYNC;
*pFIO_DIR &= ~HHBF_I2C_SDATA; // Set SDATA as input/high
SSYNC;
#if 0 /* comment by mhfan */
*pFIO_DIR |= HHBF_I2C_SDATA;
*pFIO_FLAG_D |= HHBF_I2C_SDATA;
#endif /* comment by mhfan */
*pFIO_FLAG_D |= HHBF_I2C_SCLK; // Set SCLK high
SSYNC;
}
unsigned char hhbf_read(unsigned char addr)
{
char i;
unsigned char data_tmp=0;
unsigned char data_pattern[] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
#ifdef OV_DBG
printk("current i2c op is read\n");
printk("current ID addr is %x\n",ID_addr);
printk("cureent read addr is %x\n",addr);
#endif
/*start bit */
hhbf_setscl(1);
hhbf_setsda(1);
hhbf_setsda(0);
hhbf_setscl(0);
/* setting ID address*/
for(i = 6;i >= 0;-- i)
{
hhbf_setscl(0);
if (ID_addr & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/*This is a write op */
hhbf_setsda(0);
hhbf_setscl(1);
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
/* setting sub-address */
for(i = 7;i >= 0;--i)
{
hhbf_setscl(0);
if (addr & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
/*stop bit */
hhbf_setscl(0);
hhbf_setsda(0);
hhbf_setscl(1);
hhbf_setsda(1);
/*start bit */
hhbf_setscl(1);
hhbf_setsda(1);
hhbf_setsda(0);
hhbf_setscl(0);
/* setting ID address*/
for(i = 6;i >= 0;--i)
{
hhbf_setscl(0);
if (ID_addr & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/*This is a read op */
hhbf_setsda(1);
hhbf_setscl(1);
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
data_tmp = 0;
for (i = 7;i >= 0;--i)
{
hhbf_setscl(0);
hhbf_setscl(1);
if (hhbf_getsda())
data_tmp |= data_pattern[i];
}
hhbf_setscl(0);
/*stop bit */
hhbf_setscl(0);
hhbf_setsda(0);
hhbf_setscl(1);
hhbf_setsda(1);
return data_tmp;
}
void hhbf_write(unsigned char addr,unsigned char data)
{
char i;
unsigned char data_pattern[] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
#ifdef OV_DBG
printk("current i2c op is write\n");
printk("current ID addr is %x\n",ID_addr);
printk("current write addr is %x\n",addr);
printk("current write data is %x\n",data);
#endif
/*start bit */
hhbf_setscl(1);
hhbf_setsda(1);
hhbf_setsda(0);
hhbf_setscl(0);
/* setting ID address*/
for(i = 6;i >= 0;--i)
{
hhbf_setscl(0);
if (ID_addr & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/*This is a write op */
hhbf_setsda(0);
hhbf_setscl(1);
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
/* setting sub-address */
for(i = 7;i >= 0;--i)
{
hhbf_setscl(0);
if (addr & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
for (i = 7;i >= 0;--i)
{
hhbf_setscl(0);
if (data & data_pattern[i])
hhbf_setsda(1);
else
hhbf_setsda(0);
hhbf_setscl(1);
}
hhbf_setscl(0);
/* settting the x bit */
hhbf_getsda();
hhbf_setscl(1);
hhbf_setscl(0);
/*stop bit */
hhbf_setscl(0);
hhbf_setsda(0);
hhbf_setscl(1);
hhbf_setsda(1);
}
static void setup_desc(dmasg_t* desc, void* buf,unsigned int cfg, unsigned int x_count, unsigned int ycount){
int i;
for( i=0; i < VIDEO_BUF_NUM; ++i ){
desc[i].next_desc_addr = (unsigned long)&( desc[i + 1] );
desc[i].start_addr = (unsigned long)buf + i * COL_NUM * ROW_NUM;
desc[i].cfg = cfg;
desc[i].x_count = x_count;
desc[i].x_modify = sizeof(long);
desc[i].y_count = ycount;
desc[i].y_modify = sizeof(long);
}
desc[VIDEO_BUF_NUM - 1].next_desc_addr = (unsigned long)desc; /* make circular */
/* printk(KERN_ERR"setup desc: desc0=%p, next0=%lx, desc1=%p, next1=%lx\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n",
&(desc[0]), desc[0].next_desc_addr,
&(desc[1]), desc[1].next_desc_addr,
desc[0].x_count, desc[0].y_count, desc[0].start_addr,desc[0].cfg);
*/
flush_dcache_range((unsigned int)desc, (unsigned int)desc + VIDEO_BUF_NUM * sizeof(dmasg_t));
}
static struct proc_dir_entry *rtc_ent;
static int pid_process = 0;
static int sig_count = 0;
static unsigned int glab_count = 0;
static loff_t ov_llseek(struct file *file, loff_t offset, int origin);
static ssize_t ov_read(struct file *file, char *buf,size_t count, loff_t *ppos);
static ssize_t ov_write(struct file *file,const char *buf,size_t count,loff_t *ppos);
static int ov_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg);
static int ov_open(struct inode *inode, struct file *file);
static int ov_release(struct inode *inode, struct file *file);
#if 0
static read_proc_t* pid_rcv_read_proc(char *page, char **start, off_t off, int count,int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", pid_process);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
//printk("curren imask equal %x\n",*pSIC_IMASK);
return len;
}
static write_proc_t* pid_rcv_write_proc(struct file *file, const char __user *buffer,unsigned long count, void *data)
{
char temp[10];
int i = 1;
int j = 0;
int data_tmp = 0;
for (j=0;j<count -2;j++)
i = 10 * i;
//printk("currnet i equal : %d\n",i);
copy_from_user(temp,buffer,count);
j=0;
for (;i>0;i=i/10){
//printk("current char equal: %c\n",temp[j]);
data_tmp = data_tmp+ (temp[j] - 48)*i;
//printk("current data_tmp : %d\n",data_tmp);
j++;
}
pid_process = data_tmp;
//printk("pid_process equal : %d\n",data_tmp);
//printk("string is equal : %s\n",temp);
return count;
}
#endif
static struct file_operations ov_fops = {
owner: THIS_MODULE,
llseek: ov_llseek,
read: ov_read,
write: ov_write,
ioctl: ov_ioctl,
open: ov_open,
release: ov_release
};
static struct miscdevice ov_dev =
{
OV_SENSOR_MINOR,
"ov_sensor",
&ov_fops
};
static loff_t ov_llseek(struct file *file, loff_t offset, int origin)
{
return 0;
}
static ssize_t ov_read(struct file *file, char *buf,size_t count, loff_t *ppos)
{
if (current_cmd == I2C_CYCLE)
return (hhbf_read(current_i2c_addr));
else
return 0;
}
static ssize_t ov_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
if (current_cmd == I2C_CYCLE)
{
//printk("current_i2c_addr is %x buf data is %x\n",current_i2c_addr,buf[0]);
hhbf_write(current_i2c_addr,buf[0]);
}
return 0;
}
static int ov_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{
current_cmd = cmd;
if (cmd == I2C_CYCLE)
{
current_i2c_addr = (unsigned char) arg;
ID_addr = (unsigned char)(arg >> 8);
}
return 0;
}
static int ov_open(struct inode *inode, struct file *file)
{
*pPPI_CONTROL = 0xc1;
SSYNC;
return 0;
}
static int ov_release(struct inode *inode, struct file *file)
{
*pPPI_CONTROL = 0xc0;
SSYNC;
return 0;
}
static irqreturn_t ppi_error_handler(int irq, void *dev_id, struct pt_regs *regs){
#ifdef OV_DBG
printk("in module ppi_error_handler\n");
#endif
*pDMA0_IRQ_STATUS |= (DMA_DONE | DMA_ERR);
SSYNC;
#ifdef OV_DBG
printk("*pPPI_STATUS = %x\n",*pPPI_STATUS); /* read it to clear the error */
#else
*pPPI_STATUS = *pPPI_STATUS;
SSYNC;
#endif
return IRQ_HANDLED;
}
static irqreturn_t ppi_rx_handler(int irq, void *dev_id, struct pt_regs *regs){
#ifdef OV_DBG
printk("in module ppi_rx_handler\n" );
#endif
*pDMA0_IRQ_STATUS |= (DMA_DONE | DMA_ERR);
SSYNC;
return IRQ_HANDLED;
}
static void __exit ov_exit(void){
deregister(&ov_dev);
return 0;
}
static int __init ov_init(void){
static int id3;
#if 0
#define pPPI_CONTROL
#define pPPI_STATUS
#define pPPI_DELAY
#define pPPI_COUNT
#define pPPI_FRAME
*pPPI_CONTROL = 0x40c;
SSYNC;
setup_desc(VideoDmaPtr,VideoDmaBuf,0x7817, COL_NUM, ROW_NUM);
*pDMA0_CONFIG = 0x7816;
*pDMA0_NEXT_DESC_PTR = VideoDmaPtr;
SSYNC;
#ifdef OV_DBG
printk("start request dma sources!%d,%d,%x,%x\n",IRQ_PPI,IRQ_PPI_ERROR,&VideoDmaPtr[1],&VideoDmaBuf[1]);
#endif
if(request_dma(0,"PPI RX Data") == -EBUSY){
printk("Unable to allocate PPI RX dma %d\n", IRQ_PPI);
return NULL ;
}
if( set_dma_callback(0,ppi_rx_handler, NULL) != 0){
printk("Unable to set PPI RX dma handler%d\n", IRQ_PPI);
free_dma(IRQ_PPI);
return NULL ;
}
#ifdef OV_DBG
printk("start request ppi error sources!\n");
#endif
if( request_irq(IRQ_PPI_ERROR, &ppi_error_handler, SA_SHIRQ, "PPI RX ERROR", &id3) ){
printk( "Unable to allocate ppi error IRQ %d\n", IRQ_TMR0);
ov_exit();
return -ENODEV;
}
enable_irq(IRQ_PPI_ERROR);
#ifdef OV_DBG
printk("I am ov_sensor init!%x\n",*((volatile unsigned long*) 0xffe02104));
#endif
enable_dma(0);
*pDMA0_CONFIG = 0x7817;
SSYNC;
//*pPPI_CONTROL = 0x40cd;
//SSYNC;
printk("pDMA0_CONFIG: = %x\n",*pDMA0_CONFIG);
printk("pPPI_STATUS: = %x\n",*pPPI_STATUS);
#endif
misc_register(&ov_dev);
i2c_hhbf_init();
return 0;
}
MODULE_AUTHOR("maji<maji_999@163.com>");
MODULE_DESCRIPTION("ov_sensor");
MODULE_LICENSE("GPL");
module_init(ov_init);
module_exit(ov_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -