1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * PS3 RTC Driver |
4 | * |
5 | * Copyright 2009 Sony Corporation |
6 | */ |
7 | |
8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/rtc.h> |
12 | |
13 | #include <asm/lv1call.h> |
14 | #include <asm/ps3.h> |
15 | |
16 | |
17 | static u64 read_rtc(void) |
18 | { |
19 | int result; |
20 | u64 rtc_val; |
21 | u64 tb_val; |
22 | |
23 | result = lv1_get_rtc(&rtc_val, &tb_val); |
24 | BUG_ON(result); |
25 | |
26 | return rtc_val; |
27 | } |
28 | |
29 | static int ps3_get_time(struct device *dev, struct rtc_time *tm) |
30 | { |
31 | rtc_time64_to_tm(time: read_rtc() + ps3_os_area_get_rtc_diff(), tm); |
32 | return 0; |
33 | } |
34 | |
35 | static int ps3_set_time(struct device *dev, struct rtc_time *tm) |
36 | { |
37 | ps3_os_area_set_rtc_diff(rtc_tm_to_time64(tm) - read_rtc()); |
38 | return 0; |
39 | } |
40 | |
41 | static const struct rtc_class_ops ps3_rtc_ops = { |
42 | .read_time = ps3_get_time, |
43 | .set_time = ps3_set_time, |
44 | }; |
45 | |
46 | static int __init ps3_rtc_probe(struct platform_device *dev) |
47 | { |
48 | struct rtc_device *rtc; |
49 | |
50 | rtc = devm_rtc_allocate_device(dev: &dev->dev); |
51 | if (IS_ERR(ptr: rtc)) |
52 | return PTR_ERR(ptr: rtc); |
53 | |
54 | rtc->ops = &ps3_rtc_ops; |
55 | rtc->range_max = U64_MAX; |
56 | |
57 | platform_set_drvdata(pdev: dev, data: rtc); |
58 | |
59 | return devm_rtc_register_device(rtc); |
60 | } |
61 | |
62 | static struct platform_driver ps3_rtc_driver = { |
63 | .driver = { |
64 | .name = "rtc-ps3" , |
65 | }, |
66 | }; |
67 | |
68 | module_platform_driver_probe(ps3_rtc_driver, ps3_rtc_probe); |
69 | |
70 | MODULE_AUTHOR("Sony Corporation" ); |
71 | MODULE_LICENSE("GPL" ); |
72 | MODULE_DESCRIPTION("ps3 RTC driver" ); |
73 | MODULE_ALIAS("platform:rtc-ps3" ); |
74 | |