root/drivers/rtc/rtc-v3020.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. v3020_mmio_map
  2. v3020_mmio_unmap
  3. v3020_mmio_write_bit
  4. v3020_mmio_read_bit
  5. v3020_gpio_map
  6. v3020_gpio_unmap
  7. v3020_gpio_write_bit
  8. v3020_gpio_read_bit
  9. v3020_set_reg
  10. v3020_get_reg
  11. v3020_read_time
  12. v3020_set_time
  13. rtc_probe
  14. rtc_remove

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

/* [<][>][^][v][top][bottom][index][help] */