aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig18
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/interface.c6
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c292
-rw-r--r--drivers/rtc/rtc-s3c.c8
-rw-r--r--drivers/rtc/rtc-snvs.c6
-rw-r--r--drivers/rtc/rtc-spear.c8
-rw-r--r--drivers/rtc/rtc-tegra.c8
8 files changed, 325 insertions, 22 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d6394c87ad6d..e6ab071fb6fd 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1075,7 +1075,7 @@ config RTC_DRV_TX4939
1075 1075
1076config RTC_DRV_MV 1076config RTC_DRV_MV
1077 tristate "Marvell SoC RTC" 1077 tristate "Marvell SoC RTC"
1078 depends on ARCH_KIRKWOOD || ARCH_DOVE 1078 depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU
1079 help 1079 help
1080 If you say yes here you will get support for the in-chip RTC 1080 If you say yes here you will get support for the in-chip RTC
1081 that can be found in some of Marvell's SoC devices, such as 1081 that can be found in some of Marvell's SoC devices, such as
@@ -1225,4 +1225,20 @@ config RTC_DRV_SNVS
1225 This driver can also be built as a module, if so, the module 1225 This driver can also be built as a module, if so, the module
1226 will be called "rtc-snvs". 1226 will be called "rtc-snvs".
1227 1227
1228comment "HID Sensor RTC drivers"
1229
1230config RTC_DRV_HID_SENSOR_TIME
1231 tristate "HID Sensor Time"
1232 depends on USB_HID
1233 select IIO
1234 select HID_SENSOR_HUB
1235 select HID_SENSOR_IIO_COMMON
1236 help
1237 Say yes here to build support for the HID Sensors of type Time.
1238 This drivers makes such sensors available as RTCs.
1239
1240 If this driver is compiled as a module, it will be named
1241 rtc-hid-sensor-time.
1242
1243
1228endif # RTC_CLASS 1244endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index c694d2644a6c..e8f2e2fee06f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o
53obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o 53obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
54obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o 54obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
55obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o 55obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
56obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
56obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o 57obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
57obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o 58obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
58obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o 59obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 9592b936b71b..42bd57da239d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -587,16 +587,16 @@ void rtc_update_irq(struct rtc_device *rtc,
587} 587}
588EXPORT_SYMBOL_GPL(rtc_update_irq); 588EXPORT_SYMBOL_GPL(rtc_update_irq);
589 589
590static int __rtc_match(struct device *dev, void *data) 590static int __rtc_match(struct device *dev, const void *data)
591{ 591{
592 char *name = (char *)data; 592 const char *name = data;
593 593
594 if (strcmp(dev_name(dev), name) == 0) 594 if (strcmp(dev_name(dev), name) == 0)
595 return 1; 595 return 1;
596 return 0; 596 return 0;
597} 597}
598 598
599struct rtc_device *rtc_class_open(char *name) 599struct rtc_device *rtc_class_open(const char *name)
600{ 600{
601 struct device *dev; 601 struct device *dev;
602 struct rtc_device *rtc = NULL; 602 struct rtc_device *rtc = NULL;
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
new file mode 100644
index 000000000000..31c5728ef629
--- /dev/null
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -0,0 +1,292 @@
1/*
2 * HID Sensor Time Driver
3 * Copyright (c) 2012, Alexander Holler.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/module.h>
22#include <linux/hid-sensor-hub.h>
23#include <linux/iio/iio.h>
24#include <linux/rtc.h>
25
26/* Format: HID-SENSOR-usage_id_in_hex */
27/* Usage ID from spec for Time: 0x2000A0 */
28#define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */
29
30enum hid_time_channel {
31 CHANNEL_SCAN_INDEX_YEAR,
32 CHANNEL_SCAN_INDEX_MONTH,
33 CHANNEL_SCAN_INDEX_DAY,
34 CHANNEL_SCAN_INDEX_HOUR,
35 CHANNEL_SCAN_INDEX_MINUTE,
36 CHANNEL_SCAN_INDEX_SECOND,
37 TIME_RTC_CHANNEL_MAX,
38};
39
40struct hid_time_state {
41 struct hid_sensor_hub_callbacks callbacks;
42 struct hid_sensor_common common_attributes;
43 struct hid_sensor_hub_attribute_info info[TIME_RTC_CHANNEL_MAX];
44 struct rtc_time last_time;
45 spinlock_t lock_last_time;
46 struct completion comp_last_time;
47 struct rtc_time time_buf;
48 struct rtc_device *rtc;
49};
50
51static const u32 hid_time_addresses[TIME_RTC_CHANNEL_MAX] = {
52 HID_USAGE_SENSOR_TIME_YEAR,
53 HID_USAGE_SENSOR_TIME_MONTH,
54 HID_USAGE_SENSOR_TIME_DAY,
55 HID_USAGE_SENSOR_TIME_HOUR,
56 HID_USAGE_SENSOR_TIME_MINUTE,
57 HID_USAGE_SENSOR_TIME_SECOND,
58};
59
60/* Channel names for verbose error messages */
61static const char * const hid_time_channel_names[TIME_RTC_CHANNEL_MAX] = {
62 "year", "month", "day", "hour", "minute", "second",
63};
64
65/* Callback handler to send event after all samples are received and captured */
66static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev,
67 unsigned usage_id, void *priv)
68{
69 unsigned long flags;
70 struct hid_time_state *time_state = platform_get_drvdata(priv);
71
72 spin_lock_irqsave(&time_state->lock_last_time, flags);
73 time_state->last_time = time_state->time_buf;
74 spin_unlock_irqrestore(&time_state->lock_last_time, flags);
75 complete(&time_state->comp_last_time);
76 return 0;
77}
78
79static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev,
80 unsigned usage_id, size_t raw_len,
81 char *raw_data, void *priv)
82{
83 struct hid_time_state *time_state = platform_get_drvdata(priv);
84 struct rtc_time *time_buf = &time_state->time_buf;
85
86 switch (usage_id) {
87 case HID_USAGE_SENSOR_TIME_YEAR:
88 time_buf->tm_year = *(u8 *)raw_data;
89 if (time_buf->tm_year < 70)
90 /* assume we are in 1970...2069 */
91 time_buf->tm_year += 100;
92 break;
93 case HID_USAGE_SENSOR_TIME_MONTH:
94 /* sensor sending the month as 1-12, we need 0-11 */
95 time_buf->tm_mon = *(u8 *)raw_data-1;
96 break;
97 case HID_USAGE_SENSOR_TIME_DAY:
98 time_buf->tm_mday = *(u8 *)raw_data;
99 break;
100 case HID_USAGE_SENSOR_TIME_HOUR:
101 time_buf->tm_hour = *(u8 *)raw_data;
102 break;
103 case HID_USAGE_SENSOR_TIME_MINUTE:
104 time_buf->tm_min = *(u8 *)raw_data;
105 break;
106 case HID_USAGE_SENSOR_TIME_SECOND:
107 time_buf->tm_sec = *(u8 *)raw_data;
108 break;
109 default:
110 return -EINVAL;
111 }
112 return 0;
113}
114
115/* small helper, haven't found any other way */
116static const char *hid_time_attrib_name(u32 attrib_id)
117{
118 static const char unknown[] = "unknown";
119 unsigned i;
120
121 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) {
122 if (hid_time_addresses[i] == attrib_id)
123 return hid_time_channel_names[i];
124 }
125 return unknown; /* should never happen */
126}
127
128static int hid_time_parse_report(struct platform_device *pdev,
129 struct hid_sensor_hub_device *hsdev,
130 unsigned usage_id,
131 struct hid_time_state *time_state)
132{
133 int report_id, i;
134
135 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i)
136 if (sensor_hub_input_get_attribute_info(hsdev,
137 HID_INPUT_REPORT, usage_id,
138 hid_time_addresses[i],
139 &time_state->info[i]) < 0)
140 return -EINVAL;
141 /* Check the (needed) attributes for sanity */
142 report_id = time_state->info[0].report_id;
143 if (report_id < 0) {
144 dev_err(&pdev->dev, "bad report ID!\n");
145 return -EINVAL;
146 }
147 for (i = 0; i < TIME_RTC_CHANNEL_MAX; ++i) {
148 if (time_state->info[i].report_id != report_id) {
149 dev_err(&pdev->dev,
150 "not all needed attributes inside the same report!\n");
151 return -EINVAL;
152 }
153 if (time_state->info[i].size != 1) {
154 dev_err(&pdev->dev,
155 "attribute '%s' not 8 bits wide!\n",
156 hid_time_attrib_name(
157 time_state->info[i].attrib_id));
158 return -EINVAL;
159 }
160 if (time_state->info[i].units !=
161 HID_USAGE_SENSOR_UNITS_NOT_SPECIFIED &&
162 /* allow attribute seconds with unit seconds */
163 !(time_state->info[i].attrib_id ==
164 HID_USAGE_SENSOR_TIME_SECOND &&
165 time_state->info[i].units ==
166 HID_USAGE_SENSOR_UNITS_SECOND)) {
167 dev_err(&pdev->dev,
168 "attribute '%s' hasn't a unit of type 'none'!\n",
169 hid_time_attrib_name(
170 time_state->info[i].attrib_id));
171 return -EINVAL;
172 }
173 if (time_state->info[i].unit_expo) {
174 dev_err(&pdev->dev,
175 "attribute '%s' hasn't a unit exponent of 1!\n",
176 hid_time_attrib_name(
177 time_state->info[i].attrib_id));
178 return -EINVAL;
179 }
180 }
181
182 return 0;
183}
184
185static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
186{
187 unsigned long flags;
188 struct hid_time_state *time_state =
189 platform_get_drvdata(to_platform_device(dev));
190 int ret;
191
192 INIT_COMPLETION(time_state->comp_last_time);
193 /* get a report with all values through requesting one value */
194 sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
195 HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
196 time_state->info[0].report_id);
197 /* wait for all values (event) */
198 ret = wait_for_completion_killable_timeout(
199 &time_state->comp_last_time, HZ*6);
200 if (ret > 0) {
201 /* no error */
202 spin_lock_irqsave(&time_state->lock_last_time, flags);
203 *tm = time_state->last_time;
204 spin_unlock_irqrestore(&time_state->lock_last_time, flags);
205 return 0;
206 }
207 if (!ret)
208 return -EIO; /* timeouted */
209 return ret; /* killed (-ERESTARTSYS) */
210}
211
212static const struct rtc_class_ops hid_time_rtc_ops = {
213 .read_time = hid_rtc_read_time,
214};
215
216static int hid_time_probe(struct platform_device *pdev)
217{
218 int ret = 0;
219 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
220 struct hid_time_state *time_state = devm_kzalloc(&pdev->dev,
221 sizeof(struct hid_time_state), GFP_KERNEL);
222
223 if (time_state == NULL)
224 return -ENOMEM;
225
226 platform_set_drvdata(pdev, time_state);
227
228 spin_lock_init(&time_state->lock_last_time);
229 init_completion(&time_state->comp_last_time);
230 time_state->common_attributes.hsdev = hsdev;
231 time_state->common_attributes.pdev = pdev;
232
233 ret = hid_sensor_parse_common_attributes(hsdev,
234 HID_USAGE_SENSOR_TIME,
235 &time_state->common_attributes);
236 if (ret) {
237 dev_err(&pdev->dev, "failed to setup common attributes!\n");
238 return ret;
239 }
240
241 ret = hid_time_parse_report(pdev, hsdev, HID_USAGE_SENSOR_TIME,
242 time_state);
243 if (ret) {
244 dev_err(&pdev->dev, "failed to setup attributes!\n");
245 return ret;
246 }
247
248 time_state->callbacks.send_event = hid_time_proc_event;
249 time_state->callbacks.capture_sample = hid_time_capture_sample;
250 time_state->callbacks.pdev = pdev;
251 ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TIME,
252 &time_state->callbacks);
253 if (ret < 0) {
254 dev_err(&pdev->dev, "register callback failed!\n");
255 return ret;
256 }
257
258 time_state->rtc = rtc_device_register("hid-sensor-time",
259 &pdev->dev, &hid_time_rtc_ops, THIS_MODULE);
260
261 if (IS_ERR(time_state->rtc)) {
262 dev_err(&pdev->dev, "rtc device register failed!\n");
263 return PTR_ERR(time_state->rtc);
264 }
265
266 return ret;
267}
268
269static int hid_time_remove(struct platform_device *pdev)
270{
271 struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
272 struct hid_time_state *time_state = platform_get_drvdata(pdev);
273
274 rtc_device_unregister(time_state->rtc);
275 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
276
277 return 0;
278}
279
280static struct platform_driver hid_time_platform_driver = {
281 .driver = {
282 .name = DRIVER_NAME,
283 .owner = THIS_MODULE,
284 },
285 .probe = hid_time_probe,
286 .remove = hid_time_remove,
287};
288module_platform_driver(hid_time_platform_driver);
289
290MODULE_DESCRIPTION("HID Sensor Time");
291MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>");
292MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 8ff5ec1c4746..fb994e9ddc15 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -486,11 +486,9 @@ static int s3c_rtc_probe(struct platform_device *pdev)
486 return -ENOENT; 486 return -ENOENT;
487 } 487 }
488 488
489 s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res); 489 s3c_rtc_base = devm_ioremap_resource(&pdev->dev, res);
490 if (s3c_rtc_base == NULL) { 490 if (IS_ERR(s3c_rtc_base))
491 dev_err(&pdev->dev, "failed to ioremap memory region\n"); 491 return PTR_ERR(s3c_rtc_base);
492 return -EINVAL;
493 }
494 492
495 rtc_clk = devm_clk_get(&pdev->dev, "rtc"); 493 rtc_clk = devm_clk_get(&pdev->dev, "rtc");
496 if (IS_ERR(rtc_clk)) { 494 if (IS_ERR(rtc_clk)) {
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index 9b795db3ecce..f7d90703db5e 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -252,9 +252,9 @@ static int snvs_rtc_probe(struct platform_device *pdev)
252 return -ENOMEM; 252 return -ENOMEM;
253 253
254 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 254 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
255 data->ioaddr = devm_request_and_ioremap(&pdev->dev, res); 255 data->ioaddr = devm_ioremap_resource(&pdev->dev, res);
256 if (!data->ioaddr) 256 if (IS_ERR(data->ioaddr))
257 return -EADDRNOTAVAIL; 257 return PTR_ERR(data->ioaddr);
258 258
259 data->irq = platform_get_irq(pdev, 0); 259 data->irq = platform_get_irq(pdev, 0);
260 if (data->irq < 0) 260 if (data->irq < 0)
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index c2121b5a01f2..a18c3192ed40 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -385,11 +385,9 @@ static int spear_rtc_probe(struct platform_device *pdev)
385 return status; 385 return status;
386 } 386 }
387 387
388 config->ioaddr = devm_request_and_ioremap(&pdev->dev, res); 388 config->ioaddr = devm_ioremap_resource(&pdev->dev, res);
389 if (!config->ioaddr) { 389 if (IS_ERR(config->ioaddr))
390 dev_err(&pdev->dev, "request-ioremap fail\n"); 390 return PTR_ERR(config->ioaddr);
391 return -ENOMEM;
392 }
393 391
394 config->clk = devm_clk_get(&pdev->dev, NULL); 392 config->clk = devm_clk_get(&pdev->dev, NULL);
395 if (IS_ERR(config->clk)) 393 if (IS_ERR(config->clk))
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index c84ea6659f49..7c033756d6b5 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -327,11 +327,9 @@ static int tegra_rtc_probe(struct platform_device *pdev)
327 return -EBUSY; 327 return -EBUSY;
328 } 328 }
329 329
330 info->rtc_base = devm_request_and_ioremap(&pdev->dev, res); 330 info->rtc_base = devm_ioremap_resource(&pdev->dev, res);
331 if (!info->rtc_base) { 331 if (IS_ERR(info->rtc_base))
332 dev_err(&pdev->dev, "Unable to request mem region and grab IOs for device.\n"); 332 return PTR_ERR(info->rtc_base);
333 return -EBUSY;
334 }
335 333
336 info->tegra_rtc_irq = platform_get_irq(pdev, 0); 334 info->tegra_rtc_irq = platform_get_irq(pdev, 0);
337 if (info->tegra_rtc_irq <= 0) 335 if (info->tegra_rtc_irq <= 0)