FM3130铁电存储器 linux驱动程序

发布于 2022-10-15 06:44:06 字数 19973 浏览 25 评论 0

这里面有一个函数但不知是如何定义的
extern int GM_i2c_xfer(struct i2c_msg *msgs, int num, int clockdiv);

在linux内核里根本就找不到,网络上也搜不到,请问它是如何定义的,实现一些什么功能呢?

请各位大侠帮忙呀!!O(∩_∩)O~

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
#include <asm/bitops.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/rtc.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/slab.h>
#define        DRIVER_VERSION                "0.01"

/* Register map */
/* rtc section */
#define REG_CNTL        0x00
#define REG_CAL            0x01
#define REG_WP                0x0e
/*mem */
#define MEM_RW                0x0000
#define MEM_LEN        8192
#define FM3130_MINOR 10

/* i2c configuration */
#define I2C_ADDR 0xd0
#define MEM_ADDR 0xa0

/*for APB 108MHz*/
#define DEFAULT_I2C_CLOCKDIV        180

MODULE_AUTHOR("GM Corp.";
MODULE_LICENSE("GM License";

extern int GM_i2c_xfer(struct i2c_msg *msgs, int num, int clockdiv);

/* block read */
static int i2c_read_regs(u8 reg, u8 buf[], unsigned len)
{       
        struct i2c_msg msgs[1];

        buf[0] = reg;
            msgs[0].addr = I2C_ADDR>>1;
            msgs[0].flags = 0;
            msgs[0].len = 1;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                return -1;
       
            msgs[0].addr = I2C_ADDR>>1;
            msgs[0].flags = 1;
            msgs[0].len = len+1;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                return -1;
        return 0;       
}

/* block write */
static int i2c_set_regs(u8 reg, u8 const buf[], unsigned len)
{
        u8 i2c_buf[32];
        struct i2c_msg msgs[1];

        i2c_buf[0] = reg;
        memcpy(&i2c_buf[1], &buf[0], len);   
            msgs[0].addr = I2C_ADDR>>1;
            msgs[0].flags = 0;
            msgs[0].len = len+1;
            msgs[0].buf = i2c_buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                return -1;
        return 0;       
}

//--------------------------------------存储器操作------------------------------------//
/* block read */
static int i2c_read_mem(u16 reg, u8 buf[], int len)
{
        struct i2c_msg msgs[1];

        if(len<0 ||len>MEM_LEN)
        {
                printk("Error:The number of reading for the memory is wrong!\n";
                return -1;
        }

        buf[0] = (reg>>&0xff;
        buf[1] = reg&0xff;
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags = 0;
            msgs[0].len = 2;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                return -1;
       
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags = 1;
            msgs[0].len = len+2;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                return -1;
        return 0;       
}
/* block write */
static int i2c_set_mem(u16 reg, u8 const buf[], int len)
{
        u8 *i2c_buf;
        struct i2c_msg msgs[1];

        if(len<=0 ||len>MEM_LEN)
        {
                printk("Error:The number of seting for the memory is wrong!\n";
                return -1;
        }
        i2c_buf=kmalloc(sizeof(u*len,GFP_KERNEL);
        if(NULL==i2c_buf)
        {
                printk("Error:while kmalloc for the MEM!\n";
                return -1;
        }
        memset(i2c_buf,0,sizeof(u*len);
       
        i2c_buf[0] =( reg >> 8 ) & 0xff;
        i2c_buf[1] =reg & 0xff;
        memcpy(&i2c_buf[2], &buf[0], sizeof(u*len);  
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags =0;
            msgs[0].len = len+2;
            msgs[0].buf = i2c_buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
            {
                if(NULL!=i2c_buf)
                        kfree(i2c_buf);
                return -1;
            }
        if(NULL!=i2c_buf)
                kfree(i2c_buf);
        return 0;       
}

/*ijsung: arch-indep function*/
static int FM3130_open(struct inode *inode, struct file *file)
{
        printk("Open file success!\n";
        return 0;
}

static int FM3130_release(struct inode *inode, struct file *file)
{               
        return 0;
}

ssize_t FM3130_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
        int sr;
        u8 regs[1] = { 0, };
        u8 *buffer=NULL;

        if(count<=0||count>MEM_LEN)
        {
                printk("Error:read num is wrong!\n";
                return -1;
        }
        buffer=kmalloc(sizeof(u*count,GFP_KERNEL);
        if(NULL==buffer)
        {
                printk("Error:while kmalloc for the buffer!\n";
                return -1;
        }
        memset(buffer,0,sizeof(u*count);
        sr=i2c_read_mem(MEM_RW, buffer, count);
        if (sr < 0)
        {
                printk("%s: reading mem  failed\n",__func__);
                return sr;
        }
        if(copy_to_user ((void *)buf, buffer, sizeof(u*count))
        {
                printk("Error:read count is not you want!\n";
                if(NULL!=buffer)
                        kfree(buffer);
                return -EFAULT;
        }
        if(NULL!=buffer)
                kfree(buffer);
        return 0;
       
}

ssize_t FM3130_write(struct file *file, char *buf, size_t count, loff_t *ppos)
{
        int sr;
        u8 regs[1] = { 0, };
        u8 *buffer=NULL;       

        if(count<=0||count>MEM_LEN)
        {
                printk("Error:read num is wrong!\n";
                return -1;
        }
        buffer=kmalloc(sizeof(u*count,GFP_KERNEL);
        if(NULL==buffer)
        {
                printk("Error:while kmalloc for the buffer!\n");
                return -1;
        }
        memset(buffer,0,sizeof(u*count);
        regs[0]=0x80;
        sr=i2c_set_regs(REG_WP, regs, 1);                                                //存储器去除保护
        if (sr < 0)
        {
                printk("%s: writing RTC section failed\n",__func__);
               return sr;
        }
        if (copy_from_user(buffer,(u8*)buf, sizeof(u*count))
        {
                printk("Error:write count is not you want!\n");
                if(NULL!=buffer)
                        kfree(buffer);
                return -EFAULT;       
        }
                               
        sr=i2c_set_mem(MEM_RW, buffer, count);
        if (sr < 0)
        {
                printk("%s: writing RTC section failed\n",__func__);
                if(NULL!=buffer)
                        kfree(buffer);
                return sr;
        }
        regs[0]=0x18;
        sr=i2c_set_regs(REG_WP, regs, 1);                                                //存储器写保护
        if (sr < 0)
        {
                printk("%s: writing RTC section failed\n",__func__);
                if(NULL!=buffer)
                        kfree(buffer);
                return sr;
        }
        if(NULL!=buffer)
                kfree(buffer);
        return 0;

}

static struct file_operations FM3130_fops = {
        owner:        THIS_MODULE,
        read:        FM3130_read,
        write:        FM3130_write,       
        open:        FM3130_open,
        release:        FM3130_release,
};

static struct miscdevice ftrtc010rtc_miscdev = {
        FM3130_MINOR,
        "FM3130",
        &FM3130_fops
};

static int FM3130_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
{       
        int len;
        char *p = page;       
        len = (p - page) - off;
        if (len < 0)
                len = 0;
        *eof = (len <= count) ? 1 : 0;
        *start = page + off;
        return len;
}

static int __init FM3130_init(void)
{
        int ret;
        u8 regs[1]={0};

        printk("FM3130 adjustment\n");
        misc_register (&ftrtc010rtc_miscdev);
        create_proc_read_entry ("driver/FM3130", 0, 0, FM3130_read_proc, NULL);       
        //--------------------------波形选择为方波--------------------------//
        regs[0]=0x80;
        ret=i2c_set_regs(REG_WP, regs, 1);
        if(ret<0)
        {
                printk("%s: writing RTC section failed\n",__func__);
                return ret;
        }
        //--------------------------------------------------------------------------//
        printk("FM3130  driver\n");       
        return 0;
}

static void __exit FM3130_exit(void)
{
        remove_proc_entry ("driver/FM3130", NULL);
        misc_deregister (&ftrtc010rtc_miscdev);
}
module_init(FM3130_init);
module_exit(FM3130_exit);

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

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

发布评论

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

评论(1

不奢求什么 2022-10-22 06:44:06

i2c_transfer

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