Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtc-tile.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Tilera Corporation. All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, version 2.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11  * NON INFRINGEMENT. See the GNU General Public License for
12  * more details.
13  *
14  * Tilera-specific RTC driver.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/device.h>
19 #include <linux/rtc.h>
20 #include <linux/platform_device.h>
21 
22 /* Platform device pointer. */
23 static struct platform_device *tile_rtc_platform_device;
24 
25 /*
26  * RTC read routine. Gets time info from RTC chip via hypervisor syscall.
27  */
28 static int read_rtc_time(struct device *dev, struct rtc_time *tm)
29 {
30  HV_RTCTime hvtm = hv_get_rtc();
31 
32  tm->tm_sec = hvtm.tm_sec;
33  tm->tm_min = hvtm.tm_min;
34  tm->tm_hour = hvtm.tm_hour;
35  tm->tm_mday = hvtm.tm_mday;
36  tm->tm_mon = hvtm.tm_mon;
37  tm->tm_year = hvtm.tm_year;
38  tm->tm_wday = 0;
39  tm->tm_yday = 0;
40  tm->tm_isdst = 0;
41 
42  if (rtc_valid_tm(tm) < 0)
43  dev_warn(dev, "Read invalid date/time from RTC\n");
44 
45  return 0;
46 }
47 
48 /*
49  * RTC write routine. Sends time info to hypervisor via syscall, to be
50  * written to RTC chip.
51  */
52 static int set_rtc_time(struct device *dev, struct rtc_time *tm)
53 {
54  HV_RTCTime hvtm;
55 
56  hvtm.tm_sec = tm->tm_sec;
57  hvtm.tm_min = tm->tm_min;
58  hvtm.tm_hour = tm->tm_hour;
59  hvtm.tm_mday = tm->tm_mday;
60  hvtm.tm_mon = tm->tm_mon;
61  hvtm.tm_year = tm->tm_year;
62 
63  hv_set_rtc(hvtm);
64 
65  return 0;
66 }
67 
68 /*
69  * RTC read/write ops.
70  */
71 static const struct rtc_class_ops tile_rtc_ops = {
72  .read_time = read_rtc_time,
73  .set_time = set_rtc_time,
74 };
75 
76 /*
77  * Device probe routine.
78  */
79 static int __devinit tile_rtc_probe(struct platform_device *dev)
80 {
81  struct rtc_device *rtc;
82 
83  rtc = rtc_device_register("tile",
84  &dev->dev, &tile_rtc_ops, THIS_MODULE);
85 
86  if (IS_ERR(rtc))
87  return PTR_ERR(rtc);
88 
89  platform_set_drvdata(dev, rtc);
90 
91  return 0;
92 }
93 
94 /*
95  * Device cleanup routine.
96  */
97 static int __devexit tile_rtc_remove(struct platform_device *dev)
98 {
99  struct rtc_device *rtc = platform_get_drvdata(dev);
100 
101  if (rtc)
103 
104  platform_set_drvdata(dev, NULL);
105 
106  return 0;
107 }
108 
109 static struct platform_driver tile_rtc_platform_driver = {
110  .driver = {
111  .name = "rtc-tile",
112  .owner = THIS_MODULE,
113  },
114  .probe = tile_rtc_probe,
115  .remove = __devexit_p(tile_rtc_remove),
116 };
117 
118 /*
119  * Driver init routine.
120  */
121 static int __init tile_rtc_driver_init(void)
122 {
123  int err;
124 
125  err = platform_driver_register(&tile_rtc_platform_driver);
126  if (err)
127  return err;
128 
129  tile_rtc_platform_device = platform_device_alloc("rtc-tile", 0);
130  if (tile_rtc_platform_device == NULL) {
131  err = -ENOMEM;
132  goto exit_driver_unregister;
133  }
134 
135  err = platform_device_add(tile_rtc_platform_device);
136  if (err)
137  goto exit_device_put;
138 
139  return 0;
140 
141 exit_device_put:
142  platform_device_put(tile_rtc_platform_device);
143 
144 exit_driver_unregister:
145  platform_driver_unregister(&tile_rtc_platform_driver);
146  return err;
147 }
148 
149 /*
150  * Driver cleanup routine.
151  */
152 static void __exit tile_rtc_driver_exit(void)
153 {
154  platform_driver_unregister(&tile_rtc_platform_driver);
155 }
156 
157 module_init(tile_rtc_driver_init);
158 module_exit(tile_rtc_driver_exit);
159 
160 MODULE_DESCRIPTION("Tilera-specific Real Time Clock Driver");
161 MODULE_LICENSE("GPL");
162 MODULE_ALIAS("platform:rtc-tile");