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 time = readl(rtc->regs + RTC_TIME); 64 /* 65 * WA for failing time set attempts. As stated in HW ERRATA if 66 * more than one second between two time reads is detected 67 * then read once again. 68 */ 69 time_check = readl(rtc->regs + RTC_TIME); 70 if ((time_check - time) > 1) 71 time_check = readl(rtc->regs + RTC_TIME); 72 73 spin_unlock_irqrestore(&rtc->lock, flags); 74 75 rtc_time_to_tm(time_check, tm); 76 77 return 0; 78 } 79 80 static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) 81 { 82 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 83 int ret = 0; 84 unsigned long time, flags; 85 86 ret = rtc_tm_to_time(tm, &time); 87 88 if (ret) 89 goto out; 90 /* 91 * According to errata FE-3124064, Write to RTC TIME register 92 * may fail. As a workaround, after writing to RTC TIME 93 * register, issue a dummy write of 0x0 twice to RTC Status 94 * register. 95 */ 96 spin_lock_irqsave(&rtc->lock, flags); 97 rtc_delayed_write(time, rtc, RTC_TIME); 98 rtc_delayed_write(0, rtc, RTC_STATUS); 99 rtc_delayed_write(0, rtc, RTC_STATUS); 100 spin_unlock_irqrestore(&rtc->lock, flags); 101 102 out: 103 return ret; 104 } 105 106 static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 107 { 108 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 109 unsigned long time, flags; 110 u32 val; 111 112 spin_lock_irqsave(&rtc->lock, flags); 113 114 time = readl(rtc->regs + RTC_ALARM1); 115 val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN; 116 117 spin_unlock_irqrestore(&rtc->lock, flags); 118 119 alrm->enabled = val ? 1 : 0; 120 rtc_time_to_tm(time, &alrm->time); 121 122 return 0; 123 } 124 125 static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 126 { 127 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 128 unsigned long time, flags; 129 int ret = 0; 130 u32 val; 131 132 ret = rtc_tm_to_time(&alrm->time, &time); 133 134 if (ret) 135 goto out; 136 137 spin_lock_irqsave(&rtc->lock, flags); 138 139 rtc_delayed_write(time, rtc, RTC_ALARM1); 140 141 if (alrm->enabled) { 142 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); 143 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); 144 writel(val | SOC_RTC_ALARM1_MASK, 145 rtc->regs_soc + SOC_RTC_INTERRUPT); 146 } 147 148 spin_unlock_irqrestore(&rtc->lock, flags); 149 150 out: 151 return ret; 152 } 153 154 static int armada38x_rtc_alarm_irq_enable(struct device *dev, 155 unsigned int enabled) 156 { 157 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 158 unsigned long flags; 159 160 spin_lock_irqsave(&rtc->lock, flags); 161 162 if (enabled) 163 rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF); 164 else 165 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); 166 167 spin_unlock_irqrestore(&rtc->lock, flags); 168 169 return 0; 170 } 171 172 static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) 173 { 174 struct armada38x_rtc *rtc = data; 175 u32 val; 176 int event = RTC_IRQF | RTC_AF; 177 178 dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq); 179 180 spin_lock(&rtc->lock); 181 182 val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT); 183 184 writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT); 185 val = readl(rtc->regs + RTC_IRQ1_CONF); 186 /* disable all the interrupts for alarm 1 */ 187 rtc_delayed_write(0, rtc, RTC_IRQ1_CONF); 188 /* Ack the event */ 189 rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS); 190 191 spin_unlock(&rtc->lock); 192 193 if (val & RTC_IRQ1_FREQ_EN) { 194 if (val & RTC_IRQ1_FREQ_1HZ) 195 event |= RTC_UF; 196 else 197 event |= RTC_PF; 198 } 199 200 rtc_update_irq(rtc->rtc_dev, 1, event); 201 202 return IRQ_HANDLED; 203 } 204 205 static struct rtc_class_ops armada38x_rtc_ops = { 206 .read_time = armada38x_rtc_read_time, 207 .set_time = armada38x_rtc_set_time, 208 .read_alarm = armada38x_rtc_read_alarm, 209 .set_alarm = armada38x_rtc_set_alarm, 210 .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, 211 }; 212 213 static __init int armada38x_rtc_probe(struct platform_device *pdev) 214 { 215 struct resource *res; 216 struct armada38x_rtc *rtc; 217 int ret; 218 219 rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc), 220 GFP_KERNEL); 221 if (!rtc) 222 return -ENOMEM; 223 224 spin_lock_init(&rtc->lock); 225 226 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc"); 227 rtc->regs = devm_ioremap_resource(&pdev->dev, res); 228 if (IS_ERR(rtc->regs)) 229 return PTR_ERR(rtc->regs); 230 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc"); 231 rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res); 232 if (IS_ERR(rtc->regs_soc)) 233 return PTR_ERR(rtc->regs_soc); 234 235 rtc->irq = platform_get_irq(pdev, 0); 236 237 if (rtc->irq < 0) { 238 dev_err(&pdev->dev, "no irq\n"); 239 return rtc->irq; 240 } 241 if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq, 242 0, pdev->name, rtc) < 0) { 243 dev_warn(&pdev->dev, "Interrupt not available.\n"); 244 rtc->irq = -1; 245 /* 246 * If there is no interrupt available then we can't 247 * use the alarm 248 */ 249 armada38x_rtc_ops.set_alarm = NULL; 250 armada38x_rtc_ops.alarm_irq_enable = NULL; 251 } 252 platform_set_drvdata(pdev, rtc); 253 if (rtc->irq != -1) 254 device_init_wakeup(&pdev->dev, 1); 255 256 rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, 257 &armada38x_rtc_ops, THIS_MODULE); 258 if (IS_ERR(rtc->rtc_dev)) { 259 ret = PTR_ERR(rtc->rtc_dev); 260 dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 261 return ret; 262 } 263 return 0; 264 } 265 266 #ifdef CONFIG_PM_SLEEP 267 static int armada38x_rtc_suspend(struct device *dev) 268 { 269 if (device_may_wakeup(dev)) { 270 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 271 272 return enable_irq_wake(rtc->irq); 273 } 274 275 return 0; 276 } 277 278 static int armada38x_rtc_resume(struct device *dev) 279 { 280 if (device_may_wakeup(dev)) { 281 struct armada38x_rtc *rtc = dev_get_drvdata(dev); 282 283 return disable_irq_wake(rtc->irq); 284 } 285 286 return 0; 287 } 288 #endif 289 290 static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops, 291 armada38x_rtc_suspend, armada38x_rtc_resume); 292 293 #ifdef CONFIG_OF 294 static const struct of_device_id armada38x_rtc_of_match_table[] = { 295 { .compatible = "marvell,armada-380-rtc", }, 296 {} 297 }; 298 MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table); 299 #endif 300 301 static struct platform_driver armada38x_rtc_driver = { 302 .driver = { 303 .name = "armada38x-rtc", 304 .pm = &armada38x_rtc_pm_ops, 305 .of_match_table = of_match_ptr(armada38x_rtc_of_match_table), 306 }, 307 }; 308 309 module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe); 310 311 MODULE_DESCRIPTION("Marvell Armada 38x RTC driver"); 312 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>"); 313 MODULE_LICENSE("GPL"); 314