Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c0dda14 authored by Federico Vaga's avatar Federico Vaga Committed by Greg Kroah-Hartman
Browse files

drivers/fmc: carrier can program FPGA on registration



The initial FPGA may require programming before it is useful.

Signed-off-by: default avatarFederico Vaga <federico.vaga@cern.ch>
Tested-by: default avatarPat Riehecky <riehecky@fnal.gov>
Acked-by: default avatarAlessandro Rubini <rubini@gnudd.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 15b1b0f0
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -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]);
+24 −0
Original line number Diff line number Diff line
@@ -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)
+4 −0
Original line number Diff line number Diff line
@@ -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);