/******************************************************************************
Copyright (C), 2003-1013, Whayer. Co., Ltd
文件名 ds1339_drv.c.c
作 者: shenwenjun
email : swj@whayer.com
版 本: 1.00
日 期: 2013-8-15
描 述: ds1339 RTC读取与设置功能
历史修改记录 <作者> <时间> <版本> <描述>
shenwenjun 2013-8-15 1.00 创建
******************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
//#include <linux/rtc.h>
#include <asm/atomic.h>
#include "ds1339_drv.h"
#include "gpio_i2c.h"
/* ds1339的I2C地址 */
const static int g_ds1339_i2c_addr = 0xd0;
static atomic_t g_open_cnt = ATOMIC_INIT(1);
static DEFINE_MUTEX(g_rtc_mutex);
extern unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address);
extern void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char value);
/************************************************************
函数名称: ds1339_get_time
描述 : Get the current time from the RTC
调用函数:
被调函数:
输入参数: DS1339_RTC_TIME_S *ds1339_rtc_time
输出参数: 无
返回值: 无
历史修改记录 <作者> <时间> <描述>
shenwenjun 2013-8-16 创建
***********************************************************/
static void ds1339_get_time(DS1339_RTC_TIME_S *ds1339_rtc_time)
{
unsigned char sec = 0, min = 0, hour = 0, day = 0, week = 0, cent_mon = 0, year = 0, status = 0;
mutex_lock(&g_rtc_mutex);
status = gpio_i2c_read(g_ds1339_i2c_addr, RTC_STAT_REG_ADDR);
sec = gpio_i2c_read(g_ds1339_i2c_addr, RTC_SEC_REG_ADDR);
min = gpio_i2c_read(g_ds1339_i2c_addr, RTC_MIN_REG_ADDR);
hour = gpio_i2c_read(g_ds1339_i2c_addr, RTC_HR_REG_ADDR);
week = gpio_i2c_read(g_ds1339_i2c_addr, RTC_WEEK_REG_ADDR);
day = gpio_i2c_read(g_ds1339_i2c_addr, RTC_DAY_REG_ADDR);
cent_mon = gpio_i2c_read(g_ds1339_i2c_addr, RTC_MON_REG_ADDR);
year = gpio_i2c_read(g_ds1339_i2c_addr, RTC_YR_REG_ADDR);
/*ds1339_dbg("Get RTC year: %02x mon/cent: %02x day: %02x week: %02x "
"hr: %02x min: %02x sec: %02x status: %02x\n",
year, cent_mon, day, week, hour, min, sec, status);*/
if (status & RTC_STAT_BIT_OSF)
{
ds1339_dbg ("DS1339 RTC oscillator has stopped\n");
/* clear the OSF flag */
status &= ~RTC_STAT_BIT_OSF;
gpio_i2c_write(g_ds1339_i2c_addr, RTC_STAT_REG_ADDR, status);
}
ds1339_rtc_time->second = BCD_TO_BIN(sec & 0x7F);
ds1339_rtc_time->minute = BCD_TO_BIN (min & 0x7F);
ds1339_rtc_time->hour = BCD_TO_BIN (hour & 0x3F);
ds1339_rtc_time->day = BCD_TO_BIN (day & 0x3F);
ds1339_rtc_time->month = BCD_TO_BIN (cent_mon & 0x1F);
ds1339_rtc_time->year = BCD_TO_BIN (year) + ((cent_mon & 0x80) ? 2000 : 1900);
ds1339_rtc_time->week = BCD_TO_BIN (week & 0x07);
/*ds1339_dbg( "RTC: %4d-%02d-%02d (week:%02d) %02d:%02d:%02d UTC\n",
ds1339_rtc_time->year, ds1339_rtc_time->month, ds1339_rtc_time->day,
ds1339_rtc_time->week, ds1339_rtc_time->hour, ds1339_rtc_time->minute,
ds1339_rtc_time->second);*/
mutex_unlock(&g_rtc_mutex);
return;
}
/************************************************************
函数名称: ds1339_set_time
描述 : Set the current time to the RTC
调用函数:
被调函数:
输入参数: DS1339_RTC_TIME_S *ds1339_rtc_time
输出参数: 无
返回值: 无
历史修改记录 <作者> <时间> <描述>
shenwenjun 2013-8-16 创建
***********************************************************/
static void ds1339_set_time(DS1339_RTC_TIME_S *ds1339_rtc_time)
{
unsigned char century = 0, status = 0;;
mutex_lock(&g_rtc_mutex);
ds1339_dbg( "Set DATE:: %4d-%02d-%02d (week:%02d) %02d:%02d:%02d UTC\n",
ds1339_rtc_time->year, ds1339_rtc_time->month, ds1339_rtc_time->day,
ds1339_rtc_time->week, ds1339_rtc_time->hour, ds1339_rtc_time->minute,
ds1339_rtc_time->second);
status = gpio_i2c_read(g_ds1339_i2c_addr,RTC_STAT_REG_ADDR);
if (status & RTC_STAT_BIT_OSF)
{
ds1339_dbg ("DS1339 RTC oscillator has stopped\n");
/* clear the OSF flag */
status &= ~RTC_STAT_BIT_OSF;
gpio_i2c_write(g_ds1339_i2c_addr, RTC_STAT_REG_ADDR, status);
}
gpio_i2c_write(g_ds1339_i2c_addr, RTC_YR_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->year % 100));
century = (ds1339_rtc_time->year >= 2000) ? 0x80 : 0;
gpio_i2c_write(g_ds1339_i2c_addr, RTC_MON_REG_ADDR, (BIN_TO_BCD(ds1339_rtc_time->month) | century));
if (BIN_TO_BCD(ds1339_rtc_time->week) & 0x07)
{
gpio_i2c_write(g_ds1339_i2c_addr, RTC_WEEK_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->week));
}
gpio_i2c_write(g_ds1339_i2c_addr, RTC_DAY_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->day));
gpio_i2c_write(g_ds1339_i2c_addr, RTC_HR_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->hour));
gpio_i2c_write(g_ds1339_i2c_addr, RTC_MIN_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->minute));
gpio_i2c_write(g_ds1339_i2c_addr, RTC_SEC_REG_ADDR, BIN_TO_BCD(ds1339_rtc_time->second));
mutex_unlock(&g_rtc_mutex);
return;
}
/************************************************************
函数名称: ds1339_reset_time
描述 : Reset the current time
调用函数:
被调函数:
输入参数: 无
输出参数: 无
返回值: 无
历史修改记录 <作者> <时间> <描述>
shenwenjun 2013-8-16 创建
***********************************************************/
static void ds1339_reset_time(void)
{
// DS1339_RTC_TIME_S ds1339_rtc_time = {};
unsigned char status = 0;
unsigned char control = 0;
/* clear the OSF flag */
status = gpio_i2c_read(g_ds1339_i2c_addr, RTC_STAT_REG_ADDR);
status &= ~RTC_STAT_BIT_OSF;
gpio_i2c_write(g_ds1339_i2c_addr, RTC_STAT_REG_ADDR, status);
/* 使能晶振 */
control = gpio_i2c_read(g_ds1339_i2c_addr, RTC_CTL_REG_ADDR);
control &= ~RTC_CTL_BIT_DOSC;
gpio_i2c_write(g_ds1339_i2c_addr, RTC_CTL_REG_ADDR, control);
/* 涓流充电设置 */
gpio_i2c_write(g_ds1339_i2c_addr, RTC_CHARGER_REG_ADDR, RTC_CHARGER_DIODE_2K);
#if 0
/* 初始化时间 */
ds1339_rtc_time.second = 18;
ds1339_rtc_time.minute = 16;
ds1339_rtc_time.hour = 10;
ds1339_rtc_time.day = 13;
ds1339_rtc_time.week = 6;
ds1339_rtc_time.month = 10;
ds1339_rtc_time.year = 2012;
ds1339_set_time(&ds1339_rtc_time);
ds1339_dbg( "RTC: %4d-%02d-%02d (week:%02d) %02d:%02d:%02d UTC\n",
ds1339_rtc_time.year, ds1339_rtc_time.month, ds1339_rtc_time.day,
ds1339_rtc_time.week, ds1339_rtc_time.hour, ds1339_rtc_time.minute,
ds1339_rtc_time.second);
#endif
return;
}
/************************************************************
函数名称: ds1339_open
描述 : device open. set counter
调用函数:
被调函数:
输入参数: struct inode *inode
struct file *file
输出参数: 无
返回值: 无
历史修改记录 <作者> <时间> <描述>
shenwenjun 2013-8-16 创建
***********************************************************/
static int ds1339_open(struct inode *inode, struct file *file)
{
UNUSED(inode);
UNUSED(file);
if (!atomic_dec_and_test(&g_open_cnt))
{
atomic_inc(&g_open_cnt);
ds1339_dbg("/dev/ds1339 is busy!");
return -EBUSY;
}
return 0;
}
/************************************************************
函数名称: ds1339_close
描述 : Close device, Do nothing!
调用函数:
被调函数:
输入参数: struct inode *inode
struct file *file
输出参数: 无
返回值: 无
历史修改记录 <作者> <时间> <描述>
shenwenjun 2013-8-16 创建
***********************************************************/
static int ds1339_close(struct inode *inode , struct file *file)
{
UNUSED(inode);
UNUSED(file);
atomic_inc(&g_open_cnt);
return 0;
}
/*******************************