0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/err.h>
0011 #include <linux/irqdomain.h>
0012 #include <linux/mfd/lp8788.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/rtc.h>
0016 #include <linux/slab.h>
0017
0018
0019 #define LP8788_INTEN_3 0x05
0020 #define LP8788_RTC_UNLOCK 0x64
0021 #define LP8788_RTC_SEC 0x70
0022 #define LP8788_ALM1_SEC 0x77
0023 #define LP8788_ALM1_EN 0x7D
0024 #define LP8788_ALM2_SEC 0x7E
0025 #define LP8788_ALM2_EN 0x84
0026
0027
0028 #define LP8788_INT_RTC_ALM1_M BIT(1)
0029 #define LP8788_INT_RTC_ALM1_S 1
0030 #define LP8788_INT_RTC_ALM2_M BIT(2)
0031 #define LP8788_INT_RTC_ALM2_S 2
0032 #define LP8788_ALM_EN_M BIT(7)
0033 #define LP8788_ALM_EN_S 7
0034
0035 #define DEFAULT_ALARM_SEL LP8788_ALARM_1
0036 #define LP8788_MONTH_OFFSET 1
0037 #define LP8788_BASE_YEAR 2000
0038 #define MAX_WDAY_BITS 7
0039 #define LP8788_WDAY_SET 1
0040 #define RTC_UNLOCK 0x1
0041 #define RTC_LATCH 0x2
0042 #define ALARM_IRQ_FLAG (RTC_IRQF | RTC_AF)
0043
0044 enum lp8788_time {
0045 LPTIME_SEC,
0046 LPTIME_MIN,
0047 LPTIME_HOUR,
0048 LPTIME_MDAY,
0049 LPTIME_MON,
0050 LPTIME_YEAR,
0051 LPTIME_WDAY,
0052 LPTIME_MAX,
0053 };
0054
0055 struct lp8788_rtc {
0056 struct lp8788 *lp;
0057 struct rtc_device *rdev;
0058 enum lp8788_alarm_sel alarm;
0059 int irq;
0060 };
0061
0062 static const u8 addr_alarm_sec[LP8788_ALARM_MAX] = {
0063 LP8788_ALM1_SEC,
0064 LP8788_ALM2_SEC,
0065 };
0066
0067 static const u8 addr_alarm_en[LP8788_ALARM_MAX] = {
0068 LP8788_ALM1_EN,
0069 LP8788_ALM2_EN,
0070 };
0071
0072 static const u8 mask_alarm_en[LP8788_ALARM_MAX] = {
0073 LP8788_INT_RTC_ALM1_M,
0074 LP8788_INT_RTC_ALM2_M,
0075 };
0076
0077 static const u8 shift_alarm_en[LP8788_ALARM_MAX] = {
0078 LP8788_INT_RTC_ALM1_S,
0079 LP8788_INT_RTC_ALM2_S,
0080 };
0081
0082 static int _to_tm_wday(u8 lp8788_wday)
0083 {
0084 int i;
0085
0086 if (lp8788_wday == 0)
0087 return 0;
0088
0089
0090 for (i = 0; i < MAX_WDAY_BITS; i++) {
0091 if ((lp8788_wday >> i) == LP8788_WDAY_SET)
0092 break;
0093 }
0094
0095 return i + 1;
0096 }
0097
0098 static inline int _to_lp8788_wday(int tm_wday)
0099 {
0100 return LP8788_WDAY_SET << (tm_wday - 1);
0101 }
0102
0103 static void lp8788_rtc_unlock(struct lp8788 *lp)
0104 {
0105 lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_UNLOCK);
0106 lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_LATCH);
0107 }
0108
0109 static int lp8788_rtc_read_time(struct device *dev, struct rtc_time *tm)
0110 {
0111 struct lp8788_rtc *rtc = dev_get_drvdata(dev);
0112 struct lp8788 *lp = rtc->lp;
0113 u8 data[LPTIME_MAX];
0114 int ret;
0115
0116 lp8788_rtc_unlock(lp);
0117
0118 ret = lp8788_read_multi_bytes(lp, LP8788_RTC_SEC, data, LPTIME_MAX);
0119 if (ret)
0120 return ret;
0121
0122 tm->tm_sec = data[LPTIME_SEC];
0123 tm->tm_min = data[LPTIME_MIN];
0124 tm->tm_hour = data[LPTIME_HOUR];
0125 tm->tm_mday = data[LPTIME_MDAY];
0126 tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET;
0127 tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900;
0128 tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]);
0129
0130 return 0;
0131 }
0132
0133 static int lp8788_rtc_set_time(struct device *dev, struct rtc_time *tm)
0134 {
0135 struct lp8788_rtc *rtc = dev_get_drvdata(dev);
0136 struct lp8788 *lp = rtc->lp;
0137 u8 data[LPTIME_MAX - 1];
0138 int ret, i, year;
0139
0140 year = tm->tm_year + 1900 - LP8788_BASE_YEAR;
0141 if (year < 0) {
0142 dev_err(lp->dev, "invalid year: %d\n", year);
0143 return -EINVAL;
0144 }
0145
0146
0147 data[LPTIME_SEC] = tm->tm_sec;
0148 data[LPTIME_MIN] = tm->tm_min;
0149 data[LPTIME_HOUR] = tm->tm_hour;
0150 data[LPTIME_MDAY] = tm->tm_mday;
0151 data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET;
0152 data[LPTIME_YEAR] = year;
0153
0154 for (i = 0; i < ARRAY_SIZE(data); i++) {
0155 ret = lp8788_write_byte(lp, LP8788_RTC_SEC + i, data[i]);
0156 if (ret)
0157 return ret;
0158 }
0159
0160 return 0;
0161 }
0162
0163 static int lp8788_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
0164 {
0165 struct lp8788_rtc *rtc = dev_get_drvdata(dev);
0166 struct lp8788 *lp = rtc->lp;
0167 struct rtc_time *tm = &alarm->time;
0168 u8 addr, data[LPTIME_MAX];
0169 int ret;
0170
0171 addr = addr_alarm_sec[rtc->alarm];
0172 ret = lp8788_read_multi_bytes(lp, addr, data, LPTIME_MAX);
0173 if (ret)
0174 return ret;
0175
0176 tm->tm_sec = data[LPTIME_SEC];
0177 tm->tm_min = data[LPTIME_MIN];
0178 tm->tm_hour = data[LPTIME_HOUR];
0179 tm->tm_mday = data[LPTIME_MDAY];
0180 tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET;
0181 tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900;
0182 tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]);
0183 alarm->enabled = data[LPTIME_WDAY] & LP8788_ALM_EN_M;
0184
0185 return 0;
0186 }
0187
0188 static int lp8788_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
0189 {
0190 struct lp8788_rtc *rtc = dev_get_drvdata(dev);
0191 struct lp8788 *lp = rtc->lp;
0192 struct rtc_time *tm = &alarm->time;
0193 u8 addr, data[LPTIME_MAX];
0194 int ret, i, year;
0195
0196 year = tm->tm_year + 1900 - LP8788_BASE_YEAR;
0197 if (year < 0) {
0198 dev_err(lp->dev, "invalid year: %d\n", year);
0199 return -EINVAL;
0200 }
0201
0202 data[LPTIME_SEC] = tm->tm_sec;
0203 data[LPTIME_MIN] = tm->tm_min;
0204 data[LPTIME_HOUR] = tm->tm_hour;
0205 data[LPTIME_MDAY] = tm->tm_mday;
0206 data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET;
0207 data[LPTIME_YEAR] = year;
0208 data[LPTIME_WDAY] = _to_lp8788_wday(tm->tm_wday);
0209
0210 for (i = 0; i < ARRAY_SIZE(data); i++) {
0211 addr = addr_alarm_sec[rtc->alarm] + i;
0212 ret = lp8788_write_byte(lp, addr, data[i]);
0213 if (ret)
0214 return ret;
0215 }
0216
0217 alarm->enabled = 1;
0218 addr = addr_alarm_en[rtc->alarm];
0219
0220 return lp8788_update_bits(lp, addr, LP8788_ALM_EN_M,
0221 alarm->enabled << LP8788_ALM_EN_S);
0222 }
0223
0224 static int lp8788_alarm_irq_enable(struct device *dev, unsigned int enable)
0225 {
0226 struct lp8788_rtc *rtc = dev_get_drvdata(dev);
0227 struct lp8788 *lp = rtc->lp;
0228 u8 mask, shift;
0229
0230 if (!rtc->irq)
0231 return -EIO;
0232
0233 mask = mask_alarm_en[rtc->alarm];
0234 shift = shift_alarm_en[rtc->alarm];
0235
0236 return lp8788_update_bits(lp, LP8788_INTEN_3, mask, enable << shift);
0237 }
0238
0239 static const struct rtc_class_ops lp8788_rtc_ops = {
0240 .read_time = lp8788_rtc_read_time,
0241 .set_time = lp8788_rtc_set_time,
0242 .read_alarm = lp8788_read_alarm,
0243 .set_alarm = lp8788_set_alarm,
0244 .alarm_irq_enable = lp8788_alarm_irq_enable,
0245 };
0246
0247 static irqreturn_t lp8788_alarm_irq_handler(int irq, void *ptr)
0248 {
0249 struct lp8788_rtc *rtc = ptr;
0250
0251 rtc_update_irq(rtc->rdev, 1, ALARM_IRQ_FLAG);
0252 return IRQ_HANDLED;
0253 }
0254
0255 static int lp8788_alarm_irq_register(struct platform_device *pdev,
0256 struct lp8788_rtc *rtc)
0257 {
0258 struct resource *r;
0259 struct lp8788 *lp = rtc->lp;
0260 struct irq_domain *irqdm = lp->irqdm;
0261 int irq;
0262
0263 rtc->irq = 0;
0264
0265
0266 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, LP8788_ALM_IRQ);
0267 if (!r)
0268 return 0;
0269
0270 if (rtc->alarm == LP8788_ALARM_1)
0271 irq = r->start;
0272 else
0273 irq = r->end;
0274
0275 rtc->irq = irq_create_mapping(irqdm, irq);
0276
0277 return devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
0278 lp8788_alarm_irq_handler,
0279 0, LP8788_ALM_IRQ, rtc);
0280 }
0281
0282 static int lp8788_rtc_probe(struct platform_device *pdev)
0283 {
0284 struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
0285 struct lp8788_rtc *rtc;
0286 struct device *dev = &pdev->dev;
0287
0288 rtc = devm_kzalloc(dev, sizeof(struct lp8788_rtc), GFP_KERNEL);
0289 if (!rtc)
0290 return -ENOMEM;
0291
0292 rtc->lp = lp;
0293 rtc->alarm = lp->pdata ? lp->pdata->alarm_sel : DEFAULT_ALARM_SEL;
0294 platform_set_drvdata(pdev, rtc);
0295
0296 device_init_wakeup(dev, 1);
0297
0298 rtc->rdev = devm_rtc_device_register(dev, "lp8788_rtc",
0299 &lp8788_rtc_ops, THIS_MODULE);
0300 if (IS_ERR(rtc->rdev)) {
0301 dev_err(dev, "can not register rtc device\n");
0302 return PTR_ERR(rtc->rdev);
0303 }
0304
0305 if (lp8788_alarm_irq_register(pdev, rtc))
0306 dev_warn(lp->dev, "no rtc irq handler\n");
0307
0308 return 0;
0309 }
0310
0311 static struct platform_driver lp8788_rtc_driver = {
0312 .probe = lp8788_rtc_probe,
0313 .driver = {
0314 .name = LP8788_DEV_RTC,
0315 },
0316 };
0317 module_platform_driver(lp8788_rtc_driver);
0318
0319 MODULE_DESCRIPTION("Texas Instruments LP8788 RTC Driver");
0320 MODULE_AUTHOR("Milo Kim");
0321 MODULE_LICENSE("GPL");
0322 MODULE_ALIAS("platform:lp8788-rtc");