/* * ziirave_firm_write_pkt() - Build and write a firmware packet * * A packet to send to the firmware is composed by following bytes: * Length | Addr0 | Addr1 | Data0 .. Data15 | Checksum | * Where, * Length: A data byte containing the length of the data. * Addr0: Low byte of the address. * Addr1: High byte of the address. * Data0 .. Data15: Array of 16 bytes of data. * Checksum: Checksum byte to verify data integrity.
*/ staticint __ziirave_firm_write_pkt(struct watchdog_device *wdd,
u32 addr, const u8 *data, u8 len)
{ const u16 addr16 = (u16)addr / 2; struct i2c_client *client = to_i2c_client(wdd->parent);
u8 i, checksum = 0, packet[ZIIRAVE_FIRM_PKT_TOTAL_SIZE]; int ret;
/* Check max data size */ if (len > ZIIRAVE_FIRM_PKT_DATA_SIZE) {
dev_err(&client->dev, "Firmware packet too long (%d)\n",
len); return -EMSGSIZE;
}
/* * Ignore packets that are targeting program memory outisde of * app partition, since they will be ignored by the * bootloader. At the same time, we need to make sure we'll * allow zero length packet that will be sent as the last step * of firmware update
*/ if (len && ziirave_firm_addr_readonly(addr)) return 0;
if (len > max_write_len) { /* * If data crossed page boundary we need to split this * write in two
*/
ret = __ziirave_firm_write_pkt(wdd, addr, data, max_write_len); if (ret) return ret;
addr += max_write_len;
data += max_write_len;
len -= max_write_len;
}
ret = i2c_smbus_write_byte_data(client,
ZIIRAVE_CMD_JUMP_TO_BOOTLOADER,
ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC); if (ret) {
dev_err(&client->dev, "Failed to jump to bootloader\n"); return ret;
}
msleep(500);
ret = i2c_smbus_write_byte(client, ZIIRAVE_CMD_DOWNLOAD_START); if (ret) {
dev_err(&client->dev, "Failed to start download\n"); return ret;
}
ret = ziirave_firm_read_ack(wdd); if (ret) {
dev_err(&client->dev, "No ACK for start download\n"); return ret;
}
msleep(500);
for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
ret = ziirave_firm_write_pkt(wdd, be32_to_cpu(rec->addr),
rec->data, be16_to_cpu(rec->len)); if (ret) return ret;
}
/* * Finish firmware download process by sending a zero length * payload
*/
ret = ziirave_firm_write_pkt(wdd, 0, NULL, 0); if (ret) {
dev_err(&client->dev, "Failed to send EMPTY packet: %d\n", ret); return ret;
}
/* This sleep seems to be required */
msleep(20);
/* Start firmware verification */
ret = ziirave_firm_verify(wdd, fw); if (ret) {
dev_err(&client->dev, "Failed to verify firmware: %d\n", ret); return ret;
}
/* End download operation */
ret = i2c_smbus_write_byte(client, ZIIRAVE_CMD_DOWNLOAD_END); if (ret) {
dev_err(&client->dev, "Failed to end firmware download: %d\n", ret); return ret;
}
/* Reset the processor */
ret = i2c_smbus_write_byte_data(client,
ZIIRAVE_CMD_RESET_PROCESSOR,
ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC); if (ret) {
dev_err(&client->dev, "Failed to reset the watchdog: %d\n", ret); return ret;
}
err = request_ihex_firmware(&fw, ZIIRAVE_FW_NAME, dev); if (err) {
dev_err(&client->dev, "Failed to request ihex firmware\n"); return err;
}
err = mutex_lock_interruptible(&w_priv->sysfs_mutex); if (err) goto release_firmware;
err = ziirave_firm_upload(&w_priv->wdd, fw); if (err) {
dev_err(&client->dev, "The firmware update failed: %d\n", err); goto unlock_mutex;
}
/* Update firmware version */
err = ziirave_wdt_revision(client, &w_priv->firmware_rev,
ZIIRAVE_WDT_FIRM_VER_MAJOR); if (err) {
dev_err(&client->dev, "Failed to read firmware version: %d\n",
err); goto unlock_mutex;
}
dev_info(&client->dev, "Firmware updated to version 02.%02u.%02u\n",
w_priv->firmware_rev.major, w_priv->firmware_rev.minor);
/* Restore the watchdog timeout */
err = ziirave_wdt_set_timeout(&w_priv->wdd, w_priv->wdd.timeout); if (err)
dev_err(&client->dev, "Failed to set timeout: %d\n", err);
staticint ziirave_wdt_init_duration(struct i2c_client *client)
{ int ret;
if (!reset_duration) { /* See if the reset pulse duration is provided in an of_node */ if (!client->dev.of_node)
ret = -ENODEV; else
ret = of_property_read_u32(client->dev.of_node, "reset-duration-ms",
&reset_duration); if (ret) {
dev_info(&client->dev, "No reset pulse duration specified, using default\n"); return 0;
}
}
if (reset_duration < 1 || reset_duration > 255) return -EINVAL;
dev_info(&client->dev, "Setting reset duration to %dms",
reset_duration);
/* * 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;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.6Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.