⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bq27500.c

📁 bq27500电源控制管理 bq7500德州仪器监测电源剩余电量的最新芯片
💻 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,&reg_e,1);
			DS8025RegGet(0xe,&reg_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 + -