FM3130铁电存储器 linux驱动程序
这里面有一个函数但不知是如何定义的
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
i2c_transfer