]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/rtc/rtc-v3020.c
Merge branch 'bugzilla-15749' into release
[karo-tx-linux.git] / drivers / rtc / rtc-v3020.c
1 /* drivers/rtc/rtc-v3020.c
2  *
3  * Copyright (C) 2006 8D Technologies inc.
4  * Copyright (C) 2004 Compulab Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Driver for the V3020 RTC
11  *
12  * Changelog:
13  *
14  *  10-May-2006: Raphael Assenat <raph@8d.com>
15  *                              - Converted to platform driver
16  *                              - Use the generic rtc class
17  *
18  *  ??-???-2004: Someone at Compulab
19  *                      - Initial driver creation.
20  *
21  */
22 #include <linux/platform_device.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/rtc.h>
26 #include <linux/types.h>
27 #include <linux/bcd.h>
28 #include <linux/rtc-v3020.h>
29 #include <linux/delay.h>
30 #include <linux/gpio.h>
31 #include <linux/slab.h>
32
33 #include <linux/io.h>
34
35 #undef DEBUG
36
37 struct v3020;
38
39 struct v3020_chip_ops {
40         int (*map_io)(struct v3020 *chip, struct platform_device *pdev,
41                       struct v3020_platform_data *pdata);
42         void (*unmap_io)(struct v3020 *chip);
43         unsigned char (*read_bit)(struct v3020 *chip);
44         void (*write_bit)(struct v3020 *chip, unsigned char bit);
45 };
46
47 #define V3020_CS        0
48 #define V3020_WR        1
49 #define V3020_RD        2
50 #define V3020_IO        3
51
52 struct v3020_gpio {
53         const char *name;
54         unsigned int gpio;
55 };
56
57 struct v3020 {
58         /* MMIO access */
59         void __iomem *ioaddress;
60         int leftshift;
61
62         /* GPIO access */
63         struct v3020_gpio *gpio;
64
65         struct v3020_chip_ops *ops;
66
67         struct rtc_device *rtc;
68 };
69
70
71 static int v3020_mmio_map(struct v3020 *chip, struct platform_device *pdev,
72                           struct v3020_platform_data *pdata)
73 {
74         if (pdev->num_resources != 1)
75                 return -EBUSY;
76
77         if (pdev->resource[0].flags != IORESOURCE_MEM)
78                 return -EBUSY;
79
80         chip->leftshift = pdata->leftshift;
81         chip->ioaddress = ioremap(pdev->resource[0].start, 1);
82         if (chip->ioaddress == NULL)
83                 return -EBUSY;
84
85         return 0;
86 }
87
88 static void v3020_mmio_unmap(struct v3020 *chip)
89 {
90         iounmap(chip->ioaddress);
91 }
92
93 static void v3020_mmio_write_bit(struct v3020 *chip, unsigned char bit)
94 {
95         writel(bit << chip->leftshift, chip->ioaddress);
96 }
97
98 static unsigned char v3020_mmio_read_bit(struct v3020 *chip)
99 {
100         return !!(readl(chip->ioaddress) & (1 << chip->leftshift));
101 }
102
103 static struct v3020_chip_ops v3020_mmio_ops = {
104         .map_io         = v3020_mmio_map,
105         .unmap_io       = v3020_mmio_unmap,
106         .read_bit       = v3020_mmio_read_bit,
107         .write_bit      = v3020_mmio_write_bit,
108 };
109
110 static struct v3020_gpio v3020_gpio[] = {
111         { "RTC CS", 0 },
112         { "RTC WR", 0 },
113         { "RTC RD", 0 },
114         { "RTC IO", 0 },
115 };
116
117 static int v3020_gpio_map(struct v3020 *chip, struct platform_device *pdev,
118                           struct v3020_platform_data *pdata)
119 {
120         int i, err;
121
122         v3020_gpio[V3020_CS].gpio = pdata->gpio_cs;
123         v3020_gpio[V3020_WR].gpio = pdata->gpio_wr;
124         v3020_gpio[V3020_RD].gpio = pdata->gpio_rd;
125         v3020_gpio[V3020_IO].gpio = pdata->gpio_io;
126
127         for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) {
128                 err = gpio_request(v3020_gpio[i].gpio, v3020_gpio[i].name);
129                 if (err)
130                         goto err_request;
131
132                 gpio_direction_output(v3020_gpio[i].gpio, 1);
133         }
134
135         chip->gpio = v3020_gpio;
136
137         return 0;
138
139 err_request:
140         while (--i >= 0)
141                 gpio_free(v3020_gpio[i].gpio);
142
143         return err;
144 }
145
146 static void v3020_gpio_unmap(struct v3020 *chip)
147 {
148         int i;
149
150         for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++)
151                 gpio_free(v3020_gpio[i].gpio);
152 }
153
154 static void v3020_gpio_write_bit(struct v3020 *chip, unsigned char bit)
155 {
156         gpio_direction_output(chip->gpio[V3020_IO].gpio, bit);
157         gpio_set_value(chip->gpio[V3020_CS].gpio, 0);
158         gpio_set_value(chip->gpio[V3020_WR].gpio, 0);
159         udelay(1);
160         gpio_set_value(chip->gpio[V3020_WR].gpio, 1);
161         gpio_set_value(chip->gpio[V3020_CS].gpio, 1);
162 }
163
164 static unsigned char v3020_gpio_read_bit(struct v3020 *chip)
165 {
166         int bit;
167
168         gpio_direction_input(chip->gpio[V3020_IO].gpio);
169         gpio_set_value(chip->gpio[V3020_CS].gpio, 0);
170         gpio_set_value(chip->gpio[V3020_RD].gpio, 0);
171         udelay(1);
172         bit = !!gpio_get_value(chip->gpio[V3020_IO].gpio);
173         udelay(1);
174         gpio_set_value(chip->gpio[V3020_RD].gpio, 1);
175         gpio_set_value(chip->gpio[V3020_CS].gpio, 1);
176
177         return bit;
178 }
179
180 static struct v3020_chip_ops v3020_gpio_ops = {
181         .map_io         = v3020_gpio_map,
182         .unmap_io       = v3020_gpio_unmap,
183         .read_bit       = v3020_gpio_read_bit,
184         .write_bit      = v3020_gpio_write_bit,
185 };
186
187 static void v3020_set_reg(struct v3020 *chip, unsigned char address,
188                         unsigned char data)
189 {
190         int i;
191         unsigned char tmp;
192
193         tmp = address;
194         for (i = 0; i < 4; i++) {
195                 chip->ops->write_bit(chip, (tmp & 1));
196                 tmp >>= 1;
197                 udelay(1);
198         }
199
200         /* Commands dont have data */
201         if (!V3020_IS_COMMAND(address)) {
202                 for (i = 0; i < 8; i++) {
203                         chip->ops->write_bit(chip, (data & 1));
204                         data >>= 1;
205                         udelay(1);
206                 }
207         }
208 }
209
210 static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address)
211 {
212         unsigned int data = 0;
213         int i;
214
215         for (i = 0; i < 4; i++) {
216                 chip->ops->write_bit(chip, (address & 1));
217                 address >>= 1;
218                 udelay(1);
219         }
220
221         for (i = 0; i < 8; i++) {
222                 data >>= 1;
223                 if (chip->ops->read_bit(chip))
224                         data |= 0x80;
225                 udelay(1);
226         }
227
228         return data;
229 }
230
231 static int v3020_read_time(struct device *dev, struct rtc_time *dt)
232 {
233         struct v3020 *chip = dev_get_drvdata(dev);
234         int tmp;
235
236         /* Copy the current time to ram... */
237         v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0);
238
239         /* ...and then read constant values. */
240         tmp = v3020_get_reg(chip, V3020_SECONDS);
241         dt->tm_sec      = bcd2bin(tmp);
242         tmp = v3020_get_reg(chip, V3020_MINUTES);
243         dt->tm_min      = bcd2bin(tmp);
244         tmp = v3020_get_reg(chip, V3020_HOURS);
245         dt->tm_hour     = bcd2bin(tmp);
246         tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
247         dt->tm_mday     = bcd2bin(tmp);
248         tmp = v3020_get_reg(chip, V3020_MONTH);
249         dt->tm_mon    = bcd2bin(tmp) - 1;
250         tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
251         dt->tm_wday     = bcd2bin(tmp);
252         tmp = v3020_get_reg(chip, V3020_YEAR);
253         dt->tm_year = bcd2bin(tmp)+100;
254
255         dev_dbg(dev, "\n%s : Read RTC values\n", __func__);
256         dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
257         dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
258         dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
259         dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
260         dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
261         dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
262         dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
263
264         return 0;
265 }
266
267
268 static int v3020_set_time(struct device *dev, struct rtc_time *dt)
269 {
270         struct v3020 *chip = dev_get_drvdata(dev);
271
272         dev_dbg(dev, "\n%s : Setting RTC values\n", __func__);
273         dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
274         dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
275         dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
276         dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
277         dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
278         dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
279
280         /* Write all the values to ram... */
281         v3020_set_reg(chip, V3020_SECONDS,      bin2bcd(dt->tm_sec));
282         v3020_set_reg(chip, V3020_MINUTES,      bin2bcd(dt->tm_min));
283         v3020_set_reg(chip, V3020_HOURS,        bin2bcd(dt->tm_hour));
284         v3020_set_reg(chip, V3020_MONTH_DAY,    bin2bcd(dt->tm_mday));
285         v3020_set_reg(chip, V3020_MONTH,     bin2bcd(dt->tm_mon + 1));
286         v3020_set_reg(chip, V3020_WEEK_DAY,     bin2bcd(dt->tm_wday));
287         v3020_set_reg(chip, V3020_YEAR,         bin2bcd(dt->tm_year % 100));
288
289         /* ...and set the clock. */
290         v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
291
292         /* Compulab used this delay here. I dont know why,
293          * the datasheet does not specify a delay. */
294         /*mdelay(5);*/
295
296         return 0;
297 }
298
299 static const struct rtc_class_ops v3020_rtc_ops = {
300         .read_time      = v3020_read_time,
301         .set_time       = v3020_set_time,
302 };
303
304 static int rtc_probe(struct platform_device *pdev)
305 {
306         struct v3020_platform_data *pdata = pdev->dev.platform_data;
307         struct v3020 *chip;
308         int retval = -EBUSY;
309         int i;
310         int temp;
311
312         chip = kzalloc(sizeof *chip, GFP_KERNEL);
313         if (!chip)
314                 return -ENOMEM;
315
316         if (pdata->use_gpio)
317                 chip->ops = &v3020_gpio_ops;
318         else
319                 chip->ops = &v3020_mmio_ops;
320
321         retval = chip->ops->map_io(chip, pdev, pdata);
322         if (retval)
323                 goto err_chip;
324
325         /* Make sure the v3020 expects a communication cycle
326          * by reading 8 times */
327         for (i = 0; i < 8; i++)
328                 temp = chip->ops->read_bit(chip);
329
330         /* Test chip by doing a write/read sequence
331          * to the chip ram */
332         v3020_set_reg(chip, V3020_SECONDS, 0x33);
333         if (v3020_get_reg(chip, V3020_SECONDS) != 0x33) {
334                 retval = -ENODEV;
335                 goto err_io;
336         }
337
338         /* Make sure frequency measurement mode, test modes, and lock
339          * are all disabled */
340         v3020_set_reg(chip, V3020_STATUS_0, 0x0);
341
342         if (pdata->use_gpio)
343                 dev_info(&pdev->dev, "Chip available at GPIOs "
344                          "%d, %d, %d, %d\n",
345                          chip->gpio[V3020_CS].gpio, chip->gpio[V3020_WR].gpio,
346                          chip->gpio[V3020_RD].gpio, chip->gpio[V3020_IO].gpio);
347         else
348                 dev_info(&pdev->dev, "Chip available at "
349                          "physical address 0x%llx,"
350                          "data connected to D%d\n",
351                          (unsigned long long)pdev->resource[0].start,
352                          chip->leftshift);
353
354         platform_set_drvdata(pdev, chip);
355
356         chip->rtc = rtc_device_register("v3020",
357                                 &pdev->dev, &v3020_rtc_ops, THIS_MODULE);
358         if (IS_ERR(chip->rtc)) {
359                 retval = PTR_ERR(chip->rtc);
360                 goto err_io;
361         }
362
363         return 0;
364
365 err_io:
366         chip->ops->unmap_io(chip);
367 err_chip:
368         kfree(chip);
369
370         return retval;
371 }
372
373 static int rtc_remove(struct platform_device *dev)
374 {
375         struct v3020 *chip = platform_get_drvdata(dev);
376         struct rtc_device *rtc = chip->rtc;
377
378         if (rtc)
379                 rtc_device_unregister(rtc);
380
381         chip->ops->unmap_io(chip);
382         kfree(chip);
383
384         return 0;
385 }
386
387 static struct platform_driver rtc_device_driver = {
388         .probe  = rtc_probe,
389         .remove = rtc_remove,
390         .driver = {
391                 .name   = "v3020",
392                 .owner  = THIS_MODULE,
393         },
394 };
395
396 static __init int v3020_init(void)
397 {
398         return platform_driver_register(&rtc_device_driver);
399 }
400
401 static __exit void v3020_exit(void)
402 {
403         platform_driver_unregister(&rtc_device_driver);
404 }
405
406 module_init(v3020_init);
407 module_exit(v3020_exit);
408
409 MODULE_DESCRIPTION("V3020 RTC");
410 MODULE_AUTHOR("Raphael Assenat");
411 MODULE_LICENSE("GPL");
412 MODULE_ALIAS("platform:v3020");