Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TI LP8788 MFD - rtc driver
0004  *
0005  * Copyright 2012 Texas Instruments
0006  *
0007  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
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 /* register address */
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 /* mask/shift bits */
0028 #define LP8788_INT_RTC_ALM1_M       BIT(1)  /* Addr 05h */
0029 #define LP8788_INT_RTC_ALM1_S       1
0030 #define LP8788_INT_RTC_ALM2_M       BIT(2)  /* Addr 05h */
0031 #define LP8788_INT_RTC_ALM2_S       2
0032 #define LP8788_ALM_EN_M         BIT(7)  /* Addr 7Dh or 84h */
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     /* lookup defined weekday from read register value */
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     /* because rtc weekday is a readonly register, do not update */
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     /* even the alarm IRQ number is not specified, rtc time should work */
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");