Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

Linux/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 = dev_get_platdata(&pdev->dev);
307         struct v3020 *chip;
308         int retval = -EBUSY;
309         int i;
310         int temp;
311 
312         chip = devm_kzalloc(&pdev->dev, 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                 return retval;
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 = devm_rtc_device_register(&pdev->dev, "v3020",
357                                         &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 
368         return retval;
369 }
370 
371 static int rtc_remove(struct platform_device *dev)
372 {
373         struct v3020 *chip = platform_get_drvdata(dev);
374 
375         chip->ops->unmap_io(chip);
376 
377         return 0;
378 }
379 
380 static struct platform_driver rtc_device_driver = {
381         .probe  = rtc_probe,
382         .remove = rtc_remove,
383         .driver = {
384                 .name   = "v3020",
385                 .owner  = THIS_MODULE,
386         },
387 };
388 
389 module_platform_driver(rtc_device_driver);
390 
391 MODULE_DESCRIPTION("V3020 RTC");
392 MODULE_AUTHOR("Raphael Assenat");
393 MODULE_LICENSE("GPL");
394 MODULE_ALIAS("platform:v3020");
395 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us