FMC: make eeprom attribute writable

This allows easier modification to the eeprom than loading the
fmc-write-eeprom module.  The carrier driver will refuse writing if
the FPGA is not running the golden gateware image, so writing in
practice is only available at manufacture/development time.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Acked-by: Juan David Gonzalez Cobas <dcobas@cern.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alessandro Rubini
2014-02-22 09:11:12 +01:00
committed by Greg Kroah-Hartman
parent dd97b2410e
commit 5c9a87367d
2 changed files with 36 additions and 50 deletions

View File

@@ -9,7 +9,12 @@ Overwriting the EEPROM is not something you should do daily, and it is
expected to only happen during manufacturing. For this reason, the expected to only happen during manufacturing. For this reason, the
module makes it unlikely for the random user to change a working EEPROM. module makes it unlikely for the random user to change a working EEPROM.
The module takes the following measures: However, since the EEPROM may include application-specific information
other than the identification, later versions of this packages added
write-support through sysfs. See *note Accessing the EEPROM::.
To avoid damaging the EEPROM content, the module takes the following
measures:
* It accepts a `file=' argument (within /lib/firmware) and if no * It accepts a `file=' argument (within /lib/firmware) and if no
such argument is received, it doesn't write anything to EEPROM such argument is received, it doesn't write anything to EEPROM
@@ -70,56 +75,24 @@ first time.
[ 132.899872] fake-fmc: Product name: FmcDelay1ns4cha [ 132.899872] fake-fmc: Product name: FmcDelay1ns4cha
Writing to the EEPROM Accessing the EEPROM
===================== =====================
Once you have created a binary file for your EEPROM, you can write it The bus creates a sysfs binary file called eeprom for each mezzanine it
to the storage medium using the fmc-write-eeprom (See *note knows about:
fmc-write-eeprom::, while relying on a carrier driver. The procedure
here shown here uses the SPEC driver
(`http://www.ohwr.org/projects/spec-sw').
The example assumes no driver is already loaded (actually, I unloaded spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
them by hand as everything loads automatically at boot time after you -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcAdc100m14b4cha-0800/eeprom
installed the modules), and shows kernel messages together with -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDelay1ns4cha-0200/eeprom
commands. Here the prompt is spusa.root# and two SPEC cards are plugged -r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDio5cha-0400/eeprom
in the system.
spusa.root# insmod fmc.ko Everybody can read the files and the superuser can also modify it, but
spusa.root# insmod spec.ko the operation may on the carrier driver, if the carrier is unable to
[13972.382818] spec 0000:02:00.0: probe for device 0002:0000 access the I2C bus. For example, the spec driver can access the bus
[13972.392773] spec 0000:02:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes only with its golden gateware: after a mezzanine driver reprogrammed
[13972.591388] spec 0000:02:00.0: FPGA programming successful the FPGA with a custom circuit, the carrier is unable to access the
[13972.883011] spec 0000:02:00.0: EEPROM has no FRU information EEPROM and returns ENOTSUPP.
[13972.888719] spec 0000:02:00.0: No device_id filled, using index
[13972.894676] spec 0000:02:00.0: No mezzanine_name found
[13972.899863] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
[13972.906578] spec 0000:04:00.0: probe for device 0004:0000
[13972.916509] spec 0000:04:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes
[13973.115096] spec 0000:04:00.0: FPGA programming successful
[13973.401798] spec 0000:04:00.0: EEPROM has no FRU information
[13973.407474] spec 0000:04:00.0: No device_id filled, using index
[13973.413417] spec 0000:04:00.0: No mezzanine_name found
[13973.418600] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
spusa.root# ls /sys/bus/fmc/devices
fmc-0000 fmc-0001
spusa.root# insmod fmc-write-eeprom.ko busid=0x0200 file=fdelay-eeprom.bin
[14103.966259] spec 0000:02:00.0: Matching an generic driver (no ID)
[14103.975519] spec 0000:02:00.0: programming 6155 bytes
[14126.373762] spec 0000:02:00.0: write_eeprom: success
[14126.378770] spec 0000:04:00.0: Matching an generic driver (no ID)
[14126.384903] spec 0000:04:00.0: fmc_write_eeprom: no filename given: not programming
[14126.392600] fmc_write_eeprom: probe of fmc-0001 failed with error -2
Reading back the EEPROM An alternative way to write the EEPROM is the mezzanine driver
======================= fmc-write-eeprom (See *note fmc-write-eeprom::), but the procedure is
more complex.
In order to read back the binary content of the EEPROM of your
mezzanine device, the bus creates a read-only sysfs file called eeprom
for each mezzanine it knows about:
spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
-r--r--r-- 1 root root 8192 Apr 9 16:53 FmcDelay1ns4cha-f001/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f002/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f003/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fmc-f004/eeprom

View File

@@ -99,10 +99,23 @@ static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
return count; return count;
} }
static ssize_t fmc_write_eeprom(struct file *file, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev;
struct fmc_device *fmc;
dev = container_of(kobj, struct device, kobj);
fmc = container_of(dev, struct fmc_device, dev);
return fmc->op->write_ee(fmc, off, buf, count);
}
static struct bin_attribute fmc_eeprom_attr = { static struct bin_attribute fmc_eeprom_attr = {
.attr = { .name = "eeprom", .mode = S_IRUGO, }, .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
.size = 8192, /* more or less standard */ .size = 8192, /* more or less standard */
.read = fmc_read_eeprom, .read = fmc_read_eeprom,
.write = fmc_write_eeprom,
}; };
/* /*