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


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 *msgs;
    const u8 lsc_bitstream_burst[] = SYSCONFIG_LSC_BITSTREAM_BURST; // 0x7A, 0x00, 0x00, 0x00
    size_t offset = 0;
    size_t chunk_size = 4096;
    int num_msgs, i, ret;
    u8 *padded_buf = NULL;

    if (len == 0)
        return 0;

    size_t aligned_len = (len + 3) & ~3;
    size_t total_padding = aligned_len - len;

    /* 1 сообщение под команду + N сообщений под данные */
    int data_chunks = (len + chunk_size - 1) / chunk_size;
    num_msgs = 1 + data_chunks;

    msgs = kmalloc_array(num_msgs, sizeof(struct i2c_msg), GFP_KERNEL);
    if (!msgs)
        return -ENOMEM;

    // Сообщение 0: Команда инициализации BURST (Генерирует START)
    msgs[0].addr = client->addr;
    msgs[0].flags = client->flags & I2C_M_TEN;
    msgs[0].len = sizeof(lsc_bitstream_burst);
    msgs[0].buf = (u8 *)lsc_bitstream_burst;

    // Заполняем сообщения для чанков данных
    for (i = 1; i <= data_chunks; i++) {
        size_t current_chunk = min(chunk_size, len - offset);

        msgs[i].addr = client->addr;
        /* Все последующие сообщения удерживают шину без повторного START */
        msgs[i].flags = (client->flags & I2C_M_TEN) | I2C_M_NOSTART;

        /* Проверяем, последний ли это чанк и нужен ли padding */
        if (offset + current_chunk == len && total_padding > 0) {
            size_t padded_size = current_chunk + total_padding;
            padded_buf = kmalloc(padded_size, GFP_KERNEL);
            if (!padded_buf) {
                ret = -ENOMEM;
                goto free_msgs;
            }

            memcpy(padded_buf, buf + offset, current_chunk);
            memset(padded_buf + current_chunk, 0xFF, total_padding);

            msgs[i].len = padded_size;
            msgs[i].buf = padded_buf;
        } else {
            msgs[i].len = current_chunk;
            msgs[i].buf = (u8 *)(buf + offset);
        }

        offset += current_chunk;
    }

    /* Отправляем ВСЮ прошивку за один атомарный шаг подсистемы I2C */
    ret = i2c_transfer(client->adapter, msgs, num_msgs);
    
    if (ret == num_msgs) {
        ret = 0;
        printk("%s(%d) Burst stream successfully transmitted\n", __FUNCTION__, __LINE__);
    } else {
        dev_err(priv->dev, "I2C single-pass burst transfer failed: %d\n", ret);
        ret = (ret < 0) ? ret : -EIO;
    }

free_msgs:
    kfree(padded_buf);
    kfree(msgs);
    return ret;
}