lif_md6000@40 {
compatible = "fpga,fpga_csi_bridge";
reg = <0x40>;
status = "okay";
rst-gpios = <&i2c3_gpio_expander_20 2 GPIO_ACTIVE_LOW>;
/* Аппаратные линии sysCONFIG для Lattice CrossLink-NX */
program-gpios = <&i2c4_gpio_expander 4 GPIO_ACTIVE_LOW>; /* P4 расширителя PCAL6408 */
init-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* GPIO2_IO25 */
done-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; /* GPIO2_IO27 */
#address-cells = <1>;
#size-cells = <0>;
};
priv->fpga_priv.dev = dev;
priv->fpga_priv.command_transfer = sysconfig_i2c_cmd_transfer;
priv->fpga_priv.bitstream_burst_write_init = sysconfig_i2c_bitstream_burst_init;
priv->fpga_priv.bitstream_burst_write = sysconfig_i2c_bitstream_burst_write;
priv->fpga_priv.bitstream_burst_write_complete = sysconfig_i2c_bitstream_burst_complete;
/*
* Запрашиваем дескрипторы из Device Tree.
* Для program и init выставляем начальное состояние GPIOD_OUT_LOW,
* чтобы линии подтянулись к логической единице (так как ACTIVE_LOW инвертирует их)
* и не мешали нормальной работе до старта прошивки.
*/
priv->program = devm_gpiod_get_optional(&client->dev, "program", GPIOD_OUT_LOW);
if (IS_ERR(priv->program)) {
dev_err(dev, "Failed to get program GPIO\n");
return PTR_ERR(priv->program);
}
priv->init = devm_gpiod_get_optional(&client->dev, "init", GPIOD_OUT_LOW);
if (IS_ERR(priv->init)) {
dev_err(dev, "Failed to get init GPIO\n");
return PTR_ERR(priv->init);
}
/* DONE запрашиваем как входной пин для опроса состояния */
priv->done = devm_gpiod_get_optional(&client->dev, "done", GPIOD_IN);
if (IS_ERR(priv->done)) {
dev_err(dev, "Failed to get done GPIO\n");
return PTR_ERR(priv->done);
}
/*
* КРИТИЧЕСКИЙ ШАГ: Передаем полученные GPIO внутрь структуры sysconfig.
* Без этого шага ядро lattice-sysconfig.c не узнает о них
* и продолжит использовать дедлок-режим опроса статуса по I2C!
*/
priv->fpga_priv.program = priv->program;
priv->fpga_priv.init = priv->init;
priv->fpga_priv.done = priv->done;
/* Запускаем универсальный прошивальщик ядра */
ret = sysconfig_probe(&priv->fpga_priv);