📄 bq27500.c
字号:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <asm/arch/gpio.h>
#include <bq27500.h>
#include "zydz_drv.h"
//#define I2CADDR 0x64
#define I2CADDR 0xD0
#define BQ_TWD AT91_PIN_PA23
#define BQ_TWCK AT91_PIN_PA24
static void I2cTwdOut(int va)
{
at91_set_gpio_output(BQ_TWD,va);
}
static void I2cTwckOut(int va)
{
at91_set_gpio_output(BQ_TWCK,va);
}
int I2cTwdRead(void)
{
gpio_direction_input(BQ_TWD);
return at91_get_gpio_value(BQ_TWD);
}
static int DelayMulti=1;
static void Delay(int k)
{
k*=DelayMulti;
udelay(k);
}
static void I2cClk(void)
{
Delay(2);
I2cTwckOut(1);//scl=1
Delay(2);
I2cTwckOut(0);//scl=0
Delay(2);
}
static void I2cStart(void)
{
I2cTwckOut(1);//scl=1
Delay(2);
I2cTwdOut(1);//sda=1
Delay(2);
I2cTwdOut(0);//sda=0
Delay(2);
}
void I2cStop(void)
{
Delay(2);
I2cTwdOut(0);//sda=0
Delay(2);
I2cTwckOut(1);//scl=1
Delay(5);
I2cTwdOut(1);//sda=1
Delay(5);
}
unsigned char I2Senddata(unsigned char data)
{
unsigned char r,count;
unsigned char data0=data;
I2cTwckOut(0);//scl=0
Delay(1);
for(count=0;count<8;count++)
{
if(data&0x80)
I2cTwdOut(1);//sda=1
else
I2cTwdOut(0);//sda=0
I2cClk();
data<<=1;
}
I2cTwdRead();//sda:input
Delay(2);
I2cTwckOut(1);//scl=1
Delay(2);
r=I2cTwdRead();
Delay(2);
I2cTwckOut(0);//scl=0
Delay(1);
//printk("===>%s:data=0x%x,r=0x%x\n",__FUNCTION__,data0,r);
return r;
}
unsigned char I2cReceiveData(void)
{
unsigned char count, temp,value=0;
I2cTwdOut(1);//sda=1
Delay(2);
I2cTwckOut(0);//scl=0
Delay(2);
for(count=0;count<8;count++)
{
I2cTwckOut(1);//scl=1
Delay(2);
value <<= 1;
Delay(3);
if(at91_get_gpio_value(BQ_TWD))value++;
I2cTwckOut(0);//scl=0
Delay(2);
}
I2cTwdOut(0);//sda=0
Delay(2);
I2cTwckOut(1);//scl=1
Delay(2);
I2cTwckOut(0);//scl=0
Delay(2);
I2cTwdOut(1);//sda=1
Delay(2);
return value;
}
static DECLARE_MUTEX(rtc_sem);
static void bq27500RegSet(int adr,int *va,int num)
{
int r;
unsigned long flags;
local_irq_save(flags);
down(&rtc_sem);
I2cStart();
I2Senddata(I2CADDR); //send base
//r=I2Senddata((adr<<4)|0x0); //send off base
r=I2Senddata(adr); //send off base
while(num)
{
//printk("==>%s,adr=%d,va=0x%x,num=%d,r=%d\n",__FUNCTION__,adr,*va,num,r);
I2Senddata(*va);
if(num>0){va++;num--;}
else {va--;num++;}
}
I2cStop();
up(&rtc_sem);
local_irq_restore(flags);
}
static unsigned char bq27500RegGet(int adr,int *va,int num)
{
unsigned char r,sec,min,hour;
unsigned long flags;
//local_irq_save(flags);
down(&rtc_sem);
I2cStart();
I2Senddata(0x64); //send base
I2Senddata((adr<<4)|0x0); //send off base
I2cStart();
r=I2Senddata(0x65); //set read
while(!r&&num)
{
*va=I2cReceiveData();
if(*va==0xFF){r=-1;break;}
if(num>0){va++;num--;}
else {va--;num++;}
}
I2cStop();
up(&rtc_sem);
//local_irq_restore(flags);
udelay(100);
//r!=0:取回的数据不对
return r;
}
void Init_BQ(void)
{
unsigned char temp=0;
I2cStart();
#ifdef bq27500
I2Senddata(I2CADDR); //发送从地址0xd0
I2Senddata(0xe0); //发送偏移地址
temp = 0x23;
#else
I2Senddata(I2CADDR); //发送从地址
I2Senddata(0x0e);
temp &= 0xc3;
#endif
I2Senddata(temp);
I2cStop();
Delay(20);
return;
}
int DS8025GetTime(struct rtc_time *tm)
{
int reg_e;
unsigned char va;
unsigned long flags;
//local_irq_saveflags();
down(&rtc_sem);
I2cStart();
//printk("\n===>%s\n",__FUNCTION__);
if(I2Senddata(I2CADDR))goto GetErr;//send base
if(I2Senddata(0))goto GetErr;//send off base
I2cStart();
if(I2Senddata(I2CADDR|0x1))goto GetErr;//set read
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_sec=BcdToBin(va&0x7f);
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_min=BcdToBin(va&0x7f);
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_hour=BcdToBin(va&0x3f);
if((va=I2cReceiveData())==0xFF)goto GetErr;
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_mday=BcdToBin(va&0x3f);
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_mon=BcdToBin(va);
if((va=I2cReceiveData())==0xFF)goto GetErr;
tm->tm_year=BcdToBin(va);
I2cStop();
up(&rtc_sem);
return 0;
GetErr:
I2cStop();
up(&rtc_sem);
//local_irq_restore(flags);
//r!=0:取回的时间不对
return -1;
}
#include "zydz_drv.h"
int PwrSubcmdInit(int cmd_main,int cmd_sub)
{
int r;
//unsigned long flags;
//local_irq_save(flags);
I2cStart();
if((r=I2Senddata(0xAA)))
{r=-1;goto cmdInit_end;}
if((r=I2Senddata(cmd_main)))
{r=-2;goto cmdInit_end;}
if((r=I2Senddata(cmd_sub)))
{r=-3;goto cmdInit_end;}
if((r=I2Senddata(cmd_sub>>8)))
{r=-4;goto cmdInit_end;}
cmdInit_end:
I2cStop();
//local_irq_restore(flags);
return r;
}
unsigned long PwrRead(void)
{
int r;
//unsigned long flags;
DelayMulti=50;
I2cStop();
//Delay(10);
//r=PwrSubcmdInit(0x0,0x0002);
//printk("===>%s:r=%d\n",__FUNCTION__,r);
//local_irq_save(flags);
I2cStart();
if(I2Senddata(0xAA))
{
err:
I2cStop();
return -1;
}
if(I2Senddata(0x08))
goto err;
I2cStart();
if(I2Senddata(0xAB))
goto err;
r=I2cReceiveData();
r=(I2cReceiveData()<<8)+r;
I2cStop();
//local_irq_restore(flags);
DelayMulti=1;
return r;
}
long zydz_rtc8025_callback(unsigned long cmd,unsigned long arg1,unsigned long arg2,unsigned long arg3)
{
long r=0;
if(cmd==ZYDZDRVCMD_RTCGET)
{
struct rtc_time tm;
struct TimeStruct *pa=(struct TimeStruct*)arg1;
r=DS8025GetTime(&tm);
pa->Second=tm.tm_sec;
pa->Minute=tm.tm_min;
pa->Hour=tm.tm_hour;
pa->Day=tm.tm_mday;
pa->Month=tm.tm_mon;
pa->Year=tm.tm_year+2000;
}
else if(cmd==ZYDZDRVCMD_RTCREGSET)
{
DS8025RegSet(arg1,(int *)arg2,arg3);
}
else if(cmd==ZYDZDRVCMD_RTCREGGET)
{
r=DS8025RegGet(arg1,(int *)arg2,arg3);
}
else if(cmd==ZYDZDRVCMD_PWRGET)
{
return PwrRead();
}
return r;
}
static int __init zydz_bq27500_init(void)
{
drv_zydz_register(ZYDZDRVID_RTC,zydz_rtc8025_callback);
at91_set_gpio_output(RTC_TWCK,0);
at91_set_multi_drive(RTC_TWCK,1);
at91_set_gpio_output(RTC_TWD,0);
at91_set_multi_drive(RTC_TWD,1);
Delay(50);
I2cStop();
{
#if 0
int i,reg_e;
for(i=0;i<10;i++)
{
reg_e=0x20;//24-hour
DS8025RegSet(0xe,®_e,1);
DS8025RegGet(0xe,®_e,1);
if(reg_e&0x20)break;
udelay(500);
}
#endif
}
PwrRead();
Init_RTC();
if(0)
{
struct timespec tv;
struct rtc_time tm;
DS8025GetTime(&tm);
rtc_tm_to_time(&tm, &tv.tv_sec);
printk("%s:setting the system clock to "
"%d-%02d-%02d %02d:%02d:%02d (%u)\n",__FUNCTION__,
tm.tm_year + 2000, tm.tm_mon , tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec);
}
return 0;
}
module_init(zydz_bq27500_init);
static void __exit zydz_bq27500_exit(void)
{
drv_zydz_unregister(ZYDZDRVID_bq);
}
module_exit(zydz_bq27500_exit);
MODULE_DESCRIPTION("Zydz bq27500 driver");
MODULE_AUTHOR("xiezhixin <xzx_wh@263.net>");
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -