18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2016, Zodiac Inflight Innovations
48c2ecf20Sopenharmony_ci * Copyright (c) 2007-2016, Synaptics Incorporated
58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/bitops.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/rmi.h>
128c2ecf20Sopenharmony_ci#include <linux/firmware.h>
138c2ecf20Sopenharmony_ci#include <linux/delay.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
168c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "rmi_driver.h"
198c2ecf20Sopenharmony_ci#include "rmi_f34.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic int rmi_f34v7_read_flash_status(struct f34_data *f34)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	u8 status;
248c2ecf20Sopenharmony_ci	u8 command;
258c2ecf20Sopenharmony_ci	int ret;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
288c2ecf20Sopenharmony_ci			f34->fn->fd.data_base_addr + f34->v7.off.flash_status,
298c2ecf20Sopenharmony_ci			&status,
308c2ecf20Sopenharmony_ci			sizeof(status));
318c2ecf20Sopenharmony_ci	if (ret < 0) {
328c2ecf20Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
338c2ecf20Sopenharmony_ci			"%s: Error %d reading flash status\n", __func__, ret);
348c2ecf20Sopenharmony_ci		return ret;
358c2ecf20Sopenharmony_ci	}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	f34->v7.in_bl_mode = status >> 7;
388c2ecf20Sopenharmony_ci	f34->v7.flash_status = status & 0x1f;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (f34->v7.flash_status != 0x00) {
418c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: status=%d, command=0x%02x\n",
428c2ecf20Sopenharmony_ci			__func__, f34->v7.flash_status, f34->v7.command);
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
468c2ecf20Sopenharmony_ci			f34->fn->fd.data_base_addr + f34->v7.off.flash_cmd,
478c2ecf20Sopenharmony_ci			&command,
488c2ecf20Sopenharmony_ci			sizeof(command));
498c2ecf20Sopenharmony_ci	if (ret < 0) {
508c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read flash command\n",
518c2ecf20Sopenharmony_ci			__func__);
528c2ecf20Sopenharmony_ci		return ret;
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	f34->v7.command = command;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return 0;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	unsigned long timeout;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	timeout = msecs_to_jiffies(timeout_ms);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&f34->v7.cmd_done, timeout)) {
678c2ecf20Sopenharmony_ci		dev_warn(&f34->fn->dev, "%s: Timed out waiting for idle status\n",
688c2ecf20Sopenharmony_ci			 __func__);
698c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	return 0;
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_command_single_transaction(struct f34_data *f34,
768c2ecf20Sopenharmony_ci						      u8 cmd)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	int ret;
798c2ecf20Sopenharmony_ci	u8 base;
808c2ecf20Sopenharmony_ci	struct f34v7_data_1_5 data_1_5;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	memset(&data_1_5, 0, sizeof(data_1_5));
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	switch (cmd) {
878c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_ALL:
888c2ecf20Sopenharmony_ci		data_1_5.partition_id = CORE_CODE_PARTITION;
898c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE_AP;
908c2ecf20Sopenharmony_ci		break;
918c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_FIRMWARE:
928c2ecf20Sopenharmony_ci		data_1_5.partition_id = CORE_CODE_PARTITION;
938c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
948c2ecf20Sopenharmony_ci		break;
958c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_BL_CONFIG:
968c2ecf20Sopenharmony_ci		data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION;
978c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
988c2ecf20Sopenharmony_ci		break;
998c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_CONFIG:
1008c2ecf20Sopenharmony_ci		data_1_5.partition_id = CORE_CONFIG_PARTITION;
1018c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
1028c2ecf20Sopenharmony_ci		break;
1038c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_DISP_CONFIG:
1048c2ecf20Sopenharmony_ci		data_1_5.partition_id = DISPLAY_CONFIG_PARTITION;
1058c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
1068c2ecf20Sopenharmony_ci		break;
1078c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_FLASH_CONFIG:
1088c2ecf20Sopenharmony_ci		data_1_5.partition_id = FLASH_CONFIG_PARTITION;
1098c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
1108c2ecf20Sopenharmony_ci		break;
1118c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_GUEST_CODE:
1128c2ecf20Sopenharmony_ci		data_1_5.partition_id = GUEST_CODE_PARTITION;
1138c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ERASE;
1148c2ecf20Sopenharmony_ci		break;
1158c2ecf20Sopenharmony_ci	case v7_CMD_ENABLE_FLASH_PROG:
1168c2ecf20Sopenharmony_ci		data_1_5.partition_id = BOOTLOADER_PARTITION;
1178c2ecf20Sopenharmony_ci		data_1_5.command = CMD_V7_ENTER_BL;
1188c2ecf20Sopenharmony_ci		break;
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	data_1_5.payload[0] = f34->bootloader_id[0];
1228c2ecf20Sopenharmony_ci	data_1_5.payload[1] = f34->bootloader_id[1];
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
1258c2ecf20Sopenharmony_ci			base + f34->v7.off.partition_id,
1268c2ecf20Sopenharmony_ci			&data_1_5, sizeof(data_1_5));
1278c2ecf20Sopenharmony_ci	if (ret < 0) {
1288c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev,
1298c2ecf20Sopenharmony_ci			"%s: Failed to write single transaction command\n",
1308c2ecf20Sopenharmony_ci			__func__);
1318c2ecf20Sopenharmony_ci		return ret;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return 0;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_command(struct f34_data *f34, u8 cmd)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	int ret;
1408c2ecf20Sopenharmony_ci	u8 base;
1418c2ecf20Sopenharmony_ci	u8 command;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	switch (cmd) {
1468c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_FW:
1478c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_CONFIG:
1488c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_GUEST_CODE:
1498c2ecf20Sopenharmony_ci		command = CMD_V7_WRITE;
1508c2ecf20Sopenharmony_ci		break;
1518c2ecf20Sopenharmony_ci	case v7_CMD_READ_CONFIG:
1528c2ecf20Sopenharmony_ci		command = CMD_V7_READ;
1538c2ecf20Sopenharmony_ci		break;
1548c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_ALL:
1558c2ecf20Sopenharmony_ci		command = CMD_V7_ERASE_AP;
1568c2ecf20Sopenharmony_ci		break;
1578c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_FIRMWARE:
1588c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_BL_CONFIG:
1598c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_CONFIG:
1608c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_DISP_CONFIG:
1618c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_FLASH_CONFIG:
1628c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_GUEST_CODE:
1638c2ecf20Sopenharmony_ci		command = CMD_V7_ERASE;
1648c2ecf20Sopenharmony_ci		break;
1658c2ecf20Sopenharmony_ci	case v7_CMD_ENABLE_FLASH_PROG:
1668c2ecf20Sopenharmony_ci		command = CMD_V7_ENTER_BL;
1678c2ecf20Sopenharmony_ci		break;
1688c2ecf20Sopenharmony_ci	default:
1698c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n",
1708c2ecf20Sopenharmony_ci			__func__, cmd);
1718c2ecf20Sopenharmony_ci		return -EINVAL;
1728c2ecf20Sopenharmony_ci	}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	f34->v7.command = command;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	switch (cmd) {
1778c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_ALL:
1788c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_FIRMWARE:
1798c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_BL_CONFIG:
1808c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_CONFIG:
1818c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_DISP_CONFIG:
1828c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_FLASH_CONFIG:
1838c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_GUEST_CODE:
1848c2ecf20Sopenharmony_ci	case v7_CMD_ENABLE_FLASH_PROG:
1858c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command_single_transaction(f34, cmd);
1868c2ecf20Sopenharmony_ci		if (ret < 0)
1878c2ecf20Sopenharmony_ci			return ret;
1888c2ecf20Sopenharmony_ci		else
1898c2ecf20Sopenharmony_ci			return 0;
1908c2ecf20Sopenharmony_ci	default:
1918c2ecf20Sopenharmony_ci		break;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: writing cmd %02X\n",
1958c2ecf20Sopenharmony_ci		__func__, command);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
1988c2ecf20Sopenharmony_ci			base + f34->v7.off.flash_cmd,
1998c2ecf20Sopenharmony_ci			&command, sizeof(command));
2008c2ecf20Sopenharmony_ci	if (ret < 0) {
2018c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write flash command\n",
2028c2ecf20Sopenharmony_ci			__func__);
2038c2ecf20Sopenharmony_ci		return ret;
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	return 0;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_partition_id(struct f34_data *f34, u8 cmd)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	int ret;
2128c2ecf20Sopenharmony_ci	u8 base;
2138c2ecf20Sopenharmony_ci	u8 partition;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	switch (cmd) {
2188c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_FW:
2198c2ecf20Sopenharmony_ci		partition = CORE_CODE_PARTITION;
2208c2ecf20Sopenharmony_ci		break;
2218c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_CONFIG:
2228c2ecf20Sopenharmony_ci	case v7_CMD_READ_CONFIG:
2238c2ecf20Sopenharmony_ci		if (f34->v7.config_area == v7_UI_CONFIG_AREA)
2248c2ecf20Sopenharmony_ci			partition = CORE_CONFIG_PARTITION;
2258c2ecf20Sopenharmony_ci		else if (f34->v7.config_area == v7_DP_CONFIG_AREA)
2268c2ecf20Sopenharmony_ci			partition = DISPLAY_CONFIG_PARTITION;
2278c2ecf20Sopenharmony_ci		else if (f34->v7.config_area == v7_PM_CONFIG_AREA)
2288c2ecf20Sopenharmony_ci			partition = GUEST_SERIALIZATION_PARTITION;
2298c2ecf20Sopenharmony_ci		else if (f34->v7.config_area == v7_BL_CONFIG_AREA)
2308c2ecf20Sopenharmony_ci			partition = GLOBAL_PARAMETERS_PARTITION;
2318c2ecf20Sopenharmony_ci		else if (f34->v7.config_area == v7_FLASH_CONFIG_AREA)
2328c2ecf20Sopenharmony_ci			partition = FLASH_CONFIG_PARTITION;
2338c2ecf20Sopenharmony_ci		break;
2348c2ecf20Sopenharmony_ci	case v7_CMD_WRITE_GUEST_CODE:
2358c2ecf20Sopenharmony_ci		partition = GUEST_CODE_PARTITION;
2368c2ecf20Sopenharmony_ci		break;
2378c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_ALL:
2388c2ecf20Sopenharmony_ci		partition = CORE_CODE_PARTITION;
2398c2ecf20Sopenharmony_ci		break;
2408c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_BL_CONFIG:
2418c2ecf20Sopenharmony_ci		partition = GLOBAL_PARAMETERS_PARTITION;
2428c2ecf20Sopenharmony_ci		break;
2438c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_UI_CONFIG:
2448c2ecf20Sopenharmony_ci		partition = CORE_CONFIG_PARTITION;
2458c2ecf20Sopenharmony_ci		break;
2468c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_DISP_CONFIG:
2478c2ecf20Sopenharmony_ci		partition = DISPLAY_CONFIG_PARTITION;
2488c2ecf20Sopenharmony_ci		break;
2498c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_FLASH_CONFIG:
2508c2ecf20Sopenharmony_ci		partition = FLASH_CONFIG_PARTITION;
2518c2ecf20Sopenharmony_ci		break;
2528c2ecf20Sopenharmony_ci	case v7_CMD_ERASE_GUEST_CODE:
2538c2ecf20Sopenharmony_ci		partition = GUEST_CODE_PARTITION;
2548c2ecf20Sopenharmony_ci		break;
2558c2ecf20Sopenharmony_ci	case v7_CMD_ENABLE_FLASH_PROG:
2568c2ecf20Sopenharmony_ci		partition = BOOTLOADER_PARTITION;
2578c2ecf20Sopenharmony_ci		break;
2588c2ecf20Sopenharmony_ci	default:
2598c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n",
2608c2ecf20Sopenharmony_ci			__func__, cmd);
2618c2ecf20Sopenharmony_ci		return -EINVAL;
2628c2ecf20Sopenharmony_ci	}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
2658c2ecf20Sopenharmony_ci			base + f34->v7.off.partition_id,
2668c2ecf20Sopenharmony_ci			&partition, sizeof(partition));
2678c2ecf20Sopenharmony_ci	if (ret < 0) {
2688c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write partition ID\n",
2698c2ecf20Sopenharmony_ci			__func__);
2708c2ecf20Sopenharmony_ci		return ret;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	return 0;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic int rmi_f34v7_read_partition_table(struct f34_data *f34)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	int ret;
2798c2ecf20Sopenharmony_ci	unsigned long timeout;
2808c2ecf20Sopenharmony_ci	u8 base;
2818c2ecf20Sopenharmony_ci	__le16 length;
2828c2ecf20Sopenharmony_ci	u16 block_number = 0;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_FLASH_CONFIG_AREA;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_partition_id(f34, v7_CMD_READ_CONFIG);
2898c2ecf20Sopenharmony_ci	if (ret < 0)
2908c2ecf20Sopenharmony_ci		return ret;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
2938c2ecf20Sopenharmony_ci			base + f34->v7.off.block_number,
2948c2ecf20Sopenharmony_ci			&block_number, sizeof(block_number));
2958c2ecf20Sopenharmony_ci	if (ret < 0) {
2968c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
2978c2ecf20Sopenharmony_ci			__func__);
2988c2ecf20Sopenharmony_ci		return ret;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	put_unaligned_le16(f34->v7.flash_config_length, &length);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
3048c2ecf20Sopenharmony_ci			base + f34->v7.off.transfer_length,
3058c2ecf20Sopenharmony_ci			&length, sizeof(length));
3068c2ecf20Sopenharmony_ci	if (ret < 0) {
3078c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write transfer length\n",
3088c2ecf20Sopenharmony_ci			__func__);
3098c2ecf20Sopenharmony_ci		return ret;
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_command(f34, v7_CMD_READ_CONFIG);
3158c2ecf20Sopenharmony_ci	if (ret < 0) {
3168c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write command\n",
3178c2ecf20Sopenharmony_ci			__func__);
3188c2ecf20Sopenharmony_ci		return ret;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	timeout = msecs_to_jiffies(F34_WRITE_WAIT_MS);
3228c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
3238c2ecf20Sopenharmony_ci		usleep_range(5000, 6000);
3248c2ecf20Sopenharmony_ci		rmi_f34v7_read_flash_status(f34);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		if (f34->v7.command == v7_CMD_IDLE &&
3278c2ecf20Sopenharmony_ci		    f34->v7.flash_status == 0x00) {
3288c2ecf20Sopenharmony_ci			break;
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
3338c2ecf20Sopenharmony_ci			base + f34->v7.off.payload,
3348c2ecf20Sopenharmony_ci			f34->v7.read_config_buf,
3358c2ecf20Sopenharmony_ci			f34->v7.partition_table_bytes);
3368c2ecf20Sopenharmony_ci	if (ret < 0) {
3378c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read block data\n",
3388c2ecf20Sopenharmony_ci			__func__);
3398c2ecf20Sopenharmony_ci		return ret;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void rmi_f34v7_parse_partition_table(struct f34_data *f34,
3468c2ecf20Sopenharmony_ci					    const void *partition_table,
3478c2ecf20Sopenharmony_ci					    struct block_count *blkcount,
3488c2ecf20Sopenharmony_ci					    struct physical_address *phyaddr)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	int i;
3518c2ecf20Sopenharmony_ci	int index;
3528c2ecf20Sopenharmony_ci	u16 partition_length;
3538c2ecf20Sopenharmony_ci	u16 physical_address;
3548c2ecf20Sopenharmony_ci	const struct partition_table *ptable;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	for (i = 0; i < f34->v7.partitions; i++) {
3578c2ecf20Sopenharmony_ci		index = i * 8 + 2;
3588c2ecf20Sopenharmony_ci		ptable = partition_table + index;
3598c2ecf20Sopenharmony_ci		partition_length = le16_to_cpu(ptable->partition_length);
3608c2ecf20Sopenharmony_ci		physical_address = le16_to_cpu(ptable->start_physical_address);
3618c2ecf20Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3628c2ecf20Sopenharmony_ci			"%s: Partition entry %d: %*ph\n",
3638c2ecf20Sopenharmony_ci			__func__, i, sizeof(struct partition_table), ptable);
3648c2ecf20Sopenharmony_ci		switch (ptable->partition_id & 0x1f) {
3658c2ecf20Sopenharmony_ci		case CORE_CODE_PARTITION:
3668c2ecf20Sopenharmony_ci			blkcount->ui_firmware = partition_length;
3678c2ecf20Sopenharmony_ci			phyaddr->ui_firmware = physical_address;
3688c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3698c2ecf20Sopenharmony_ci				"%s: Core code block count: %d\n",
3708c2ecf20Sopenharmony_ci				__func__, blkcount->ui_firmware);
3718c2ecf20Sopenharmony_ci			break;
3728c2ecf20Sopenharmony_ci		case CORE_CONFIG_PARTITION:
3738c2ecf20Sopenharmony_ci			blkcount->ui_config = partition_length;
3748c2ecf20Sopenharmony_ci			phyaddr->ui_config = physical_address;
3758c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3768c2ecf20Sopenharmony_ci				"%s: Core config block count: %d\n",
3778c2ecf20Sopenharmony_ci				__func__, blkcount->ui_config);
3788c2ecf20Sopenharmony_ci			break;
3798c2ecf20Sopenharmony_ci		case DISPLAY_CONFIG_PARTITION:
3808c2ecf20Sopenharmony_ci			blkcount->dp_config = partition_length;
3818c2ecf20Sopenharmony_ci			phyaddr->dp_config = physical_address;
3828c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3838c2ecf20Sopenharmony_ci				"%s: Display config block count: %d\n",
3848c2ecf20Sopenharmony_ci				__func__, blkcount->dp_config);
3858c2ecf20Sopenharmony_ci			break;
3868c2ecf20Sopenharmony_ci		case FLASH_CONFIG_PARTITION:
3878c2ecf20Sopenharmony_ci			blkcount->fl_config = partition_length;
3888c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3898c2ecf20Sopenharmony_ci				"%s: Flash config block count: %d\n",
3908c2ecf20Sopenharmony_ci				__func__, blkcount->fl_config);
3918c2ecf20Sopenharmony_ci			break;
3928c2ecf20Sopenharmony_ci		case GUEST_CODE_PARTITION:
3938c2ecf20Sopenharmony_ci			blkcount->guest_code = partition_length;
3948c2ecf20Sopenharmony_ci			phyaddr->guest_code = physical_address;
3958c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
3968c2ecf20Sopenharmony_ci				"%s: Guest code block count: %d\n",
3978c2ecf20Sopenharmony_ci				__func__, blkcount->guest_code);
3988c2ecf20Sopenharmony_ci			break;
3998c2ecf20Sopenharmony_ci		case GUEST_SERIALIZATION_PARTITION:
4008c2ecf20Sopenharmony_ci			blkcount->pm_config = partition_length;
4018c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
4028c2ecf20Sopenharmony_ci				"%s: Guest serialization block count: %d\n",
4038c2ecf20Sopenharmony_ci				__func__, blkcount->pm_config);
4048c2ecf20Sopenharmony_ci			break;
4058c2ecf20Sopenharmony_ci		case GLOBAL_PARAMETERS_PARTITION:
4068c2ecf20Sopenharmony_ci			blkcount->bl_config = partition_length;
4078c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
4088c2ecf20Sopenharmony_ci				"%s: Global parameters block count: %d\n",
4098c2ecf20Sopenharmony_ci				__func__, blkcount->bl_config);
4108c2ecf20Sopenharmony_ci			break;
4118c2ecf20Sopenharmony_ci		case DEVICE_CONFIG_PARTITION:
4128c2ecf20Sopenharmony_ci			blkcount->lockdown = partition_length;
4138c2ecf20Sopenharmony_ci			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
4148c2ecf20Sopenharmony_ci				"%s: Device config block count: %d\n",
4158c2ecf20Sopenharmony_ci				__func__, blkcount->lockdown);
4168c2ecf20Sopenharmony_ci			break;
4178c2ecf20Sopenharmony_ci		}
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic int rmi_f34v7_read_queries_bl_version(struct f34_data *f34)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	int ret;
4248c2ecf20Sopenharmony_ci	u8 base;
4258c2ecf20Sopenharmony_ci	int offset;
4268c2ecf20Sopenharmony_ci	u8 query_0;
4278c2ecf20Sopenharmony_ci	struct f34v7_query_1_7 query_1_7;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	base = f34->fn->fd.query_base_addr;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
4328c2ecf20Sopenharmony_ci			base,
4338c2ecf20Sopenharmony_ci			&query_0,
4348c2ecf20Sopenharmony_ci			sizeof(query_0));
4358c2ecf20Sopenharmony_ci	if (ret < 0) {
4368c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev,
4378c2ecf20Sopenharmony_ci			"%s: Failed to read query 0\n", __func__);
4388c2ecf20Sopenharmony_ci		return ret;
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	offset = (query_0 & 0x7) + 1;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
4448c2ecf20Sopenharmony_ci			base + offset,
4458c2ecf20Sopenharmony_ci			&query_1_7,
4468c2ecf20Sopenharmony_ci			sizeof(query_1_7));
4478c2ecf20Sopenharmony_ci	if (ret < 0) {
4488c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n",
4498c2ecf20Sopenharmony_ci			__func__);
4508c2ecf20Sopenharmony_ci		return ret;
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	f34->bootloader_id[0] = query_1_7.bl_minor_revision;
4548c2ecf20Sopenharmony_ci	f34->bootloader_id[1] = query_1_7.bl_major_revision;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "Bootloader V%d.%d\n",
4578c2ecf20Sopenharmony_ci		f34->bootloader_id[1], f34->bootloader_id[0]);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	return 0;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic int rmi_f34v7_read_queries(struct f34_data *f34)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	int ret;
4658c2ecf20Sopenharmony_ci	int i;
4668c2ecf20Sopenharmony_ci	u8 base;
4678c2ecf20Sopenharmony_ci	int offset;
4688c2ecf20Sopenharmony_ci	u8 *ptable;
4698c2ecf20Sopenharmony_ci	u8 query_0;
4708c2ecf20Sopenharmony_ci	struct f34v7_query_1_7 query_1_7;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	base = f34->fn->fd.query_base_addr;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
4758c2ecf20Sopenharmony_ci			base,
4768c2ecf20Sopenharmony_ci			&query_0,
4778c2ecf20Sopenharmony_ci			sizeof(query_0));
4788c2ecf20Sopenharmony_ci	if (ret < 0) {
4798c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev,
4808c2ecf20Sopenharmony_ci			"%s: Failed to read query 0\n", __func__);
4818c2ecf20Sopenharmony_ci		return ret;
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	offset = (query_0 & 0x07) + 1;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
4878c2ecf20Sopenharmony_ci			base + offset,
4888c2ecf20Sopenharmony_ci			&query_1_7,
4898c2ecf20Sopenharmony_ci			sizeof(query_1_7));
4908c2ecf20Sopenharmony_ci	if (ret < 0) {
4918c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n",
4928c2ecf20Sopenharmony_ci			__func__);
4938c2ecf20Sopenharmony_ci		return ret;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	f34->bootloader_id[0] = query_1_7.bl_minor_revision;
4978c2ecf20Sopenharmony_ci	f34->bootloader_id[1] = query_1_7.bl_major_revision;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	f34->v7.block_size = le16_to_cpu(query_1_7.block_size);
5008c2ecf20Sopenharmony_ci	f34->v7.flash_config_length =
5018c2ecf20Sopenharmony_ci			le16_to_cpu(query_1_7.flash_config_length);
5028c2ecf20Sopenharmony_ci	f34->v7.payload_length = le16_to_cpu(query_1_7.payload_length);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: f34->v7.block_size = %d\n",
5058c2ecf20Sopenharmony_ci		 __func__, f34->v7.block_size);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	f34->v7.off.flash_status = V7_FLASH_STATUS_OFFSET;
5088c2ecf20Sopenharmony_ci	f34->v7.off.partition_id = V7_PARTITION_ID_OFFSET;
5098c2ecf20Sopenharmony_ci	f34->v7.off.block_number = V7_BLOCK_NUMBER_OFFSET;
5108c2ecf20Sopenharmony_ci	f34->v7.off.transfer_length = V7_TRANSFER_LENGTH_OFFSET;
5118c2ecf20Sopenharmony_ci	f34->v7.off.flash_cmd = V7_COMMAND_OFFSET;
5128c2ecf20Sopenharmony_ci	f34->v7.off.payload = V7_PAYLOAD_OFFSET;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	f34->v7.has_display_cfg = query_1_7.partition_support[1] & HAS_DISP_CFG;
5158c2ecf20Sopenharmony_ci	f34->v7.has_guest_code =
5168c2ecf20Sopenharmony_ci			query_1_7.partition_support[1] & HAS_GUEST_CODE;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	if (query_0 & HAS_CONFIG_ID) {
5198c2ecf20Sopenharmony_ci		u8 f34_ctrl[CONFIG_ID_SIZE];
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci		ret = rmi_read_block(f34->fn->rmi_dev,
5228c2ecf20Sopenharmony_ci				f34->fn->fd.control_base_addr,
5238c2ecf20Sopenharmony_ci				f34_ctrl,
5248c2ecf20Sopenharmony_ci				sizeof(f34_ctrl));
5258c2ecf20Sopenharmony_ci		if (ret)
5268c2ecf20Sopenharmony_ci			return ret;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci		/* Eat leading zeros */
5298c2ecf20Sopenharmony_ci		for (i = 0; i < sizeof(f34_ctrl) - 1 && !f34_ctrl[i]; i++)
5308c2ecf20Sopenharmony_ci			/* Empty */;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci		snprintf(f34->configuration_id, sizeof(f34->configuration_id),
5338c2ecf20Sopenharmony_ci			 "%*phN", (int)sizeof(f34_ctrl) - i, f34_ctrl + i);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "Configuration ID: %s\n",
5368c2ecf20Sopenharmony_ci			f34->configuration_id);
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	f34->v7.partitions = 0;
5408c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(query_1_7.partition_support); i++)
5418c2ecf20Sopenharmony_ci		f34->v7.partitions += hweight8(query_1_7.partition_support[i]);
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: Supported partitions: %*ph\n",
5448c2ecf20Sopenharmony_ci		__func__, sizeof(query_1_7.partition_support),
5458c2ecf20Sopenharmony_ci		query_1_7.partition_support);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	f34->v7.partition_table_bytes = f34->v7.partitions * 8 + 2;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	f34->v7.read_config_buf = devm_kzalloc(&f34->fn->dev,
5518c2ecf20Sopenharmony_ci			f34->v7.partition_table_bytes,
5528c2ecf20Sopenharmony_ci			GFP_KERNEL);
5538c2ecf20Sopenharmony_ci	if (!f34->v7.read_config_buf) {
5548c2ecf20Sopenharmony_ci		f34->v7.read_config_buf_size = 0;
5558c2ecf20Sopenharmony_ci		return -ENOMEM;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	f34->v7.read_config_buf_size = f34->v7.partition_table_bytes;
5598c2ecf20Sopenharmony_ci	ptable = f34->v7.read_config_buf;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ret = rmi_f34v7_read_partition_table(f34);
5628c2ecf20Sopenharmony_ci	if (ret < 0) {
5638c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read partition table\n",
5648c2ecf20Sopenharmony_ci				__func__);
5658c2ecf20Sopenharmony_ci		return ret;
5668c2ecf20Sopenharmony_ci	}
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	rmi_f34v7_parse_partition_table(f34, ptable,
5698c2ecf20Sopenharmony_ci					&f34->v7.blkcount, &f34->v7.phyaddr);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	return 0;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	u16 block_count;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
5798c2ecf20Sopenharmony_ci	f34->update_size += block_count;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	if (block_count != f34->v7.blkcount.ui_firmware) {
5828c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev,
5838c2ecf20Sopenharmony_ci			"UI firmware size mismatch: %d != %d\n",
5848c2ecf20Sopenharmony_ci			block_count, f34->v7.blkcount.ui_firmware);
5858c2ecf20Sopenharmony_ci		return -EINVAL;
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return 0;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic int rmi_f34v7_check_ui_config_size(struct f34_data *f34)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	u16 block_count;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	block_count = f34->v7.img.ui_config.size / f34->v7.block_size;
5968c2ecf20Sopenharmony_ci	f34->update_size += block_count;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (block_count != f34->v7.blkcount.ui_config) {
5998c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "UI config size mismatch\n");
6008c2ecf20Sopenharmony_ci		return -EINVAL;
6018c2ecf20Sopenharmony_ci	}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	return 0;
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cistatic int rmi_f34v7_check_dp_config_size(struct f34_data *f34)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	u16 block_count;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	block_count = f34->v7.img.dp_config.size / f34->v7.block_size;
6118c2ecf20Sopenharmony_ci	f34->update_size += block_count;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	if (block_count != f34->v7.blkcount.dp_config) {
6148c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "Display config size mismatch\n");
6158c2ecf20Sopenharmony_ci		return -EINVAL;
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	return 0;
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_cistatic int rmi_f34v7_check_guest_code_size(struct f34_data *f34)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	u16 block_count;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	block_count = f34->v7.img.guest_code.size / f34->v7.block_size;
6268c2ecf20Sopenharmony_ci	f34->update_size += block_count;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	if (block_count != f34->v7.blkcount.guest_code) {
6298c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "Guest code size mismatch\n");
6308c2ecf20Sopenharmony_ci		return -EINVAL;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	return 0;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
6378c2ecf20Sopenharmony_ci{
6388c2ecf20Sopenharmony_ci	u16 block_count;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	block_count = f34->v7.img.bl_config.size / f34->v7.block_size;
6418c2ecf20Sopenharmony_ci	f34->update_size += block_count;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	if (block_count != f34->v7.blkcount.bl_config) {
6448c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "Bootloader config size mismatch\n");
6458c2ecf20Sopenharmony_ci		return -EINVAL;
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	return 0;
6498c2ecf20Sopenharmony_ci}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic int rmi_f34v7_erase_config(struct f34_data *f34)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	int ret;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Erasing config...\n");
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	switch (f34->v7.config_area) {
6608c2ecf20Sopenharmony_ci	case v7_UI_CONFIG_AREA:
6618c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_CONFIG);
6628c2ecf20Sopenharmony_ci		if (ret < 0)
6638c2ecf20Sopenharmony_ci			return ret;
6648c2ecf20Sopenharmony_ci		break;
6658c2ecf20Sopenharmony_ci	case v7_DP_CONFIG_AREA:
6668c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_DISP_CONFIG);
6678c2ecf20Sopenharmony_ci		if (ret < 0)
6688c2ecf20Sopenharmony_ci			return ret;
6698c2ecf20Sopenharmony_ci		break;
6708c2ecf20Sopenharmony_ci	case v7_BL_CONFIG_AREA:
6718c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_BL_CONFIG);
6728c2ecf20Sopenharmony_ci		if (ret < 0)
6738c2ecf20Sopenharmony_ci			return ret;
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci	}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
6788c2ecf20Sopenharmony_ci	if (ret < 0)
6798c2ecf20Sopenharmony_ci		return ret;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	return 0;
6828c2ecf20Sopenharmony_ci}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_cistatic int rmi_f34v7_erase_guest_code(struct f34_data *f34)
6858c2ecf20Sopenharmony_ci{
6868c2ecf20Sopenharmony_ci	int ret;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Erasing guest code...\n");
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_GUEST_CODE);
6938c2ecf20Sopenharmony_ci	if (ret < 0)
6948c2ecf20Sopenharmony_ci		return ret;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
6978c2ecf20Sopenharmony_ci	if (ret < 0)
6988c2ecf20Sopenharmony_ci		return ret;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	return 0;
7018c2ecf20Sopenharmony_ci}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cistatic int rmi_f34v7_erase_all(struct f34_data *f34)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	int ret;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Erasing firmware...\n");
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_FIRMWARE);
7128c2ecf20Sopenharmony_ci	if (ret < 0)
7138c2ecf20Sopenharmony_ci		return ret;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
7168c2ecf20Sopenharmony_ci	if (ret < 0)
7178c2ecf20Sopenharmony_ci		return ret;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_UI_CONFIG_AREA;
7208c2ecf20Sopenharmony_ci	ret = rmi_f34v7_erase_config(f34);
7218c2ecf20Sopenharmony_ci	if (ret < 0)
7228c2ecf20Sopenharmony_ci		return ret;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	if (f34->v7.has_display_cfg) {
7258c2ecf20Sopenharmony_ci		f34->v7.config_area = v7_DP_CONFIG_AREA;
7268c2ecf20Sopenharmony_ci		ret = rmi_f34v7_erase_config(f34);
7278c2ecf20Sopenharmony_ci		if (ret < 0)
7288c2ecf20Sopenharmony_ci			return ret;
7298c2ecf20Sopenharmony_ci	}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (f34->v7.new_partition_table && f34->v7.has_guest_code) {
7328c2ecf20Sopenharmony_ci		ret = rmi_f34v7_erase_guest_code(f34);
7338c2ecf20Sopenharmony_ci		if (ret < 0)
7348c2ecf20Sopenharmony_ci			return ret;
7358c2ecf20Sopenharmony_ci	}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	return 0;
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cistatic int rmi_f34v7_read_blocks(struct f34_data *f34,
7418c2ecf20Sopenharmony_ci				 u16 block_cnt, u8 command)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	int ret;
7448c2ecf20Sopenharmony_ci	u8 base;
7458c2ecf20Sopenharmony_ci	__le16 length;
7468c2ecf20Sopenharmony_ci	u16 transfer;
7478c2ecf20Sopenharmony_ci	u16 max_transfer;
7488c2ecf20Sopenharmony_ci	u16 remaining = block_cnt;
7498c2ecf20Sopenharmony_ci	u16 block_number = 0;
7508c2ecf20Sopenharmony_ci	u16 index = 0;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_partition_id(f34, command);
7558c2ecf20Sopenharmony_ci	if (ret < 0)
7568c2ecf20Sopenharmony_ci		return ret;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
7598c2ecf20Sopenharmony_ci			base + f34->v7.off.block_number,
7608c2ecf20Sopenharmony_ci			&block_number, sizeof(block_number));
7618c2ecf20Sopenharmony_ci	if (ret < 0) {
7628c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
7638c2ecf20Sopenharmony_ci			__func__);
7648c2ecf20Sopenharmony_ci		return ret;
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	max_transfer = min(f34->v7.payload_length,
7688c2ecf20Sopenharmony_ci			   (u16)(PAGE_SIZE / f34->v7.block_size));
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	do {
7718c2ecf20Sopenharmony_ci		transfer = min(remaining, max_transfer);
7728c2ecf20Sopenharmony_ci		put_unaligned_le16(transfer, &length);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci		ret = rmi_write_block(f34->fn->rmi_dev,
7758c2ecf20Sopenharmony_ci				base + f34->v7.off.transfer_length,
7768c2ecf20Sopenharmony_ci				&length, sizeof(length));
7778c2ecf20Sopenharmony_ci		if (ret < 0) {
7788c2ecf20Sopenharmony_ci			dev_err(&f34->fn->dev,
7798c2ecf20Sopenharmony_ci				"%s: Write transfer length fail (%d remaining)\n",
7808c2ecf20Sopenharmony_ci				__func__, remaining);
7818c2ecf20Sopenharmony_ci			return ret;
7828c2ecf20Sopenharmony_ci		}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci		init_completion(&f34->v7.cmd_done);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command(f34, command);
7878c2ecf20Sopenharmony_ci		if (ret < 0)
7888c2ecf20Sopenharmony_ci			return ret;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci		ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
7918c2ecf20Sopenharmony_ci		if (ret < 0)
7928c2ecf20Sopenharmony_ci			return ret;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci		ret = rmi_read_block(f34->fn->rmi_dev,
7958c2ecf20Sopenharmony_ci				base + f34->v7.off.payload,
7968c2ecf20Sopenharmony_ci				&f34->v7.read_config_buf[index],
7978c2ecf20Sopenharmony_ci				transfer * f34->v7.block_size);
7988c2ecf20Sopenharmony_ci		if (ret < 0) {
7998c2ecf20Sopenharmony_ci			dev_err(&f34->fn->dev,
8008c2ecf20Sopenharmony_ci				"%s: Read block failed (%d blks remaining)\n",
8018c2ecf20Sopenharmony_ci				__func__, remaining);
8028c2ecf20Sopenharmony_ci			return ret;
8038c2ecf20Sopenharmony_ci		}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci		index += (transfer * f34->v7.block_size);
8068c2ecf20Sopenharmony_ci		remaining -= transfer;
8078c2ecf20Sopenharmony_ci	} while (remaining);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	return 0;
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
8138c2ecf20Sopenharmony_ci					const void *block_ptr, u16 block_cnt,
8148c2ecf20Sopenharmony_ci					u8 command)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	int ret;
8178c2ecf20Sopenharmony_ci	u8 base;
8188c2ecf20Sopenharmony_ci	__le16 length;
8198c2ecf20Sopenharmony_ci	u16 transfer;
8208c2ecf20Sopenharmony_ci	u16 max_transfer;
8218c2ecf20Sopenharmony_ci	u16 remaining = block_cnt;
8228c2ecf20Sopenharmony_ci	u16 block_number = 0;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	base = f34->fn->fd.data_base_addr;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_partition_id(f34, command);
8278c2ecf20Sopenharmony_ci	if (ret < 0)
8288c2ecf20Sopenharmony_ci		return ret;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	ret = rmi_write_block(f34->fn->rmi_dev,
8318c2ecf20Sopenharmony_ci			base + f34->v7.off.block_number,
8328c2ecf20Sopenharmony_ci			&block_number, sizeof(block_number));
8338c2ecf20Sopenharmony_ci	if (ret < 0) {
8348c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
8358c2ecf20Sopenharmony_ci			__func__);
8368c2ecf20Sopenharmony_ci		return ret;
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	if (f34->v7.payload_length > (PAGE_SIZE / f34->v7.block_size))
8408c2ecf20Sopenharmony_ci		max_transfer = PAGE_SIZE / f34->v7.block_size;
8418c2ecf20Sopenharmony_ci	else
8428c2ecf20Sopenharmony_ci		max_transfer = f34->v7.payload_length;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	do {
8458c2ecf20Sopenharmony_ci		transfer = min(remaining, max_transfer);
8468c2ecf20Sopenharmony_ci		put_unaligned_le16(transfer, &length);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		init_completion(&f34->v7.cmd_done);
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci		ret = rmi_write_block(f34->fn->rmi_dev,
8518c2ecf20Sopenharmony_ci				base + f34->v7.off.transfer_length,
8528c2ecf20Sopenharmony_ci				&length, sizeof(length));
8538c2ecf20Sopenharmony_ci		if (ret < 0) {
8548c2ecf20Sopenharmony_ci			dev_err(&f34->fn->dev,
8558c2ecf20Sopenharmony_ci				"%s: Write transfer length fail (%d remaining)\n",
8568c2ecf20Sopenharmony_ci				__func__, remaining);
8578c2ecf20Sopenharmony_ci			return ret;
8588c2ecf20Sopenharmony_ci		}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_command(f34, command);
8618c2ecf20Sopenharmony_ci		if (ret < 0)
8628c2ecf20Sopenharmony_ci			return ret;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci		ret = rmi_write_block(f34->fn->rmi_dev,
8658c2ecf20Sopenharmony_ci				base + f34->v7.off.payload,
8668c2ecf20Sopenharmony_ci				block_ptr, transfer * f34->v7.block_size);
8678c2ecf20Sopenharmony_ci		if (ret < 0) {
8688c2ecf20Sopenharmony_ci			dev_err(&f34->fn->dev,
8698c2ecf20Sopenharmony_ci				"%s: Failed writing data (%d blks remaining)\n",
8708c2ecf20Sopenharmony_ci				__func__, remaining);
8718c2ecf20Sopenharmony_ci			return ret;
8728c2ecf20Sopenharmony_ci		}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci		ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
8758c2ecf20Sopenharmony_ci		if (ret < 0)
8768c2ecf20Sopenharmony_ci			return ret;
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci		block_ptr += (transfer * f34->v7.block_size);
8798c2ecf20Sopenharmony_ci		remaining -= transfer;
8808c2ecf20Sopenharmony_ci		f34->update_progress += transfer;
8818c2ecf20Sopenharmony_ci		f34->update_status = (f34->update_progress * 100) /
8828c2ecf20Sopenharmony_ci				     f34->update_size;
8838c2ecf20Sopenharmony_ci	} while (remaining);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	return 0;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_config(struct f34_data *f34)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.config_data,
8918c2ecf20Sopenharmony_ci					    f34->v7.config_block_count,
8928c2ecf20Sopenharmony_ci					    v7_CMD_WRITE_CONFIG);
8938c2ecf20Sopenharmony_ci}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_ui_config(struct f34_data *f34)
8968c2ecf20Sopenharmony_ci{
8978c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_UI_CONFIG_AREA;
8988c2ecf20Sopenharmony_ci	f34->v7.config_data = f34->v7.img.ui_config.data;
8998c2ecf20Sopenharmony_ci	f34->v7.config_size = f34->v7.img.ui_config.size;
9008c2ecf20Sopenharmony_ci	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	return rmi_f34v7_write_config(f34);
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_dp_config(struct f34_data *f34)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_DP_CONFIG_AREA;
9088c2ecf20Sopenharmony_ci	f34->v7.config_data = f34->v7.img.dp_config.data;
9098c2ecf20Sopenharmony_ci	f34->v7.config_size = f34->v7.img.dp_config.size;
9108c2ecf20Sopenharmony_ci	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	return rmi_f34v7_write_config(f34);
9138c2ecf20Sopenharmony_ci}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_guest_code(struct f34_data *f34)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.img.guest_code.data,
9188c2ecf20Sopenharmony_ci					    f34->v7.img.guest_code.size /
9198c2ecf20Sopenharmony_ci							f34->v7.block_size,
9208c2ecf20Sopenharmony_ci					    v7_CMD_WRITE_GUEST_CODE);
9218c2ecf20Sopenharmony_ci}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_flash_config(struct f34_data *f34)
9248c2ecf20Sopenharmony_ci{
9258c2ecf20Sopenharmony_ci	int ret;
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_FLASH_CONFIG_AREA;
9288c2ecf20Sopenharmony_ci	f34->v7.config_data = f34->v7.img.fl_config.data;
9298c2ecf20Sopenharmony_ci	f34->v7.config_size = f34->v7.img.fl_config.size;
9308c2ecf20Sopenharmony_ci	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	if (f34->v7.config_block_count != f34->v7.blkcount.fl_config) {
9338c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Flash config size mismatch\n",
9348c2ecf20Sopenharmony_ci			__func__);
9358c2ecf20Sopenharmony_ci		return -EINVAL;
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_FLASH_CONFIG);
9418c2ecf20Sopenharmony_ci	if (ret < 0)
9428c2ecf20Sopenharmony_ci		return ret;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
9458c2ecf20Sopenharmony_ci		"%s: Erase flash config command written\n", __func__);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	ret = rmi_f34v7_wait_for_idle(f34, F34_WRITE_WAIT_MS);
9488c2ecf20Sopenharmony_ci	if (ret < 0)
9498c2ecf20Sopenharmony_ci		return ret;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_config(f34);
9528c2ecf20Sopenharmony_ci	if (ret < 0)
9538c2ecf20Sopenharmony_ci		return ret;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	return 0;
9568c2ecf20Sopenharmony_ci}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_partition_table(struct f34_data *f34)
9598c2ecf20Sopenharmony_ci{
9608c2ecf20Sopenharmony_ci	u16 block_count;
9618c2ecf20Sopenharmony_ci	int ret;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	block_count = f34->v7.blkcount.bl_config;
9648c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_BL_CONFIG_AREA;
9658c2ecf20Sopenharmony_ci	f34->v7.config_size = f34->v7.block_size * block_count;
9668c2ecf20Sopenharmony_ci	devm_kfree(&f34->fn->dev, f34->v7.read_config_buf);
9678c2ecf20Sopenharmony_ci	f34->v7.read_config_buf = devm_kzalloc(&f34->fn->dev,
9688c2ecf20Sopenharmony_ci					       f34->v7.config_size, GFP_KERNEL);
9698c2ecf20Sopenharmony_ci	if (!f34->v7.read_config_buf) {
9708c2ecf20Sopenharmony_ci		f34->v7.read_config_buf_size = 0;
9718c2ecf20Sopenharmony_ci		return -ENOMEM;
9728c2ecf20Sopenharmony_ci	}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	f34->v7.read_config_buf_size = f34->v7.config_size;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	ret = rmi_f34v7_read_blocks(f34, block_count, v7_CMD_READ_CONFIG);
9778c2ecf20Sopenharmony_ci	if (ret < 0)
9788c2ecf20Sopenharmony_ci		return ret;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	ret = rmi_f34v7_erase_config(f34);
9818c2ecf20Sopenharmony_ci	if (ret < 0)
9828c2ecf20Sopenharmony_ci		return ret;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_flash_config(f34);
9858c2ecf20Sopenharmony_ci	if (ret < 0)
9868c2ecf20Sopenharmony_ci		return ret;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_BL_CONFIG_AREA;
9898c2ecf20Sopenharmony_ci	f34->v7.config_data = f34->v7.read_config_buf;
9908c2ecf20Sopenharmony_ci	f34->v7.config_size = f34->v7.img.bl_config.size;
9918c2ecf20Sopenharmony_ci	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_config(f34);
9948c2ecf20Sopenharmony_ci	if (ret < 0)
9958c2ecf20Sopenharmony_ci		return ret;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	return 0;
9988c2ecf20Sopenharmony_ci}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_cistatic int rmi_f34v7_write_firmware(struct f34_data *f34)
10018c2ecf20Sopenharmony_ci{
10028c2ecf20Sopenharmony_ci	u16 blk_count;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	blk_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.img.ui_firmware.data,
10078c2ecf20Sopenharmony_ci					    blk_count, v7_CMD_WRITE_FW);
10088c2ecf20Sopenharmony_ci}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_cistatic void rmi_f34v7_compare_partition_tables(struct f34_data *f34)
10118c2ecf20Sopenharmony_ci{
10128c2ecf20Sopenharmony_ci	if (f34->v7.phyaddr.ui_firmware != f34->v7.img.phyaddr.ui_firmware) {
10138c2ecf20Sopenharmony_ci		f34->v7.new_partition_table = true;
10148c2ecf20Sopenharmony_ci		return;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	if (f34->v7.phyaddr.ui_config != f34->v7.img.phyaddr.ui_config) {
10188c2ecf20Sopenharmony_ci		f34->v7.new_partition_table = true;
10198c2ecf20Sopenharmony_ci		return;
10208c2ecf20Sopenharmony_ci	}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	if (f34->v7.has_display_cfg &&
10238c2ecf20Sopenharmony_ci	    f34->v7.phyaddr.dp_config != f34->v7.img.phyaddr.dp_config) {
10248c2ecf20Sopenharmony_ci		f34->v7.new_partition_table = true;
10258c2ecf20Sopenharmony_ci		return;
10268c2ecf20Sopenharmony_ci	}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	if (f34->v7.has_guest_code &&
10298c2ecf20Sopenharmony_ci	    f34->v7.phyaddr.guest_code != f34->v7.img.phyaddr.guest_code) {
10308c2ecf20Sopenharmony_ci		f34->v7.new_partition_table = true;
10318c2ecf20Sopenharmony_ci		return;
10328c2ecf20Sopenharmony_ci	}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	f34->v7.new_partition_table = false;
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic void rmi_f34v7_parse_img_header_10_bl_container(struct f34_data *f34,
10388c2ecf20Sopenharmony_ci						       const void *image)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	int i;
10418c2ecf20Sopenharmony_ci	int num_of_containers;
10428c2ecf20Sopenharmony_ci	unsigned int addr;
10438c2ecf20Sopenharmony_ci	unsigned int container_id;
10448c2ecf20Sopenharmony_ci	unsigned int length;
10458c2ecf20Sopenharmony_ci	const void *content;
10468c2ecf20Sopenharmony_ci	const struct container_descriptor *descriptor;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	num_of_containers = f34->v7.img.bootloader.size / 4 - 1;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	for (i = 1; i <= num_of_containers; i++) {
10518c2ecf20Sopenharmony_ci		addr = get_unaligned_le32(f34->v7.img.bootloader.data + i * 4);
10528c2ecf20Sopenharmony_ci		descriptor = image + addr;
10538c2ecf20Sopenharmony_ci		container_id = le16_to_cpu(descriptor->container_id);
10548c2ecf20Sopenharmony_ci		content = image + le32_to_cpu(descriptor->content_address);
10558c2ecf20Sopenharmony_ci		length = le32_to_cpu(descriptor->content_length);
10568c2ecf20Sopenharmony_ci		switch (container_id) {
10578c2ecf20Sopenharmony_ci		case BL_CONFIG_CONTAINER:
10588c2ecf20Sopenharmony_ci		case GLOBAL_PARAMETERS_CONTAINER:
10598c2ecf20Sopenharmony_ci			f34->v7.img.bl_config.data = content;
10608c2ecf20Sopenharmony_ci			f34->v7.img.bl_config.size = length;
10618c2ecf20Sopenharmony_ci			break;
10628c2ecf20Sopenharmony_ci		case BL_LOCKDOWN_INFO_CONTAINER:
10638c2ecf20Sopenharmony_ci		case DEVICE_CONFIG_CONTAINER:
10648c2ecf20Sopenharmony_ci			f34->v7.img.lockdown.data = content;
10658c2ecf20Sopenharmony_ci			f34->v7.img.lockdown.size = length;
10668c2ecf20Sopenharmony_ci			break;
10678c2ecf20Sopenharmony_ci		default:
10688c2ecf20Sopenharmony_ci			break;
10698c2ecf20Sopenharmony_ci		}
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci}
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_cistatic void rmi_f34v7_parse_image_header_10(struct f34_data *f34)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	unsigned int i;
10768c2ecf20Sopenharmony_ci	unsigned int num_of_containers;
10778c2ecf20Sopenharmony_ci	unsigned int addr;
10788c2ecf20Sopenharmony_ci	unsigned int offset;
10798c2ecf20Sopenharmony_ci	unsigned int container_id;
10808c2ecf20Sopenharmony_ci	unsigned int length;
10818c2ecf20Sopenharmony_ci	const void *image = f34->v7.image;
10828c2ecf20Sopenharmony_ci	const u8 *content;
10838c2ecf20Sopenharmony_ci	const struct container_descriptor *descriptor;
10848c2ecf20Sopenharmony_ci	const struct image_header_10 *header = image;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	f34->v7.img.checksum = le32_to_cpu(header->checksum);
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: f34->v7.img.checksum=%X\n",
10898c2ecf20Sopenharmony_ci		__func__, f34->v7.img.checksum);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	/* address of top level container */
10928c2ecf20Sopenharmony_ci	offset = le32_to_cpu(header->top_level_container_start_addr);
10938c2ecf20Sopenharmony_ci	descriptor = image + offset;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	/* address of top level container content */
10968c2ecf20Sopenharmony_ci	offset = le32_to_cpu(descriptor->content_address);
10978c2ecf20Sopenharmony_ci	num_of_containers = le32_to_cpu(descriptor->content_length) / 4;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	for (i = 0; i < num_of_containers; i++) {
11008c2ecf20Sopenharmony_ci		addr = get_unaligned_le32(image + offset);
11018c2ecf20Sopenharmony_ci		offset += 4;
11028c2ecf20Sopenharmony_ci		descriptor = image + addr;
11038c2ecf20Sopenharmony_ci		container_id = le16_to_cpu(descriptor->container_id);
11048c2ecf20Sopenharmony_ci		content = image + le32_to_cpu(descriptor->content_address);
11058c2ecf20Sopenharmony_ci		length = le32_to_cpu(descriptor->content_length);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
11088c2ecf20Sopenharmony_ci			"%s: container_id=%d, length=%d\n", __func__,
11098c2ecf20Sopenharmony_ci			container_id, length);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci		switch (container_id) {
11128c2ecf20Sopenharmony_ci		case UI_CONTAINER:
11138c2ecf20Sopenharmony_ci		case CORE_CODE_CONTAINER:
11148c2ecf20Sopenharmony_ci			f34->v7.img.ui_firmware.data = content;
11158c2ecf20Sopenharmony_ci			f34->v7.img.ui_firmware.size = length;
11168c2ecf20Sopenharmony_ci			break;
11178c2ecf20Sopenharmony_ci		case UI_CONFIG_CONTAINER:
11188c2ecf20Sopenharmony_ci		case CORE_CONFIG_CONTAINER:
11198c2ecf20Sopenharmony_ci			f34->v7.img.ui_config.data = content;
11208c2ecf20Sopenharmony_ci			f34->v7.img.ui_config.size = length;
11218c2ecf20Sopenharmony_ci			break;
11228c2ecf20Sopenharmony_ci		case BL_CONTAINER:
11238c2ecf20Sopenharmony_ci			f34->v7.img.bl_version = *content;
11248c2ecf20Sopenharmony_ci			f34->v7.img.bootloader.data = content;
11258c2ecf20Sopenharmony_ci			f34->v7.img.bootloader.size = length;
11268c2ecf20Sopenharmony_ci			rmi_f34v7_parse_img_header_10_bl_container(f34, image);
11278c2ecf20Sopenharmony_ci			break;
11288c2ecf20Sopenharmony_ci		case GUEST_CODE_CONTAINER:
11298c2ecf20Sopenharmony_ci			f34->v7.img.contains_guest_code = true;
11308c2ecf20Sopenharmony_ci			f34->v7.img.guest_code.data = content;
11318c2ecf20Sopenharmony_ci			f34->v7.img.guest_code.size = length;
11328c2ecf20Sopenharmony_ci			break;
11338c2ecf20Sopenharmony_ci		case DISPLAY_CONFIG_CONTAINER:
11348c2ecf20Sopenharmony_ci			f34->v7.img.contains_display_cfg = true;
11358c2ecf20Sopenharmony_ci			f34->v7.img.dp_config.data = content;
11368c2ecf20Sopenharmony_ci			f34->v7.img.dp_config.size = length;
11378c2ecf20Sopenharmony_ci			break;
11388c2ecf20Sopenharmony_ci		case FLASH_CONFIG_CONTAINER:
11398c2ecf20Sopenharmony_ci			f34->v7.img.contains_flash_config = true;
11408c2ecf20Sopenharmony_ci			f34->v7.img.fl_config.data = content;
11418c2ecf20Sopenharmony_ci			f34->v7.img.fl_config.size = length;
11428c2ecf20Sopenharmony_ci			break;
11438c2ecf20Sopenharmony_ci		case GENERAL_INFORMATION_CONTAINER:
11448c2ecf20Sopenharmony_ci			f34->v7.img.contains_firmware_id = true;
11458c2ecf20Sopenharmony_ci			f34->v7.img.firmware_id =
11468c2ecf20Sopenharmony_ci				get_unaligned_le32(content + 4);
11478c2ecf20Sopenharmony_ci			break;
11488c2ecf20Sopenharmony_ci		default:
11498c2ecf20Sopenharmony_ci			break;
11508c2ecf20Sopenharmony_ci		}
11518c2ecf20Sopenharmony_ci	}
11528c2ecf20Sopenharmony_ci}
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_cistatic int rmi_f34v7_parse_image_info(struct f34_data *f34)
11558c2ecf20Sopenharmony_ci{
11568c2ecf20Sopenharmony_ci	const struct image_header_10 *header = f34->v7.image;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	memset(&f34->v7.img, 0x00, sizeof(f34->v7.img));
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
11618c2ecf20Sopenharmony_ci		"%s: header->major_header_version = %d\n",
11628c2ecf20Sopenharmony_ci		__func__, header->major_header_version);
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	switch (header->major_header_version) {
11658c2ecf20Sopenharmony_ci	case IMAGE_HEADER_VERSION_10:
11668c2ecf20Sopenharmony_ci		rmi_f34v7_parse_image_header_10(f34);
11678c2ecf20Sopenharmony_ci		break;
11688c2ecf20Sopenharmony_ci	default:
11698c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "Unsupported image file format %02X\n",
11708c2ecf20Sopenharmony_ci			header->major_header_version);
11718c2ecf20Sopenharmony_ci		return -EINVAL;
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	if (!f34->v7.img.contains_flash_config) {
11758c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: No flash config in fw image\n",
11768c2ecf20Sopenharmony_ci			__func__);
11778c2ecf20Sopenharmony_ci		return -EINVAL;
11788c2ecf20Sopenharmony_ci	}
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	rmi_f34v7_parse_partition_table(f34, f34->v7.img.fl_config.data,
11818c2ecf20Sopenharmony_ci			&f34->v7.img.blkcount, &f34->v7.img.phyaddr);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	rmi_f34v7_compare_partition_tables(f34);
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci	return 0;
11868c2ecf20Sopenharmony_ci}
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ciint rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
11898c2ecf20Sopenharmony_ci{
11908c2ecf20Sopenharmony_ci	int ret;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev,
11938c2ecf20Sopenharmony_ci					       f34->fn->irq_mask);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	rmi_f34v7_read_queries_bl_version(f34);
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	f34->v7.image = fw->data;
11988c2ecf20Sopenharmony_ci	f34->update_progress = 0;
11998c2ecf20Sopenharmony_ci	f34->update_size = 0;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	ret = rmi_f34v7_parse_image_info(f34);
12028c2ecf20Sopenharmony_ci	if (ret < 0)
12038c2ecf20Sopenharmony_ci		goto fail;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	if (!f34->v7.new_partition_table) {
12068c2ecf20Sopenharmony_ci		ret = rmi_f34v7_check_ui_firmware_size(f34);
12078c2ecf20Sopenharmony_ci		if (ret < 0)
12088c2ecf20Sopenharmony_ci			goto fail;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci		ret = rmi_f34v7_check_ui_config_size(f34);
12118c2ecf20Sopenharmony_ci		if (ret < 0)
12128c2ecf20Sopenharmony_ci			goto fail;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci		if (f34->v7.has_display_cfg &&
12158c2ecf20Sopenharmony_ci		    f34->v7.img.contains_display_cfg) {
12168c2ecf20Sopenharmony_ci			ret = rmi_f34v7_check_dp_config_size(f34);
12178c2ecf20Sopenharmony_ci			if (ret < 0)
12188c2ecf20Sopenharmony_ci				goto fail;
12198c2ecf20Sopenharmony_ci		}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci		if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
12228c2ecf20Sopenharmony_ci			ret = rmi_f34v7_check_guest_code_size(f34);
12238c2ecf20Sopenharmony_ci			if (ret < 0)
12248c2ecf20Sopenharmony_ci				goto fail;
12258c2ecf20Sopenharmony_ci		}
12268c2ecf20Sopenharmony_ci	} else {
12278c2ecf20Sopenharmony_ci		ret = rmi_f34v7_check_bl_config_size(f34);
12288c2ecf20Sopenharmony_ci		if (ret < 0)
12298c2ecf20Sopenharmony_ci			goto fail;
12308c2ecf20Sopenharmony_ci	}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	ret = rmi_f34v7_erase_all(f34);
12338c2ecf20Sopenharmony_ci	if (ret < 0)
12348c2ecf20Sopenharmony_ci		goto fail;
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	if (f34->v7.new_partition_table) {
12378c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_partition_table(f34);
12388c2ecf20Sopenharmony_ci		if (ret < 0)
12398c2ecf20Sopenharmony_ci			goto fail;
12408c2ecf20Sopenharmony_ci		dev_info(&f34->fn->dev, "%s: Partition table programmed\n",
12418c2ecf20Sopenharmony_ci			 __func__);
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Writing firmware (%d bytes)...\n",
12458c2ecf20Sopenharmony_ci		 f34->v7.img.ui_firmware.size);
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_firmware(f34);
12488c2ecf20Sopenharmony_ci	if (ret < 0)
12498c2ecf20Sopenharmony_ci		goto fail;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Writing config (%d bytes)...\n",
12528c2ecf20Sopenharmony_ci		 f34->v7.img.ui_config.size);
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_UI_CONFIG_AREA;
12558c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_ui_config(f34);
12568c2ecf20Sopenharmony_ci	if (ret < 0)
12578c2ecf20Sopenharmony_ci		goto fail;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	if (f34->v7.has_display_cfg && f34->v7.img.contains_display_cfg) {
12608c2ecf20Sopenharmony_ci		dev_info(&f34->fn->dev, "Writing display config...\n");
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci		ret = rmi_f34v7_write_dp_config(f34);
12638c2ecf20Sopenharmony_ci		if (ret < 0)
12648c2ecf20Sopenharmony_ci			goto fail;
12658c2ecf20Sopenharmony_ci	}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if (f34->v7.new_partition_table) {
12688c2ecf20Sopenharmony_ci		if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
12698c2ecf20Sopenharmony_ci			dev_info(&f34->fn->dev, "Writing guest code...\n");
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci			ret = rmi_f34v7_write_guest_code(f34);
12728c2ecf20Sopenharmony_ci			if (ret < 0)
12738c2ecf20Sopenharmony_ci				goto fail;
12748c2ecf20Sopenharmony_ci		}
12758c2ecf20Sopenharmony_ci	}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_cifail:
12788c2ecf20Sopenharmony_ci	return ret;
12798c2ecf20Sopenharmony_ci}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_cistatic int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
12828c2ecf20Sopenharmony_ci{
12838c2ecf20Sopenharmony_ci	int ret;
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	ret = rmi_f34v7_read_flash_status(f34);
12888c2ecf20Sopenharmony_ci	if (ret < 0)
12898c2ecf20Sopenharmony_ci		return ret;
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	if (f34->v7.in_bl_mode)
12928c2ecf20Sopenharmony_ci		return 0;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	ret = rmi_f34v7_write_command(f34, v7_CMD_ENABLE_FLASH_PROG);
12978c2ecf20Sopenharmony_ci	if (ret < 0)
12988c2ecf20Sopenharmony_ci		return ret;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
13018c2ecf20Sopenharmony_ci	if (ret < 0)
13028c2ecf20Sopenharmony_ci		return ret;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	return 0;
13058c2ecf20Sopenharmony_ci}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ciint rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw)
13088c2ecf20Sopenharmony_ci{
13098c2ecf20Sopenharmony_ci	int ret = 0;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask);
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	f34->v7.config_area = v7_UI_CONFIG_AREA;
13148c2ecf20Sopenharmony_ci	f34->v7.image = fw->data;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	ret = rmi_f34v7_parse_image_info(f34);
13178c2ecf20Sopenharmony_ci	if (ret < 0)
13188c2ecf20Sopenharmony_ci		goto exit;
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	if (!f34->v7.force_update && f34->v7.new_partition_table) {
13218c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Partition table mismatch\n",
13228c2ecf20Sopenharmony_ci				__func__);
13238c2ecf20Sopenharmony_ci		ret = -EINVAL;
13248c2ecf20Sopenharmony_ci		goto exit;
13258c2ecf20Sopenharmony_ci	}
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	dev_info(&f34->fn->dev, "Firmware image OK\n");
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	ret = rmi_f34v7_read_flash_status(f34);
13308c2ecf20Sopenharmony_ci	if (ret < 0)
13318c2ecf20Sopenharmony_ci		goto exit;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	if (f34->v7.in_bl_mode) {
13348c2ecf20Sopenharmony_ci		dev_info(&f34->fn->dev, "%s: Device in bootloader mode\n",
13358c2ecf20Sopenharmony_ci				__func__);
13368c2ecf20Sopenharmony_ci	}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	rmi_f34v7_enter_flash_prog(f34);
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	return 0;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ciexit:
13438c2ecf20Sopenharmony_ci	return ret;
13448c2ecf20Sopenharmony_ci}
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ciint rmi_f34v7_probe(struct f34_data *f34)
13478c2ecf20Sopenharmony_ci{
13488c2ecf20Sopenharmony_ci	int ret;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	/* Read bootloader version */
13518c2ecf20Sopenharmony_ci	ret = rmi_read_block(f34->fn->rmi_dev,
13528c2ecf20Sopenharmony_ci			f34->fn->fd.query_base_addr + V7_BOOTLOADER_ID_OFFSET,
13538c2ecf20Sopenharmony_ci			f34->bootloader_id,
13548c2ecf20Sopenharmony_ci			sizeof(f34->bootloader_id));
13558c2ecf20Sopenharmony_ci	if (ret < 0) {
13568c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev, "%s: Failed to read bootloader ID\n",
13578c2ecf20Sopenharmony_ci			__func__);
13588c2ecf20Sopenharmony_ci		return ret;
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	if (f34->bootloader_id[1] == '5') {
13628c2ecf20Sopenharmony_ci		f34->bl_version = 5;
13638c2ecf20Sopenharmony_ci	} else if (f34->bootloader_id[1] == '6') {
13648c2ecf20Sopenharmony_ci		f34->bl_version = 6;
13658c2ecf20Sopenharmony_ci	} else if (f34->bootloader_id[1] == 7) {
13668c2ecf20Sopenharmony_ci		f34->bl_version = 7;
13678c2ecf20Sopenharmony_ci	} else if (f34->bootloader_id[1] == 8) {
13688c2ecf20Sopenharmony_ci		f34->bl_version = 8;
13698c2ecf20Sopenharmony_ci	} else {
13708c2ecf20Sopenharmony_ci		dev_err(&f34->fn->dev,
13718c2ecf20Sopenharmony_ci			"%s: Unrecognized bootloader version: %d (%c) %d (%c)\n",
13728c2ecf20Sopenharmony_ci			__func__,
13738c2ecf20Sopenharmony_ci			f34->bootloader_id[0], f34->bootloader_id[0],
13748c2ecf20Sopenharmony_ci			f34->bootloader_id[1], f34->bootloader_id[1]);
13758c2ecf20Sopenharmony_ci		return -EINVAL;
13768c2ecf20Sopenharmony_ci	}
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	memset(&f34->v7.blkcount, 0x00, sizeof(f34->v7.blkcount));
13798c2ecf20Sopenharmony_ci	memset(&f34->v7.phyaddr, 0x00, sizeof(f34->v7.phyaddr));
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	init_completion(&f34->v7.cmd_done);
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	ret = rmi_f34v7_read_queries(f34);
13848c2ecf20Sopenharmony_ci	if (ret < 0)
13858c2ecf20Sopenharmony_ci		return ret;
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci	f34->v7.force_update = true;
13888c2ecf20Sopenharmony_ci	return 0;
13898c2ecf20Sopenharmony_ci}
1390