.. | .. |
---|
1 | | -/* |
---|
2 | | - * Copyright (C) 2012 Sven Schnelle <svens@stackframe.org> |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 as |
---|
6 | | - * published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - */ |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
| 2 | +// Copyright (C) 2012 Sven Schnelle <svens@stackframe.org> |
---|
9 | 3 | |
---|
10 | 4 | #include <linux/platform_device.h> |
---|
11 | 5 | #include <linux/module.h> |
---|
.. | .. |
---|
29 | 23 | #define DS2404_COPY_SCRATCHPAD_CMD 0x55 |
---|
30 | 24 | #define DS2404_READ_MEMORY_CMD 0xf0 |
---|
31 | 25 | |
---|
32 | | -struct ds2404; |
---|
33 | | - |
---|
34 | | -struct ds2404_chip_ops { |
---|
35 | | - int (*map_io)(struct ds2404 *chip, struct platform_device *pdev, |
---|
36 | | - struct ds2404_platform_data *pdata); |
---|
37 | | - void (*unmap_io)(struct ds2404 *chip); |
---|
38 | | -}; |
---|
39 | | - |
---|
40 | 26 | #define DS2404_RST 0 |
---|
41 | 27 | #define DS2404_CLK 1 |
---|
42 | 28 | #define DS2404_DQ 2 |
---|
.. | .. |
---|
48 | 34 | |
---|
49 | 35 | struct ds2404 { |
---|
50 | 36 | struct ds2404_gpio *gpio; |
---|
51 | | - const struct ds2404_chip_ops *ops; |
---|
52 | 37 | struct rtc_device *rtc; |
---|
53 | 38 | }; |
---|
54 | 39 | |
---|
.. | .. |
---|
87 | 72 | return err; |
---|
88 | 73 | } |
---|
89 | 74 | |
---|
90 | | -static void ds2404_gpio_unmap(struct ds2404 *chip) |
---|
| 75 | +static void ds2404_gpio_unmap(void *data) |
---|
91 | 76 | { |
---|
92 | 77 | int i; |
---|
93 | 78 | |
---|
94 | 79 | for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) |
---|
95 | 80 | gpio_free(ds2404_gpio[i].gpio); |
---|
96 | 81 | } |
---|
97 | | - |
---|
98 | | -static const struct ds2404_chip_ops ds2404_gpio_ops = { |
---|
99 | | - .map_io = ds2404_gpio_map, |
---|
100 | | - .unmap_io = ds2404_gpio_unmap, |
---|
101 | | -}; |
---|
102 | 82 | |
---|
103 | 83 | static void ds2404_reset(struct device *dev) |
---|
104 | 84 | { |
---|
.. | .. |
---|
202 | 182 | static int ds2404_read_time(struct device *dev, struct rtc_time *dt) |
---|
203 | 183 | { |
---|
204 | 184 | unsigned long time = 0; |
---|
| 185 | + __le32 hw_time = 0; |
---|
205 | 186 | |
---|
206 | | - ds2404_read_memory(dev, 0x203, 4, (u8 *)&time); |
---|
207 | | - time = le32_to_cpu(time); |
---|
| 187 | + ds2404_read_memory(dev, 0x203, 4, (u8 *)&hw_time); |
---|
| 188 | + time = le32_to_cpu(hw_time); |
---|
208 | 189 | |
---|
209 | | - rtc_time_to_tm(time, dt); |
---|
| 190 | + rtc_time64_to_tm(time, dt); |
---|
210 | 191 | return 0; |
---|
211 | 192 | } |
---|
212 | 193 | |
---|
213 | | -static int ds2404_set_mmss(struct device *dev, unsigned long secs) |
---|
| 194 | +static int ds2404_set_time(struct device *dev, struct rtc_time *dt) |
---|
214 | 195 | { |
---|
215 | | - u32 time = cpu_to_le32(secs); |
---|
| 196 | + u32 time = cpu_to_le32(rtc_tm_to_time64(dt)); |
---|
216 | 197 | ds2404_write_memory(dev, 0x203, 4, (u8 *)&time); |
---|
217 | 198 | return 0; |
---|
218 | 199 | } |
---|
219 | 200 | |
---|
220 | 201 | static const struct rtc_class_ops ds2404_rtc_ops = { |
---|
221 | 202 | .read_time = ds2404_read_time, |
---|
222 | | - .set_mmss = ds2404_set_mmss, |
---|
| 203 | + .set_time = ds2404_set_time, |
---|
223 | 204 | }; |
---|
224 | 205 | |
---|
225 | 206 | static int rtc_probe(struct platform_device *pdev) |
---|
.. | .. |
---|
232 | 213 | if (!chip) |
---|
233 | 214 | return -ENOMEM; |
---|
234 | 215 | |
---|
235 | | - chip->ops = &ds2404_gpio_ops; |
---|
| 216 | + chip->rtc = devm_rtc_allocate_device(&pdev->dev); |
---|
| 217 | + if (IS_ERR(chip->rtc)) |
---|
| 218 | + return PTR_ERR(chip->rtc); |
---|
236 | 219 | |
---|
237 | | - retval = chip->ops->map_io(chip, pdev, pdata); |
---|
| 220 | + retval = ds2404_gpio_map(chip, pdev, pdata); |
---|
238 | 221 | if (retval) |
---|
239 | | - goto err_chip; |
---|
| 222 | + return retval; |
---|
| 223 | + |
---|
| 224 | + retval = devm_add_action_or_reset(&pdev->dev, ds2404_gpio_unmap, chip); |
---|
| 225 | + if (retval) |
---|
| 226 | + return retval; |
---|
240 | 227 | |
---|
241 | 228 | dev_info(&pdev->dev, "using GPIOs RST:%d, CLK:%d, DQ:%d\n", |
---|
242 | 229 | chip->gpio[DS2404_RST].gpio, chip->gpio[DS2404_CLK].gpio, |
---|
.. | .. |
---|
244 | 231 | |
---|
245 | 232 | platform_set_drvdata(pdev, chip); |
---|
246 | 233 | |
---|
247 | | - chip->rtc = devm_rtc_device_register(&pdev->dev, "ds2404", |
---|
248 | | - &ds2404_rtc_ops, THIS_MODULE); |
---|
249 | | - if (IS_ERR(chip->rtc)) { |
---|
250 | | - retval = PTR_ERR(chip->rtc); |
---|
251 | | - goto err_io; |
---|
252 | | - } |
---|
| 234 | + chip->rtc->ops = &ds2404_rtc_ops; |
---|
| 235 | + chip->rtc->range_max = U32_MAX; |
---|
| 236 | + |
---|
| 237 | + retval = rtc_register_device(chip->rtc); |
---|
| 238 | + if (retval) |
---|
| 239 | + return retval; |
---|
253 | 240 | |
---|
254 | 241 | ds2404_enable_osc(&pdev->dev); |
---|
255 | | - return 0; |
---|
256 | | - |
---|
257 | | -err_io: |
---|
258 | | - chip->ops->unmap_io(chip); |
---|
259 | | -err_chip: |
---|
260 | | - return retval; |
---|
261 | | -} |
---|
262 | | - |
---|
263 | | -static int rtc_remove(struct platform_device *dev) |
---|
264 | | -{ |
---|
265 | | - struct ds2404 *chip = platform_get_drvdata(dev); |
---|
266 | | - |
---|
267 | | - chip->ops->unmap_io(chip); |
---|
268 | | - |
---|
269 | 242 | return 0; |
---|
270 | 243 | } |
---|
271 | 244 | |
---|
272 | 245 | static struct platform_driver rtc_device_driver = { |
---|
273 | 246 | .probe = rtc_probe, |
---|
274 | | - .remove = rtc_remove, |
---|
275 | 247 | .driver = { |
---|
276 | 248 | .name = "ds2404", |
---|
277 | 249 | }, |
---|