in ziirave_wdt.c [596:709]
static int ziirave_wdt_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct ziirave_wdt_data *w_priv;
int val;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
return -ENODEV;
w_priv = devm_kzalloc(&client->dev, sizeof(*w_priv), GFP_KERNEL);
if (!w_priv)
return -ENOMEM;
mutex_init(&w_priv->sysfs_mutex);
w_priv->wdd.info = &ziirave_wdt_info;
w_priv->wdd.ops = &ziirave_wdt_ops;
w_priv->wdd.min_timeout = ZIIRAVE_TIMEOUT_MIN;
w_priv->wdd.max_timeout = ZIIRAVE_TIMEOUT_MAX;
w_priv->wdd.parent = &client->dev;
w_priv->wdd.groups = ziirave_wdt_groups;
watchdog_init_timeout(&w_priv->wdd, wdt_timeout, &client->dev);
/*
* The default value set in the watchdog should be perfectly valid, so
* pass that in if we haven't provided one via the module parameter or
* of property.
*/
if (w_priv->wdd.timeout == 0) {
val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_TIMEOUT);
if (val < 0) {
dev_err(&client->dev, "Failed to read timeout\n");
return val;
}
if (val > ZIIRAVE_TIMEOUT_MAX ||
val < ZIIRAVE_TIMEOUT_MIN)
val = ZIIRAVE_TIMEOUT_DEFAULT;
w_priv->wdd.timeout = val;
}
ret = ziirave_wdt_set_timeout(&w_priv->wdd, w_priv->wdd.timeout);
if (ret) {
dev_err(&client->dev, "Failed to set timeout\n");
return ret;
}
dev_info(&client->dev, "Timeout set to %ds\n", w_priv->wdd.timeout);
watchdog_set_nowayout(&w_priv->wdd, nowayout);
i2c_set_clientdata(client, w_priv);
/* If in unconfigured state, set to stopped */
val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_STATE);
if (val < 0) {
dev_err(&client->dev, "Failed to read state\n");
return val;
}
if (val == ZIIRAVE_STATE_INITIAL)
ziirave_wdt_stop(&w_priv->wdd);
ret = ziirave_wdt_init_duration(client);
if (ret) {
dev_err(&client->dev, "Failed to init duration\n");
return ret;
}
ret = ziirave_wdt_revision(client, &w_priv->firmware_rev,
ZIIRAVE_WDT_FIRM_VER_MAJOR);
if (ret) {
dev_err(&client->dev, "Failed to read firmware version\n");
return ret;
}
dev_info(&client->dev,
"Firmware version: 02.%02u.%02u\n",
w_priv->firmware_rev.major, w_priv->firmware_rev.minor);
ret = ziirave_wdt_revision(client, &w_priv->bootloader_rev,
ZIIRAVE_WDT_BOOT_VER_MAJOR);
if (ret) {
dev_err(&client->dev, "Failed to read bootloader version\n");
return ret;
}
dev_info(&client->dev,
"Bootloader version: 01.%02u.%02u\n",
w_priv->bootloader_rev.major, w_priv->bootloader_rev.minor);
w_priv->reset_reason = i2c_smbus_read_byte_data(client,
ZIIRAVE_WDT_RESET_REASON);
if (w_priv->reset_reason < 0) {
dev_err(&client->dev, "Failed to read reset reason\n");
return w_priv->reset_reason;
}
if (w_priv->reset_reason >= ARRAY_SIZE(ziirave_reasons) ||
!ziirave_reasons[w_priv->reset_reason]) {
dev_err(&client->dev, "Invalid reset reason\n");
return -ENODEV;
}
ret = watchdog_register_device(&w_priv->wdd);
return ret;
}