Blame view
drivers/rtc/rtc-sun4v.c
1.94 KB
cecf61bde
|
1 |
/* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems. |
7a138ede5
|
2 |
* |
8b6102534
|
3 4 5 |
* Author: David S. Miller * License: GPL * |
7a138ede5
|
6 7 |
* Copyright (C) 2008 David S. Miller <davem@davemloft.net> */ |
d959f7319
|
8 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7a138ede5
|
9 |
#include <linux/kernel.h> |
7a138ede5
|
10 11 |
#include <linux/delay.h> #include <linux/init.h> |
7a138ede5
|
12 13 14 15 |
#include <linux/rtc.h> #include <linux/platform_device.h> #include <asm/hypervisor.h> |
7a138ede5
|
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
static unsigned long hypervisor_get_time(void) { unsigned long ret, time; int retries = 10000; retry: ret = sun4v_tod_get(&time); if (ret == HV_EOK) return time; if (ret == HV_EWOULDBLOCK) { if (--retries > 0) { udelay(100); goto retry; } |
d959f7319
|
30 31 |
pr_warn("tod_get() timed out. "); |
7a138ede5
|
32 33 |
return 0; } |
d959f7319
|
34 35 |
pr_warn("tod_get() not supported. "); |
7a138ede5
|
36 37 38 39 40 |
return 0; } static int sun4v_read_time(struct device *dev, struct rtc_time *tm) { |
cecf61bde
|
41 |
rtc_time_to_tm(hypervisor_get_time(), tm); |
7a138ede5
|
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
return 0; } static int hypervisor_set_time(unsigned long secs) { unsigned long ret; int retries = 10000; retry: ret = sun4v_tod_set(secs); if (ret == HV_EOK) return 0; if (ret == HV_EWOULDBLOCK) { if (--retries > 0) { udelay(100); goto retry; } |
d959f7319
|
59 60 |
pr_warn("tod_set() timed out. "); |
7a138ede5
|
61 62 |
return -EAGAIN; } |
d959f7319
|
63 64 |
pr_warn("tod_set() not supported. "); |
7a138ede5
|
65 66 67 68 69 |
return -EOPNOTSUPP; } static int sun4v_set_time(struct device *dev, struct rtc_time *tm) { |
cecf61bde
|
70 |
unsigned long secs; |
7a138ede5
|
71 72 73 74 75 |
int err; err = rtc_tm_to_time(tm, &secs); if (err) return err; |
cecf61bde
|
76 |
return hypervisor_set_time(secs); |
7a138ede5
|
77 78 79 80 81 82 |
} static const struct rtc_class_ops sun4v_rtc_ops = { .read_time = sun4v_read_time, .set_time = sun4v_set_time, }; |
cecf61bde
|
83 |
static int __init sun4v_rtc_probe(struct platform_device *pdev) |
7a138ede5
|
84 |
{ |
cc40d642f
|
85 86 87 88 |
struct rtc_device *rtc; rtc = devm_rtc_device_register(&pdev->dev, "sun4v", &sun4v_rtc_ops, THIS_MODULE); |
cecf61bde
|
89 90 91 92 |
if (IS_ERR(rtc)) return PTR_ERR(rtc); platform_set_drvdata(pdev, rtc); |
7a138ede5
|
93 94 |
return 0; } |
7a138ede5
|
95 96 97 |
static struct platform_driver sun4v_rtc_driver = { .driver = { .name = "rtc-sun4v", |
7a138ede5
|
98 |
}, |
7a138ede5
|
99 |
}; |
8b6102534
|
100 |
builtin_platform_driver_probe(sun4v_rtc_driver, sun4v_rtc_probe); |