Commit 2ec98f56 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v5.3-1' of git://

Pull GPIO updates from Linus Walleij:
 "This is the big slew of GPIO changes for the v5.3 kernel cycle. This
  is mostly incremental work this time.

  Three important things:

   - The FMC subsystem is deleted through my tree. This happens through
     GPIO as its demise was discussed in relation to a patch decoupling
     its GPIO implementation from the standard way of handling GPIO. As
     it turns out, that is not the only subsystem it reimplements and
     the authors think it is better do scratch it and start over using
     the proper kernel subsystems than try to polish the rust shiny. See
     the commit (ACKed by the maintainers) for details.

   - Arnd made a small devres patch that was ACKed by Greg and goes into
     the device core.

   - SPDX header change colissions may happen, because at times I've
     seen that quite a lot changed during the -rc:s in regards to SPDX.
     (It is good stuff, tglx has me convinced, and it is worth the
     occasional pain.)

  Apart from this is is nothing controversial or problematic.



   - When a gpio_chip request GPIOs from itself, it can now fully
     control the line characteristics, both machine and consumer flags.
     This makes a lot of sense, but took some time before I figured out
     that this is how it has to work.

   - Several smallish documentation fixes.

  New drivers:

   - The PCA953x driver now supports the TI TCA9539.

   - The DaVinci driver now supports the K3 AM654 SoCs.

  Driver improvements:

   - Major overhaul and hardening of the OMAP driver by Russell King.

   - Starting to move some drivers to the new API passing irq_chip along
     with the gpio_chip when adding the gpio_chip instead of adding it


   - Delete the FMC subsystem"

* tag 'gpio-v5.3-1' of git:// (87 commits)
  Revert "gpio: tegra: Clean-up debugfs initialisation"
  gpiolib: Use spinlock_t instead of struct spinlock
  gpio: stp-xway: allow compile-testing
  gpio: stp-xway: get rid of the #include <lantiq_soc.h> dependency
  gpio: stp-xway: improve module clock error handling
  gpio: stp-xway: simplify error handling in xway_stp_probe()
  gpiolib: Clarify use of non-sleeping functions
  gpiolib: Fix references to gpiod_[gs]et_*value_cansleep() variants
  gpiolib: Document new gpio_chip.init_valid_mask field
  Documentation: gpio: Fix reference to gpiod_get_array()
  gpio: pl061: drop duplicate printing of device name
  gpio: altera: Pass irqchip when adding gpiochip
  gpio: siox: Use devm_ managed gpiochip
  gpio: siox: Add struct device *dev helper variable
  gpio: siox: Pass irqchip when adding gpiochip
  drivers: gpio: amd-fch: make resource struct const
  devres: allow const resource arguments
  gpio: ath79: Pass irqchip when adding gpiochip
  gpio: tegra: Clean-up debugfs initialisation
  gpio: siox: Switch to IRQ_TYPE_NONE
parents 96407298 9b3b6238
......@@ -5,6 +5,7 @@ Required Properties:
"ti,keystone-gpio": for Keystone 2 66AK2H/K, 66AK2L,
66AK2E SoCs
"ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G
"ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654
- reg: Physical base address of the controller and the size of memory mapped
......@@ -145,3 +146,20 @@ gpio0: gpio@260bf00 {
ti,ngpio = <32>;
ti,davinci-gpio-unbanked = <32>;
Example for K3 AM654:
wkup_gpio0: wkup_gpio0@42110000 {
compatible = "ti,am654-gpio", "ti,keystone-gpio";
reg = <0x42110000 0x100>;
#gpio-cells = <2>;
interrupt-parent = <&intr_wkup_gpio>;
interrupts = <59 128>, <59 129>, <59 130>, <59 131>;
#interrupt-cells = <2>;
ti,ngpio = <56>;
ti,davinci-gpio-unbanked = <0>;
clocks = <&k3_clks 59 0>;
clock-names = "gpio";
ARM PL061 GPIO controller
Required properties:
- compatible : "arm,pl061", "arm,primecell"
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt mapping for GPIO IRQ.
- gpio-ranges : Interaction with the PINCTRL subsystem.
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
title: ARM PL061 GPIO controller
- Linus Walleij <>
- Rob Herring <>
# We need a select here so we don't match all nodes with 'arm,primecell'
const: arm,pl061
- compatible
pattern: "^gpio@[0-9a-f]+$"
- const: arm,pl061
- const: arm,primecell
maxItems: 1
- maxItems: 1
- maxItems: 8
interrupt-controller: true
const: 2
maxItems: 1
clock-names: true
const: 2
gpio-controller: true
maxItems: 8
- compatible
- reg
- interrupts
- interrupt-controller
- "#interrupt-cells"
- clocks
- "#gpio-cells"
- gpio-controller
additionalProperties: false
......@@ -283,8 +283,6 @@ To summarize::
gpiod_set_value(desc, 1); default (active high) high
gpiod_set_value(desc, 0); active low high
gpiod_set_value(desc, 1); active low low
gpiod_set_value(desc, 0); default (active high) low
gpiod_set_value(desc, 1); default (active high) high
gpiod_set_value(desc, 0); open drain low
gpiod_set_value(desc, 1); open drain high impedance
gpiod_set_value(desc, 0); open source high impedance
......@@ -366,7 +364,7 @@ accessed sequentially.
The functions take three arguments:
* array_size - the number of array elements
* desc_array - an array of GPIO descriptors
* array_info - optional information obtained from gpiod_array_get()
* array_info - optional information obtained from gpiod_get_array()
* value_bitmap - a bitmap to store the GPIOs' values (get) or
a bitmap of values to assign to the GPIOs (set)
......@@ -235,7 +235,7 @@ means that a pull up or pull-down resistor is available on the output of the
GPIO line, and this resistor is software controlled.
In discrete designs, a pull-up or pull-down resistor is simply soldered on
the circuit board. This is not something we deal or model in software. The
the circuit board. This is not something we deal with or model in software. The
most you will think about these lines is that they will very likely be
configured as open drain or open source (see the section above).
......@@ -292,18 +292,18 @@ We can divide GPIO irqchips in two broad categories:
- HIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated
irq line to a parent interrupt controller one level up. There is no need
to inquire the GPIO hardware to figure out which line has figured, but it
may still be necessary to acknowledge the interrupt and set up the
configuration such as edge sensitivity.
to inquire the GPIO hardware to figure out which line has fired, but it
may still be necessary to acknowledge the interrupt and set up configuration
such as edge sensitivity.
Realtime considerations: a realtime compliant GPIO driver should not use
spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip
- spinlock_t should be replaced with raw_spinlock_t [1].
- spinlock_t should be replaced with raw_spinlock_t.[1]
- If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
on an irqchip. Create the callbacks if needed [2].
on an irqchip. Create the callbacks if needed.[2]
Cascaded GPIO irqchips
......@@ -361,7 +361,7 @@ Cascaded GPIO irqchips usually fall in one of three categories:
Realtime considerations: this kind of handlers will be forced threaded on -RT,
and as result the IRQ core will complain that generic_handle_irq() is called
with IRQ enabled and the same work around as for "CHAINED GPIO irqchips" can
with IRQ enabled and the same work-around as for "CHAINED GPIO irqchips" can
be applied.
- NESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any
......@@ -418,7 +418,7 @@ symbol:
If there is a need to exclude certain GPIO lines from the IRQ domain handled by
these helpers, we can set .irq.need_valid_mask of the gpiochip before
[devm_]gpiochip_add_data() is called. This allocates an .irq.valid_mask with as
``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as
many bits set as there are GPIO lines in the chip, each bit representing line
0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask
must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested()
Functions Exported by fmc.ko
The FMC core exports the usual 4 functions that are needed for a bus to
work, and a few more:
int fmc_driver_register(struct fmc_driver *drv);
void fmc_driver_unregister(struct fmc_driver *drv);
int fmc_device_register(struct fmc_device *fmc);
void fmc_device_unregister(struct fmc_device *fmc);
int fmc_device_register_n(struct fmc_device **fmc, int n);
void fmc_device_unregister_n(struct fmc_device **fmc, int n);
uint32_t fmc_readl(struct fmc_device *fmc, int offset);
void fmc_writel(struct fmc_device *fmc, uint32_t val, int off);
void *fmc_get_drvdata(struct fmc_device *fmc);
void fmc_set_drvdata(struct fmc_device *fmc, void *data);
int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw,
int sdb_entry);
The data structure that describe a device is detailed in *note FMC
Device::, the one that describes a driver is detailed in *note FMC
Driver::. Please note that structures of type fmc_device must be
allocated by the caller, but must not be released after unregistering.
The fmc-bus itself takes care of releasing the structure when their use
count reaches zero - actually, the device model does that in lieu of us.
The functions to register and unregister n devices are meant to be used
by carriers that host more than one mezzanine. The devices must all be
registered at the same time because if the FPGA is reprogrammed, all
devices in the array are affected. Usually, the driver matching the
first device will reprogram the FPGA, so other devices must know they
are already driven by a reprogrammed FPGA.
If a carrier hosts slots that are driven by different FPGA devices, it
should register as a group only mezzanines that are driven by the same
FPGA, for the reason outlined above.
Finally, the fmc_reprogram function calls the reprogram method (see
*note The API Offered by Carriers:: and also scans the memory area for
an SDB tree. You can pass -1 as sdb_entry to disable such scan.
Otherwise, the function fails if no tree is found at the specified
entry point. The function is meant to factorize common code, and by
the time you read this it is already used by the spec-sw and fine-delay
FMC (FPGA Mezzanine Card) is the standard we use for our I/O devices,
in the context of White Rabbit and related hardware.
In our I/O environments we need to write drivers for each mezzanine
card, and such drivers must work regardless of the carrier being used.
To achieve this, we abstract the FMC interface.
We have a carrier for PCI-E called SPEC and one for VME called SVEC,
but more are planned. Also, we support stand-alone devices (usually
plugged on a SPEC card), controlled through Etherbone, developed by GSI.
Code and documentation for the FMC bus was born as part of the spec-sw
project, but now it lives in its own project. Other projects, i.e.
software support for the various carriers, should include this as a
The most up to date version of code and documentation is always
available from the repository you can clone from:
git:// (read-only) (read-write for developers)
Selected versions of the documentation, as well as complete tar
archives for selected revisions are placed to the Files section of the
project: `'
What is FMC
FMC, as said, stands for "FPGA Mezzanine Card". It is a standard
developed by the VME consortium called VITA (VMEbus International Trade
Association and ratified by ANSI, the American National Standard
Institute. The official documentation is called "ANSI-VITA 57.1".
The FMC card is an almost square PCB, around 70x75 millimeters, that is
called mezzanine in this document. It usually lives plugged into
another PCB for power supply and control; such bigger circuit board is
called carrier from now on, and a single carrier may host more than one
In the typical application the mezzanine is mostly analog while the
carrier is mostly digital, and hosts an FPGA that must be configured to
match the specific mezzanine and the desired application. Thus, you may
need to load different FPGA images to drive different instances of the
same mezzanine.
FMC, as such, is not a bus in the usual meaning of the term, because
most carriers have only one connector, and carriers with several
connectors have completely separate electrical connections to them.
This package, however, implements a bus as a software abstraction.
What is SDB
SDB (Self Describing Bus) is a set of data structures that we use for
enumerating the internal structure of an FPGA image. We also use it as
a filesystem inside the FMC EEPROM.
SDB is not mandatory for use of this FMC kernel bus, but if you have SDB
this package can make good use of it. SDB itself is developed in the
fpga-config-space OHWR project. The link to the repository is
`git://' and what is used in
this project lives in the sdbfs subdirectory in there.
SDB support for FMC is described in *note FMC Identification:: and
*note SDB Support::
SDB Support
The fmc.ko bus driver exports a few functions to help drivers taking
advantage of the SDB information that may be present in your own FPGA
memory image.
The module exports the following functions, in the special header
<linux/fmc-sdb.h>. The linux/ prefix in the name is there because we
plan to submit it upstream in the future, and don't want to force
changes on our drivers if that happens.
int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address);
void fmc_show_sdb_tree(struct fmc_device *fmc);
signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor,
uint32_t device, unsigned long *sz);
int fmc_free_sdb_tree(struct fmc_device *fmc);
This diff is collapsed.
This is a simple generic driver, that allows user access by means of a
character device (actually, one for each mezzanine it takes hold of).
The char device is created as a misc device. Its name in /dev (as
created by udev) is the same name as the underlying FMC device. Thus,
the name can be a silly fmc-0000 look-alike if the device has no
identifiers nor bus_id, a more specific fmc-0400 if the device has a
bus-specific address but no associated name, or something like
fdelay-0400 if the FMC core can rely on both a mezzanine name and a bus
Currently the driver only supports read and write: you can lseek to the
desired address and read or write a register.
The driver assumes all registers are 32-bit in size, and only accepts a
single read or write per system call. However, as a result of Unix read
and write semantics, users can simply fread or fwrite bigger areas in
order to dump or store bigger memory areas.
There is currently no support for mmap, user-space interrupt management
and DMA buffers. They may be added in later versions, if the need
The example below shows raw access to a SPEC card programmed with its
golden FPGA file, that features an SDB structure at offset 256 - i.e.
64 words. The mezzanine's EEPROM in this case is not programmed, so the
default name is fmc-<bus><devfn>, and there are two cards in the system:
spusa.root# insmod fmc-chardev.ko
[ 1073.339332] spec 0000:02:00.0: Driver has no ID: matches all
[ 1073.345051] spec 0000:02:00.0: Created misc device "fmc-0200"
[ 1073.350821] spec 0000:04:00.0: Driver has no ID: matches all
[ 1073.356525] spec 0000:04:00.0: Created misc device "fmc-0400"
spusa.root# ls -l /dev/fmc*
crw------- 1 root root 10, 58 Nov 20 19:23 /dev/fmc-0200
crw------- 1 root root 10, 57 Nov 20 19:23 /dev/fmc-0400
spusa.root# dd bs=4 skip=64 count=1 if=/dev/fmc-0200 2> /dev/null | od -t x1z
0000000 2d 42 44 53 >-BDS<
The simple program tools/fmc-mem in this package can access an FMC char
device and read or write a word or a whole area. Actually, the program
is not specific to FMC at all, it just uses lseek, read and write.
Its first argument is the device name, the second the offset, the third
(if any) the value to write and the optional last argument that must
begin with "+" is the number of bytes to read or write. In case of
repeated reading data is written to stdout; repeated writes read from
stdin and the value argument is ignored.
The following examples show reading the SDB magic number and the first
SDB record from a SPEC device programmed with its golden image:
spusa.root# ./fmc-mem /dev/fmc-0200 100
spusa.root# ./fmc-mem /dev/fmc-0200 100 +40 | od -Ax -t x1z
000000 2d 42 44 53 00 01 02 00 00 00 00 00 00 00 00 00 >-BDS............<
000010 00 00 00 00 ff 01 00 00 00 00 00 00 51 06 00 00 >............Q...<
000020 c9 42 a5 e6 02 00 00 00 11 05 12 20 2d 34 42 57 >.B......... -4BW<
000030 73 6f 72 43 72 61 62 73 49 53 47 2d 00 20 20 20 >sorCrabsISG-. <
This package includes a software-only device, called fmc-fakedev, which
is able to register up to 4 mezzanines (by default it registers one).
Unlike the SPEC driver, which creates an FMC device for each PCI cards
it manages, this module creates a single instance of its set of
It is meant as the simplest possible example of how a driver should be
written, and it includes a fake EEPROM image (built using the tools
described in *note FMC Identification::),, which by default is
replicated for each fake mezzanine.
You can also use this device to verify the match algorithms, by asking
it to test your own EEPROM image. You can provide the image by means of
the eeprom= module parameter: the new EEPROM image is loaded, as usual,
by means of the firmware loader. This example shows the defaults and a
custom EEPROM image:
spusa.root# insmod fmc-fakedev.ko
[ 99.971247] fake-fmc-carrier: mezzanine 0
[ 99.975393] Manufacturer: fake-vendor
[ 99.979624] Product name: fake-design-for-testing
spusa.root# rmmod fmc-fakedev
spusa.root# insmod fmc-fakedev.ko eeprom=fdelay-eeprom.bin
[ 121.447464] fake-fmc-carrier: Mezzanine 0: eeprom "fdelay-eeprom.bin"
[ 121.462725] fake-fmc-carrier: mezzanine 0
[ 121.466858] Manufacturer: CERN
[ 121.470477] Product name: FmcDelay1ns4cha
spusa.root# rmmod fmc-fakedev
After loading the device, you can use the write_ee method do modify its
own internal fake EEPROM: whenever the image is overwritten starting at
offset 0, the module will unregister and register again the FMC device.
This is shown in fmc-write-eeprom.txt
The simple module fmc-trivial is just a simple client that registers an
interrupt handler. I used it to verify the basic mechanism of the FMC
bus and how interrupts worked.
The module implements the generic FMC parameters, so it can program a
different gateware file in each card. The whole list of parameters it
accepts are:
Generic parameters. See mezzanine.txt
This driver is worth reading, in my opinion.
This module is designed to load a binary file from /lib/firmware and to
write it to the internal EEPROM of the mezzanine card. This driver uses
the `busid' generic parameter.
Overwriting the EEPROM is not something you should do daily, and it is
expected to only happen during manufacturing. For this reason, the
module makes it unlikely for the random user to change a working EEPROM.
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
* It accepts a `file=' argument (within /lib/firmware) and if no
such argument is received, it doesn't write anything to EEPROM
(i.e. there is no default file name).
* If the file name ends with `.bin' it is written verbatim starting
at offset 0.
* If the file name ends with `.tlv' it is interpreted as
type-length-value (i.e., it allows writev(2)-like operation).
* If the file name doesn't match any of the patterns above, it is
ignored and no write is performed.
* Only cards listed with `busid=' are written to. If no busid is
specified, no programming is done (and the probe function of the
driver will fail).
Each TLV tuple is formatted in this way: the header is 5 bytes,
followed by data. The first byte is `w' for write, the next two bytes
represent the address, in little-endian byte order, and the next two
represent the data length, in little-endian order. The length does not
include the header (it is the actual number of bytes to be written).
This is a real example: that writes 5 bytes at position 0x110:
spusa.root# od -t x1 -Ax /lib/firmware/try.tlv
000000 77 10 01 05 00 30 31 32 33 34
spusa.root# insmod /tmp/fmc-write-eeprom.ko busid=0x0200 file=try.tlv
[19983.391498] spec 0000:03:00.0: write 5 bytes at 0x0110
[19983.414615] spec 0000:03:00.0: write_eeprom: success
Please note that you'll most likely want to use SDBFS to build your
EEPROM image, at least if your mezzanines are being used in the White
Rabbit environment. For this reason the TLV format is not expected to
be used much and is not expected to be developed further.
If you want to try reflashing fake EEPROM devices, you can use the
fmc-fakedev.ko module (see *note fmc-fakedev::). Whenever you change
the image starting at offset 0, it will deregister and register again
after two seconds. Please note, however, that if fmc-write-eeprom is
still loaded, the system will associate it to the new device, which
will be reprogrammed and thus will be unloaded after two seconds. The
following example removes the module after it reflashed fakedev the
first time.
spusa.root# insmod fmc-fakedev.ko
[ 72.984733] fake-fmc: Manufacturer: fake-vendor
[ 72.989434] fake-fmc: Product name: fake-design-for-testing
spusa.root# insmod fmc-write-eeprom.ko busid=0 file=fdelay-eeprom.bin; \
rmmod fmc-write-eeprom
[ 130.874098] fake-fmc: Matching a generic driver (no ID)
[ 130.887845] fake-fmc: programming 6155 bytes
[ 130.894567] fake-fmc: write_eeprom: success
[ 132.895794] fake-fmc: Manufacturer: CERN
[ 132.899872] fake-fmc: Product name: FmcDelay1ns4cha
Accessing the EEPROM
The bus creates a sysfs binary 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 Feb 21 12:30 FmcAdc100m14b4cha-0800/eeprom
-r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDelay1ns4cha-0200/eeprom
-r--r--r-- 1 root root 8192 Feb 21 12:30 FmcDio5cha-0400/eeprom
Everybody can read the files and the superuser can also modify it, but
the operation may on the carrier driver, if the carrier is unable to
access the I2C bus. For example, the spec driver can access the bus
only with its golden gateware: after a mezzanine driver reprogrammed
the FPGA with a custom circuit, the carrier is unable to access the
EEPROM and returns ENOTSUPP.
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.
FMC Identification
The FMC standard requires every compliant mezzanine to carry
identification information in an I2C EEPROM. The information must be
laid out according to the "IPMI Platform Management FRU Information",
where IPMI is a lie I'd better not expand, and FRU means "Field
Replaceable Unit".
The FRU information is an intricate unreadable binary blob that must
live at offset 0 of the EEPROM, and typically extends for a few hundred
bytes. The standard allows the application to use all the remaining
storage area of the EEPROM as it wants.
This chapter explains how to create your own EEPROM image and how to
write it in your mezzanine, as well as how devices and drivers are
paired at run time. EEPROM programming uses tools that are part of this
package and SDB (part of the fpga-config-space package).
The first sections are only interesting for manufacturers who need to
write the EEPROM. If you are just a software developer writing an FMC
device or driver, you may jump straight to *note SDB Support::.
Building the FRU Structure
If you want to know the internals of the FRU structure and despair, you
can retrieve the document from
`' . The
standard is awful and difficult without reason, so we only support the
minimum mandatory subset - we create a simple structure and parse it
back at run time, but we are not able to either generate or parse more
arcane features like non-english languages and 6-bit text. If you need
more items of the FRU standard for your boards, please submit patches.
This package includes the Python script that Matthieu Cattin wrote to
generate the FRU binary blob, based on an helper libipmi by Manohar
Vanga and Matthieu himself. I changed the test script to receive
parameters from the command line or from the environment (the command
line takes precedence)
To make a long story short, in order to build a standard-compliant
binary file to be burned in your EEPROM, you need the following items:
Environment Opt Official Name Default
FRU_VENDOR -v "Board Manufacturer" fmc-example
FRU_NAME -n "Board Product Name" mezzanine
FRU_SERIAL -s `Board Serial Number" 0001
FRU_PART -p "Board Part Number" sample-part
FRU_OUTPUT -o not applicable /dev/stdout
The "Official Name" above is what you find in the FRU official
documentation, chapter 11, page 7 ("Board Info Area Format"). The
output option is used to save the generated binary to a specific file
name instead of stdout.
You can pass the items to the FRU generator either in the environment
or on the command line. This package has currently no support for
specifying power consumption or such stuff, but I plan to add it as
soon as I find some time for that.
FIXME: consumption etc for FRU are here or in PTS?
The following example creates a binary image for a specific board:
./tools/fru-generator -v CERN -n FmcAdc100m14b4cha \
-s HCCFFIA___-CR000003 -p EDA-02063-V5-0 > eeprom.bin
The following example shows a script that builds several binary EEPROM
images for a series of boards, changing the serial number for each of
them. The script uses a mix of environment variables and command line
options, and uses the same string patterns shown above.
export FRU_NAME="FmcAdc100m14b4cha"
export FRU_PART="EDA-02063-V5-0"
for number in $(seq 1 50); do
# build number-string "ns"
ns="$(printf %06d $number)"
./fru-generator -s "${serial}${ns}" > eeprom-${ns}.bin
Using SDB-FS in the EEPROM
If you want to use SDB as a filesystem in the EEPROM device within the
mezzanine, you should create one such filesystem using gensdbfs, from
the fpga-config-space package on OHWR.
By using an SBD filesystem you can cluster several files in a single
EEPROM, so both the host system and a soft-core running in the FPGA (if
any) can access extra production-time information.
We chose to use SDB as a storage filesystem because the format is very
simple, and both the host system and the soft-core will likely already
include support code for such format. The SDB library offered by the
fpga-config-space is less than 1kB under LM32, so it proves quite up to
the task.
The SDB entry point (which acts as a directory listing) cannot live at
offset zero in the flash device, because the FRU information must live
there. To avoid wasting precious storage space while still allowing
for more-than-minimal FRU structures, the fmc.ko will look for the SDB
record at address 256, 512 and 1024.
In order to generate the complete EEPROM image you'll need a
configuration file for gensdbfs: you tell the program where to place
the sdb entry point, and you must force the FRU data file to be placed
at the beginning of the storage device. If needed, you can also place
other files at a special offset (we sometimes do it for backward
compatibility with drivers we wrote before implementing SDB for flash
The directory tools/sdbfs of this package includes a well-commented
example that you may want to use as a starting point (the comments are
in the file called -SDB-CONFIG-). Reading documentation for gensdbfs
is a suggested first step anyways.
This package (generic FMC bus support) only accesses two files in the
EEPROM: the FRU information, at offset zero, with a suggested filename
of IPMI-FRU and the short name for the mezzanine, in a file called
name. The IPMI-FRU name is not mandatory, but a strongly suggested
choice; the name filename is mandatory, because this is the preferred
short name used by the FMC core. For example, a name of "fdelay" may
supplement a Product Name like "FmcDelay1ns4cha" - exactly as
demonstrated in `tools/sdbfs'.
Note: SDB access to flash memory is not yet supported, so the short
name currently in use is just the "Product Name" FRU string.
The example in tools/sdbfs includes an extra file, that is needed by
the fine-delay driver, and must live at a known address of 0x1800. By
running gensdbfs on that directory you can output your binary EEPROM
image (here below spusa$ is the shell prompt):
spusa$ ../fru-generator -v CERN -n FmcDelay1ns4cha -s proto-0 \
-p EDA-02267-V3 > IPMI-FRU
spusa$ ls -l
total 16
-rw-rw-r-- 1 rubini staff 975 Nov 19 18:08 --SDB-CONFIG--
-rw-rw-r-- 1 rubini staff 216 Nov 19 18:13 IPMI-FRU
-rw-rw-r-- 1 rubini staff 11 Nov 19 18:04 fd-calib
-rw-rw-r-- 1 rubini staff 7 Nov 19 18:04 name
spusa$ sudo gensdbfs . /lib/firmware/fdelay-eeprom.bin
spusa$ sdb-read -l -e 0x100 /lib/firmware/fdelay-eeprom.bin
/home/rubini/wip/sdbfs/userspace/sdb-read: listing format is to be defined
46696c6544617461:2e202020 00000100-000018ff .
46696c6544617461:6e616d65 00000200-00000206 name
46696c6544617461:66642d63 00001800-000018ff fd-calib
46696c6544617461:49504d49 00000000-000000d7 IPMI-FRU
spusa$ ../fru-dump /lib/firmware/fdelay-eeprom.bin
/lib/firmware/fdelay-eeprom.bin: manufacturer: CERN
/lib/firmware/fdelay-eeprom.bin: product-name: FmcDelay1ns4cha
/lib/firmware/fdelay-eeprom.bin: serial-number: proto-0
/lib/firmware/fdelay-eeprom.bin: part-number: EDA-02267-V3
As expected, the output file is both a proper sdbfs object and an IPMI
FRU information blob. The fd-calib file lives at offset 0x1800 and is
over-allocated to 256 bytes, according to the configuration file for
FMC Driver
An FMC driver is concerned with the specific mezzanine and associated