linux/drivers/i2c/chips/ds1337.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/i2c/chips/ds1337.c
   3 *
   4 *  Copyright (C) 2005 James Chapman <jchapman@katalix.com>
   5 *
   6 *      based on linux/drivers/acorn/char/pcf8583.c
   7 *  Copyright (C) 2000 Russell King
   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 * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/init.h>
  18#include <linux/slab.h>
  19#include <linux/i2c.h>
  20#include <linux/string.h>
  21#include <linux/rtc.h>          /* get the user-level API */
  22#include <linux/bcd.h>
  23#include <linux/list.h>
  24
  25/* Device registers */
  26#define DS1337_REG_HOUR         2
  27#define DS1337_REG_DAY          3
  28#define DS1337_REG_DATE         4
  29#define DS1337_REG_MONTH        5
  30#define DS1337_REG_CONTROL      14
  31#define DS1337_REG_STATUS       15
  32
  33/* FIXME - how do we export these interface constants? */
  34#define DS1337_GET_DATE         0
  35#define DS1337_SET_DATE         1
  36
  37/*
  38 * Functions declaration
  39 */
  40static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
  41
  42I2C_CLIENT_INSMOD_1(ds1337);
  43
  44static int ds1337_attach_adapter(struct i2c_adapter *adapter);
  45static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
  46static void ds1337_init_client(struct i2c_client *client);
  47static int ds1337_detach_client(struct i2c_client *client);
  48static int ds1337_command(struct i2c_client *client, unsigned int cmd,
  49                          void *arg);
  50
  51/*
  52 * Driver data (common to all clients)
  53 */
  54static struct i2c_driver ds1337_driver = {
  55        .driver = {
  56                .name   = "ds1337",
  57        },
  58        .attach_adapter = ds1337_attach_adapter,
  59        .detach_client  = ds1337_detach_client,
  60        .command        = ds1337_command,
  61};
  62
  63/*
  64 * Client data (each client gets its own)
  65 */
  66struct ds1337_data {
  67        struct i2c_client client;
  68        struct list_head list;
  69};
  70
  71/*
  72 * Internal variables
  73 */
  74static LIST_HEAD(ds1337_clients);
  75
  76static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
  77{
  78        s32 tmp = i2c_smbus_read_byte_data(client, reg);
  79
  80        if (tmp < 0)
  81                return -EIO;
  82
  83        *value = tmp;
  84
  85        return 0;
  86}
  87
  88/*
  89 * Chip access functions
  90 */
  91static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
  92{
  93        int result;
  94        u8 buf[7];
  95        u8 val;
  96        struct i2c_msg msg[2];
  97        u8 offs = 0;
  98
  99        if (!dt) {
 100                dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
 101                return -EINVAL;
 102        }
 103
 104        msg[0].addr = client->addr;
 105        msg[0].flags = 0;
 106        msg[0].len = 1;
 107        msg[0].buf = &offs;
 108
 109        msg[1].addr = client->addr;
 110        msg[1].flags = I2C_M_RD;
 111        msg[1].len = sizeof(buf);
 112        msg[1].buf = &buf[0];
 113
 114        result = i2c_transfer(client->adapter, msg, 2);
 115
 116        dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
 117                __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
 118                buf[4], buf[5], buf[6]);
 119
 120        if (result == 2) {
 121                dt->tm_sec = BCD2BIN(buf[0]);
 122                dt->tm_min = BCD2BIN(buf[1]);
 123                val = buf[2] & 0x3f;
 124                dt->tm_hour = BCD2BIN(val);
 125                dt->tm_wday = BCD2BIN(buf[3]) - 1;
 126                dt->tm_mday = BCD2BIN(buf[4]);
 127                val = buf[5] & 0x7f;
 128                dt->tm_mon = BCD2BIN(val) - 1;
 129                dt->tm_year = BCD2BIN(buf[6]);
 130                if (buf[5] & 0x80)
 131                        dt->tm_year += 100;
 132
 133                dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
 134                        "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
 135                        __FUNCTION__, dt->tm_sec, dt->tm_min,
 136                        dt->tm_hour, dt->tm_mday,
 137                        dt->tm_mon, dt->tm_year, dt->tm_wday);
 138
 139                return 0;
 140        }
 141
 142        dev_err(&client->dev, "error reading data! %d\n", result);
 143        return -EIO;
 144}
 145
 146static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
 147{
 148        int result;
 149        u8 buf[8];
 150        u8 val;
 151        struct i2c_msg msg[1];
 152
 153        if (!dt) {
 154                dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
 155                return -EINVAL;
 156        }
 157
 158        dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
 159                "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
 160                dt->tm_sec, dt->tm_min, dt->tm_hour,
 161                dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
 162
 163        buf[0] = 0;             /* reg offset */
 164        buf[1] = BIN2BCD(dt->tm_sec);
 165        buf[2] = BIN2BCD(dt->tm_min);
 166        buf[3] = BIN2BCD(dt->tm_hour);
 167        buf[4] = BIN2BCD(dt->tm_wday + 1);
 168        buf[5] = BIN2BCD(dt->tm_mday);
 169        buf[6] = BIN2BCD(dt->tm_mon + 1);
 170        val = dt->tm_year;
 171        if (val >= 100) {
 172                val -= 100;
 173                buf[6] |= (1 << 7);
 174        }
 175        buf[7] = BIN2BCD(val);
 176
 177        msg[0].addr = client->addr;
 178        msg[0].flags = 0;
 179        msg[0].len = sizeof(buf);
 180        msg[0].buf = &buf[0];
 181
 182        result = i2c_transfer(client->adapter, msg, 1);
 183        if (result == 1)
 184                return 0;
 185
 186        dev_err(&client->dev, "error writing data! %d\n", result);
 187        return -EIO;
 188}
 189
 190static int ds1337_command(struct i2c_client *client, unsigned int cmd,
 191                          void *arg)
 192{
 193        dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
 194
 195        switch (cmd) {
 196        case DS1337_GET_DATE:
 197                return ds1337_get_datetime(client, arg);
 198
 199        case DS1337_SET_DATE:
 200                return ds1337_set_datetime(client, arg);
 201
 202        default:
 203                return -EINVAL;
 204        }
 205}
 206
 207/*
 208 * Public API for access to specific device. Useful for low-level
 209 * RTC access from kernel code.
 210 */
 211int ds1337_do_command(int bus, int cmd, void *arg)
 212{
 213        struct list_head *walk;
 214        struct list_head *tmp;
 215        struct ds1337_data *data;
 216
 217        list_for_each_safe(walk, tmp, &ds1337_clients) {
 218                data = list_entry(walk, struct ds1337_data, list);
 219                if (data->client.adapter->nr == bus)
 220                        return ds1337_command(&data->client, cmd, arg);
 221        }
 222
 223        return -ENODEV;
 224}
 225
 226static int ds1337_attach_adapter(struct i2c_adapter *adapter)
 227{
 228        return i2c_probe(adapter, &addr_data, ds1337_detect);
 229}
 230
 231/*
 232 * The following function does more than just detection. If detection
 233 * succeeds, it also registers the new chip.
 234 */
 235static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
 236{
 237        struct i2c_client *new_client;
 238        struct ds1337_data *data;
 239        int err = 0;
 240        const char *name = "";
 241
 242        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 243                                     I2C_FUNC_I2C))
 244                goto exit;
 245
 246        if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
 247                err = -ENOMEM;
 248                goto exit;
 249        }
 250        INIT_LIST_HEAD(&data->list);
 251
 252        /* The common I2C client data is placed right before the
 253         * DS1337-specific data. 
 254         */
 255        new_client = &data->client;
 256        i2c_set_clientdata(new_client, data);
 257        new_client->addr = address;
 258        new_client->adapter = adapter;
 259        new_client->driver = &ds1337_driver;
 260        new_client->flags = 0;
 261
 262        /*
 263         * Now we do the remaining detection. A negative kind means that
 264         * the driver was loaded with no force parameter (default), so we
 265         * must both detect and identify the chip. A zero kind means that
 266         * the driver was loaded with the force parameter, the detection
 267         * step shall be skipped. A positive kind means that the driver
 268         * was loaded with the force parameter and a given kind of chip is
 269         * requested, so both the detection and the identification steps
 270         * are skipped.
 271         *
 272         * For detection, we read registers that are most likely to cause
 273         * detection failure, i.e. those that have more bits with fixed
 274         * or reserved values.
 275         */
 276
 277        /* Default to an DS1337 if forced */
 278        if (kind == 0)
 279                kind = ds1337;
 280
 281        if (kind < 0) {         /* detection and identification */
 282                u8 data;
 283
 284                /* Check that status register bits 6-2 are zero */
 285                if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||
 286                    (data & 0x7c))
 287                        goto exit_free;
 288
 289                /* Check for a valid day register value */
 290                if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||
 291                    (data == 0) || (data & 0xf8))
 292                        goto exit_free;
 293
 294                /* Check for a valid date register value */
 295                if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||
 296                    (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||
 297                    (data >= 0x32))
 298                        goto exit_free;
 299
 300                /* Check for a valid month register value */
 301                if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||
 302                    (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||
 303                    ((data >= 0x13) && (data <= 0x19)))
 304                        goto exit_free;
 305
 306                /* Check that control register bits 6-5 are zero */
 307                if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||
 308                    (data & 0x60))
 309                        goto exit_free;
 310
 311                kind = ds1337;
 312        }
 313
 314        if (kind == ds1337)
 315                name = "ds1337";
 316
 317        /* We can fill in the remaining client fields */
 318        strlcpy(new_client->name, name, I2C_NAME_SIZE);
 319
 320        /* Tell the I2C layer a new client has arrived */
 321        if ((err = i2c_attach_client(new_client)))
 322                goto exit_free;
 323
 324        /* Initialize the DS1337 chip */
 325        ds1337_init_client(new_client);
 326
 327        /* Add client to local list */
 328        list_add(&data->list, &ds1337_clients);
 329
 330        return 0;
 331
 332exit_free:
 333        kfree(data);
 334exit:
 335        return err;
 336}
 337
 338static void ds1337_init_client(struct i2c_client *client)
 339{
 340        u8 status, control;
 341
 342        /* On some boards, the RTC isn't configured by boot firmware.
 343         * Handle that case by starting/configuring the RTC now.
 344         */
 345        status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
 346        control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
 347
 348        if ((status & 0x80) || (control & 0x80)) {
 349                /* RTC not running */
 350                u8 buf[1+16];   /* First byte is interpreted as address */
 351                struct i2c_msg msg[1];
 352
 353                dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
 354
 355                /* Initialize all, including STATUS and CONTROL to zero */
 356                memset(buf, 0, sizeof(buf));
 357
 358                /* Write valid values in the date/time registers */
 359                buf[1+DS1337_REG_DAY] = 1;
 360                buf[1+DS1337_REG_DATE] = 1;
 361                buf[1+DS1337_REG_MONTH] = 1;
 362
 363                msg[0].addr = client->addr;
 364                msg[0].flags = 0;
 365                msg[0].len = sizeof(buf);
 366                msg[0].buf = &buf[0];
 367
 368                i2c_transfer(client->adapter, msg, 1);
 369        } else {
 370                /* Running: ensure that device is set in 24-hour mode */
 371                s32 val;
 372
 373                val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
 374                if ((val >= 0) && (val & (1 << 6)))
 375                        i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
 376                                                  val & 0x3f);
 377        }
 378}
 379
 380static int ds1337_detach_client(struct i2c_client *client)
 381{
 382        int err;
 383        struct ds1337_data *data = i2c_get_clientdata(client);
 384
 385        if ((err = i2c_detach_client(client)))
 386                return err;
 387
 388        list_del(&data->list);
 389        kfree(data);
 390        return 0;
 391}
 392
 393static int __init ds1337_init(void)
 394{
 395        return i2c_add_driver(&ds1337_driver);
 396}
 397
 398static void __exit ds1337_exit(void)
 399{
 400        i2c_del_driver(&ds1337_driver);
 401}
 402
 403MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 404MODULE_DESCRIPTION("DS1337 RTC driver");
 405MODULE_LICENSE("GPL");
 406
 407EXPORT_SYMBOL_GPL(ds1337_do_command);
 408
 409module_init(ds1337_init);
 410module_exit(ds1337_exit);
 411
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.