2 * Copyright (C) 2015 Zodiac Inflight Innovations
4 * Author: Martyn Welch <martyn.welch@collabora.co.uk>
6 * Based on twl4030_wdt.c by Timo Kokkonen <timo.t.kokkonen at nokia.com>:
8 * Copyright (C) Nokia Corporation
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include <linux/delay.h>
22 #include <linux/i2c.h>
23 #include <linux/ihex.h>
24 #include <linux/firmware.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/sysfs.h>
29 #include <linux/types.h>
30 #include <linux/version.h>
31 #include <linux/watchdog.h>
33 #define ZIIRAVE_TIMEOUT_MIN 3
34 #define ZIIRAVE_TIMEOUT_MAX 255
36 #define ZIIRAVE_PING_VALUE 0x0
38 #define ZIIRAVE_STATE_INITIAL 0x0
39 #define ZIIRAVE_STATE_OFF 0x1
40 #define ZIIRAVE_STATE_ON 0x2
42 #define ZIIRAVE_FW_NAME "ziirave_wdt.fw"
44 static char *ziirave_reasons
[] = {"power cycle", "hw watchdog", NULL
, NULL
,
45 "host request", NULL
, "illegal configuration",
46 "illegal instruction", "illegal trap",
49 #define ZIIRAVE_WDT_FIRM_VER_MAJOR 0x1
50 #define ZIIRAVE_WDT_BOOT_VER_MAJOR 0x3
51 #define ZIIRAVE_WDT_RESET_REASON 0x5
52 #define ZIIRAVE_WDT_STATE 0x6
53 #define ZIIRAVE_WDT_TIMEOUT 0x7
54 #define ZIIRAVE_WDT_TIME_LEFT 0x8
55 #define ZIIRAVE_WDT_PING 0x9
56 #define ZIIRAVE_WDT_RESET_DURATION 0xa
58 #define ZIIRAVE_FIRM_PKT_TOTAL_SIZE 20
59 #define ZIIRAVE_FIRM_PKT_DATA_SIZE 16
60 #define ZIIRAVE_FIRM_FLASH_MEMORY_START 0x1600
61 #define ZIIRAVE_FIRM_FLASH_MEMORY_END 0x2bbf
63 /* Received and ready for next Download packet. */
64 #define ZIIRAVE_FIRM_DOWNLOAD_ACK 1
65 /* Currently writing to flash. Retry Download status in a moment! */
66 #define ZIIRAVE_FIRM_DOWNLOAD_BUSY 2
68 /* Wait for ACK timeout in ms */
69 #define ZIIRAVE_FIRM_WAIT_FOR_ACK_TIMEOUT 50
71 /* Firmware commands */
72 #define ZIIRAVE_CMD_DOWNLOAD_START 0x10
73 #define ZIIRAVE_CMD_DOWNLOAD_END 0x11
74 #define ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR 0x12
75 #define ZIIRAVE_CMD_DOWNLOAD_READ_BYTE 0x13
76 #define ZIIRAVE_CMD_RESET_PROCESSOR 0x0b
77 #define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER 0x0c
78 #define ZIIRAVE_CMD_DOWNLOAD_PACKET 0x0e
80 struct ziirave_wdt_rev
{
85 struct ziirave_wdt_data
{
86 struct mutex sysfs_mutex
;
87 struct watchdog_device wdd
;
88 struct ziirave_wdt_rev bootloader_rev
;
89 struct ziirave_wdt_rev firmware_rev
;
93 static int wdt_timeout
;
94 module_param(wdt_timeout
, int, 0);
95 MODULE_PARM_DESC(wdt_timeout
, "Watchdog timeout in seconds");
97 static int reset_duration
;
98 module_param(reset_duration
, int, 0);
99 MODULE_PARM_DESC(reset_duration
,
100 "Watchdog reset pulse duration in milliseconds");
102 static bool nowayout
= WATCHDOG_NOWAYOUT
;
103 module_param(nowayout
, bool, 0);
104 MODULE_PARM_DESC(nowayout
, "Watchdog cannot be stopped once started default="
105 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
107 static int ziirave_wdt_revision(struct i2c_client
*client
,
108 struct ziirave_wdt_rev
*rev
, u8 command
)
112 ret
= i2c_smbus_read_byte_data(client
, command
);
118 ret
= i2c_smbus_read_byte_data(client
, command
+ 1);
127 static int ziirave_wdt_set_state(struct watchdog_device
*wdd
, int state
)
129 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
131 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_STATE
, state
);
134 static int ziirave_wdt_start(struct watchdog_device
*wdd
)
136 return ziirave_wdt_set_state(wdd
, ZIIRAVE_STATE_ON
);
139 static int ziirave_wdt_stop(struct watchdog_device
*wdd
)
141 return ziirave_wdt_set_state(wdd
, ZIIRAVE_STATE_OFF
);
144 static int ziirave_wdt_ping(struct watchdog_device
*wdd
)
146 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
148 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_PING
,
152 static int ziirave_wdt_set_timeout(struct watchdog_device
*wdd
,
153 unsigned int timeout
)
155 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
158 ret
= i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_TIMEOUT
, timeout
);
160 wdd
->timeout
= timeout
;
165 static unsigned int ziirave_wdt_get_timeleft(struct watchdog_device
*wdd
)
167 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
170 ret
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_TIME_LEFT
);
177 static int ziirave_firm_wait_for_ack(struct watchdog_device
*wdd
)
179 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
181 unsigned long timeout
;
183 timeout
= jiffies
+ msecs_to_jiffies(ZIIRAVE_FIRM_WAIT_FOR_ACK_TIMEOUT
);
185 if (time_after(jiffies
, timeout
))
188 usleep_range(5000, 10000);
190 ret
= i2c_smbus_read_byte(client
);
192 dev_err(&client
->dev
, "Failed to read byte\n");
195 } while (ret
== ZIIRAVE_FIRM_DOWNLOAD_BUSY
);
197 return ret
== ZIIRAVE_FIRM_DOWNLOAD_ACK
? 0 : -EIO
;
200 static int ziirave_firm_set_read_addr(struct watchdog_device
*wdd
, u16 addr
)
202 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
205 address
[0] = addr
& 0xff;
206 address
[1] = (addr
>> 8) & 0xff;
208 return i2c_smbus_write_block_data(client
,
209 ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR
,
210 ARRAY_SIZE(address
), address
);
213 static int ziirave_firm_write_block_data(struct watchdog_device
*wdd
,
214 u8 command
, u8 length
, const u8
*data
,
217 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
220 ret
= i2c_smbus_write_block_data(client
, command
, length
, data
);
222 dev_err(&client
->dev
,
223 "Failed to send command 0x%02x: %d\n", command
, ret
);
228 ret
= ziirave_firm_wait_for_ack(wdd
);
233 static int ziirave_firm_write_byte(struct watchdog_device
*wdd
, u8 command
,
234 u8 byte
, bool wait_for_ack
)
236 return ziirave_firm_write_block_data(wdd
, command
, 1, &byte
,
241 * ziirave_firm_write_pkt() - Build and write a firmware packet
243 * A packet to send to the firmware is composed by following bytes:
244 * Length | Addr0 | Addr1 | Data0 .. Data15 | Checksum |
246 * Length: A data byte containing the length of the data.
247 * Addr0: Low byte of the address.
248 * Addr1: High byte of the address.
249 * Data0 .. Data15: Array of 16 bytes of data.
250 * Checksum: Checksum byte to verify data integrity.
252 static int ziirave_firm_write_pkt(struct watchdog_device
*wdd
,
253 const struct ihex_binrec
*rec
)
255 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
256 u8 i
, checksum
= 0, packet
[ZIIRAVE_FIRM_PKT_TOTAL_SIZE
];
260 memset(packet
, 0, ARRAY_SIZE(packet
));
263 packet
[0] = (u8
)be16_to_cpu(rec
->len
);
265 addr
= (be32_to_cpu(rec
->addr
) & 0xffff) >> 1;
266 packet
[1] = addr
& 0xff;
267 packet
[2] = (addr
& 0xff00) >> 8;
270 if (be16_to_cpu(rec
->len
) > ZIIRAVE_FIRM_PKT_DATA_SIZE
)
272 memcpy(packet
+ 3, rec
->data
, be16_to_cpu(rec
->len
));
274 /* Packet checksum */
275 for (i
= 0; i
< ZIIRAVE_FIRM_PKT_TOTAL_SIZE
- 1; i
++)
276 checksum
+= packet
[i
];
277 packet
[ZIIRAVE_FIRM_PKT_TOTAL_SIZE
- 1] = checksum
;
279 ret
= ziirave_firm_write_block_data(wdd
, ZIIRAVE_CMD_DOWNLOAD_PACKET
,
280 ARRAY_SIZE(packet
), packet
, true);
282 dev_err(&client
->dev
,
283 "Failed to write firmware packet at address 0x%04x: %d\n",
289 static int ziirave_firm_verify(struct watchdog_device
*wdd
,
290 const struct firmware
*fw
)
292 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
293 const struct ihex_binrec
*rec
;
295 u8 data
[ZIIRAVE_FIRM_PKT_DATA_SIZE
];
298 for (rec
= (void *)fw
->data
; rec
; rec
= ihex_next_binrec(rec
)) {
299 /* Zero length marks end of records */
300 if (!be16_to_cpu(rec
->len
))
303 addr
= (be32_to_cpu(rec
->addr
) & 0xffff) >> 1;
304 if (addr
< ZIIRAVE_FIRM_FLASH_MEMORY_START
||
305 addr
> ZIIRAVE_FIRM_FLASH_MEMORY_END
)
308 ret
= ziirave_firm_set_read_addr(wdd
, addr
);
310 dev_err(&client
->dev
,
311 "Failed to send SET_READ_ADDR command: %d\n",
316 for (i
= 0; i
< ARRAY_SIZE(data
); i
++) {
317 ret
= i2c_smbus_read_byte_data(client
,
318 ZIIRAVE_CMD_DOWNLOAD_READ_BYTE
);
320 dev_err(&client
->dev
,
321 "Failed to READ DATA: %d\n", ret
);
327 if (memcmp(data
, rec
->data
, be16_to_cpu(rec
->len
))) {
328 dev_err(&client
->dev
,
329 "Firmware mismatch at address 0x%04x\n", addr
);
337 static int ziirave_firm_upload(struct watchdog_device
*wdd
,
338 const struct firmware
*fw
)
340 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
341 int ret
, words_till_page_break
;
342 const struct ihex_binrec
*rec
;
343 struct ihex_binrec
*rec_new
;
345 ret
= ziirave_firm_write_byte(wdd
, ZIIRAVE_CMD_JUMP_TO_BOOTLOADER
, 1,
352 ret
= ziirave_firm_write_byte(wdd
, ZIIRAVE_CMD_DOWNLOAD_START
, 1, true);
358 for (rec
= (void *)fw
->data
; rec
; rec
= ihex_next_binrec(rec
)) {
359 /* Zero length marks end of records */
360 if (!be16_to_cpu(rec
->len
))
363 /* Check max data size */
364 if (be16_to_cpu(rec
->len
) > ZIIRAVE_FIRM_PKT_DATA_SIZE
) {
365 dev_err(&client
->dev
, "Firmware packet too long (%d)\n",
366 be16_to_cpu(rec
->len
));
370 /* Calculate words till page break */
371 words_till_page_break
= (64 - ((be32_to_cpu(rec
->addr
) >> 1) &
373 if ((be16_to_cpu(rec
->len
) >> 1) > words_till_page_break
) {
375 * Data in passes page boundary, so we need to split in
376 * two blocks of data. Create a packet with the first
379 rec_new
= kzalloc(sizeof(struct ihex_binrec
) +
380 (words_till_page_break
<< 1),
385 rec_new
->len
= cpu_to_be16(words_till_page_break
<< 1);
386 rec_new
->addr
= rec
->addr
;
387 memcpy(rec_new
->data
, rec
->data
,
388 be16_to_cpu(rec_new
->len
));
390 ret
= ziirave_firm_write_pkt(wdd
, rec_new
);
395 /* Create a packet with the second block of data */
396 rec_new
= kzalloc(sizeof(struct ihex_binrec
) +
397 be16_to_cpu(rec
->len
) -
398 (words_till_page_break
<< 1),
403 /* Remaining bytes */
404 rec_new
->len
= rec
->len
-
405 cpu_to_be16(words_till_page_break
<< 1);
407 rec_new
->addr
= cpu_to_be32(be32_to_cpu(rec
->addr
) +
408 (words_till_page_break
<< 1));
410 memcpy(rec_new
->data
,
411 rec
->data
+ (words_till_page_break
<< 1),
412 be16_to_cpu(rec_new
->len
));
414 ret
= ziirave_firm_write_pkt(wdd
, rec_new
);
419 ret
= ziirave_firm_write_pkt(wdd
, rec
);
425 /* For end of download, the length field will be set to 0 */
426 rec_new
= kzalloc(sizeof(struct ihex_binrec
) + 1, GFP_KERNEL
);
430 ret
= ziirave_firm_write_pkt(wdd
, rec_new
);
433 dev_err(&client
->dev
, "Failed to send EMPTY packet: %d\n", ret
);
437 /* This sleep seems to be required */
440 /* Start firmware verification */
441 ret
= ziirave_firm_verify(wdd
, fw
);
443 dev_err(&client
->dev
,
444 "Failed to verify firmware: %d\n", ret
);
448 /* End download operation */
449 ret
= ziirave_firm_write_byte(wdd
, ZIIRAVE_CMD_DOWNLOAD_END
, 1, false);
453 /* Reset the processor */
454 ret
= ziirave_firm_write_byte(wdd
, ZIIRAVE_CMD_RESET_PROCESSOR
, 1,
464 static const struct watchdog_info ziirave_wdt_info
= {
465 .options
= WDIOF_SETTIMEOUT
| WDIOF_MAGICCLOSE
| WDIOF_KEEPALIVEPING
,
466 .identity
= "Zodiac RAVE Watchdog",
469 static const struct watchdog_ops ziirave_wdt_ops
= {
470 .owner
= THIS_MODULE
,
471 .start
= ziirave_wdt_start
,
472 .stop
= ziirave_wdt_stop
,
473 .ping
= ziirave_wdt_ping
,
474 .set_timeout
= ziirave_wdt_set_timeout
,
475 .get_timeleft
= ziirave_wdt_get_timeleft
,
478 static ssize_t
ziirave_wdt_sysfs_show_firm(struct device
*dev
,
479 struct device_attribute
*attr
,
482 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
483 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
486 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
490 ret
= sprintf(buf
, "02.%02u.%02u", w_priv
->firmware_rev
.major
,
491 w_priv
->firmware_rev
.minor
);
493 mutex_unlock(&w_priv
->sysfs_mutex
);
498 static DEVICE_ATTR(firmware_version
, S_IRUGO
, ziirave_wdt_sysfs_show_firm
,
501 static ssize_t
ziirave_wdt_sysfs_show_boot(struct device
*dev
,
502 struct device_attribute
*attr
,
505 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
506 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
509 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
513 ret
= sprintf(buf
, "01.%02u.%02u", w_priv
->bootloader_rev
.major
,
514 w_priv
->bootloader_rev
.minor
);
516 mutex_unlock(&w_priv
->sysfs_mutex
);
521 static DEVICE_ATTR(bootloader_version
, S_IRUGO
, ziirave_wdt_sysfs_show_boot
,
524 static ssize_t
ziirave_wdt_sysfs_show_reason(struct device
*dev
,
525 struct device_attribute
*attr
,
528 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
529 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
532 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
536 ret
= sprintf(buf
, "%s", ziirave_reasons
[w_priv
->reset_reason
]);
538 mutex_unlock(&w_priv
->sysfs_mutex
);
543 static DEVICE_ATTR(reset_reason
, S_IRUGO
, ziirave_wdt_sysfs_show_reason
,
546 static ssize_t
ziirave_wdt_sysfs_store_firm(struct device
*dev
,
547 struct device_attribute
*attr
,
548 const char *buf
, size_t count
)
550 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
551 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
552 const struct firmware
*fw
;
555 err
= request_ihex_firmware(&fw
, ZIIRAVE_FW_NAME
, dev
);
557 dev_err(&client
->dev
, "Failed to request ihex firmware\n");
561 err
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
563 goto release_firmware
;
565 err
= ziirave_firm_upload(&w_priv
->wdd
, fw
);
567 dev_err(&client
->dev
, "The firmware update failed: %d\n", err
);
571 /* Update firmware version */
572 err
= ziirave_wdt_revision(client
, &w_priv
->firmware_rev
,
573 ZIIRAVE_WDT_FIRM_VER_MAJOR
);
575 dev_err(&client
->dev
, "Failed to read firmware version: %d\n",
580 dev_info(&client
->dev
, "Firmware updated to version 02.%02u.%02u\n",
581 w_priv
->firmware_rev
.major
, w_priv
->firmware_rev
.minor
);
583 /* Restore the watchdog timeout */
584 err
= ziirave_wdt_set_timeout(&w_priv
->wdd
, w_priv
->wdd
.timeout
);
586 dev_err(&client
->dev
, "Failed to set timeout: %d\n", err
);
589 mutex_unlock(&w_priv
->sysfs_mutex
);
592 release_firmware(fw
);
594 return err
? err
: count
;
597 static DEVICE_ATTR(update_firmware
, S_IWUSR
, NULL
,
598 ziirave_wdt_sysfs_store_firm
);
600 static struct attribute
*ziirave_wdt_attrs
[] = {
601 &dev_attr_firmware_version
.attr
,
602 &dev_attr_bootloader_version
.attr
,
603 &dev_attr_reset_reason
.attr
,
604 &dev_attr_update_firmware
.attr
,
607 ATTRIBUTE_GROUPS(ziirave_wdt
);
609 static int ziirave_wdt_init_duration(struct i2c_client
*client
)
613 if (!reset_duration
) {
614 /* See if the reset pulse duration is provided in an of_node */
615 if (!client
->dev
.of_node
)
618 ret
= of_property_read_u32(client
->dev
.of_node
,
622 dev_info(&client
->dev
,
623 "Unable to set reset pulse duration, using default\n");
628 if (reset_duration
< 1 || reset_duration
> 255)
631 dev_info(&client
->dev
, "Setting reset duration to %dms",
634 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_RESET_DURATION
,
638 static int ziirave_wdt_probe(struct i2c_client
*client
,
639 const struct i2c_device_id
*id
)
642 struct ziirave_wdt_data
*w_priv
;
645 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_SMBUS_BYTE_DATA
))
648 w_priv
= devm_kzalloc(&client
->dev
, sizeof(*w_priv
), GFP_KERNEL
);
652 mutex_init(&w_priv
->sysfs_mutex
);
654 w_priv
->wdd
.info
= &ziirave_wdt_info
;
655 w_priv
->wdd
.ops
= &ziirave_wdt_ops
;
656 w_priv
->wdd
.min_timeout
= ZIIRAVE_TIMEOUT_MIN
;
657 w_priv
->wdd
.max_timeout
= ZIIRAVE_TIMEOUT_MAX
;
658 w_priv
->wdd
.parent
= &client
->dev
;
659 w_priv
->wdd
.groups
= ziirave_wdt_groups
;
661 ret
= watchdog_init_timeout(&w_priv
->wdd
, wdt_timeout
, &client
->dev
);
663 dev_info(&client
->dev
,
664 "Unable to select timeout value, using default\n");
668 * The default value set in the watchdog should be perfectly valid, so
669 * pass that in if we haven't provided one via the module parameter or
672 if (w_priv
->wdd
.timeout
== 0) {
673 val
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_TIMEOUT
);
677 if (val
< ZIIRAVE_TIMEOUT_MIN
)
680 w_priv
->wdd
.timeout
= val
;
682 ret
= ziirave_wdt_set_timeout(&w_priv
->wdd
,
683 w_priv
->wdd
.timeout
);
687 dev_info(&client
->dev
, "Timeout set to %ds.",
688 w_priv
->wdd
.timeout
);
691 watchdog_set_nowayout(&w_priv
->wdd
, nowayout
);
693 i2c_set_clientdata(client
, w_priv
);
695 /* If in unconfigured state, set to stopped */
696 val
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_STATE
);
700 if (val
== ZIIRAVE_STATE_INITIAL
)
701 ziirave_wdt_stop(&w_priv
->wdd
);
703 ret
= ziirave_wdt_init_duration(client
);
707 ret
= ziirave_wdt_revision(client
, &w_priv
->firmware_rev
,
708 ZIIRAVE_WDT_FIRM_VER_MAJOR
);
712 ret
= ziirave_wdt_revision(client
, &w_priv
->bootloader_rev
,
713 ZIIRAVE_WDT_BOOT_VER_MAJOR
);
717 w_priv
->reset_reason
= i2c_smbus_read_byte_data(client
,
718 ZIIRAVE_WDT_RESET_REASON
);
719 if (w_priv
->reset_reason
< 0)
720 return w_priv
->reset_reason
;
722 if (w_priv
->reset_reason
>= ARRAY_SIZE(ziirave_reasons
) ||
723 !ziirave_reasons
[w_priv
->reset_reason
])
726 ret
= watchdog_register_device(&w_priv
->wdd
);
731 static int ziirave_wdt_remove(struct i2c_client
*client
)
733 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
735 watchdog_unregister_device(&w_priv
->wdd
);
740 static const struct i2c_device_id ziirave_wdt_id
[] = {
744 MODULE_DEVICE_TABLE(i2c
, ziirave_wdt_id
);
746 static const struct of_device_id zrv_wdt_of_match
[] = {
747 { .compatible
= "zii,rave-wdt", },
750 MODULE_DEVICE_TABLE(of
, zrv_wdt_of_match
);
752 static struct i2c_driver ziirave_wdt_driver
= {
754 .name
= "ziirave_wdt",
755 .of_match_table
= zrv_wdt_of_match
,
757 .probe
= ziirave_wdt_probe
,
758 .remove
= ziirave_wdt_remove
,
759 .id_table
= ziirave_wdt_id
,
762 module_i2c_driver(ziirave_wdt_driver
);
764 MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk");
765 MODULE_DESCRIPTION("Zodiac Aerospace RAVE Switch Watchdog Processor Driver");
766 MODULE_LICENSE("GPL");