1/* 2 * PCF8563 RTC 3 * 4 * From Phillips' datasheet: 5 * 6 * The PCF8563 is a CMOS real-time clock/calendar optimized for low power 7 * consumption. A programmable clock output, interupt output and voltage 8 * low detector are also provided. All address and data are transferred 9 * serially via two-line bidirectional I2C-bus. Maximum bus speed is 10 * 400 kbits/s. The built-in word address register is incremented 11 * automatically after each written or read bute. 12 * 13 * Copyright (c) 2002, Axis Communications AB 14 * All rights reserved. 15 * 16 * Author: Tobias Anderberg <tobiasa@axis.com>. 17 * 18 * $Id: pcf8563.c,v 1.1.1.1 2008/10/15 03:26:01 james26_jang Exp $ 19 */ 20 21#include <linux/config.h> 22#include <linux/version.h> 23#include <linux/module.h> 24#include <linux/kernel.h> 25#include <linux/types.h> 26#include <linux/sched.h> 27#include <linux/init.h> 28#include <linux/fs.h> 29#include <linux/ioctl.h> 30#include <linux/delay.h> 31 32#include <asm/uaccess.h> 33#include <asm/system.h> 34#include <asm/io.h> 35#include <asm/svinto.h> 36#include <asm/rtc.h> 37#include "i2c.h" 38 39#define PCF8563_MAJOR 121 /* Local major number. */ 40#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ 41#define PCF8563_NAME "PCF8563" 42#define DRIVER_VERSION "$Rev$" 43 44/* Two simple wrapper macros, saves a few keystrokes. */ 45#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) 46#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) 47 48static const unsigned char days_in_month[] = 49 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 50 51int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long); 52int pcf8563_open(struct inode *, struct file *); 53int pcf8563_release(struct inode *, struct file *); 54 55static struct file_operations pcf8563_fops = { 56 owner: THIS_MODULE, 57 ioctl: pcf8563_ioctl, 58 open: pcf8563_open, 59 release: pcf8563_release, 60}; 61 62void 63get_rtc_time(struct rtc_time *tm) 64{ 65 unsigned long flags; 66 67 tm->tm_sec = rtc_read(RTC_SECONDS); 68 tm->tm_min = rtc_read(RTC_MINUTES); 69 tm->tm_hour = rtc_read(RTC_HOURS); 70 tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH); 71 tm->tm_mon = rtc_read(RTC_MONTH); 72 tm->tm_year = rtc_read(RTC_YEAR); 73 74 if (tm->tm_sec & 0x80) 75 printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME); 76 77 tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0); 78 tm->tm_sec &= 0x7f; 79 tm->tm_min &= 0x7f; 80 tm->tm_hour &= 0x3f; 81 tm->tm_mday &= 0x3f; 82 tm->tm_mon &= 0x1f; 83 84 BCD_TO_BIN(tm->tm_sec); 85 BCD_TO_BIN(tm->tm_min); 86 BCD_TO_BIN(tm->tm_hour); 87 BCD_TO_BIN(tm->tm_mday); 88 BCD_TO_BIN(tm->tm_mon); 89 tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */ 90} 91 92int __init 93pcf8563_init(void) 94{ 95 unsigned char ret; 96 struct rtc_time tm; 97 98 /* 99 * First of all we need to reset the chip. This is done by 100 * clearing control1, control2 and clk freq, clear the 101 * Voltage Low bit, and resetting all alarms. 102 */ 103 if (rtc_write(RTC_CONTROL1, 0x00) < 0) 104 goto err; 105 106 if (rtc_write(RTC_CONTROL2, 0x00) < 0) 107 goto err; 108 109 if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0) 110 goto err; 111 112 /* Clear the VL bit in the seconds register. */ 113 ret = rtc_read(RTC_SECONDS); 114 115 if (rtc_write(RTC_SECONDS, (ret & 0x7f)) < 0) 116 goto err; 117 118 /* Reset the alarms. */ 119 if (rtc_write(RTC_MINUTE_ALARM, 0x00) < 0) 120 goto err; 121 122 if (rtc_write(RTC_HOUR_ALARM, 0x00) < 0) 123 goto err; 124 125 if (rtc_write(RTC_DAY_ALARM, 0x00) < 0) 126 goto err; 127 128 if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0) 129 goto err; 130 131 if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { 132 printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n", 133 PCF8563_NAME, PCF8563_MAJOR); 134 return -1; 135 } 136 137 printk(KERN_INFO "%s Real-Time Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); 138 139 /* Check for low voltage, and warn about it.. */ 140 if (rtc_read(RTC_SECONDS) & 0x80) 141 printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME); 142 143 return 0; 144 145err: 146 printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME); 147 return -1; 148} 149 150void __exit 151pcf8563_exit(void) 152{ 153 if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) { 154 printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME); 155 } 156} 157 158/* 159 * ioctl calls for this driver. Why return -ENOTTY upon error? Because 160 * POSIX says so! 161 */ 162int 163pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 164{ 165 /* Some sanity checks. */ 166 if (_IOC_TYPE(cmd) != PCF8563_MAGIC) 167 return -ENOTTY; 168 169 if (_IOC_NR(cmd) > RTC_MAX_IOCTL) 170 return -ENOTTY; 171 172 switch (cmd) { 173 case RTC_RD_TIME: 174 { 175 struct rtc_time tm; 176 177 get_rtc_time(&tm); 178 179 if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) { 180 return -EFAULT; 181 } 182 183 return 0; 184 } 185 break; 186 case RTC_SET_TIME: 187 { 188 int leap; 189 int century; 190 unsigned long flags; 191 struct rtc_time tm; 192 193 if (!capable(CAP_SYS_TIME)) 194 return -EPERM; 195 196 if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time))) 197 return -EFAULT; 198 199 /* Convert from struct tm to struct rtc_time. */ 200 tm.tm_year += 1900; 201 tm.tm_mon += 1; 202 203 leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0; 204 205 /* Perform some sanity checks. */ 206 if ((tm.tm_year < 1970) || 207 (tm.tm_mon > 12) || 208 (tm.tm_mday == 0) || 209 (tm.tm_mday > days_in_month[tm.tm_mon] + leap) || 210 (tm.tm_hour >= 24) || 211 (tm.tm_min >= 60) || 212 (tm.tm_sec >= 60)) 213 return -EINVAL; 214 215 century = (tm.tm_year >= 2000) ? 0x80 : 0; 216 tm.tm_year = tm.tm_year % 100; 217 218 BIN_TO_BCD(tm.tm_year); 219 BIN_TO_BCD(tm.tm_mday); 220 BIN_TO_BCD(tm.tm_hour); 221 BIN_TO_BCD(tm.tm_min); 222 BIN_TO_BCD(tm.tm_sec); 223 tm.tm_mon |= century; 224 225 rtc_write(RTC_YEAR, tm.tm_year); 226 rtc_write(RTC_MONTH, tm.tm_mon); 227 rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday); 228 rtc_write(RTC_HOURS, tm.tm_hour); 229 rtc_write(RTC_MINUTES, tm.tm_min); 230 rtc_write(RTC_SECONDS, tm.tm_sec); 231 232 return 0; 233 } 234 break; 235 default: 236 return -ENOTTY; 237 } 238 239 return 0; 240} 241 242int 243pcf8563_open(struct inode *inode, struct file *filp) 244{ 245 MOD_INC_USE_COUNT; 246 return 0; 247} 248 249int 250pcf8563_release(struct inode *inode, struct file *filp) 251{ 252 MOD_DEC_USE_COUNT; 253 return 0; 254} 255 256EXPORT_NO_SYMBOLS; 257module_init(pcf8563_init); 258module_exit(pcf8563_exit); 259