1 /* 2 * RTC driver for the Armada 38x Marvell SoCs 3 * 4 * Copyright (C) 2015 Marvell 5 * 6 * Gregory Clement <gregory.clement@free-electrons.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 */ 14 15 #include <linux/delay.h> 16 #include <linux/io.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 #include <linux/rtc.h> 21 22 #define RTC_STATUS 0x0 23 #define RTC_STATUS_ALARM1 BIT(0) 24 #define RTC_STATUS_ALARM2 BIT(1) 25 #define RTC_IRQ1_CONF 0x4 26 #define RTC_IRQ1_AL_EN BIT(0) 27 #define RTC_IRQ1_FREQ_EN BIT(1) 28 #define RTC_IRQ1_FREQ_1HZ BIT(2) 29 #define RTC_TIME 0xC 30 #define RTC_ALARM1 0x10 31 32 #define SOC_RTC_INTERRUPT 0x8 33 #define SOC_RTC_ALARM1 BIT(0) 34 #define SOC_RTC_ALARM2 BIT(1) 35 #define SOC_RTC_ALARM1_MASK BIT(2) 36 #define SOC_RTC_ALARM2_MASK BIT(3) 37 38 struct armada38x_rtc { 39 struct rtc_device *rtc_dev; 40 void __iomem *regs; 41 void __iomem *regs_soc; 42 spinlock_t lock; 43 int irq; 44 }; 45 46 /* 47 * According to the datasheet, the OS should wait 5us after every 48 * register write to the RTC hard macro so that the required update 49 * can occur without holding off the system bus 50 */ 51 static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset) 52 { 53 writel(val, rtc->regs + offset); 54 udelay(5); 55 } 56 57 static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) 58 { 59 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 60 unsigned long time, time_check, flags; 61 62 spin_lock_irqsave(&rtc->lock, flags); 63 64 time = readl(rtc->regs + RTC_TIME); 65 /* 66 * WA for failing time set attempts. As stated in HW ERRATA if 67 * more than one second between two time reads is detected 68 * then read once again. 69 */ 70 time_check = readl(rtc->regs + RTC_TIME); 71 if ((time_check - time) > 1) 72 time_check = readl(rtc->regs + RTC_TIME); 73 74 spin_unlock_irqrestore(&rtc->lock, flags); 75 76 rtc_time_to_tm(time_check, tm); 77 78 return 0; 79 } 80 81 static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) 82 { 83 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 84 int ret = 0; 85 unsigned long time, flags; 86 87 ret = rtc_tm_to_time(tm, &time); 88 89 if (ret) 90 goto out; 91 /* 92 * Setting the RTC time not always succeeds. According to the 93 * errata we need to first write on the status register and 94 * then wait for 100ms before writing to the time register to be 95 * sure that the data will be taken into account. 96 */ 97 spin_lock_irqsave(&rtc->lock, flags); 98 99 rtc_delayed_write(0, rtc, RTC_STATUS); 100 101 spin_unlock_irqrestore(&rtc->lock, flags); 102 103 msleep(100); 104 105 spin_lock_irqsave(&rtc->lock, flags); 106 107 rtc_delayed_write(time, rtc, RTC_TIME); 108 109 spin_unlock_irqrestore(&rtc->lock, flags); 110 out: 111 return ret; 112 } 113 114 static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 115 { 116 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 117 unsigned long time, flags; 118 u32 val; 119 120 spin_lock_irqsave(&rtc->lock, flags); 121 122 time = readl(rtc->regs + RTC_ALARM1); 123 val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN; 124 125 spin_unlock_irqrestore(&rtc->lock, flags); 126 127 alrm->enabled = val ? 1 : 0; 128 rtc_time_to_tm(time, &alrm->time); 129 130 return 0; 131 } 132 133 static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 134 { 135 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 136 unsigned long time, flags; 137 int ret = 0; 138 u32 val; 139 140 ret = rtc_tm_to_time(&alrm->time, &time); 141 142 if (ret) 143 goto out; 144 145 spin_lock_irqsave(&rtc->lock, flags); 146 147 rtc_delayed_write(time, rtc, RTC_ALARM1); 148 149 if (alrm->enabled) { 150 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); 151 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); 152 writel(val | SOC_RTC_ALARM1_MASK, 153 rtc->regs_soc + SOC_RTC_INTERRUPT); 154 } 155 156 spin_unlock_irqrestore(&rtc->lock, flags); 157 158 out: 159 return ret; 160 } 161 162 static int armada38x_rtc_alarm_irq_enable(struct device *dev, 163 unsigned int enabled) 164 { 165 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 166 unsigned long flags; 167 168 spin_lock_irqsave(&rtc->lock, flags); 169 170 if (enabled) 171 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); 172 else 173 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); 174 175 spin_unlock_irqrestore(&rtc->lock, flags); 176 177 return 0; 178 } 179 180 static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) 181 { 182 struct armada38x_rtc *rtc = data; 183 u32 val; 184 int event = RTC_IRQF | RTC_AF; 185 186 dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq); 187 188 spin_lock(&rtc->lock); 189 190 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); 191 192 writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT); 193 val = readl(rtc->regs + RTC_IRQ1_CONF); 194 /* disable all the interrupts for alarm 1 */ 195 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); 196 /* Ack the event */ 197 rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS); 198 199 spin_unlock(&rtc->lock); 200 201 if (val & RTC_IRQ1_FREQ_EN) { 202 if (val & RTC_IRQ1_FREQ_1HZ) 203 event |= RTC_UF; 204 else 205 event |= RTC_PF; 206 } 207 208 rtc_update_irq(rtc->rtc_dev, 1, event); 209 210 return IRQ_HANDLED; 211 } 212 213 static struct rtc_class_ops armada38x_rtc_ops = { 214 .read_time = armada38x_rtc_read_time, 215 .set_time = armada38x_rtc_set_time, 216 .read_alarm = armada38x_rtc_read_alarm, 217 .set_alarm = armada38x_rtc_set_alarm, 218 .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, 219 }; 220 221 static __init int armada38x_rtc_probe(struct platform_device *pdev) 222 { 223 struct resource *res; 224 struct armada38x_rtc *rtc; 225 int ret; 226 227 rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc), 228 GFP_KERNEL); 229 if (!rtc) 230 return -ENOMEM; 231 232 spin_lock_init(&rtc->lock); 233 234 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); 235 rtc->regs = devm_ioremap_resource(&pdev->dev, res); 236 if (IS_ERR(rtc->regs)) 237 return PTR_ERR(rtc->regs); 238 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc"); 239 rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res); 240 if (IS_ERR(rtc->regs_soc)) 241 return PTR_ERR(rtc->regs_soc); 242 243 rtc->irq = platform_get_irq(pdev, 0); 244 245 if (rtc->irq < 0) { 246 dev_err(&pdev->dev, "no irq\n"); 247 return rtc->irq; 248 } 249 if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq, 250 0, pdev->name, rtc) < 0) { 251 dev_warn(&pdev->dev, "Interrupt not available.\n"); 252 rtc->irq = -1; 253 /* 254 * If there is no interrupt available then we can't 255 * use the alarm 256 */ 257 armada38x_rtc_ops.set_alarm = NULL; 258 armada38x_rtc_ops.alarm_irq_enable = NULL; 259 } 260 platform_set_drvdata(pdev, rtc); 261 if (rtc->irq != -1) 262 device_init_wakeup(&pdev->dev, 1); 263 264 rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, 265 &armada38x_rtc_ops, THIS_MODULE); 266 if (IS_ERR(rtc->rtc_dev)) { 267 ret = PTR_ERR(rtc->rtc_dev); 268 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 269 return ret; 270 } 271 return 0; 272 } 273 274 #ifdef CONFIG_PM_SLEEP 275 static int armada38x_rtc_suspend(struct device *dev) 276 { 277 if (device_may_wakeup(dev)) { 278 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 279 280 return enable_irq_wake(rtc->irq); 281 } 282 283 return 0; 284 } 285 286 static int armada38x_rtc_resume(struct device *dev) 287 { 288 if (device_may_wakeup(dev)) { 289 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 290 291 return disable_irq_wake(rtc->irq); 292 } 293 294 return 0; 295 } 296 #endif 297 298 static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops, 299 armada38x_rtc_suspend, armada38x_rtc_resume); 300 301 #ifdef CONFIG_OF 302 static const struct of_device_id armada38x_rtc_of_match_table[] = { 303 { .compatible = "marvell,armada-380-rtc", }, 304 {} 305 }; 306 #endif 307 308 static struct platform_driver armada38x_rtc_driver = { 309 .driver = { 310 .name = "armada38x-rtc", 311 .pm = &armada38x_rtc_pm_ops, 312 .of_match_table = of_match_ptr(armada38x_rtc_of_match_table), 313 }, 314 }; 315 316 module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe); 317 318 MODULE_DESCRIPTION("Marvell Armada 38x RTC driver"); 319 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>"); 320 MODULE_LICENSE("GPL"); 321