aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/chips')
-rw-r--r--drivers/i2c/chips/Kconfig8
-rw-r--r--drivers/i2c/chips/m41t00.c346
2 files changed, 262 insertions, 92 deletions
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 7aa5c38f0855..87ee3ce58618 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -39,6 +39,7 @@ config SENSORS_EEPROM
39config SENSORS_PCF8574 39config SENSORS_PCF8574
40 tristate "Philips PCF8574 and PCF8574A" 40 tristate "Philips PCF8574 and PCF8574A"
41 depends on I2C && EXPERIMENTAL 41 depends on I2C && EXPERIMENTAL
42 default n
42 help 43 help
43 If you say yes here you get support for Philips PCF8574 and 44 If you say yes here you get support for Philips PCF8574 and
44 PCF8574A chips. 45 PCF8574A chips.
@@ -46,6 +47,9 @@ config SENSORS_PCF8574
46 This driver can also be built as a module. If so, the module 47 This driver can also be built as a module. If so, the module
47 will be called pcf8574. 48 will be called pcf8574.
48 49
50 These devices are hard to detect and rarely found on mainstream
51 hardware. If unsure, say N.
52
49config SENSORS_PCA9539 53config SENSORS_PCA9539
50 tristate "Philips PCA9539 16-bit I/O port" 54 tristate "Philips PCA9539 16-bit I/O port"
51 depends on I2C && EXPERIMENTAL 55 depends on I2C && EXPERIMENTAL
@@ -59,12 +63,16 @@ config SENSORS_PCA9539
59config SENSORS_PCF8591 63config SENSORS_PCF8591
60 tristate "Philips PCF8591" 64 tristate "Philips PCF8591"
61 depends on I2C && EXPERIMENTAL 65 depends on I2C && EXPERIMENTAL
66 default n
62 help 67 help
63 If you say yes here you get support for Philips PCF8591 chips. 68 If you say yes here you get support for Philips PCF8591 chips.
64 69
65 This driver can also be built as a module. If so, the module 70 This driver can also be built as a module. If so, the module
66 will be called pcf8591. 71 will be called pcf8591.
67 72
73 These devices are hard to detect and rarely found on mainstream
74 hardware. If unsure, say N.
75
68config ISP1301_OMAP 76config ISP1301_OMAP
69 tristate "Philips ISP1301 with OMAP OTG" 77 tristate "Philips ISP1301 with OMAP OTG"
70 depends on I2C && ARCH_OMAP_OTG 78 depends on I2C && ARCH_OMAP_OTG
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 99ab4ec34390..2dd0a34d9472 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -1,11 +1,9 @@
1/* 1/*
2 * drivers/i2c/chips/m41t00.c 2 * I2C client/driver for the ST M41T00 family of i2c rtc chips.
3 *
4 * I2C client/driver for the ST M41T00 Real-Time Clock chip.
5 * 3 *
6 * Author: Mark A. Greer <mgreer@mvista.com> 4 * Author: Mark A. Greer <mgreer@mvista.com>
7 * 5 *
8 * 2005 (c) MontaVista Software, Inc. This file is licensed under 6 * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program 7 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express 8 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied. 9 * or implied.
@@ -13,9 +11,6 @@
13/* 11/*
14 * This i2c client/driver wedges between the drivers/char/genrtc.c RTC 12 * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
15 * interface and the SMBus interface of the i2c subsystem. 13 * interface and the SMBus interface of the i2c subsystem.
16 * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
17 * recommened in .../Documentation/i2c/writing-clients section
18 * "Sending and receiving", using SMBus level communication is preferred.
19 */ 14 */
20 15
21#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -24,56 +19,110 @@
24#include <linux/i2c.h> 19#include <linux/i2c.h>
25#include <linux/rtc.h> 20#include <linux/rtc.h>
26#include <linux/bcd.h> 21#include <linux/bcd.h>
27#include <linux/mutex.h>
28#include <linux/workqueue.h> 22#include <linux/workqueue.h>
29 23#include <linux/platform_device.h>
24#include <linux/m41t00.h>
30#include <asm/time.h> 25#include <asm/time.h>
31#include <asm/rtc.h> 26#include <asm/rtc.h>
32 27
33#define M41T00_DRV_NAME "m41t00"
34
35static DEFINE_MUTEX(m41t00_mutex);
36
37static struct i2c_driver m41t00_driver; 28static struct i2c_driver m41t00_driver;
38static struct i2c_client *save_client; 29static struct i2c_client *save_client;
39 30
40static unsigned short ignore[] = { I2C_CLIENT_END }; 31static unsigned short ignore[] = { I2C_CLIENT_END };
41static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; 32static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END };
42 33
43static struct i2c_client_address_data addr_data = { 34static struct i2c_client_address_data addr_data = {
44 .normal_i2c = normal_addr, 35 .normal_i2c = normal_addr,
45 .probe = ignore, 36 .probe = ignore,
46 .ignore = ignore, 37 .ignore = ignore,
38};
39
40struct m41t00_chip_info {
41 u8 type;
42 char *name;
43 u8 read_limit;
44 u8 sec; /* Offsets for chip regs */
45 u8 min;
46 u8 hour;
47 u8 day;
48 u8 mon;
49 u8 year;
50 u8 alarm_mon;
51 u8 alarm_hour;
52 u8 sqw;
53 u8 sqw_freq;
47}; 54};
48 55
56static struct m41t00_chip_info m41t00_chip_info_tbl[] = {
57 {
58 .type = M41T00_TYPE_M41T00,
59 .name = "m41t00",
60 .read_limit = 5,
61 .sec = 0,
62 .min = 1,
63 .hour = 2,
64 .day = 4,
65 .mon = 5,
66 .year = 6,
67 },
68 {
69 .type = M41T00_TYPE_M41T81,
70 .name = "m41t81",
71 .read_limit = 1,
72 .sec = 1,
73 .min = 2,
74 .hour = 3,
75 .day = 5,
76 .mon = 6,
77 .year = 7,
78 .alarm_mon = 0xa,
79 .alarm_hour = 0xc,
80 .sqw = 0x13,
81 },
82 {
83 .type = M41T00_TYPE_M41T85,
84 .name = "m41t85",
85 .read_limit = 1,
86 .sec = 1,
87 .min = 2,
88 .hour = 3,
89 .day = 5,
90 .mon = 6,
91 .year = 7,
92 .alarm_mon = 0xa,
93 .alarm_hour = 0xc,
94 .sqw = 0x13,
95 },
96};
97static struct m41t00_chip_info *m41t00_chip;
98
49ulong 99ulong
50m41t00_get_rtc_time(void) 100m41t00_get_rtc_time(void)
51{ 101{
52 s32 sec, min, hour, day, mon, year; 102 s32 sec, min, hour, day, mon, year;
53 s32 sec1, min1, hour1, day1, mon1, year1; 103 s32 sec1, min1, hour1, day1, mon1, year1;
54 ulong limit = 10; 104 u8 reads = 0;
105 u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */
106 struct i2c_msg msgs[] = {
107 {
108 .addr = save_client->addr,
109 .flags = 0,
110 .len = 1,
111 .buf = msgbuf,
112 },
113 {
114 .addr = save_client->addr,
115 .flags = I2C_M_RD,
116 .len = 8,
117 .buf = buf,
118 },
119 };
55 120
56 sec = min = hour = day = mon = year = 0; 121 sec = min = hour = day = mon = year = 0;
57 sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
58 122
59 mutex_lock(&m41t00_mutex);
60 do { 123 do {
61 if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) 124 if (i2c_transfer(save_client->adapter, msgs, 2) < 0)
62 && ((min = i2c_smbus_read_byte_data(save_client, 1)) 125 goto read_err;
63 >= 0)
64 && ((hour = i2c_smbus_read_byte_data(save_client, 2))
65 >= 0)
66 && ((day = i2c_smbus_read_byte_data(save_client, 4))
67 >= 0)
68 && ((mon = i2c_smbus_read_byte_data(save_client, 5))
69 >= 0)
70 && ((year = i2c_smbus_read_byte_data(save_client, 6))
71 >= 0)
72 && ((sec == sec1) && (min == min1) && (hour == hour1)
73 && (day == day1) && (mon == mon1)
74 && (year == year1)))
75
76 break;
77 126
78 sec1 = sec; 127 sec1 = sec;
79 min1 = min; 128 min1 = min;
@@ -81,69 +130,88 @@ m41t00_get_rtc_time(void)
81 day1 = day; 130 day1 = day;
82 mon1 = mon; 131 mon1 = mon;
83 year1 = year; 132 year1 = year;
84 } while (--limit > 0);
85 mutex_unlock(&m41t00_mutex);
86
87 if (limit == 0) {
88 dev_warn(&save_client->dev,
89 "m41t00: can't read rtc chip\n");
90 sec = min = hour = day = mon = year = 0;
91 }
92
93 sec &= 0x7f;
94 min &= 0x7f;
95 hour &= 0x3f;
96 day &= 0x3f;
97 mon &= 0x1f;
98 year &= 0xff;
99 133
100 BCD_TO_BIN(sec); 134 sec = buf[m41t00_chip->sec] & 0x7f;
101 BCD_TO_BIN(min); 135 min = buf[m41t00_chip->min] & 0x7f;
102 BCD_TO_BIN(hour); 136 hour = buf[m41t00_chip->hour] & 0x3f;
103 BCD_TO_BIN(day); 137 day = buf[m41t00_chip->day] & 0x3f;
104 BCD_TO_BIN(mon); 138 mon = buf[m41t00_chip->mon] & 0x1f;
105 BCD_TO_BIN(year); 139 year = buf[m41t00_chip->year];
140 } while ((++reads < m41t00_chip->read_limit) && ((sec != sec1)
141 || (min != min1) || (hour != hour1) || (day != day1)
142 || (mon != mon1) || (year != year1)));
143
144 if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1)
145 || (hour != hour1) || (day != day1) || (mon != mon1)
146 || (year != year1)))
147 goto read_err;
148
149 sec = BCD2BIN(sec);
150 min = BCD2BIN(min);
151 hour = BCD2BIN(hour);
152 day = BCD2BIN(day);
153 mon = BCD2BIN(mon);
154 year = BCD2BIN(year);
106 155
107 year += 1900; 156 year += 1900;
108 if (year < 1970) 157 if (year < 1970)
109 year += 100; 158 year += 100;
110 159
111 return mktime(year, mon, day, hour, min, sec); 160 return mktime(year, mon, day, hour, min, sec);
161
162read_err:
163 dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n");
164 return 0;
112} 165}
166EXPORT_SYMBOL_GPL(m41t00_get_rtc_time);
113 167
114static void 168static void
115m41t00_set(void *arg) 169m41t00_set(void *arg)
116{ 170{
117 struct rtc_time tm; 171 struct rtc_time tm;
118 ulong nowtime = *(ulong *)arg; 172 int nowtime = *(int *)arg;
173 s32 sec, min, hour, day, mon, year;
174 u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 };
175 struct i2c_msg msgs[] = {
176 {
177 .addr = save_client->addr,
178 .flags = 0,
179 .len = 1,
180 .buf = msgbuf,
181 },
182 {
183 .addr = save_client->addr,
184 .flags = I2C_M_RD,
185 .len = 8,
186 .buf = buf,
187 },
188 };
119 189
120 to_tm(nowtime, &tm); 190 to_tm(nowtime, &tm);
121 tm.tm_year = (tm.tm_year - 1900) % 100; 191 tm.tm_year = (tm.tm_year - 1900) % 100;
122 192
123 BIN_TO_BCD(tm.tm_sec); 193 sec = BIN2BCD(tm.tm_sec);
124 BIN_TO_BCD(tm.tm_min); 194 min = BIN2BCD(tm.tm_min);
125 BIN_TO_BCD(tm.tm_hour); 195 hour = BIN2BCD(tm.tm_hour);
126 BIN_TO_BCD(tm.tm_mon); 196 day = BIN2BCD(tm.tm_mday);
127 BIN_TO_BCD(tm.tm_mday); 197 mon = BIN2BCD(tm.tm_mon);
128 BIN_TO_BCD(tm.tm_year); 198 year = BIN2BCD(tm.tm_year);
129 199
130 mutex_lock(&m41t00_mutex); 200 /* Read reg values into buf[0..7]/wbuf[1..8] */
131 if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) 201 if (i2c_transfer(save_client->adapter, msgs, 2) < 0) {
132 || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) 202 dev_err(&save_client->dev, "m41t00_set: Read error\n");
133 < 0) 203 return;
134 || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f) 204 }
135 < 0) 205
136 || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f) 206 wbuf[0] = 0; /* offset into rtc's regs */
137 < 0) 207 buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f);
138 || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f) 208 buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f);
139 < 0) 209 buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
140 || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff) 210 buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
141 < 0)) 211 buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
142 212
143 dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); 213 if (i2c_master_send(save_client, wbuf, 9) < 0)
144 214 dev_err(&save_client->dev, "m41t00_set: Write error\n");
145 mutex_unlock(&m41t00_mutex);
146 return;
147} 215}
148 216
149static ulong new_time; 217static ulong new_time;
@@ -162,6 +230,48 @@ m41t00_set_rtc_time(ulong nowtime)
162 230
163 return 0; 231 return 0;
164} 232}
233EXPORT_SYMBOL_GPL(m41t00_set_rtc_time);
234
235/*
236 *****************************************************************************
237 *
238 * platform_data Driver Interface
239 *
240 *****************************************************************************
241 */
242static int __init
243m41t00_platform_probe(struct platform_device *pdev)
244{
245 struct m41t00_platform_data *pdata;
246 int i;
247
248 if (pdev && (pdata = pdev->dev.platform_data)) {
249 normal_addr[0] = pdata->i2c_addr;
250
251 for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++)
252 if (m41t00_chip_info_tbl[i].type == pdata->type) {
253 m41t00_chip = &m41t00_chip_info_tbl[i];
254 m41t00_chip->sqw_freq = pdata->sqw_freq;
255 return 0;
256 }
257 }
258 return -ENODEV;
259}
260
261static int __exit
262m41t00_platform_remove(struct platform_device *pdev)
263{
264 return 0;
265}
266
267static struct platform_driver m41t00_platform_driver = {
268 .probe = m41t00_platform_probe,
269 .remove = m41t00_platform_remove,
270 .driver = {
271 .owner = THIS_MODULE,
272 .name = M41T00_DRV_NAME,
273 },
274};
165 275
166/* 276/*
167 ***************************************************************************** 277 *****************************************************************************
@@ -176,23 +286,71 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
176 struct i2c_client *client; 286 struct i2c_client *client;
177 int rc; 287 int rc;
178 288
289 if (!i2c_check_functionality(adap, I2C_FUNC_I2C
290 | I2C_FUNC_SMBUS_BYTE_DATA))
291 return 0;
292
179 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); 293 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
180 if (!client) 294 if (!client)
181 return -ENOMEM; 295 return -ENOMEM;
182 296
183 strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); 297 strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE);
184 client->addr = addr; 298 client->addr = addr;
185 client->adapter = adap; 299 client->adapter = adap;
186 client->driver = &m41t00_driver; 300 client->driver = &m41t00_driver;
187 301
188 if ((rc = i2c_attach_client(client)) != 0) { 302 if ((rc = i2c_attach_client(client)))
189 kfree(client); 303 goto attach_err;
190 return rc; 304
305 if (m41t00_chip->type != M41T00_TYPE_M41T00) {
306 /* If asked, disable SQW, set SQW frequency & re-enable */
307 if (m41t00_chip->sqw_freq)
308 if (((rc = i2c_smbus_read_byte_data(client,
309 m41t00_chip->alarm_mon)) < 0)
310 || ((rc = i2c_smbus_write_byte_data(client,
311 m41t00_chip->alarm_mon, rc & ~0x40)) <0)
312 || ((rc = i2c_smbus_write_byte_data(client,
313 m41t00_chip->sqw,
314 m41t00_chip->sqw_freq)) < 0)
315 || ((rc = i2c_smbus_write_byte_data(client,
316 m41t00_chip->alarm_mon, rc | 0x40)) <0))
317 goto sqw_err;
318
319 /* Make sure HT (Halt Update) bit is cleared */
320 if ((rc = i2c_smbus_read_byte_data(client,
321 m41t00_chip->alarm_hour)) < 0)
322 goto ht_err;
323
324 if (rc & 0x40)
325 if ((rc = i2c_smbus_write_byte_data(client,
326 m41t00_chip->alarm_hour, rc & ~0x40))<0)
327 goto ht_err;
191 } 328 }
192 329
193 m41t00_wq = create_singlethread_workqueue("m41t00"); 330 /* Make sure ST (stop) bit is cleared */
331 if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0)
332 goto st_err;
333
334 if (rc & 0x80)
335 if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec,
336 rc & ~0x80)) < 0)
337 goto st_err;
338
339 m41t00_wq = create_singlethread_workqueue(m41t00_chip->name);
194 save_client = client; 340 save_client = client;
195 return 0; 341 return 0;
342
343st_err:
344 dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n");
345 goto attach_err;
346ht_err:
347 dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n");
348 goto attach_err;
349sqw_err:
350 dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n");
351attach_err:
352 kfree(client);
353 return rc;
196} 354}
197 355
198static int 356static int
@@ -204,7 +362,7 @@ m41t00_attach(struct i2c_adapter *adap)
204static int 362static int
205m41t00_detach(struct i2c_client *client) 363m41t00_detach(struct i2c_client *client)
206{ 364{
207 int rc; 365 int rc;
208 366
209 if ((rc = i2c_detach_client(client)) == 0) { 367 if ((rc = i2c_detach_client(client)) == 0) {
210 kfree(client); 368 kfree(client);
@@ -225,14 +383,18 @@ static struct i2c_driver m41t00_driver = {
225static int __init 383static int __init
226m41t00_init(void) 384m41t00_init(void)
227{ 385{
228 return i2c_add_driver(&m41t00_driver); 386 int rc;
387
388 if (!(rc = platform_driver_register(&m41t00_platform_driver)))
389 rc = i2c_add_driver(&m41t00_driver);
390 return rc;
229} 391}
230 392
231static void __exit 393static void __exit
232m41t00_exit(void) 394m41t00_exit(void)
233{ 395{
234 i2c_del_driver(&m41t00_driver); 396 i2c_del_driver(&m41t00_driver);
235 return; 397 platform_driver_unregister(&m41t00_platform_driver);
236} 398}
237 399
238module_init(m41t00_init); 400module_init(m41t00_init);