From b0353f9f87a43c592da5ddd9e79bbacc68799ed7 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini <rubini@gnudd.com> Date: Wed, 25 Jul 2012 00:46:44 +0200 Subject: [PATCH] added reprogram method, with some shake up --- kernel/spec-fmc.c | 9 ++++++++- kernel/spec-pci.c | 44 ++++++++++++++++++++++++-------------------- kernel/spec.h | 3 +++ 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/kernel/spec-fmc.c b/kernel/spec-fmc.c index 684f963..62bf7ba 100644 --- a/kernel/spec-fmc.c +++ b/kernel/spec-fmc.c @@ -18,6 +18,13 @@ module_param_named(test_irq, spec_test_irq, int, 0444); /* The main role of this file is offering the fmc_operations for the spec */ +static int spec_reprogram(struct fmc_device *fmc, void *data, int len) +{ + struct spec_dev *spec = fmc->carrier_data; + + return spec_load_fpga(spec, data, len); /* spec-pci.c */ +} + static int spec_irq_request(struct fmc_device *fmc, irq_handler_t handler, char *name, int flags) { @@ -86,7 +93,7 @@ static int spec_write_ee(struct fmc_device *fmc, int pos, static struct fmc_operations spec_fmc_operations = { /* no readl/writel because we have the base pointer */ - /* FIXME: reprogram */ + .reprogram = spec_reprogram, .irq_request = spec_irq_request, .irq_ack = spec_irq_ack, .irq_free = spec_irq_free, diff --git a/kernel/spec-pci.c b/kernel/spec-pci.c index 9feee95..f82c692 100644 --- a/kernel/spec-pci.c +++ b/kernel/spec-pci.c @@ -28,25 +28,15 @@ static char *spec_fw_name = "fmc/spec-init.bin"; module_param_named(fw_name, spec_fw_name, charp, 0444); /* Load the FPGA. This bases on loader-ll.c, a kernel/user space thing */ -static int spec_load_fpga(struct spec_dev *spec) +int spec_load_fpga(struct spec_dev *spec, const void *data, int size) { - const struct firmware *fw; struct device *dev = &spec->pdev->dev; + int i, wrote; unsigned long j; - int i, err = 0, wrote; - char *name = spec_fw_name; /* FIXME: temporary hack */ - - err = request_firmware(&fw, name, dev); - if (err < 0) { - dev_err(dev, "request firmware \"%s\": error %i\n", name, err); - return err; - } - dev_info(dev, "got file \"%s\", %i (0x%x) bytes\n", - spec_fw_name, fw->size, fw->size); /* loader_low_level is designed to run from user space too */ wrote = loader_low_level(0 /* unused fd */, - spec->remap[2], fw->data, fw->size); + spec->remap[2], data, size); j = jiffies + 2 * HZ; /* Wait for DONE interrupt */ while(1) { @@ -54,23 +44,37 @@ static int spec_load_fpga(struct spec_dev *spec) i = readl(spec->remap[2] + FCL_IRQ); if (i & 0x8) { dev_info(dev, "FPGA programming sucessful\n"); - goto out; + return 0; } if(i & 0x4) { dev_err(dev, "FPGA program error after %i writes\n", wrote); - err = -ETIMEDOUT; - goto out; + return -ETIMEDOUT; } if (time_after(jiffies, j)) { dev_err(dev, "FPGA timeout after %i writes\n", wrote); - err = -ETIMEDOUT; - goto out; + return -ETIMEDOUT; } } -out: +} + +int spec_load_fpga_file(struct spec_dev *spec, char *name) +{ + struct device *dev = &spec->pdev->dev; + const struct firmware *fw; + int err = 0; + + err = request_firmware(&fw, name, dev); + if (err < 0) { + dev_err(dev, "request firmware \"%s\": error %i\n", name, err); + return err; + } + dev_info(dev, "got file \"%s\", %i (0x%x) bytes\n", + spec_fw_name, fw->size, fw->size); + + err = spec_load_fpga(spec, fw->data, fw->size); release_firmware(fw); return err; } @@ -114,7 +118,7 @@ static int __devinit spec_probe(struct pci_dev *pdev, /* Load the golden FPGA binary to read the eeprom */ - ret = spec_load_fpga(spec); + ret = spec_load_fpga_file(spec, spec_fw_name); if (ret) goto out_unmap; diff --git a/kernel/spec.h b/kernel/spec.h index c50a598..4304659 100644 --- a/kernel/spec.h +++ b/kernel/spec.h @@ -115,6 +115,9 @@ static inline void gennum_mask_val(struct spec_dev *spec, gennum_writel(spec, v, reg); } +/* Functions in spec-pci.c */ +extern int spec_load_fpga(struct spec_dev *spec, const void *data, int size); +extern int spec_load_fpga_file(struct spec_dev *spec, char *name); /* Functions in spec-fmc.c, used by spec-pci.c */ extern int spec_fmc_create(struct spec_dev *spec); -- GitLab