aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/fmc/API.txt47
-rw-r--r--Documentation/fmc/FMC-and-SDB.txt88
-rw-r--r--Documentation/fmc/carrier.txt311
-rw-r--r--Documentation/fmc/fmc-chardev.txt64
-rw-r--r--Documentation/fmc/fmc-fakedev.txt36
-rw-r--r--Documentation/fmc/fmc-trivial.txt17
-rw-r--r--Documentation/fmc/fmc-write-eeprom.txt98
-rw-r--r--Documentation/fmc/identifiers.txt168
-rw-r--r--Documentation/fmc/mezzanine.txt123
-rw-r--r--Documentation/fmc/parameters.txt56
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/fmc/Kconfig52
-rw-r--r--drivers/fmc/Makefile15
-rw-r--r--drivers/fmc/fmc-chardev.c199
-rw-r--r--drivers/fmc/fmc-core.c388
-rw-r--r--drivers/fmc/fmc-debug.c172
-rw-r--r--drivers/fmc/fmc-dump.c58
-rw-r--r--drivers/fmc/fmc-fakedev.c355
-rw-r--r--drivers/fmc/fmc-match.c113
-rw-r--r--drivers/fmc/fmc-private.h8
-rw-r--r--drivers/fmc/fmc-sdb.c219
-rw-r--r--drivers/fmc/fmc-trivial.c102
-rw-r--r--drivers/fmc/fmc-write-eeprom.c175
-rw-r--r--drivers/fmc/fru-parse.c80
-rw-r--r--include/linux/fmc-sdb.h39
-rw-r--r--include/linux/fmc.h271
27 files changed, 0 insertions, 3257 deletions
diff --git a/Documentation/fmc/API.txt b/Documentation/fmc/API.txt
deleted file mode 100644
index 06b06b92c794..000000000000
--- a/Documentation/fmc/API.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-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
-modules.
diff --git a/Documentation/fmc/FMC-and-SDB.txt b/Documentation/fmc/FMC-and-SDB.txt
deleted file mode 100644
index fa14e0b24521..000000000000
--- a/Documentation/fmc/FMC-and-SDB.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-
-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
-submodule.
-
-The most up to date version of code and documentation is always
-available from the repository you can clone from:
-
- git://ohwr.org/fmc-projects/fmc-bus.git (read-only)
- git@ohwr.org:fmc-projects/fmc-bus.git (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: `http://www.ohwr.org/projects/fmc-bus/files'
-
-
-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
-mezzanine.
-
-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://ohwr.org/hdl-core-lib/fpga-config-space.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);
diff --git a/Documentation/fmc/carrier.txt b/Documentation/fmc/carrier.txt
deleted file mode 100644
index 5e4f1dd3e98b..000000000000
--- a/Documentation/fmc/carrier.txt
+++ /dev/null
@@ -1,311 +0,0 @@
-FMC Device
-**********
-
-Within the Linux bus framework, the FMC device is created and
-registered by the carrier driver. For example, the PCI driver for the
-SPEC card fills a data structure for each SPEC that it drives, and
-registers an associated FMC device for each card. The SVEC driver can
-do exactly the same for the VME carrier (actually, it should do it
-twice, because the SVEC carries two FMC mezzanines). Similarly, an
-Etherbone driver will be able to register its own FMC devices, offering
-communication primitives through frame exchange.
-
-The contents of the EEPROM within the FMC are used for identification
-purposes, i.e. for matching the device with its own driver. For this
-reason the device structure includes a complete copy of the EEPROM
-(actually, the carrier driver may choose whether or not to return it -
-for example we most likely won't have the whole EEPROM available for
-Etherbone devices.
-
-The following listing shows the current structure defining a device.
-Please note that all the machinery is in place but some details may
-still change in the future. For this reason, there is a version field
-at the beginning of the structure. As usual, the minor number will
-change for compatible changes (like a new flag) and the major number
-will increase when an incompatible change happens (for example, a
-change in layout of some fmc data structures). Device writers should
-just set it to the value FMC_VERSION, and be ready to get back -EINVAL
-at registration time.
-
- struct fmc_device {
- unsigned long version;
- unsigned long flags;
- struct module *owner; /* char device must pin it */
- struct fmc_fru_id id; /* for EEPROM-based match */
- struct fmc_operations *op; /* carrier-provided */
- int irq; /* according to host bus. 0 == none */
- int eeprom_len; /* Usually 8kB, may be less */
- int eeprom_addr; /* 0x50, 0x52 etc */
- uint8_t *eeprom; /* Full contents or leading part */
- char *carrier_name; /* "SPEC" or similar, for special use */
- void *carrier_data; /* "struct spec *" or equivalent */
- __iomem void *fpga_base; /* May be NULL (Etherbone) */
- __iomem void *slot_base; /* Set by the driver */
- struct fmc_device **devarray; /* Allocated by the bus */
- int slot_id; /* Index in the slot array */
- int nr_slots; /* Number of slots in this carrier */
- unsigned long memlen; /* Used for the char device */
- struct device dev; /* For Linux use */
- struct device *hwdev; /* The underlying hardware device */
- unsigned long sdbfs_entry;
- struct sdb_array *sdb;
- uint32_t device_id; /* Filled by the device */
- char *mezzanine_name; /* Defaults to ``fmc'' */
- void *mezzanine_data;
- };
-
-The meaning of most fields is summarized in the code comment above.
-
-The following fields must be filled by the carrier driver before
-registration:
-
- * version: must be set to FMC_VERSION.
-
- * owner: set to MODULE_OWNER.
-
- * op: the operations to act on the device.
-
- * irq: number for the mezzanine; may be zero.
-
- * eeprom_len: length of the following array.
-
- * eeprom_addr: 0x50 for first mezzanine and so on.
-
- * eeprom: the full content of the I2C EEPROM.
-
- * carrier_name.
-
- * carrier_data: a unique pointer for the carrier.
-
- * fpga_base: the I/O memory address (may be NULL).
-
- * slot_id: the index of this slot (starting from zero).
-
- * memlen: if fpga_base is valid, the length of I/O memory.
-
- * hwdev: to be used in some dev_err() calls.
-
- * device_id: a slot-specific unique integer number.
-
-
-Please note that the carrier should read its own EEPROM memory before
-registering the device, as well as fill all other fields listed above.
-
-The following fields should not be assigned, because they are filled
-later by either the bus or the device driver:
-
- * flags.
-
- * fru_id: filled by the bus, parsing the eeprom.
-
- * slot_base: filled and used by the driver, if useful to it.
-
- * devarray: an array og all mezzanines driven by a singe FPGA.
-
- * nr_slots: set by the core at registration time.
-
- * dev: used by Linux.
-
- * sdb: FPGA contents, scanned according to driver's directions.
-
- * sdbfs_entry: SDB entry point in EEPROM: autodetected.
-
- * mezzanine_data: available for the driver.
-
- * mezzanine_name: filled by fmc-bus during identification.
-
-
-Note: mezzanine_data may be redundant, because Linux offers the drvdata
-approach, so the field may be removed in later versions of this bus
-implementation.
-
-As I write this, she SPEC carrier is already completely functional in
-the fmc-bus environment, and is a good reference to look at.
-
-
-The API Offered by Carriers
-===========================
-
-The carrier provides a number of methods by means of the
-`fmc_operations' structure, which currently is defined like this
-(again, it is a moving target, please refer to the header rather than
-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 *f, struct fmc_driver *d, char *gw);
- int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv);
- int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
- char *name, int flags);
- void (*irq_ack)(struct fmc_device *fmc);
- int (*irq_free)(struct fmc_device *fmc);
- int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio,
- int ngpio);
- int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l);
- int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l);
- };
-
-The individual methods perform the following tasks:
-
-`readl'
-`writel'
- These functions access FPGA registers by whatever means the
- carrier offers. They are not expected to fail, and most of the time
- they will just make a memory access to the host bus. If the
- carrier provides a fpga_base pointer, the driver may use direct
- access through that pointer. For this reason the header offers the
- inline functions fmc_readl and fmc_writel that access fpga_base if
- the respective method is NULL. A driver that wants to be portable
- and efficient should use fmc_readl and fmc_writel. For Etherbone,
- or other non-local carriers, error-management is still to be
- defined.
-
-`validate'
- Module parameters are used to manage different applications for
- two or more boards of the same kind. Validation is based on the
- busid module parameter, if provided, and returns the matching
- index in the associated array. See *note Module Parameters:: in in
- doubt. If no match is found, `-ENOENT' is returned; if the user
- didn't pass `busid=', all devices will pass validation. The value
- returned by the validate method can be used as index into other
- parameters (for example, some drivers use the `lm32=' parameter in
- this way). Such "generic parameters" are documented in *note
- Module Parameters::, below. The validate method is used by
- `fmc-trivial.ko', described in *note fmc-trivial::.
-
-`reprogram'
- The carrier enumerates FMC devices by loading a standard (or
- golden) FPGA binary that allows EEPROM access. Each driver, then,
- will need to reprogram the FPGA by calling this function. If the
- name argument is NULL, the carrier should 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. Per-device gateware names can be specified using
- the `gateware=' parameter, see *note Module Parameters::. Note:
- Clients should call rhe new helper, fmc_reprogram, which both
- calls this method and parse the SDB tree of the FPGA.
-
-`irq_request'
-`irq_ack'
-`irq_free'
- Interrupt management is carrier-specific, so it is abstracted as
- operations. The interrupt number is listed in the device
- structure, and for the mezzanine driver the number is only
- informative. The handler will receive the fmc pointer as dev_id;
- the flags argument is passed to the Linux request_irq function,
- but fmc-specific flags may be added in the future. You'll most
- likely want to pass the `IRQF_SHARED' flag.
-
-`gpio_config'
- The method allows to configure a GPIO pin in the carrier, and read
- its current value if it is configured as input. See *note The GPIO
- Abstraction:: for details.
-
-`read_ee'
-`write_ee'
- Read or write the EEPROM. The functions are expected to be only
- called before reprogramming and the carrier should refuse them
- with `ENODEV' after reprogramming. The offset is expected to be
- within 8kB (the current size), but addresses up to 1MB are
- reserved to fit bigger I2C devices in the future. Carriers may
- offer access to other internal flash memories using these same
- methods: for example the SPEC driver may define that its carrier
- I2C memory is seen at offset 1M and the internal SPI flash is seen
- at offset 16M. This multiplexing of several flash memories in the
- same address space is carrier-specific and should only be used
- by a driver that has verified the `carrier_name' field.
-
-
-
-The GPIO Abstraction
-====================
-
-Support for GPIO pins in the fmc-bus environment is not very
-straightforward and deserves special discussion.
-
-While the general idea of a carrier-independent driver seems to fly,
-configuration of specific signals within the carrier needs at least
-some knowledge of the carrier itself. For this reason, the specific
-driver can request to configure carrier-specific GPIO pins, numbered
-from 0 to at most 4095. Configuration is performed by passing a
-pointer to an array of struct fmc_gpio items, as well as the length of
-the array. This is the data structure:
-
- struct fmc_gpio {
- char *carrier_name;
- int gpio;
- int _gpio; /* internal use by the carrier */
- int mode; /* GPIOF_DIR_OUT etc, from <linux/gpio.h> */
- int irqmode; /* IRQF_TRIGGER_LOW and so on */
- };
-
-By specifying a carrier_name for each pin, the driver may access
-different pins in different carriers. The gpio_config method is
-expected to return the number of pins successfully configured, ignoring
-requests for other carriers. However, if no pin is configured (because
-no structure at all refers to the current carrier_name), the operation
-returns an error so the caller will know that it is running under a
-yet-unsupported carrier.
-
-So, for example, a driver that has been developed and tested on both
-the SPEC and the SVEC may request configuration of two different GPIO
-pins, and expect one such configuration to succeed - if none succeeds
-it most likely means that the current carrier is a still-unknown one.
-
-If, however, your GPIO pin has a specific known role, you can pass a
-special number in the gpio field, using one of the following macros:
-
- #define FMC_GPIO_RAW(x) (x) /* 4096 of them */
- #define FMC_GPIO_IRQ(x) ((x) + 0x1000) /* 256 of them */
- #define FMC_GPIO_LED(x) ((x) + 0x1100) /* 256 of them */
- #define FMC_GPIO_KEY(x) ((x) + 0x1200) /* 256 of them */
- #define FMC_GPIO_TP(x) ((x) + 0x1300) /* 256 of them */
- #define FMC_GPIO_USER(x) ((x) + 0x1400) /* 256 of them */
-
-Use of virtual GPIO numbers (anything but FMC_GPIO_RAW) is allowed
-provided the carrier_name field in the data structure is left
-unspecified (NULL). Each carrier is responsible for providing a mapping
-between virtual and physical GPIO numbers. The carrier may then use the
-_gpio field to cache the result of this mapping.
-
-All carriers must map their I/O lines to the sets above starting from
-zero. The SPEC, for example, maps interrupt pins 0 and 1, and test
-points 0 through 3 (even if the test points on the PCB are called
-5,6,7,8).
-
-If, for example, a driver requires a free LED and a test point (for a
-scope probe to be plugged at some point during development) it may ask
-for FMC_GPIO_LED(0) and FMC_GPIO_TP(0). Each carrier will provide
-suitable GPIO pins. Clearly, the person running the drivers will know
-the order used by the specific carrier driver in assigning leds and
-testpoints, so to make a carrier-dependent use of the diagnostic tools.
-
-In theory, some form of autodetection should be possible: a driver like
-the wr-nic (which uses IRQ(1) on the SPEC card) should configure
-IRQ(0), make a test with software-generated interrupts and configure
-IRQ(1) if the test fails. This probing step should be used because even
-if the wr-nic gateware is known to use IRQ1 on the SPEC, the driver
-should be carrier-independent and thus use IRQ(0) as a first bet -
-actually, the knowledge that IRQ0 may fail is carrier-dependent
-information, but using it doesn't make the driver unsuitable for other
-carriers.
-
-The return value of gpio_config is defined as follows:
-
- * If no pin in the array can be used by the carrier, `-ENODEV'.
-
- * If at least one virtual GPIO number cannot be mapped, `-ENOENT'.
-
- * On success, 0 or positive. The value returned is the number of
- high input bits (if no input is configured, the value for success
- is 0).
-
-While I admit the procedure is not completely straightforward, it
-allows configuration, input and output with a single carrier operation.
-Given the typical use case of FMC devices, GPIO operations are not
-expected to ever by in hot paths, and GPIO access so fare has only been
-used to configure the interrupt pin, mode and polarity. Especially
-reading inputs is not expected to be common. If your device has GPIO
-capabilities in the hot path, you should consider using the kernel's
-GPIO mechanisms.
diff --git a/Documentation/fmc/fmc-chardev.txt b/Documentation/fmc/fmc-chardev.txt
deleted file mode 100644
index d9ccb278e597..000000000000
--- a/Documentation/fmc/fmc-chardev.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-fmc-chardev
-===========
-
-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
-address.
-
-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
-arises.
-
-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<
- 0000004
-
-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
- 5344422d
- 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-. <
- 000040
diff --git a/Documentation/fmc/fmc-fakedev.txt b/Documentation/fmc/fmc-fakedev.txt
deleted file mode 100644
index e85b74a4ae30..000000000000
--- a/Documentation/fmc/fmc-fakedev.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-fmc-fakedev
-===========
-
-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
-mezzanines.
-
-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
diff --git a/Documentation/fmc/fmc-trivial.txt b/Documentation/fmc/fmc-trivial.txt
deleted file mode 100644
index d1910bc67159..000000000000
--- a/Documentation/fmc/fmc-trivial.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-fmc-trivial
-===========
-
-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:
-
-`busid='
-`gateware='
- Generic parameters. See mezzanine.txt
-
-
-This driver is worth reading, in my opinion.
diff --git a/Documentation/fmc/fmc-write-eeprom.txt b/Documentation/fmc/fmc-write-eeprom.txt
deleted file mode 100644
index e0a9712156aa..000000000000
--- a/Documentation/fmc/fmc-write-eeprom.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-fmc-write-eeprom
-================
-
-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
-measures:
-
- * 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
- 00000a
- 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.
diff --git a/Documentation/fmc/identifiers.txt b/Documentation/fmc/identifiers.txt
deleted file mode 100644
index 3bb577ff0d52..000000000000
--- a/Documentation/fmc/identifiers.txt
+++ /dev/null
@@ -1,168 +0,0 @@
-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
-`http://download.intel.com/design/servers/ipmi/FRU1011.pdf' . 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.
-
- #!/bin/sh
-
- export FRU_VENDOR="CERN"
- export FRU_NAME="FmcAdc100m14b4cha"
- export FRU_PART="EDA-02063-V5-0"
-
- serial="HCCFFIA___-CR"
-
- for number in $(seq 1 50); do
- # build number-string "ns"
- ns="$(printf %06d $number)"
- ./fru-generator -s "${serial}${ns}" > eeprom-${ns}.bin
- done
-
-
-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
-memory).
-
-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
-gensdbfs.
diff --git a/Documentation/fmc/mezzanine.txt b/Documentation/fmc/mezzanine.txt
deleted file mode 100644
index 87910dbfc91e..000000000000
--- a/Documentation/fmc/mezzanine.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-FMC Driver
-**********
-
-An FMC driver is concerned with the specific mezzanine and associated
-gateware. As such, it is expected to be independent of the carrier
-being used: it will perform I/O accesses only by means of
-carrier-provided functions.
-
-The matching between device and driver is based on the content of the
-EEPROM (as mandated by the FMC standard) or by the actual cores
-configured in the FPGA; the latter technique is used when the FPGA is
-already programmed when the device is registered to the bus core.
-
-In some special cases it is possible for a driver to directly access
-FPGA registers, by means of the `fpga_base' field of the device
-structure. This may be needed for high-bandwidth peripherals like fast
-ADC cards. If the device module registered a remote device (for example
-by means of Etherbone), the `fpga_base' pointer will be NULL.
-Therefore, drivers must be ready to deal with NULL base pointers, and
-fail gracefully. Most driver, however, are not expected to access the
-pointer directly but run fmc_readl and fmc_writel instead, which will
-work in any case.
-
-In even more special cases, the driver may access carrier-specific
-functionality: the `carrier_name' string allows the driver to check
-which is the current carrier and make use of the `carrier_data'
-pointer. We chose to use carrier names rather than numeric identifiers
-for greater flexibility, but also to avoid a central registry within
-the `fmc.h' file - we hope other users will exploit our framework with
-their own carriers. An example use of carrier names is in GPIO setup
-(see *note The GPIO Abstraction::), although the name match is not
-expected to be performed by the driver. If you depend on specific
-carriers, please check the carrier name and fail gracefully if your
-driver finds it is running in a yet-unknown-to-it environment.
-
-
-ID Table
-========
-
-Like most other Linux drivers, and FMC driver must list all the devices
-which it is able to drive. This is usually done by means of a device
-table, but in FMC we can match hardware based either on the contents of
-their EEPROM or on the actual FPGA cores that can be enumerated.
-Therefore, we have two tables of identifiers.
-
-Matching of FRU information depends on two names, the manufacturer (or
-vendor) and the device (see *note FMC Identification::); for
-flexibility during production (i.e. before writing to the EEPROM) the
-bus supports a catch-all driver that specifies NULL strings. For this
-reason, the table is specified as pointer-and-length, not a a
-null-terminated array - the entry with NULL names can be a valid entry.
-
-Matching on FPGA cores depends on two numeric fields: the 64-bit vendor
-number and the 32-bit device number. Support for matching based on
-class is not yet implemented. Each device is expected to be uniquely
-identified by an array of cores (it matches if all of the cores are
-instantiated), and for consistency the list is passed as
-pointer-and-length. Several similar devices can be driven by the same
-driver, and thus the driver specifies and array of such arrays.
-
-The complete set of involved data structures is thus the following:
-
- struct fmc_fru_id { char *manufacturer; char *product_name; };
- struct fmc_sdb_one_id { uint64_t vendor; uint32_t device; };
- struct fmc_sdb_id { struct fmc_sdb_one_id *cores; int cores_nr; };
-
- struct fmc_device_id {
- struct fmc_fru_id *fru_id; int fru_id_nr;
- struct fmc_sdb_id *sdb_id; int sdb_id_nr;
- };
-
-A better reference, with full explanation, is the <linux/fmc.h> header.
-
-
-Module Parameters
-=================
-
-Most of the FMC drivers need the same set of kernel parameters. This
-package includes support to implement common parameters by means of
-fields in the `fmc_driver' structure and simple macro definitions.
-
-The parameters are carrier-specific, in that they rely on the busid
-concept, that varies among carriers. For the SPEC, the identifier is a
-PCI bus and devfn number, 16 bits wide in total; drivers for other
-carriers will most likely offer something similar but not identical,
-and some code duplication is unavoidable.
-
-This is the list of parameters that are common to several modules to
-see how they are actually used, please look at spec-trivial.c.
-
-`busid='
- This is an array of integers, listing carrier-specific
- identification numbers. For PIC, for example, `0x0400' represents
- bus 4, slot 0. If any such ID is specified, the driver will only
- accept to drive cards that appear in the list (even if the FMC ID
- matches). This is accomplished by the validate carrier method.
-
-`gateware='
- The argument is an array of strings. If no busid= is specified,
- the first string of gateware= is used for all cards; otherwise the
- identifiers and gateware names are paired one by one, in the order
- specified.
-
-`show_sdb='
- For modules supporting it, this parameter asks to show the SDB
- internal structure by means of kernel messages. It is disabled by
- default because those lines tend to hide more important messages,
- if you look at the system console while loading the drivers.
- Note: the parameter is being obsoleted, because fmc.ko itself now
- supports dump_sdb= that applies to every client driver.
-
-
-For example, if you are using the trivial driver to load two different
-gateware files to two different cards, you can use the following
-parameters to load different binaries to the cards, after looking up
-the PCI identifiers. This has been tested with a SPEC carrier.
-
- insmod fmc-trivial.ko \
- busid=0x0200,0x0400 \
- gateware=fmc/fine-delay.bin,fmc/simple-dio.bin
-
-Please note that not all sub-modules support all of those parameters.
-You can use modinfo to check what is supported by each module.
diff --git a/Documentation/fmc/parameters.txt b/Documentation/fmc/parameters.txt
deleted file mode 100644
index 59edf088e3a4..000000000000
--- a/Documentation/fmc/parameters.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-Module Parameters in fmc.ko
-***************************
-
-The core driver receives two module parameters, meant to help debugging
-client modules. Both parameters can be modified by writing to
-/sys/module/fmc/parameters/, because they are used when client drivers
-are devices are registered, not when fmc.ko is loaded.
-
-`dump_eeprom='
- If not zero, the parameter asks the bus controller to dump the
- EEPROM of any device that is registered, using printk.
-
-`dump_sdb='
- If not zero, the parameter prints the SDB tree of every FPGA it is
- loaded by fmc_reprogram(). If greater than one, it asks to dump
- the binary content of SDB records. This currently only dumps the
- top-level SDB array, though.
-
-
-EEPROM dumping avoids repeating lines, since most of the contents is
-usually empty and all bits are one or zero. This is an example of the
-output:
-
- [ 6625.850480] spec 0000:02:00.0: FPGA programming successful
- [ 6626.139949] spec 0000:02:00.0: Manufacturer: CERN
- [ 6626.144666] spec 0000:02:00.0: Product name: FmcDelay1ns4cha
- [ 6626.150370] FMC: mezzanine 0: 0000:02:00.0 on SPEC
- [ 6626.155179] FMC: dumping eeprom 0x2000 (8192) bytes
- [ 6626.160087] 0000: 01 00 00 01 00 0b 00 f3 01 0a 00 a5 85 87 c4 43
- [ 6626.167069] 0010: 45 52 4e cf 46 6d 63 44 65 6c 61 79 31 6e 73 34
- [ 6626.174019] 0020: 63 68 61 c7 70 72 6f 74 6f 2d 30 cc 45 44 41 2d
- [ 6626.180975] 0030: 30 32 32 36 37 2d 56 33 da 32 30 31 32 2d 31 31
- [...]
- [ 6626.371366] 0200: 66 64 65 6c 61 79 0a 00 00 00 00 00 00 00 00 00
- [ 6626.378359] 0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- [ 6626.385361] [...]
- [ 6626.387308] 1800: 70 6c 61 63 65 68 6f 6c 64 65 72 ff ff ff ff ff
- [ 6626.394259] 1810: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
- [ 6626.401250] [...]
-
-The dump of SDB looks like the following; the example shows the simple
-golden gateware for the SPEC card, removing the leading timestamps to
-fit the page:
-
- spec 0000:02:00.0: SDB: 00000651:e6a542c9 WB4-Crossbar-GSI
- spec 0000:02:00.0: SDB: 0000ce42:ff07fc47 WR-Periph-Syscon (00000000-000000ff)
- FMC: mezzanine 0: 0000:02:00.0 on SPEC
- FMC: poor dump of sdb first level:
- 0000: 53 44 42 2d 00 02 01 00 00 00 00 00 00 00 00 00
- 0010: 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 06 51
- 0020: e6 a5 42 c9 00 00 00 02 20 12 05 11 57 42 34 2d
- 0030: 43 72 6f 73 73 62 61 72 2d 47 53 49 20 20 20 00
- 0040: 00 00 01 01 00 00 00 07 00 00 00 00 00 00 00 00
- 0050: 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 ce 42
- 0060: ff 07 fc 47 00 00 00 01 20 12 03 05 57 52 2d 50
- 0070: 65 72 69 70 68 2d 53 79 73 63 6f 6e 20 20 20 01
diff --git a/drivers/Kconfig b/drivers/Kconfig
index e8231663f201..61cf4ea2c229 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -188,8 +188,6 @@ source "drivers/ipack/Kconfig"
source "drivers/reset/Kconfig"
-source "drivers/fmc/Kconfig"
-
source "drivers/phy/Kconfig"
source "drivers/powercap/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 28b030d7988d..6d37564e783c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -168,7 +168,6 @@ obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_IPACK_BUS) += ipack/
obj-$(CONFIG_NTB) += ntb/
-obj-$(CONFIG_FMC) += fmc/
obj-$(CONFIG_POWERCAP) += powercap/
obj-$(CONFIG_MCB) += mcb/
obj-$(CONFIG_PERF_EVENTS) += perf/
diff --git a/drivers/fmc/Kconfig b/drivers/fmc/Kconfig
deleted file mode 100644
index ae3d7f634932..000000000000
--- a/drivers/fmc/Kconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# FMC (ANSI-VITA 57.1) bus support
-#
-
-menuconfig FMC
- tristate "FMC support"
- help
-
- FMC (FPGA Mezzanine Carrier) is a mechanical and electrical
- standard for mezzanine cards that plug into a carrier board.
- This kernel subsystem supports the matching between carrier
- and mezzanine based on identifiers stored in the internal I2C
- EEPROM, as well as having carrier-independent drivers.
-
- The framework was born outside of the kernel and at this time
- the off-tree code base is more complete. Code and documentation
- is at git://ohwr.org/fmc-projects/fmc-bus.git .
-
-if FMC
-
-config FMC_FAKEDEV
- tristate "FMC fake device (software testing)"
- help
- This is a fake carrier, bringing a default EEPROM content
- that can be rewritten at run time and usef for matching
- mezzanines.
-
-config FMC_TRIVIAL
- tristate "FMC trivial mezzanine driver (software testing)"
- help
- This is a fake mezzanine driver, to show how FMC works and test it.
- The driver also handles interrupts (we used it with a real carrier
- before the mezzanines were produced)
-
-config FMC_WRITE_EEPROM
- tristate "FMC mezzanine driver to write I2C EEPROM"
- help
- This driver matches every mezzanine device and can write the
- internal EEPROM of the PCB, using the firmware loader to get
- its binary and the function carrier->reprogram to actually do it.
- It is useful when the mezzanines are produced.
-
-config FMC_CHARDEV
- tristate "FMC mezzanine driver that registers a char device"
- help
- This driver matches every mezzanine device and allows user
- space to read and write registers using a char device. It
- can be used to write user-space drivers, or just get
- acquainted with a mezzanine before writing its specific driver.
-
-endif # FMC
diff --git a/drivers/fmc/Makefile b/drivers/fmc/Makefile
deleted file mode 100644
index e3da6192cf39..000000000000
--- a/drivers/fmc/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_FMC) += fmc.o
-
-fmc-y = fmc-core.o
-fmc-y += fmc-match.o
-fmc-y += fmc-sdb.o
-fmc-y += fru-parse.o
-fmc-y += fmc-dump.o
-fmc-y += fmc-debug.o
-
-obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o
-obj-$(CONFIG_FMC_TRIVIAL) += fmc-trivial.o
-obj-$(CONFIG_FMC_WRITE_EEPROM) += fmc-write-eeprom.o
-obj-$(CONFIG_FMC_CHARDEV) += fmc-chardev.o
diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c
deleted file mode 100644
index 7d2091b5e978..000000000000
--- a/drivers/fmc/fmc-chardev.c
+++ /dev/null
@@ -1,199 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * 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/init.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-#include <linux/fmc.h>
-#include <linux/uaccess.h>
-
-static LIST_HEAD(fc_devices);
-static DEFINE_SPINLOCK(fc_lock);
-
-struct fc_instance {
- struct list_head list;
- struct fmc_device *fmc;
- struct miscdevice misc;
-};
-
-/* at open time, we must identify our device */
-static int fc_open(struct inode *ino, struct file *f)
-{
- struct fmc_device *fmc;
- struct fc_instance *fc;
- int minor = iminor(ino);
-
- list_for_each_entry(fc, &fc_devices, list)
- if (fc->misc.minor == minor)
- break;
- if (fc->misc.minor != minor)
- return -ENODEV;
- fmc = fc->fmc;
- if (try_module_get(fmc->owner) == 0)
- return -ENODEV;
-
- f->private_data = fmc;
- return 0;
-}
-
-static int fc_release(struct inode *ino, struct file *f)
-{
- struct fmc_device *fmc = f->private_data;
- module_put(fmc->owner);
- return 0;
-}
-
-/* read and write are simple after the default llseek has been used */
-static ssize_t fc_read(struct file *f, char __user *buf, size_t count,
- loff_t *offp)
-{
- struct fmc_device *fmc = f->private_data;
- unsigned long addr;
- uint32_t val;
-
- if (count < sizeof(val))
- return -EINVAL;
- count = sizeof(val);
-
- addr = *offp;
- if (addr > fmc->memlen)
- return -ESPIPE; /* Illegal seek */
- val = fmc_readl(fmc, addr);
- if (copy_to_user(buf, &val, count))
- return -EFAULT;
- *offp += count;
- return count;
-}
-
-static ssize_t fc_write(struct file *f, const char __user *buf, size_t count,
- loff_t *offp)
-{
- struct fmc_device *fmc = f->private_data;
- unsigned long addr;
- uint32_t val;
-
- if (count < sizeof(val))
- return -EINVAL;
- count = sizeof(val);
-
- addr = *offp;
- if (addr > fmc->memlen)
- return -ESPIPE; /* Illegal seek */
- if (copy_from_user(&val, buf, count))
- return -EFAULT;
- fmc_writel(fmc, val, addr);
- *offp += count;
- return count;
-}
-
-static const struct file_operations fc_fops = {
- .owner = THIS_MODULE,
- .open = fc_open,
- .release = fc_release,
- .llseek = generic_file_llseek,
- .read = fc_read,
- .write = fc_write,
-};
-
-
-/* Device part .. */
-static int fc_probe(struct fmc_device *fmc);
-static int fc_remove(struct fmc_device *fmc);
-
-static struct fmc_driver fc_drv = {
- .version = FMC_VERSION,
- .driver.name = KBUILD_MODNAME,
- .probe = fc_probe,
- .remove = fc_remove,
- /* no table: we want to match everything */
-};
-
-/* We accept the generic busid parameter */
-FMC_PARAM_BUSID(fc_drv);
-
-/* probe and remove must allocate and release a misc device */
-static int fc_probe(struct fmc_device *fmc)
-{
- int ret;
- int index = 0;
-
- struct fc_instance *fc;
-
- index = fmc_validate(fmc, &fc_drv);
- if (index < 0)
- return -EINVAL; /* not our device: invalid */
-
- /* Create a char device: we want to create it anew */
- fc = kzalloc(sizeof(*fc), GFP_KERNEL);
- if (!fc)
- return -ENOMEM;
- fc->fmc = fmc;
- fc->misc.minor = MISC_DYNAMIC_MINOR;
- fc->misc.fops = &fc_fops;
- fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL);
-
- ret = misc_register(&fc->misc);
- if (ret < 0)
- goto out;
- spin_lock(&fc_lock);
- list_add(&fc->list, &fc_devices);
- spin_unlock(&fc_lock);
- dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n",
- fc->misc.name);
- return 0;
-
-out:
- kfree(fc->misc.name);
- kfree(fc);
- return ret;
-}
-
-static int fc_remove(struct fmc_device *fmc)
-{
- struct fc_instance *fc;
-
- list_for_each_entry(fc, &fc_devices, list)
- if (fc->fmc == fmc)
- break;
- if (fc->fmc != fmc) {
- dev_err(&fmc->dev, "remove called but not found\n");
- return -ENODEV;
- }
-
- spin_lock(&fc_lock);
- list_del(&fc->list);
- spin_unlock(&fc_lock);
- misc_deregister(&fc->misc);
- kfree(fc->misc.name);
- kfree(fc);
-
- return 0;
-}
-
-
-static int fc_init(void)
-{
- int ret;
-
- ret = fmc_driver_register(&fc_drv);
- return ret;
-}
-
-static void fc_exit(void)
-{
- fmc_driver_unregister(&fc_drv);
-}
-
-module_init(fc_init);
-module_exit(fc_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/fmc/fmc-core.c b/drivers/fmc/fmc-core.c
deleted file mode 100644
index 573f5471f680..000000000000
--- a/drivers/fmc/fmc-core.c
+++ /dev/null
@@ -1,388 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * This work is part of the White Rabbit project, a research effort led
- * by CERN, the European Institute for Nuclear Research.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/fmc.h>
-#include <linux/fmc-sdb.h>
-
-#include "fmc-private.h"
-
-static int fmc_check_version(unsigned long version, const char *name)
-{
- if (__FMC_MAJOR(version) != FMC_MAJOR) {
- pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
- __func__, name, __FMC_MAJOR(version), FMC_MAJOR);
- return -EINVAL;
- }
-
- if (__FMC_MINOR(version) != FMC_MINOR)
- pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
- __func__, name, __FMC_MINOR(version), FMC_MINOR);
- return 0;
-}
-
-static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- /* struct fmc_device *fdev = to_fmc_device(dev); */
-
- /* FIXME: The MODALIAS */
- add_uevent_var(env, "MODALIAS=%s", "fmc");
- return 0;
-}
-
-static int fmc_probe(struct device *dev)
-{
- struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
- struct fmc_device *fdev = to_fmc_device(dev);
-
- return fdrv->probe(fdev);
-}
-
-static int fmc_remove(struct device *dev)
-{
- struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
- struct fmc_device *fdev = to_fmc_device(dev);
-
- return fdrv->remove(fdev);
-}
-
-static void fmc_shutdown(struct device *dev)
-{
- /* not implemented but mandatory */
-}
-
-static struct bus_type fmc_bus_type = {
- .name = "fmc",
- .match = fmc_match,
- .uevent = fmc_uevent,
- .probe = fmc_probe,
- .remove = fmc_remove,
- .shutdown = fmc_shutdown,
-};
-
-static void fmc_release(struct device *dev)
-{
- struct fmc_device *fmc = container_of(dev, struct fmc_device, dev);
-
- kfree(fmc);
-}
-
-/*
- * The eeprom is exported in sysfs, through a binary attribute
- */
-
-static ssize_t fmc_read_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;
- int eelen;
-
- dev = container_of(kobj, struct device, kobj);
- fmc = container_of(dev, struct fmc_device, dev);
- eelen = fmc->eeprom_len;
- if (off > eelen)
- return -ESPIPE;
- if (off == eelen)
- return 0; /* EOF */
- if (off + count > eelen)
- count = eelen - off;
- memcpy(buf, fmc->eeprom + off, 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 = {
- .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, },
- .size = 8192, /* more or less standard */
- .read = fmc_read_eeprom,
- .write = fmc_write_eeprom,
-};
-
-int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h,
- char *name, int flags)
-{
- if (fmc->op->irq_request)
- return fmc->op->irq_request(fmc, h, name, flags);
- return -EPERM;
-}
-EXPORT_SYMBOL(fmc_irq_request);
-
-void fmc_irq_free(struct fmc_device *fmc)
-{
- if (fmc->op->irq_free)
- fmc->op->irq_free(fmc);
-}
-EXPORT_SYMBOL(fmc_irq_free);
-
-void fmc_irq_ack(struct fmc_device *fmc)
-{
- if (likely(fmc->op->irq_ack))
- fmc->op->irq_ack(fmc);
-}
-EXPORT_SYMBOL(fmc_irq_ack);
-
-int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv)
-{
- if (fmc->op->validate)
- return fmc->op->validate(fmc, drv);
- return -EPERM;
-}
-EXPORT_SYMBOL(fmc_validate);
-
-int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio, int ngpio)
-{
- if (fmc->op->gpio_config)
- return fmc->op->gpio_config(fmc, gpio, ngpio);
- return -EPERM;
-}
-EXPORT_SYMBOL(fmc_gpio_config);
-
-int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l)
-{
- if (fmc->op->read_ee)
- return fmc->op->read_ee(fmc, pos, d, l);
- return -EPERM;
-}
-EXPORT_SYMBOL(fmc_read_ee);
-
-int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l)
-{
- if (fmc->op->write_ee)
- return fmc->op->write_ee(fmc, pos, d, l);
- return -EPERM;
-}
-EXPORT_SYMBOL(fmc_write_ee);
-
-/*
- * Functions for client modules follow
- */
-
-int fmc_driver_register(struct fmc_driver *drv)
-{
- if (fmc_check_version(drv->version, drv->driver.name))
- return -EINVAL;
- drv->driver.bus = &fmc_bus_type;
- return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(fmc_driver_register);
-
-void fmc_driver_unregister(struct fmc_driver *drv)
-{
- driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(fmc_driver_unregister);
-
-/*
- * When a device set is registered, all eeproms must be read
- * and all FRUs must be parsed
- */
-int fmc_device_register_n_gw(struct fmc_device **devs, int n,
- struct fmc_gateware *gw)
-{
- struct fmc_device *fmc, **devarray;
- uint32_t device_id;
- int i, ret = 0;
-
- if (n < 1)
- return 0;
-
- /* Check the version of the first data structure (function prints) */
- if (fmc_check_version(devs[0]->version, devs[0]->carrier_name))
- return -EINVAL;
-
- devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL);
- if (!devarray)
- return -ENOMEM;
-
- /* Make all other checks before continuing, for all devices */
- for (i = 0; i < n; i++) {
- fmc = devarray[i];
- if (!fmc->hwdev) {
- pr_err("%s: device nr. %i has no hwdev pointer\n",
- __func__, i);
- ret = -EINVAL;
- break;
- }
- if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) {
- dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
- fmc->slot_id);
- continue;
- }
- if (!fmc->eeprom) {
- dev_err(fmc->hwdev, "no eeprom provided for slot %i\n",
- fmc->slot_id);
- ret = -EINVAL;
- }
- if (!fmc->eeprom_addr) {
- dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n",
- fmc->slot_id);
- ret = -EINVAL;
- }
- if (!fmc->carrier_name || !fmc->carrier_data ||
- !fmc->device_id) {
- dev_err(fmc->hwdev,
- "device nr %i: carrier name, "
- "data or dev_id not set\n", i);
- ret = -EINVAL;
- }
- if (ret)
- break;
-
- }
- if (ret) {
- kfree(devarray);
- return ret;
- }
-
- /* Validation is ok. Now init and register the devices */
- for (i = 0; i < n; i++) {
- fmc = devarray[i];
-
- fmc->nr_slots = n; /* each slot must know how many are there */
- fmc->devarray = devarray;
-
- device_initialize(&fmc->dev);
- fmc->dev.release = fmc_release;
- fmc->dev.parent = fmc->hwdev;
-
- /* Fill the identification stuff (may fail) */
- fmc_fill_id_info(fmc);
-
- fmc->dev.bus = &fmc_bus_type;
-
- /* Name from mezzanine info or carrier info. Or 0,1,2.. */
- device_id = fmc->device_id;
- if (!fmc->mezzanine_name)
- dev_set_name(&fmc->dev, "fmc-%04x", device_id);
- else
- dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
- device_id);
-
- if (gw) {
- /*
- * The carrier already know the bitstream to load
- * for this set of FMC mezzanines.
- */
- ret = fmc->op->reprogram_raw(fmc, NULL,
- gw->bitstream, gw->len);
- if (ret) {
- dev_warn(fmc->hwdev,
- "Invalid gateware for FMC mezzanine\n");
- goto out;
- }
- }
-
- ret = device_add(&fmc->dev);
- if (ret < 0) {
- dev_err(fmc->hwdev, "Slot %i: Failed in registering "
- "\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name);
- goto out;
- }
- ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
- if (ret < 0) {
- dev_err(&fmc->dev, "Failed in registering eeprom\n");
- goto out1;
- }
- /* This device went well, give information to the user */
- fmc_dump_eeprom(fmc);
- fmc_debug_init(fmc);
- }
- return 0;
-
-out1:
- device_del(&fmc->dev);
-out:
- kfree(devarray);
- for (i--; i >= 0; i--) {
- fmc_debug_exit(devs[i]);
- sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
- device_del(&devs[i]->dev);
- fmc_free_id_info(devs[i]);
- put_device(&devs[i]->dev);
- }
- return ret;
-
-}
-EXPORT_SYMBOL(fmc_device_register_n_gw);
-
-int fmc_device_register_n(struct fmc_device **devs, int n)
-{
- return fmc_device_register_n_gw(devs, n, NULL);
-}
-EXPORT_SYMBOL(fmc_device_register_n);
-
-int fmc_device_register_gw(struct fmc_device *fmc, struct fmc_gateware *gw)
-{
- return fmc_device_register_n_gw(&fmc, 1, gw);
-}
-EXPORT_SYMBOL(fmc_device_register_gw);
-
-int fmc_device_register(struct fmc_device *fmc)
-{
- return fmc_device_register_n(&fmc, 1);
-}
-EXPORT_SYMBOL(fmc_device_register);
-
-void fmc_device_unregister_n(struct fmc_device **devs, int n)
-{
- int i;
-
- if (n < 1)
- return;
-
- /* Free devarray first, not used by the later loop */
- kfree(devs[0]->devarray);
-
- for (i = 0; i < n; i++) {
- fmc_debug_exit(devs[i]);
- sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
- device_del(&devs[i]->dev);
- fmc_free_id_info(devs[i]);
- put_device(&devs[i]->dev);
- }
-}
-EXPORT_SYMBOL(fmc_device_unregister_n);
-
-void fmc_device_unregister(struct fmc_device *fmc)
-{
- fmc_device_unregister_n(&fmc, 1);
-}
-EXPORT_SYMBOL(fmc_device_unregister);
-
-/* Init and exit are trivial */
-static int fmc_init(void)
-{
- return bus_register(&fmc_bus_type);
-}
-
-static void fmc_exit(void)
-{
- bus_unregister(&fmc_bus_type);
-}
-
-module_init(fmc_init);
-module_exit(fmc_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/fmc/fmc-debug.c b/drivers/fmc/fmc-debug.c
deleted file mode 100644
index 1734c7cf0e76..000000000000
--- a/drivers/fmc/fmc-debug.c
+++ /dev/null
@@ -1,172 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2015 CERN (www.cern.ch)
- * Author: Federico Vaga <federico.vaga@cern.ch>
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <asm/byteorder.h>
-
-#include <linux/fmc.h>
-#include <linux/sdb.h>
-#include <linux/fmc-sdb.h>
-
-#define FMC_DBG_SDB_DUMP "dump_sdb"
-
-static char *__strip_trailing_space(char *buf, char *str, int len)
-{
- int i = len - 1;
-
- memcpy(buf, str, len);
- buf[len] = '\0';
- while (i >= 0 && buf[i] == ' ')
- buf[i--] = '\0';
- return buf;
-}
-
-#define __sdb_string(buf, field) ({ \
- BUILD_BUG_ON(sizeof(buf) < sizeof(field)); \
- __strip_trailing_space(buf, (void *)(field), sizeof(field)); \
- })
-
-/**
- * We do not check seq_printf() errors because we want to see things in any case
- */
-static void fmc_sdb_dump_recursive(struct fmc_device *fmc, struct seq_file *s,
- const struct sdb_array *arr)
-{
- unsigned long base = arr->baseaddr;
- int i, j, n = arr->len, level = arr->level;
- char tmp[64];
-
- for (i = 0; i < n; i++) {
- union sdb_record *r;
- struct sdb_product *p;
- struct sdb_component *c;
-
- r = &arr->record[i];
- c = &r->dev.sdb_component;
- p = &c->product;
-
- for (j = 0; j < level; j++)
- seq_printf(s, " ");
- switch (r->empty.record_type) {
- case sdb_type_interconnect:
- seq_printf(s, "%08llx:%08x %.19s\n",
- __be64_to_cpu(p->vendor_id),
- __be32_to_cpu(p->device_id),
- p->name);
- break;
- case sdb_type_device:
- seq_printf(s, "%08llx:%08x %.19s (%08llx-%08llx)\n",
- __be64_to_cpu(p->vendor_id),
- __be32_to_cpu(p->device_id),
- p->name,
- __be64_to_cpu(c->addr_first) + base,
- __be64_to_cpu(c->addr_last) + base);
- break;
- case sdb_type_bridge:
- seq_printf(s, "%08llx:%08x %.19s (bridge: %08llx)\n",
- __be64_to_cpu(p->vendor_id),
- __be32_to_cpu(p->device_id),
- p->name,
- __be64_to_cpu(c->addr_first) + base);
- if (IS_ERR(arr->subtree[i])) {
- seq_printf(s, "SDB: (bridge error %li)\n",
- PTR_ERR(arr->subtree[i]));
- break;
- }
- fmc_sdb_dump_recursive(fmc, s, arr->subtree[i]);
- break;
- case sdb_type_integration:
- seq_printf(s, "integration\n");
- break;
- case sdb_type_repo_url:
- seq_printf(s, "Synthesis repository: %s\n",
- __sdb_string(tmp, r->repo_url.repo_url));
- break;
- case sdb_type_synthesis:
- seq_printf(s, "Bitstream '%s' ",
- __sdb_string(tmp, r->synthesis.syn_name));
- seq_printf(s, "synthesized %08x by %s ",
- __be32_to_cpu(r->synthesis.date),
- __sdb_string(tmp, r->synthesis.user_name));
- seq_printf(s, "(%s version %x), ",
- __sdb_string(tmp, r->synthesis.tool_name),
- __be32_to_cpu(r->synthesis.tool_version));
- seq_printf(s, "commit %pm\n",
- r->synthesis.commit_id);
- break;
- case sdb_type_empty:
- seq_printf(s, "empty\n");
- break;
- default:
- seq_printf(s, "UNKNOWN TYPE 0x%02x\n",
- r->empty.record_type);
- break;
- }
- }
-}
-
-static int fmc_sdb_dump(struct seq_file *s, void *offset)
-{
- struct fmc_device *fmc = s->private;
-
- if (!fmc->sdb) {
- seq_printf(s, "no SDB information\n");
- return 0;
- }
-
- seq_printf(s, "FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
- fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
- /* Dump SDB information */
- fmc_sdb_dump_recursive(fmc, s, fmc->sdb);
-
- return 0;
-}
-
-
-static int fmc_sdb_dump_open(struct inode *inode, struct file *file)
-{
- struct fmc_device *fmc = inode->i_private;
-
- return single_open(file, fmc_sdb_dump, fmc);
-}
-
-
-const struct file_operations fmc_dbgfs_sdb_dump = {
- .owner = THIS_MODULE,
- .open = fmc_sdb_dump_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-int fmc_debug_init(struct fmc_device *fmc)
-{
- fmc->dbg_dir = debugfs_create_dir(dev_name(&fmc->dev), NULL);
- if (IS_ERR_OR_NULL(fmc->dbg_dir)) {
- pr_err("FMC: Cannot create debugfs\n");
- return PTR_ERR(fmc->dbg_dir);
- }
-
- fmc->dbg_sdb_dump = debugfs_create_file(FMC_DBG_SDB_DUMP, 0444,
- fmc->dbg_dir, fmc,
- &fmc_dbgfs_sdb_dump);
- if (IS_ERR_OR_NULL(fmc->dbg_sdb_dump))
- pr_err("FMC: Cannot create debugfs file %s\n",
- FMC_DBG_SDB_DUMP);
-
- return 0;
-}
-
-void fmc_debug_exit(struct fmc_device *fmc)
-{
- if (fmc->dbg_dir)
- debugfs_remove_recursive(fmc->dbg_dir);
-}
diff --git a/drivers/fmc/fmc-dump.c b/drivers/fmc/fmc-dump.c
deleted file mode 100644
index 6c81dbde1d16..000000000000
--- a/drivers/fmc/fmc-dump.c
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2013 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * This work is part of the White Rabbit project, a research effort led
- * by CERN, the European Institute for Nuclear Research.
- */
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/fmc.h>
-#include <linux/fmc-sdb.h>
-
-static int fmc_must_dump_eeprom;
-module_param_named(dump_eeprom, fmc_must_dump_eeprom, int, 0644);
-
-#define LINELEN 16
-
-/* Dumping 8k takes oh so much: avoid duplicate lines */
-static const uint8_t *dump_line(int addr, const uint8_t *line,
- const uint8_t *prev)
-{
- int i;
-
- if (!prev || memcmp(line, prev, LINELEN)) {
- pr_info("%04x: ", addr);
- for (i = 0; i < LINELEN; ) {
- printk(KERN_CONT "%02x", line[i]);
- i++;
- printk(i & 3 ? " " : i & (LINELEN - 1) ? " " : "\n");
- }
- return line;
- }
- /* repeated line */
- if (line == prev + LINELEN)
- pr_info("[...]\n");
- return prev;
-}
-
-void fmc_dump_eeprom(const struct fmc_device *fmc)
-{
- const uint8_t *line, *prev;
- int i;
-
- if (!fmc_must_dump_eeprom)
- return;
-
- pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
- fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
- pr_info("FMC: dumping eeprom 0x%x (%i) bytes\n", fmc->eeprom_len,
- fmc->eeprom_len);
-
- line = fmc->eeprom;
- prev = NULL;
- for (i = 0; i < fmc->eeprom_len; i += LINELEN, line += LINELEN)
- prev = dump_line(i, line, prev);
-}
diff --git a/drivers/fmc/fmc-fakedev.c b/drivers/fmc/fmc-fakedev.c
deleted file mode 100644
index 941d0930969a..000000000000
--- a/drivers/fmc/fmc-fakedev.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * The software is provided "as is"; the copyright holders disclaim
- * all warranties and liabilities, to the extent permitted by
- * applicable law.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-#include <linux/workqueue.h>
-#include <linux/err.h>
-#include <linux/fmc.h>
-
-#define FF_EEPROM_SIZE 8192 /* The standard eeprom size */
-#define FF_MAX_MEZZANINES 4 /* Fakes a multi-mezzanine carrier */
-
-/* The user can pass up to 4 names of eeprom images to load */
-static char *ff_eeprom[FF_MAX_MEZZANINES];
-static int ff_nr_eeprom;
-module_param_array_named(eeprom, ff_eeprom, charp, &ff_nr_eeprom, 0444);
-
-/* The user can ask for a multi-mezzanine carrier, with the default eeprom */
-static int ff_nr_dev = 1;
-module_param_named(ndev, ff_nr_dev, int, 0444);
-
-
-/* Lazily, don't support the "standard" module parameters */
-
-/*
- * Eeprom built from these commands:
-
- ../fru-generator -v fake-vendor -n fake-design-for-testing \
- -s 01234 -p none > IPMI-FRU
-
- gensdbfs . ../fake-eeprom.bin
-*/
-static char ff_eeimg[FF_MAX_MEZZANINES][FF_EEPROM_SIZE] = {
- {
- 0x01, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf2, 0x01, 0x0b, 0x00, 0xb2,
- 0x86, 0x87, 0xcb, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x76, 0x65, 0x6e, 0x64,
- 0x6f, 0x72, 0xd7, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x69,
- 0x67, 0x6e, 0x2d, 0x66, 0x6f, 0x72, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69,
- 0x6e, 0x67, 0xc5, 0x30, 0x31, 0x32, 0x33, 0x34, 0xc4, 0x6e, 0x6f, 0x6e,
- 0x65, 0xda, 0x32, 0x30, 0x31, 0x32, 0x2d, 0x31, 0x31, 0x2d, 0x31, 0x39,
- 0x20, 0x32, 0x32, 0x3a, 0x34, 0x32, 0x3a, 0x33, 0x30, 0x2e, 0x30, 0x37,
- 0x34, 0x30, 0x35, 0x35, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
- 0x02, 0x02, 0x0d, 0xf7, 0xf8, 0x02, 0xb0, 0x04, 0x74, 0x04, 0xec, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x02, 0x02, 0x0d, 0x5c, 0x93, 0x01,
- 0x4a, 0x01, 0x39, 0x01, 0x5a, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0b,
- 0x02, 0x02, 0x0d, 0x63, 0x8c, 0x00, 0xfa, 0x00, 0xed, 0x00, 0x06, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x01, 0x02, 0x0d, 0xfb, 0xf5, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x0d, 0xfc, 0xf4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0d, 0xfd, 0xf3, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xfa, 0x82, 0x0b, 0xea, 0x8f, 0xa2, 0x12, 0x00, 0x00, 0x1e, 0x44, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x53, 0x44, 0x42, 0x2d, 0x00, 0x03, 0x01, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61,
- 0x2e, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65,
- 0x44, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf,
- 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x49, 0x50, 0x4d, 0x49,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4d, 0x49,
- 0x2d, 0x46, 0x52, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x01, 0x66, 0x61, 0x6b, 0x65, 0x0a,
- },
-};
-
-struct ff_dev {
- struct fmc_device *fmc[FF_MAX_MEZZANINES];
- struct device dev;
-};
-
-static struct ff_dev *ff_current_dev; /* We have 1 carrier, 1 slot */
-
-static int ff_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
- char *gw)
-{
- const struct firmware *fw;
- int ret;
-
- if (!gw) {
- /* program golden: success */
- fmc->flags &= ~FMC_DEVICE_HAS_CUSTOM;
- fmc->flags |= FMC_DEVICE_HAS_GOLDEN;
- return 0;
- }
-
- dev_info(&fmc->dev, "reprogramming with %s\n", gw);
- ret = request_firmware(&fw, gw, &fmc->dev);
- if (ret < 0) {
- dev_warn(&fmc->dev, "request firmware \"%s\": error %i\n",
- gw, ret);
- goto out;
- }
- fmc->flags &= ~FMC_DEVICE_HAS_GOLDEN;
- fmc->flags |= FMC_DEVICE_HAS_CUSTOM;
-
-out:
- release_firmware(fw);
- return ret;
-}
-
-static int ff_irq_request(struct fmc_device *fmc, irq_handler_t handler,
- char *name, int flags)
-{
- return -EOPNOTSUPP;
-}
-
-/* FIXME: should also have some fake FMC GPIO mapping */
-
-
-/*
- * This work function is called when we changed the eeprom. It removes the
- * current fmc device and registers a new one, with different identifiers.
- */
-static struct ff_dev *ff_dev_create(void); /* defined later */
-
-static void ff_work_fn(struct work_struct *work)
-{
- struct ff_dev *ff = ff_current_dev;
- int ret;
-
- fmc_device_unregister_n(ff->fmc, ff_nr_dev);
- device_unregister(&ff->dev);
- ff_current_dev = NULL;
-
- ff = ff_dev_create();
- if (IS_ERR(ff)) {
- pr_warning("%s: can't re-create FMC devices\n", __func__);
- return;
- }
- ret = fmc_device_register_n(ff->fmc, ff_nr_dev);
- if (ret < 0) {
- dev_warn(&ff->dev, "can't re-register FMC devices\n");
- device_unregister(&ff->dev);
- return;
- }
-
- ff_current_dev = ff;
-}
-
-static DECLARE_DELAYED_WORK(ff_work, ff_work_fn);
-
-
-/* low-level i2c */
-static int ff_eeprom_read(struct fmc_device *fmc, uint32_t offset,
- void *buf, size_t size)
-{
- if (offset > FF_EEPROM_SIZE)
- return -EINVAL;
- if (offset + size > FF_EEPROM_SIZE)
- size = FF_EEPROM_SIZE - offset;
- memcpy(buf, fmc->eeprom + offset, size);
- return size;
-}
-
-static int ff_eeprom_write(struct fmc_device *fmc, uint32_t offset,
- const void *buf, size_t size)
-{
- if (offset > FF_EEPROM_SIZE)
- return -EINVAL;
- if (offset + size > FF_EEPROM_SIZE)
- size = FF_EEPROM_SIZE - offset;
- dev_info(&fmc->dev, "write_eeprom: offset %i, size %zi\n",
- (int)offset, size);
- memcpy(fmc->eeprom + offset, buf, size);
- schedule_delayed_work(&ff_work, HZ * 2); /* remove, replug, in 2s */
- return size;
-}
-
-/* i2c operations for fmc */
-static int ff_read_ee(struct fmc_device *fmc, int pos, void *data, int len)
-{
- if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
- return -EOPNOTSUPP;
- return ff_eeprom_read(fmc, pos, data, len);
-}
-
-static int ff_write_ee(struct fmc_device *fmc, int pos,
- const void *data, int len)
-{
- if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
- return -EOPNOTSUPP;
- return ff_eeprom_write(fmc, pos, data, len);
-}
-
-/* readl and writel do not do anything. Don't waste RAM with "base" */
-static uint32_t ff_readl(struct fmc_device *fmc, int offset)
-{
- return 0;
-}
-
-static void ff_writel(struct fmc_device *fmc, uint32_t value, int offset)
-{
- return;
-}
-
-/* validate is useful so fmc-write-eeprom will not reprogram every 2 seconds */
-static int ff_validate(struct fmc_device *fmc, struct fmc_driver *drv)
-{
- int i;
-
- if (!drv->busid_n)
- return 0; /* everyhing is valid */
- for (i = 0; i < drv->busid_n; i++)
- if (drv->busid_val[i] == fmc->device_id)
- return i;
- return -ENOENT;
-}
-
-
-
-static struct fmc_operations ff_fmc_operations = {
- .read32 = ff_readl,
- .write32 = ff_writel,
- .reprogram = ff_reprogram,
- .irq_request = ff_irq_request,
- .read_ee = ff_read_ee,
- .write_ee = ff_write_ee,
- .validate = ff_validate,
-};
-
-/* This device is kmalloced: release it */
-static void ff_dev_release(struct device *dev)
-{
- struct ff_dev *ff = container_of(dev, struct ff_dev, dev);
- kfree(ff);
-}
-
-static struct fmc_device ff_template_fmc = {
- .version = FMC_VERSION,
- .owner = THIS_MODULE,
- .carrier_name = "fake-fmc-carrier",
- .device_id = 0xf001, /* fool */
- .eeprom_len = sizeof(ff_eeimg[0]),
- .memlen = 0x1000, /* 4k, to show something */
- .op = &ff_fmc_operations,
- .hwdev = NULL, /* filled at creation time */
- .flags = FMC_DEVICE_HAS_GOLDEN,
-};
-
-static struct ff_dev *ff_dev_create(void)
-{
- struct ff_dev *ff;
- struct fmc_device *fmc;
- int i, ret;
-
- ff = kzalloc(sizeof(*ff), GFP_KERNEL);
- if (!ff)
- return ERR_PTR(-ENOMEM);
- dev_set_name(&ff->dev, "fake-fmc-carrier");
- ff->dev.release = ff_dev_release;
-
- ret = device_register(&ff->dev);
- if (ret < 0) {
- put_device(&ff->dev);
- return ERR_PTR(ret);
- }
-
- /* Create fmc structures that refer to this new "hw" device */
- for (i = 0; i < ff_nr_dev; i++) {
- fmc = kmemdup(&ff_template_fmc, sizeof(ff_template_fmc),
- GFP_KERNEL);
- fmc->hwdev = &ff->dev;
- fmc->carrier_data = ff;
- fmc->nr_slots = ff_nr_dev;
- /* the following fields are different for each slot */
- fmc->eeprom = ff_eeimg[i];
- fmc->eeprom_addr = 0x50 + 2 * i;
- fmc->slot_id = i;
- ff->fmc[i] = fmc;
- /* increment the identifier, each must be different */
- ff_template_fmc.device_id++;
- }
- return ff;
-}
-
-/* init and exit */
-static int ff_init(void)
-{
- struct ff_dev *ff;
- const struct firmware *fw;
- int i, len, ret = 0;
-
- /* Replicate the default eeprom for the max number of mezzanines */
- for (i = 1; i < FF_MAX_MEZZANINES; i++)
- memcpy(ff_eeimg[i], ff_eeimg[0], sizeof(ff_eeimg[0]));
-
- if (ff_nr_eeprom > ff_nr_dev)
- ff_nr_dev = ff_nr_eeprom;
-
- ff = ff_dev_create();
- if (IS_ERR(ff))
- return PTR_ERR(ff);
-
- /* If the user passed "eeprom=" as a parameter, fetch them */
- for (i = 0; i < ff_nr_eeprom; i++) {
- if (!strlen(ff_eeprom[i]))
- continue;
- ret = request_firmware(&fw, ff_eeprom[i], &ff->dev);
- if (ret < 0) {
- dev_err(&ff->dev, "Mezzanine %i: can't load \"%s\" "
- "(error %i)\n", i, ff_eeprom[i], -ret);
- } else {
- len = min_t(size_t, fw->size, (size_t)FF_EEPROM_SIZE);
- memcpy(ff_eeimg[i], fw->data, len);
- release_firmware(fw);
- dev_info(&ff->dev, "Mezzanine %i: eeprom \"%s\"\n", i,
- ff_eeprom[i]);
- }
- }
-
- ret = fmc_device_register_n(ff->fmc, ff_nr_dev);
- if (ret) {
- device_unregister(&ff->dev);
- return ret;
- }
- ff_current_dev = ff;
- return ret;
-}
-
-static void ff_exit(void)
-{
- if (ff_current_dev) {
- fmc_device_unregister_n(ff_current_dev->fmc, ff_nr_dev);
- device_unregister(&ff_current_dev->dev);
- }
- cancel_delayed_work_sync(&ff_work);
-}
-
-module_init(ff_init);
-module_exit(ff_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/fmc/fmc-match.c b/drivers/fmc/fmc-match.c
deleted file mode 100644
index 995bd6041a67..000000000000
--- a/drivers/fmc/fmc-match.c
+++ /dev/null
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * This work is part of the White Rabbit project, a research effort led
- * by CERN, the European Institute for Nuclear Research.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/fmc.h>
-#include <linux/ipmi-fru.h>
-
-/* The fru parser is both user and kernel capable: it needs alloc */
-void *fru_alloc(size_t size)
-{
- return kzalloc(size, GFP_KERNEL);
-}
-
-/* The actual match function */
-int fmc_match(struct device *dev, struct device_driver *drv)
-{
- struct fmc_driver *fdrv = to_fmc_driver(drv);
- struct fmc_device *fdev = to_fmc_device(dev);
- struct fmc_fru_id *fid;
- int i, matched = 0;
-
- /* This currently only matches the EEPROM (FRU id) */
- fid = fdrv->id_table.fru_id;
- if (!fid) {
- dev_warn(&fdev->dev, "Driver has no ID: matches all\n");
- matched = 1;
- } else {
- if (!fdev->id.manufacturer || !fdev->id.product_name)
- return 0; /* the device has no FRU information */
- for (i = 0; i < fdrv->id_table.fru_id_nr; i++, fid++) {
- if (fid->manufacturer &&
- strcmp(fid->manufacturer, fdev->id.manufacturer))
- continue;
- if (fid->product_name &&
- strcmp(fid->product_name, fdev->id.product_name))
- continue;
- matched = 1;
- break;
- }
- }
-
- /* FIXME: match SDB contents */
- return matched;
-}
-
-/* This function creates ID info for a newly registered device */
-int fmc_fill_id_info(struct fmc_device *fmc)
-{
- struct fru_common_header *h;
- struct fru_board_info_area *bia;
- int ret, allocated = 0;
-
- /* If we know the eeprom length, try to read it off the device */
- if (fmc->eeprom_len && !fmc->eeprom) {
- fmc->eeprom = kzalloc(fmc->eeprom_len, GFP_KERNEL);
- if (!fmc->eeprom)
- return -ENOMEM;
- allocated = 1;
- ret = fmc_read_ee(fmc, 0, fmc->eeprom, fmc->eeprom_len);
- if (ret < 0)
- goto out;
- }
-
- /* If no eeprom, continue with other matches */
- if (!fmc->eeprom)
- return 0;
-
- dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id); /* header */
-
- /* So we have the eeprom: parse the FRU part (if any) */
- h = (void *)fmc->eeprom;
- if (h->format != 1) {
- pr_info(" EEPROM has no FRU information\n");
- goto out;
- }
- if (!fru_header_cksum_ok(h)) {
- pr_info(" FRU: wrong header checksum\n");
- goto out;
- }
- bia = fru_get_board_area(h);
- if (!fru_bia_cksum_ok(bia)) {
- pr_info(" FRU: wrong board area checksum\n");
- goto out;
- }
- fmc->id.manufacturer = fru_get_board_manufacturer(h);
- fmc->id.product_name = fru_get_product_name(h);
- pr_info(" Manufacturer: %s\n", fmc->id.manufacturer);
- pr_info(" Product name: %s\n", fmc->id.product_name);
-
- /* Create the short name (FIXME: look in sdb as well) */
- fmc->mezzanine_name = kstrdup(fmc->id.product_name, GFP_KERNEL);
-
-out:
- if (allocated) {
- kfree(fmc->eeprom);
- fmc->eeprom = NULL;
- }
- return 0; /* no error: let other identification work */
-}
-
-/* Some ID data is allocated using fru_alloc() above, so release it */
-void fmc_free_id_info(struct fmc_device *fmc)
-{
- kfree(fmc->mezzanine_name);
- kfree(fmc->id.manufacturer);
- kfree(fmc->id.product_name);
-}
diff --git a/drivers/fmc/fmc-private.h b/drivers/fmc/fmc-private.h
deleted file mode 100644
index 93cb8030f764..000000000000
--- a/drivers/fmc/fmc-private.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 CERN (www.cern.ch)
- * Author: Federico Vaga <federico.vaga@cern.ch>
- */
-
-extern int fmc_debug_init(struct fmc_device *fmc);
-extern void fmc_debug_exit(struct fmc_device *fmc);
diff --git a/drivers/fmc/fmc-sdb.c b/drivers/fmc/fmc-sdb.c
deleted file mode 100644
index 14758db1a5fb..000000000000
--- a/drivers/fmc/fmc-sdb.c
+++ /dev/null
@@ -1,219 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * 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/sdb.h>
-#include <linux/err.h>
-#include <linux/fmc-sdb.h>
-#include <asm/byteorder.h>
-
-static uint32_t __sdb_rd(struct fmc_device *fmc, unsigned long address,
- int convert)
-{
- uint32_t res = fmc_readl(fmc, address);
- if (convert)
- return __be32_to_cpu(res);
- return res;
-}
-
-static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc,
- unsigned long sdb_addr,
- unsigned long reg_base, int level)
-{
- uint32_t onew;
- int i, j, n, convert = 0;
- struct sdb_array *arr, *sub;
-
- onew = fmc_readl(fmc, sdb_addr);
- if (onew == SDB_MAGIC) {
- /* Uh! If we are little-endian, we must convert */
- if (SDB_MAGIC != __be32_to_cpu(SDB_MAGIC))
- convert = 1;
- } else if (onew == __be32_to_cpu(SDB_MAGIC)) {
- /* ok, don't convert */
- } else {
- return ERR_PTR(-ENOENT);
- }
- /* So, the magic was there: get the count from offset 4*/
- onew = __sdb_rd(fmc, sdb_addr + 4, convert);
- n = __be16_to_cpu(*(uint16_t *)&onew);
- arr = kzalloc(sizeof(*arr), GFP_KERNEL);
- if (!arr)
- return ERR_PTR(-ENOMEM);
- arr->record = kcalloc(n, sizeof(arr->record[0]), GFP_KERNEL);
- arr->subtree = kcalloc(n, sizeof(arr->subtree[0]), GFP_KERNEL);
- if (!arr->record || !arr->subtree) {
- kfree(arr->record);
- kfree(arr->subtree);
- kfree(arr);
- return ERR_PTR(-ENOMEM);
- }
-
- arr->len = n;
- arr->level = level;
- arr->fmc = fmc;
- for (i = 0; i < n; i++) {
- union sdb_record *r;
-
- for (j = 0; j < sizeof(arr->record[0]); j += 4) {
- *(uint32_t *)((void *)(arr->record + i) + j) =
- __sdb_rd(fmc, sdb_addr + (i * 64) + j, convert);
- }
- r = &arr->record[i];
- arr->subtree[i] = ERR_PTR(-ENODEV);
- if (r->empty.record_type == sdb_type_bridge) {
- struct sdb_component *c = &r->bridge.sdb_component;
- uint64_t subaddr = __be64_to_cpu(r->bridge.sdb_child);
- uint64_t newbase = __be64_to_cpu(c->addr_first);
-
- subaddr += reg_base;
- newbase += reg_base;
- sub = __fmc_scan_sdb_tree(fmc, subaddr, newbase,
- level + 1);
- arr->subtree[i] = sub; /* may be error */
- if (IS_ERR(sub))
- continue;
- sub->parent = arr;
- sub->baseaddr = newbase;
- }
- }
- return arr;
-}
-
-int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address)
-{
- struct sdb_array *ret;
- if (fmc->sdb)
- return -EBUSY;
- ret = __fmc_scan_sdb_tree(fmc, address, 0 /* regs */, 0);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- fmc->sdb = ret;
- return 0;
-}
-EXPORT_SYMBOL(fmc_scan_sdb_tree);
-
-static void __fmc_sdb_free(struct sdb_array *arr)
-{
- int i, n;
-
- if (!arr)
- return;
- n = arr->len;
- for (i = 0; i < n; i++) {
- if (IS_ERR(arr->subtree[i]))
- continue;
- __fmc_sdb_free(arr->subtree[i]);
- }
- kfree(arr->record);
- kfree(arr->subtree);
- kfree(arr);
-}
-
-int fmc_free_sdb_tree(struct fmc_device *fmc)
-{
- __fmc_sdb_free(fmc->sdb);
- fmc->sdb = NULL;
- return 0;
-}
-EXPORT_SYMBOL(fmc_free_sdb_tree);
-
-/* This helper calls reprogram and inizialized sdb as well */
-int fmc_reprogram_raw(struct fmc_device *fmc, struct fmc_driver *d,
- void *gw, unsigned long len, int sdb_entry)
-{
- int ret;
-
- ret = fmc->op->reprogram_raw(fmc, d, gw, len);
- if (ret < 0)
- return ret;
- if (sdb_entry < 0)
- return ret;
-
- /* We are required to find SDB at a given offset */
- ret = fmc_scan_sdb_tree(fmc, sdb_entry);
- if (ret < 0) {
- dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n",
- sdb_entry);
- return -ENODEV;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(fmc_reprogram_raw);
-
-/* This helper calls reprogram and inizialized sdb as well */
-int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
- int sdb_entry)
-{
- int ret;
-
- ret = fmc->op->reprogram(fmc, d, gw);
- if (ret < 0)
- return ret;
- if (sdb_entry < 0)
- return ret;
-
- /* We are required to find SDB at a given offset */
- ret = fmc_scan_sdb_tree(fmc, sdb_entry);
- if (ret < 0) {
- dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n",
- sdb_entry);
- return -ENODEV;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(fmc_reprogram);
-
-void fmc_show_sdb_tree(const struct fmc_device *fmc)
-{
- pr_err("%s: not supported anymore, use debugfs to dump SDB\n",
- __func__);
-}
-EXPORT_SYMBOL(fmc_show_sdb_tree);
-
-signed long fmc_find_sdb_device(struct sdb_array *tree,
- uint64_t vid, uint32_t did, unsigned long *sz)
-{
- signed long res = -ENODEV;
- union sdb_record *r;
- struct sdb_product *p;
- struct sdb_component *c;
- int i, n = tree->len;
- uint64_t last, first;
-
- /* FIXME: what if the first interconnect is not at zero? */
- for (i = 0; i < n; i++) {
- r = &tree->record[i];
- c = &r->dev.sdb_component;
- p = &c->product;
-
- if (!IS_ERR(tree->subtree[i]))
- res = fmc_find_sdb_device(tree->subtree[i],
- vid, did, sz);
- if (res >= 0)
- return res + tree->baseaddr;
- if (r->empty.record_type != sdb_type_device)
- continue;
- if (__be64_to_cpu(p->vendor_id) != vid)
- continue;
- if (__be32_to_cpu(p->device_id) != did)
- continue;
- /* found */
- last = __be64_to_cpu(c->addr_last);
- first = __be64_to_cpu(c->addr_first);
- if (sz)
- *sz = (typeof(*sz))(last + 1 - first);
- return first + tree->baseaddr;
- }
- return res;
-}
-EXPORT_SYMBOL(fmc_find_sdb_device);
diff --git a/drivers/fmc/fmc-trivial.c b/drivers/fmc/fmc-trivial.c
deleted file mode 100644
index b99dbc7ee203..000000000000
--- a/drivers/fmc/fmc-trivial.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * The software is provided "as is"; the copyright holders disclaim
- * all warranties and liabilities, to the extent permitted by
- * applicable law.
- */
-
-/* A trivial fmc driver that can load a gateware file and reports interrupts */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fmc.h>
-
-static struct fmc_driver t_drv; /* initialized later */
-
-static irqreturn_t t_handler(int irq, void *dev_id)
-{
- struct fmc_device *fmc = dev_id;
-
- fmc_irq_ack(fmc);
- dev_info(&fmc->dev, "received irq %i\n", irq);
- return IRQ_HANDLED;
-}
-
-static struct fmc_gpio t_gpio[] = {
- {
- .gpio = FMC_GPIO_IRQ(0),
- .mode = GPIOF_DIR_IN,
- .irqmode = IRQF_TRIGGER_RISING,
- }, {
- .gpio = FMC_GPIO_IRQ(1),
- .mode = GPIOF_DIR_IN,
- .irqmode = IRQF_TRIGGER_RISING,
- }
-};
-
-static int t_probe(struct fmc_device *fmc)
-{
- int ret;
- int index = 0;
-
- index = fmc_validate(fmc, &t_drv);
- if (index < 0)
- return -EINVAL; /* not our device: invalid */
-
- ret = fmc_irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED);
- if (ret < 0)
- return ret;
- /* ignore error code of call below, we really don't care */
- fmc_gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio));
-
- ret = fmc_reprogram(fmc, &t_drv, "", 0);
- if (ret == -EPERM) /* programming not supported */
- ret = 0;
- if (ret < 0)
- fmc_irq_free(fmc);
-
- /* FIXME: reprogram LM32 too */
- return ret;
-}
-
-static int t_remove(struct fmc_device *fmc)
-{
- fmc_irq_free(fmc);
- return 0;
-}
-
-static struct fmc_driver t_drv = {
- .version = FMC_VERSION,
- .driver.name = KBUILD_MODNAME,
- .probe = t_probe,
- .remove = t_remove,
- /* no table, as the current match just matches everything */
-};
-
- /* We accept the generic parameters */
-FMC_PARAM_BUSID(t_drv);
-FMC_PARAM_GATEWARE(t_drv);
-
-static int t_init(void)
-{
- int ret;
-
- ret = fmc_driver_register(&t_drv);
- return ret;
-}
-
-static void t_exit(void)
-{
- fmc_driver_unregister(&t_drv);
-}
-
-module_init(t_init);
-module_exit(t_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/fmc/fmc-write-eeprom.c b/drivers/fmc/fmc-write-eeprom.c
deleted file mode 100644
index 1c7826e3f526..000000000000
--- a/drivers/fmc/fmc-write-eeprom.c
+++ /dev/null
@@ -1,175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * 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/string.h>
-#include <linux/firmware.h>
-#include <linux/init.h>
-#include <linux/fmc.h>
-#include <asm/unaligned.h>
-
-/*
- * This module uses the firmware loader to program the whole or part
- * of the FMC eeprom. The meat is in the _run functions. However, no
- * default file name is provided, to avoid accidental mishaps. Also,
- * you must pass the busid argument
- */
-static struct fmc_driver fwe_drv;
-
-FMC_PARAM_BUSID(fwe_drv);
-
-/* The "file=" is like the generic "gateware=" used elsewhere */
-static char *fwe_file[FMC_MAX_CARDS];
-static int fwe_file_n;
-module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444);
-
-static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
- int write)
-{
- const uint8_t *p = fw->data;
- int len = fw->size;
- uint16_t thislen, thisaddr;
- int err;
-
- /* format is: 'w' addr16 len16 data... */
- while (len > 5) {
- thisaddr = get_unaligned_le16(p+1);
- thislen = get_unaligned_le16(p+3);
- if (p[0] != 'w' || thislen + 5 > len) {
- dev_err(&fmc->dev, "invalid tlv at offset %ti\n",
- p - fw->data);
- return -EINVAL;
- }
- err = 0;
- if (write) {
- dev_info(&fmc->dev, "write %i bytes at 0x%04x\n",
- thislen, thisaddr);
- err = fmc_write_ee(fmc, thisaddr, p + 5, thislen);
- }
- if (err < 0) {
- dev_err(&fmc->dev, "write failure @0x%04x\n",
- thisaddr);
- return err;
- }
- p += 5 + thislen;
- len -= 5 + thislen;
- }
- if (write)
- dev_info(&fmc->dev, "write_eeprom: success\n");
- return 0;
-}
-
-static int fwe_run_bin(struct fmc_device *fmc, const struct firmware *fw)
-{
- int ret;
-
- dev_info(&fmc->dev, "programming %zi bytes\n", fw->size);
- ret = fmc_write_ee(fmc, 0, (void *)fw->data, fw->size);
- if (ret < 0) {
- dev_info(&fmc->dev, "write_eeprom: error %i\n", ret);
- return ret;
- }
- dev_info(&fmc->dev, "write_eeprom: success\n");
- return 0;
-}
-
-static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s)
-{
- char *last4 = s + strlen(s) - 4;
- int err;
-
- if (!strcmp(last4, ".bin"))
- return fwe_run_bin(fmc, fw);
- if (!strcmp(last4, ".tlv")) {
- err = fwe_run_tlv(fmc, fw, 0);
- if (!err)
- err = fwe_run_tlv(fmc, fw, 1);
- return err;
- }
- dev_err(&fmc->dev, "invalid file name \"%s\"\n", s);
- return -EINVAL;
-}
-
-/*
- * Programming is done at probe time. Morever, only those listed with
- * busid= are programmed.
- * card is probed for, only one is programmed. Unfortunately, it's
- * difficult to know in advance when probing the first card if others
- * are there.
- */
-static int fwe_probe(struct fmc_device *fmc)
-{
- int err, index = 0;
- const struct firmware *fw;
- struct device *dev = &fmc->dev;
- char *s;
-
- if (!fwe_drv.busid_n) {
- dev_err(dev, "%s: no busid passed, refusing all cards\n",
- KBUILD_MODNAME);
- return -ENODEV;
- }
-
- index = fmc_validate(fmc, &fwe_drv);
- if (index < 0) {
- pr_err("%s: refusing device \"%s\"\n", KBUILD_MODNAME,
- dev_name(dev));
- return -ENODEV;
- }
- if (index >= fwe_file_n) {
- pr_err("%s: no filename for device index %i\n",
- KBUILD_MODNAME, index);
- return -ENODEV;
- }
- s = fwe_file[index];
- if (!s) {
- pr_err("%s: no filename for \"%s\" not programming\n",
- KBUILD_MODNAME, dev_name(dev));
- return -ENOENT;
- }
- err = request_firmware(&fw, s, dev);
- if (err < 0) {
- dev_err(&fmc->dev, "request firmware \"%s\": error %i\n",
- s, err);
- return err;
- }
- fwe_run(fmc, fw, s);
- release_firmware(fw);
- return 0;
-}
-
-static int fwe_remove(struct fmc_device *fmc)
-{
- return 0;
-}
-
-static struct fmc_driver fwe_drv = {
- .version = FMC_VERSION,
- .driver.name = KBUILD_MODNAME,
- .probe = fwe_probe,
- .remove = fwe_remove,
- /* no table, as the current match just matches everything */
-};
-
-static int fwe_init(void)
-{
- int ret;
-
- ret = fmc_driver_register(&fwe_drv);
- return ret;
-}
-
-static void fwe_exit(void)
-{
- fmc_driver_unregister(&fwe_drv);
-}
-
-module_init(fwe_init);
-module_exit(fwe_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/fmc/fru-parse.c b/drivers/fmc/fru-parse.c
deleted file mode 100644
index f551b81f4fd9..000000000000
--- a/drivers/fmc/fru-parse.c
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * This work is part of the White Rabbit project, a research effort led
- * by CERN, the European Institute for Nuclear Research.
- */
-#include <linux/ipmi-fru.h>
-
-/* Some internal helpers */
-static struct fru_type_length *
-__fru_get_board_tl(struct fru_common_header *header, int nr)
-{
- struct fru_board_info_area *bia;
- struct fru_type_length *tl;
-
- bia = fru_get_board_area(header);
- tl = bia->tl;
- while (nr > 0 && !fru_is_eof(tl)) {
- tl = fru_next_tl(tl);
- nr--;
- }
- if (fru_is_eof(tl))
- return NULL;
- return tl;
-}
-
-static char *__fru_alloc_get_tl(struct fru_common_header *header, int nr)
-{
- struct fru_type_length *tl;
- char *res;
-
- tl = __fru_get_board_tl(header, nr);
- if (!tl)
- return NULL;
-
- res = fru_alloc(fru_strlen(tl) + 1);
- if (!res)
- return NULL;
- return fru_strcpy(res, tl);
-}
-
-/* Public checksum verifiers */
-int fru_header_cksum_ok(struct fru_common_header *header)
-{
- uint8_t *ptr = (void *)header;
- int i, sum;
-
- for (i = sum = 0; i < sizeof(*header); i++)
- sum += ptr[i];
- return (sum & 0xff) == 0;
-}
-int fru_bia_cksum_ok(struct fru_board_info_area *bia)
-{
- uint8_t *ptr = (void *)bia;
- int i, sum;
-
- for (i = sum = 0; i < 8 * bia->area_len; i++)
- sum += ptr[i];
- return (sum & 0xff) == 0;
-}
-
-/* Get various stuff, trivial */
-char *fru_get_board_manufacturer(struct fru_common_header *header)
-{
- return __fru_alloc_get_tl(header, 0);
-}
-char *fru_get_product_name(struct fru_common_header *header)
-{
- return __fru_alloc_get_tl(header, 1);
-}
-char *fru_get_serial_number(struct fru_common_header *header)
-{
- return __fru_alloc_get_tl(header, 2);
-}
-char *fru_get_part_number(struct fru_common_header *header)
-{
- return __fru_alloc_get_tl(header, 3);
-}
diff --git a/include/linux/fmc-sdb.h b/include/linux/fmc-sdb.h
deleted file mode 100644
index bec899f0867c..000000000000
--- a/include/linux/fmc-sdb.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This file is separate from sdb.h, because I want that one to remain
- * unchanged (as far as possible) from the official sdb distribution
- *
- * This file and associated functionality are a playground for me to
- * understand stuff which will later be implemented in more generic places.
- */
-#include <linux/sdb.h>
-
-/* This is the union of all currently defined types */
-union sdb_record {
- struct sdb_interconnect ic;
- struct sdb_device dev;
- struct sdb_bridge bridge;
- struct sdb_integration integr;
- struct sdb_empty empty;
- struct sdb_synthesis synthesis;
- struct sdb_repo_url repo_url;
-};
-
-struct fmc_device;
-
-/* Every sdb table is turned into this structure */
-struct sdb_array {
- int len;
- int level;
- unsigned long baseaddr;
- struct fmc_device *fmc; /* the device that hosts it */
- struct sdb_array *parent; /* NULL at root */
- union sdb_record *record; /* copies of the struct */
- struct sdb_array **subtree; /* only valid for bridge items */
-};
-
-extern int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address);
-extern void fmc_show_sdb_tree(const struct fmc_device *fmc);
-extern signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor,
- uint32_t device, unsigned long *sz);
-extern int fmc_free_sdb_tree(struct fmc_device *fmc);
diff --git a/include/linux/fmc.h b/include/linux/fmc.h
deleted file mode 100644
index 8661a46a676f..000000000000
--- a/include/linux/fmc.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2012 CERN (www.cern.ch)
- * Author: Alessandro Rubini <rubini@gnudd.com>
- *
- * This work is part of the White Rabbit project, a research effort led
- * by CERN, the European Institute for Nuclear Research.
- */
-#ifndef __LINUX_FMC_H__
-#define __LINUX_FMC_H__
-#include <linux/types.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-struct fmc_device;
-struct fmc_driver;
-
-/*
- * This bus abstraction is developed separately from drivers, so we need
- * to check the version of the data structures we receive.
- */
-
-#define FMC_MAJOR 3
-#define FMC_MINOR 0
-#define FMC_VERSION ((FMC_MAJOR << 16) | FMC_MINOR)
-#define __FMC_MAJOR(x) ((x) >> 16)
-#define __FMC_MINOR(x) ((x) & 0xffff)
-
-/*
- * The device identification, as defined by the IPMI FRU (Field Replaceable
- * Unit) includes four different strings to describe the device. Here we
- * only match the "Board Manufacturer" and the "Board Product Name",
- * ignoring the "Board Serial Number" and "Board Part Number". All 4 are
- * expected to be strings, so they are treated as zero-terminated C strings.
- * Unspecified string (NULL) means "any", so if both are unspecified this
- * is a catch-all driver. So null entries are allowed and we use array
- * and length. This is unlike pci and usb that use null-terminated arrays
- */
-struct fmc_fru_id {
- char *manufacturer;
- char *product_name;
-};
-
-/*
- * If the FPGA is already programmed (think Etherbone or the second
- * SVEC slot), we can match on SDB devices in the memory image. This
- * match uses an array of devices that must all be present, and the
- * match is based on vendor and device only. Further checks are expected
- * to happen in the probe function. Zero means "any" and catch-all is allowed.
- */
-struct fmc_sdb_one_id {
- uint64_t vendor;
- uint32_t device;
-};
-struct fmc_sdb_id {
- struct fmc_sdb_one_id *cores;
- int cores_nr;
-};
-
-struct fmc_device_id {
- struct fmc_fru_id *fru_id;
- int fru_id_nr;
- struct fmc_sdb_id *sdb_id;
- int sdb_id_nr;
-};
-
-/* This sizes the module_param_array used by generic module parameters */
-#define FMC_MAX_CARDS 32
-
-/* The driver is a pretty simple thing */
-struct fmc_driver {
- unsigned long version;
- struct device_driver driver;
- int (*probe)(struct fmc_device *);
- int (*remove)(struct fmc_device *);
- const struct fmc_device_id id_table;
- /* What follows is for generic module parameters */
- int busid_n;
- int busid_val[FMC_MAX_CARDS];
- int gw_n;
- char *gw_val[FMC_MAX_CARDS];
-};
-#define to_fmc_driver(x) container_of((x), struct fmc_driver, driver)
-
-/* These are the generic parameters, that drivers may instantiate */
-#define FMC_PARAM_BUSID(_d) \
- module_param_array_named(busid, _d.busid_val, int, &_d.busid_n, 0444)
-#define FMC_PARAM_GATEWARE(_d) \
- module_param_array_named(gateware, _d.gw_val, charp, &_d.gw_n, 0444)
-
-/*
- * Drivers may need to configure gpio pins in the carrier. To read input
- * (a very uncommon operation, and definitely not in the hot paths), just
- * configure one gpio only and get 0 or 1 as retval of the config method
- */
-struct fmc_gpio {
- char *carrier_name; /* name or NULL for virtual pins */
- int gpio;
- int _gpio; /* internal use by the carrier */
- int mode; /* GPIOF_DIR_OUT etc */
- int irqmode; /* IRQF_TRIGGER_LOW and so on */
-};
-
-/* The numbering of gpio pins allows access to raw pins or virtual roles */
-#define FMC_GPIO_RAW(x) (x) /* 4096 of them */
-#define __FMC_GPIO_IS_RAW(x) ((x) < 0x1000)
-#define FMC_GPIO_IRQ(x) ((x) + 0x1000) /* 256 of them */
-#define FMC_GPIO_LED(x) ((x) + 0x1100) /* 256 of them */
-#define FMC_GPIO_KEY(x) ((x) + 0x1200) /* 256 of them */
-#define FMC_GPIO_TP(x) ((x) + 0x1300) /* 256 of them */
-#define FMC_GPIO_USER(x) ((x) + 0x1400) /* 256 of them */
-/* We may add SCL and SDA, or other roles if the need arises */
-
-/*
- * These are similar to the legacy Linux GPIO defines from <linux/gpio.h>
- * but in fact FMC has its own GPIO handling and is not using the Linux
- * GPIO subsystem.
- */
-#define GPIOF_DIR_OUT (0 << 0)
-#define GPIOF_DIR_IN (1 << 0)
-#define GPIOF_INIT_LOW (0 << 1)
-#define GPIOF_INIT_HIGH (1 << 1)
-
-/*
- * The operations are offered by each carrier and should make driver
- * design completely independent of the carrier. Named GPIO pins may be
- * the exception.
- */
-struct fmc_operations {
- uint32_t (*read32)(struct fmc_device *fmc, int offset);
- void (*write32)(struct fmc_device *fmc, uint32_t value, int offset);
- int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv);
- int (*reprogram_raw)(struct fmc_device *f, struct fmc_driver *d,
- void *gw, unsigned long len);
- int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw);
- int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
- char *name, int flags);
- void (*irq_ack)(struct fmc_device *fmc);
- int (*irq_free)(struct fmc_device *fmc);
- int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio,
- int ngpio);
- int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l);
- int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l);
-};
-
-/* Prefer this helper rather than calling of fmc->reprogram directly */
-int fmc_reprogram_raw(struct fmc_device *fmc, struct fmc_driver *d,
- void *gw, unsigned long len, int sdb_entry);
-extern int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw,
- int sdb_entry);
-
-/*
- * The device reports all information needed to access hw.
- *
- * If we have eeprom_len and not contents, the core reads it.
- * Then, parsing of identifiers is done by the core which fills fmc_fru_id..
- * Similarly a device that must be matched based on SDB cores must
- * fill the entry point and the core will scan the bus (FIXME: sdb match)
- */
-struct fmc_device {
- unsigned long version;
- unsigned long flags;
- struct module *owner; /* char device must pin it */
- struct fmc_fru_id id; /* for EEPROM-based match */
- struct fmc_operations *op; /* carrier-provided */
- int irq; /* according to host bus. 0 == none */
- int eeprom_len; /* Usually 8kB, may be less */
- int eeprom_addr; /* 0x50, 0x52 etc */
- uint8_t *eeprom; /* Full contents or leading part */
- char *carrier_name; /* "SPEC" or similar, for special use */
- void *carrier_data; /* "struct spec *" or equivalent */
- __iomem void *fpga_base; /* May be NULL (Etherbone) */
- __iomem void *slot_base; /* Set by the driver */
- struct fmc_device **devarray; /* Allocated by the bus */
- int slot_id; /* Index in the slot array */
- int nr_slots; /* Number of slots in this carrier */
- unsigned long memlen; /* Used for the char device */
- struct device dev; /* For Linux use */
- struct device *hwdev; /* The underlying hardware device */
- unsigned long sdbfs_entry;
- struct sdb_array *sdb;
- uint32_t device_id; /* Filled by the device */
- char *mezzanine_name; /* Defaults to ``fmc'' */
- void *mezzanine_data;
-
- struct dentry *dbg_dir;
- struct dentry *dbg_sdb_dump;
-};
-#define to_fmc_device(x) container_of((x), struct fmc_device, dev)
-
-#define FMC_DEVICE_HAS_GOLDEN 1
-#define FMC_DEVICE_HAS_CUSTOM 2
-#define FMC_DEVICE_NO_MEZZANINE 4
-#define FMC_DEVICE_MATCH_SDB 8 /* fmc-core must scan sdb in fpga */
-
-/*
- * If fpga_base can be used, the carrier offers no readl/writel methods, and
- * this expands to a single, fast, I/O access.
- */
-static inline uint32_t fmc_readl(struct fmc_device *fmc, int offset)
-{
- if (unlikely(fmc->op->read32))
- return fmc->op->read32(fmc, offset);
- return readl(fmc->fpga_base + offset);
-}
-static inline void fmc_writel(struct fmc_device *fmc, uint32_t val, int off)
-{
- if (unlikely(fmc->op->write32))
- fmc->op->write32(fmc, val, off);
- else
- writel(val, fmc->fpga_base + off);
-}
-
-/* pci-like naming */
-static inline void *fmc_get_drvdata(const struct fmc_device *fmc)
-{
- return dev_get_drvdata(&fmc->dev);
-}
-
-static inline void fmc_set_drvdata(struct fmc_device *fmc, void *data)
-{
- dev_set_drvdata(&fmc->dev, data);
-}
-
-struct fmc_gateware {
- void *bitstream;
- unsigned long len;
-};
-
-/* The 5 access points */
-extern int fmc_driver_register(struct fmc_driver *drv);
-extern void fmc_driver_unregister(struct fmc_driver *drv);
-extern int fmc_device_register(struct fmc_device *tdev);
-extern int fmc_device_register_gw(struct fmc_device *tdev,
- struct fmc_gateware *gw);
-extern void fmc_device_unregister(struct fmc_device *tdev);
-
-/* Three more for device sets, all driven by the same FPGA */
-extern int fmc_device_register_n(struct fmc_device **devs, int n);
-extern int fmc_device_register_n_gw(struct fmc_device **devs, int n,
- struct fmc_gateware *gw);
-extern void fmc_device_unregister_n(struct fmc_device **devs, int n);
-
-/* Internal cross-calls between files; not exported to other modules */
-extern int fmc_match(struct device *dev, struct device_driver *drv);
-extern int fmc_fill_id_info(struct fmc_device *fmc);
-extern void fmc_free_id_info(struct fmc_device *fmc);
-extern void fmc_dump_eeprom(const struct fmc_device *fmc);
-
-/* helpers for FMC operations */
-extern int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h,
- char *name, int flags);
-extern void fmc_irq_free(struct fmc_device *fmc);
-extern void fmc_irq_ack(struct fmc_device *fmc);
-extern int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv);
-extern int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio,
- int ngpio);
-extern int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l);
-extern int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l);
-
-/* helpers for FMC operations */
-extern int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h,
- char *name, int flags);
-extern void fmc_irq_free(struct fmc_device *fmc);
-extern void fmc_irq_ack(struct fmc_device *fmc);
-extern int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv);
-
-#endif /* __LINUX_FMC_H__ */