aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Jensen <jonas.jensen@gmail.com>2013-09-11 17:24:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:58:54 -0400
commit453b4c6db59f7f6411a0b5eb58389a1fa129cc9a (patch)
treee96efb3520d9faf46ca777bc9cdbb4300822b18d
parent4540bae9cd8c03ec4a26eacad468d2f2f2e85cbb (diff)
rtc: add MOXA ART RTC driver
Add RTC driver for MOXA ART SoCs. Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com> Reviewed-by: Mark Brown <broonie@linaro.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt17
-rw-r--r--drivers/rtc/Kconfig9
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-moxart.c330
4 files changed, 357 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt b/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt
new file mode 100644
index 000000000000..c9d3ac1477fe
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/moxa,moxart-rtc.txt
@@ -0,0 +1,17 @@
1MOXA ART real-time clock
2
3Required properties:
4
5- compatible : Should be "moxa,moxart-rtc"
6- gpio-rtc-sclk : RTC sclk gpio, with zero flags
7- gpio-rtc-data : RTC data gpio, with zero flags
8- gpio-rtc-reset : RTC reset gpio, with zero flags
9
10Example:
11
12 rtc: rtc {
13 compatible = "moxa,moxart-rtc";
14 gpio-rtc-sclk = <&gpio 5 0>;
15 gpio-rtc-data = <&gpio 6 0>;
16 gpio-rtc-reset = <&gpio 7 0>;
17 };
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9e3498bf302b..9654aa3c05cb 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1249,6 +1249,15 @@ config RTC_DRV_SIRFSOC
1249 Say "yes" here to support the real time clock on SiRF SOC chips. 1249 Say "yes" here to support the real time clock on SiRF SOC chips.
1250 This driver can also be built as a module called rtc-sirfsoc. 1250 This driver can also be built as a module called rtc-sirfsoc.
1251 1251
1252config RTC_DRV_MOXART
1253 tristate "MOXA ART RTC"
1254 help
1255 If you say yes here you get support for the MOXA ART
1256 RTC module.
1257
1258 This driver can also be built as a module. If so, the module
1259 will be called rtc-moxart
1260
1252comment "HID Sensor RTC drivers" 1261comment "HID Sensor RTC drivers"
1253 1262
1254config RTC_DRV_HID_SENSOR_TIME 1263config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index d3b4488f48f2..2dff3d2009b5 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -130,3 +130,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
130obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o 130obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
131obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o 131obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
132obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o 132obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
133obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
diff --git a/drivers/rtc/rtc-moxart.c b/drivers/rtc/rtc-moxart.c
new file mode 100644
index 000000000000..c29dee0946e6
--- /dev/null
+++ b/drivers/rtc/rtc-moxart.c
@@ -0,0 +1,330 @@
1/*
2 * MOXA ART RTC driver.
3 *
4 * Copyright (C) 2013 Jonas Jensen
5 *
6 * Jonas Jensen <jonas.jensen@gmail.com>
7 *
8 * Based on code from
9 * Moxa Technology Co., Ltd. <www.moxa.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/delay.h>
19#include <linux/rtc.h>
20#include <linux/platform_device.h>
21#include <linux/module.h>
22#include <linux/gpio.h>
23#include <linux/of_gpio.h>
24
25#define GPIO_RTC_RESERVED 0x0C
26#define GPIO_RTC_DATA_SET 0x10
27#define GPIO_RTC_DATA_CLEAR 0x14
28#define GPIO_RTC_PIN_PULL_ENABLE 0x18
29#define GPIO_RTC_PIN_PULL_TYPE 0x1C
30#define GPIO_RTC_INT_ENABLE 0x20
31#define GPIO_RTC_INT_RAW_STATE 0x24
32#define GPIO_RTC_INT_MASKED_STATE 0x28
33#define GPIO_RTC_INT_MASK 0x2C
34#define GPIO_RTC_INT_CLEAR 0x30
35#define GPIO_RTC_INT_TRIGGER 0x34
36#define GPIO_RTC_INT_BOTH 0x38
37#define GPIO_RTC_INT_RISE_NEG 0x3C
38#define GPIO_RTC_BOUNCE_ENABLE 0x40
39#define GPIO_RTC_BOUNCE_PRE_SCALE 0x44
40#define GPIO_RTC_PROTECT_W 0x8E
41#define GPIO_RTC_PROTECT_R 0x8F
42#define GPIO_RTC_YEAR_W 0x8C
43#define GPIO_RTC_YEAR_R 0x8D
44#define GPIO_RTC_DAY_W 0x8A
45#define GPIO_RTC_DAY_R 0x8B
46#define GPIO_RTC_MONTH_W 0x88
47#define GPIO_RTC_MONTH_R 0x89
48#define GPIO_RTC_DATE_W 0x86
49#define GPIO_RTC_DATE_R 0x87
50#define GPIO_RTC_HOURS_W 0x84
51#define GPIO_RTC_HOURS_R 0x85
52#define GPIO_RTC_MINUTES_W 0x82
53#define GPIO_RTC_MINUTES_R 0x83
54#define GPIO_RTC_SECONDS_W 0x80
55#define GPIO_RTC_SECONDS_R 0x81
56#define GPIO_RTC_DELAY_TIME 8
57
58struct moxart_rtc {
59 struct rtc_device *rtc;
60 spinlock_t rtc_lock;
61 int gpio_data, gpio_sclk, gpio_reset;
62};
63
64static int day_of_year[12] = { 0, 31, 59, 90, 120, 151, 181,
65 212, 243, 273, 304, 334 };
66
67static void moxart_rtc_write_byte(struct device *dev, u8 data)
68{
69 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
70 int i;
71
72 for (i = 0; i < 8; i++, data >>= 1) {
73 gpio_set_value(moxart_rtc->gpio_sclk, 0);
74 gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1));
75 udelay(GPIO_RTC_DELAY_TIME);
76 gpio_set_value(moxart_rtc->gpio_sclk, 1);
77 udelay(GPIO_RTC_DELAY_TIME);
78 }
79}
80
81static u8 moxart_rtc_read_byte(struct device *dev)
82{
83 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
84 int i;
85 u8 data = 0;
86
87 for (i = 0; i < 8; i++) {
88 gpio_set_value(moxart_rtc->gpio_sclk, 0);
89 udelay(GPIO_RTC_DELAY_TIME);
90 gpio_set_value(moxart_rtc->gpio_sclk, 1);
91 udelay(GPIO_RTC_DELAY_TIME);
92 if (gpio_get_value(moxart_rtc->gpio_data))
93 data |= (1 << i);
94 udelay(GPIO_RTC_DELAY_TIME);
95 }
96 return data;
97}
98
99static u8 moxart_rtc_read_register(struct device *dev, u8 cmd)
100{
101 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
102 u8 data;
103 unsigned long flags;
104
105 local_irq_save(flags);
106
107 gpio_direction_output(moxart_rtc->gpio_data, 0);
108 gpio_set_value(moxart_rtc->gpio_reset, 1);
109 udelay(GPIO_RTC_DELAY_TIME);
110 moxart_rtc_write_byte(dev, cmd);
111 gpio_direction_input(moxart_rtc->gpio_data);
112 udelay(GPIO_RTC_DELAY_TIME);
113 data = moxart_rtc_read_byte(dev);
114 gpio_set_value(moxart_rtc->gpio_sclk, 0);
115 gpio_set_value(moxart_rtc->gpio_reset, 0);
116 udelay(GPIO_RTC_DELAY_TIME);
117
118 local_irq_restore(flags);
119
120 return data;
121}
122
123static void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data)
124{
125 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
126 unsigned long flags;
127
128 local_irq_save(flags);
129
130 gpio_direction_output(moxart_rtc->gpio_data, 0);
131 gpio_set_value(moxart_rtc->gpio_reset, 1);
132 udelay(GPIO_RTC_DELAY_TIME);
133 moxart_rtc_write_byte(dev, cmd);
134 moxart_rtc_write_byte(dev, data);
135 gpio_set_value(moxart_rtc->gpio_sclk, 0);
136 gpio_set_value(moxart_rtc->gpio_reset, 0);
137 udelay(GPIO_RTC_DELAY_TIME);
138
139 local_irq_restore(flags);
140}
141
142static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm)
143{
144 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
145
146 spin_lock_irq(&moxart_rtc->rtc_lock);
147
148 moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0);
149 moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W,
150 (((tm->tm_year - 100) / 10) << 4) |
151 ((tm->tm_year - 100) % 10));
152
153 moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W,
154 (((tm->tm_mon + 1) / 10) << 4) |
155 ((tm->tm_mon + 1) % 10));
156
157 moxart_rtc_write_register(dev, GPIO_RTC_DATE_W,
158 ((tm->tm_mday / 10) << 4) |
159 (tm->tm_mday % 10));
160
161 moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W,
162 ((tm->tm_hour / 10) << 4) |
163 (tm->tm_hour % 10));
164
165 moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W,
166 ((tm->tm_min / 10) << 4) |
167 (tm->tm_min % 10));
168
169 moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W,
170 ((tm->tm_sec / 10) << 4) |
171 (tm->tm_sec % 10));
172
173 moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80);
174
175 spin_unlock_irq(&moxart_rtc->rtc_lock);
176
177 dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n"
178 "tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n",
179 __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
180 tm->tm_hour, tm->tm_min, tm->tm_sec);
181
182 return 0;
183}
184
185static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm)
186{
187 struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
188 unsigned char v;
189
190 spin_lock_irq(&moxart_rtc->rtc_lock);
191
192 v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R);
193 tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
194
195 v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R);
196 tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
197
198 v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R);
199 if (v & 0x80) { /* 12-hour mode */
200 tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
201 if (v & 0x20) { /* PM mode */
202 tm->tm_hour += 12;
203 if (tm->tm_hour >= 24)
204 tm->tm_hour = 0;
205 }
206 } else { /* 24-hour mode */
207 tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
208 }
209
210 v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R);
211 tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
212
213 v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R);
214 tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
215 tm->tm_mon--;
216
217 v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R);
218 tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F);
219 tm->tm_year += 100;
220 if (tm->tm_year <= 69)
221 tm->tm_year += 100;
222
223 v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R);
224 tm->tm_wday = (v & 0x0f) - 1;
225 tm->tm_yday = day_of_year[tm->tm_mon];
226 tm->tm_yday += (tm->tm_mday - 1);
227 if (tm->tm_mon >= 2) {
228 if (!(tm->tm_year % 4) && (tm->tm_year % 100))
229 tm->tm_yday++;
230 }
231
232 tm->tm_isdst = 0;
233
234 spin_unlock_irq(&moxart_rtc->rtc_lock);
235
236 return 0;
237}
238
239static const struct rtc_class_ops moxart_rtc_ops = {
240 .read_time = moxart_rtc_read_time,
241 .set_time = moxart_rtc_set_time,
242};
243
244static int moxart_rtc_probe(struct platform_device *pdev)
245{
246 struct moxart_rtc *moxart_rtc;
247 int ret = 0;
248
249 moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL);
250 if (!moxart_rtc) {
251 dev_err(&pdev->dev, "devm_kzalloc failed\n");
252 return -ENOMEM;
253 }
254
255 moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node,
256 "gpio-rtc-data", 0);
257 if (!gpio_is_valid(moxart_rtc->gpio_data)) {
258 dev_err(&pdev->dev, "invalid gpio (data): %d\n",
259 moxart_rtc->gpio_data);
260 return moxart_rtc->gpio_data;
261 }
262
263 moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node,
264 "gpio-rtc-sclk", 0);
265 if (!gpio_is_valid(moxart_rtc->gpio_sclk)) {
266 dev_err(&pdev->dev, "invalid gpio (sclk): %d\n",
267 moxart_rtc->gpio_sclk);
268 return moxart_rtc->gpio_sclk;
269 }
270
271 moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node,
272 "gpio-rtc-reset", 0);
273 if (!gpio_is_valid(moxart_rtc->gpio_reset)) {
274 dev_err(&pdev->dev, "invalid gpio (reset): %d\n",
275 moxart_rtc->gpio_reset);
276 return moxart_rtc->gpio_reset;
277 }
278
279 spin_lock_init(&moxart_rtc->rtc_lock);
280 platform_set_drvdata(pdev, moxart_rtc);
281
282 ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data");
283 if (ret) {
284 dev_err(&pdev->dev, "can't get rtc_data gpio\n");
285 return ret;
286 }
287
288 ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk,
289 GPIOF_DIR_OUT, "rtc_sclk");
290 if (ret) {
291 dev_err(&pdev->dev, "can't get rtc_sclk gpio\n");
292 return ret;
293 }
294
295 ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset,
296 GPIOF_DIR_OUT, "rtc_reset");
297 if (ret) {
298 dev_err(&pdev->dev, "can't get rtc_reset gpio\n");
299 return ret;
300 }
301
302 moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
303 &moxart_rtc_ops,
304 THIS_MODULE);
305 if (IS_ERR(moxart_rtc->rtc)) {
306 dev_err(&pdev->dev, "devm_rtc_device_register failed\n");
307 return PTR_ERR(moxart_rtc->rtc);
308 }
309
310 return 0;
311}
312
313static const struct of_device_id moxart_rtc_match[] = {
314 { .compatible = "moxa,moxart-rtc" },
315 { },
316};
317
318static struct platform_driver moxart_rtc_driver = {
319 .probe = moxart_rtc_probe,
320 .driver = {
321 .name = "moxart-rtc",
322 .owner = THIS_MODULE,
323 .of_match_table = moxart_rtc_match,
324 },
325};
326module_platform_driver(moxart_rtc_driver);
327
328MODULE_DESCRIPTION("MOXART RTC driver");
329MODULE_LICENSE("GPL");
330MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");