1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015 Zodiac Inflight Innovations
5 * Author: Martyn Welch <martyn.welch@collabora.co.uk>
7 * Based on twl4030_wdt.c by Timo Kokkonen <timo.t.kokkonen at nokia.com>:
9 * Copyright (C) Nokia Corporation
12 #include <linux/delay.h>
13 #include <linux/i2c.h>
14 #include <linux/ihex.h>
15 #include <linux/firmware.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/sysfs.h>
20 #include <linux/types.h>
21 #include <linux/version.h>
22 #include <linux/watchdog.h>
24 #include <asm/unaligned.h>
26 #define ZIIRAVE_TIMEOUT_MIN 3
27 #define ZIIRAVE_TIMEOUT_MAX 255
28 #define ZIIRAVE_TIMEOUT_DEFAULT 30
30 #define ZIIRAVE_PING_VALUE 0x0
32 #define ZIIRAVE_STATE_INITIAL 0x0
33 #define ZIIRAVE_STATE_OFF 0x1
34 #define ZIIRAVE_STATE_ON 0x2
36 #define ZIIRAVE_FW_NAME "ziirave_wdt.fw"
38 static char *ziirave_reasons
[] = {"power cycle", "hw watchdog", NULL
, NULL
,
39 "host request", NULL
, "illegal configuration",
40 "illegal instruction", "illegal trap",
43 #define ZIIRAVE_WDT_FIRM_VER_MAJOR 0x1
44 #define ZIIRAVE_WDT_BOOT_VER_MAJOR 0x3
45 #define ZIIRAVE_WDT_RESET_REASON 0x5
46 #define ZIIRAVE_WDT_STATE 0x6
47 #define ZIIRAVE_WDT_TIMEOUT 0x7
48 #define ZIIRAVE_WDT_TIME_LEFT 0x8
49 #define ZIIRAVE_WDT_PING 0x9
50 #define ZIIRAVE_WDT_RESET_DURATION 0xa
52 #define ZIIRAVE_FIRM_PKT_TOTAL_SIZE 20
53 #define ZIIRAVE_FIRM_PKT_DATA_SIZE 16
54 #define ZIIRAVE_FIRM_FLASH_MEMORY_START (2 * 0x1600)
55 #define ZIIRAVE_FIRM_FLASH_MEMORY_END (2 * 0x2bbf)
56 #define ZIIRAVE_FIRM_PAGE_SIZE 128
58 /* Received and ready for next Download packet. */
59 #define ZIIRAVE_FIRM_DOWNLOAD_ACK 1
61 /* Firmware commands */
62 #define ZIIRAVE_CMD_DOWNLOAD_START 0x10
63 #define ZIIRAVE_CMD_DOWNLOAD_END 0x11
64 #define ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR 0x12
65 #define ZIIRAVE_CMD_DOWNLOAD_READ_BYTE 0x13
66 #define ZIIRAVE_CMD_RESET_PROCESSOR 0x0b
67 #define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER 0x0c
68 #define ZIIRAVE_CMD_DOWNLOAD_PACKET 0x0e
70 #define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC 1
71 #define ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC 1
73 #define ZIIRAVE_FW_VERSION_FMT "02.%02u.%02u"
74 #define ZIIRAVE_BL_VERSION_FMT "01.%02u.%02u"
76 struct ziirave_wdt_rev
{
81 struct ziirave_wdt_data
{
82 struct mutex sysfs_mutex
;
83 struct watchdog_device wdd
;
84 struct ziirave_wdt_rev bootloader_rev
;
85 struct ziirave_wdt_rev firmware_rev
;
89 static int wdt_timeout
;
90 module_param(wdt_timeout
, int, 0);
91 MODULE_PARM_DESC(wdt_timeout
, "Watchdog timeout in seconds");
93 static int reset_duration
;
94 module_param(reset_duration
, int, 0);
95 MODULE_PARM_DESC(reset_duration
,
96 "Watchdog reset pulse duration in milliseconds");
98 static bool nowayout
= WATCHDOG_NOWAYOUT
;
99 module_param(nowayout
, bool, 0);
100 MODULE_PARM_DESC(nowayout
, "Watchdog cannot be stopped once started default="
101 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
103 static int ziirave_wdt_revision(struct i2c_client
*client
,
104 struct ziirave_wdt_rev
*rev
, u8 command
)
108 ret
= i2c_smbus_read_byte_data(client
, command
);
114 ret
= i2c_smbus_read_byte_data(client
, command
+ 1);
123 static int ziirave_wdt_set_state(struct watchdog_device
*wdd
, int state
)
125 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
127 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_STATE
, state
);
130 static int ziirave_wdt_start(struct watchdog_device
*wdd
)
132 return ziirave_wdt_set_state(wdd
, ZIIRAVE_STATE_ON
);
135 static int ziirave_wdt_stop(struct watchdog_device
*wdd
)
137 return ziirave_wdt_set_state(wdd
, ZIIRAVE_STATE_OFF
);
140 static int ziirave_wdt_ping(struct watchdog_device
*wdd
)
142 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
144 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_PING
,
148 static int ziirave_wdt_set_timeout(struct watchdog_device
*wdd
,
149 unsigned int timeout
)
151 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
154 ret
= i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_TIMEOUT
, timeout
);
156 wdd
->timeout
= timeout
;
161 static unsigned int ziirave_wdt_get_timeleft(struct watchdog_device
*wdd
)
163 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
166 ret
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_TIME_LEFT
);
173 static int ziirave_firm_read_ack(struct watchdog_device
*wdd
)
175 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
178 ret
= i2c_smbus_read_byte(client
);
180 dev_err(&client
->dev
, "Failed to read status byte\n");
184 return ret
== ZIIRAVE_FIRM_DOWNLOAD_ACK
? 0 : -EIO
;
187 static int ziirave_firm_set_read_addr(struct watchdog_device
*wdd
, u32 addr
)
189 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
190 const u16 addr16
= (u16
)addr
/ 2;
193 put_unaligned_le16(addr16
, address
);
195 return i2c_smbus_write_block_data(client
,
196 ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR
,
197 sizeof(address
), address
);
200 static bool ziirave_firm_addr_readonly(u32 addr
)
202 return addr
< ZIIRAVE_FIRM_FLASH_MEMORY_START
||
203 addr
> ZIIRAVE_FIRM_FLASH_MEMORY_END
;
207 * ziirave_firm_write_pkt() - Build and write a firmware packet
209 * A packet to send to the firmware is composed by following bytes:
210 * Length | Addr0 | Addr1 | Data0 .. Data15 | Checksum |
212 * Length: A data byte containing the length of the data.
213 * Addr0: Low byte of the address.
214 * Addr1: High byte of the address.
215 * Data0 .. Data15: Array of 16 bytes of data.
216 * Checksum: Checksum byte to verify data integrity.
218 static int __ziirave_firm_write_pkt(struct watchdog_device
*wdd
,
219 u32 addr
, const u8
*data
, u8 len
)
221 const u16 addr16
= (u16
)addr
/ 2;
222 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
223 u8 i
, checksum
= 0, packet
[ZIIRAVE_FIRM_PKT_TOTAL_SIZE
];
226 /* Check max data size */
227 if (len
> ZIIRAVE_FIRM_PKT_DATA_SIZE
) {
228 dev_err(&client
->dev
, "Firmware packet too long (%d)\n",
234 * Ignore packets that are targeting program memory outisde of
235 * app partition, since they will be ignored by the
236 * bootloader. At the same time, we need to make sure we'll
237 * allow zero length packet that will be sent as the last step
240 if (len
&& ziirave_firm_addr_readonly(addr
))
246 put_unaligned_le16(addr16
, packet
+ 1);
248 memcpy(packet
+ 3, data
, len
);
249 memset(packet
+ 3 + len
, 0, ZIIRAVE_FIRM_PKT_DATA_SIZE
- len
);
251 /* Packet checksum */
252 for (i
= 0; i
< len
+ 3; i
++)
253 checksum
+= packet
[i
];
254 packet
[ZIIRAVE_FIRM_PKT_TOTAL_SIZE
- 1] = checksum
;
256 ret
= i2c_smbus_write_block_data(client
, ZIIRAVE_CMD_DOWNLOAD_PACKET
,
257 sizeof(packet
), packet
);
259 dev_err(&client
->dev
,
260 "Failed to send DOWNLOAD_PACKET: %d\n", ret
);
264 ret
= ziirave_firm_read_ack(wdd
);
266 dev_err(&client
->dev
,
267 "Failed to write firmware packet at address 0x%04x: %d\n",
273 static int ziirave_firm_write_pkt(struct watchdog_device
*wdd
,
274 u32 addr
, const u8
*data
, u8 len
)
276 const u8 max_write_len
= ZIIRAVE_FIRM_PAGE_SIZE
-
277 (addr
- ALIGN_DOWN(addr
, ZIIRAVE_FIRM_PAGE_SIZE
));
280 if (len
> max_write_len
) {
282 * If data crossed page boundary we need to split this
285 ret
= __ziirave_firm_write_pkt(wdd
, addr
, data
, max_write_len
);
289 addr
+= max_write_len
;
290 data
+= max_write_len
;
291 len
-= max_write_len
;
294 return __ziirave_firm_write_pkt(wdd
, addr
, data
, len
);
297 static int ziirave_firm_verify(struct watchdog_device
*wdd
,
298 const struct firmware
*fw
)
300 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
301 const struct ihex_binrec
*rec
;
303 u8 data
[ZIIRAVE_FIRM_PKT_DATA_SIZE
];
305 for (rec
= (void *)fw
->data
; rec
; rec
= ihex_next_binrec(rec
)) {
306 const u16 len
= be16_to_cpu(rec
->len
);
307 const u32 addr
= be32_to_cpu(rec
->addr
);
309 if (ziirave_firm_addr_readonly(addr
))
312 ret
= ziirave_firm_set_read_addr(wdd
, addr
);
314 dev_err(&client
->dev
,
315 "Failed to send SET_READ_ADDR command: %d\n",
320 for (i
= 0; i
< len
; i
++) {
321 ret
= i2c_smbus_read_byte_data(client
,
322 ZIIRAVE_CMD_DOWNLOAD_READ_BYTE
);
324 dev_err(&client
->dev
,
325 "Failed to READ DATA: %d\n", ret
);
331 if (memcmp(data
, rec
->data
, len
)) {
332 dev_err(&client
->dev
,
333 "Firmware mismatch at address 0x%04x\n", addr
);
341 static int ziirave_firm_upload(struct watchdog_device
*wdd
,
342 const struct firmware
*fw
)
344 struct i2c_client
*client
= to_i2c_client(wdd
->parent
);
345 const struct ihex_binrec
*rec
;
348 ret
= i2c_smbus_write_byte_data(client
,
349 ZIIRAVE_CMD_JUMP_TO_BOOTLOADER
,
350 ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC
);
352 dev_err(&client
->dev
, "Failed to jump to bootloader\n");
358 ret
= i2c_smbus_write_byte(client
, ZIIRAVE_CMD_DOWNLOAD_START
);
360 dev_err(&client
->dev
, "Failed to start download\n");
364 ret
= ziirave_firm_read_ack(wdd
);
366 dev_err(&client
->dev
, "No ACK for start download\n");
372 for (rec
= (void *)fw
->data
; rec
; rec
= ihex_next_binrec(rec
)) {
373 ret
= ziirave_firm_write_pkt(wdd
, be32_to_cpu(rec
->addr
),
374 rec
->data
, be16_to_cpu(rec
->len
));
380 * Finish firmware download process by sending a zero length
383 ret
= ziirave_firm_write_pkt(wdd
, 0, NULL
, 0);
385 dev_err(&client
->dev
, "Failed to send EMPTY packet: %d\n", ret
);
389 /* This sleep seems to be required */
392 /* Start firmware verification */
393 ret
= ziirave_firm_verify(wdd
, fw
);
395 dev_err(&client
->dev
,
396 "Failed to verify firmware: %d\n", ret
);
400 /* End download operation */
401 ret
= i2c_smbus_write_byte(client
, ZIIRAVE_CMD_DOWNLOAD_END
);
403 dev_err(&client
->dev
,
404 "Failed to end firmware download: %d\n", ret
);
408 /* Reset the processor */
409 ret
= i2c_smbus_write_byte_data(client
,
410 ZIIRAVE_CMD_RESET_PROCESSOR
,
411 ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC
);
413 dev_err(&client
->dev
,
414 "Failed to reset the watchdog: %d\n", ret
);
423 static const struct watchdog_info ziirave_wdt_info
= {
424 .options
= WDIOF_SETTIMEOUT
| WDIOF_MAGICCLOSE
| WDIOF_KEEPALIVEPING
,
425 .identity
= "RAVE Switch Watchdog",
428 static const struct watchdog_ops ziirave_wdt_ops
= {
429 .owner
= THIS_MODULE
,
430 .start
= ziirave_wdt_start
,
431 .stop
= ziirave_wdt_stop
,
432 .ping
= ziirave_wdt_ping
,
433 .set_timeout
= ziirave_wdt_set_timeout
,
434 .get_timeleft
= ziirave_wdt_get_timeleft
,
437 static ssize_t
ziirave_wdt_sysfs_show_firm(struct device
*dev
,
438 struct device_attribute
*attr
,
441 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
442 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
445 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
449 ret
= sprintf(buf
, ZIIRAVE_FW_VERSION_FMT
, w_priv
->firmware_rev
.major
,
450 w_priv
->firmware_rev
.minor
);
452 mutex_unlock(&w_priv
->sysfs_mutex
);
457 static DEVICE_ATTR(firmware_version
, S_IRUGO
, ziirave_wdt_sysfs_show_firm
,
460 static ssize_t
ziirave_wdt_sysfs_show_boot(struct device
*dev
,
461 struct device_attribute
*attr
,
464 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
465 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
468 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
472 ret
= sprintf(buf
, ZIIRAVE_BL_VERSION_FMT
, w_priv
->bootloader_rev
.major
,
473 w_priv
->bootloader_rev
.minor
);
475 mutex_unlock(&w_priv
->sysfs_mutex
);
480 static DEVICE_ATTR(bootloader_version
, S_IRUGO
, ziirave_wdt_sysfs_show_boot
,
483 static ssize_t
ziirave_wdt_sysfs_show_reason(struct device
*dev
,
484 struct device_attribute
*attr
,
487 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
488 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
491 ret
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
495 ret
= sprintf(buf
, "%s", ziirave_reasons
[w_priv
->reset_reason
]);
497 mutex_unlock(&w_priv
->sysfs_mutex
);
502 static DEVICE_ATTR(reset_reason
, S_IRUGO
, ziirave_wdt_sysfs_show_reason
,
505 static ssize_t
ziirave_wdt_sysfs_store_firm(struct device
*dev
,
506 struct device_attribute
*attr
,
507 const char *buf
, size_t count
)
509 struct i2c_client
*client
= to_i2c_client(dev
->parent
);
510 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
511 const struct firmware
*fw
;
514 err
= request_ihex_firmware(&fw
, ZIIRAVE_FW_NAME
, dev
);
516 dev_err(&client
->dev
, "Failed to request ihex firmware\n");
520 err
= mutex_lock_interruptible(&w_priv
->sysfs_mutex
);
522 goto release_firmware
;
524 err
= ziirave_firm_upload(&w_priv
->wdd
, fw
);
526 dev_err(&client
->dev
, "The firmware update failed: %d\n", err
);
530 /* Update firmware version */
531 err
= ziirave_wdt_revision(client
, &w_priv
->firmware_rev
,
532 ZIIRAVE_WDT_FIRM_VER_MAJOR
);
534 dev_err(&client
->dev
, "Failed to read firmware version: %d\n",
539 dev_info(&client
->dev
,
540 "Firmware updated to version " ZIIRAVE_FW_VERSION_FMT
"\n",
541 w_priv
->firmware_rev
.major
, w_priv
->firmware_rev
.minor
);
543 /* Restore the watchdog timeout */
544 err
= ziirave_wdt_set_timeout(&w_priv
->wdd
, w_priv
->wdd
.timeout
);
546 dev_err(&client
->dev
, "Failed to set timeout: %d\n", err
);
549 mutex_unlock(&w_priv
->sysfs_mutex
);
552 release_firmware(fw
);
554 return err
? err
: count
;
557 static DEVICE_ATTR(update_firmware
, S_IWUSR
, NULL
,
558 ziirave_wdt_sysfs_store_firm
);
560 static struct attribute
*ziirave_wdt_attrs
[] = {
561 &dev_attr_firmware_version
.attr
,
562 &dev_attr_bootloader_version
.attr
,
563 &dev_attr_reset_reason
.attr
,
564 &dev_attr_update_firmware
.attr
,
567 ATTRIBUTE_GROUPS(ziirave_wdt
);
569 static int ziirave_wdt_init_duration(struct i2c_client
*client
)
573 if (!reset_duration
) {
574 /* See if the reset pulse duration is provided in an of_node */
575 if (!client
->dev
.of_node
)
578 ret
= of_property_read_u32(client
->dev
.of_node
,
582 dev_info(&client
->dev
,
583 "No reset pulse duration specified, using default\n");
588 if (reset_duration
< 1 || reset_duration
> 255)
591 dev_info(&client
->dev
, "Setting reset duration to %dms",
594 return i2c_smbus_write_byte_data(client
, ZIIRAVE_WDT_RESET_DURATION
,
598 static int ziirave_wdt_probe(struct i2c_client
*client
,
599 const struct i2c_device_id
*id
)
602 struct ziirave_wdt_data
*w_priv
;
605 if (!i2c_check_functionality(client
->adapter
,
606 I2C_FUNC_SMBUS_BYTE
|
607 I2C_FUNC_SMBUS_BYTE_DATA
|
608 I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
))
611 w_priv
= devm_kzalloc(&client
->dev
, sizeof(*w_priv
), GFP_KERNEL
);
615 mutex_init(&w_priv
->sysfs_mutex
);
617 w_priv
->wdd
.info
= &ziirave_wdt_info
;
618 w_priv
->wdd
.ops
= &ziirave_wdt_ops
;
619 w_priv
->wdd
.min_timeout
= ZIIRAVE_TIMEOUT_MIN
;
620 w_priv
->wdd
.max_timeout
= ZIIRAVE_TIMEOUT_MAX
;
621 w_priv
->wdd
.parent
= &client
->dev
;
622 w_priv
->wdd
.groups
= ziirave_wdt_groups
;
624 watchdog_init_timeout(&w_priv
->wdd
, wdt_timeout
, &client
->dev
);
627 * The default value set in the watchdog should be perfectly valid, so
628 * pass that in if we haven't provided one via the module parameter or
631 if (w_priv
->wdd
.timeout
== 0) {
632 val
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_TIMEOUT
);
634 dev_err(&client
->dev
, "Failed to read timeout\n");
638 if (val
> ZIIRAVE_TIMEOUT_MAX
||
639 val
< ZIIRAVE_TIMEOUT_MIN
)
640 val
= ZIIRAVE_TIMEOUT_DEFAULT
;
642 w_priv
->wdd
.timeout
= val
;
645 ret
= ziirave_wdt_set_timeout(&w_priv
->wdd
, w_priv
->wdd
.timeout
);
647 dev_err(&client
->dev
, "Failed to set timeout\n");
651 dev_info(&client
->dev
, "Timeout set to %ds\n", w_priv
->wdd
.timeout
);
653 watchdog_set_nowayout(&w_priv
->wdd
, nowayout
);
655 i2c_set_clientdata(client
, w_priv
);
657 /* If in unconfigured state, set to stopped */
658 val
= i2c_smbus_read_byte_data(client
, ZIIRAVE_WDT_STATE
);
660 dev_err(&client
->dev
, "Failed to read state\n");
664 if (val
== ZIIRAVE_STATE_INITIAL
)
665 ziirave_wdt_stop(&w_priv
->wdd
);
667 ret
= ziirave_wdt_init_duration(client
);
669 dev_err(&client
->dev
, "Failed to init duration\n");
673 ret
= ziirave_wdt_revision(client
, &w_priv
->firmware_rev
,
674 ZIIRAVE_WDT_FIRM_VER_MAJOR
);
676 dev_err(&client
->dev
, "Failed to read firmware version\n");
680 dev_info(&client
->dev
,
681 "Firmware version: " ZIIRAVE_FW_VERSION_FMT
"\n",
682 w_priv
->firmware_rev
.major
, w_priv
->firmware_rev
.minor
);
684 ret
= ziirave_wdt_revision(client
, &w_priv
->bootloader_rev
,
685 ZIIRAVE_WDT_BOOT_VER_MAJOR
);
687 dev_err(&client
->dev
, "Failed to read bootloader version\n");
691 dev_info(&client
->dev
,
692 "Bootloader version: " ZIIRAVE_BL_VERSION_FMT
"\n",
693 w_priv
->bootloader_rev
.major
, w_priv
->bootloader_rev
.minor
);
695 w_priv
->reset_reason
= i2c_smbus_read_byte_data(client
,
696 ZIIRAVE_WDT_RESET_REASON
);
697 if (w_priv
->reset_reason
< 0) {
698 dev_err(&client
->dev
, "Failed to read reset reason\n");
699 return w_priv
->reset_reason
;
702 if (w_priv
->reset_reason
>= ARRAY_SIZE(ziirave_reasons
) ||
703 !ziirave_reasons
[w_priv
->reset_reason
]) {
704 dev_err(&client
->dev
, "Invalid reset reason\n");
708 ret
= watchdog_register_device(&w_priv
->wdd
);
713 static int ziirave_wdt_remove(struct i2c_client
*client
)
715 struct ziirave_wdt_data
*w_priv
= i2c_get_clientdata(client
);
717 watchdog_unregister_device(&w_priv
->wdd
);
722 static const struct i2c_device_id ziirave_wdt_id
[] = {
726 MODULE_DEVICE_TABLE(i2c
, ziirave_wdt_id
);
728 static const struct of_device_id zrv_wdt_of_match
[] = {
729 { .compatible
= "zii,rave-wdt", },
732 MODULE_DEVICE_TABLE(of
, zrv_wdt_of_match
);
734 static struct i2c_driver ziirave_wdt_driver
= {
736 .name
= "ziirave_wdt",
737 .of_match_table
= zrv_wdt_of_match
,
739 .probe
= ziirave_wdt_probe
,
740 .remove
= ziirave_wdt_remove
,
741 .id_table
= ziirave_wdt_id
,
744 module_i2c_driver(ziirave_wdt_driver
);
746 MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk");
747 MODULE_DESCRIPTION("Zodiac Aerospace RAVE Switch Watchdog Processor Driver");
748 MODULE_LICENSE("GPL");