OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [rtc/] [rtc-ds1672.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * An rtc/i2c driver for the Dallas DS1672
3
 * Copyright 2005-06 Tower Technologies
4
 *
5
 * Author: Alessandro Zummo <a.zummo@towertech.it>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/i2c.h>
14
#include <linux/rtc.h>
15
 
16
#define DRV_VERSION "0.3"
17
 
18
/* Addresses to scan: none. This chip cannot be detected. */
19
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
20
 
21
/* Insmod parameters */
22
I2C_CLIENT_INSMOD;
23
 
24
/* Registers */
25
 
26
#define DS1672_REG_CNT_BASE     0
27
#define DS1672_REG_CONTROL      4
28
#define DS1672_REG_TRICKLE      5
29
 
30
#define DS1672_REG_CONTROL_EOSC 0x80
31
 
32
/* Prototypes */
33
static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
34
 
35
/*
36
 * In the routines that deal directly with the ds1672 hardware, we use
37
 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
38
 * Epoch is initialized as 2000. Time is set to UTC.
39
 */
40
static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
41
{
42
        unsigned long time;
43
        unsigned char addr = DS1672_REG_CNT_BASE;
44
        unsigned char buf[4];
45
 
46
        struct i2c_msg msgs[] = {
47
                { client->addr, 0, 1, &addr },           /* setup read ptr */
48
                { client->addr, I2C_M_RD, 4, buf },     /* read date */
49
        };
50
 
51
        /* read date registers */
52
        if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
53
                dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
54
                return -EIO;
55
        }
56
 
57
        dev_dbg(&client->dev,
58
                "%s: raw read data - counters=%02x,%02x,%02x,%02x\n",
59
                __FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
60
 
61
        time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
62
 
63
        rtc_time_to_tm(time, tm);
64
 
65
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
66
                "mday=%d, mon=%d, year=%d, wday=%d\n",
67
                __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
68
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
69
 
70
        return 0;
71
}
72
 
73
static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
74
{
75
        int xfer;
76
        unsigned char buf[6];
77
 
78
        buf[0] = DS1672_REG_CNT_BASE;
79
        buf[1] = secs & 0x000000FF;
80
        buf[2] = (secs & 0x0000FF00) >> 8;
81
        buf[3] = (secs & 0x00FF0000) >> 16;
82
        buf[4] = (secs & 0xFF000000) >> 24;
83
        buf[5] = 0;      /* set control reg to enable counting */
84
 
85
        xfer = i2c_master_send(client, buf, 6);
86
        if (xfer != 6) {
87
                dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
88
                return -EIO;
89
        }
90
 
91
        return 0;
92
}
93
 
94
static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm)
95
{
96
        unsigned long secs;
97
 
98
        dev_dbg(&client->dev,
99
                "%s: secs=%d, mins=%d, hours=%d, "
100
                "mday=%d, mon=%d, year=%d, wday=%d\n",
101
                __FUNCTION__,
102
                tm->tm_sec, tm->tm_min, tm->tm_hour,
103
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
104
 
105
        rtc_tm_to_time(tm, &secs);
106
 
107
        return ds1672_set_mmss(client, secs);
108
}
109
 
110
static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm)
111
{
112
        return ds1672_get_datetime(to_i2c_client(dev), tm);
113
}
114
 
115
static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm)
116
{
117
        return ds1672_set_datetime(to_i2c_client(dev), tm);
118
}
119
 
120
static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
121
{
122
        return ds1672_set_mmss(to_i2c_client(dev), secs);
123
}
124
 
125
static int ds1672_get_control(struct i2c_client *client, u8 *status)
126
{
127
        unsigned char addr = DS1672_REG_CONTROL;
128
 
129
        struct i2c_msg msgs[] = {
130
                { client->addr, 0, 1, &addr },           /* setup read ptr */
131
                { client->addr, I2C_M_RD, 1, status },  /* read control */
132
        };
133
 
134
        /* read control register */
135
        if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
136
                dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
137
                return -EIO;
138
        }
139
 
140
        return 0;
141
}
142
 
143
/* following are the sysfs callback functions */
144
static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
145
{
146
        struct i2c_client *client = to_i2c_client(dev);
147
        u8 control;
148
        int err;
149
 
150
        err = ds1672_get_control(client, &control);
151
        if (err)
152
                return err;
153
 
154
        return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
155
                                        ? "disabled" : "enabled");
156
}
157
static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
158
 
159
static const struct rtc_class_ops ds1672_rtc_ops = {
160
        .read_time      = ds1672_rtc_read_time,
161
        .set_time       = ds1672_rtc_set_time,
162
        .set_mmss       = ds1672_rtc_set_mmss,
163
};
164
 
165
static int ds1672_attach(struct i2c_adapter *adapter)
166
{
167
        return i2c_probe(adapter, &addr_data, ds1672_probe);
168
}
169
 
170
static int ds1672_detach(struct i2c_client *client)
171
{
172
        int err;
173
        struct rtc_device *rtc = i2c_get_clientdata(client);
174
 
175
        if (rtc)
176
                rtc_device_unregister(rtc);
177
 
178
        if ((err = i2c_detach_client(client)))
179
                return err;
180
 
181
        kfree(client);
182
 
183
        return 0;
184
}
185
 
186
static struct i2c_driver ds1672_driver = {
187
        .driver         = {
188
                .name   = "ds1672",
189
        },
190
        .id             = I2C_DRIVERID_DS1672,
191
        .attach_adapter = &ds1672_attach,
192
        .detach_client  = &ds1672_detach,
193
};
194
 
195
static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
196
{
197
        int err = 0;
198
        u8 control;
199
        struct i2c_client *client;
200
        struct rtc_device *rtc;
201
 
202
        dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
203
 
204
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
205
                err = -ENODEV;
206
                goto exit;
207
        }
208
 
209
        if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
210
                err = -ENOMEM;
211
                goto exit;
212
        }
213
 
214
        /* I2C client */
215
        client->addr = address;
216
        client->driver = &ds1672_driver;
217
        client->adapter = adapter;
218
 
219
        strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
220
 
221
        /* Inform the i2c layer */
222
        if ((err = i2c_attach_client(client)))
223
                goto exit_kfree;
224
 
225
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
226
 
227
        rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
228
                                &ds1672_rtc_ops, THIS_MODULE);
229
 
230
        if (IS_ERR(rtc)) {
231
                err = PTR_ERR(rtc);
232
                goto exit_detach;
233
        }
234
 
235
        i2c_set_clientdata(client, rtc);
236
 
237
        /* read control register */
238
        err = ds1672_get_control(client, &control);
239
        if (err)
240
                goto exit_devreg;
241
 
242
        if (control & DS1672_REG_CONTROL_EOSC)
243
                dev_warn(&client->dev, "Oscillator not enabled. "
244
                                        "Set time to enable.\n");
245
 
246
        /* Register sysfs hooks */
247
        err = device_create_file(&client->dev, &dev_attr_control);
248
        if (err)
249
                goto exit_devreg;
250
 
251
        return 0;
252
 
253
exit_devreg:
254
        rtc_device_unregister(rtc);
255
 
256
exit_detach:
257
        i2c_detach_client(client);
258
 
259
exit_kfree:
260
        kfree(client);
261
 
262
exit:
263
        return err;
264
}
265
 
266
static int __init ds1672_init(void)
267
{
268
        return i2c_add_driver(&ds1672_driver);
269
}
270
 
271
static void __exit ds1672_exit(void)
272
{
273
        i2c_del_driver(&ds1672_driver);
274
}
275
 
276
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
277
MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");
278
MODULE_LICENSE("GPL");
279
MODULE_VERSION(DRV_VERSION);
280
 
281
module_init(ds1672_init);
282
module_exit(ds1672_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.