/** ** FILE NAME : ifx_dma_core.h ** PROJECT : IFX UEIP ** MODULES : Central DMA ** DATE : 03 June 2009 ** AUTHOR : Reddy Mallikarjuna ** DESCRIPTION : IFX Cross-Platform Central DMA driver header file ** COPYRIGHT : Copyright (c) 2009 ** Infineon Technologies AG ** Am Campeon 1-12, 85579 Neubiberg, Germany ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** HISTORY ** $Date $Author $Comment ** 03 June 2009 Reddy Mallikarjuna Initial release *******************************************************************************/ #ifndef _IFX_DMA_CORE_H_ #define _IFX_DMA_CORE_H_ /*! \defgroup IFX_DMA_CORE UEIP Project - Central DMA core driver \brief UEIP Project - Central DMA core Module, supports IFX CPE platforms(Danube/ASE/ARx/VRx). */ /*! \defgroup IFX_DMA_DRV_API External APIs \ingroup IFX_DMA_CORE \brief External APIs definitions for other modules. */ /*! \defgroup IFX_DMA_DRV_STRUCTURE Driver Structures \ingroup IFX_DMA_CORE \brief Definitions/Structures of IFX dma core module. */ /*! \file ifx_dma_core.h \ingroup IFX_DMA_CORE \brief Header file for IFX Central DMA core driver */ /** =============================*/ /* Includes */ /** =============================*/ #include /* ============================= */ /* Local Macros & Definitions */ /* ============================= */ /** Platform specific supported DMA channel & Devices */ #if defined(CONFIG_DANUBE) #define ENABLE_RX_DPLUS_PATH 0 /** Max num of ports */ #if !defined(ENABLE_RX_DPLUS_PATH) || !ENABLE_RX_DPLUS_PATH #define MAX_DMA_DEVICE_NUM 6 #else #define MAX_DMA_DEVICE_NUM 7 #endif /** Max num of dma channels */ #define MAX_DMA_CHANNEL_NUM 20 #elif defined(CONFIG_AMAZON_SE) /** Max num of ports */ #define MAX_DMA_DEVICE_NUM 3 /** Max num of dma channels */ #define MAX_DMA_CHANNEL_NUM 10 #elif defined(CONFIG_AR9) /** Max num of ports */ #define MAX_DMA_DEVICE_NUM 6 /** Max num of dma channels */ #define MAX_DMA_CHANNEL_NUM 20 /*--- #define CONFIG_NAPI_ENABLED ---*/ /*--- XXX for testing ---*/ #elif defined(CONFIG_VR9) /** Max num of ports */ #define MAX_DMA_DEVICE_NUM 7 /** Max num of dma channels */ #define MAX_DMA_CHANNEL_NUM 28 #elif defined(CONFIG_AR10) /** Max num of ports */ #define MAX_DMA_DEVICE_NUM 5 /** Max num of dma channels */ #define MAX_DMA_CHANNEL_NUM 24 #else #error "Platform is not specified(ifx_dma_core.h)!!!\n" #endif /** Not start of Packet */ #define IFX_DMA_NOT_SOP (1 << 31) /** Not end of Packet */ #define IFX_DMA_NOT_EOP (1 << 30) /** IFX_DMA_CHANNEL_LOCK was acquired by upper layer **/ #define IFX_DMA_LOCK_BY_UPPER_LAYER (1 << 29) /** Config the Num of descriptors from Kernel configurations * or else if will take default number of descriptors per channel */ //#ifdef CONFIG_IFX_EXTRA_CFG #define IFX_DMA_DESCRIPTOR_OFFSET CONFIG_IFX_DMA_DESCRIPTOR_NUMBER //#else //#define IFX_DMA_DESCRIPTOR_OFFSET 32 //#endif /*! \addtogroup IFX_DMA_DRV_STRUCTURE */ /*@{*/ /*! \enum dma_psuedeo_interrupts_t * \brief DMA pseudo interrupts. These interrupts are generated by dma core driver to sync with client drivers to handle the data between the clinet and core driver. */ typedef enum { RCV_INT = 1, /*!< Receive psuedo interrupt */ TX_BUF_FULL_INT = 2, /*!< Tx channel descriptors full interrupt */ TRANSMIT_CPT_INT = 4, /*!< Tx channel descriptors available interrupt */ }dma_psuedeo_interrupts_t; /*! \enum ifx_dma_channel_onOff_t \brief dma channel is on/ off. */ typedef enum { IFX_DMA_CH_OFF = 0, /*!< DMA channel is OFF */ IFX_DMA_CH_ON = 1, /*!< DMA channel is ON */ } ifx_dma_channel_onOff_t; /*! \enum ifx_dma_class_t \brief dma channel class value. */ typedef enum { IFX_DMA_CLASS_0 = 0, IFX_DMA_CLASS_1, IFX_DMA_CLASS_2, IFX_DMA_CLASS_3, IFX_DMA_CLASS_4, IFX_DMA_CLASS_5, IFX_DMA_CLASS_6, IFX_DMA_CLASS_7, } ifx_dma_class_t; /*! \enum ifx_dma_endian_t \brief DMA endiannes type. */ typedef enum { IFX_DMA_ENDIAN_TYPE0 = 0, /*!< No byte Swapping */ IFX_DMA_ENDIAN_TYPE1, /*!< Byte Swap(B0B1B2B3 => B1B0B3B2)*/ IFX_DMA_ENDIAN_TYPE2, /*!< Word Swap (B0B1B2B3 => B2B3B0B1)*/ IFX_DMA_ENDIAN_TYPE3, /*!< DWord Swap (B0B1B2B3 => B3B2B1B0) */ }ifx_dma_endian_t; enum { /** 2 DWORDS */ IFX_DMA_BURSTL_2 = 1, /** 4 DWORDS */ IFX_DMA_BURSTL_4 = 2, /** 8 DWORDS */ IFX_DMA_BURSTL_8 = 3, }; /*! \enum ifx_dma_burst_len_t \brief DMA Burst length. */ typedef enum { DMA_BURSTL_2DW = 2, /*!< 2 DWORD DMA burst length */ DMA_BURSTL_4DW = 4, /*!< 4 DWORD DMA burst length */ DMA_BURSTL_8DW = 8, /*!< 8 DWORD DMA burst length (not supported all peripherals) */ }ifx_dma_burst_len_t; /*! \typedef _dma_arbitration_info \brief Parameter Structure to used to configure DMA arbitration based on packet or burst also Descriptor read back enabled/disabled (Supported only VR9) Used by reference dma_device_info */ typedef struct dma_arbitration_info { IFX_enDis_t packet_arbitration; /*!< enabled/disabled packet arbitration*/ IFX_enDis_t multiple_burst_arbitration;/*!< Enabled/Disabled Multi burst arbitration */ unsigned int multiple_burst_counter; /*!< Counter of the Multi burst arbitration(Num of bursts that served before the arbitration of another peri port)*/ IFX_enDis_t desc_read_back; /*!< enabled/disabled Descriptor read back */ }_dma_arbitration_info; /*! \typedef _dma_channel_info \brief The parameter structure is used to configure the DMA channel info when the peripheral driver need to register with DMA core device driver. */ typedef struct dma_channel_info { int rel_chan_no; /*!< Relative channel number(if more than one DMA channel for device) */ int dir; /*!< Direction of channel */ int irq; /*!< DMA channel IRQ number */ unsigned int desc_base; /*!< Channel descriptor base address*/ int desc_len; /*!< Num of descriptors per channel */ volatile int curr_desc; /*!< Current Descriptor number*/ volatile int prev_desc; /*!< Previous Descriptor number */ int byte_offset; /*!< Byte offset */ int desc_handle; /*!< Descriptor handled flag ( to handle Rx Descriptor by client driver)*/ int weight; /*!< WFQ present weight value for DMA channel */ int default_weight; /*!< WFQ default weight value to handle in driver for DMA channel */ int tx_channel_weight; /*!< Config the Tx DMA channel weight value */ ifx_dma_class_t class_value; /*!< Config the DMA class value */ int packet_size; /*!< Size of the packet length */ int channel_packet_drop_enable; /*!< Config channel based packet drop(supported only VR9)*/ int channel_packet_drop_counter;/*!< Channel based packet drop counter */ int channel_complete_irq_counter; int channel_full_irq_counter; unsigned long channel_hangs_since; int peri_to_peri; /*!< Config Peripheral to Peripheral(not supported Danube) */ int no_cpu_data; /* added by avm: this channel is a direct path channel (data is not going through mips-cpu) */ int global_buffer_len; /*!< Config global buffer length, valid only when enabled peri_to_peri) */ int loopback_enable; /*!< Config Loop back between the DMA channels (Supported only VRx)*/ int loopback_channel_number; /*!< Config the loopback Channel number (supported only VRx) */ int req_irq_to_free; /*!< Release the DMA channel IRQ, which was already requested */ int dur; /*!< Flag for Descriptor underrun interrupt */ int scatter_gather_channel; spinlock_t irq_lock; /*!< spin lock */ ifx_dma_channel_onOff_t control; /*!< Channel on/off flag */ void* opt[IFX_DMA_DESCRIPTOR_OFFSET]; /*!< Optional info*/ void* dma_dev; /*!< Pointing to the devices */ void (*open)(struct dma_channel_info* pCh); /*!< DMA channel ON */ void (*close)(struct dma_channel_info* pCh);/*!< DMA channel OFF */ void (*reset)(struct dma_channel_info* pCh);/*!< Reset DMA channel */ void (*enable_irq)(struct dma_channel_info* pCh);/*!< Enable DMA channel interrupt */ void (*disable_irq)(struct dma_channel_info* pCh);/*!< Disable DMA channel interrupt */ char interrupt_name[32]; } _dma_channel_info; /*! \typedef _dma_device_info \brief The parameter structure is used to configure the DMA Peripheral ports info when the peripheral driver need to register with DMA core device driver. */ typedef struct dma_device_info { struct list_head parachute_list; char device_name[16]; /*!< Peripheral Device name */ int port_reserved; /*!< Reserve the device by client driver */ int port_num; /*!< Port number */ ifx_dma_burst_len_t tx_burst_len; /*!< Configure the Tx burst length */ ifx_dma_burst_len_t rx_burst_len; /*!< Conigure the Rx burst length */ int port_tx_weight; /*!< Configure the Port based weight value */ int port_packet_drop_enable; /*!< Packet drop Enabled/Disabled*/ int port_packet_drop_counter; /*!< Packet drop counter */ int mem_port_control; /*!< Configure the mem port control, only used Memory Ports */ ifx_dma_endian_t tx_endianness_mode; /*!< Configure the Endiannes in Tx direction */ ifx_dma_endian_t rx_endianness_mode; /*!< Configure the Endiannes in Rx direction */ unsigned int num_tx_chan; /*!< Config the num of Tx channels for device */ unsigned int num_rx_chan; /*!< Config the num of Rx channels for device */ unsigned int max_rx_chan_num; /*!< Max number of Rx channels supported */ unsigned int max_tx_chan_num; /*!< Max number of Tx channels supported */ spinlock_t irq_lock; /*!< spin lock */ _dma_arbitration_info arbitration_info; /*!< Structure of the arbitration config*/ _dma_channel_info* tx_chan[MAX_DMA_CHANNEL_NUM]; /*!< Max number of Channesl */ _dma_channel_info* rx_chan[MAX_DMA_CHANNEL_NUM]; /*!< Max number of Channesl */ u8* (*buffer_alloc)(int len, int* offset, void** opt); /*!< Buffer allocation */ int (*buffer_free)(u8* dataptr, void* opt); /*!< Buffer free */ int (*intr_handler)(struct dma_device_info* info, int status, int chan_no); /*!< DMA pseudo interrupt handler */ void (*activate_poll)(struct dma_device_info* dma_dev); /*!< activate the polling (Used when NAPI enables)*/ void (*inactivate_poll)(struct dma_device_info* dma_dev); /*!< Deactivate the polling (used when NAPI enabled) */ void * priv; /*!< Pointer to the device private structure */ }_dma_device_info; /* @} */ extern void dma_device_resume_tasklet(void); extern void dma_device_suspend_tasklet(void); /** Reserve the dma device port * This function should call before the dma_device_register */ extern _dma_device_info* dma_device_reserve(char* dev_name); /** Unreseve the dma device port * This function will called after the dma_device_unregister */ extern int dma_device_release(_dma_device_info* dev); /** Register with DMA device driver. This function should call after dma_device_reserve function. * This function register with dma device driver to handle dma functionality. * Should provide the required configuration info during the register with dma device. * if not provide config info, then take default values. */ extern int dma_device_register(_dma_device_info* info); /** Unregister with DMA core driver * This function unregister with dma core driver. Once it unregister there is no * DMA handling with client driver.*/ extern int dma_device_unregister(_dma_device_info* info); /** Read data packet from DMA Rx channel. * This function gets the data from the current rx descriptor of the DMA channel and send * to the client driver. * This functions is called when the client driver gets a pseudo DMA interrupt(RCV_INT). * Handle with care when call this function as well as dma_device_desc_setup function.*/ extern int dma_device_read(struct dma_device_info* info, u8** dataptr, void** opt, int chan_no) __attribute__ ((hot)); /** Write data Packet to DMA Tx channel. * This function gets the data packet from the client driver and send over on DMA channel.*/ extern int dma_device_write(struct dma_device_info* info, const u8* dataptr, int len, void* opt, int chan_no) __attribute__ ((hot)); /** Setup the DMA channel descriptor. * This function setup the descriptor of the DMA channel used by client driver. * The client driver will take care the buffer allocation and do proper checking of * buffer for DMA burst alignment. * Handle with care when call this function as well as dma_device_read function */ extern int dma_device_desc_setup(_dma_device_info *dma_dev, char *buf, size_t len, int chan_no); /** Clear the interrupt status flag * This function used to exit from DMA tasklet(tasklet don't need to run again and again ) * This is also used to avoid multiple psuedo interrupt (RCV_INT) per packet.*/ extern int dma_device_clear_int(_dma_device_info *dma_dev, int dir); /**Clear the descriptor status word from the client driver once receive a pseudo interrupt(RCV_INT) from the DMA module to avoid duplicate interrupts from tasklet. */ extern int dma_device_clear_desc_status_word(_dma_device_info *dma_dev, int dir, int chan_no); /** Poll the DMA device channel descriptors * This function polls the interrupts status in polling mode. */ extern int dma_device_poll(struct dma_device_info* info, int work_to_do, int *work_done); /** setup the dma channel class value * This function setup the class of service value for DMA channel.*/ extern void dma_device_setup_class_val(_dma_channel_info* pCh, int cls); extern unsigned long acquire_channel_lock(struct dma_device_info* dma_dev, int tx_chan_no); extern void free_channel_lock(struct dma_device_info* dma_dev, int tx_chan_no, unsigned long lock_flags); extern int tx_channels_busy(struct dma_device_info* dma_dev); #endif /* _IFX_DMA_CORE_H_ */