| .. | .. |
|---|
| 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 | }, |
|---|