Commit 13e4f901 authored by Federico Vaga's avatar Federico Vaga

Program FPGA right after device creation

parents be8b33e0 8fda123d
...@@ -199,7 +199,8 @@ EXPORT_SYMBOL(fmc_driver_unregister); ...@@ -199,7 +199,8 @@ EXPORT_SYMBOL(fmc_driver_unregister);
* When a device set is registered, all eeproms must be read * When a device set is registered, all eeproms must be read
* and all FRUs must be parsed * and all FRUs must be parsed
*/ */
int fmc_device_register_n(struct fmc_device **devs, int n) int fmc_device_register_n_gw(struct fmc_device **devs, int n,
struct fmc_gateware *gw)
{ {
struct fmc_device *fmc, **devarray; struct fmc_device *fmc, **devarray;
uint32_t device_id; uint32_t device_id;
...@@ -279,6 +280,21 @@ int fmc_device_register_n(struct fmc_device **devs, int n) ...@@ -279,6 +280,21 @@ int fmc_device_register_n(struct fmc_device **devs, int n)
else else
dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name, dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
device_id); 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); ret = device_add(&fmc->dev);
if (ret < 0) { if (ret < 0) {
dev_err(fmc->hwdev, "Slot %i: Failed in registering " dev_err(fmc->hwdev, "Slot %i: Failed in registering "
...@@ -299,9 +315,6 @@ int fmc_device_register_n(struct fmc_device **devs, int n) ...@@ -299,9 +315,6 @@ int fmc_device_register_n(struct fmc_device **devs, int n)
out1: out1:
device_del(&fmc->dev); device_del(&fmc->dev);
out: out:
fmc_free_id_info(fmc);
put_device(&fmc->dev);
kfree(devarray); kfree(devarray);
for (i--; i >= 0; i--) { for (i--; i >= 0; i--) {
fmc_debug_exit(devs[i]); fmc_debug_exit(devs[i]);
...@@ -313,8 +326,20 @@ out: ...@@ -313,8 +326,20 @@ out:
return ret; return ret;
} }
EXPORT_SYMBOL(fmc_device_register_n_gw);
int fmc_device_register_n(struct fmc_device **devs, int n)
{
return fmc_device_register_n_gw(devs, n, NULL);
}
EXPORT_SYMBOL(fmc_device_register_n); EXPORT_SYMBOL(fmc_device_register_n);
int fmc_device_register_gw(struct fmc_device *fmc, struct fmc_gateware *gw)
{
return fmc_device_register_n_gw(&fmc, 1, gw);
}
EXPORT_SYMBOL(fmc_device_register_gw);
int fmc_device_register(struct fmc_device *fmc) int fmc_device_register(struct fmc_device *fmc)
{ {
return fmc_device_register_n(&fmc, 1); return fmc_device_register_n(&fmc, 1);
......
...@@ -126,6 +126,30 @@ int fmc_free_sdb_tree(struct fmc_device *fmc) ...@@ -126,6 +126,30 @@ int fmc_free_sdb_tree(struct fmc_device *fmc)
} }
EXPORT_SYMBOL(fmc_free_sdb_tree); 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 */ /* This helper calls reprogram and inizialized sdb as well */
int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw, int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
int sdb_entry) int sdb_entry)
......
...@@ -132,6 +132,8 @@ struct fmc_operations { ...@@ -132,6 +132,8 @@ struct fmc_operations {
uint32_t (*read32)(struct fmc_device *fmc, int offset); uint32_t (*read32)(struct fmc_device *fmc, int offset);
void (*write32)(struct fmc_device *fmc, uint32_t value, int offset); void (*write32)(struct fmc_device *fmc, uint32_t value, int offset);
int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv); 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 (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw);
int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
char *name, int flags); char *name, int flags);
...@@ -144,6 +146,8 @@ struct fmc_operations { ...@@ -144,6 +146,8 @@ struct fmc_operations {
}; };
/* Prefer this helper rather than calling of fmc->reprogram directly */ /* 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, extern int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw,
int sdb_entry); int sdb_entry);
...@@ -220,14 +224,23 @@ static inline void fmc_set_drvdata(struct fmc_device *fmc, void *data) ...@@ -220,14 +224,23 @@ static inline void fmc_set_drvdata(struct fmc_device *fmc, void *data)
dev_set_drvdata(&fmc->dev, data); dev_set_drvdata(&fmc->dev, data);
} }
/* The 4 access points */ struct fmc_gateware {
void *bitstream;
unsigned long len;
};
/* The 5 access points */
extern int fmc_driver_register(struct fmc_driver *drv); extern int fmc_driver_register(struct fmc_driver *drv);
extern void fmc_driver_unregister(struct fmc_driver *drv); extern void fmc_driver_unregister(struct fmc_driver *drv);
extern int fmc_device_register(struct fmc_device *tdev); extern int fmc_device_register(struct fmc_device *tdev);
extern int fmc_device_register_gw(struct fmc_device *tdev,
struct fmc_gateware *gw);
extern void fmc_device_unregister(struct fmc_device *tdev); extern void fmc_device_unregister(struct fmc_device *tdev);
/* Two more for device sets, all driven by the same FPGA */ /* Three more for device sets, all driven by the same FPGA */
extern int fmc_device_register_n(struct fmc_device **devs, int n); extern int fmc_device_register_n(struct fmc_device **devs, int n);
extern int fmc_device_register_n_gw(struct fmc_device **devs, int n,
struct fmc_gateware *gw);
extern void fmc_device_unregister_n(struct fmc_device **devs, int n); extern void fmc_device_unregister_n(struct fmc_device **devs, int n);
/* Internal cross-calls between files; not exported to other modules */ /* Internal cross-calls between files; not exported to other modules */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment