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:
committed by
Greg Kroah-Hartman
parent
dd97b2410e
commit
5c9a87367d
@@ -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
|
|
||||||
|
@@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user