diff options
Diffstat (limited to '')
-rw-r--r-- | Documentation/fmc/carrier.txt | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/Documentation/fmc/carrier.txt b/Documentation/fmc/carrier.txt new file mode 100644 index 000000000..5e4f1dd3e --- /dev/null +++ b/Documentation/fmc/carrier.txt @@ -0,0 +1,311 @@ +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. |