diff --git a/fmc-bus b/fmc-bus index 29f077e42c420f596d05b51fdc356505cc42edb1..b2ca26a566e978dc8426a0cebe8dba40cadac2ac 160000 --- a/fmc-bus +++ b/fmc-bus @@ -1 +1 @@ -Subproject commit 29f077e42c420f596d05b51fdc356505cc42edb1 +Subproject commit b2ca26a566e978dc8426a0cebe8dba40cadac2ac diff --git a/kernel/spec-fmc.c b/kernel/spec-fmc.c index 3de6bf1c658f176757d177b6351abc66fa4437f9..ec8ad67d89961b2f970e339c4439a13962018541 100644 --- a/kernel/spec-fmc.c +++ b/kernel/spec-fmc.c @@ -7,6 +7,7 @@ * This work is part of the White Rabbit project, a research effort led * by CERN, the European Institute for Nuclear Research. */ +#include <linux/module.h> #include <linux/slab.h> #include <linux/fmc.h> #include <linux/interrupt.h> @@ -256,7 +257,7 @@ static int spec_read_ee(struct fmc_device *fmc, int pos, void *data, int len) { if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN)) return -ENOTSUPP; - return spec_eeprom_read(fmc, SPEC_I2C_EEPROM_ADDR, pos, data, len); + return spec_eeprom_read(fmc, pos, data, len); } static int spec_write_ee(struct fmc_device *fmc, int pos, @@ -264,7 +265,7 @@ static int spec_write_ee(struct fmc_device *fmc, int pos, { if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN)) return -ENOTSUPP; - return spec_eeprom_write(fmc, SPEC_I2C_EEPROM_ADDR, pos, data, len); + return spec_eeprom_write(fmc, pos, data, len); } static struct fmc_operations spec_fmc_operations = { @@ -391,6 +392,7 @@ static int check_golden(struct fmc_device *fmc) int spec_fmc_create(struct spec_dev *spec) { struct fmc_device *fmc; + struct pci_dev *pdev; int ret; fmc = kzalloc(sizeof(*fmc), GFP_KERNEL); @@ -398,14 +400,27 @@ int spec_fmc_create(struct spec_dev *spec) return -ENOMEM; fmc->version = FMC_VERSION; + fmc->owner = THIS_MODULE; fmc->carrier_name = "SPEC"; fmc->carrier_data = spec; - fmc->base = spec->remap[0]; /* 1M window at offset 0 */ + + /* 1M window at offset 0 */ + fmc->fpga_base = spec->remap[0]; + fmc->memlen = 1 << 20; + fmc->irq = spec->pdev->irq; fmc->op = &spec_fmc_operations; fmc->hwdev = &spec->pdev->dev; /* for messages */ spec->fmc = fmc; + /* We have one slot only, and the i2c address is mandated */ + fmc->slot_id = 0; + fmc->eeprom_addr = SPEC_I2C_EEPROM_ADDR; + + /* The device id is needed to build mezzanine unique names */ + pdev = spec->pdev; + fmc->device_id = (pdev->bus->number << 8) | pdev->devfn; + /* Check that the golden binary is actually correct */ ret = check_golden(fmc); if (ret) diff --git a/kernel/spec-i2c.c b/kernel/spec-i2c.c index a99650f459fe6e213c2358d5bf2c750f0dbc4e56..e2aedb59a94c2278c1153a06408d163792a16e69 100644 --- a/kernel/spec-i2c.c +++ b/kernel/spec-i2c.c @@ -139,7 +139,7 @@ int mi2c_scan(struct fmc_device *fmc) } /* FIXME: this is very inefficient: read several bytes in a row instead */ -int spec_eeprom_read(struct fmc_device *fmc, int i2c_addr, uint32_t offset, +int spec_eeprom_read(struct fmc_device *fmc, uint32_t offset, void *buf, size_t size) { int i; @@ -148,7 +148,7 @@ int spec_eeprom_read(struct fmc_device *fmc, int i2c_addr, uint32_t offset, for(i = 0; i < size; i++) { mi2c_start(fmc); - if(mi2c_put_byte(fmc, i2c_addr << 1) < 0) { + if(mi2c_put_byte(fmc, fmc->eeprom_addr << 1) < 0) { mi2c_stop(fmc); return -EIO; } @@ -158,7 +158,7 @@ int spec_eeprom_read(struct fmc_device *fmc, int i2c_addr, uint32_t offset, offset++; mi2c_stop(fmc); mi2c_start(fmc); - mi2c_put_byte(fmc, (i2c_addr << 1) | 1); + mi2c_put_byte(fmc, (fmc->eeprom_addr << 1) | 1); mi2c_get_byte(fmc, &c, 0); *buf8++ = c; mi2c_stop(fmc); @@ -166,7 +166,7 @@ int spec_eeprom_read(struct fmc_device *fmc, int i2c_addr, uint32_t offset, return size; } -int spec_eeprom_write(struct fmc_device *fmc, int i2c_addr, uint32_t offset, +int spec_eeprom_write(struct fmc_device *fmc, uint32_t offset, const void *buf, size_t size) { int i, busy; @@ -175,7 +175,7 @@ int spec_eeprom_write(struct fmc_device *fmc, int i2c_addr, uint32_t offset, for(i = 0; i < size; i++) { mi2c_start((fmc)); - if(mi2c_put_byte(fmc, i2c_addr << 1) < 0) { + if(mi2c_put_byte(fmc, fmc->eeprom_addr << 1) < 0) { mi2c_stop(fmc); return -1; } @@ -187,7 +187,7 @@ int spec_eeprom_write(struct fmc_device *fmc, int i2c_addr, uint32_t offset, do { /* wait until the chip becomes ready */ mi2c_start(fmc); - busy = mi2c_put_byte(fmc, i2c_addr << 1); + busy = mi2c_put_byte(fmc, fmc->eeprom_addr << 1); mi2c_stop(fmc); } while(busy); } @@ -210,12 +210,12 @@ int spec_i2c_init(struct fmc_device *fmc) if (!buf) return -ENOMEM; - i = spec_eeprom_read(fmc, SPEC_I2C_EEPROM_ADDR, 0, buf, - SPEC_I2C_EEPROM_SIZE); + i = spec_eeprom_read(fmc, 0, buf, SPEC_I2C_EEPROM_SIZE); if (i != SPEC_I2C_EEPROM_SIZE) { - dev_err(&spec->pdev->dev, "EEPROM read error: retval is %i\n", - i); + dev_err(&spec->pdev->dev, "EEPROM read error %i\n", i); kfree(buf); + fmc->eeprom = NULL; + fmc->eeprom_len = 0; return -EIO; } fmc->eeprom = buf; diff --git a/kernel/spec.h b/kernel/spec.h index 3fdbe6e9fb0452b461e6b131df67e71e32ba0a65..9ec90bebc7cd84386aab182c435ef997e320d19a 100644 --- a/kernel/spec.h +++ b/kernel/spec.h @@ -125,10 +125,10 @@ extern void spec_fmc_destroy(struct spec_dev *spec); /* Functions in spec-i2c.c, used by spec-fmc.c */ extern int spec_i2c_init(struct fmc_device *fmc); extern void spec_i2c_exit(struct fmc_device *fmc); -extern int spec_eeprom_read(struct fmc_device *fmc, int i2c_addr, - uint32_t offset, void *buf, size_t size); -extern int spec_eeprom_write(struct fmc_device *fmc, int i2c_addr, - uint32_t offset, const void *buf, size_t size); +extern int spec_eeprom_read(struct fmc_device *fmc, uint32_t offset, + void *buf, size_t size); +extern int spec_eeprom_write(struct fmc_device *fmc, uint32_t offset, + const void *buf, size_t size); /* The eeprom is at address 0x50 */ #define SPEC_I2C_EEPROM_ADDR 0x50 diff --git a/kernel/wr-nic-core.c b/kernel/wr-nic-core.c index 8a470102fabb1146c30a880a71c554c6fa88ef50..00de69fa42496fd4cd62d2180aa9f539fde453a7 100644 --- a/kernel/wr-nic-core.c +++ b/kernel/wr-nic-core.c @@ -88,9 +88,9 @@ int wrn_fmc_probe(struct fmc_device *fmc) * global name */ if (wrn_drv.gw_n) - ret = fmc->op->reprogram(fmc, &wrn_drv, ""); + ret = fmc_reprogram(fmc, &wrn_drv, "", 0x630000 /* SDB */); else - ret = fmc->op->reprogram(fmc, &wrn_drv, wrn_filename); + ret = fmc_reprogram(fmc, &wrn_drv, wrn_filename, 0x63000); if (ret <0) { if (ret == -ESRCH) { dev_info(fmc->hwdev, "%s: no gateware at index %i\n", @@ -102,19 +102,9 @@ int wrn_fmc_probe(struct fmc_device *fmc) wrn_filename, ret); return ret; } - - /* Verify that we have SDB at offset WRN_SDB_ADDR (0x63000) */ - if (fmc_readl(fmc, WRN_SDB_ADDR) != 0x5344422d) { - dev_err(dev, "Can't find SDB magic\n"); - ret = -ENODEV; - goto out; - } dev_info(dev, "Gateware successfully loaded\n"); - if ( (ret = fmc_scan_sdb_tree(fmc, WRN_SDB_ADDR)) < 0) { - dev_err(dev, "scan fmc failed %i\n", ret); - goto out; - } + /* FIXME: remove this parameter, fmc.ko shows it already */ if (wrn_show_sdb) fmc_show_sdb_tree(fmc); diff --git a/kernel/wr-nic-eth.c b/kernel/wr-nic-eth.c index 14633ed69bc15cb1739c636eb3a6c96bd21e140d..4d1ce875a1d611d74c26214f17992eb71e7a271b 100644 --- a/kernel/wr-nic-eth.c +++ b/kernel/wr-nic-eth.c @@ -223,7 +223,8 @@ int wrn_eth_init(struct fmc_device *fmc) continue; } /* use c->offset to copy and already-remapped value */ - *((void **)((u8 *)drvdata + c->offset)) = fmc->base + start; + *((void **)((u8 *)drvdata + c->offset)) = + fmc->fpga_base + start; } pdev->resource = resarr; pdev->num_resources = ARRAY_SIZE(wrn_cores);