linux/drivers/rtc/rtc-em3027.c
<<
>>
Prefs
   1/*
   2 * An rtc/i2c driver for the EM Microelectronic EM3027
   3 * Copyright 2011 CompuLab, Ltd.
   4 *
   5 * Author: Mike Rapoport <mike@compulab.co.il>
   6 *
   7 * Based on rtc-ds1672.c by Alessandro Zummo <a.zummo@towertech.it>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13
  14#include <linux/i2c.h>
  15#include <linux/rtc.h>
  16#include <linux/bcd.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19
  20/* Registers */
  21#define EM3027_REG_ON_OFF_CTRL  0x00
  22#define EM3027_REG_IRQ_CTRL     0x01
  23#define EM3027_REG_IRQ_FLAGS    0x02
  24#define EM3027_REG_STATUS       0x03
  25#define EM3027_REG_RST_CTRL     0x04
  26
  27#define EM3027_REG_WATCH_SEC    0x08
  28#define EM3027_REG_WATCH_MIN    0x09
  29#define EM3027_REG_WATCH_HOUR   0x0a
  30#define EM3027_REG_WATCH_DATE   0x0b
  31#define EM3027_REG_WATCH_DAY    0x0c
  32#define EM3027_REG_WATCH_MON    0x0d
  33#define EM3027_REG_WATCH_YEAR   0x0e
  34
  35#define EM3027_REG_ALARM_SEC    0x10
  36#define EM3027_REG_ALARM_MIN    0x11
  37#define EM3027_REG_ALARM_HOUR   0x12
  38#define EM3027_REG_ALARM_DATE   0x13
  39#define EM3027_REG_ALARM_DAY    0x14
  40#define EM3027_REG_ALARM_MON    0x15
  41#define EM3027_REG_ALARM_YEAR   0x16
  42
  43static struct i2c_driver em3027_driver;
  44
  45static int em3027_get_time(struct device *dev, struct rtc_time *tm)
  46{
  47        struct i2c_client *client = to_i2c_client(dev);
  48
  49        unsigned char addr = EM3027_REG_WATCH_SEC;
  50        unsigned char buf[7];
  51
  52        struct i2c_msg msgs[] = {
  53                {/* setup read addr */
  54                        .addr = client->addr,
  55                        .len = 1,
  56                        .buf = &addr
  57                },
  58                {/* read time/date */
  59                        .addr = client->addr,
  60                        .flags = I2C_M_RD,
  61                        .len = 7,
  62                        .buf = buf
  63                },
  64        };
  65
  66        /* read time/date registers */
  67        if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
  68                dev_err(&client->dev, "%s: read error\n", __func__);
  69                return -EIO;
  70        }
  71
  72        tm->tm_sec      = bcd2bin(buf[0]);
  73        tm->tm_min      = bcd2bin(buf[1]);
  74        tm->tm_hour     = bcd2bin(buf[2]);
  75        tm->tm_mday     = bcd2bin(buf[3]);
  76        tm->tm_wday     = bcd2bin(buf[4]);
  77        tm->tm_mon      = bcd2bin(buf[5]);
  78        tm->tm_year     = bcd2bin(buf[6]) + 100;
  79
  80        return 0;
  81}
  82
  83static int em3027_set_time(struct device *dev, struct rtc_time *tm)
  84{
  85        struct i2c_client *client = to_i2c_client(dev);
  86        unsigned char buf[8];
  87
  88        struct i2c_msg msg = {
  89                .addr = client->addr,
  90                .len = 8,
  91                .buf = buf,     /* write time/date */
  92        };
  93
  94        buf[0] = EM3027_REG_WATCH_SEC;
  95        buf[1] = bin2bcd(tm->tm_sec);
  96        buf[2] = bin2bcd(tm->tm_min);
  97        buf[3] = bin2bcd(tm->tm_hour);
  98        buf[4] = bin2bcd(tm->tm_mday);
  99        buf[5] = bin2bcd(tm->tm_wday);
 100        buf[6] = bin2bcd(tm->tm_mon);
 101        buf[7] = bin2bcd(tm->tm_year % 100);
 102
 103        /* write time/date registers */
 104        if ((i2c_transfer(client->adapter, &msg, 1)) != 1) {
 105                dev_err(&client->dev, "%s: write error\n", __func__);
 106                return -EIO;
 107        }
 108
 109        return 0;
 110}
 111
 112static const struct rtc_class_ops em3027_rtc_ops = {
 113        .read_time = em3027_get_time,
 114        .set_time = em3027_set_time,
 115};
 116
 117static int em3027_probe(struct i2c_client *client,
 118                        const struct i2c_device_id *id)
 119{
 120        struct rtc_device *rtc;
 121
 122        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 123                return -ENODEV;
 124
 125        rtc = devm_rtc_device_register(&client->dev, em3027_driver.driver.name,
 126                                  &em3027_rtc_ops, THIS_MODULE);
 127        if (IS_ERR(rtc))
 128                return PTR_ERR(rtc);
 129
 130        i2c_set_clientdata(client, rtc);
 131
 132        return 0;
 133}
 134
 135static const struct i2c_device_id em3027_id[] = {
 136        { "em3027", 0 },
 137        { }
 138};
 139MODULE_DEVICE_TABLE(i2c, em3027_id);
 140
 141#ifdef CONFIG_OF
 142static const struct of_device_id em3027_of_match[] = {
 143        { .compatible = "emmicro,em3027", },
 144        {}
 145};
 146MODULE_DEVICE_TABLE(of, em3027_of_match);
 147#endif
 148
 149static struct i2c_driver em3027_driver = {
 150        .driver = {
 151                   .name = "rtc-em3027",
 152                   .of_match_table = of_match_ptr(em3027_of_match),
 153        },
 154        .probe = &em3027_probe,
 155        .id_table = em3027_id,
 156};
 157
 158module_i2c_driver(em3027_driver);
 159
 160MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 161MODULE_DESCRIPTION("EM Microelectronic EM3027 RTC driver");
 162MODULE_LICENSE("GPL");
 163