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;
const u8 lsc_bitstream_burst[] = { 0x7A, 0x00, 0x00, 0x00 };
int ret;
if (len == 0)
return 0;
/* 1. Вычисляем строгое выравнивание до кратности 4 байтам */
size_t aligned_len = (len + 3) & ~3;
size_t total_padding = aligned_len - len;
/* 2. Выделяем ОДИН большой монолитный буфер под команду + всю прошивку + паддинг */
size_t total_alloc_size = sizeof(lsc_bitstream_burst) + aligned_len;
u8 *tx_buf = kmalloc(total_alloc_size, GFP_KERNEL);
if (!tx_buf)
return -ENOMEM;
/* 3. Копируем команду 0x7A 00 00 00 в самое начало буфера */
memcpy(tx_buf, lsc_bitstream_burst, sizeof(lsc_bitstream_burst));
/* 4. Копируем весь ваш файл целиком строго следом */
memcpy(tx_buf + sizeof(lsc_bitstream_burst), buf, len);
/* 5. Забиваем самый хвост буфера байтами NOP (0xFF) */
if (total_padding > 0) {
memset(tx_buf + sizeof(lsc_bitstream_burst) + len, 0xFF, total_padding);
}
printk("%s: Launching monolithic DMA transfer. Total size = %zu bytes\n",
__FUNCTION__, total_alloc_size);
/* 6. Описываем ОДНО единственное I2C-сообщение (num = 1) */
msg.addr = client->addr;
msg.flags = 0; // Чистый режим записи
msg.len = total_alloc_size;
msg.buf = tx_buf;
/* 7. Передаем в lpi2c. Контроллер сделает один START, один запуск DMA и один STOP в конце */
ret = i2c_transfer(client->adapter, &msg, 1);
kfree(tx_buf);
if (ret != 1) {
dev_err(priv->dev, "Monolithic DMA transfer failed: %d\n", ret);
return (ret < 0) ? ret : -EIO;
}
return 0;
}