brintos

brintos / linux-shallow public Read only

0
0
Text · 18.4 KiB · 7758383 Raw
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