0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0043
0044 #include <linux/module.h>
0045 #include <linux/err.h>
0046 #include <linux/rtc.h>
0047 #include <linux/platform_device.h>
0048 #include <linux/bcd.h>
0049 #include <linux/delay.h>
0050 #include <linux/io.h>
0051
0052 #define DRV_NAME "rs5c313"
0053
0054 #ifdef CONFIG_SH_LANDISK
0055
0056
0057
0058
0059 #define SCSMR1 0xFFE00000
0060 #define SCSCR1 0xFFE00008
0061 #define SCSMR1_CA 0x80
0062 #define SCSCR1_CKE 0x03
0063 #define SCSPTR1 0xFFE0001C
0064 #define SCSPTR1_EIO 0x80
0065 #define SCSPTR1_SPB1IO 0x08
0066 #define SCSPTR1_SPB1DT 0x04
0067 #define SCSPTR1_SPB0IO 0x02
0068 #define SCSPTR1_SPB0DT 0x01
0069
0070 #define SDA_OEN SCSPTR1_SPB1IO
0071 #define SDA SCSPTR1_SPB1DT
0072 #define SCL_OEN SCSPTR1_SPB0IO
0073 #define SCL SCSPTR1_SPB0DT
0074
0075
0076 #define RS5C313_CE 0xB0000003
0077
0078
0079 #define RS5C313_CE_RTCCE 0x02
0080
0081
0082 unsigned char scsptr1_data;
0083
0084 #define RS5C313_CEENABLE __raw_writeb(RS5C313_CE_RTCCE, RS5C313_CE);
0085 #define RS5C313_CEDISABLE __raw_writeb(0x00, RS5C313_CE)
0086 #define RS5C313_MISCOP __raw_writeb(0x02, 0xB0000008)
0087
0088 static void rs5c313_init_port(void)
0089 {
0090
0091 __raw_writeb(__raw_readb(SCSMR1) & ~SCSMR1_CA, SCSMR1);
0092 __raw_writeb(__raw_readb(SCSCR1) & ~SCSCR1_CKE, SCSCR1);
0093
0094
0095 scsptr1_data = __raw_readb(SCSPTR1) | SCL;
0096 __raw_writeb(scsptr1_data, SCSPTR1);
0097 scsptr1_data = __raw_readb(SCSPTR1) | SCL_OEN;
0098 __raw_writeb(scsptr1_data, SCSPTR1);
0099 RS5C313_CEDISABLE;
0100 }
0101
0102 static void rs5c313_write_data(unsigned char data)
0103 {
0104 int i;
0105
0106 for (i = 0; i < 8; i++) {
0107
0108 scsptr1_data = (scsptr1_data & ~SDA) |
0109 ((((0x80 >> i) & data) >> (7 - i)) << 2);
0110 __raw_writeb(scsptr1_data, SCSPTR1);
0111 if (i == 0) {
0112 scsptr1_data |= SDA_OEN;
0113 __raw_writeb(scsptr1_data, SCSPTR1);
0114 }
0115 ndelay(700);
0116 scsptr1_data &= ~SCL;
0117 __raw_writeb(scsptr1_data, SCSPTR1);
0118 ndelay(700);
0119 scsptr1_data |= SCL;
0120 __raw_writeb(scsptr1_data, SCSPTR1);
0121 }
0122
0123 scsptr1_data &= ~SDA_OEN;
0124 __raw_writeb(scsptr1_data, SCSPTR1);
0125 }
0126
0127 static unsigned char rs5c313_read_data(void)
0128 {
0129 int i;
0130 unsigned char data = 0;
0131
0132 for (i = 0; i < 8; i++) {
0133 ndelay(700);
0134
0135 data |= ((__raw_readb(SCSPTR1) & SDA) >> 2) << (7 - i);
0136 scsptr1_data &= ~SCL;
0137 __raw_writeb(scsptr1_data, SCSPTR1);
0138 ndelay(700);
0139 scsptr1_data |= SCL;
0140 __raw_writeb(scsptr1_data, SCSPTR1);
0141 }
0142 return data & 0x0F;
0143 }
0144
0145 #endif
0146
0147
0148
0149
0150
0151
0152 #define RS5C313_ADDR_SEC 0x00
0153 #define RS5C313_ADDR_SEC10 0x01
0154 #define RS5C313_ADDR_MIN 0x02
0155 #define RS5C313_ADDR_MIN10 0x03
0156 #define RS5C313_ADDR_HOUR 0x04
0157 #define RS5C313_ADDR_HOUR10 0x05
0158 #define RS5C313_ADDR_WEEK 0x06
0159 #define RS5C313_ADDR_INTINTVREG 0x07
0160 #define RS5C313_ADDR_DAY 0x08
0161 #define RS5C313_ADDR_DAY10 0x09
0162 #define RS5C313_ADDR_MON 0x0A
0163 #define RS5C313_ADDR_MON10 0x0B
0164 #define RS5C313_ADDR_YEAR 0x0C
0165 #define RS5C313_ADDR_YEAR10 0x0D
0166 #define RS5C313_ADDR_CNTREG 0x0E
0167 #define RS5C313_ADDR_TESTREG 0x0F
0168
0169
0170 #define RS5C313_CNTREG_ADJ_BSY 0x01
0171 #define RS5C313_CNTREG_WTEN_XSTP 0x02
0172 #define RS5C313_CNTREG_12_24 0x04
0173 #define RS5C313_CNTREG_CTFG 0x08
0174
0175
0176 #define RS5C313_TESTREG_TEST 0x01
0177
0178
0179 #define RS5C313_CNTBIT_READ 0x40
0180 #define RS5C313_CNTBIT_AD 0x20
0181 #define RS5C313_CNTBIT_DT 0x10
0182
0183 static unsigned char rs5c313_read_reg(unsigned char addr)
0184 {
0185
0186 rs5c313_write_data(addr | RS5C313_CNTBIT_READ | RS5C313_CNTBIT_AD);
0187 return rs5c313_read_data();
0188 }
0189
0190 static void rs5c313_write_reg(unsigned char addr, unsigned char data)
0191 {
0192 data &= 0x0f;
0193 rs5c313_write_data(addr | RS5C313_CNTBIT_AD);
0194 rs5c313_write_data(data | RS5C313_CNTBIT_DT);
0195 return;
0196 }
0197
0198 static inline unsigned char rs5c313_read_cntreg(void)
0199 {
0200 return rs5c313_read_reg(RS5C313_ADDR_CNTREG);
0201 }
0202
0203 static inline void rs5c313_write_cntreg(unsigned char data)
0204 {
0205 rs5c313_write_reg(RS5C313_ADDR_CNTREG, data);
0206 }
0207
0208 static inline void rs5c313_write_intintvreg(unsigned char data)
0209 {
0210 rs5c313_write_reg(RS5C313_ADDR_INTINTVREG, data);
0211 }
0212
0213 static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
0214 {
0215 int data;
0216 int cnt;
0217
0218 cnt = 0;
0219 while (1) {
0220 RS5C313_CEENABLE;
0221
0222
0223 rs5c313_write_cntreg(0x04);
0224
0225 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
0226 break;
0227
0228 RS5C313_CEDISABLE;
0229 ndelay(700);
0230
0231 if (cnt++ > 100) {
0232 dev_err(dev, "%s: timeout error\n", __func__);
0233 return -EIO;
0234 }
0235 }
0236
0237 data = rs5c313_read_reg(RS5C313_ADDR_SEC);
0238 data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4);
0239 tm->tm_sec = bcd2bin(data);
0240
0241 data = rs5c313_read_reg(RS5C313_ADDR_MIN);
0242 data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4);
0243 tm->tm_min = bcd2bin(data);
0244
0245 data = rs5c313_read_reg(RS5C313_ADDR_HOUR);
0246 data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4);
0247 tm->tm_hour = bcd2bin(data);
0248
0249 data = rs5c313_read_reg(RS5C313_ADDR_DAY);
0250 data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4);
0251 tm->tm_mday = bcd2bin(data);
0252
0253 data = rs5c313_read_reg(RS5C313_ADDR_MON);
0254 data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4);
0255 tm->tm_mon = bcd2bin(data) - 1;
0256
0257 data = rs5c313_read_reg(RS5C313_ADDR_YEAR);
0258 data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4);
0259 tm->tm_year = bcd2bin(data);
0260
0261 if (tm->tm_year < 70)
0262 tm->tm_year += 100;
0263
0264 data = rs5c313_read_reg(RS5C313_ADDR_WEEK);
0265 tm->tm_wday = bcd2bin(data);
0266
0267 RS5C313_CEDISABLE;
0268 ndelay(700);
0269
0270 return 0;
0271 }
0272
0273 static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
0274 {
0275 int data;
0276 int cnt;
0277
0278 cnt = 0;
0279
0280 while (1) {
0281 RS5C313_CEENABLE;
0282
0283
0284 rs5c313_write_cntreg(0x04);
0285
0286 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
0287 break;
0288 RS5C313_MISCOP;
0289 RS5C313_CEDISABLE;
0290 ndelay(700);
0291
0292 if (cnt++ > 100) {
0293 dev_err(dev, "%s: timeout error\n", __func__);
0294 return -EIO;
0295 }
0296 }
0297
0298 data = bin2bcd(tm->tm_sec);
0299 rs5c313_write_reg(RS5C313_ADDR_SEC, data);
0300 rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4));
0301
0302 data = bin2bcd(tm->tm_min);
0303 rs5c313_write_reg(RS5C313_ADDR_MIN, data);
0304 rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4));
0305
0306 data = bin2bcd(tm->tm_hour);
0307 rs5c313_write_reg(RS5C313_ADDR_HOUR, data);
0308 rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4));
0309
0310 data = bin2bcd(tm->tm_mday);
0311 rs5c313_write_reg(RS5C313_ADDR_DAY, data);
0312 rs5c313_write_reg(RS5C313_ADDR_DAY10, (data >> 4));
0313
0314 data = bin2bcd(tm->tm_mon + 1);
0315 rs5c313_write_reg(RS5C313_ADDR_MON, data);
0316 rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4));
0317
0318 data = bin2bcd(tm->tm_year % 100);
0319 rs5c313_write_reg(RS5C313_ADDR_YEAR, data);
0320 rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4));
0321
0322 data = bin2bcd(tm->tm_wday);
0323 rs5c313_write_reg(RS5C313_ADDR_WEEK, data);
0324
0325 RS5C313_CEDISABLE;
0326 ndelay(700);
0327
0328 return 0;
0329 }
0330
0331 static void rs5c313_check_xstp_bit(void)
0332 {
0333 struct rtc_time tm;
0334 int cnt;
0335
0336 RS5C313_CEENABLE;
0337 if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) {
0338
0339 rs5c313_write_intintvreg(0x00);
0340
0341 rs5c313_write_cntreg(0x07);
0342
0343
0344 for (cnt = 0; cnt < 100; cnt++) {
0345 if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
0346 break;
0347 RS5C313_MISCOP;
0348 }
0349
0350 memset(&tm, 0, sizeof(struct rtc_time));
0351 tm.tm_mday = 1;
0352 tm.tm_mon = 1 - 1;
0353 tm.tm_year = 2000 - 1900;
0354
0355 rs5c313_rtc_set_time(NULL, &tm);
0356 pr_err("invalid value, resetting to 1 Jan 2000\n");
0357 }
0358 RS5C313_CEDISABLE;
0359 ndelay(700);
0360 }
0361
0362 static const struct rtc_class_ops rs5c313_rtc_ops = {
0363 .read_time = rs5c313_rtc_read_time,
0364 .set_time = rs5c313_rtc_set_time,
0365 };
0366
0367 static int rs5c313_rtc_probe(struct platform_device *pdev)
0368 {
0369 struct rtc_device *rtc;
0370
0371 rs5c313_init_port();
0372 rs5c313_check_xstp_bit();
0373
0374 rtc = devm_rtc_device_register(&pdev->dev, "rs5c313", &rs5c313_rtc_ops,
0375 THIS_MODULE);
0376
0377 return PTR_ERR_OR_ZERO(rtc);
0378 }
0379
0380 static struct platform_driver rs5c313_rtc_platform_driver = {
0381 .driver = {
0382 .name = DRV_NAME,
0383 },
0384 .probe = rs5c313_rtc_probe,
0385 };
0386
0387 module_platform_driver(rs5c313_rtc_platform_driver);
0388
0389 MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>");
0390 MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver");
0391 MODULE_LICENSE("GPL");
0392 MODULE_ALIAS("platform:" DRV_NAME);