[PATCH] RTC subsystem: DS1672 oscillator handling
[pandora-kernel.git] / drivers / rtc / rtc-ds1672.c
1 /*
2  * An rtc/i2c driver for the Dallas DS1672
3  * Copyright 2005 Alessandro Zummo
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/module.h>
11 #include <linux/i2c.h>
12 #include <linux/rtc.h>
13
14 #define DRV_VERSION "0.2"
15
16 /* Addresses to scan: none. This chip cannot be detected. */
17 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
18
19 /* Insmod parameters */
20 I2C_CLIENT_INSMOD;
21
22 /* Registers */
23
24 #define DS1672_REG_CNT_BASE     0
25 #define DS1672_REG_CONTROL      4
26 #define DS1672_REG_CONTROL_EOSC 0x80
27 #define DS1672_REG_TRICKLE      5
28
29
30 /* Prototypes */
31 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
32
33 /*
34  * In the routines that deal directly with the ds1672 hardware, we use
35  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
36  * Epoch is initialized as 2000. Time is set to UTC.
37  */
38 static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
39 {
40         unsigned long time;
41         unsigned char addr = DS1672_REG_CNT_BASE;
42         unsigned char buf[4];
43
44         struct i2c_msg msgs[] = {
45                 { client->addr, 0, 1, &addr },          /* setup read ptr */
46                 { client->addr, I2C_M_RD, 4, buf },     /* read date */
47         };
48
49         /* read date registers */
50         if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
51                 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
52                 return -EIO;
53         }
54
55         dev_dbg(&client->dev,
56                 "%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
57                 __FUNCTION__,
58                 buf[0], buf[1], buf[2], buf[3]);
59
60         time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
61
62         rtc_time_to_tm(time, tm);
63
64         dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
65                 "mday=%d, mon=%d, year=%d, wday=%d\n",
66                 __FUNCTION__,
67                 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         char *state = "enabled";
148         u8 control;
149         int err;
150
151         err = ds1672_get_control(client, &control);
152         if (err)
153                 return err;
154
155         if (control & DS1672_REG_CONTROL_EOSC)
156                 state = "disabled";
157
158         return sprintf(buf, "%s\n", state);
159 }
160
161 static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
162
163 static struct rtc_class_ops ds1672_rtc_ops = {
164         .read_time      = ds1672_rtc_read_time,
165         .set_time       = ds1672_rtc_set_time,
166         .set_mmss       = ds1672_rtc_set_mmss,
167 };
168
169 static int ds1672_attach(struct i2c_adapter *adapter)
170 {
171         dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
172         return i2c_probe(adapter, &addr_data, ds1672_probe);
173 }
174
175 static int ds1672_detach(struct i2c_client *client)
176 {
177         int err;
178         struct rtc_device *rtc = i2c_get_clientdata(client);
179
180         dev_dbg(&client->dev, "%s\n", __FUNCTION__);
181
182         if (rtc)
183                 rtc_device_unregister(rtc);
184
185         if ((err = i2c_detach_client(client)))
186                 return err;
187
188         kfree(client);
189
190         return 0;
191 }
192
193 static struct i2c_driver ds1672_driver = {
194         .driver         = {
195                 .name   = "ds1672",
196         },
197         .id             = I2C_DRIVERID_DS1672,
198         .attach_adapter = &ds1672_attach,
199         .detach_client  = &ds1672_detach,
200 };
201
202 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
203 {
204         int err = 0;
205         u8 control;
206         struct i2c_client *client;
207         struct rtc_device *rtc;
208
209         dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
210
211         if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
212                 err = -ENODEV;
213                 goto exit;
214         }
215
216         if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
217                 err = -ENOMEM;
218                 goto exit;
219         }
220
221         /* I2C client */
222         client->addr = address;
223         client->driver = &ds1672_driver;
224         client->adapter = adapter;
225
226         strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
227
228         /* Inform the i2c layer */
229         if ((err = i2c_attach_client(client)))
230                 goto exit_kfree;
231
232         dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
233
234         rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
235                                 &ds1672_rtc_ops, THIS_MODULE);
236
237         if (IS_ERR(rtc)) {
238                 err = PTR_ERR(rtc);
239                 dev_err(&client->dev,
240                         "unable to register the class device\n");
241                 goto exit_detach;
242         }
243
244         i2c_set_clientdata(client, rtc);
245
246         /* read control register */
247         err = ds1672_get_control(client, &control);
248         if (err) {
249                 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
250                 goto exit_detach;
251         }
252
253         if (control & DS1672_REG_CONTROL_EOSC)
254                 dev_warn(&client->dev, "Oscillator not enabled. "
255                                         "Set time to enable.\n");
256
257         /* Register sysfs hooks */
258         device_create_file(&client->dev, &dev_attr_control);
259
260         return 0;
261
262 exit_detach:
263         i2c_detach_client(client);
264
265 exit_kfree:
266         kfree(client);
267
268 exit:
269         return err;
270 }
271
272 static int __init ds1672_init(void)
273 {
274         return i2c_add_driver(&ds1672_driver);
275 }
276
277 static void __exit ds1672_exit(void)
278 {
279         i2c_del_driver(&ds1672_driver);
280 }
281
282 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
283 MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");
284 MODULE_LICENSE("GPL");
285 MODULE_VERSION(DRV_VERSION);
286
287 module_init(ds1672_init);
288 module_exit(ds1672_exit);