Skip to content
Snippets Groups Projects
Commit a079c57b authored by Alessandro Rubini's avatar Alessandro Rubini
Browse files

fmc_operations: use a different reprogram

parent f1a948ae
Branches
Tags
No related merge requests found
......@@ -184,7 +184,7 @@ this document):
struct fmc_operations {
uint32_t (*readl)(struct fmc_device *fmc, int offset);
void (*writel)(struct fmc_device *fmc, uint32_t value, int offset);
int (*reprogram)(struct fmc_device *fmc, void *data, int len);
int (*reprogram)(struct fmc_device *fmc, char *gateware);
int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
char *name, int flags);
void (*irq_ack)(struct fmc_device *fmc);
......@@ -214,10 +214,11 @@ The individual methods perform the following tasks:
The carrier enumerates FMC devices by loading a standard (or
@i{golden} FPGA binary that allows EEPROM access. Each driver, then,
will need to reprogram the FPGA for its own use by calling this
function. If @i{reprogram} is called with NULL arguments, the
carrier will reprogram the golden binary -- which will happen
after @i{remove} time in any case.
will need to reprogram the FPGA by calling this
function. If the name argument is NULL,
the carrier will reprogram the golden binary. If the gateware name
has been overridden through module parameters (in a carrier-specific
way) the file loaded will match the parameters.
@item irq_request
@itemx irq_ack
......
......@@ -2,7 +2,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/fmc.h>
#include "spec.h"
......@@ -21,31 +20,15 @@ irqreturn_t t_handler(int irq, void *dev_id)
int t_probe(struct fmc_device *fmc)
{
int ret;
struct device *dev = fmc->hwdev;
ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", 0);
if (ret < 0)
return ret;
if (t_filename) {
const struct firmware *fw;
ret = request_firmware(&fw, t_filename, dev);
if (ret < 0) {
dev_warn(dev, "request firmware \"%s\": error %i\n",
t_filename, ret);
ret = 0; /* not fatal */
} else {
ret = fmc->op->reprogram(fmc, (void *)fw->data,
fw->size);
}
if (ret <0) {
dev_err(dev, "write firmware \"%s\": error %i\n",
t_filename, ret);
ret = 0; /* not fatal, either (lazy me) */
}
release_firmware(fw);
}
/* Reprogram, but only if specified in the arguments */
ret = fmc->op->reprogram(fmc, "");
if (ret < 0)
fmc->op->irq_free(fmc);
return ret;
}
......
......@@ -36,7 +36,7 @@ struct fmc_driver {
struct fmc_operations {
uint32_t (*readl)(struct fmc_device *fmc, int offset);
void (*writel)(struct fmc_device *fmc, uint32_t value, int offset);
int (*reprogram)(struct fmc_device *fmc, void *data, int len);
int (*reprogram)(struct fmc_device *fmc, char *gateware);
int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
char *name, int flags);
void (*irq_ack)(struct fmc_device *fmc);
......
......@@ -18,11 +18,36 @@ 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)
static int spec_reprogram(struct fmc_device *fmc, char *gw)
{
struct spec_dev *spec = fmc->carrier_data;
const struct firmware *fw;
struct device *dev = fmc->hwdev;
int ret;
if (!gw)
return 0;
if (!strlen(gw)) {
/* FIXME: use module parameters */
return 0;
}
return spec_load_fpga(spec, data, len); /* spec-pci.c */
ret = request_firmware(&fw, gw, dev);
if (ret < 0) {
dev_warn(dev, "request firmware \"%s\": error %i\n", gw, ret);
goto out;
}
ret = spec_load_fpga(spec, fw->data, fw->size);
if (ret <0) {
dev_err(dev, "write firmware \"%s\": error %i\n", gw, ret);
goto out;
}
/* FIXME: load lm32 */
out:
release_firmware(fw);
return ret;
}
static int spec_irq_request(struct fmc_device *fmc, irq_handler_t handler,
......
......@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include "wr-nic.h"
......@@ -32,7 +31,6 @@ int wrn_probe(struct fmc_device *fmc)
{
int ret = 0;
struct device *dev = fmc->hwdev;
const struct firmware *fw;
struct wrn_drvdata *dd;
/* Driver data */
......@@ -41,41 +39,34 @@ int wrn_probe(struct fmc_device *fmc)
return -ENOMEM;
fmc_set_drvdata(fmc, dd);
/* We first write a new binary within the spec */
if (wrn_filename) {
ret = request_firmware(&fw, wrn_filename, dev);
if (ret < 0) {
dev_warn(dev, "request firmware \"%s\": error %i\n",
wrn_filename, ret);
goto out;
}
ret = fmc->op->reprogram(fmc, (void *)fw->data, fw->size);
if (ret <0) {
dev_err(dev, "write firmware \"%s\": error %i\n",
wrn_filename, ret);
goto out_fw;
}
/* We first write a new binary (and lm32) within the spec */
ret = fmc->op->reprogram(fmc, WRN_GATEWARE_DEFAULT_NAME);
if (ret <0) {
dev_err(dev, "write firmware \"%s\": error %i\n",
wrn_filename, ret);
goto out;
}
/* Verify that we have SDB at offset 0x63000 */
if (fmc_readl(fmc, 0x63000) != 0x5344422d) {
dev_err(dev, "Can't find SDB magic\n");
ret = -ENODEV;
goto out_fw;
goto out;
}
dev_info(dev, "Gateware successfully loaded\n");
if ( (ret = fmc_scan_sdb_tree(fmc, 0x63000)) < 0) {
dev_err(dev, "scan fmc failed %i\n", ret);
goto out_fw;
goto out;
}
fmc_show_sdb_tree(fmc);
/* FIXME: load lm32 */
/* Register the gpio stuff, if we have kernel support */
ret = wrn_gpio_init(fmc);
if (ret < 0)
goto out_fw;
goto out;
/* The netword device */
ret = wrn_eth_init(fmc);
......@@ -94,8 +85,6 @@ out_nic:
wrn_eth_exit(fmc);
out_gpio:
wrn_gpio_exit(fmc);
out_fw:
release_firmware(fw);
out:
return ret;
}
......
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