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