drivers/fmc: carrier can program FPGA on registration
The initial FPGA may require programming before it is useful. Signed-off-by: Federico Vaga <federico.vaga@cern.ch> Tested-by: Pat Riehecky <riehecky@fnal.gov> Acked-by: Alessandro Rubini <rubini@gnudd.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
15b1b0f0d8
Коммит
9c0dda1495
|
@ -280,6 +280,21 @@ int fmc_device_register_n_gw(struct fmc_device **devs, int n,
|
|||
else
|
||||
dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
|
||||
device_id);
|
||||
|
||||
if (gw) {
|
||||
/*
|
||||
* The carrier already know the bitstream to load
|
||||
* for this set of FMC mezzanines.
|
||||
*/
|
||||
ret = fmc->op->reprogram_raw(fmc, NULL,
|
||||
gw->bitstream, gw->len);
|
||||
if (ret) {
|
||||
dev_warn(fmc->hwdev,
|
||||
"Invalid gateware for FMC mezzanine\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = device_add(&fmc->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(fmc->hwdev, "Slot %i: Failed in registering "
|
||||
|
@ -300,9 +315,6 @@ int fmc_device_register_n_gw(struct fmc_device **devs, int n,
|
|||
out1:
|
||||
device_del(&fmc->dev);
|
||||
out:
|
||||
fmc_free_id_info(fmc);
|
||||
put_device(&fmc->dev);
|
||||
|
||||
kfree(devarray);
|
||||
for (i--; i >= 0; i--) {
|
||||
fmc_debug_exit(devs[i]);
|
||||
|
|
|
@ -126,6 +126,30 @@ int fmc_free_sdb_tree(struct fmc_device *fmc)
|
|||
}
|
||||
EXPORT_SYMBOL(fmc_free_sdb_tree);
|
||||
|
||||
/* This helper calls reprogram and inizialized sdb as well */
|
||||
int fmc_reprogram_raw(struct fmc_device *fmc, struct fmc_driver *d,
|
||||
void *gw, unsigned long len, int sdb_entry)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fmc->op->reprogram_raw(fmc, d, gw, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (sdb_entry < 0)
|
||||
return ret;
|
||||
|
||||
/* We are required to find SDB at a given offset */
|
||||
ret = fmc_scan_sdb_tree(fmc, sdb_entry);
|
||||
if (ret < 0) {
|
||||
dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n",
|
||||
sdb_entry);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fmc_reprogram_raw);
|
||||
|
||||
/* This helper calls reprogram and inizialized sdb as well */
|
||||
int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
|
||||
int sdb_entry)
|
||||
|
|
|
@ -132,6 +132,8 @@ struct fmc_operations {
|
|||
uint32_t (*read32)(struct fmc_device *fmc, int offset);
|
||||
void (*write32)(struct fmc_device *fmc, uint32_t value, int offset);
|
||||
int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv);
|
||||
int (*reprogram_raw)(struct fmc_device *f, struct fmc_driver *d,
|
||||
void *gw, unsigned long len);
|
||||
int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw);
|
||||
int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
|
||||
char *name, int flags);
|
||||
|
@ -144,6 +146,8 @@ struct fmc_operations {
|
|||
};
|
||||
|
||||
/* Prefer this helper rather than calling of fmc->reprogram directly */
|
||||
int fmc_reprogram_raw(struct fmc_device *fmc, struct fmc_driver *d,
|
||||
void *gw, unsigned long len, int sdb_entry);
|
||||
extern int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw,
|
||||
int sdb_entry);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче