Загрузка данных


/* Флаг для отслеживания первой транзакции */
static bool is_first_burst_chunk = true;

static int sysconfig_i2c_bitstream_burst_init(struct sysconfig_priv *priv)
{
	/* 
	 * ВАЖНО: Больше не шлем команду отдельно, чтобы не генерировать STOP на шине.
	 * Просто взводим флаг готовности к первой передаче.
	 */
	is_first_burst_chunk = true;
	return 0;
}

static int sysconfig_i2c_bitstream_burst_write(struct sysconfig_priv *priv,
					       const char *buf, size_t len)
{
	struct i2c_client *client = to_i2c_client(priv->dev);
	struct i2c_msg msg;
	int ret;

	if (len == 0)
		return 0;

	if (is_first_burst_chunk) {
		/* 
		 * Для самой первой пачки данных мы обязаны склеить 
		 * команду BURST_WRITE (4 байта) и начало файла прошивки.
		 */
		u8 burst_cmd[] = SYSCONFIG_LSC_BITSTREAM_BURST;
		size_t tx_len = sizeof(burst_cmd) + len;
		u8 *tx_buf;

		tx_buf = kmalloc(tx_len, GFP_KERNEL);
		if (!tx_buf)
			return -ENOMEM;

		/* Копируем команду 0x7A, 0x00, 0x00, 0x00 */
		memcpy(tx_buf, burst_cmd, sizeof(burst_cmd));
		/* Следом копируем первый кусок прошивки */
		memcpy(tx_buf + sizeof(burst_cmd), buf, len);

		msg.addr = client->addr;
		msg.flags = client->flags & I2C_M_TEN; /* СТАНДАРТНЫЙ СТАРТ (открываем шину) */
		msg.len = tx_len;
		msg.buf = tx_buf;

		dev_info(priv->dev, "Sending burst command merged with first chunk (%zu bytes)...\n", tx_len);
		ret = i2c_transfer(client->adapter, &msg, 1);
		kfree(tx_buf);

		if (ret < 0)
			return ret;
		if (ret != 1)
			return -EIO;

		is_first_burst_chunk = false;
	} else {
		/* 
		 * Все последующие куски файла шлем стандартно через NOSTART.
		 * Теперь это безопасно, так как шина уже была открыта первой транзакцией!
		 */
		msg.addr = client->addr;
		msg.flags = (client->flags & I2C_M_TEN) | I2C_M_NOSTART;
		msg.len = len;
		msg.buf = (u8 *)buf;

		ret = i2c_transfer(client->adapter, &msg, 1);
		if (ret < 0)
			return ret;
		if (ret != 1)
			return -EIO;
	}

	/* Небольшая пауза для стабильности автомата ПЛИС */
	usleep_range(100, 200);

	return 0;
}