1 // SPDX-License-Identifier: GPL-2.0 2 /* drivers/rtc/rtc-goldfish.c 3 * 4 * Copyright (C) 2007 Google, Inc. 5 * Copyright (C) 2017 Imagination Technologies Ltd. 6 */ 7 8 #include <linux/io.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/rtc.h> 13 14 #define TIMER_TIME_LOW 0x00 /* get low bits of current time */ 15 /* and update TIMER_TIME_HIGH */ 16 #define TIMER_TIME_HIGH 0x04 /* get high bits of time at last */ 17 /* TIMER_TIME_LOW read */ 18 #define TIMER_ALARM_LOW 0x08 /* set low bits of alarm and */ 19 /* activate it */ 20 #define TIMER_ALARM_HIGH 0x0c /* set high bits of next alarm */ 21 #define TIMER_IRQ_ENABLED 0x10 22 #define TIMER_CLEAR_ALARM 0x14 23 #define TIMER_ALARM_STATUS 0x18 24 #define TIMER_CLEAR_INTERRUPT 0x1c 25 26 struct goldfish_rtc { 27 void __iomem *base; 28 int irq; 29 struct rtc_device *rtc; 30 }; 31 32 static int goldfish_rtc_read_alarm(struct device *dev, 33 struct rtc_wkalrm *alrm) 34 { 35 u64 rtc_alarm; 36 u64 rtc_alarm_low; 37 u64 rtc_alarm_high; 38 void __iomem *base; 39 struct goldfish_rtc *rtcdrv; 40 41 rtcdrv = dev_get_drvdata(dev); 42 base = rtcdrv->base; 43 44 rtc_alarm_low = readl(base + TIMER_ALARM_LOW); 45 rtc_alarm_high = readl(base + TIMER_ALARM_HIGH); 46 rtc_alarm = (rtc_alarm_high << 32) | rtc_alarm_low; 47 48 do_div(rtc_alarm, NSEC_PER_SEC); 49 memset(alrm, 0, sizeof(struct rtc_wkalrm)); 50 51 rtc_time64_to_tm(rtc_alarm, &alrm->time); 52 53 if (readl(base + TIMER_ALARM_STATUS)) 54 alrm->enabled = 1; 55 else 56 alrm->enabled = 0; 57 58 return 0; 59 } 60 61 static int goldfish_rtc_set_alarm(struct device *dev, 62 struct rtc_wkalrm *alrm) 63 { 64 struct goldfish_rtc *rtcdrv; 65 u64 rtc_alarm64; 66 u64 rtc_status_reg; 67 void __iomem *base; 68 69 rtcdrv = dev_get_drvdata(dev); 70 base = rtcdrv->base; 71 72 if (alrm->enabled) { 73 rtc_alarm64 = rtc_tm_to_time64(&alrm->time) * NSEC_PER_SEC; 74 writel((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH); 75 writel(rtc_alarm64, base + TIMER_ALARM_LOW); 76 } else { 77 /* 78 * if this function was called with enabled=0 79 * then it could mean that the application is 80 * trying to cancel an ongoing alarm 81 */ 82 rtc_status_reg = readl(base + TIMER_ALARM_STATUS); 83 if (rtc_status_reg) 84 writel(1, base + TIMER_CLEAR_ALARM); 85 } 86 87 return 0; 88 } 89 90 static int goldfish_rtc_alarm_irq_enable(struct device *dev, 91 unsigned int enabled) 92 { 93 void __iomem *base; 94 struct goldfish_rtc *rtcdrv; 95 96 rtcdrv = dev_get_drvdata(dev); 97 base = rtcdrv->base; 98 99 if (enabled) 100 writel(1, base + TIMER_IRQ_ENABLED); 101 else 102 writel(0, base + TIMER_IRQ_ENABLED); 103 104 return 0; 105 } 106 107 static irqreturn_t goldfish_rtc_interrupt(int irq, void *dev_id) 108 { 109 struct goldfish_rtc *rtcdrv = dev_id; 110 void __iomem *base = rtcdrv->base; 111 112 writel(1, base + TIMER_CLEAR_INTERRUPT); 113 114 rtc_update_irq(rtcdrv->rtc, 1, RTC_IRQF | RTC_AF); 115 116 return IRQ_HANDLED; 117 } 118 119 static int goldfish_rtc_read_time(struct device *dev, struct rtc_time *tm) 120 { 121 struct goldfish_rtc *rtcdrv; 122 void __iomem *base; 123 u64 time_high; 124 u64 time_low; 125 u64 time; 126 127 rtcdrv = dev_get_drvdata(dev); 128 base = rtcdrv->base; 129 130 time_low = readl(base + TIMER_TIME_LOW); 131 time_high = readl(base + TIMER_TIME_HIGH); 132 time = (time_high << 32) | time_low; 133 134 do_div(time, NSEC_PER_SEC); 135 136 rtc_time64_to_tm(time, tm); 137 138 return 0; 139 } 140 141 static int goldfish_rtc_set_time(struct device *dev, struct rtc_time *tm) 142 { 143 struct goldfish_rtc *rtcdrv; 144 void __iomem *base; 145 u64 now64; 146 147 rtcdrv = dev_get_drvdata(dev); 148 base = rtcdrv->base; 149 150 now64 = rtc_tm_to_time64(tm) * NSEC_PER_SEC; 151 writel((now64 >> 32), base + TIMER_TIME_HIGH); 152 writel(now64, base + TIMER_TIME_LOW); 153 154 return 0; 155 } 156 157 static const struct rtc_class_ops goldfish_rtc_ops = { 158 .read_time = goldfish_rtc_read_time, 159 .set_time = goldfish_rtc_set_time, 160 .read_alarm = goldfish_rtc_read_alarm, 161 .set_alarm = goldfish_rtc_set_alarm, 162 .alarm_irq_enable = goldfish_rtc_alarm_irq_enable 163 }; 164 165 static int goldfish_rtc_probe(struct platform_device *pdev) 166 { 167 struct goldfish_rtc *rtcdrv; 168 struct resource *r; 169 int err; 170 171 rtcdrv = devm_kzalloc(&pdev->dev, sizeof(*rtcdrv), GFP_KERNEL); 172 if (!rtcdrv) 173 return -ENOMEM; 174 175 platform_set_drvdata(pdev, rtcdrv); 176 177 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 178 if (!r) 179 return -ENODEV; 180 181 rtcdrv->base = devm_ioremap_resource(&pdev->dev, r); 182 if (IS_ERR(rtcdrv->base)) 183 return -ENODEV; 184 185 rtcdrv->irq = platform_get_irq(pdev, 0); 186 if (rtcdrv->irq < 0) 187 return -ENODEV; 188 189 rtcdrv->rtc = devm_rtc_allocate_device(&pdev->dev); 190 if (IS_ERR(rtcdrv->rtc)) 191 return PTR_ERR(rtcdrv->rtc); 192 193 rtcdrv->rtc->ops = &goldfish_rtc_ops; 194 rtcdrv->rtc->range_max = U64_MAX / NSEC_PER_SEC; 195 196 err = devm_request_irq(&pdev->dev, rtcdrv->irq, 197 goldfish_rtc_interrupt, 198 0, pdev->name, rtcdrv); 199 if (err) 200 return err; 201 202 return rtc_register_device(rtcdrv->rtc); 203 } 204 205 static const struct of_device_id goldfish_rtc_of_match[] = { 206 { .compatible = "google,goldfish-rtc", }, 207 {}, 208 }; 209 MODULE_DEVICE_TABLE(of, goldfish_rtc_of_match); 210 211 static struct platform_driver goldfish_rtc = { 212 .probe = goldfish_rtc_probe, 213 .driver = { 214 .name = "goldfish_rtc", 215 .of_match_table = goldfish_rtc_of_match, 216 } 217 }; 218 219 module_platform_driver(goldfish_rtc); 220 221 MODULE_LICENSE("GPL v2"); 222