rtc-rs5c313.c (10402B)
1/* 2 * Ricoh RS5C313 RTC device/driver 3 * Copyright (C) 2007 Nobuhiro Iwamatsu 4 * 5 * 2005-09-19 modifed by kogiidena 6 * 7 * Based on the old drivers/char/rs5c313_rtc.c by: 8 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 9 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka 10 * 11 * Based on code written by Paul Gortmaker. 12 * Copyright (C) 1996 Paul Gortmaker 13 * 14 * This file is subject to the terms and conditions of the GNU General Public 15 * License. See the file "COPYING" in the main directory of this archive 16 * for more details. 17 * 18 * Based on other minimal char device drivers, like Alan's 19 * watchdog, Ted's random, etc. etc. 20 * 21 * 1.07 Paul Gortmaker. 22 * 1.08 Miquel van Smoorenburg: disallow certain things on the 23 * DEC Alpha as the CMOS clock is also used for other things. 24 * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup. 25 * 1.09a Pete Zaitcev: Sun SPARC 26 * 1.09b Jeff Garzik: Modularize, init cleanup 27 * 1.09c Jeff Garzik: SMP cleanup 28 * 1.10 Paul Barton-Davis: add support for async I/O 29 * 1.10a Andrea Arcangeli: Alpha updates 30 * 1.10b Andrew Morton: SMP lock fix 31 * 1.10c Cesar Barros: SMP locking fixes and cleanup 32 * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit 33 * 1.10e Maciej W. Rozycki: Handle DECstation's year weirdness. 34 * 1.11 Takashi Iwai: Kernel access functions 35 * rtc_register/rtc_unregister/rtc_control 36 * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init 37 * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer 38 * CONFIG_HPET_EMULATE_RTC 39 * 1.13 Nobuhiro Iwamatsu: Updata driver. 40 */ 41 42#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 43 44#include <linux/module.h> 45#include <linux/err.h> 46#include <linux/rtc.h> 47#include <linux/platform_device.h> 48#include <linux/bcd.h> 49#include <linux/delay.h> 50#include <linux/io.h> 51 52#define DRV_NAME "rs5c313" 53 54#ifdef CONFIG_SH_LANDISK 55/*****************************************************/ 56/* LANDISK dependence part of RS5C313 */ 57/*****************************************************/ 58 59#define SCSMR1 0xFFE00000 60#define SCSCR1 0xFFE00008 61#define SCSMR1_CA 0x80 62#define SCSCR1_CKE 0x03 63#define SCSPTR1 0xFFE0001C 64#define SCSPTR1_EIO 0x80 65#define SCSPTR1_SPB1IO 0x08 66#define SCSPTR1_SPB1DT 0x04 67#define SCSPTR1_SPB0IO 0x02 68#define SCSPTR1_SPB0DT 0x01 69 70#define SDA_OEN SCSPTR1_SPB1IO 71#define SDA SCSPTR1_SPB1DT 72#define SCL_OEN SCSPTR1_SPB0IO 73#define SCL SCSPTR1_SPB0DT 74 75/* RICOH RS5C313 CE port */ 76#define RS5C313_CE 0xB0000003 77 78/* RICOH RS5C313 CE port bit */ 79#define RS5C313_CE_RTCCE 0x02 80 81/* SCSPTR1 data */ 82unsigned char scsptr1_data; 83 84#define RS5C313_CEENABLE __raw_writeb(RS5C313_CE_RTCCE, RS5C313_CE); 85#define RS5C313_CEDISABLE __raw_writeb(0x00, RS5C313_CE) 86#define RS5C313_MISCOP __raw_writeb(0x02, 0xB0000008) 87 88static void rs5c313_init_port(void) 89{ 90 /* Set SCK as I/O port and Initialize SCSPTR1 data & I/O port. */ 91 __raw_writeb(__raw_readb(SCSMR1) & ~SCSMR1_CA, SCSMR1); 92 __raw_writeb(__raw_readb(SCSCR1) & ~SCSCR1_CKE, SCSCR1); 93 94 /* And Initialize SCL for RS5C313 clock */ 95 scsptr1_data = __raw_readb(SCSPTR1) | SCL; /* SCL:H */ 96 __raw_writeb(scsptr1_data, SCSPTR1); 97 scsptr1_data = __raw_readb(SCSPTR1) | SCL_OEN; /* SCL output enable */ 98 __raw_writeb(scsptr1_data, SCSPTR1); 99 RS5C313_CEDISABLE; /* CE:L */ 100} 101 102static void rs5c313_write_data(unsigned char data) 103{ 104 int i; 105 106 for (i = 0; i < 8; i++) { 107 /* SDA:Write Data */ 108 scsptr1_data = (scsptr1_data & ~SDA) | 109 ((((0x80 >> i) & data) >> (7 - i)) << 2); 110 __raw_writeb(scsptr1_data, SCSPTR1); 111 if (i == 0) { 112 scsptr1_data |= SDA_OEN; /* SDA:output enable */ 113 __raw_writeb(scsptr1_data, SCSPTR1); 114 } 115 ndelay(700); 116 scsptr1_data &= ~SCL; /* SCL:L */ 117 __raw_writeb(scsptr1_data, SCSPTR1); 118 ndelay(700); 119 scsptr1_data |= SCL; /* SCL:H */ 120 __raw_writeb(scsptr1_data, SCSPTR1); 121 } 122 123 scsptr1_data &= ~SDA_OEN; /* SDA:output disable */ 124 __raw_writeb(scsptr1_data, SCSPTR1); 125} 126 127static unsigned char rs5c313_read_data(void) 128{ 129 int i; 130 unsigned char data = 0; 131 132 for (i = 0; i < 8; i++) { 133 ndelay(700); 134 /* SDA:Read Data */ 135 data |= ((__raw_readb(SCSPTR1) & SDA) >> 2) << (7 - i); 136 scsptr1_data &= ~SCL; /* SCL:L */ 137 __raw_writeb(scsptr1_data, SCSPTR1); 138 ndelay(700); 139 scsptr1_data |= SCL; /* SCL:H */ 140 __raw_writeb(scsptr1_data, SCSPTR1); 141 } 142 return data & 0x0F; 143} 144 145#endif /* CONFIG_SH_LANDISK */ 146 147/*****************************************************/ 148/* machine independence part of RS5C313 */ 149/*****************************************************/ 150 151/* RICOH RS5C313 address */ 152#define RS5C313_ADDR_SEC 0x00 153#define RS5C313_ADDR_SEC10 0x01 154#define RS5C313_ADDR_MIN 0x02 155#define RS5C313_ADDR_MIN10 0x03 156#define RS5C313_ADDR_HOUR 0x04 157#define RS5C313_ADDR_HOUR10 0x05 158#define RS5C313_ADDR_WEEK 0x06 159#define RS5C313_ADDR_INTINTVREG 0x07 160#define RS5C313_ADDR_DAY 0x08 161#define RS5C313_ADDR_DAY10 0x09 162#define RS5C313_ADDR_MON 0x0A 163#define RS5C313_ADDR_MON10 0x0B 164#define RS5C313_ADDR_YEAR 0x0C 165#define RS5C313_ADDR_YEAR10 0x0D 166#define RS5C313_ADDR_CNTREG 0x0E 167#define RS5C313_ADDR_TESTREG 0x0F 168 169/* RICOH RS5C313 control register */ 170#define RS5C313_CNTREG_ADJ_BSY 0x01 171#define RS5C313_CNTREG_WTEN_XSTP 0x02 172#define RS5C313_CNTREG_12_24 0x04 173#define RS5C313_CNTREG_CTFG 0x08 174 175/* RICOH RS5C313 test register */ 176#define RS5C313_TESTREG_TEST 0x01 177 178/* RICOH RS5C313 control bit */ 179#define RS5C313_CNTBIT_READ 0x40 180#define RS5C313_CNTBIT_AD 0x20 181#define RS5C313_CNTBIT_DT 0x10 182 183static unsigned char rs5c313_read_reg(unsigned char addr) 184{ 185 186 rs5c313_write_data(addr | RS5C313_CNTBIT_READ | RS5C313_CNTBIT_AD); 187 return rs5c313_read_data(); 188} 189 190static void rs5c313_write_reg(unsigned char addr, unsigned char data) 191{ 192 data &= 0x0f; 193 rs5c313_write_data(addr | RS5C313_CNTBIT_AD); 194 rs5c313_write_data(data | RS5C313_CNTBIT_DT); 195 return; 196} 197 198static inline unsigned char rs5c313_read_cntreg(void) 199{ 200 return rs5c313_read_reg(RS5C313_ADDR_CNTREG); 201} 202 203static inline void rs5c313_write_cntreg(unsigned char data) 204{ 205 rs5c313_write_reg(RS5C313_ADDR_CNTREG, data); 206} 207 208static inline void rs5c313_write_intintvreg(unsigned char data) 209{ 210 rs5c313_write_reg(RS5C313_ADDR_INTINTVREG, data); 211} 212 213static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) 214{ 215 int data; 216 int cnt; 217 218 cnt = 0; 219 while (1) { 220 RS5C313_CEENABLE; /* CE:H */ 221 222 /* Initialize control reg. 24 hour */ 223 rs5c313_write_cntreg(0x04); 224 225 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) 226 break; 227 228 RS5C313_CEDISABLE; 229 ndelay(700); /* CE:L */ 230 231 if (cnt++ > 100) { 232 dev_err(dev, "%s: timeout error\n", __func__); 233 return -EIO; 234 } 235 } 236 237 data = rs5c313_read_reg(RS5C313_ADDR_SEC); 238 data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4); 239 tm->tm_sec = bcd2bin(data); 240 241 data = rs5c313_read_reg(RS5C313_ADDR_MIN); 242 data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4); 243 tm->tm_min = bcd2bin(data); 244 245 data = rs5c313_read_reg(RS5C313_ADDR_HOUR); 246 data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4); 247 tm->tm_hour = bcd2bin(data); 248 249 data = rs5c313_read_reg(RS5C313_ADDR_DAY); 250 data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4); 251 tm->tm_mday = bcd2bin(data); 252 253 data = rs5c313_read_reg(RS5C313_ADDR_MON); 254 data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4); 255 tm->tm_mon = bcd2bin(data) - 1; 256 257 data = rs5c313_read_reg(RS5C313_ADDR_YEAR); 258 data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4); 259 tm->tm_year = bcd2bin(data); 260 261 if (tm->tm_year < 70) 262 tm->tm_year += 100; 263 264 data = rs5c313_read_reg(RS5C313_ADDR_WEEK); 265 tm->tm_wday = bcd2bin(data); 266 267 RS5C313_CEDISABLE; 268 ndelay(700); /* CE:L */ 269 270 return 0; 271} 272 273static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) 274{ 275 int data; 276 int cnt; 277 278 cnt = 0; 279 /* busy check. */ 280 while (1) { 281 RS5C313_CEENABLE; /* CE:H */ 282 283 /* Initiatlize control reg. 24 hour */ 284 rs5c313_write_cntreg(0x04); 285 286 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) 287 break; 288 RS5C313_MISCOP; 289 RS5C313_CEDISABLE; 290 ndelay(700); /* CE:L */ 291 292 if (cnt++ > 100) { 293 dev_err(dev, "%s: timeout error\n", __func__); 294 return -EIO; 295 } 296 } 297 298 data = bin2bcd(tm->tm_sec); 299 rs5c313_write_reg(RS5C313_ADDR_SEC, data); 300 rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4)); 301 302 data = bin2bcd(tm->tm_min); 303 rs5c313_write_reg(RS5C313_ADDR_MIN, data); 304 rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4)); 305 306 data = bin2bcd(tm->tm_hour); 307 rs5c313_write_reg(RS5C313_ADDR_HOUR, data); 308 rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4)); 309 310 data = bin2bcd(tm->tm_mday); 311 rs5c313_write_reg(RS5C313_ADDR_DAY, data); 312 rs5c313_write_reg(RS5C313_ADDR_DAY10, (data >> 4)); 313 314 data = bin2bcd(tm->tm_mon + 1); 315 rs5c313_write_reg(RS5C313_ADDR_MON, data); 316 rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4)); 317 318 data = bin2bcd(tm->tm_year % 100); 319 rs5c313_write_reg(RS5C313_ADDR_YEAR, data); 320 rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4)); 321 322 data = bin2bcd(tm->tm_wday); 323 rs5c313_write_reg(RS5C313_ADDR_WEEK, data); 324 325 RS5C313_CEDISABLE; /* CE:H */ 326 ndelay(700); 327 328 return 0; 329} 330 331static void rs5c313_check_xstp_bit(void) 332{ 333 struct rtc_time tm; 334 int cnt; 335 336 RS5C313_CEENABLE; /* CE:H */ 337 if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { 338 /* INT interval reg. OFF */ 339 rs5c313_write_intintvreg(0x00); 340 /* Initialize control reg. 24 hour & adjust */ 341 rs5c313_write_cntreg(0x07); 342 343 /* busy check. */ 344 for (cnt = 0; cnt < 100; cnt++) { 345 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) 346 break; 347 RS5C313_MISCOP; 348 } 349 350 memset(&tm, 0, sizeof(struct rtc_time)); 351 tm.tm_mday = 1; 352 tm.tm_mon = 1 - 1; 353 tm.tm_year = 2000 - 1900; 354 355 rs5c313_rtc_set_time(NULL, &tm); 356 pr_err("invalid value, resetting to 1 Jan 2000\n"); 357 } 358 RS5C313_CEDISABLE; 359 ndelay(700); /* CE:L */ 360} 361 362static const struct rtc_class_ops rs5c313_rtc_ops = { 363 .read_time = rs5c313_rtc_read_time, 364 .set_time = rs5c313_rtc_set_time, 365}; 366 367static int rs5c313_rtc_probe(struct platform_device *pdev) 368{ 369 struct rtc_device *rtc; 370 371 rs5c313_init_port(); 372 rs5c313_check_xstp_bit(); 373 374 rtc = devm_rtc_device_register(&pdev->dev, "rs5c313", &rs5c313_rtc_ops, 375 THIS_MODULE); 376 377 return PTR_ERR_OR_ZERO(rtc); 378} 379 380static struct platform_driver rs5c313_rtc_platform_driver = { 381 .driver = { 382 .name = DRV_NAME, 383 }, 384 .probe = rs5c313_rtc_probe, 385}; 386 387module_platform_driver(rs5c313_rtc_platform_driver); 388 389MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>"); 390MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver"); 391MODULE_LICENSE("GPL"); 392MODULE_ALIAS("platform:" DRV_NAME);