Blame view

drivers/rtc/rtc-sun4v.c 2.48 KB
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
1
  /* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems.
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
2
3
4
5
6
7
8
9
   *
   * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/delay.h>
  #include <linux/init.h>
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
10
11
12
13
  #include <linux/rtc.h>
  #include <linux/platform_device.h>
  
  #include <asm/hypervisor.h>
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  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;
  		}
  		printk(KERN_WARNING "SUN4V: tod_get() timed out.
  ");
  		return 0;
  	}
  	printk(KERN_WARNING "SUN4V: tod_get() not supported.
  ");
  	return 0;
  }
  
  static int sun4v_read_time(struct device *dev, struct rtc_time *tm)
  {
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
39
  	rtc_time_to_tm(hypervisor_get_time(), tm);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  	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;
  		}
  		printk(KERN_WARNING "SUN4V: tod_set() timed out.
  ");
  		return -EAGAIN;
  	}
  	printk(KERN_WARNING "SUN4V: tod_set() not supported.
  ");
  	return -EOPNOTSUPP;
  }
  
  static int sun4v_set_time(struct device *dev, struct rtc_time *tm)
  {
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
68
  	unsigned long secs;
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
69
70
71
72
73
  	int err;
  
  	err = rtc_tm_to_time(tm, &secs);
  	if (err)
  		return err;
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
74
  	return hypervisor_set_time(secs);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
75
76
77
78
79
80
  }
  
  static const struct rtc_class_ops sun4v_rtc_ops = {
  	.read_time	= sun4v_read_time,
  	.set_time	= sun4v_set_time,
  };
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
81
  static int __init sun4v_rtc_probe(struct platform_device *pdev)
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
82
  {
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
83
  	struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev,
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
84
  				     &sun4v_rtc_ops, THIS_MODULE);
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
85
86
87
88
  	if (IS_ERR(rtc))
  		return PTR_ERR(rtc);
  
  	platform_set_drvdata(pdev, rtc);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
89
90
  	return 0;
  }
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
91
  static int __exit sun4v_rtc_remove(struct platform_device *pdev)
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
92
  {
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
93
  	struct rtc_device *rtc = platform_get_drvdata(pdev);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
94

cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
95
  	rtc_device_unregister(rtc);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
96
97
98
99
100
101
102
103
  	return 0;
  }
  
  static struct platform_driver sun4v_rtc_driver = {
  	.driver		= {
  		.name	= "rtc-sun4v",
  		.owner	= THIS_MODULE,
  	},
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
104
  	.remove		= __exit_p(sun4v_rtc_remove),
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
105
106
107
108
  };
  
  static int __init sun4v_rtc_init(void)
  {
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
109
  	return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe);
7a138ede5   David S. Miller   rtc: Add Sun4V hy...
110
111
112
113
114
115
116
117
118
  }
  
  static void __exit sun4v_rtc_exit(void)
  {
  	platform_driver_unregister(&sun4v_rtc_driver);
  }
  
  module_init(sun4v_rtc_init);
  module_exit(sun4v_rtc_exit);
cecf61bde   Alessandro Zummo   rtc: rtc-sun4v fi...
119
120
121
122
  
  MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
  MODULE_DESCRIPTION("SUN4V RTC driver");
  MODULE_LICENSE("GPL");