1/* 2 * APM X-Gene SoC Real Time Clock Driver 3 * 4 * Copyright (c) 2014, Applied Micro Circuits Corporation 5 * Author: Rameshwar Prasad Sahu <rsahu@apm.com> 6 * Loc Ho <lho@apm.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23#include <linux/init.h> 24#include <linux/module.h> 25#include <linux/of.h> 26#include <linux/platform_device.h> 27#include <linux/io.h> 28#include <linux/slab.h> 29#include <linux/clk.h> 30#include <linux/delay.h> 31#include <linux/rtc.h> 32 33/* RTC CSR Registers */ 34#define RTC_CCVR 0x00 35#define RTC_CMR 0x04 36#define RTC_CLR 0x08 37#define RTC_CCR 0x0C 38#define RTC_CCR_IE BIT(0) 39#define RTC_CCR_MASK BIT(1) 40#define RTC_CCR_EN BIT(2) 41#define RTC_CCR_WEN BIT(3) 42#define RTC_STAT 0x10 43#define RTC_STAT_BIT BIT(0) 44#define RTC_RSTAT 0x14 45#define RTC_EOI 0x18 46#define RTC_VER 0x1C 47 48struct xgene_rtc_dev { 49 struct rtc_device *rtc; 50 struct device *dev; 51 unsigned long alarm_time; 52 void __iomem *csr_base; 53 struct clk *clk; 54 unsigned int irq_wake; 55}; 56 57static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm) 58{ 59 struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); 60 61 rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm); 62 return rtc_valid_tm(tm); 63} 64 65static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs) 66{ 67 struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); 68 69 /* 70 * NOTE: After the following write, the RTC_CCVR is only reflected 71 * after the update cycle of 1 seconds. 72 */ 73 writel((u32) secs, pdata->csr_base + RTC_CLR); 74 readl(pdata->csr_base + RTC_CLR); /* Force a barrier */ 75 76 return 0; 77} 78 79static int xgene_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 80{ 81 struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); 82 83 rtc_time_to_tm(pdata->alarm_time, &alrm->time); 84 alrm->enabled = readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE; 85 86 return 0; 87} 88 89static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled) 90{ 91 struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); 92 u32 ccr; 93 94 ccr = readl(pdata->csr_base + RTC_CCR); 95 if (enabled) { 96 ccr &= ~RTC_CCR_MASK; 97 ccr |= RTC_CCR_IE; 98 } else { 99 ccr &= ~RTC_CCR_IE; 100 ccr |= RTC_CCR_MASK; 101 } 102 writel(ccr, pdata->csr_base + RTC_CCR); 103 104 return 0; 105} 106 107static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 108{ 109 struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); 110 unsigned long rtc_time; 111 unsigned long alarm_time; 112 113 rtc_time = readl(pdata->csr_base + RTC_CCVR); 114 rtc_tm_to_time(&alrm->time, &alarm_time); 115 116 pdata->alarm_time = alarm_time; 117 writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR); 118 119 xgene_rtc_alarm_irq_enable(dev, alrm->enabled); 120 121 return 0; 122} 123 124static const struct rtc_class_ops xgene_rtc_ops = { 125 .read_time = xgene_rtc_read_time, 126 .set_mmss = xgene_rtc_set_mmss, 127 .read_alarm = xgene_rtc_read_alarm, 128 .set_alarm = xgene_rtc_set_alarm, 129 .alarm_irq_enable = xgene_rtc_alarm_irq_enable, 130}; 131 132static irqreturn_t xgene_rtc_interrupt(int irq, void *id) 133{ 134 struct xgene_rtc_dev *pdata = (struct xgene_rtc_dev *) id; 135 136 /* Check if interrupt asserted */ 137 if (!(readl(pdata->csr_base + RTC_STAT) & RTC_STAT_BIT)) 138 return IRQ_NONE; 139 140 /* Clear interrupt */ 141 readl(pdata->csr_base + RTC_EOI); 142 143 rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); 144 145 return IRQ_HANDLED; 146} 147 148static int xgene_rtc_probe(struct platform_device *pdev) 149{ 150 struct xgene_rtc_dev *pdata; 151 struct resource *res; 152 int ret; 153 int irq; 154 155 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 156 if (!pdata) 157 return -ENOMEM; 158 platform_set_drvdata(pdev, pdata); 159 pdata->dev = &pdev->dev; 160 161 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 162 pdata->csr_base = devm_ioremap_resource(&pdev->dev, res); 163 if (IS_ERR(pdata->csr_base)) 164 return PTR_ERR(pdata->csr_base); 165 166 irq = platform_get_irq(pdev, 0); 167 if (irq < 0) { 168 dev_err(&pdev->dev, "No IRQ resource\n"); 169 return irq; 170 } 171 ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0, 172 dev_name(&pdev->dev), pdata); 173 if (ret) { 174 dev_err(&pdev->dev, "Could not request IRQ\n"); 175 return ret; 176 } 177 178 pdata->clk = devm_clk_get(&pdev->dev, NULL); 179 if (IS_ERR(pdata->clk)) { 180 dev_err(&pdev->dev, "Couldn't get the clock for RTC\n"); 181 return -ENODEV; 182 } 183 clk_prepare_enable(pdata->clk); 184 185 /* Turn on the clock and the crystal */ 186 writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR); 187 188 device_init_wakeup(&pdev->dev, 1); 189 190 pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 191 &xgene_rtc_ops, THIS_MODULE); 192 if (IS_ERR(pdata->rtc)) { 193 clk_disable_unprepare(pdata->clk); 194 return PTR_ERR(pdata->rtc); 195 } 196 197 /* HW does not support update faster than 1 seconds */ 198 pdata->rtc->uie_unsupported = 1; 199 200 return 0; 201} 202 203static int xgene_rtc_remove(struct platform_device *pdev) 204{ 205 struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); 206 207 xgene_rtc_alarm_irq_enable(&pdev->dev, 0); 208 device_init_wakeup(&pdev->dev, 0); 209 clk_disable_unprepare(pdata->clk); 210 return 0; 211} 212 213#ifdef CONFIG_PM_SLEEP 214static int xgene_rtc_suspend(struct device *dev) 215{ 216 struct platform_device *pdev = to_platform_device(dev); 217 struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); 218 int irq; 219 220 irq = platform_get_irq(pdev, 0); 221 if (device_may_wakeup(&pdev->dev)) { 222 if (!enable_irq_wake(irq)) 223 pdata->irq_wake = 1; 224 } else { 225 xgene_rtc_alarm_irq_enable(dev, 0); 226 clk_disable(pdata->clk); 227 } 228 229 return 0; 230} 231 232static int xgene_rtc_resume(struct device *dev) 233{ 234 struct platform_device *pdev = to_platform_device(dev); 235 struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); 236 int irq; 237 238 irq = platform_get_irq(pdev, 0); 239 if (device_may_wakeup(&pdev->dev)) { 240 if (pdata->irq_wake) { 241 disable_irq_wake(irq); 242 pdata->irq_wake = 0; 243 } 244 } else { 245 clk_enable(pdata->clk); 246 xgene_rtc_alarm_irq_enable(dev, 1); 247 } 248 249 return 0; 250} 251#endif 252 253static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume); 254 255#ifdef CONFIG_OF 256static const struct of_device_id xgene_rtc_of_match[] = { 257 {.compatible = "apm,xgene-rtc" }, 258 { } 259}; 260MODULE_DEVICE_TABLE(of, xgene_rtc_of_match); 261#endif 262 263static struct platform_driver xgene_rtc_driver = { 264 .probe = xgene_rtc_probe, 265 .remove = xgene_rtc_remove, 266 .driver = { 267 .name = "xgene-rtc", 268 .pm = &xgene_rtc_pm_ops, 269 .of_match_table = of_match_ptr(xgene_rtc_of_match), 270 }, 271}; 272 273module_platform_driver(xgene_rtc_driver); 274 275MODULE_DESCRIPTION("APM X-Gene SoC RTC driver"); 276MODULE_AUTHOR("Rameshwar Sahu <rsahu@apm.com>"); 277MODULE_LICENSE("GPL"); 278