| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2007-2009 ST-Ericsson AB |
|---|
| 3 | | - * License terms: GNU General Public License (GPL) version 2 |
|---|
| 4 | 4 | * Real Time Clock interface for ST-Ericsson AB COH 901 331 RTC. |
|---|
| 5 | 5 | * Author: Linus Walleij <linus.walleij@stericsson.com> |
|---|
| 6 | 6 | * Based on rtc-pl031.c by Deepak Saxena <dsaxena@plexity.net> |
|---|
| .. | .. |
|---|
| 80 | 80 | |
|---|
| 81 | 81 | clk_enable(rtap->clk); |
|---|
| 82 | 82 | /* Check if the time is valid */ |
|---|
| 83 | | - if (readl(rtap->virtbase + COH901331_VALID)) { |
|---|
| 84 | | - rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); |
|---|
| 83 | + if (!readl(rtap->virtbase + COH901331_VALID)) { |
|---|
| 85 | 84 | clk_disable(rtap->clk); |
|---|
| 86 | | - return 0; |
|---|
| 85 | + return -EINVAL; |
|---|
| 87 | 86 | } |
|---|
| 87 | + |
|---|
| 88 | + rtc_time64_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); |
|---|
| 88 | 89 | clk_disable(rtap->clk); |
|---|
| 89 | | - return -EINVAL; |
|---|
| 90 | + return 0; |
|---|
| 90 | 91 | } |
|---|
| 91 | 92 | |
|---|
| 92 | | -static int coh901331_set_mmss(struct device *dev, unsigned long secs) |
|---|
| 93 | +static int coh901331_set_time(struct device *dev, struct rtc_time *tm) |
|---|
| 93 | 94 | { |
|---|
| 94 | 95 | struct coh901331_port *rtap = dev_get_drvdata(dev); |
|---|
| 95 | 96 | |
|---|
| 96 | 97 | clk_enable(rtap->clk); |
|---|
| 97 | | - writel(secs, rtap->virtbase + COH901331_SET_TIME); |
|---|
| 98 | + writel(rtc_tm_to_time64(tm), rtap->virtbase + COH901331_SET_TIME); |
|---|
| 98 | 99 | clk_disable(rtap->clk); |
|---|
| 99 | 100 | |
|---|
| 100 | 101 | return 0; |
|---|
| .. | .. |
|---|
| 105 | 106 | struct coh901331_port *rtap = dev_get_drvdata(dev); |
|---|
| 106 | 107 | |
|---|
| 107 | 108 | clk_enable(rtap->clk); |
|---|
| 108 | | - rtc_time_to_tm(readl(rtap->virtbase + COH901331_ALARM), &alarm->time); |
|---|
| 109 | + rtc_time64_to_tm(readl(rtap->virtbase + COH901331_ALARM), &alarm->time); |
|---|
| 109 | 110 | alarm->pending = readl(rtap->virtbase + COH901331_IRQ_EVENT) & 1U; |
|---|
| 110 | 111 | alarm->enabled = readl(rtap->virtbase + COH901331_IRQ_MASK) & 1U; |
|---|
| 111 | 112 | clk_disable(rtap->clk); |
|---|
| .. | .. |
|---|
| 116 | 117 | static int coh901331_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
|---|
| 117 | 118 | { |
|---|
| 118 | 119 | struct coh901331_port *rtap = dev_get_drvdata(dev); |
|---|
| 119 | | - unsigned long time; |
|---|
| 120 | + unsigned long time = rtc_tm_to_time64(&alarm->time); |
|---|
| 120 | 121 | |
|---|
| 121 | | - rtc_tm_to_time(&alarm->time, &time); |
|---|
| 122 | 122 | clk_enable(rtap->clk); |
|---|
| 123 | 123 | writel(time, rtap->virtbase + COH901331_ALARM); |
|---|
| 124 | 124 | writel(alarm->enabled, rtap->virtbase + COH901331_IRQ_MASK); |
|---|
| .. | .. |
|---|
| 143 | 143 | |
|---|
| 144 | 144 | static const struct rtc_class_ops coh901331_ops = { |
|---|
| 145 | 145 | .read_time = coh901331_read_time, |
|---|
| 146 | | - .set_mmss = coh901331_set_mmss, |
|---|
| 146 | + .set_time = coh901331_set_time, |
|---|
| 147 | 147 | .read_alarm = coh901331_read_alarm, |
|---|
| 148 | 148 | .set_alarm = coh901331_set_alarm, |
|---|
| 149 | 149 | .alarm_irq_enable = coh901331_alarm_irq_enable, |
|---|
| .. | .. |
|---|
| 164 | 164 | { |
|---|
| 165 | 165 | int ret; |
|---|
| 166 | 166 | struct coh901331_port *rtap; |
|---|
| 167 | | - struct resource *res; |
|---|
| 168 | 167 | |
|---|
| 169 | 168 | rtap = devm_kzalloc(&pdev->dev, |
|---|
| 170 | 169 | sizeof(struct coh901331_port), GFP_KERNEL); |
|---|
| 171 | 170 | if (!rtap) |
|---|
| 172 | 171 | return -ENOMEM; |
|---|
| 173 | 172 | |
|---|
| 174 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 175 | | - rtap->virtbase = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 173 | + rtap->virtbase = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 176 | 174 | if (IS_ERR(rtap->virtbase)) |
|---|
| 177 | 175 | return PTR_ERR(rtap->virtbase); |
|---|
| 178 | 176 | |
|---|
| .. | .. |
|---|
| 188 | 186 | return ret; |
|---|
| 189 | 187 | } |
|---|
| 190 | 188 | |
|---|
| 189 | + rtap->rtc = devm_rtc_allocate_device(&pdev->dev); |
|---|
| 190 | + if (IS_ERR(rtap->rtc)) |
|---|
| 191 | + return PTR_ERR(rtap->rtc); |
|---|
| 192 | + |
|---|
| 193 | + rtap->rtc->ops = &coh901331_ops; |
|---|
| 194 | + rtap->rtc->range_max = U32_MAX; |
|---|
| 195 | + |
|---|
| 191 | 196 | /* We enable/disable the clock only to assure it works */ |
|---|
| 192 | 197 | ret = clk_prepare_enable(rtap->clk); |
|---|
| 193 | 198 | if (ret) { |
|---|
| .. | .. |
|---|
| 197 | 202 | clk_disable(rtap->clk); |
|---|
| 198 | 203 | |
|---|
| 199 | 204 | platform_set_drvdata(pdev, rtap); |
|---|
| 200 | | - rtap->rtc = devm_rtc_device_register(&pdev->dev, "coh901331", |
|---|
| 201 | | - &coh901331_ops, THIS_MODULE); |
|---|
| 202 | | - if (IS_ERR(rtap->rtc)) { |
|---|
| 203 | | - ret = PTR_ERR(rtap->rtc); |
|---|
| 205 | + |
|---|
| 206 | + ret = rtc_register_device(rtap->rtc); |
|---|
| 207 | + if (ret) |
|---|
| 204 | 208 | goto out_no_rtc; |
|---|
| 205 | | - } |
|---|
| 206 | 209 | |
|---|
| 207 | 210 | return 0; |
|---|
| 208 | 211 | |
|---|
| .. | .. |
|---|
| 235 | 238 | |
|---|
| 236 | 239 | static int coh901331_resume(struct device *dev) |
|---|
| 237 | 240 | { |
|---|
| 241 | + int ret; |
|---|
| 238 | 242 | struct coh901331_port *rtap = dev_get_drvdata(dev); |
|---|
| 239 | 243 | |
|---|
| 240 | | - clk_prepare(rtap->clk); |
|---|
| 244 | + ret = clk_prepare(rtap->clk); |
|---|
| 245 | + if (ret) |
|---|
| 246 | + return ret; |
|---|
| 247 | + |
|---|
| 241 | 248 | if (device_may_wakeup(dev)) { |
|---|
| 242 | 249 | disable_irq_wake(rtap->irq); |
|---|
| 243 | 250 | } else { |
|---|