aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips
diff options
context:
space:
mode:
authorAlessandro Zummo <a.zummo@towertech.it>2006-03-27 04:16:37 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:51 -0500
commit6fc7f10cee28c7fa190920fefda8c696d5bf3074 (patch)
tree549dd6be7fb058bf404deae6f72cd01f9ec177b3 /drivers/i2c/chips
parent0c86edc0d4970649f39748c4ce4f2895f728468f (diff)
[PATCH] RTC subsystem: I2C cleanup
This patch, completely optional, removes from drivers/i2c/chips all the drivers that are implemented in the new RTC subsystem. It should be noted that none of the current driver is actually integrated, i.e. usable without further patches. Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/i2c/chips')
-rw-r--r--drivers/i2c/chips/Kconfig18
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/rtc8564.c385
-rw-r--r--drivers/i2c/chips/rtc8564.h78
-rw-r--r--drivers/i2c/chips/x1205.c698
5 files changed, 0 insertions, 1181 deletions
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f9fae28f5612..7aa5c38f0855 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -65,15 +65,6 @@ config SENSORS_PCF8591
65 This driver can also be built as a module. If so, the module 65 This driver can also be built as a module. If so, the module
66 will be called pcf8591. 66 will be called pcf8591.
67 67
68config SENSORS_RTC8564
69 tristate "Epson 8564 RTC chip"
70 depends on I2C && EXPERIMENTAL
71 help
72 If you say yes here you get support for the Epson 8564 RTC chip.
73
74 This driver can also be built as a module. If so, the module
75 will be called i2c-rtc8564.
76
77config ISP1301_OMAP 68config ISP1301_OMAP
78 tristate "Philips ISP1301 with OMAP OTG" 69 tristate "Philips ISP1301 with OMAP OTG"
79 depends on I2C && ARCH_OMAP_OTG 70 depends on I2C && ARCH_OMAP_OTG
@@ -126,13 +117,4 @@ config SENSORS_MAX6875
126 This driver can also be built as a module. If so, the module 117 This driver can also be built as a module. If so, the module
127 will be called max6875. 118 will be called max6875.
128 119
129config RTC_X1205_I2C
130 tristate "Xicor X1205 RTC chip"
131 depends on I2C && EXPERIMENTAL
132 help
133 If you say yes here you get support for the Xicor X1205 RTC chip.
134
135 This driver can also be built as a module. If so, the module
136 will be called x1205.
137
138endmenu 120endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 46178b57b1f1..779868ef2e26 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
10obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o 10obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
11obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o 11obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
12obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o 12obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
13obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
14obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o 13obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
15obj-$(CONFIG_TPS65010) += tps65010.o 14obj-$(CONFIG_TPS65010) += tps65010.o
16obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
17 15
18ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) 16ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
19EXTRA_CFLAGS += -DDEBUG 17EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
deleted file mode 100644
index 0d8699b3f488..000000000000
--- a/drivers/i2c/chips/rtc8564.c
+++ /dev/null
@@ -1,385 +0,0 @@
1/*
2 * linux/drivers/i2c/chips/rtc8564.c
3 *
4 * Copyright (C) 2002-2004 Stefan Eletzhofer
5 *
6 * based on linux/drivers/acron/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 system3's EPSON RTC 8564 chip
14 */
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/bcd.h>
18#include <linux/i2c.h>
19#include <linux/slab.h>
20#include <linux/string.h>
21#include <linux/rtc.h> /* get the user-level API */
22#include <linux/init.h>
23
24#include "rtc8564.h"
25
26#ifdef DEBUG
27# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
28#else
29# define _DBG(x, fmt, args...) do { } while(0);
30#endif
31
32#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
33 "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
34 (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
35 (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
36
37struct rtc8564_data {
38 struct i2c_client client;
39 u16 ctrl;
40};
41
42static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
43{
44 struct rtc8564_data *data = i2c_get_clientdata(client);
45 return data->ctrl & 0xff;
46}
47static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
48{
49 struct rtc8564_data *data = i2c_get_clientdata(client);
50 return (data->ctrl & 0xff00) >> 8;
51}
52
53#define CTRL1(c) _rtc8564_ctrl1(c)
54#define CTRL2(c) _rtc8564_ctrl2(c)
55
56static int debug;
57module_param(debug, int, S_IRUGO | S_IWUSR);
58
59static struct i2c_driver rtc8564_driver;
60
61static unsigned short ignore[] = { I2C_CLIENT_END };
62static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
63
64static struct i2c_client_address_data addr_data = {
65 .normal_i2c = normal_addr,
66 .probe = ignore,
67 .ignore = ignore,
68};
69
70static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
71static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
72
73static int rtc8564_read(struct i2c_client *client, unsigned char adr,
74 unsigned char *buf, unsigned char len)
75{
76 int ret = -EIO;
77 unsigned char addr[1] = { adr };
78 struct i2c_msg msgs[2] = {
79 {client->addr, 0, 1, addr},
80 {client->addr, I2C_M_RD, len, buf}
81 };
82
83 _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
84
85 if (!buf) {
86 ret = -EINVAL;
87 goto done;
88 }
89
90 ret = i2c_transfer(client->adapter, msgs, 2);
91 if (ret == 2) {
92 ret = 0;
93 }
94
95done:
96 return ret;
97}
98
99static int rtc8564_write(struct i2c_client *client, unsigned char adr,
100 unsigned char *data, unsigned char len)
101{
102 int ret = 0;
103 unsigned char _data[16];
104 struct i2c_msg wr;
105 int i;
106
107 if (!data || len > 15) {
108 ret = -EINVAL;
109 goto done;
110 }
111
112 _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
113
114 _data[0] = adr;
115 for (i = 0; i < len; i++) {
116 _data[i + 1] = data[i];
117 _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
118 }
119
120 wr.addr = client->addr;
121 wr.flags = 0;
122 wr.len = len + 1;
123 wr.buf = _data;
124
125 ret = i2c_transfer(client->adapter, &wr, 1);
126 if (ret == 1) {
127 ret = 0;
128 }
129
130done:
131 return ret;
132}
133
134static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
135{
136 int ret;
137 struct i2c_client *new_client;
138 struct rtc8564_data *d;
139 unsigned char data[10];
140 unsigned char ad[1] = { 0 };
141 struct i2c_msg ctrl_wr[1] = {
142 {addr, 0, 2, data}
143 };
144 struct i2c_msg ctrl_rd[2] = {
145 {addr, 0, 1, ad},
146 {addr, I2C_M_RD, 2, data}
147 };
148
149 d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
150 if (!d) {
151 ret = -ENOMEM;
152 goto done;
153 }
154 new_client = &d->client;
155
156 strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
157 i2c_set_clientdata(new_client, d);
158 new_client->addr = addr;
159 new_client->adapter = adap;
160 new_client->driver = &rtc8564_driver;
161
162 _DBG(1, "client=%p", new_client);
163
164 /* init ctrl1 reg */
165 data[0] = 0;
166 data[1] = 0;
167 ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
168 if (ret != 1) {
169 printk(KERN_INFO "rtc8564: cant init ctrl1\n");
170 ret = -ENODEV;
171 goto done;
172 }
173
174 /* read back ctrl1 and ctrl2 */
175 ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
176 if (ret != 2) {
177 printk(KERN_INFO "rtc8564: cant read ctrl\n");
178 ret = -ENODEV;
179 goto done;
180 }
181
182 d->ctrl = data[0] | (data[1] << 8);
183
184 _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
185 data[0], data[1]);
186
187 ret = i2c_attach_client(new_client);
188done:
189 if (ret) {
190 kfree(d);
191 }
192 return ret;
193}
194
195static int rtc8564_probe(struct i2c_adapter *adap)
196{
197 return i2c_probe(adap, &addr_data, rtc8564_attach);
198}
199
200static int rtc8564_detach(struct i2c_client *client)
201{
202 i2c_detach_client(client);
203 kfree(i2c_get_clientdata(client));
204 return 0;
205}
206
207static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
208{
209 int ret = -EIO;
210 unsigned char buf[15];
211
212 _DBG(1, "client=%p, dt=%p", client, dt);
213
214 if (!dt)
215 return -EINVAL;
216
217 memset(buf, 0, sizeof(buf));
218
219 ret = rtc8564_read(client, 0, buf, 15);
220 if (ret)
221 return ret;
222
223 /* century stored in minute alarm reg */
224 dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
225 dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
226 dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
227 dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
228 dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
229
230 dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
231 dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
232 dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
233 dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
234
235 _DBGRTCTM(2, *dt);
236
237 return 0;
238}
239
240static int
241rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
242{
243 int ret, len = 5;
244 unsigned char buf[15];
245
246 _DBG(1, "client=%p, dt=%p", client, dt);
247
248 if (!dt)
249 return -EINVAL;
250
251 _DBGRTCTM(2, *dt);
252
253 buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
254 buf[RTC8564_REG_CTRL2] = CTRL2(client);
255 buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
256 buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
257 buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
258
259 if (datetoo) {
260 len += 5;
261 buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
262 buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
263 buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
264 /* century stored in minute alarm reg */
265 buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
266 buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
267 }
268
269 ret = rtc8564_write(client, 0, buf, len);
270 if (ret) {
271 _DBG(1, "error writing data! %d", ret);
272 }
273
274 buf[RTC8564_REG_CTRL1] = CTRL1(client);
275 ret = rtc8564_write(client, 0, buf, 1);
276 if (ret) {
277 _DBG(1, "error writing data! %d", ret);
278 }
279
280 return ret;
281}
282
283static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
284{
285 struct rtc8564_data *data = i2c_get_clientdata(client);
286
287 if (!ctrl)
288 return -1;
289
290 *ctrl = data->ctrl;
291 return 0;
292}
293
294static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
295{
296 struct rtc8564_data *data = i2c_get_clientdata(client);
297 unsigned char buf[2];
298
299 if (!ctrl)
300 return -1;
301
302 buf[0] = *ctrl & 0xff;
303 buf[1] = (*ctrl & 0xff00) >> 8;
304 data->ctrl = *ctrl;
305
306 return rtc8564_write(client, 0, buf, 2);
307}
308
309static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
310{
311
312 if (!mem)
313 return -EINVAL;
314
315 return rtc8564_read(client, mem->loc, mem->data, mem->nr);
316}
317
318static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
319{
320
321 if (!mem)
322 return -EINVAL;
323
324 return rtc8564_write(client, mem->loc, mem->data, mem->nr);
325}
326
327static int
328rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
329{
330
331 _DBG(1, "cmd=%d", cmd);
332
333 switch (cmd) {
334 case RTC_GETDATETIME:
335 return rtc8564_get_datetime(client, arg);
336
337 case RTC_SETTIME:
338 return rtc8564_set_datetime(client, arg, 0);
339
340 case RTC_SETDATETIME:
341 return rtc8564_set_datetime(client, arg, 1);
342
343 case RTC_GETCTRL:
344 return rtc8564_get_ctrl(client, arg);
345
346 case RTC_SETCTRL:
347 return rtc8564_set_ctrl(client, arg);
348
349 case MEM_READ:
350 return rtc8564_read_mem(client, arg);
351
352 case MEM_WRITE:
353 return rtc8564_write_mem(client, arg);
354
355 default:
356 return -EINVAL;
357 }
358}
359
360static struct i2c_driver rtc8564_driver = {
361 .driver = {
362 .name = "RTC8564",
363 },
364 .id = I2C_DRIVERID_RTC8564,
365 .attach_adapter = rtc8564_probe,
366 .detach_client = rtc8564_detach,
367 .command = rtc8564_command
368};
369
370static __init int rtc8564_init(void)
371{
372 return i2c_add_driver(&rtc8564_driver);
373}
374
375static __exit void rtc8564_exit(void)
376{
377 i2c_del_driver(&rtc8564_driver);
378}
379
380MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
381MODULE_DESCRIPTION("EPSON RTC8564 Driver");
382MODULE_LICENSE("GPL");
383
384module_init(rtc8564_init);
385module_exit(rtc8564_exit);
diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h
deleted file mode 100644
index e5342d10b8fa..000000000000
--- a/drivers/i2c/chips/rtc8564.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * linux/drivers/i2c/chips/rtc8564.h
3 *
4 * Copyright (C) 2002-2004 Stefan Eletzhofer
5 *
6 * based on linux/drivers/acron/char/pcf8583.h
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 */
13struct rtc_tm {
14 unsigned char secs;
15 unsigned char mins;
16 unsigned char hours;
17 unsigned char mday;
18 unsigned char mon;
19 unsigned short year; /* xxxx 4 digits :) */
20 unsigned char wday;
21 unsigned char vl;
22};
23
24struct mem {
25 unsigned int loc;
26 unsigned int nr;
27 unsigned char *data;
28};
29
30#define RTC_GETDATETIME 0
31#define RTC_SETTIME 1
32#define RTC_SETDATETIME 2
33#define RTC_GETCTRL 3
34#define RTC_SETCTRL 4
35#define MEM_READ 5
36#define MEM_WRITE 6
37
38#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */
39#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */
40#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */
41#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */
42#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */
43#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */
44#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */
45#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */
46#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */
47#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */
48#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */
49#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */
50#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */
51#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */
52#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */
53#define RTC8564_REG_TIMER 0xf /* 8 bit binary */
54
55/* Control reg */
56#define RTC8564_CTRL1_TEST1 (1<<3)
57#define RTC8564_CTRL1_STOP (1<<5)
58#define RTC8564_CTRL1_TEST2 (1<<7)
59
60#define RTC8564_CTRL2_TIE (1<<0)
61#define RTC8564_CTRL2_AIE (1<<1)
62#define RTC8564_CTRL2_TF (1<<2)
63#define RTC8564_CTRL2_AF (1<<3)
64#define RTC8564_CTRL2_TI_TP (1<<4)
65
66/* CLKOUT frequencies */
67#define RTC8564_FD_32768HZ (0x0)
68#define RTC8564_FD_1024HZ (0x1)
69#define RTC8564_FD_32 (0x2)
70#define RTC8564_FD_1HZ (0x3)
71
72/* Timer CTRL */
73#define RTC8564_TD_4096HZ (0x0)
74#define RTC8564_TD_64HZ (0x1)
75#define RTC8564_TD_1HZ (0x2)
76#define RTC8564_TD_1_60HZ (0x3)
77
78#define I2C_DRIVERID_RTC8564 0xf000
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
deleted file mode 100644
index 245fffa92dbd..000000000000
--- a/drivers/i2c/chips/x1205.c
+++ /dev/null
@@ -1,698 +0,0 @@
1/*
2 * x1205.c - An i2c driver for the Xicor X1205 RTC
3 * Copyright 2004 Karen Spearel
4 * Copyright 2005 Alessandro Zummo
5 *
6 * please send all reports to:
7 * kas11 at tampabay dot rr dot com
8 * a dot zummo at towertech dot it
9 *
10 * based on the other drivers in this same directory.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/i2c.h>
22#include <linux/string.h>
23#include <linux/bcd.h>
24#include <linux/rtc.h>
25#include <linux/list.h>
26
27#include <linux/x1205.h>
28
29#define DRV_VERSION "0.9.9"
30
31/* Addresses to scan: none. This chip is located at
32 * 0x6f and uses a two bytes register addressing.
33 * Two bytes need to be written to read a single register,
34 * while most other chips just require one and take the second
35 * one as the data to be written. To prevent corrupting
36 * unknown chips, the user must explicitely set the probe parameter.
37 */
38
39static unsigned short normal_i2c[] = { I2C_CLIENT_END };
40
41/* Insmod parameters */
42I2C_CLIENT_INSMOD;
43I2C_CLIENT_MODULE_PARM(hctosys,
44 "Set the system time from the hardware clock upon initialization");
45
46/* offsets into CCR area */
47
48#define CCR_SEC 0
49#define CCR_MIN 1
50#define CCR_HOUR 2
51#define CCR_MDAY 3
52#define CCR_MONTH 4
53#define CCR_YEAR 5
54#define CCR_WDAY 6
55#define CCR_Y2K 7
56
57#define X1205_REG_SR 0x3F /* status register */
58#define X1205_REG_Y2K 0x37
59#define X1205_REG_DW 0x36
60#define X1205_REG_YR 0x35
61#define X1205_REG_MO 0x34
62#define X1205_REG_DT 0x33
63#define X1205_REG_HR 0x32
64#define X1205_REG_MN 0x31
65#define X1205_REG_SC 0x30
66#define X1205_REG_DTR 0x13
67#define X1205_REG_ATR 0x12
68#define X1205_REG_INT 0x11
69#define X1205_REG_0 0x10
70#define X1205_REG_Y2K1 0x0F
71#define X1205_REG_DWA1 0x0E
72#define X1205_REG_YRA1 0x0D
73#define X1205_REG_MOA1 0x0C
74#define X1205_REG_DTA1 0x0B
75#define X1205_REG_HRA1 0x0A
76#define X1205_REG_MNA1 0x09
77#define X1205_REG_SCA1 0x08
78#define X1205_REG_Y2K0 0x07
79#define X1205_REG_DWA0 0x06
80#define X1205_REG_YRA0 0x05
81#define X1205_REG_MOA0 0x04
82#define X1205_REG_DTA0 0x03
83#define X1205_REG_HRA0 0x02
84#define X1205_REG_MNA0 0x01
85#define X1205_REG_SCA0 0x00
86
87#define X1205_CCR_BASE 0x30 /* Base address of CCR */
88#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
89
90#define X1205_SR_RTCF 0x01 /* Clock failure */
91#define X1205_SR_WEL 0x02 /* Write Enable Latch */
92#define X1205_SR_RWEL 0x04 /* Register Write Enable */
93
94#define X1205_DTR_DTR0 0x01
95#define X1205_DTR_DTR1 0x02
96#define X1205_DTR_DTR2 0x04
97
98#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
99
100/* Prototypes */
101static int x1205_attach(struct i2c_adapter *adapter);
102static int x1205_detach(struct i2c_client *client);
103static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
104static int x1205_command(struct i2c_client *client, unsigned int cmd,
105 void *arg);
106
107static struct i2c_driver x1205_driver = {
108 .driver = {
109 .name = "x1205",
110 },
111 .attach_adapter = &x1205_attach,
112 .detach_client = &x1205_detach,
113};
114
115struct x1205_data {
116 struct i2c_client client;
117 struct list_head list;
118 unsigned int epoch;
119};
120
121static const unsigned char days_in_mo[] =
122 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
123
124static LIST_HEAD(x1205_clients);
125
126/* Workaround until the I2C subsytem will allow to send
127 * commands to a specific client. This function will send the command
128 * to the first client.
129 */
130int x1205_do_command(unsigned int cmd, void *arg)
131{
132 struct list_head *walk;
133 struct list_head *tmp;
134 struct x1205_data *data;
135
136 list_for_each_safe(walk, tmp, &x1205_clients) {
137 data = list_entry(walk, struct x1205_data, list);
138 return x1205_command(&data->client, cmd, arg);
139 }
140
141 return -ENODEV;
142}
143
144#define is_leap(year) \
145 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
146
147/* make sure the rtc_time values are in bounds */
148static int x1205_validate_tm(struct rtc_time *tm)
149{
150 int year = tm->tm_year + 1900;
151
152 if ((tm->tm_year < 70) || (tm->tm_year > 255))
153 return -EINVAL;
154
155 if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
156 return -EINVAL;
157
158 if (tm->tm_mday > days_in_mo[tm->tm_mon]
159 + ((tm->tm_mon == 1) && is_leap(year)))
160 return -EINVAL;
161
162 if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
163 return -EINVAL;
164
165 return 0;
166}
167
168/*
169 * In the routines that deal directly with the x1205 hardware, we use
170 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
171 * Epoch is initialized as 2000. Time is set to UTC.
172 */
173static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
174 u8 reg_base)
175{
176 unsigned char dt_addr[2] = { 0, reg_base };
177 static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
178
179 unsigned char buf[8], sr;
180
181 struct i2c_msg msgs[] = {
182 { client->addr, 0, 2, sr_addr }, /* setup read ptr */
183 { client->addr, I2C_M_RD, 1, &sr }, /* read status */
184 { client->addr, 0, 2, dt_addr }, /* setup read ptr */
185 { client->addr, I2C_M_RD, 8, buf }, /* read date */
186 };
187
188 struct x1205_data *data = i2c_get_clientdata(client);
189
190 /* read status register */
191 if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
192 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
193 return -EIO;
194 }
195
196 /* check for battery failure */
197 if (sr & X1205_SR_RTCF) {
198 dev_warn(&client->dev,
199 "Clock had a power failure, you must set the date.\n");
200 return -EINVAL;
201 }
202
203 /* read date registers */
204 if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
205 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
206 return -EIO;
207 }
208
209 dev_dbg(&client->dev,
210 "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
211 "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
212 __FUNCTION__,
213 buf[0], buf[1], buf[2], buf[3],
214 buf[4], buf[5], buf[6], buf[7]);
215
216 tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
217 tm->tm_min = BCD2BIN(buf[CCR_MIN]);
218 tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
219 tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
220 tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
221 data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
222 tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
223 tm->tm_wday = buf[CCR_WDAY];
224
225 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
226 "mday=%d, mon=%d, year=%d, wday=%d\n",
227 __FUNCTION__,
228 tm->tm_sec, tm->tm_min, tm->tm_hour,
229 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
230
231 return 0;
232}
233
234static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
235 int datetoo, u8 reg_base)
236{
237 int i, err, xfer;
238
239 unsigned char buf[8];
240
241 static const unsigned char wel[3] = { 0, X1205_REG_SR,
242 X1205_SR_WEL };
243
244 static const unsigned char rwel[3] = { 0, X1205_REG_SR,
245 X1205_SR_WEL | X1205_SR_RWEL };
246
247 static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
248
249 struct x1205_data *data = i2c_get_clientdata(client);
250
251 /* check if all values in the tm struct are correct */
252 if ((err = x1205_validate_tm(tm)) < 0)
253 return err;
254
255 dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
256 "mday=%d, mon=%d, year=%d, wday=%d\n",
257 __FUNCTION__,
258 tm->tm_sec, tm->tm_min, tm->tm_hour,
259 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
260
261 buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
262 buf[CCR_MIN] = BIN2BCD(tm->tm_min);
263
264 /* set hour and 24hr bit */
265 buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
266
267 /* should we also set the date? */
268 if (datetoo) {
269 buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
270
271 /* month, 0 - 11 */
272 buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
273
274 /* year, since 1900 */
275 buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
276 buf[CCR_WDAY] = tm->tm_wday & 0x07;
277 buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
278 }
279
280 /* this sequence is required to unlock the chip */
281 xfer = i2c_master_send(client, wel, 3);
282 if (xfer != 3) {
283 dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
284 return -EIO;
285 }
286
287 xfer = i2c_master_send(client, rwel, 3);
288 if (xfer != 3) {
289 dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
290 return -EIO;
291 }
292
293 /* write register's data */
294 for (i = 0; i < (datetoo ? 8 : 3); i++) {
295 unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
296
297 xfer = i2c_master_send(client, rdata, 3);
298 if (xfer != 3) {
299 dev_err(&client->dev,
300 "%s: xfer=%d addr=%02x, data=%02x\n",
301 __FUNCTION__,
302 xfer, rdata[1], rdata[2]);
303 return -EIO;
304 }
305 };
306
307 /* disable further writes */
308 xfer = i2c_master_send(client, diswe, 3);
309 if (xfer != 3) {
310 dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
311 return -EIO;
312 }
313
314 return 0;
315}
316
317static int x1205_get_dtrim(struct i2c_client *client, int *trim)
318{
319 unsigned char dtr;
320 static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
321
322 struct i2c_msg msgs[] = {
323 { client->addr, 0, 2, dtr_addr }, /* setup read ptr */
324 { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
325 };
326
327 /* read dtr register */
328 if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
329 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
330 return -EIO;
331 }
332
333 dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
334
335 *trim = 0;
336
337 if (dtr & X1205_DTR_DTR0)
338 *trim += 20;
339
340 if (dtr & X1205_DTR_DTR1)
341 *trim += 10;
342
343 if (dtr & X1205_DTR_DTR2)
344 *trim = -*trim;
345
346 return 0;
347}
348
349static int x1205_get_atrim(struct i2c_client *client, int *trim)
350{
351 s8 atr;
352 static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
353
354 struct i2c_msg msgs[] = {
355 { client->addr, 0, 2, atr_addr }, /* setup read ptr */
356 { client->addr, I2C_M_RD, 1, &atr }, /* read atr */
357 };
358
359 /* read atr register */
360 if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
361 dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
362 return -EIO;
363 }
364
365 dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
366
367 /* atr is a two's complement value on 6 bits,
368 * perform sign extension. The formula is
369 * Catr = (atr * 0.25pF) + 11.00pF.
370 */
371 if (atr & 0x20)
372 atr |= 0xC0;
373
374 dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
375
376 *trim = (atr * 250) + 11000;
377
378 dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
379
380 return 0;
381}
382
383static int x1205_hctosys(struct i2c_client *client)
384{
385 int err;
386
387 struct rtc_time tm;
388 struct timespec tv;
389
390 err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
391
392 if (err) {
393 dev_err(&client->dev,
394 "Unable to set the system clock\n");
395 return err;
396 }
397
398 /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
399 * whether it stores the most close value or the value with partial
400 * seconds truncated. However, it is important that we use it to store
401 * the truncated value. This is because otherwise it is necessary,
402 * in an rtc sync function, to read both xtime.tv_sec and
403 * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
404 * of >32bits is not possible. So storing the most close value would
405 * slow down the sync API. So here we have the truncated value and
406 * the best guess is to add 0.5s.
407 */
408
409 tv.tv_nsec = NSEC_PER_SEC >> 1;
410
411 /* WARNING: this is not the C library 'mktime' call, it is a built in
412 * inline function from include/linux/time.h. It expects (requires)
413 * the month to be in the range 1-12
414 */
415
416 tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
417 tm.tm_mday, tm.tm_hour,
418 tm.tm_min, tm.tm_sec);
419
420 do_settimeofday(&tv);
421
422 dev_info(&client->dev,
423 "setting the system clock to %d-%d-%d %d:%d:%d\n",
424 tm.tm_year + 1900, tm.tm_mon + 1,
425 tm.tm_mday, tm.tm_hour, tm.tm_min,
426 tm.tm_sec);
427
428 return 0;
429}
430
431struct x1205_limit
432{
433 unsigned char reg;
434 unsigned char mask;
435 unsigned char min;
436 unsigned char max;
437};
438
439static int x1205_validate_client(struct i2c_client *client)
440{
441 int i, xfer;
442
443 /* Probe array. We will read the register at the specified
444 * address and check if the given bits are zero.
445 */
446 static const unsigned char probe_zero_pattern[] = {
447 /* register, mask */
448 X1205_REG_SR, 0x18,
449 X1205_REG_DTR, 0xF8,
450 X1205_REG_ATR, 0xC0,
451 X1205_REG_INT, 0x18,
452 X1205_REG_0, 0xFF,
453 };
454
455 static const struct x1205_limit probe_limits_pattern[] = {
456 /* register, mask, min, max */
457 { X1205_REG_Y2K, 0xFF, 19, 20 },
458 { X1205_REG_DW, 0xFF, 0, 6 },
459 { X1205_REG_YR, 0xFF, 0, 99 },
460 { X1205_REG_MO, 0xFF, 0, 12 },
461 { X1205_REG_DT, 0xFF, 0, 31 },
462 { X1205_REG_HR, 0x7F, 0, 23 },
463 { X1205_REG_MN, 0xFF, 0, 59 },
464 { X1205_REG_SC, 0xFF, 0, 59 },
465 { X1205_REG_Y2K1, 0xFF, 19, 20 },
466 { X1205_REG_Y2K0, 0xFF, 19, 20 },
467 };
468
469 /* check that registers have bits a 0 where expected */
470 for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
471 unsigned char buf;
472
473 unsigned char addr[2] = { 0, probe_zero_pattern[i] };
474
475 struct i2c_msg msgs[2] = {
476 { client->addr, 0, 2, addr },
477 { client->addr, I2C_M_RD, 1, &buf },
478 };
479
480 xfer = i2c_transfer(client->adapter, msgs, 2);
481 if (xfer != 2) {
482 dev_err(&client->adapter->dev,
483 "%s: could not read register %x\n",
484 __FUNCTION__, addr[1]);
485
486 return -EIO;
487 }
488
489 if ((buf & probe_zero_pattern[i+1]) != 0) {
490 dev_err(&client->adapter->dev,
491 "%s: register=%02x, zero pattern=%d, value=%x\n",
492 __FUNCTION__, addr[1], i, buf);
493
494 return -ENODEV;
495 }
496 }
497
498 /* check limits (only registers with bcd values) */
499 for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
500 unsigned char reg, value;
501
502 unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
503
504 struct i2c_msg msgs[2] = {
505 { client->addr, 0, 2, addr },
506 { client->addr, I2C_M_RD, 1, &reg },
507 };
508
509 xfer = i2c_transfer(client->adapter, msgs, 2);
510
511 if (xfer != 2) {
512 dev_err(&client->adapter->dev,
513 "%s: could not read register %x\n",
514 __FUNCTION__, addr[1]);
515
516 return -EIO;
517 }
518
519 value = BCD2BIN(reg & probe_limits_pattern[i].mask);
520
521 if (value > probe_limits_pattern[i].max ||
522 value < probe_limits_pattern[i].min) {
523 dev_dbg(&client->adapter->dev,
524 "%s: register=%x, lim pattern=%d, value=%d\n",
525 __FUNCTION__, addr[1], i, value);
526
527 return -ENODEV;
528 }
529 }
530
531 return 0;
532}
533
534static int x1205_attach(struct i2c_adapter *adapter)
535{
536 dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
537
538 return i2c_probe(adapter, &addr_data, x1205_probe);
539}
540
541int x1205_direct_attach(int adapter_id,
542 struct i2c_client_address_data *address_data)
543{
544 int err;
545 struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
546
547 if (adapter) {
548 err = i2c_probe(adapter,
549 address_data, x1205_probe);
550
551 i2c_put_adapter(adapter);
552
553 return err;
554 }
555
556 return -ENODEV;
557}
558
559static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
560{
561 struct i2c_client *client;
562 struct x1205_data *data;
563
564 int err = 0;
565
566 dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
567
568 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
569 err = -ENODEV;
570 goto exit;
571 }
572
573 if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
574 err = -ENOMEM;
575 goto exit;
576 }
577
578 /* Initialize our structures */
579 data->epoch = 2000;
580
581 client = &data->client;
582 client->addr = address;
583 client->driver = &x1205_driver;
584 client->adapter = adapter;
585
586 strlcpy(client->name, "x1205", I2C_NAME_SIZE);
587
588 i2c_set_clientdata(client, data);
589
590 /* Verify the chip is really an X1205 */
591 if (kind < 0) {
592 if (x1205_validate_client(client) < 0) {
593 err = -ENODEV;
594 goto exit_kfree;
595 }
596 }
597
598 /* Inform the i2c layer */
599 if ((err = i2c_attach_client(client)))
600 goto exit_kfree;
601
602 list_add(&data->list, &x1205_clients);
603
604 dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
605
606 /* If requested, set the system time */
607 if (hctosys)
608 x1205_hctosys(client);
609
610 return 0;
611
612exit_kfree:
613 kfree(data);
614
615exit:
616 return err;
617}
618
619static int x1205_detach(struct i2c_client *client)
620{
621 int err;
622 struct x1205_data *data = i2c_get_clientdata(client);
623
624 dev_dbg(&client->dev, "%s\n", __FUNCTION__);
625
626 if ((err = i2c_detach_client(client)))
627 return err;
628
629 list_del(&data->list);
630
631 kfree(data);
632
633 return 0;
634}
635
636static int x1205_command(struct i2c_client *client, unsigned int cmd,
637 void *param)
638{
639 if (param == NULL)
640 return -EINVAL;
641
642 if (!capable(CAP_SYS_TIME))
643 return -EACCES;
644
645 dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
646
647 switch (cmd) {
648 case X1205_CMD_GETDATETIME:
649 return x1205_get_datetime(client, param, X1205_CCR_BASE);
650
651 case X1205_CMD_SETTIME:
652 return x1205_set_datetime(client, param, 0,
653 X1205_CCR_BASE);
654
655 case X1205_CMD_SETDATETIME:
656 return x1205_set_datetime(client, param, 1,
657 X1205_CCR_BASE);
658
659 case X1205_CMD_GETALARM:
660 return x1205_get_datetime(client, param, X1205_ALM0_BASE);
661
662 case X1205_CMD_SETALARM:
663 return x1205_set_datetime(client, param, 1,
664 X1205_ALM0_BASE);
665
666 case X1205_CMD_GETDTRIM:
667 return x1205_get_dtrim(client, param);
668
669 case X1205_CMD_GETATRIM:
670 return x1205_get_atrim(client, param);
671
672 default:
673 return -EINVAL;
674 }
675}
676
677static int __init x1205_init(void)
678{
679 return i2c_add_driver(&x1205_driver);
680}
681
682static void __exit x1205_exit(void)
683{
684 i2c_del_driver(&x1205_driver);
685}
686
687MODULE_AUTHOR(
688 "Karen Spearel <kas11@tampabay.rr.com>, "
689 "Alessandro Zummo <a.zummo@towertech.it>");
690MODULE_DESCRIPTION("Xicor X1205 RTC driver");
691MODULE_LICENSE("GPL");
692MODULE_VERSION(DRV_VERSION);
693
694EXPORT_SYMBOL_GPL(x1205_do_command);
695EXPORT_SYMBOL_GPL(x1205_direct_attach);
696
697module_init(x1205_init);
698module_exit(x1205_exit);