// SPDX-License-Identifier: GPL-2.0-only /* * Altera Passive Serial SPI Driver * * Copyright (c) 2017 United Western Technologies, Corporation * * Joshua Clayton <stillcompiling@gmail.com> * * Manage Altera FPGA firmware that is loaded over SPI using the passive * serial configuration method. * Firmware must be in binary "rbf" format. * Works on Arria 10, Cyclone V and Stratix V. Should work on Cyclone series. * May work on other Altera FPGAs.
*/
if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); return -EINVAL;
}
gpiod_set_value_cansleep(conf->config, 1);
/* wait min reset pulse time */
altera_ps_delay(conf->data->t_cfg_us);
if (!gpiod_get_value_cansleep(conf->status)) {
dev_err(&mgr->dev, "Status pin failed to show a reset\n"); return -EIO;
}
gpiod_set_value_cansleep(conf->config, 0);
min = conf->data->status_wait_min_us;
max = conf->data->status_wait_max_us;
waits = max / min; if (max % min)
waits++;
/* wait for max { max(t_STATUS), max(t_CF2ST1) } */ for (i = 0; i < waits; i++) {
usleep_range(min, min + 10); if (!gpiod_get_value_cansleep(conf->status)) { /* wait for min(t_ST2CK)*/
altera_ps_delay(conf->data->t_st2ck_us); return 0;
}
}
dev_err(&mgr->dev, "Status pin not ready.\n"); return -EIO;
}
if (gpiod_get_value_cansleep(conf->status)) {
dev_err(&mgr->dev, "Error during configuration.\n"); return -EIO;
}
if (conf->confd) { if (!gpiod_get_raw_value_cansleep(conf->confd)) {
dev_err(&mgr->dev, "CONF_DONE is inactive!\n"); return -EIO;
}
}
/* * After CONF_DONE goes high, send two additional falling edges on DCLK * to begin initialization and enter user mode
*/
ret = spi_write(conf->spi, dummy, 1); if (ret) {
dev_err(&mgr->dev, "spi error during end sequence: %d\n", ret); return ret;
}
conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); if (!conf) return -ENOMEM;
conf->data = spi_get_device_match_data(spi);
conf->spi = spi;
conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_LOW); if (IS_ERR(conf->config)) {
dev_err(&spi->dev, "Failed to get config gpio: %ld\n",
PTR_ERR(conf->config)); return PTR_ERR(conf->config);
}
conf->status = devm_gpiod_get(&spi->dev, "nstat", GPIOD_IN); if (IS_ERR(conf->status)) {
dev_err(&spi->dev, "Failed to get status gpio: %ld\n",
PTR_ERR(conf->status)); return PTR_ERR(conf->status);
}
conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN); if (IS_ERR(conf->confd)) {
dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
PTR_ERR(conf->confd)); return PTR_ERR(conf->confd);
} elseif (!conf->confd) {
dev_warn(&spi->dev, "Not using confd gpio");
}
/* Register manager with unique name */
snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s",
dev_driver_string(&spi->dev), dev_name(&spi->dev));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.