Parallel Peripheral Interface (PPI) The Parallel Peripheral Interface (PPI (Parallel Peripheral Interface)) is a half-duplex, bidirectional port accommodating up to 16 bits of data. It has a dedicated clock pin and three multiplexed frame sync pins. It is sometimes referred to as a “video port” as it most commonly used to drive video devices (like LCDs or CMOS sensors or video encoders/decoders). Really though, this can be used to drive any sort of high speed parallel device. Blackfin Interface The figure below provides a block diagram of the Blackfin PPI (Parallel Peripheral Interface). Linux Framework No framework or API (Application Programming Interface) exists to help with controlling the PPI (Parallel Peripheral Interface), so you will be spending a lot of time reading/writing directly to the PPI (Parallel Peripheral Interface)'s MMR (Memory Mapped Register) registers. Like any other driver, you will also need to use the portmux framework and request/free any peripheral pins you wish to utilize. Time to grab a copy of the HRM ((Blackfin) Hardware Reference Manual) for your particular Blackfin variant! MMR Accessor Functions All MMR (Memory Mapped Register) reads and writes are done through so called “acessor helper functions”. These functions all have the form bfin_read_MMR (Memory Mapped Register)() and bfin_write_MMR (Memory Mapped Register)(value) where MMR (Memory Mapped Register) is replaced with the actual register name. For example, if you wish to read the PPI (Parallel Peripheral Interface) status register PPI (Parallel Peripheral Interface)_STATUS, then you should use the function bfin_read_PPI (Parallel Peripheral Interface)_STATUS(). Function Reference Here are all the accessor functions laid out. Note that we include a helper bfin_clear_PPI (Parallel Peripheral Interface)_STATUS() function as different variants of the Blackfin processor require different handling of the PPI (Parallel Peripheral Interface)_STATUS register in order to clear it properly. u16 bfin_read_PPI_CONTROL (void) void bfin_write_PPI_CONTROL (u16 val) u16 bfin_read_PPI_STATUS (void) void bfin_write_PPI_STATUS (u16 val) void bfin_clear_PPI_STATUS (void) u16 bfin_read_PPI_DELAY (void) void bfin_write_PPI_DELAY (u16 val) u16 bfin_read_PPI_COUNT (void) void bfin_write_PPI_COUNT (u16 val) u16 bfin_read_PPI_FRAME (void) void bfin_write_PPI_FRAME (u16 val) Troubleshooting PPI Underrun/Overflow Errors There are two potential causes: PPI ERROR interrupt overtakes PPI-DMA-DONE interrupt due to higher priority: Your driver in question performs a PPI (Parallel Peripheral Interface) out write operation. And uses PPI (Parallel Peripheral Interface) DMA (Direct Memory Access)-DONE interrupts to signal completion of a work load. And the PPI (Parallel Peripheral Interface) line sync PPI (Parallel Peripheral Interface)_FS1 re-asserts before the PPI (Parallel Peripheral Interface) is disabled, while there is a continuous PPI (Parallel Peripheral Interface)_CLK. Workarounds: Move IRQ (Interrupt request)_PPI (Parallel Peripheral Interface)_ERROR priority below IRQ (Interrupt request)_PPI (Parallel Peripheral Interface) (IRQ (Interrupt request)_DMAx) Don't request IRQ (Interrupt request)_PPI (Parallel Peripheral Interface)_ERROR The PPI FIFO is 16 bits wide and has 16 entries. In case the DMA can’t access L3 Memory fast enough, this fifo might overflow (OVR) or underrun (UNDR) Workarounds: Make sure you set the CDPRIO bit in the ASYNC Memory Configuration. (EBIU (External Bus Interface Unit)_AMGCTL: This allows the DMA (Direct Memory Access) to have higher priority than the Core for external memory accesses.) Increase SCLK (System Clock) System Clock. If external memory mapped peripherals like Ethernet Controllers are accesses while high speed PPI (Parallel Peripheral Interface) DMA (Direct Memory Access) is active into L3 Memory, External Async. Memmory access timings low. (EBIU (External Bus Interface Unit)_AMBCTL) If possible use internal L1 data memory for DMA (Direct Memory Access) buffers. If buffers dont fit in L1, you can try keep the data buffers in separate SDRAM (synchronous dynamic random access memory (system memory)) data banks to reduce bank open/close latency. Linux does not inheritly support allocation in specific banks or on specific address ranges. It can be solved by direct addressing a specific bank, check the memory allocator page. Fine-tune SDRAM (synchronous dynamic random access memory (system memory)) initialization parameters. (Use faster SDRAM (synchronous dynamic random access memory (system memory))). Always utilize the maximum DMA (Direct Memory Access) bus width, for 8-bit PPI (Parallel Peripheral Interface) transfers use the packing option. Reduce PPI (Parallel Peripheral Interface) CLK. Further reading Code examples frame_capture_device v4l_blackfin_camera framebuffer