diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 08:41:41 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 13:07:53 -0400 |
| commit | 816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch) | |
| tree | 421fa29aedff988e392f92780637553e275d37a0 /drivers/i2c/chips/m41t00.c | |
| parent | 70ac4385a13f78bc478f26d317511893741b05bd (diff) | |
| parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
fs/nfs/inode.c
fs/super.c
Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch
'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'drivers/i2c/chips/m41t00.c')
| -rw-r--r-- | drivers/i2c/chips/m41t00.c | 346 |
1 files changed, 254 insertions, 92 deletions
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); |
