0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/errno.h>
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/types.h>
0014 #include <linux/rtc.h>
0015 #include <linux/bcd.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/mfd/rc5t583.h>
0019
0020 struct rc5t583_rtc {
0021 struct rtc_device *rtc;
0022
0023 u32 irqen;
0024 };
0025
0026
0027 #define NUM_TIME_REGS (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1)
0028
0029
0030 #define NUM_YAL_REGS (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1)
0031
0032
0033 #define SET_YAL BIT(5)
0034
0035
0036 #define GET_YAL_STATUS BIT(3)
0037
0038 static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
0039 {
0040 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0041 u8 val;
0042
0043
0044 val = enabled ? SET_YAL : 0;
0045
0046 return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL,
0047 val);
0048 }
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm)
0060 {
0061 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0062 u8 rtc_data[NUM_TIME_REGS];
0063 int ret;
0064
0065 ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
0066 NUM_TIME_REGS);
0067 if (ret < 0) {
0068 dev_err(dev, "RTC read time failed with err:%d\n", ret);
0069 return ret;
0070 }
0071
0072 tm->tm_sec = bcd2bin(rtc_data[0]);
0073 tm->tm_min = bcd2bin(rtc_data[1]);
0074 tm->tm_hour = bcd2bin(rtc_data[2]);
0075 tm->tm_wday = bcd2bin(rtc_data[3]);
0076 tm->tm_mday = bcd2bin(rtc_data[4]);
0077 tm->tm_mon = bcd2bin(rtc_data[5]) - 1;
0078 tm->tm_year = bcd2bin(rtc_data[6]) + 100;
0079
0080 return ret;
0081 }
0082
0083 static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm)
0084 {
0085 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0086 unsigned char rtc_data[NUM_TIME_REGS];
0087 int ret;
0088
0089 rtc_data[0] = bin2bcd(tm->tm_sec);
0090 rtc_data[1] = bin2bcd(tm->tm_min);
0091 rtc_data[2] = bin2bcd(tm->tm_hour);
0092 rtc_data[3] = bin2bcd(tm->tm_wday);
0093 rtc_data[4] = bin2bcd(tm->tm_mday);
0094 rtc_data[5] = bin2bcd(tm->tm_mon + 1);
0095 rtc_data[6] = bin2bcd(tm->tm_year - 100);
0096
0097 ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
0098 NUM_TIME_REGS);
0099 if (ret < 0) {
0100 dev_err(dev, "RTC set time failed with error %d\n", ret);
0101 return ret;
0102 }
0103
0104 return ret;
0105 }
0106
0107 static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
0108 {
0109 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0110 unsigned char alarm_data[NUM_YAL_REGS];
0111 u32 interrupt_enable;
0112 int ret;
0113
0114 ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
0115 NUM_YAL_REGS);
0116 if (ret < 0) {
0117 dev_err(dev, "rtc_read_alarm error %d\n", ret);
0118 return ret;
0119 }
0120
0121 alm->time.tm_sec = 0;
0122 alm->time.tm_min = bcd2bin(alarm_data[0]);
0123 alm->time.tm_hour = bcd2bin(alarm_data[1]);
0124 alm->time.tm_mday = bcd2bin(alarm_data[2]);
0125 alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1;
0126 alm->time.tm_year = bcd2bin(alarm_data[4]) + 100;
0127
0128 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable);
0129 if (ret < 0)
0130 return ret;
0131
0132
0133 if (interrupt_enable & SET_YAL)
0134 alm->enabled = 1;
0135
0136 return ret;
0137 }
0138
0139 static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
0140 {
0141 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0142 unsigned char alarm_data[NUM_YAL_REGS];
0143 int ret;
0144
0145 ret = rc5t583_rtc_alarm_irq_enable(dev, 0);
0146 if (ret)
0147 return ret;
0148
0149 alarm_data[0] = bin2bcd(alm->time.tm_min);
0150 alarm_data[1] = bin2bcd(alm->time.tm_hour);
0151 alarm_data[2] = bin2bcd(alm->time.tm_mday);
0152 alarm_data[3] = bin2bcd(alm->time.tm_mon + 1);
0153 alarm_data[4] = bin2bcd(alm->time.tm_year - 100);
0154
0155 ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
0156 NUM_YAL_REGS);
0157 if (ret) {
0158 dev_err(dev, "rtc_set_alarm error %d\n", ret);
0159 return ret;
0160 }
0161
0162 if (alm->enabled)
0163 ret = rc5t583_rtc_alarm_irq_enable(dev, 1);
0164
0165 return ret;
0166 }
0167
0168 static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc)
0169 {
0170 struct device *dev = rtc;
0171 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0172 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0173 unsigned long events = 0;
0174 int ret;
0175 u32 rtc_reg;
0176
0177 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg);
0178 if (ret < 0)
0179 return IRQ_NONE;
0180
0181 if (rtc_reg & GET_YAL_STATUS) {
0182 events = RTC_IRQF | RTC_AF;
0183
0184 rtc_reg &= ~GET_YAL_STATUS;
0185 }
0186
0187 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg);
0188 if (ret)
0189 return IRQ_NONE;
0190
0191
0192 rtc_update_irq(rc5t583_rtc->rtc, 1, events);
0193
0194 return IRQ_HANDLED;
0195 }
0196
0197 static const struct rtc_class_ops rc5t583_rtc_ops = {
0198 .read_time = rc5t583_rtc_read_time,
0199 .set_time = rc5t583_rtc_set_time,
0200 .read_alarm = rc5t583_rtc_read_alarm,
0201 .set_alarm = rc5t583_rtc_set_alarm,
0202 .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,
0203 };
0204
0205 static int rc5t583_rtc_probe(struct platform_device *pdev)
0206 {
0207 struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
0208 struct rc5t583_rtc *ricoh_rtc;
0209 struct rc5t583_platform_data *pmic_plat_data;
0210 int ret;
0211 int irq;
0212
0213 ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc),
0214 GFP_KERNEL);
0215 if (!ricoh_rtc)
0216 return -ENOMEM;
0217
0218 platform_set_drvdata(pdev, ricoh_rtc);
0219
0220
0221 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0);
0222 if (ret < 0)
0223 return ret;
0224
0225
0226 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0);
0227 if (ret < 0) {
0228 dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
0229 return -EBUSY;
0230 }
0231
0232 pmic_plat_data = dev_get_platdata(rc5t583->dev);
0233 irq = pmic_plat_data->irq_base;
0234 if (irq <= 0) {
0235 dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
0236 irq);
0237 return ret;
0238 }
0239
0240 irq += RC5T583_IRQ_YALE;
0241 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0242 rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW,
0243 "rtc-rc5t583", &pdev->dev);
0244 if (ret < 0) {
0245 dev_err(&pdev->dev, "IRQ is not free.\n");
0246 return ret;
0247 }
0248 device_init_wakeup(&pdev->dev, 1);
0249
0250 ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
0251 &rc5t583_rtc_ops, THIS_MODULE);
0252 if (IS_ERR(ricoh_rtc->rtc)) {
0253 ret = PTR_ERR(ricoh_rtc->rtc);
0254 dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
0255 return ret;
0256 }
0257
0258 return 0;
0259 }
0260
0261
0262
0263
0264
0265 static int rc5t583_rtc_remove(struct platform_device *pdev)
0266 {
0267 struct rc5t583_rtc *rc5t583_rtc = platform_get_drvdata(pdev);
0268
0269 rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0);
0270 return 0;
0271 }
0272
0273 #ifdef CONFIG_PM_SLEEP
0274 static int rc5t583_rtc_suspend(struct device *dev)
0275 {
0276 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0277 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0278 int ret;
0279
0280
0281 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1,
0282 &rc5t583_rtc->irqen);
0283 return ret;
0284 }
0285
0286 static int rc5t583_rtc_resume(struct device *dev)
0287 {
0288 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0289 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0290
0291
0292 return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1,
0293 rc5t583_rtc->irqen);
0294 }
0295 #endif
0296
0297 static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
0298 rc5t583_rtc_resume);
0299
0300 static struct platform_driver rc5t583_rtc_driver = {
0301 .probe = rc5t583_rtc_probe,
0302 .remove = rc5t583_rtc_remove,
0303 .driver = {
0304 .name = "rtc-rc5t583",
0305 .pm = &rc5t583_rtc_pm_ops,
0306 },
0307 };
0308
0309 module_platform_driver(rc5t583_rtc_driver);
0310 MODULE_ALIAS("platform:rtc-rc5t583");
0311 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
0312 MODULE_LICENSE("GPL v2");