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
  19/* Registers */
  20#define EM3027_REG_ON_OFF_CTRL  0x00
  21#define EM3027_REG_IRQ_CTRL     0x01
  22#define EM3027_REG_IRQ_FLAGS    0x02
  23#define EM3027_REG_STATUS       0x03
  24#define EM3027_REG_RST_CTRL     0x04
  25
  26#define EM3027_REG_WATCH_SEC    0x08
  27#define EM3027_REG_WATCH_MIN    0x09
  28#define EM3027_REG_WATCH_HOUR   0x0a
  29#define EM3027_REG_WATCH_DATE   0x0b
  30#define EM3027_REG_WATCH_DAY    0x0c
  31#define EM3027_REG_WATCH_MON    0x0d
  32#define EM3027_REG_WATCH_YEAR   0x0e
  33
  34#define EM3027_REG_ALARM_SEC    0x10
  35#define EM3027_REG_ALARM_MIN    0x11
  36#define EM3027_REG_ALARM_HOUR   0x12
  37#define EM3027_REG_ALARM_DATE   0x13
  38#define EM3027_REG_ALARM_DAY    0x14
  39#define EM3027_REG_ALARM_MON    0x15
  40#define EM3027_REG_ALARM_YEAR   0x16
  41
  42static struct i2c_driver em3027_driver;
  43
  44static int em3027_get_time(struct device *dev, struct rtc_time *tm)
  45{
  46        struct i2c_client *client = to_i2c_client(dev);
  47
  48        unsigned char addr = EM3027_REG_WATCH_SEC;
  49        unsigned char buf[7];
  50
  51        struct i2c_msg msgs[] = {
  52                {client->addr, 0, 1, &addr},            /* setup read addr */
  53                {client->addr, I2C_M_RD, 7, buf},       /* read time/date */
  54        };
  55
  56        /* read time/date registers */
  57        if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
  58                dev_err(&client->dev, "%s: read error\n", __func__);
  59                return -EIO;
  60        }
  61
  62        tm->tm_sec      = bcd2bin(buf[0]);
  63        tm->tm_min      = bcd2bin(buf[1]);
  64        tm->tm_hour     = bcd2bin(buf[2]);
  65        tm->tm_mday     = bcd2bin(buf[3]);
  66        tm->tm_wday     = bcd2bin(buf[4]);
  67        tm->tm_mon      = bcd2bin(buf[5]);
  68        tm->tm_year     = bcd2bin(buf[6]) + 100;
  69
  70        return 0;
  71}
  72
  73static int em3027_set_time(struct device *dev, struct rtc_time *tm)
  74{
  75        struct i2c_client *client = to_i2c_client(dev);
  76        unsigned char buf[8];
  77
  78        struct i2c_msg msg = {
  79                client->addr, 0, 8, buf,        /* write time/date */
  80        };
  81
  82        buf[0] = EM3027_REG_WATCH_SEC;
  83        buf[1] = bin2bcd(tm->tm_sec);
  84        buf[2] = bin2bcd(tm->tm_min);
  85        buf[3] = bin2bcd(tm->tm_hour);
  86        buf[4] = bin2bcd(tm->tm_mday);
  87        buf[5] = bin2bcd(tm->tm_wday);
  88        buf[6] = bin2bcd(tm->tm_mon);
  89        buf[7] = bin2bcd(tm->tm_year % 100);
  90
  91        /* write time/date registers */
  92        if ((i2c_transfer(client->adapter, &msg, 1)) != 1) {
  93                dev_err(&client->dev, "%s: write error\n", __func__);
  94                return -EIO;
  95        }
  96
  97        return 0;
  98}
  99
 100static const struct rtc_class_ops em3027_rtc_ops = {
 101        .read_time = em3027_get_time,
 102        .set_time = em3027_set_time,
 103};
 104
 105static int em3027_probe(struct i2c_client *client,
 106                        const struct i2c_device_id *id)
 107{
 108        struct rtc_device *rtc;
 109
 110        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 111                return -ENODEV;
 112
 113        rtc = rtc_device_register(em3027_driver.driver.name, &client->dev,
 114                                  &em3027_rtc_ops, THIS_MODULE);
 115        if (IS_ERR(rtc))
 116                return PTR_ERR(rtc);
 117
 118        i2c_set_clientdata(client, rtc);
 119
 120        return 0;
 121}
 122
 123static int em3027_remove(struct i2c_client *client)
 124{
 125        struct rtc_device *rtc = i2c_get_clientdata(client);
 126
 127        if (rtc)
 128                rtc_device_unregister(rtc);
 129
 130        return 0;
 131}
 132
 133static struct i2c_device_id em3027_id[] = {
 134        { "em3027", 0 },
 135        { }
 136};
 137
 138static struct i2c_driver em3027_driver = {
 139        .driver = {
 140                   .name = "rtc-em3027",
 141        },
 142        .probe = &em3027_probe,
 143        .remove = &em3027_remove,
 144        .id_table = em3027_id,
 145};
 146
 147module_i2c_driver(em3027_driver);
 148
 149MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 150MODULE_DESCRIPTION("EM Microelectronic EM3027 RTC driver");
 151MODULE_LICENSE("GPL");
 152
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.