linux驱动程序,编译正确,加载不行:

发布于 2022-10-15 07:00:50 字数 3278 浏览 35 评论 0

linux驱动程序,编译正确,加载不行:

#define PCONF   (*(volatile unsigned *)0x56000040)
在初始化函数中有这句*(volatile unsigned *) PCONF |=0x0a;或 //PCONF |=0x0a;
出去上面的两句加载正确,加上就出现以下情况,请问是怎么回事啊?

[root@FriendlyARM 2.6.32.2-FriendlyARM]# insmod memdev.ko
module init   WO KAO  !
Unable to handle kernel paging request at virtual address 56000040
pgd = c3b14000
[56000040] *pgd=00000000
Internal error: Oops: 5 [#1]
last sysfs file: /sys/devices/virtual/vc/vcs4/dev
Modules linked in: memdev(+) hello
CPU: 0    Not tainted  (2.6.32.2-FriendlyARM #3)
PC is at memdev_init+0x1c/0x168 [memdev]
LR is at release_console_sem+0x188/0x1e4
pc : [<bf0182e8>]    lr : [<c004a6d8>]    psr: 60000013
sp : c3b1bf10  ip : c3b1be28  fp : c3b1bf34
r10: bf0182cc  r9 : 00000000  r8 : c0503660
r7 : c3b1a000  r6 : bf01855c  r5 : 000a18b7  r4 : 00001329
r3 : 56000000  r2 : c04c9638  r1 : 0000512f  r0 : 0000001e
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 33b14000  DAC: 00000015
Process insmod (pid: 747, stack limit = 0xc3b1a270)
Stack: (0xc3b1bf10 to 0xc3b1c000)
bf00:                                     c4840b2c 00000043 00000002 00001329
bf20: 000a18b7 bf01855c c3b1bf7c c3b1bf38 c003032c bf0182dc 00000000 00000000
bf40: 00000000 00001329 000a18b7 bf01855c 00000000 00001329 000a18b7 bf01855c
bf60: 00000000 c00310c8 c3b1a000 00000000 c3b1bfa4 c3b1bf80 c0070344 c0030300
bf80: c009b6b0 c009b5a0 4001d838 00000000 bebe4e68 00000080 00000000 c3b1bfa8
bfa0: c0030f20 c0070284 4001d838 00000000 000b5038 00001329 000a18b7 00000000
bfc0: 4001d838 00000000 bebe4e68 00000080 bebe4e64 bebe4e68 00000001 00000000
bfe0: 00000069 bebe4b34 0001778c 401d3c24 60000010 000b5038 305bb031 305bb431
Backtrace:
[<bf0182cc>] (memdev_init+0x0/0x168 [memdev]) from [<c003032c>] (do_one_initcall
+0x3c/0x1c
r6:bf01855c r5:000a18b7 r4:00001329
[<c00302f0>] (do_one_initcall+0x0/0x1c from [<c0070344>] (sys_init_module+0xd0
/0x204)
[<c0070274>] (sys_init_module+0x0/0x204) from [<c0030f20>] (ret_fast_syscall+0x0
/0x2
r7:00000080 r6:bebe4e68 r5:00000000 r4:4001d838
Code: e24dd00c e59f0130 eb4df5d0 e3a03456 (e5932040)
---[ end trace 04628c8e3797af5d ]---
Segmentation fault
[root@FriendlyARM 2.6.32.2-FriendlyARM]#

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

暖阳 2022-10-22 07:00:50

顶一下。。。

臻嫒无言 2022-10-22 07:00:50

我不知道你开发板提供的BSP操作的地址是不是直接通过那种形式来操作,有一些需要使用虚拟地址进行操作,敬请确认。

救星 2022-10-22 07:00:50

Unable to handle kernel paging request at virtual address 56000040
pgd = c3b14000
[56000040] *pgd=00000000

这块虚拟地址对应的物理地址未映射。

看程序你应该是想要访问物理地址0x56000040吧,用这个物理地址对应的虚拟地址访问。

神回复 2022-10-22 07:00:50

linux驱动中,对那些物理地址的访问,是要先转换成对应虚拟地址,才能访问的。
具体的,有page_to_virt之类的宏(或函数),记不清了,自己网上找找。

小猫一只 2022-10-22 07:00:50

回复 4# l2y3n2

   

大哥这是源程序,麻烦帮我看一下,我实在搞不来了,谢啦O(∩_∩)O~

#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <linux/interrupt.h>
#include <plat/iic.h>

#define u32 unsigned int
#define u16 unsigned short
#define s32 int
#define s16 short int
#define u8 unsigned char

/*  I/O PORT */

#define PCONF        (*(volatile unsigned *)0x56000040)
#define PDATF        (*(volatile unsigned *)0x56000044)
#define PUPF        (*(volatile unsigned *)0x5600004

#define IICCON        (*(volatile unsigned *)0x54000000)
#define IICSTAT        (*(volatile unsigned *)0x54000004)
#define IICADD        (*(volatile unsigned *)0x5400000
#define IICDS        (*(volatile unsigned *)0x5400000c)

#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_iic_dir, devfs_iicraw;
#endif

#define SKQ_IIC_MODULE_NAME        "IICBUS"
/*60--63,120--127,240--254*/
#define IICBUS_MAJOR        240
#define IICBUSRAW_MINOR 1

#define IICBUS_INT IRQ_IIC

static char *IICBUD_id = "SKQ IICBUS driver v1.0 (2005-06-02)<psc@hualiangtech.com>";

/* debug macros */
#undef DEBUG
//#define DEBUG
#ifdef DEBUG
#define DPRINTK( x... )            printk("SKQ IICBUS: "##x)
#else
#define DPRINTK( x... )
#endif

#define WRDATA                (1)
#define POLLACK                (2)
#define RDDATA                (3)
#define SETRDADDR        (4)

#define IICBUFSIZE 2048

char IICBUS_Buf[IICBUFSIZE];

static int opencount=0;
static int tsMajor=0;
static loff_t newpos=0;
int writenFM24CL16(char * buffer, size_t count, int address)
{
unsigned long timeo;
u16 i;
u16 PageAdd;
char slvAddr, tpICON,tempIICSTAT;
IICCON=(1<<7)|(0<<6)|(1<<5)|(0xf);
IICSTAT=0x10;

slvAddr=0xa0;
PageAdd=address;
/*  send the bit of start and address of device and page of address */
PageAdd>>7;
PageAdd&=0x0e;
slvAddr=(char)PageAdd;
slvAddr|=0xa0;
IICDS=slvAddr;  //0xa0
IICSTAT=0xf0;   //MasTx,Start

timeo = jiffies + (HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;        /* pending */
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;        /* ack */
if((tpICON==0x10))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf; /*pending */

IICDS=(char)address;  //0xa0
timeo = jiffies +(HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;
if((tpICON==0x10)) break;  // &&tempIICSTAT==0x00)
if(time_after(jiffies,timeo))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf;

for(i=0;i<count;i++)
{
IICDS=buffer;
timeo=jiffies + (HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;
if((tpICON==0x10)&&(tempIICSTAT==0x00)) break;
if(time_after(jiffies,timeo))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf;  /* clr pending */
}
IICSTAT =0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return count;
}

int ReadFM24CL16(char *buffer, size_t count, int address)
{
unsigned long timeo;
u16 i;
u8 slvAddr ,tpICON,tempIICSTAT;
u16 PageAdd;
PageAdd=address;
/* 发送起始位和设备地址和页地址 */
PageAdd>>=7;
PageAdd&=0x0e;
slvAddr=(char )PageAdd;
slvAddr|=0xa0;
IICDS=slvAddr;  //0xa0;
IICSTAT=0Xf0;   //MasTx,Start
timeo = jiffies +(HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        // tempIICSTAT=rIICSTAT;
        //tempEECSTAT&=0x01;
        if((tpICON==0x10)) break;  //&&(tempIICSTAT==0x00)
        if(time_after(jiffies,timeo))
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;
/* 发送地址低8位 */
IICDS=(char)address;
timeo = jiffies + (HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        tempIICSTAT=IICSTAT;
        tempIICSTAT&=0X01;
        if((tpICON==0x01)) break;  //&&(tempIICSTAT==0x00)
        if(time_after(jiffies, timeo))
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;
//IICSTAT&=0xef;
/* 发送起始位和设备地址和页地址 */
PageAdd>>=7;
PageAdd&=0x0e;
slvAddr=(char )PageAdd;
slvAddr|=0xa1;
IICDS=slvAddr;
IICSTAT=0xb0;  //MasRx,Start
timeo = jiffies +(HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        tempIICSTAT=IICSTAT;
        tempIICSTAT&=0x01;
        if((tpICON==0x10)) break; // &&(tempIICSTAT==0x00)
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;

for(i=0;i<count;i++)
{
        IICDS=slvAddr;
        //timeo =jiffies +(HZ/100);
        while(1){
                tpICON=IICCON;
                tpICON&=0x10;
                tempIICSTAT=IICSTAT;
                tempIICSTAT&=0x01;
                if((tpICON==0x10)) break ;//(tempIICSTAT==0x00)
                //else
                //        {
                //        if((tpICON==0x10)&&(i==count-1))break;
                //        }
                if(time_after(jiffies, timeo))
                {
                        IICSTAT=0x90;
                        IICCON=0xaf;
                        udelay(200);
                        IICCON=0xaf;
                        IICSTAT=0x10;
                        IICSTAT=0x10;
                        return -1;
                }
        };
        buffer=IICDS;
        if(i==count-1) IICCON=0x2f;
        else IICCON=0xaf;
}

IICSTAT=0x90;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;

return count;
}

loff_t  IICBUS_llseek(struct file *filp, loff_t off,int whence)
{
        switch(whence){
        case 0 :        /* SEEK_SET */
                newpos=off;
                break;
        default:        /* cant,t happen */
                return -EINVAL;
        }
        if(newpos<0) return -EINVAL;
        return newpos;
}

static ssize_t IICBUS_write(struct file *file,const char *buffer,size_t count, loff_t *ppos)
{
        int ret;
        int address=(int)newpos;
        if(count>204 return 0;
        // copy_from_user(&address,ppos, sizeof(loff_t));
        // address=(int)*ppos;
        // printk("IICBUS_write address=%ld\n",address);
        if(address+count>204 return 0;
        copy_from_user(IICBUS_Buf, count, address);
        return ret;
}
static ssize_t IICBUS_read(struct file *filp,char *buffer,size_t count, loff_t *ppos)
{
        int len;
        int address=(int)newpos;
        //int address1;
        if(count>204 return 0;
        //copy_from_user(&address,ppos, sizeof(loff_t));
        //address=(int)*ppos;
        //printk("IICBUS_read address=%d\n",address);
        if(address+count>204 return 0;
        //address1=(int)*ppos;
        //printk("IICBUS_read address1=%ld\n",address);
        //printk("IICBUS_read ppos=%ld\n",ppos);
        len=ReadFM24CL16(IICBUS_Buf,count,address);
        copy_to_user(buffer,IICBUS_Buf,len);
        DPRINTK("read data=%d\n",data);
        return len;
}

static int IICBUS_open(struct inode *inode, struct file *file)
{
        //if(opencount==1)
        //return -EBUSY;
        opencount++;
       try_module_get(THIS_MODULE);        //MOD_INC_USE_COUNT;
        DPRINTK("device open\n";
        return 0;
}

static int IICBUS_release(struct inode *inode, struct file *filp)
{
        opencount--;
        module_put(THIS_MODULE);   //MOD_DEC_USE_COUNT;
        DPRINTK("device release\n";
        return 0;
}
static struct file_operations s3c44b0_iicbus_fops ={
owner:        THIS_MODULE,
llseek:        IICBUS_llseek,
write:        IICBUS_write,
read:        IICBUS_read,
open:        IICBUS_open,
release:        IICBUS_release,
};

static int __init IICBUS_init(void)
{
        int ret;
        int flags;
        //local_irq_save(flags);
        /* port F */
                /* Bit8                 7         6        5        4        3        2       
                     SPICKL            SPIMISO        SPICS        SPIMOSI        INCARD2        NC        NC */
                     PCONF |=0x0a;        //PF0:IICSCL,PF1:IICSDA
                     PUPF |=0x03;        //pull-up disable
                     IICCON=(1<<7)|(0<<6)|(0<<5)|(0xf);
                     //Enable interrupt,IICCLK=MCKL/16,Enable ACK
                     //40Mhz/16/(15+1)=257khz
                     IICADD=0x10;  //s3c44B0X slave address
                     IICSTAT=0X10;
                     local_irq_restore(flags);
                     opencount=0;
                     ret = register_chrdev(IICBUS_MAJOR, SKQ_IIC_MODULE_NAME,&s3c44b0_iicbus_fops);
                     if (ret<0)
                     {
                     printk( ":can't get major number\n",__FUNCTION__);      
                     return -1;
                     }
                     tsMajor=ret;
                     #if 0
                     if(0 !=request_irq(IICBUS_INT,IICBUS_isr,SA_INTERRUPT,IICBUD_ID,NULL))
                     {
                                  printk(KERN_WARNING "tce44b0_usb:failed to get IRQ\n";
                                  return 1;
                     }
                     #endif
                     #ifdef CONFIG_DEVFS_FS
                                     devfs_iic_dir = devfs_mkdir(NULL,SKQ_IIC_MODULE_NAME,NULL);
                                     devfs_iicraw = devfs_register(devfs_iic_dir, "0",DEVFS_FL_DEFAULT,
                                             tsMajor,IICBUSRAW_MINOR,S_IFCHR | S_IRUSR | S_IWUSR,
                                             &s3c44b0_iicbus_fops,NULL);
                     #endif
                                     printk(SKQ_IIC_MODULE_NAME " initialized\n";
                                     return 0;
}

static void __exit IICBUS_exit(void)
{
        printk(":SKQ IIC Exit.\n",__FUNCTION__);
//        free_irq(IICBUS_INT, IICBUD_id);
         unregister_chrdev_region(IICBUS_MAJOR,1);
}

module_init(IICBUS_init);
module_exit(IICBUS_exit);
MODULE_DESCRIPTION("SKQ IIC driver";
MODULE_AUTHOR("pengshicao ";
MODULE_LICENSE("GPL";

谁人与我共长歌 2022-10-22 07:00:50

回复 3# nazily2150

    我用的是S3C2440开发板,帮我看一下,我把源程序贴出来了
谢谢O(∩_∩)O~

潜移默化 2022-10-22 07:00:50

是I2C控制器的物理地址没有转化成虚拟地址就直接访问了!

夜唯美灬不弃 2022-10-22 07:00:50

在init函数里面这样:

  1. volatile void *pbase, *iicbase;
  2. pbase = ioremap(PCONF, 0x10);
  3. iicbase = ioremap(IICCON, 0x10);

复制代码然后对PCONF、PDATA、PUPF的访问使用pbase、pbase+4、pbase+8
II2系列寄存器也一样用iicbase、iicbase+4、iicbase+8、iicbase+12

沐歌 2022-10-22 07:00:50

回复 9# l2y3n2

我后来把代码改成下列形式了,编译正确,加载出错:  Segmentation fault

什么问题啊?

#include <asm/io.h>

#include "config.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include "hardware.h"
//  #include <linux/interrupt.h>
//  #include <plat/iic.h>
#include <linux/gpio.h>
#include <mach/regs-gpio.h>

#define u32 unsigned int
#define u16 unsigned short
#define s32 int
#define s16 short int
#define u8 unsigned char

#define   iiccon  0x54000000
#define   iicstat 0x54000004
#define   iicds 0x5400000c
#define   iicadd 0x54000008
#define   iicl  0x54000010
#define   clkcon 0x4c00000c
static void *IICSTAT;
static void *IICCON;
static void *IICDS;
static void *IICADD;
static void *IICLC;

#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_iic_dir, devfs_iicraw;
#endif

#define SKQ_IIC_MODULE_NAME        "IICBUS"
/*60--63,120--127,240--254*/
#define IICBUS_MAJOR        240
#define IICBUSRAW_MINOR 1

#define IICBUS_INT IRQ_IIC

static char *IICBUD_id = "SKQ IICBUS driver v1.0 (2005-06-02)<psc@hualiangtech.com>";

/* debug macros */
#undef DEBUG
//#define DEBUG
#ifdef DEBUG
#define DPRINTK( x... )            printk("SKQ IICBUS: "##x)
#else
#define DPRINTK( x... )
#endif

#define WRDATA                (1)
#define POLLACK                (2)
#define RDDATA                (3)
#define SETRDADDR        (4)

#define IICBUFSIZE 2048

char IICBUS_Buf[IICBUFSIZE];

static int opencount=0;
static int tsMajor=0;
static loff_t newpos=0;
int writenFM24CL16(char * buffer, size_t count, int address)
{
unsigned long timeo;
u16 i;
u16 PageAdd;
char slvAddr, tpICON,tempIICSTAT;
IICCON=(1<<7)|(0<<6)|(1<<5)|(0xf);
IICSTAT=0x10;

slvAddr=0xa0;
PageAdd=address;
/*  send the bit of start and address of device and page of address */
PageAdd>>7;
PageAdd&=0x0e;
slvAddr=(char)PageAdd;
slvAddr|=0xa0;
IICDS=slvAddr;  //0xa0
IICSTAT=0xf0;   //MasTx,Start

timeo = jiffies + (HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;        /* pending */
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;        /* ack */
if((tpICON==0x10))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf; /*pending */

IICDS=(char)address;  //0xa0
timeo = jiffies +(HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;
if((tpICON==0x10)) break;  // &&tempIICSTAT==0x00)
if(time_after(jiffies,timeo))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf;

for(i=0;i<count;i++)
{
IICDS=buffer;
timeo=jiffies + (HZ/100);
while(1)
{
tpICON=IICCON;
tpICON&=0x10;
tempIICSTAT=IICSTAT;
tempIICSTAT&=0x01;
if((tpICON==0x10)&&(tempIICSTAT==0x00)) break;
if(time_after(jiffies,timeo))
{
IICSTAT=0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return -1;
}
};
IICCON=0xaf;  /* clr pending */
}
IICSTAT =0xd0;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;
return count;
}

int ReadFM24CL16(char *buffer, size_t count, int address)
{
unsigned long timeo;
u16 i;
u8 slvAddr ,tpICON,tempIICSTAT;
u16 PageAdd;
PageAdd=address;
/* 发送起始位和设备地址和页地址 */
PageAdd>>=7;
PageAdd&=0x0e;
slvAddr=(char )PageAdd;
slvAddr|=0xa0;
IICDS=slvAddr;  //0xa0;
IICSTAT=0Xf0;   //MasTx,Start
timeo = jiffies +(HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        // tempIICSTAT=rIICSTAT;
        //tempEECSTAT&=0x01;
        if((tpICON==0x10)) break;  //&&(tempIICSTAT==0x00)
        if(time_after(jiffies,timeo))
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;
/* 发送地址低8位 */
IICDS=(char)address;
timeo = jiffies + (HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        tempIICSTAT=IICSTAT;
        tempIICSTAT&=0X01;
        if((tpICON==0x01)) break;  //&&(tempIICSTAT==0x00)
        if(time_after(jiffies, timeo))
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;
//IICSTAT&=0xef;
/* 发送起始位和设备地址和页地址 */
PageAdd>>=7;
PageAdd&=0x0e;
slvAddr=(char )PageAdd;
slvAddr|=0xa1;
IICDS=slvAddr;
IICSTAT=0xb0;  //MasRx,Start
timeo = jiffies +(HZ/100);
while(1){
        tpICON=IICCON;
        tpICON&=0x10;
        tempIICSTAT=IICSTAT;
        tempIICSTAT&=0x01;
        if((tpICON==0x10)) break; // &&(tempIICSTAT==0x00)
        {
                IICSTAT=0x90;
                IICCON=0xaf;
                udelay(200);
                IICCON=0xaf;
                IICSTAT=0x10;
                return -1;
        }
};
IICCON=0xaf;

for(i=0;i<count;i++)
{
        IICDS=slvAddr;
        //timeo =jiffies +(HZ/100);
        while(1){
                tpICON=IICCON;
                tpICON&=0x10;
                tempIICSTAT=IICSTAT;
                tempIICSTAT&=0x01;
                if((tpICON==0x10)) break ;//(tempIICSTAT==0x00)
                //else
                //        {
                //        if((tpICON==0x10)&&(i==count-1))break;
                //        }
                if(time_after(jiffies, timeo))
                {
                        IICSTAT=0x90;
                        IICCON=0xaf;
                        udelay(200);
                        IICCON=0xaf;
                        IICSTAT=0x10;
                        IICSTAT=0x10;
                        return -1;
                }
        };
        buffer=IICDS;
        if(i==count-1) IICCON=0x2f;
        else IICCON=0xaf;
}

IICSTAT=0x90;
IICCON=0xaf;
udelay(200);
IICCON=0xaf;
IICSTAT=0x10;

return count;
}

loff_t  IICBUS_llseek(struct file *filp, loff_t off,int whence)
{
        switch(whence){
        case 0 :        /* SEEK_SET */
                newpos=off;
                break;
        default:        /* cant,t happen */
                return -EINVAL;
        }
        if(newpos<0) return -EINVAL;
        return newpos;
}

static ssize_t IICBUS_write(struct file *file,const char *buffer,size_t count, loff_t *ppos)
{
        int ret;
        int address=(int)newpos;
        if(count>204 return 0;
        // copy_from_user(&address,ppos, sizeof(loff_t));
        // address=(int)*ppos;
        // printk("IICBUS_write address=%ld\n",address);
        if(address+count>204 return 0;
        copy_from_user(IICBUS_Buf, count, address);
        return ret;
}
static ssize_t IICBUS_read(struct file *filp,char *buffer,size_t count, loff_t *ppos)
{
        int len;
        int address=(int)newpos;
        //int address1;
        if(count>204 return 0;
        //copy_from_user(&address,ppos, sizeof(loff_t));
        //address=(int)*ppos;
        //printk("IICBUS_read address=%d\n",address);
        if(address+count>204 return 0;
        //address1=(int)*ppos;
        //printk("IICBUS_read address1=%ld\n",address);
        //printk("IICBUS_read ppos=%ld\n",ppos);
        len=ReadFM24CL16(IICBUS_Buf,count,address);
        copy_to_user(buffer,IICBUS_Buf,len);
        DPRINTK("read data=%d\n",data);
        return len;
}

static int IICBUS_open(struct inode *inode, struct file *file)
{
        //if(opencount==1)
        //return -EBUSY;
        opencount++;
       try_module_get(THIS_MODULE);        //MOD_INC_USE_COUNT;
        DPRINTK("device open\n";
        return 0;
}

static int IICBUS_release(struct inode *inode, struct file *filp)
{
        opencount--;
        module_put(THIS_MODULE);   //MOD_DEC_USE_COUNT;
        DPRINTK("device release\n";
        return 0;
}
static struct file_operations s3c44b0_iicbus_fops ={
owner:        THIS_MODULE,
llseek:        IICBUS_llseek,
write:        IICBUS_write,
read:        IICBUS_read,
open:        IICBUS_open,
release:        IICBUS_release,
};

static int __init IICBUS_init(void)
{

s3c2410_gpio_cfgpin(S3C2410_GPB(14),S3C2410_GPE14_IICSCL);
s3c2410_gpio_cfgpin(S3C2410_GPB(15),S3C2410_GPE15_IICSDA);

IICCON=ioremap(iiccon,0x00000004);
IICSTAT=ioremap(iicstat,0x00000004);
IICDS=ioremap(iicds,0x00000004);
IICADD=ioremap(iicadd,0x00000004);
IICLC=ioremap(iicl,0X00000004);

        int ret;
        int flags;
        //local_irq_save(flags);
        /* port F */
                /* Bit8                 7         6        5        4        3        2       
                     SPICKL            SPIMISO        SPICS        SPIMOSI        INCARD2        NC        NC */
             //        PCONF |=0x0a;        //PF0:IICSCL,PF1:IICSDA
               //      PUPF |=0x03;        //pull-up disable
                     IICCON=(1<<7)|(0<<6)|(0<<5)|(0xf);
                     //Enable interrupt,IICCLK=MCKL/16,Enable ACK
                     //40Mhz/16/(15+1)=257khz
                     IICADD=0x10;  //s3c44B0X slave address
                     IICSTAT=0X10;
                     local_irq_restore(flags);
                     opencount=0;
                     ret = register_chrdev(IICBUS_MAJOR, SKQ_IIC_MODULE_NAME,&s3c44b0_iicbus_fops);
                     if (ret<0)
                     {
                     printk( ":can't get major number\n",__FUNCTION__);      
                     return -1;
                     }
                     tsMajor=ret;
                     #if 0
                     if(0 !=request_irq(IICBUS_INT,IICBUS_isr,SA_INTERRUPT,IICBUD_ID,NULL))
                     {
                                  printk(KERN_WARNING "tce44b0_usb:failed to get IRQ\n";
                                  return 1;
                     }
                     #endif
                     #ifdef CONFIG_DEVFS_FS
                                     devfs_iic_dir = devfs_mkdir(NULL,SKQ_IIC_MODULE_NAME,NULL);
                                     devfs_iicraw = devfs_register(devfs_iic_dir, "0",DEVFS_FL_DEFAULT,
                                             tsMajor,IICBUSRAW_MINOR,S_IFCHR | S_IRUSR | S_IWUSR,
                                             &s3c44b0_iicbus_fops,NULL);
                     #endif
                                     printk(SKQ_IIC_MODULE_NAME " initialized\n";
                                     return 0;
}

static void __exit IICBUS_exit(void)
{
        printk(":SKQ IIC Exit.\n",__FUNCTION__);
//        free_irq(IICBUS_INT, IICBUD_id);
         unregister_chrdev_region(IICBUS_MAJOR,1);
}

module_init(IICBUS_init);
module_exit(IICBUS_exit);
MODULE_DESCRIPTION("SKQ IIC driver";
MODULE_AUTHOR("pengshicao ";
MODULE_LICENSE("GPL";

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文