code style scripts/checkpatch.pl (linux-3.9-rc1) formatting
[linux-2.6.34.14-moxart.git] / drivers / rtc / rtc-moxart.c
blobc41160616e68f80b3cc15cd5a7ea5a7165505696
1 /* Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the License,
5 * or (at your option) any later version. */
7 #include <linux/bcd.h>
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/delay.h>
11 #include <linux/jiffies.h>
12 #include <linux/rtc.h>
13 #include <linux/platform_device.h>
14 #include <linux/io.h>
16 #include <mach/hardware.h>
17 #include <mach/gpio.h>
19 #define DRV_VERSION "1.0"
21 #define RTC_REG_SIZE 0x1000
23 struct rtc_plat_data {
24 struct rtc_device *rtc;
25 void __iomem *ioaddr;
26 resource_size_t baseaddr;
27 unsigned long last_jiffies;
28 int irq;
29 unsigned int irqen;
30 int alrm_sec;
31 int alrm_min;
32 int alrm_hour;
33 int alrm_mday;
36 static spinlock_t rtc_lock;
37 static int day_of_year[12] = {0, 31, 59, 90, 120, 151, 181,
38 212, 243, 273, 304, 334};
40 static u8 moxart_rtc_read_register(u8 cmd)
42 u8 data;
43 unsigned long flags;
45 local_irq_save(flags);
47 moxart_gpio_inout(GPIO_RTC_DATA, GPIO_EM1240_OUTPUT);
48 moxart_gpio_set(GPIO_RTC_RESET, GPIO_EM1240_HIGH);
49 udelay(GPIO_RTC_DELAY_TIME);
51 moxart_gpio_write_byte(cmd);
53 moxart_gpio_inout(GPIO_RTC_DATA, GPIO_EM1240_INPUT);
54 udelay(GPIO_RTC_DELAY_TIME);
56 data = moxart_gpio_read_byte();
58 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_LOW);
59 moxart_gpio_set(GPIO_RTC_RESET, GPIO_EM1240_LOW);
60 udelay(GPIO_RTC_DELAY_TIME);
62 local_irq_restore(flags);
64 return data;
67 static void moxart_rtc_write_register(u8 cmd, u8 data)
69 unsigned long flags;
71 local_irq_save(flags);
73 moxart_gpio_inout(GPIO_RTC_DATA, GPIO_EM1240_OUTPUT);
74 moxart_gpio_set(GPIO_RTC_RESET, GPIO_EM1240_HIGH);
75 udelay(GPIO_RTC_DELAY_TIME);
77 moxart_gpio_write_byte(cmd);
79 moxart_gpio_inout(GPIO_RTC_DATA, GPIO_EM1240_OUTPUT);
81 moxart_gpio_write_byte(data);
83 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_LOW);
84 moxart_gpio_set(GPIO_RTC_RESET, GPIO_EM1240_LOW);
85 udelay(GPIO_RTC_DELAY_TIME);
86 /* moxart_gpio_inout(GPIO_RTC_DATA, GPIO_EM1240_INPUT); */
88 local_irq_restore(flags);
91 static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm)
93 spin_lock_irq(&rtc_lock);
95 moxart_rtc_write_register(GPIO_RTC_PROTECT_W, 0);
96 moxart_rtc_write_register(GPIO_RTC_YEAR_W,
97 ((((tm->tm_year - 100) / 10) << 4) |
98 ((tm->tm_year - 100) % 10)));
99 moxart_rtc_write_register(GPIO_RTC_MONTH_W,
100 ((((tm->tm_mon + 1) / 10) << 4) | ((tm->tm_mon + 1) % 10)));
101 moxart_rtc_write_register(GPIO_RTC_DATE_W,
102 (((tm->tm_mday / 10) << 4) | (tm->tm_mday % 10)));
103 moxart_rtc_write_register(GPIO_RTC_HOURS_W,
104 (((tm->tm_hour / 10) << 4) | (tm->tm_hour % 10)));
105 moxart_rtc_write_register(GPIO_RTC_MINUTES_W,
106 (((tm->tm_min / 10) << 4) | (tm->tm_min % 10)));
107 moxart_rtc_write_register(GPIO_RTC_SECONDS_W,
108 (((tm->tm_sec / 10) << 4) | (tm->tm_sec % 10)));
109 moxart_rtc_write_register(GPIO_RTC_PROTECT_W, 0x80);
111 spin_unlock_irq(&rtc_lock);
113 dbg_printk(KERN_INFO
114 "MOXART RTC: moxart_rtc_set_time success tm_year=%d tm_mon=%d\n"
115 "tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n",
116 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
117 tm->tm_min, tm->tm_sec);
119 return 0;
122 static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm)
124 unsigned char v;
126 spin_lock_irq(&rtc_lock);
128 v = moxart_rtc_read_register(GPIO_RTC_SECONDS_R);
129 tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
130 v = moxart_rtc_read_register(GPIO_RTC_MINUTES_R);
131 tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
132 v = moxart_rtc_read_register(GPIO_RTC_HOURS_R);
133 if (v & 0x80) { /* 12-hour mode */
134 tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
135 if (v & 0x20) { /* PM mode */
136 tm->tm_hour += 12;
137 if (tm->tm_hour >= 24)
138 tm->tm_hour = 0;
140 } else { /* 24-hour mode */
141 tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
143 v = moxart_rtc_read_register(GPIO_RTC_DATE_R);
144 tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
145 v = moxart_rtc_read_register(GPIO_RTC_MONTH_R);
146 tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
147 tm->tm_mon--;
148 v = moxart_rtc_read_register(GPIO_RTC_YEAR_R);
149 tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F);
150 tm->tm_year += 100;
151 if (tm->tm_year <= 69)
152 tm->tm_year += 100;
153 v = moxart_rtc_read_register(GPIO_RTC_DAY_R);
154 tm->tm_wday = (v & 0x0f) - 1;
155 tm->tm_yday = day_of_year[tm->tm_mon];
156 tm->tm_yday += (tm->tm_mday - 1);
157 if (tm->tm_mon >= 2) {
158 if (!(tm->tm_year % 4) && (tm->tm_year % 100))
159 tm->tm_yday++;
161 tm->tm_isdst = 0;
163 spin_unlock_irq(&rtc_lock);
165 return 0;
168 static int moxart_rtc_ioctl(struct device *dev, unsigned int cmd,
169 unsigned long arg)
171 struct platform_device *pdev = to_platform_device(dev);
172 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
174 if (pdata->irq <= 0)
175 return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
176 switch (cmd) {
177 default:
178 return -ENOIOCTLCMD;
180 return 0;
183 static const struct rtc_class_ops moxart_rtc_ops = {
184 .read_time = moxart_rtc_read_time,
185 .set_time = moxart_rtc_set_time,
186 .ioctl = moxart_rtc_ioctl,
189 static int moxart_rtc_probe(struct platform_device *pdev)
191 struct rtc_device *rtc;
192 struct resource *res;
193 struct rtc_plat_data *pdata = NULL;
194 void __iomem *ioaddr = NULL;
195 int ret = 0;
197 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
198 if (!res) {
199 dev_info(&pdev->dev,
200 "MOXART RTC: platform_get_resource failed\n");
201 return -ENODEV;
203 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
204 if (!pdata) {
205 dev_info(&pdev->dev, "MOXART RTC: devm_kzalloc failed\n");
206 return -ENOMEM;
208 if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
209 ret = -EBUSY;
210 dev_info(&pdev->dev, "MOXART RTC: request_mem_region failed\n");
211 goto out;
213 pdata->baseaddr = res->start;
214 ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
215 if (!ioaddr) {
216 ret = -ENOMEM;
217 dev_info(&pdev->dev, "MOXART RTC: ioremap failed\n");
218 goto out;
220 pdata->ioaddr = ioaddr;
222 moxart_gpio_mp_set(GPIO_RTC_MASK);
223 moxart_gpio_inout(GPIO_RTC_RESET, GPIO_EM1240_OUTPUT);
224 moxart_gpio_inout(GPIO_RTC_SCLK, GPIO_EM1240_OUTPUT);
226 rtc = rtc_device_register(pdev->name, &pdev->dev,
227 &moxart_rtc_ops, THIS_MODULE);
228 if (IS_ERR(rtc)) {
229 ret = PTR_ERR(rtc);
230 goto out;
232 pdata->rtc = rtc;
233 pdata->last_jiffies = jiffies;
234 platform_set_drvdata(pdev, pdata);
236 spin_lock_init(&rtc_lock);
238 dev_info(&pdev->dev, "MOXART RTC: finished moxart_rtc_probe\n");
240 if (ret)
241 goto out;
243 return 0;
245 out:
246 if (pdata->rtc)
247 rtc_device_unregister(pdata->rtc);
248 if (ioaddr)
249 iounmap(ioaddr);
250 if (pdata->baseaddr)
251 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
252 devm_kfree(&pdev->dev, pdata);
253 return ret;
256 static int moxart_rtc_remove(struct platform_device *pdev)
258 struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
260 rtc_device_unregister(pdata->rtc);
261 iounmap(pdata->ioaddr);
262 release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
263 devm_kfree(&pdev->dev, pdata);
264 return 0;
267 /* work with hotplug and coldplug */
268 MODULE_ALIAS("platform:rtc-moxart");
270 static struct platform_driver moxart_rtc_driver = {
271 .probe = moxart_rtc_probe,
272 .remove = __devexit_p(moxart_rtc_remove),
273 .driver = {
274 .name = "MOXART_RTC",
275 .owner = THIS_MODULE,
279 static __init int moxart_init(void)
281 return platform_driver_register(&moxart_rtc_driver);
284 static __exit void moxart_exit(void)
286 platform_driver_unregister(&moxart_rtc_driver);
289 module_init(moxart_init);
290 module_exit(moxart_exit);
292 MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
293 MODULE_DESCRIPTION("MOXART RTC driver");
294 MODULE_LICENSE("GPL");
295 MODULE_VERSION(DRV_VERSION);