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


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 chunk_size = 256; /* Строго 256 байт - аппаратный лимит регистра MTDR NXP */
    size_t offset = 0;
    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 сообщение под команду (со START) + N сообщений под данные (с NOSTART) */
    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.addr = client->addr;
    msgs.flags = client->flags & I2C_M_TEN;
    msgs.len = sizeof(lsc_bitstream_burst);
    msgs.buf = (u8 *)lsc_bitstream_burst;

    // Заполняем цепочку сообщениями строго по 256 байт со сброшенным START
    for (i = 1; i <= data_chunks; i++) {
        size_t current_chunk = min(chunk_size, len - offset);

        msgs[i].addr = client->addr;
        /* Флаг NOSTART принудительно переключит lpi2c_imx_xfer в чистый PIO режим */
        msgs[i].flags = (client->flags & I2C_M_TEN) | I2C_M_NOSTART;

        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;
    }

    dev_info(priv->dev, "Submitting %d messages (strictly 256 bytes each) via PIO/NOSTART...\n", num_msgs);

    /* Вызываем атомарный i2c_transfer */
    ret = i2c_transfer(client->adapter, msgs, num_msgs);
    
    if (ret == num_msgs) {
        ret = 0;
        dev_info(priv->dev, "Bitstream successfully transmitted via segmented PIO!\n");
    } else {
        dev_err(priv->dev, "Segmented PIO transfer failed: %d\n", ret);
        ret = (ret < 0) ? ret : -EIO;
    }

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