Path: blob/master/arch/cris/arch-v10/drivers/pcf8563.c
15126 views
/*1* PCF8563 RTC2*3* From Phillips' datasheet:4*5* The PCF8563 is a CMOS real-time clock/calendar optimized for low power6* consumption. A programmable clock output, interrupt output and voltage7* low detector are also provided. All address and data are transferred8* serially via two-line bidirectional I2C-bus. Maximum bus speed is9* 400 kbits/s. The built-in word address register is incremented10* automatically after each written or read byte.11*12* Copyright (c) 2002-2007, Axis Communications AB13* All rights reserved.14*15* Author: Tobias Anderberg <[email protected]>.16*17*/1819#include <linux/module.h>20#include <linux/kernel.h>21#include <linux/types.h>22#include <linux/sched.h>23#include <linux/init.h>24#include <linux/fs.h>25#include <linux/ioctl.h>26#include <linux/delay.h>27#include <linux/bcd.h>28#include <linux/mutex.h>2930#include <asm/uaccess.h>31#include <asm/system.h>32#include <asm/io.h>33#include <asm/rtc.h>3435#include "i2c.h"3637#define PCF8563_MAJOR 121 /* Local major number. */38#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */39#define PCF8563_NAME "PCF8563"40#define DRIVER_VERSION "$Revision: 1.24 $"4142/* I2C bus slave registers. */43#define RTC_I2C_READ 0xa344#define RTC_I2C_WRITE 0xa24546/* Two simple wrapper macros, saves a few keystrokes. */47#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)48#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)4950static DEFINE_MUTEX(pcf8563_mutex);51static DEFINE_MUTEX(rtc_lock); /* Protect state etc */5253static const unsigned char days_in_month[] =54{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };5556static long pcf8563_unlocked_ioctl(struct file *, unsigned int, unsigned long);5758/* Cache VL bit value read at driver init since writing the RTC_SECOND59* register clears the VL status.60*/61static int voltage_low;6263static const struct file_operations pcf8563_fops = {64.owner = THIS_MODULE,65.unlocked_ioctl = pcf8563_unlocked_ioctl,66.llseek = noop_llseek,67};6869unsigned char70pcf8563_readreg(int reg)71{72unsigned char res = rtc_read(reg);7374/* The PCF8563 does not return 0 for unimplemented bits. */75switch (reg) {76case RTC_SECONDS:77case RTC_MINUTES:78res &= 0x7F;79break;80case RTC_HOURS:81case RTC_DAY_OF_MONTH:82res &= 0x3F;83break;84case RTC_WEEKDAY:85res &= 0x07;86break;87case RTC_MONTH:88res &= 0x1F;89break;90case RTC_CONTROL1:91res &= 0xA8;92break;93case RTC_CONTROL2:94res &= 0x1F;95break;96case RTC_CLOCKOUT_FREQ:97case RTC_TIMER_CONTROL:98res &= 0x83;99break;100}101return res;102}103104void105pcf8563_writereg(int reg, unsigned char val)106{107rtc_write(reg, val);108}109110void111get_rtc_time(struct rtc_time *tm)112{113tm->tm_sec = rtc_read(RTC_SECONDS);114tm->tm_min = rtc_read(RTC_MINUTES);115tm->tm_hour = rtc_read(RTC_HOURS);116tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);117tm->tm_wday = rtc_read(RTC_WEEKDAY);118tm->tm_mon = rtc_read(RTC_MONTH);119tm->tm_year = rtc_read(RTC_YEAR);120121if (tm->tm_sec & 0x80) {122printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "123"information is no longer guaranteed!\n", PCF8563_NAME);124}125126tm->tm_year = bcd2bin(tm->tm_year) +127((tm->tm_mon & 0x80) ? 100 : 0);128tm->tm_sec &= 0x7F;129tm->tm_min &= 0x7F;130tm->tm_hour &= 0x3F;131tm->tm_mday &= 0x3F;132tm->tm_wday &= 0x07; /* Not coded in BCD. */133tm->tm_mon &= 0x1F;134135tm->tm_sec = bcd2bin(tm->tm_sec);136tm->tm_min = bcd2bin(tm->tm_min);137tm->tm_hour = bcd2bin(tm->tm_hour);138tm->tm_mday = bcd2bin(tm->tm_mday);139tm->tm_mon = bcd2bin(tm->tm_mon);140tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */141}142143int __init144pcf8563_init(void)145{146static int res;147static int first = 1;148149if (!first)150return res;151first = 0;152153/* Initiate the i2c protocol. */154res = i2c_init();155if (res < 0) {156printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");157return res;158}159160/*161* First of all we need to reset the chip. This is done by162* clearing control1, control2 and clk freq and resetting163* all alarms.164*/165if (rtc_write(RTC_CONTROL1, 0x00) < 0)166goto err;167168if (rtc_write(RTC_CONTROL2, 0x00) < 0)169goto err;170171if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)172goto err;173174if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)175goto err;176177/* Reset the alarms. */178if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)179goto err;180181if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)182goto err;183184if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)185goto err;186187if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)188goto err;189190/* Check for low voltage, and warn about it. */191if (rtc_read(RTC_SECONDS) & 0x80) {192voltage_low = 1;193printk(KERN_WARNING "%s: RTC Voltage Low - reliable "194"date/time information is no longer guaranteed!\n",195PCF8563_NAME);196}197198return res;199200err:201printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);202res = -1;203return res;204}205206void __exit207pcf8563_exit(void)208{209unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME);210}211212/*213* ioctl calls for this driver. Why return -ENOTTY upon error? Because214* POSIX says so!215*/216static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)217{218/* Some sanity checks. */219if (_IOC_TYPE(cmd) != RTC_MAGIC)220return -ENOTTY;221222if (_IOC_NR(cmd) > RTC_MAX_IOCTL)223return -ENOTTY;224225switch (cmd) {226case RTC_RD_TIME:227{228struct rtc_time tm;229230mutex_lock(&rtc_lock);231memset(&tm, 0, sizeof tm);232get_rtc_time(&tm);233234if (copy_to_user((struct rtc_time *) arg, &tm,235sizeof tm)) {236mutex_unlock(&rtc_lock);237return -EFAULT;238}239240mutex_unlock(&rtc_lock);241242return 0;243}244case RTC_SET_TIME:245{246int leap;247int year;248int century;249struct rtc_time tm;250251memset(&tm, 0, sizeof tm);252if (!capable(CAP_SYS_TIME))253return -EPERM;254255if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))256return -EFAULT;257258/* Convert from struct tm to struct rtc_time. */259tm.tm_year += 1900;260tm.tm_mon += 1;261262/*263* Check if tm.tm_year is a leap year. A year is a leap264* year if it is divisible by 4 but not 100, except265* that years divisible by 400 _are_ leap years.266*/267year = tm.tm_year;268leap = (tm.tm_mon == 2) &&269((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);270271/* Perform some sanity checks. */272if ((tm.tm_year < 1970) ||273(tm.tm_mon > 12) ||274(tm.tm_mday == 0) ||275(tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||276(tm.tm_wday >= 7) ||277(tm.tm_hour >= 24) ||278(tm.tm_min >= 60) ||279(tm.tm_sec >= 60))280return -EINVAL;281282century = (tm.tm_year >= 2000) ? 0x80 : 0;283tm.tm_year = tm.tm_year % 100;284285tm.tm_year = bin2bcd(tm.tm_year);286tm.tm_mon = bin2bcd(tm.tm_mon);287tm.tm_mday = bin2bcd(tm.tm_mday);288tm.tm_hour = bin2bcd(tm.tm_hour);289tm.tm_min = bin2bcd(tm.tm_min);290tm.tm_sec = bin2bcd(tm.tm_sec);291tm.tm_mon |= century;292293mutex_lock(&rtc_lock);294295rtc_write(RTC_YEAR, tm.tm_year);296rtc_write(RTC_MONTH, tm.tm_mon);297rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */298rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);299rtc_write(RTC_HOURS, tm.tm_hour);300rtc_write(RTC_MINUTES, tm.tm_min);301rtc_write(RTC_SECONDS, tm.tm_sec);302303mutex_unlock(&rtc_lock);304305return 0;306}307case RTC_VL_READ:308if (voltage_low) {309printk(KERN_ERR "%s: RTC Voltage Low - "310"reliable date/time information is no "311"longer guaranteed!\n", PCF8563_NAME);312}313314if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))315return -EFAULT;316return 0;317318case RTC_VL_CLR:319{320/* Clear the VL bit in the seconds register in case321* the time has not been set already (which would322* have cleared it). This does not really matter323* because of the cached voltage_low value but do it324* anyway for consistency. */325326int ret = rtc_read(RTC_SECONDS);327328rtc_write(RTC_SECONDS, (ret & 0x7F));329330/* Clear the cached value. */331voltage_low = 0;332333return 0;334}335default:336return -ENOTTY;337}338339return 0;340}341342static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)343{344int ret;345346mutex_lock(&pcf8563_mutex);347ret = pcf8563_ioctl(filp, cmd, arg);348mutex_unlock(&pcf8563_mutex);349350return ret;351}352353static int __init pcf8563_register(void)354{355if (pcf8563_init() < 0) {356printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "357"Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);358return -1;359}360361if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {362printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",363PCF8563_NAME, PCF8563_MAJOR);364return -1;365}366367printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,368DRIVER_VERSION);369370/* Check for low voltage, and warn about it. */371if (voltage_low) {372printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "373"information is no longer guaranteed!\n", PCF8563_NAME);374}375376return 0;377}378379module_init(pcf8563_register);380module_exit(pcf8563_exit);381382383