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


static int sysconfig_i2c_bitstream_burst_init(struct sysconfig_priv *priv)
{
    const u8 lsc_bitstream_burst[] = SYSCONFIG_LSC_BITSTREAM_BURST;
    struct i2c_client *client = to_i2c_client(priv->dev);
    int ret;

    /* 
     * Инициализируем сессию. Передаем команду начала burst-записи.
     * Здесь флаг I2C_M_NOSTART НЕ используется, так как нам НАДО 
     * передать адрес устройства и сгенерировать START.
     */
    ret = i2c_master_send(client, lsc_bitstream_burst, sizeof(lsc_bitstream_burst));
    if (ret < 0) {
        dev_err(priv->dev, "Burst init failed: %d\n", ret);
        return ret;
    }

    return (ret == sizeof(lsc_bitstream_burst)) ? 0 : -EIO;
}

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;
    size_t offset = 0;
    int ret;

    if (len == 0)
        return 0;

    /* 
     * БЕЗОПАСНАЯ ПАКЕТНАЯ ПЕРЕДАЧА:
     * Нарезаем 4КБ буфер ядра на безопасные для i.MX95 чанки по 64 байта.
     * Флаг I2C_M_NOSTART гарантирует, что весь массив уйдет как один
     * сплошной бесконечный поток байт (payload) без перезапуска шины.
     */
    while (offset < len) {
        size_t chunk_size = min((size_t)64, len - offset);

        msg.addr = client->addr;
        msg.flags = (client->flags & I2C_M_TEN) | I2C_M_NOSTART;
        msg.len = chunk_size;
        msg.buf = (u8 *)(buf + offset);

        ret = i2c_transfer(client->adapter, &msg, 1);
        if (ret < 0) {
            dev_err(priv->dev, "I2C burst chunk write failed at offset %f: %d\n", (double)offset, ret);
            return ret;
        }
        if (ret != 1) {
            dev_err(priv->dev, "I2C burst chunk write incomplete at offset %f\n", (double)offset);
            return -EIO;
        }

        offset += chunk_size;
    }

    return 0;
}

static int sysconfig_i2c_bitstream_burst_complete(struct sysconfig_priv *priv)
{
    struct i2c_client *client = to_i2c_client(priv->dev);
    u8 dummy = 0xFF;
    struct i2c_msg msg;
    int ret;

    /* 
     * ФИНАЛИЗАЦИЯ:
     * Чтобы завершить трансляцию и отпустить ПЛИС в рабочий режим,
     * отправляем финальный холостой байт БЕЗ флага I2C_M_NOSTART.
     * Контроллер i.MX95 сгенерирует аппаратный STOP-бит на шине.
     */
    msg.addr = client->addr;
    msg.flags = client->flags & I2C_M_TEN; // Без NOSTART!
    msg.len = 1;
    msg.buf = &dummy;

    ret = i2c_transfer(client->adapter, &msg, 1);
    if (ret < 0) {
        dev_err(priv->dev, "Burst complete STOP generation failed: %d\n", ret);
        return ret;
    }

    dev_info(priv->dev, "I2C Bitstream transfer complete. FPGA should boot now.\n");
    return 0;
}