diff options
Diffstat (limited to 'drivers/i2c/chips')
-rw-r--r-- | drivers/i2c/chips/Kconfig | 8 | ||||
-rw-r--r-- | drivers/i2c/chips/m41t00.c | 346 |
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 | |||
39 | config SENSORS_PCF8574 | 39 | config 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 | |||
49 | config SENSORS_PCA9539 | 53 | config 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 | |||
59 | config SENSORS_PCF8591 | 63 | config 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 | |||
68 | config ISP1301_OMAP | 76 | config 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 | |||
35 | static DEFINE_MUTEX(m41t00_mutex); | ||
36 | |||
37 | static struct i2c_driver m41t00_driver; | 28 | static struct i2c_driver m41t00_driver; |
38 | static struct i2c_client *save_client; | 29 | static struct i2c_client *save_client; |
39 | 30 | ||
40 | static unsigned short ignore[] = { I2C_CLIENT_END }; | 31 | static unsigned short ignore[] = { I2C_CLIENT_END }; |
41 | static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; | 32 | static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END }; |
42 | 33 | ||
43 | static struct i2c_client_address_data addr_data = { | 34 | static 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 | |||
40 | struct 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 | ||
56 | static 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 | }; | ||
97 | static struct m41t00_chip_info *m41t00_chip; | ||
98 | |||
49 | ulong | 99 | ulong |
50 | m41t00_get_rtc_time(void) | 100 | m41t00_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 | |||
162 | read_err: | ||
163 | dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n"); | ||
164 | return 0; | ||
112 | } | 165 | } |
166 | EXPORT_SYMBOL_GPL(m41t00_get_rtc_time); | ||
113 | 167 | ||
114 | static void | 168 | static void |
115 | m41t00_set(void *arg) | 169 | m41t00_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 | ||
149 | static ulong new_time; | 217 | static ulong new_time; |
@@ -162,6 +230,48 @@ m41t00_set_rtc_time(ulong nowtime) | |||
162 | 230 | ||
163 | return 0; | 231 | return 0; |
164 | } | 232 | } |
233 | EXPORT_SYMBOL_GPL(m41t00_set_rtc_time); | ||
234 | |||
235 | /* | ||
236 | ***************************************************************************** | ||
237 | * | ||
238 | * platform_data Driver Interface | ||
239 | * | ||
240 | ***************************************************************************** | ||
241 | */ | ||
242 | static int __init | ||
243 | m41t00_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 | |||
261 | static int __exit | ||
262 | m41t00_platform_remove(struct platform_device *pdev) | ||
263 | { | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static 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 | |||
343 | st_err: | ||
344 | dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n"); | ||
345 | goto attach_err; | ||
346 | ht_err: | ||
347 | dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n"); | ||
348 | goto attach_err; | ||
349 | sqw_err: | ||
350 | dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n"); | ||
351 | attach_err: | ||
352 | kfree(client); | ||
353 | return rc; | ||
196 | } | 354 | } |
197 | 355 | ||
198 | static int | 356 | static int |
@@ -204,7 +362,7 @@ m41t00_attach(struct i2c_adapter *adap) | |||
204 | static int | 362 | static int |
205 | m41t00_detach(struct i2c_client *client) | 363 | m41t00_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 = { | |||
225 | static int __init | 383 | static int __init |
226 | m41t00_init(void) | 384 | m41t00_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 | ||
231 | static void __exit | 393 | static void __exit |
232 | m41t00_exit(void) | 394 | m41t00_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 | ||
238 | module_init(m41t00_init); | 400 | module_init(m41t00_init); |