Exemplo n.º 1
0
static int spi_read_wait_chg(struct ssp_data *data, uint8_t *buffer, int len)
{
	int ret;

	ret = ssp_wait_for_chg(data);

	if (ret < 0) {
		pr_err("[SSP] Error %d while waiting for chg\n", ret);
	}

	ret = spi_read(data->spi, buffer, len);

	if (ret < 0) {
		pr_err("[SSP] Error in %d spi_read()\n", ret);
	}

	return ret;
}
static int load_kernel_fw_bootmode(struct i2c_client *client, const char *pFn)
{
	const struct firmware *fw = NULL;
	unsigned int uFrameSize;
	unsigned int uPos = 0;
	int iRet;
	int iCheckFrameCrcError = 0;
	int iCheckWatingFrameDataError = 0;
	int count = 0;
	struct ssp_data *data = i2c_get_clientdata(client);

	pr_info("[SSP] ssp_load_fw start!!!\n");

	iRet = request_firmware(&fw, pFn, &client->dev);
	if (iRet) {
		pr_err("[SSP]: %s - Unable to open firmware %s\n",
			__func__, pFn);
		return iRet;
	}

	/* Unlock bootloader */
	iRet = unlock_bootloader(client);
	if (iRet < 0) {
		pr_err("[SSP] %s - unlock_bootloader failed! %d\n",
			__func__, iRet);
		goto out;
	}

	while (uPos < fw->size) {
		if (data->ssp_changes == SSP_MCU_L5) {
			iRet = ssp_wait_for_chg(data);
			if (iRet < 0) {
				pr_err("[SSP] %s - ssp_wait_for_chg failed! %d\n",
					__func__, iRet);
				goto out;
			}
		}
		iRet = check_bootloader(client, BL_WAITING_FRAME_DATA);
		if (iRet) {
			iCheckWatingFrameDataError++;
			if (iCheckWatingFrameDataError > 10) {
				pr_err("[SSP]: %s - F/W update fail\n",
					__func__);
				goto out;
			} else {
				pr_err("[SSP]: %s - F/W data_error %d, retry\n",
					__func__, iCheckWatingFrameDataError);
				continue;
			}
		}

		uFrameSize = ((*(fw->data + uPos) << 8) |
			*(fw->data + uPos + 1));

		/* We should add 2 at frame size as the the firmware data is not
		*  included the CRC bytes.
		*/
		uFrameSize += 2;

		/* Write one frame to device */
		fw_write(client, fw->data + uPos, uFrameSize);
		if (data->ssp_changes == SSP_MCU_L5) {
			iRet = ssp_wait_for_chg(data);
			if (iRet < 0) {
				pr_err("[SSP] %s - ssp_wait_for_chg failed! %d\n",
					__func__, iRet);
				goto out;
			}
		}
		iRet = check_bootloader(client, BL_FRAME_CRC_PASS);
		if (iRet) {
			iCheckFrameCrcError++;
			if (iCheckFrameCrcError > 10) {
				pr_err("[SSP]: %s - F/W Update Fail. crc err\n",
					__func__);
				goto out;
			} else {
				pr_err("[SSP]: %s - F/W crc_error %d, retry\n",
					__func__, iCheckFrameCrcError);
				continue;
			}
		}

		uPos += uFrameSize;
		if (count++ == 100) {
			pr_info("[SSP] Updated %d bytes / %zd bytes\n", uPos,
				fw->size);
			count = 0;
		}
		mdelay(1);
	}
	pr_info("[SSP] Firmware download is success.(%d bytes)\n", uPos);
out:
	release_firmware(fw);
	return iRet;
}
static int check_bootloader(struct i2c_client *client, unsigned int uState)
{
	u8 uVal;
	u8 uTemp;
	struct ssp_data *data = i2c_get_clientdata(client);

recheck:
	if (i2c_master_recv(client, &uVal, 1) != 1)
		return -EIO;

	pr_debug("%s, uVal = 0x%x\n", __func__, uVal);
	if (uVal & 0x20) {
		if (i2c_master_recv(client, &uTemp, 1) != 1) {
			pr_err("[SSP]: %s - i2c recv fail\n", __func__);
			return -EIO;
		}

		if (i2c_master_recv(client, &uTemp, 1) != 1) {
			pr_err("[SSP]: %s - i2c recv fail\n", __func__);
			return -EIO;
		}

		uVal &= ~0x20;
	}

	if ((uVal & 0xF0) == BL_APP_CRC_FAIL) {
		pr_info("[SSP] SSP_APP_CRC_FAIL - There is no bootloader.\n");
		if (i2c_master_recv(client, &uVal, 1) != 1) {
			pr_err("[SSP]: %s - i2c recv fail\n", __func__);
			return -EIO;
		}

		if (uVal & 0x20) {
			if (i2c_master_recv(client, &uTemp, 1) != 1) {
				pr_err("[SSP]: %s - i2c recv fail\n", __func__);
				return -EIO;
			}

			if (i2c_master_recv(client, &uTemp, 1) != 1) {
				pr_err("[SSP]: %s - i2c recv fail\n", __func__);
				return -EIO;
			}

			uVal &= ~0x20;
		}
	}

	switch (uState) {
	case BL_WAITING_BOOTLOAD_CMD:
	case BL_WAITING_FRAME_DATA:
		uVal &= ~BL_BOOT_STATUS_MASK;
		break;
	case BL_FRAME_CRC_PASS:
		if (uVal == BL_FRAME_CRC_CHECK) {
			if (data->ssp_changes == SSP_MCU_L5)
				ssp_wait_for_chg(data);
			goto recheck;
		}
		break;
	default:
		return -EINVAL;
	}

	if (uVal != uState) {
		pr_err("[SSP]: %s - Invalid bootloader mode state\n", __func__);
		return -EINVAL;
	}

	return 0;
}
static int load_ums_fw_bootmode(struct i2c_client *client, const char *pFn)
{
	const u8 *buff = NULL;
	char fw_path[BL_UMS_FW_PATH+1];
	unsigned int uFrameSize;
	unsigned int uFSize = 0, uNRead = 0;
	unsigned int uPos = 0;
	int iRet = SUCCESS;
	int iCheckFrameCrcError = 0;
	int iCheckWatingFrameDataError = 0;
	int count = 0;
	struct file *fp = NULL;
	mm_segment_t old_fs = get_fs();
	struct ssp_data *data = i2c_get_clientdata(client);

	pr_info("[SSP] ssp_load_ums_fw start!!!\n");

	old_fs = get_fs();
	set_fs(get_ds());

	snprintf(fw_path, BL_UMS_FW_PATH, "/sdcard/ssp/%s", pFn);

	fp = filp_open(fw_path, O_RDONLY, 0);
	if (IS_ERR(fp)) {
		iRet = ERROR;
		pr_err("file %s open error:%d\n", fw_path, (s32)fp);
		goto err_open;
	}

	uFSize = (unsigned int)fp->f_path.dentry->d_inode->i_size;
	pr_info("ssp_load_ums firmware size: %u\n", uFSize);

	buff = kzalloc((size_t)uFSize, GFP_KERNEL);
	if (!buff) {
		iRet = ERROR;
		pr_err("fail to alloc buffer for fw\n");
		goto err_alloc;
	}

	uNRead = (unsigned int)vfs_read(fp, (char __user *)buff,
			(unsigned int)uFSize, &fp->f_pos);
	if (uNRead != uFSize) {
		iRet = ERROR;
		pr_err("fail to read file %s (nread = %u)\n", fw_path, uNRead);
		goto err_fw_size;
	}

	/* Unlock bootloader */
	iRet = unlock_bootloader(client);
	if (iRet < 0) {
		pr_err("[SSP] %s - unlock_bootloader failed! %d\n",
			__func__, iRet);
		goto out;
	}

	while (uPos < uFSize) {
		if (data->ssp_changes == SSP_MCU_L5) {
			iRet = ssp_wait_for_chg(data);
			if (iRet < 0) {
				pr_err("[SSP] %s - ssp_wait_for_chg failed! %d\n",
					__func__, iRet);
				goto out;
			}
		}
		if (check_bootloader(client, BL_WAITING_FRAME_DATA)) {
			iCheckWatingFrameDataError++;
			if (iCheckWatingFrameDataError > 10) {
				iRet = ERROR;
				pr_err("[SSP]: %s - F/W update fail\n",
					__func__);
				goto out;
			} else {
				pr_err("[SSP]: %s - F/W data_error %d, retry\n",
					__func__, iCheckWatingFrameDataError);
				continue;
			}
		}

		uFrameSize = (unsigned int)((*(buff + uPos) << 8) |
			*(buff + uPos + 1));

		/* We should add 2 at frame size as the the firmware data is not
		*  included the CRC bytes.
		*/
		uFrameSize += 2;

		/* Write one frame to device */
		fw_write(client, buff + uPos, uFrameSize);
		if (data->ssp_changes == SSP_MCU_L5) {
			iRet = ssp_wait_for_chg(data);
			if (iRet < 0) {
				pr_err("[SSP] %s - ssp_wait_for_chg failed! %d\n",
					__func__, iRet);
				goto out;
			}
		}
		if (check_bootloader(client, BL_FRAME_CRC_PASS)) {
			iCheckFrameCrcError++;
			if (iCheckFrameCrcError > 10) {
				iRet = ERROR;
				pr_err("[SSP]: %s - F/W Update Fail. crc err\n",
					__func__);
				goto out;
			} else {
				pr_err("[SSP]: %s - F/W crc_error %d, retry\n",
					__func__, iCheckFrameCrcError);
				continue;
			}
		}

		uPos += uFrameSize;
		if (count++ == 100) {
			pr_info("[SSP] Updated %u bytes / %u bytes\n", uPos,
				uFSize);
			count = 0;
		}

		mdelay(1);
	}

out:
err_fw_size:
	kfree(buff);
err_alloc:
	filp_close(fp, NULL);
err_open:
	set_fs(old_fs);

	return iRet;
}