From ab7810aefff22384cbbe0381c8a1ea1994d691af Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Tue, 17 Jul 2012 11:16:00 +0200
Subject: [PATCH] doc: filled first draft of fmc-bus

---
 doc/fmc-bus.in | 155 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 3 deletions(-)

diff --git a/doc/fmc-bus.in b/doc/fmc-bus.in
index a37f81a..6bb24b2 100644
--- a/doc/fmc-bus.in
+++ b/doc/fmc-bus.in
@@ -72,27 +72,176 @@ Currently, code and documentation for the FMC bus is part of the
 @i{spec-sw} project at @code{ohwr.org}.
 
 @menu
-* The Core Driver::             
+* What is a Linux Bus::         
+* FMC Device::                  
+* FMC Driver::                  
+* The API Offered by Carriers::  
 @end menu
 
 @c ##########################################################################
 @node What is a Linux Bus
 @chapter What is a Linux Bus
 
+Within the Linux kernel, a @i{bus} is a data structure with a few
+methods.  It's main role is registering a list of devices and a list
+of drivers, offering a @i{match} function that compares the respective
+identifiers (in a bus-specific way) to assign drivers to devices.
+
+Activation and deactivation of devices happens through the @i{probe}
+and @i{remove} functions of the respective driver; an advanced user
+can also use @i{sysfs} to change the binding of drivers to devices
+(for example, if more than one driver can drive the same device you
+may want to force the choice).
+
 @c ##########################################################################
 @node FMC Device
 @chapter FMC Device
 
+Within this 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 drivers, and registers an
+associated FMC device.  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 will be 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 to only return
+the leading part of it).
+
+This is the current structure defining a device. Please note that stuff
+is still being defined as I write this, so the structures are going to
+change (if in doubt, please check the header file in the repository rather
+than this document):
+
+@smallexample
+struct fmc_device {
+        struct fmc_device_id id;        /* for the match function */
+        struct fmc_operations *op;      /* carrier-provided */
+        int irq;                        /* according to host bus. 0 == none */
+        int eeprom_len;                 /* Usually 8kB, may be less */
+        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 *base;             /* May be NULL (Etherbone) */
+        struct device dev;              /* For Linux use */
+};
+@end smallexample
+
 @c ##########################################################################
 @node FMC Driver
 @chapter FMC Driver
 
+Within this framework the FMC driver is expected to be independent of
+the carrier being used.  The matching between device and driver is
+only based on the content of the EEPROM (as mandated by the FMC
+standard) and the driver will perform I/O accesses only by means of
+carrier-provided functions.
+
+In some special cases it is possible for a driver to directly access
+FPGA registers, by means of the @code{base} field of the device
+structure. This is needed for high-bandwidth peripherals like fast ADC
+cards. The @code{base} pointer is NULL for remote devices, and the driver
+will refuse to work with them if it needs direct access.
+
+In even more special cases, the driver may access carrier-specific
+functionality: the @code{carrier_name} string allows the driver to
+check which is the current carrier and make use of the
+@code{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 @code{fmc.h} file -- we hope other users
+will exploit our framework with their own carriers.
+
+@c ##########################################################################
+@node Functions Exported by the Core
+@chapter Functions Exported by the Core
+
+The FMC core exports the usual 4 functions that are needed for a bus
+to work:
+
+@smallexample
+   int fmc_driver_register(struct fmc_driver *drv);
+   void fmc_driver_unregister(struct fmc_driver *drv);
+   int fmc_device_register(struct fmc_device *tdev);
+   void fmc_device_unregister(struct fmc_device *tdev);
+@end smallexample
+
+They should be self-explicative, so nothing is added here.
+
 @c ##########################################################################
 @node The API Offered by Carriers
 @chapter The API Offered by Carriers
 
+The carrier provides a number of methods by means of the
+@code{fmc_operations} structure, which currently is defined like this
+(again, it is a moving target, please refer to the header rather than
+this document):
+
+@smallexample
+struct fmc_operations {
+        uint32_t (*readl)(struct fmc_device *d, int offset);
+        void (*writel)(struct fmc_device *d, int offset, uint32_t value);
+        int (*reprogram)(struct fmc_device *d, void *data, int len);
+        void (*irq_ack)(struct fmc_device *d);
+        int (*read_ee)(struct fmc_device *d, int pos, void *data, int len);
+        int (*write_ee)(struct fmc_device *d, int pos, void *data, int len);
+};
+@end smallexample
+
+They perform the following tasks:
+
+@table @code
+@item readl
+@itemx writel
+
+	These functions access FPGA registers by whatever means the
+        carrier offers. They are not expected to fail, as most of the time
+        they will just make a memory access to the host bus. While
+        calling a function is slower than making direct access with macros,
+        flexibility requires this approach. Drivers may use the @code{base}
+        pointer at their own risk, or maybe later specifications will mandate
+        @code{base} to be equivalent to @i{readl}/@i{writel} if not NULL.
+        For Etherbone, or other non-local carriers,
+        error-management is still to be defined.
+
+@item reprogram
+
+	The carrier enumerates FMC devices by loading a standard (or
+        @i{golden} FPGA binary that allows EEPROM access. Each driver, then,
+        will need to reprogram the FPGA for its own use by calling this
+        function.  If @i{reprogram} is called with NULL argumentes, the
+        carrier will reprogram the golden binary -- which will happen
+        after @i{remove} time in any case.
+
+@item irq_ack
+
+	Interrupt acknowledge is carrier-specific, so it is abstracted
+        as an operation. Interrupts on the other hand are expected to be
+        reported by normal host means, at the IRQ number stated in the
+        device structure.
+
+@item read_ee
+@itemx write_ee
+
+	Read or write the EEPROM. The functions are expected to be only
+        called before reprogramming and the carrier will refuse them
+        with @code{ENODEV} after reprogramming.  The offset is limited
+        to 8kB 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 own I2C memory
+        is seen at offset 1M and the internal SPI flash is seen at offset
+        16M.  This is carrier-specific and should only be used by the
+        driver after checking the @code{carrier_name} field.
+
+@end table
+
+
 
 @bye
 @c  LocalWords:  gnudd titlepage iftex texinfo CERN documentlanguage settitle
-@c  LocalWords:  documentencoding setfilename afourpaper paragraphindent
-@c  LocalWords:  setchapternewpage finalout
+@c  LocalWords:  documentencoding setfilename afourpaper paragraphindent SVEC
+@c  LocalWords:  setchapternewpage finalout Etherbone EEPROM
-- 
GitLab