744 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2015 Zodiac Inflight Innovations4 *5 * Author: Martyn Welch <martyn.welch@collabora.co.uk>6 *7 * Based on twl4030_wdt.c by Timo Kokkonen <timo.t.kokkonen at nokia.com>:8 *9 * Copyright (C) Nokia Corporation10 */11 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/watchdog.h>22 23#include <linux/unaligned.h>24 25#define ZIIRAVE_TIMEOUT_MIN 326#define ZIIRAVE_TIMEOUT_MAX 25527#define ZIIRAVE_TIMEOUT_DEFAULT 3028 29#define ZIIRAVE_PING_VALUE 0x030 31#define ZIIRAVE_STATE_INITIAL 0x032#define ZIIRAVE_STATE_OFF 0x133#define ZIIRAVE_STATE_ON 0x234 35#define ZIIRAVE_FW_NAME "ziirave_wdt.fw"36 37static char *ziirave_reasons[] = {"power cycle", "hw watchdog", NULL, NULL,38 "host request", NULL, "illegal configuration",39 "illegal instruction", "illegal trap",40 "unknown"};41 42#define ZIIRAVE_WDT_FIRM_VER_MAJOR 0x143#define ZIIRAVE_WDT_BOOT_VER_MAJOR 0x344#define ZIIRAVE_WDT_RESET_REASON 0x545#define ZIIRAVE_WDT_STATE 0x646#define ZIIRAVE_WDT_TIMEOUT 0x747#define ZIIRAVE_WDT_TIME_LEFT 0x848#define ZIIRAVE_WDT_PING 0x949#define ZIIRAVE_WDT_RESET_DURATION 0xa50 51#define ZIIRAVE_FIRM_PKT_TOTAL_SIZE 2052#define ZIIRAVE_FIRM_PKT_DATA_SIZE 1653#define ZIIRAVE_FIRM_FLASH_MEMORY_START (2 * 0x1600)54#define ZIIRAVE_FIRM_FLASH_MEMORY_END (2 * 0x2bbf)55#define ZIIRAVE_FIRM_PAGE_SIZE 12856 57/* Received and ready for next Download packet. */58#define ZIIRAVE_FIRM_DOWNLOAD_ACK 159 60/* Firmware commands */61#define ZIIRAVE_CMD_DOWNLOAD_START 0x1062#define ZIIRAVE_CMD_DOWNLOAD_END 0x1163#define ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR 0x1264#define ZIIRAVE_CMD_DOWNLOAD_READ_BYTE 0x1365#define ZIIRAVE_CMD_RESET_PROCESSOR 0x0b66#define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER 0x0c67#define ZIIRAVE_CMD_DOWNLOAD_PACKET 0x0e68 69#define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC 170#define ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC 171 72struct ziirave_wdt_rev {73 unsigned char major;74 unsigned char minor;75};76 77struct ziirave_wdt_data {78 struct mutex sysfs_mutex;79 struct watchdog_device wdd;80 struct ziirave_wdt_rev bootloader_rev;81 struct ziirave_wdt_rev firmware_rev;82 int reset_reason;83};84 85static int wdt_timeout;86module_param(wdt_timeout, int, 0);87MODULE_PARM_DESC(wdt_timeout, "Watchdog timeout in seconds");88 89static int reset_duration;90module_param(reset_duration, int, 0);91MODULE_PARM_DESC(reset_duration,92 "Watchdog reset pulse duration in milliseconds");93 94static bool nowayout = WATCHDOG_NOWAYOUT;95module_param(nowayout, bool, 0);96MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started default="97 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");98 99static int ziirave_wdt_revision(struct i2c_client *client,100 struct ziirave_wdt_rev *rev, u8 command)101{102 int ret;103 104 ret = i2c_smbus_read_byte_data(client, command);105 if (ret < 0)106 return ret;107 108 rev->major = ret;109 110 ret = i2c_smbus_read_byte_data(client, command + 1);111 if (ret < 0)112 return ret;113 114 rev->minor = ret;115 116 return 0;117}118 119static int ziirave_wdt_set_state(struct watchdog_device *wdd, int state)120{121 struct i2c_client *client = to_i2c_client(wdd->parent);122 123 return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_STATE, state);124}125 126static int ziirave_wdt_start(struct watchdog_device *wdd)127{128 return ziirave_wdt_set_state(wdd, ZIIRAVE_STATE_ON);129}130 131static int ziirave_wdt_stop(struct watchdog_device *wdd)132{133 return ziirave_wdt_set_state(wdd, ZIIRAVE_STATE_OFF);134}135 136static int ziirave_wdt_ping(struct watchdog_device *wdd)137{138 struct i2c_client *client = to_i2c_client(wdd->parent);139 140 return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_PING,141 ZIIRAVE_PING_VALUE);142}143 144static int ziirave_wdt_set_timeout(struct watchdog_device *wdd,145 unsigned int timeout)146{147 struct i2c_client *client = to_i2c_client(wdd->parent);148 int ret;149 150 ret = i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_TIMEOUT, timeout);151 if (!ret)152 wdd->timeout = timeout;153 154 return ret;155}156 157static unsigned int ziirave_wdt_get_timeleft(struct watchdog_device *wdd)158{159 struct i2c_client *client = to_i2c_client(wdd->parent);160 int ret;161 162 ret = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_TIME_LEFT);163 if (ret < 0)164 ret = 0;165 166 return ret;167}168 169static int ziirave_firm_read_ack(struct watchdog_device *wdd)170{171 struct i2c_client *client = to_i2c_client(wdd->parent);172 int ret;173 174 ret = i2c_smbus_read_byte(client);175 if (ret < 0) {176 dev_err(&client->dev, "Failed to read status byte\n");177 return ret;178 }179 180 return ret == ZIIRAVE_FIRM_DOWNLOAD_ACK ? 0 : -EIO;181}182 183static int ziirave_firm_set_read_addr(struct watchdog_device *wdd, u32 addr)184{185 struct i2c_client *client = to_i2c_client(wdd->parent);186 const u16 addr16 = (u16)addr / 2;187 u8 address[2];188 189 put_unaligned_le16(addr16, address);190 191 return i2c_smbus_write_block_data(client,192 ZIIRAVE_CMD_DOWNLOAD_SET_READ_ADDR,193 sizeof(address), address);194}195 196static bool ziirave_firm_addr_readonly(u32 addr)197{198 return addr < ZIIRAVE_FIRM_FLASH_MEMORY_START ||199 addr > ZIIRAVE_FIRM_FLASH_MEMORY_END;200}201 202/*203 * ziirave_firm_write_pkt() - Build and write a firmware packet204 *205 * A packet to send to the firmware is composed by following bytes:206 * Length | Addr0 | Addr1 | Data0 .. Data15 | Checksum |207 * Where,208 * Length: A data byte containing the length of the data.209 * Addr0: Low byte of the address.210 * Addr1: High byte of the address.211 * Data0 .. Data15: Array of 16 bytes of data.212 * Checksum: Checksum byte to verify data integrity.213 */214static int __ziirave_firm_write_pkt(struct watchdog_device *wdd,215 u32 addr, const u8 *data, u8 len)216{217 const u16 addr16 = (u16)addr / 2;218 struct i2c_client *client = to_i2c_client(wdd->parent);219 u8 i, checksum = 0, packet[ZIIRAVE_FIRM_PKT_TOTAL_SIZE];220 int ret;221 222 /* Check max data size */223 if (len > ZIIRAVE_FIRM_PKT_DATA_SIZE) {224 dev_err(&client->dev, "Firmware packet too long (%d)\n",225 len);226 return -EMSGSIZE;227 }228 229 /*230 * Ignore packets that are targeting program memory outisde of231 * app partition, since they will be ignored by the232 * bootloader. At the same time, we need to make sure we'll233 * allow zero length packet that will be sent as the last step234 * of firmware update235 */236 if (len && ziirave_firm_addr_readonly(addr))237 return 0;238 239 /* Packet length */240 packet[0] = len;241 /* Packet address */242 put_unaligned_le16(addr16, packet + 1);243 244 memcpy(packet + 3, data, len);245 memset(packet + 3 + len, 0, ZIIRAVE_FIRM_PKT_DATA_SIZE - len);246 247 /* Packet checksum */248 for (i = 0; i < len + 3; i++)249 checksum += packet[i];250 packet[ZIIRAVE_FIRM_PKT_TOTAL_SIZE - 1] = checksum;251 252 ret = i2c_smbus_write_block_data(client, ZIIRAVE_CMD_DOWNLOAD_PACKET,253 sizeof(packet), packet);254 if (ret) {255 dev_err(&client->dev,256 "Failed to send DOWNLOAD_PACKET: %d\n", ret);257 return ret;258 }259 260 ret = ziirave_firm_read_ack(wdd);261 if (ret)262 dev_err(&client->dev,263 "Failed to write firmware packet at address 0x%04x: %d\n",264 addr, ret);265 266 return ret;267}268 269static int ziirave_firm_write_pkt(struct watchdog_device *wdd,270 u32 addr, const u8 *data, u8 len)271{272 const u8 max_write_len = ZIIRAVE_FIRM_PAGE_SIZE -273 (addr - ALIGN_DOWN(addr, ZIIRAVE_FIRM_PAGE_SIZE));274 int ret;275 276 if (len > max_write_len) {277 /*278 * If data crossed page boundary we need to split this279 * write in two280 */281 ret = __ziirave_firm_write_pkt(wdd, addr, data, max_write_len);282 if (ret)283 return ret;284 285 addr += max_write_len;286 data += max_write_len;287 len -= max_write_len;288 }289 290 return __ziirave_firm_write_pkt(wdd, addr, data, len);291}292 293static int ziirave_firm_verify(struct watchdog_device *wdd,294 const struct firmware *fw)295{296 struct i2c_client *client = to_i2c_client(wdd->parent);297 const struct ihex_binrec *rec;298 int i, ret;299 u8 data[ZIIRAVE_FIRM_PKT_DATA_SIZE];300 301 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {302 const u16 len = be16_to_cpu(rec->len);303 const u32 addr = be32_to_cpu(rec->addr);304 305 if (ziirave_firm_addr_readonly(addr))306 continue;307 308 ret = ziirave_firm_set_read_addr(wdd, addr);309 if (ret) {310 dev_err(&client->dev,311 "Failed to send SET_READ_ADDR command: %d\n",312 ret);313 return ret;314 }315 316 for (i = 0; i < len; i++) {317 ret = i2c_smbus_read_byte_data(client,318 ZIIRAVE_CMD_DOWNLOAD_READ_BYTE);319 if (ret < 0) {320 dev_err(&client->dev,321 "Failed to READ DATA: %d\n", ret);322 return ret;323 }324 data[i] = ret;325 }326 327 if (memcmp(data, rec->data, len)) {328 dev_err(&client->dev,329 "Firmware mismatch at address 0x%04x\n", addr);330 return -EINVAL;331 }332 }333 334 return 0;335}336 337static int ziirave_firm_upload(struct watchdog_device *wdd,338 const struct firmware *fw)339{340 struct i2c_client *client = to_i2c_client(wdd->parent);341 const struct ihex_binrec *rec;342 int ret;343 344 ret = i2c_smbus_write_byte_data(client,345 ZIIRAVE_CMD_JUMP_TO_BOOTLOADER,346 ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC);347 if (ret) {348 dev_err(&client->dev, "Failed to jump to bootloader\n");349 return ret;350 }351 352 msleep(500);353 354 ret = i2c_smbus_write_byte(client, ZIIRAVE_CMD_DOWNLOAD_START);355 if (ret) {356 dev_err(&client->dev, "Failed to start download\n");357 return ret;358 }359 360 ret = ziirave_firm_read_ack(wdd);361 if (ret) {362 dev_err(&client->dev, "No ACK for start download\n");363 return ret;364 }365 366 msleep(500);367 368 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {369 ret = ziirave_firm_write_pkt(wdd, be32_to_cpu(rec->addr),370 rec->data, be16_to_cpu(rec->len));371 if (ret)372 return ret;373 }374 375 /*376 * Finish firmware download process by sending a zero length377 * payload378 */379 ret = ziirave_firm_write_pkt(wdd, 0, NULL, 0);380 if (ret) {381 dev_err(&client->dev, "Failed to send EMPTY packet: %d\n", ret);382 return ret;383 }384 385 /* This sleep seems to be required */386 msleep(20);387 388 /* Start firmware verification */389 ret = ziirave_firm_verify(wdd, fw);390 if (ret) {391 dev_err(&client->dev,392 "Failed to verify firmware: %d\n", ret);393 return ret;394 }395 396 /* End download operation */397 ret = i2c_smbus_write_byte(client, ZIIRAVE_CMD_DOWNLOAD_END);398 if (ret) {399 dev_err(&client->dev,400 "Failed to end firmware download: %d\n", ret);401 return ret;402 }403 404 /* Reset the processor */405 ret = i2c_smbus_write_byte_data(client,406 ZIIRAVE_CMD_RESET_PROCESSOR,407 ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC);408 if (ret) {409 dev_err(&client->dev,410 "Failed to reset the watchdog: %d\n", ret);411 return ret;412 }413 414 msleep(500);415 416 return 0;417}418 419static const struct watchdog_info ziirave_wdt_info = {420 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,421 .identity = "RAVE Switch Watchdog",422};423 424static const struct watchdog_ops ziirave_wdt_ops = {425 .owner = THIS_MODULE,426 .start = ziirave_wdt_start,427 .stop = ziirave_wdt_stop,428 .ping = ziirave_wdt_ping,429 .set_timeout = ziirave_wdt_set_timeout,430 .get_timeleft = ziirave_wdt_get_timeleft,431};432 433static ssize_t ziirave_wdt_sysfs_show_firm(struct device *dev,434 struct device_attribute *attr,435 char *buf)436{437 struct i2c_client *client = to_i2c_client(dev->parent);438 struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client);439 int ret;440 441 ret = mutex_lock_interruptible(&w_priv->sysfs_mutex);442 if (ret)443 return ret;444 445 ret = sysfs_emit(buf, "02.%02u.%02u\n",446 w_priv->firmware_rev.major,447 w_priv->firmware_rev.minor);448 449 mutex_unlock(&w_priv->sysfs_mutex);450 451 return ret;452}453 454static DEVICE_ATTR(firmware_version, S_IRUGO, ziirave_wdt_sysfs_show_firm,455 NULL);456 457static ssize_t ziirave_wdt_sysfs_show_boot(struct device *dev,458 struct device_attribute *attr,459 char *buf)460{461 struct i2c_client *client = to_i2c_client(dev->parent);462 struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client);463 int ret;464 465 ret = mutex_lock_interruptible(&w_priv->sysfs_mutex);466 if (ret)467 return ret;468 469 ret = sysfs_emit(buf, "01.%02u.%02u\n",470 w_priv->bootloader_rev.major,471 w_priv->bootloader_rev.minor);472 473 mutex_unlock(&w_priv->sysfs_mutex);474 475 return ret;476}477 478static DEVICE_ATTR(bootloader_version, S_IRUGO, ziirave_wdt_sysfs_show_boot,479 NULL);480 481static ssize_t ziirave_wdt_sysfs_show_reason(struct device *dev,482 struct device_attribute *attr,483 char *buf)484{485 struct i2c_client *client = to_i2c_client(dev->parent);486 struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client);487 int ret;488 489 ret = mutex_lock_interruptible(&w_priv->sysfs_mutex);490 if (ret)491 return ret;492 493 ret = sysfs_emit(buf, "%s\n", ziirave_reasons[w_priv->reset_reason]);494 495 mutex_unlock(&w_priv->sysfs_mutex);496 497 return ret;498}499 500static DEVICE_ATTR(reset_reason, S_IRUGO, ziirave_wdt_sysfs_show_reason,501 NULL);502 503static ssize_t ziirave_wdt_sysfs_store_firm(struct device *dev,504 struct device_attribute *attr,505 const char *buf, size_t count)506{507 struct i2c_client *client = to_i2c_client(dev->parent);508 struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client);509 const struct firmware *fw;510 int err;511 512 err = request_ihex_firmware(&fw, ZIIRAVE_FW_NAME, dev);513 if (err) {514 dev_err(&client->dev, "Failed to request ihex firmware\n");515 return err;516 }517 518 err = mutex_lock_interruptible(&w_priv->sysfs_mutex);519 if (err)520 goto release_firmware;521 522 err = ziirave_firm_upload(&w_priv->wdd, fw);523 if (err) {524 dev_err(&client->dev, "The firmware update failed: %d\n", err);525 goto unlock_mutex;526 }527 528 /* Update firmware version */529 err = ziirave_wdt_revision(client, &w_priv->firmware_rev,530 ZIIRAVE_WDT_FIRM_VER_MAJOR);531 if (err) {532 dev_err(&client->dev, "Failed to read firmware version: %d\n",533 err);534 goto unlock_mutex;535 }536 537 dev_info(&client->dev,538 "Firmware updated to version 02.%02u.%02u\n",539 w_priv->firmware_rev.major, w_priv->firmware_rev.minor);540 541 /* Restore the watchdog timeout */542 err = ziirave_wdt_set_timeout(&w_priv->wdd, w_priv->wdd.timeout);543 if (err)544 dev_err(&client->dev, "Failed to set timeout: %d\n", err);545 546unlock_mutex:547 mutex_unlock(&w_priv->sysfs_mutex);548 549release_firmware:550 release_firmware(fw);551 552 return err ? err : count;553}554 555static DEVICE_ATTR(update_firmware, S_IWUSR, NULL,556 ziirave_wdt_sysfs_store_firm);557 558static struct attribute *ziirave_wdt_attrs[] = {559 &dev_attr_firmware_version.attr,560 &dev_attr_bootloader_version.attr,561 &dev_attr_reset_reason.attr,562 &dev_attr_update_firmware.attr,563 NULL564};565ATTRIBUTE_GROUPS(ziirave_wdt);566 567static int ziirave_wdt_init_duration(struct i2c_client *client)568{569 int ret;570 571 if (!reset_duration) {572 /* See if the reset pulse duration is provided in an of_node */573 if (!client->dev.of_node)574 ret = -ENODEV;575 else576 ret = of_property_read_u32(client->dev.of_node,577 "reset-duration-ms",578 &reset_duration);579 if (ret) {580 dev_info(&client->dev,581 "No reset pulse duration specified, using default\n");582 return 0;583 }584 }585 586 if (reset_duration < 1 || reset_duration > 255)587 return -EINVAL;588 589 dev_info(&client->dev, "Setting reset duration to %dms",590 reset_duration);591 592 return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_RESET_DURATION,593 reset_duration);594}595 596static int ziirave_wdt_probe(struct i2c_client *client)597{598 int ret;599 struct ziirave_wdt_data *w_priv;600 int val;601 602 if (!i2c_check_functionality(client->adapter,603 I2C_FUNC_SMBUS_BYTE |604 I2C_FUNC_SMBUS_BYTE_DATA |605 I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))606 return -ENODEV;607 608 w_priv = devm_kzalloc(&client->dev, sizeof(*w_priv), GFP_KERNEL);609 if (!w_priv)610 return -ENOMEM;611 612 mutex_init(&w_priv->sysfs_mutex);613 614 w_priv->wdd.info = &ziirave_wdt_info;615 w_priv->wdd.ops = &ziirave_wdt_ops;616 w_priv->wdd.min_timeout = ZIIRAVE_TIMEOUT_MIN;617 w_priv->wdd.max_timeout = ZIIRAVE_TIMEOUT_MAX;618 w_priv->wdd.parent = &client->dev;619 w_priv->wdd.groups = ziirave_wdt_groups;620 621 watchdog_init_timeout(&w_priv->wdd, wdt_timeout, &client->dev);622 623 /*624 * The default value set in the watchdog should be perfectly valid, so625 * pass that in if we haven't provided one via the module parameter or626 * of property.627 */628 if (w_priv->wdd.timeout == 0) {629 val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_TIMEOUT);630 if (val < 0) {631 dev_err(&client->dev, "Failed to read timeout\n");632 return val;633 }634 635 if (val > ZIIRAVE_TIMEOUT_MAX ||636 val < ZIIRAVE_TIMEOUT_MIN)637 val = ZIIRAVE_TIMEOUT_DEFAULT;638 639 w_priv->wdd.timeout = val;640 }641 642 ret = ziirave_wdt_set_timeout(&w_priv->wdd, w_priv->wdd.timeout);643 if (ret) {644 dev_err(&client->dev, "Failed to set timeout\n");645 return ret;646 }647 648 dev_info(&client->dev, "Timeout set to %ds\n", w_priv->wdd.timeout);649 650 watchdog_set_nowayout(&w_priv->wdd, nowayout);651 652 i2c_set_clientdata(client, w_priv);653 654 /* If in unconfigured state, set to stopped */655 val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_STATE);656 if (val < 0) {657 dev_err(&client->dev, "Failed to read state\n");658 return val;659 }660 661 if (val == ZIIRAVE_STATE_INITIAL)662 ziirave_wdt_stop(&w_priv->wdd);663 664 ret = ziirave_wdt_init_duration(client);665 if (ret) {666 dev_err(&client->dev, "Failed to init duration\n");667 return ret;668 }669 670 ret = ziirave_wdt_revision(client, &w_priv->firmware_rev,671 ZIIRAVE_WDT_FIRM_VER_MAJOR);672 if (ret) {673 dev_err(&client->dev, "Failed to read firmware version\n");674 return ret;675 }676 677 dev_info(&client->dev,678 "Firmware version: 02.%02u.%02u\n",679 w_priv->firmware_rev.major, w_priv->firmware_rev.minor);680 681 ret = ziirave_wdt_revision(client, &w_priv->bootloader_rev,682 ZIIRAVE_WDT_BOOT_VER_MAJOR);683 if (ret) {684 dev_err(&client->dev, "Failed to read bootloader version\n");685 return ret;686 }687 688 dev_info(&client->dev,689 "Bootloader version: 01.%02u.%02u\n",690 w_priv->bootloader_rev.major, w_priv->bootloader_rev.minor);691 692 w_priv->reset_reason = i2c_smbus_read_byte_data(client,693 ZIIRAVE_WDT_RESET_REASON);694 if (w_priv->reset_reason < 0) {695 dev_err(&client->dev, "Failed to read reset reason\n");696 return w_priv->reset_reason;697 }698 699 if (w_priv->reset_reason >= ARRAY_SIZE(ziirave_reasons) ||700 !ziirave_reasons[w_priv->reset_reason]) {701 dev_err(&client->dev, "Invalid reset reason\n");702 return -ENODEV;703 }704 705 ret = watchdog_register_device(&w_priv->wdd);706 707 return ret;708}709 710static void ziirave_wdt_remove(struct i2c_client *client)711{712 struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client);713 714 watchdog_unregister_device(&w_priv->wdd);715}716 717static const struct i2c_device_id ziirave_wdt_id[] = {718 { "rave-wdt", 0 },719 { }720};721MODULE_DEVICE_TABLE(i2c, ziirave_wdt_id);722 723static const struct of_device_id zrv_wdt_of_match[] = {724 { .compatible = "zii,rave-wdt", },725 { },726};727MODULE_DEVICE_TABLE(of, zrv_wdt_of_match);728 729static struct i2c_driver ziirave_wdt_driver = {730 .driver = {731 .name = "ziirave_wdt",732 .of_match_table = zrv_wdt_of_match,733 },734 .probe = ziirave_wdt_probe,735 .remove = ziirave_wdt_remove,736 .id_table = ziirave_wdt_id,737};738 739module_i2c_driver(ziirave_wdt_driver);740 741MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk");742MODULE_DESCRIPTION("Zodiac Aerospace RAVE Switch Watchdog Processor Driver");743MODULE_LICENSE("GPL");744