1 /* 2 * RTC driver for Maxim MAX8907 3 * 4 * Copyright (c) 2011-2012, NVIDIA Corporation. 5 * 6 * Based on drivers/rtc/rtc-max8925.c, 7 * Copyright (C) 2009-2010 Marvell International Ltd. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/bcd.h> 15 #include <linux/i2c.h> 16 #include <linux/mfd/max8907.h> 17 #include <linux/module.h> 18 #include <linux/platform_device.h> 19 #include <linux/regmap.h> 20 #include <linux/rtc.h> 21 #include <linux/slab.h> 22 23 enum { 24 RTC_SEC = 0, 25 RTC_MIN, 26 RTC_HOUR, 27 RTC_WEEKDAY, 28 RTC_DATE, 29 RTC_MONTH, 30 RTC_YEAR1, 31 RTC_YEAR2, 32 }; 33 34 #define TIME_NUM 8 35 #define ALARM_1SEC (1 << 7) 36 #define HOUR_12 (1 << 7) 37 #define HOUR_AM_PM (1 << 5) 38 #define ALARM0_IRQ (1 << 3) 39 #define ALARM1_IRQ (1 << 2) 40 #define ALARM0_STATUS (1 << 2) 41 #define ALARM1_STATUS (1 << 1) 42 43 struct max8907_rtc { 44 struct max8907 *max8907; 45 struct regmap *regmap; 46 struct rtc_device *rtc_dev; 47 int irq; 48 }; 49 50 static irqreturn_t max8907_irq_handler(int irq, void *data) 51 { 52 struct max8907_rtc *rtc = data; 53 54 regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); 55 56 rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); 57 58 return IRQ_HANDLED; 59 } 60 61 static void regs_to_tm(u8 *regs, struct rtc_time *tm) 62 { 63 tm->tm_year = bcd2bin(regs[RTC_YEAR2]) * 100 + 64 bcd2bin(regs[RTC_YEAR1]) - 1900; 65 tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1; 66 tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f); 67 tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07) - 1; 68 if (regs[RTC_HOUR] & HOUR_12) { 69 tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f); 70 if (tm->tm_hour == 12) 71 tm->tm_hour = 0; 72 if (regs[RTC_HOUR] & HOUR_AM_PM) 73 tm->tm_hour += 12; 74 } else { 75 tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x03f); 76 } 77 tm->tm_min = bcd2bin(regs[RTC_MIN] & 0x7f); 78 tm->tm_sec = bcd2bin(regs[RTC_SEC] & 0x7f); 79 } 80 81 static void tm_to_regs(struct rtc_time *tm, u8 *regs) 82 { 83 u8 high, low; 84 85 high = (tm->tm_year + 1900) / 100; 86 low = tm->tm_year % 100; 87 regs[RTC_YEAR2] = bin2bcd(high); 88 regs[RTC_YEAR1] = bin2bcd(low); 89 regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1); 90 regs[RTC_DATE] = bin2bcd(tm->tm_mday); 91 regs[RTC_WEEKDAY] = tm->tm_wday + 1; 92 regs[RTC_HOUR] = bin2bcd(tm->tm_hour); 93 regs[RTC_MIN] = bin2bcd(tm->tm_min); 94 regs[RTC_SEC] = bin2bcd(tm->tm_sec); 95 } 96 97 static int max8907_rtc_read_time(struct device *dev, struct rtc_time *tm) 98 { 99 struct max8907_rtc *rtc = dev_get_drvdata(dev); 100 u8 regs[TIME_NUM]; 101 int ret; 102 103 ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_RTC_SEC, regs, 104 TIME_NUM); 105 if (ret < 0) 106 return ret; 107 108 regs_to_tm(regs, tm); 109 110 return 0; 111 } 112 113 static int max8907_rtc_set_time(struct device *dev, struct rtc_time *tm) 114 { 115 struct max8907_rtc *rtc = dev_get_drvdata(dev); 116 u8 regs[TIME_NUM]; 117 118 tm_to_regs(tm, regs); 119 120 return regmap_bulk_write(rtc->regmap, MAX8907_REG_RTC_SEC, regs, 121 TIME_NUM); 122 } 123 124 static int max8907_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 125 { 126 struct max8907_rtc *rtc = dev_get_drvdata(dev); 127 u8 regs[TIME_NUM]; 128 unsigned int val; 129 int ret; 130 131 ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs, 132 TIME_NUM); 133 if (ret < 0) 134 return ret; 135 136 regs_to_tm(regs, &alrm->time); 137 138 ret = regmap_read(rtc->regmap, MAX8907_REG_ALARM0_CNTL, &val); 139 if (ret < 0) 140 return ret; 141 142 alrm->enabled = !!(val & 0x7f); 143 144 return 0; 145 } 146 147 static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 148 { 149 struct max8907_rtc *rtc = dev_get_drvdata(dev); 150 u8 regs[TIME_NUM]; 151 int ret; 152 153 tm_to_regs(&alrm->time, regs); 154 155 /* Disable alarm while we update the target time */ 156 ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); 157 if (ret < 0) 158 return ret; 159 160 ret = regmap_bulk_write(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs, 161 TIME_NUM); 162 if (ret < 0) 163 return ret; 164 165 if (alrm->enabled) 166 ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 167 0x7f, 0x7f); 168 169 return ret; 170 } 171 172 static const struct rtc_class_ops max8907_rtc_ops = { 173 .read_time = max8907_rtc_read_time, 174 .set_time = max8907_rtc_set_time, 175 .read_alarm = max8907_rtc_read_alarm, 176 .set_alarm = max8907_rtc_set_alarm, 177 }; 178 179 static int max8907_rtc_probe(struct platform_device *pdev) 180 { 181 struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); 182 struct max8907_rtc *rtc; 183 int ret; 184 185 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 186 if (!rtc) 187 return -ENOMEM; 188 platform_set_drvdata(pdev, rtc); 189 190 rtc->max8907 = max8907; 191 rtc->regmap = max8907->regmap_rtc; 192 193 rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev, 194 &max8907_rtc_ops, THIS_MODULE); 195 if (IS_ERR(rtc->rtc_dev)) { 196 ret = PTR_ERR(rtc->rtc_dev); 197 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 198 return ret; 199 } 200 201 rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc, 202 MAX8907_IRQ_RTC_ALARM0); 203 if (rtc->irq < 0) { 204 ret = rtc->irq; 205 goto err_unregister; 206 } 207 208 ret = request_threaded_irq(rtc->irq, NULL, max8907_irq_handler, 209 IRQF_ONESHOT, "max8907-alarm0", rtc); 210 if (ret < 0) { 211 dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n", 212 rtc->irq, ret); 213 goto err_unregister; 214 } 215 216 return 0; 217 218 err_unregister: 219 rtc_device_unregister(rtc->rtc_dev); 220 return ret; 221 } 222 223 static int max8907_rtc_remove(struct platform_device *pdev) 224 { 225 struct max8907_rtc *rtc = platform_get_drvdata(pdev); 226 227 free_irq(rtc->irq, rtc); 228 rtc_device_unregister(rtc->rtc_dev); 229 230 return 0; 231 } 232 233 static struct platform_driver max8907_rtc_driver = { 234 .driver = { 235 .name = "max8907-rtc", 236 .owner = THIS_MODULE, 237 }, 238 .probe = max8907_rtc_probe, 239 .remove = max8907_rtc_remove, 240 }; 241 module_platform_driver(max8907_rtc_driver); 242 243 MODULE_DESCRIPTION("Maxim MAX8907 RTC driver"); 244 MODULE_LICENSE("GPL v2"); 245