1 /* 2 * RTC driver for Maxim MAX8925 3 * 4 * Copyright (C) 2009-2010 Marvell International Ltd. 5 * Haojian Zhuang <haojian.zhuang@marvell.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/i2c.h> 14 #include <linux/rtc.h> 15 #include <linux/platform_device.h> 16 #include <linux/mfd/max8925.h> 17 18 enum { 19 RTC_SEC = 0, 20 RTC_MIN, 21 RTC_HOUR, 22 RTC_WEEKDAY, 23 RTC_DATE, 24 RTC_MONTH, 25 RTC_YEAR1, 26 RTC_YEAR2, 27 }; 28 29 #define MAX8925_RTC_SEC 0x00 30 #define MAX8925_RTC_MIN 0x01 31 #define MAX8925_RTC_HOUR 0x02 32 #define MAX8925_RTC_WEEKDAY 0x03 33 #define MAX8925_RTC_DATE 0x04 34 #define MAX8925_RTC_MONTH 0x05 35 #define MAX8925_RTC_YEAR1 0x06 36 #define MAX8925_RTC_YEAR2 0x07 37 #define MAX8925_ALARM0_SEC 0x08 38 #define MAX8925_ALARM0_MIN 0x09 39 #define MAX8925_ALARM0_HOUR 0x0a 40 #define MAX8925_ALARM0_WEEKDAY 0x0b 41 #define MAX8925_ALARM0_DATE 0x0c 42 #define MAX8925_ALARM0_MON 0x0d 43 #define MAX8925_ALARM0_YEAR1 0x0e 44 #define MAX8925_ALARM0_YEAR2 0x0f 45 #define MAX8925_ALARM1_SEC 0x10 46 #define MAX8925_ALARM1_MIN 0x11 47 #define MAX8925_ALARM1_HOUR 0x12 48 #define MAX8925_ALARM1_WEEKDAY 0x13 49 #define MAX8925_ALARM1_DATE 0x14 50 #define MAX8925_ALARM1_MON 0x15 51 #define MAX8925_ALARM1_YEAR1 0x16 52 #define MAX8925_ALARM1_YEAR2 0x17 53 #define MAX8925_RTC_CNTL 0x1b 54 #define MAX8925_RTC_STATUS 0x20 55 56 #define TIME_NUM 8 57 #define ALARM_1SEC (1 << 7) 58 #define HOUR_12 (1 << 7) 59 #define HOUR_AM_PM (1 << 5) 60 #define ALARM0_IRQ (1 << 3) 61 #define ALARM1_IRQ (1 << 2) 62 #define ALARM0_STATUS (1 << 2) 63 #define ALARM1_STATUS (1 << 1) 64 65 66 struct max8925_rtc_info { 67 struct rtc_device *rtc_dev; 68 struct max8925_chip *chip; 69 struct i2c_client *rtc; 70 struct device *dev; 71 }; 72 73 static irqreturn_t rtc_update_handler(int irq, void *data) 74 { 75 struct max8925_rtc_info *info = (struct max8925_rtc_info *)data; 76 77 /* disable ALARM0 except for 1SEC alarm */ 78 max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0); 79 rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); 80 return IRQ_HANDLED; 81 } 82 83 static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len) 84 { 85 if (len < TIME_NUM) 86 return -EINVAL; 87 tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000 88 + (buf[RTC_YEAR2] & 0xf) * 100 89 + (buf[RTC_YEAR1] >> 4) * 10 90 + (buf[RTC_YEAR1] & 0xf); 91 tm->tm_year -= 1900; 92 tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10 93 + (buf[RTC_MONTH] & 0x0f); 94 tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10 95 + (buf[RTC_DATE] & 0x0f); 96 tm->tm_wday = buf[RTC_WEEKDAY] & 0x07; 97 if (buf[RTC_HOUR] & HOUR_12) { 98 tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10 99 + (buf[RTC_HOUR] & 0x0f); 100 if (buf[RTC_HOUR] & HOUR_AM_PM) 101 tm->tm_hour += 12; 102 } else 103 tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10 104 + (buf[RTC_HOUR] & 0x0f); 105 tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10 106 + (buf[RTC_MIN] & 0x0f); 107 tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10 108 + (buf[RTC_SEC] & 0x0f); 109 return 0; 110 } 111 112 static int data_calc(unsigned char *buf, struct rtc_time *tm, int len) 113 { 114 unsigned char high, low; 115 116 if (len < TIME_NUM) 117 return -EINVAL; 118 119 high = (tm->tm_year + 1900) / 1000; 120 low = (tm->tm_year + 1900) / 100; 121 low = low - high * 10; 122 buf[RTC_YEAR2] = (high << 4) + low; 123 high = (tm->tm_year + 1900) / 10; 124 low = tm->tm_year + 1900; 125 low = low - high * 10; 126 high = high - (high / 10) * 10; 127 buf[RTC_YEAR1] = (high << 4) + low; 128 high = tm->tm_mon / 10; 129 low = tm->tm_mon; 130 low = low - high * 10; 131 buf[RTC_MONTH] = (high << 4) + low; 132 high = tm->tm_mday / 10; 133 low = tm->tm_mday; 134 low = low - high * 10; 135 buf[RTC_DATE] = (high << 4) + low; 136 buf[RTC_WEEKDAY] = tm->tm_wday; 137 high = tm->tm_hour / 10; 138 low = tm->tm_hour; 139 low = low - high * 10; 140 buf[RTC_HOUR] = (high << 4) + low; 141 high = tm->tm_min / 10; 142 low = tm->tm_min; 143 low = low - high * 10; 144 buf[RTC_MIN] = (high << 4) + low; 145 high = tm->tm_sec / 10; 146 low = tm->tm_sec; 147 low = low - high * 10; 148 buf[RTC_SEC] = (high << 4) + low; 149 return 0; 150 } 151 152 static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm) 153 { 154 struct max8925_rtc_info *info = dev_get_drvdata(dev); 155 unsigned char buf[TIME_NUM]; 156 int ret; 157 158 ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); 159 if (ret < 0) 160 goto out; 161 ret = tm_calc(tm, buf, TIME_NUM); 162 out: 163 return ret; 164 } 165 166 static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm) 167 { 168 struct max8925_rtc_info *info = dev_get_drvdata(dev); 169 unsigned char buf[TIME_NUM]; 170 int ret; 171 172 ret = data_calc(buf, tm, TIME_NUM); 173 if (ret < 0) 174 goto out; 175 ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); 176 out: 177 return ret; 178 } 179 180 static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 181 { 182 struct max8925_rtc_info *info = dev_get_drvdata(dev); 183 unsigned char buf[TIME_NUM]; 184 int ret; 185 186 ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); 187 if (ret < 0) 188 goto out; 189 ret = tm_calc(&alrm->time, buf, TIME_NUM); 190 if (ret < 0) 191 goto out; 192 ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK); 193 if (ret < 0) 194 goto out; 195 if ((ret & ALARM0_IRQ) == 0) 196 alrm->enabled = 1; 197 else 198 alrm->enabled = 0; 199 ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS); 200 if (ret < 0) 201 goto out; 202 if (ret & ALARM0_STATUS) 203 alrm->pending = 1; 204 else 205 alrm->pending = 0; 206 out: 207 return ret; 208 } 209 210 static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 211 { 212 struct max8925_rtc_info *info = dev_get_drvdata(dev); 213 unsigned char buf[TIME_NUM]; 214 int ret; 215 216 ret = data_calc(buf, &alrm->time, TIME_NUM); 217 if (ret < 0) 218 goto out; 219 ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); 220 if (ret < 0) 221 goto out; 222 /* only enable alarm on year/month/day/hour/min/sec */ 223 ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); 224 if (ret < 0) 225 goto out; 226 out: 227 return ret; 228 } 229 230 static const struct rtc_class_ops max8925_rtc_ops = { 231 .read_time = max8925_rtc_read_time, 232 .set_time = max8925_rtc_set_time, 233 .read_alarm = max8925_rtc_read_alarm, 234 .set_alarm = max8925_rtc_set_alarm, 235 }; 236 237 static int __devinit max8925_rtc_probe(struct platform_device *pdev) 238 { 239 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 240 struct max8925_rtc_info *info; 241 int irq, ret; 242 243 info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL); 244 if (!info) 245 return -ENOMEM; 246 info->chip = chip; 247 info->rtc = chip->rtc; 248 info->dev = &pdev->dev; 249 irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0; 250 251 ret = request_threaded_irq(irq, NULL, rtc_update_handler, 252 IRQF_ONESHOT, "rtc-alarm0", info); 253 if (ret < 0) { 254 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", 255 irq, ret); 256 goto out_irq; 257 } 258 259 info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev, 260 &max8925_rtc_ops, THIS_MODULE); 261 ret = PTR_ERR(info->rtc_dev); 262 if (IS_ERR(info->rtc_dev)) { 263 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 264 goto out_rtc; 265 } 266 267 dev_set_drvdata(&pdev->dev, info); 268 platform_set_drvdata(pdev, info); 269 270 return 0; 271 out_rtc: 272 free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); 273 out_irq: 274 kfree(info); 275 return ret; 276 } 277 278 static int __devexit max8925_rtc_remove(struct platform_device *pdev) 279 { 280 struct max8925_rtc_info *info = platform_get_drvdata(pdev); 281 282 if (info) { 283 free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); 284 rtc_device_unregister(info->rtc_dev); 285 kfree(info); 286 } 287 return 0; 288 } 289 290 static struct platform_driver max8925_rtc_driver = { 291 .driver = { 292 .name = "max8925-rtc", 293 .owner = THIS_MODULE, 294 }, 295 .probe = max8925_rtc_probe, 296 .remove = __devexit_p(max8925_rtc_remove), 297 }; 298 299 static int __init max8925_rtc_init(void) 300 { 301 return platform_driver_register(&max8925_rtc_driver); 302 } 303 module_init(max8925_rtc_init); 304 305 static void __exit max8925_rtc_exit(void) 306 { 307 platform_driver_unregister(&max8925_rtc_driver); 308 } 309 module_exit(max8925_rtc_exit); 310 311 MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); 312 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 313 MODULE_LICENSE("GPL"); 314 315