| /* |
| * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * 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" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| //============================================================================== |
| // HIF specific declarations and prototypes |
| // |
| // Author(s): ="Atheros" |
| //============================================================================== |
| #ifndef _HIF_H_ |
| #define _HIF_H_ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| /* Header files */ |
| //#include "a_config.h" |
| #include "athdefs.h" |
| #include "a_types.h" |
| #include "osapi_linux.h" |
| #include "dl_list.h" |
| |
| #define ENABLE_MBOX_DUMMY_SPACE_FEATURE 1 |
| |
| typedef struct htc_callbacks HTC_CALLBACKS; |
| typedef struct hif_device HIF_DEVICE; |
| typedef void __iomem *A_target_id_t; |
| |
| #define HIF_TYPE_AR6002 2 |
| #define HIF_TYPE_AR6003 3 |
| #define HIF_TYPE_AR6004 5 |
| #define HIF_TYPE_AR9888 6 |
| #define HIF_TYPE_AR6320 7 |
| #define HIF_TYPE_AR6320V2 8 |
| /* For attaching Peregrine 2.0 board host_reg_tbl only */ |
| #define HIF_TYPE_AR9888V2 8 |
| |
| /* |
| * direction - Direction of transfer (HIF_READ/HIF_WRITE). |
| */ |
| #define HIF_READ 0x00000001 |
| #define HIF_WRITE 0x00000002 |
| #define HIF_DIR_MASK (HIF_READ | HIF_WRITE) |
| |
| /* |
| * type - An interface may support different kind of read/write commands. |
| * For example: SDIO supports CMD52/CMD53s. In case of MSIO it |
| * translates to using different kinds of TPCs. The command type |
| * is thus divided into a basic and an extended command and can |
| * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO. |
| */ |
| #define HIF_BASIC_IO 0x00000004 |
| #define HIF_EXTENDED_IO 0x00000008 |
| #define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO) |
| |
| /* |
| * emode - This indicates the whether the command is to be executed in a |
| * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ |
| * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been |
| * implemented using the asynchronous mode allowing the the bus |
| * driver to indicate the completion of operation through the |
| * registered callback routine. The requirement primarily comes |
| * from the contexts these operations get called from (a driver's |
| * transmit context or the ISR context in case of receive). |
| * Support for both of these modes is essential. |
| */ |
| #define HIF_SYNCHRONOUS 0x00000010 |
| #define HIF_ASYNCHRONOUS 0x00000020 |
| #define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) |
| |
| /* |
| * dmode - An interface may support different kinds of commands based on |
| * the tradeoff between the amount of data it can carry and the |
| * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ |
| * HIF_BLOCK_BASIS). In case of latter, the data is rounded off |
| * to the nearest block size by padding. The size of the block is |
| * configurable at compile time using the HIF_BLOCK_SIZE and is |
| * negotiated with the target during initialization after the |
| * AR6000 interrupts are enabled. |
| */ |
| #define HIF_BYTE_BASIS 0x00000040 |
| #define HIF_BLOCK_BASIS 0x00000080 |
| #define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) |
| |
| /* |
| * amode - This indicates if the address has to be incremented on AR6000 |
| * after every read/write operation (HIF?FIXED_ADDRESS/ |
| * HIF_INCREMENTAL_ADDRESS). |
| */ |
| #define HIF_FIXED_ADDRESS 0x00000100 |
| #define HIF_INCREMENTAL_ADDRESS 0x00000200 |
| #define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) |
| |
| /* |
| * dummy - data written into the dummy space will not put into the final mbox FIFO |
| */ |
| #define HIF_DUMMY_SPACE_MASK 0xFFFF0000 |
| |
| |
| #define HIF_WR_ASYNC_BYTE_FIX \ |
| (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_WR_ASYNC_BYTE_INC \ |
| (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_WR_ASYNC_BLOCK_INC \ |
| (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_WR_SYNC_BYTE_FIX \ |
| (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_WR_SYNC_BYTE_INC \ |
| (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_WR_SYNC_BLOCK_INC \ |
| (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_WR_ASYNC_BLOCK_FIX \ |
| (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_WR_SYNC_BLOCK_FIX \ |
| (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_RD_SYNC_BYTE_INC \ |
| (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_RD_SYNC_BYTE_FIX \ |
| (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_RD_ASYNC_BYTE_FIX \ |
| (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_RD_ASYNC_BLOCK_FIX \ |
| (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) |
| #define HIF_RD_ASYNC_BYTE_INC \ |
| (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_RD_ASYNC_BLOCK_INC \ |
| (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_RD_SYNC_BLOCK_INC \ |
| (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) |
| #define HIF_RD_SYNC_BLOCK_FIX \ |
| (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) |
| |
| typedef enum { |
| HIF_DEVICE_POWER_STATE = 0, |
| HIF_DEVICE_GET_MBOX_BLOCK_SIZE, |
| HIF_DEVICE_GET_MBOX_ADDR, |
| HIF_DEVICE_GET_PENDING_EVENTS_FUNC, |
| HIF_DEVICE_GET_IRQ_PROC_MODE, |
| HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, |
| HIF_DEVICE_POWER_STATE_CHANGE, |
| HIF_DEVICE_GET_IRQ_YIELD_PARAMS, |
| HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, |
| HIF_DEVICE_GET_OS_DEVICE, |
| HIF_DEVICE_DEBUG_BUS_STATE, |
| HIF_BMI_DONE, |
| HIF_DEVICE_SET_TARGET_TYPE, |
| HIF_DEVICE_SET_HTC_CONTEXT, |
| HIF_DEVICE_GET_HTC_CONTEXT, |
| } HIF_DEVICE_CONFIG_OPCODE; |
| |
| /* |
| * HIF CONFIGURE definitions: |
| * |
| * HIF_DEVICE_GET_MBOX_BLOCK_SIZE |
| * input : none |
| * output : array of 4 u_int32_ts |
| * notes: block size is returned for each mailbox (4) |
| * |
| * HIF_DEVICE_GET_MBOX_ADDR |
| * input : none |
| * output : HIF_DEVICE_MBOX_INFO |
| * notes: |
| * |
| * HIF_DEVICE_GET_PENDING_EVENTS_FUNC |
| * input : none |
| * output: HIF_PENDING_EVENTS_FUNC function pointer |
| * notes: this is optional for the HIF layer, if the request is |
| * not handled then it indicates that the upper layer can use |
| * the standard device methods to get pending events (IRQs, mailbox messages etc..) |
| * otherwise it can call the function pointer to check pending events. |
| * |
| * HIF_DEVICE_GET_IRQ_PROC_MODE |
| * input : none |
| * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode) |
| * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF |
| * layer can report whether IRQ processing is requires synchronous behavior or |
| * can be processed using asynchronous bus requests (typically faster). |
| * |
| * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC |
| * input : |
| * output : HIF_MASK_UNMASK_RECV_EVENT function pointer |
| * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism |
| * to mask receive message events. The upper layer can call this pointer when it needs |
| * to mask/unmask receive events (in case it runs out of buffers). |
| * |
| * HIF_DEVICE_POWER_STATE_CHANGE |
| * |
| * input : HIF_DEVICE_POWER_CHANGE_TYPE |
| * output : none |
| * note: this is optional for the HIF layer. The HIF layer can handle power on/off state change |
| * requests in an interconnect specific way. This is highly OS and bus driver dependent. |
| * The caller must guarantee that no HIF read/write requests will be made after the device |
| * is powered down. |
| * |
| * HIF_DEVICE_GET_IRQ_YIELD_PARAMS |
| * |
| * input : none |
| * output : HIF_DEVICE_IRQ_YIELD_PARAMS |
| * note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler. |
| * The DSR callback handler will exit after a fixed number of RX packets or events are processed. |
| * This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. |
| * The HIF implementation can ignore this command if it does not desire the DSR callback to yield. |
| * The HIF layer can indicate the maximum number of IRQ processing units (RX packets) before the |
| * DSR handler callback must yield and return control back to the HIF layer. When a yield limit is |
| * used the DSR callback will not call HIFAckInterrupts() as it would normally do before returning. |
| * The HIF implementation that requires a yield count must call HIFAckInterrupt() when it is prepared |
| * to process interrupts again. |
| * |
| * HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT |
| * input : none |
| * output : HIF_DEVICE_SCATTER_SUPPORT_INFO |
| * note: This query checks if the HIF layer implements the SCATTER request interface. Scatter requests |
| * allows upper layers to submit mailbox I/O operations using a list of buffers. This is useful for |
| * multi-message transfers that can better utilize the bus interconnect. |
| * |
| * |
| * HIF_DEVICE_GET_OS_DEVICE |
| * intput : none |
| * output : HIF_DEVICE_OS_DEVICE_INFO; |
| * note: On some operating systems, the HIF layer has a parent device object for the bus. This object |
| * may be required to register certain types of logical devices. |
| * |
| * HIF_DEVICE_DEBUG_BUS_STATE |
| * input : none |
| * output : none |
| * note: This configure option triggers the HIF interface to dump as much bus interface state. This |
| * configuration request is optional (No-OP on some HIF implementations) |
| * |
| * HIF_DEVICE_SET_TARGET_TYPE |
| * input : TARGET_TYPE_* |
| * output : none |
| * note: Some HIF implementations may need to know TargetType in order to access |
| * Target registers or Host Interest Area. (No-OP on some HIF implementations) |
| */ |
| |
| typedef struct { |
| u_int32_t ExtendedAddress; /* extended address for larger writes */ |
| u_int32_t ExtendedSize; |
| } HIF_MBOX_PROPERTIES; |
| |
| #define HIF_MBOX_FLAG_NO_BUNDLING (1 << 0) /* do not allow bundling over the mailbox */ |
| |
| typedef struct { |
| u_int32_t MboxAddresses[4]; /* must be first element for legacy HIFs that return the address in |
| and ARRAY of 32-bit words */ |
| |
| /* the following describe extended mailbox properties */ |
| HIF_MBOX_PROPERTIES MboxProp[4]; |
| /* if the HIF supports the GMbox extended address region it can report it |
| * here, some interfaces cannot support the GMBOX address range and not set this */ |
| u_int32_t GMboxAddress; |
| u_int32_t GMboxSize; |
| u_int32_t Flags; /* flags to describe mbox behavior or usage */ |
| } HIF_DEVICE_MBOX_INFO; |
| |
| typedef enum { |
| HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all |
| interrupts before returning */ |
| HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts |
| using ASYNC I/O (that is HIFAckInterrupt can be called at a |
| later time */ |
| } HIF_DEVICE_IRQ_PROCESSING_MODE; |
| |
| typedef enum { |
| HIF_DEVICE_POWER_UP, /* HIF layer should power up interface and/or module */ |
| HIF_DEVICE_POWER_DOWN, /* HIF layer should initiate bus-specific measures to minimize power */ |
| HIF_DEVICE_POWER_CUT /* HIF layer should initiate bus-specific AND/OR platform-specific measures |
| to completely power-off the module and associated hardware (i.e. cut power supplies) |
| */ |
| } HIF_DEVICE_POWER_CHANGE_TYPE; |
| |
| typedef enum { |
| HIF_DEVICE_STATE_ON, |
| HIF_DEVICE_STATE_DEEPSLEEP, |
| HIF_DEVICE_STATE_CUTPOWER, |
| HIF_DEVICE_STATE_WOW |
| } HIF_DEVICE_STATE; |
| |
| typedef struct { |
| int RecvPacketYieldCount; /* max number of packets to force DSR to return */ |
| } HIF_DEVICE_IRQ_YIELD_PARAMS; |
| |
| |
| typedef struct _HIF_SCATTER_ITEM { |
| u_int8_t *pBuffer; /* CPU accessible address of buffer */ |
| int Length; /* length of transfer to/from this buffer */ |
| void *pCallerContexts[2]; /* space for caller to insert a context associated with this item */ |
| } HIF_SCATTER_ITEM; |
| |
| struct _HIF_SCATTER_REQ; |
| |
| typedef void ( *HIF_SCATTER_COMP_CB)(struct _HIF_SCATTER_REQ *); |
| |
| typedef enum _HIF_SCATTER_METHOD { |
| HIF_SCATTER_NONE = 0, |
| HIF_SCATTER_DMA_REAL, /* Real SG support no restrictions */ |
| HIF_SCATTER_DMA_BOUNCE, /* Uses SG DMA but HIF layer uses an internal bounce buffer */ |
| } HIF_SCATTER_METHOD; |
| |
| typedef struct _HIF_SCATTER_REQ { |
| DL_LIST ListLink; /* link management */ |
| u_int32_t Address; /* address for the read/write operation */ |
| u_int32_t Request; /* request flags */ |
| u_int32_t TotalLength; /* total length of entire transfer */ |
| u_int32_t CallerFlags; /* caller specific flags can be stored here */ |
| HIF_SCATTER_COMP_CB CompletionRoutine; /* completion routine set by caller */ |
| int CompletionStatus; /* status of completion */ |
| void *Context; /* caller context for this request */ |
| int ValidScatterEntries; /* number of valid entries set by caller */ |
| HIF_SCATTER_METHOD ScatterMethod; /* scatter method handled by HIF */ |
| void *HIFPrivate[4]; /* HIF private area */ |
| u_int8_t *pScatterBounceBuffer; /* bounce buffer for upper layers to copy to/from */ |
| HIF_SCATTER_ITEM ScatterList[1]; /* start of scatter list */ |
| } HIF_SCATTER_REQ; |
| |
| typedef HIF_SCATTER_REQ * ( *HIF_ALLOCATE_SCATTER_REQUEST)(HIF_DEVICE *device); |
| typedef void ( *HIF_FREE_SCATTER_REQUEST)(HIF_DEVICE *device, HIF_SCATTER_REQ *request); |
| typedef int ( *HIF_READWRITE_SCATTER)(HIF_DEVICE *device, HIF_SCATTER_REQ *request); |
| |
| typedef struct _HIF_DEVICE_SCATTER_SUPPORT_INFO { |
| /* information returned from HIF layer */ |
| HIF_ALLOCATE_SCATTER_REQUEST pAllocateReqFunc; |
| HIF_FREE_SCATTER_REQUEST pFreeReqFunc; |
| HIF_READWRITE_SCATTER pReadWriteScatterFunc; |
| int MaxScatterEntries; |
| int MaxTransferSizePerScatterReq; |
| } HIF_DEVICE_SCATTER_SUPPORT_INFO; |
| |
| typedef struct { |
| void *pOSDevice; |
| } HIF_DEVICE_OS_DEVICE_INFO; |
| |
| #ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG |
| typedef struct _HID_ACCESS_LOG { |
| A_UINT32 seqnum; |
| bool is_write; |
| void *addr; |
| A_UINT32 value; |
| }HIF_ACCESS_LOG; |
| #endif |
| |
| #define HIF_MAX_DEVICES 1 |
| |
| struct htc_callbacks { |
| void *context; /* context to pass to the dsrhandler |
| note : rwCompletionHandler is provided the context passed to HIFReadWrite */ |
| int (* rwCompletionHandler)(void *rwContext, int status); |
| int (* dsrHandler)(void *context); |
| }; |
| |
| typedef struct osdrv_callbacks { |
| void *context; /* context to pass for all callbacks except deviceRemovedHandler |
| the deviceRemovedHandler is only called if the device is claimed */ |
| int (* deviceInsertedHandler)(void *context, void *hif_handle); |
| int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle); |
| int (* deviceSuspendHandler)(void *context); |
| int (* deviceResumeHandler)(void *context); |
| int (* deviceWakeupHandler)(void *context); |
| int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config); |
| } OSDRV_CALLBACKS; |
| |
| #define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host |
| needs to read the register table to figure out what */ |
| #define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */ |
| |
| typedef struct _HIF_PENDING_EVENTS_INFO { |
| u_int32_t Events; |
| u_int32_t LookAhead; |
| u_int32_t AvailableRecvBytes; |
| } HIF_PENDING_EVENTS_INFO; |
| |
| /* function to get pending events , some HIF modules use special mechanisms |
| * to detect packet available and other interrupts */ |
| typedef int ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE *device, |
| HIF_PENDING_EVENTS_INFO *pEvents, |
| void *AsyncContext); |
| |
| #define HIF_MASK_RECV TRUE |
| #define HIF_UNMASK_RECV FALSE |
| /* function to mask recv events */ |
| typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE *device, |
| bool Mask, |
| void *AsyncContext); |
| |
| #ifdef HIF_MBOX_SLEEP_WAR |
| /* This API is used to update the target sleep state */ |
| void |
| HIFSetMboxSleep(HIF_DEVICE *device, bool sleep, bool wait, bool cache); |
| #endif |
| /* |
| * This API is used to perform any global initialization of the HIF layer |
| * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer |
| * |
| */ |
| int HIFInit(OSDRV_CALLBACKS *callbacks); |
| |
| /* This API claims the HIF device and provides a context for handling removal. |
| * The device removal callback is only called when the OSDRV layer claims |
| * a device. The claimed context must be non-NULL */ |
| void HIFClaimDevice(HIF_DEVICE *device, void *claimedContext); |
| /* release the claimed device */ |
| void HIFReleaseDevice(HIF_DEVICE *device); |
| |
| /* This API allows the HTC layer to attach to the HIF device */ |
| int HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks); |
| /* This API detaches the HTC layer from the HIF device */ |
| void HIFDetachHTC(HIF_DEVICE *device); |
| |
| A_STATUS |
| HIFSyncRead(HIF_DEVICE *device, |
| A_UINT32 address, |
| A_UCHAR *buffer, |
| A_UINT32 length, |
| A_UINT32 request, |
| void *context); |
| |
| /* |
| * This API is used to provide the read/write interface over the specific bus |
| * interface. |
| * address - Starting address in the AR6000's address space. For mailbox |
| * writes, it refers to the start of the mbox boundary. It should |
| * be ensured that the last byte falls on the mailbox's EOM. For |
| * mailbox reads, it refers to the end of the mbox boundary. |
| * buffer - Pointer to the buffer containg the data to be transmitted or |
| * received. |
| * length - Amount of data to be transmitted or received. |
| * request - Characterizes the attributes of the command. |
| */ |
| int |
| HIFReadWrite(HIF_DEVICE *device, |
| u_int32_t address, |
| u_char *buffer, |
| u_int32_t length, |
| u_int32_t request, |
| void *context); |
| |
| /* |
| * This can be initiated from the unload driver context when the OSDRV layer has no more use for |
| * the device. |
| */ |
| void HIFShutDownDevice(HIF_DEVICE *device); |
| void HIFSurpriseRemoved(HIF_DEVICE *device); |
| |
| /* |
| * This should translate to an acknowledgment to the bus driver indicating that |
| * the previous interrupt request has been serviced and the all the relevant |
| * sources have been cleared. HTC is ready to process more interrupts. |
| * This should prevent the bus driver from raising an interrupt unless the |
| * previous one has been serviced and acknowledged using the previous API. |
| */ |
| void HIFAckInterrupt(HIF_DEVICE *device); |
| |
| void HIFMaskInterrupt(HIF_DEVICE *device); |
| |
| void HIFUnMaskInterrupt(HIF_DEVICE *device); |
| |
| int |
| HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, |
| void *config, u_int32_t configLen); |
| |
| /* |
| * This API wait for the remaining MBOX messages to be drained |
| * This should be moved to HTC AR6K layer |
| */ |
| int hifWaitForPendingRecv(HIF_DEVICE *device); |
| |
| /****************************************************************/ |
| /* BMI and Diag window abstraction */ |
| /****************************************************************/ |
| |
| #define HIF_BMI_EXCHANGE_NO_TIMEOUT ((u_int32_t)(0)) |
| |
| #define DIAG_TRANSFER_LIMIT 2048U /* maximum number of bytes that can be |
| handled atomically by DiagRead/DiagWrite */ |
| |
| /* API to handle HIF-specific BMI message exchanges, this API is synchronous |
| * and only allowed to be called from a context that can block (sleep) */ |
| int HIFExchangeBMIMsg(HIF_DEVICE *device, |
| u_int8_t *pSendMessage, |
| u_int32_t Length, |
| u_int8_t *pResponseMessage, |
| u_int32_t *pResponseLength, |
| u_int32_t TimeoutMS); |
| |
| |
| |
| /* |
| * APIs to handle HIF specific diagnostic read accesses. These APIs are |
| * synchronous and only allowed to be called from a context that can block (sleep). |
| * They are not high performance APIs. |
| * |
| * HIFDiagReadAccess reads a 4 Byte aligned/length value from a Target register |
| * or memory word. |
| * |
| * HIFDiagReadMem reads an arbitrary length of arbitrarily aligned memory. |
| */ |
| int HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data); |
| int HIFDiagReadMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes); |
| void HIFDumpTargetMemory(HIF_DEVICE *hif_device, void *ramdump_base, |
| u_int32_t address, u_int32_t size); |
| /* |
| * APIs to handle HIF specific diagnostic write accesses. These APIs are |
| * synchronous and only allowed to be called from a context that can block (sleep). |
| * They are not high performance APIs. |
| * |
| * HIFDiagWriteAccess writes a 4 Byte aligned/length value to a Target register |
| * or memory word. |
| * |
| * HIFDiagWriteMem writes an arbitrary length of arbitrarily aligned memory. |
| */ |
| int HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data); |
| int HIFDiagWriteMem(HIF_DEVICE *hif_device, A_UINT32 address, A_UINT8 *data, int nbytes); |
| #if defined(HIF_PCI) && ! defined(A_SIMOS_DEVHOST) |
| /* |
| * This API allows the Host to access Target registers of a given |
| * A_target_id_t directly and relatively efficiently over PCIe. |
| * This allows the Host to avoid extra overhead associated with |
| * sending a message to firmware and waiting for a response message |
| * from firmware, as is done on other interconnects. |
| * |
| * Yet there is some complexity with direct accesses because the |
| * Target's power state is not known a priori. The Host must issue |
| * special PCIe reads/writes in order to explicitly wake the Target |
| * and to verify that it is awake and will remain awake. |
| * |
| * NB: Host endianness conversion is left for the caller to handle. |
| * These interfaces handle access; not interpretation. |
| * |
| * Usage: |
| * During initialization, use A_TARGET_ID to obtain an 'target ID' |
| * for use with these interfaces. |
| * |
| * Use A_TARGET_READ and A_TARGET_WRITE to access Target space. |
| * These calls must be bracketed by A_TARGET_ACCESS_BEGIN and |
| * A_TARGET_ACCESS_END. A single BEGIN/END pair is adequate for |
| * multiple READ/WRITE operations. |
| * |
| * Use A_TARGET_ACCESS_BEGIN to put the Target in a state in |
| * which it is legal for the Host to directly access it. This |
| * may involve waking the Target from a low power state, which |
| * may take up to 2Ms! |
| * |
| * Use A_TARGET_ACCESS_END to tell the Target that as far as |
| * this code path is concerned, it no longer needs to remain |
| * directly accessible. BEGIN/END is under a reference counter; |
| * multiple code paths may issue BEGIN/END on a single targid. |
| * |
| * For added efficiency, the Host may use A_TARGET_ACCESS_LIKELY. |
| * The LIKELY interface works just like A_TARGET_ACCESS_BEGIN, |
| * except that it may return before the Target is actually |
| * available. It's a vague indication that some Target accesses |
| * are expected "soon". When the LIKELY API is used, |
| * A_TARGET_ACCESS_BEGIN must be used before any access. |
| * |
| * There are several uses for the LIKELY/UNLIKELY API: |
| * -If there is some potential time before Target accesses |
| * and we want to get a head start on waking the Target |
| * (e.g. to overlap Target wake with Host-side malloc) |
| * -High-level code knows that it will call low-level |
| * functions that will use BEGIN/END, and we don't want |
| * to allow the Target to sleep until the entire sequence |
| * has completed. |
| * |
| * A_TARGET_ACCESS_OK verifies that the Target can be |
| * accessed. In general, this should not be needed, but it |
| * may be useful for debugging or for special uses. |
| * |
| * Note that there must be a matching END for each BEGIN |
| * AND there must be a matching UNLIKELY for each LIKELY! |
| * |
| * NB: This API is designed to allow some flexibility in tradeoffs |
| * between Target power utilization and Host efficiency and |
| * system performance. |
| */ |
| |
| /* |
| * For maximum performance and no power management, set this to 1. |
| * For power management at the cost of performance, set this to 0. |
| */ |
| #define CONFIG_ATH_PCIE_MAX_PERF 0 |
| |
| /* |
| * For keeping the target awake till the driver is |
| * loaded, set this to 1 |
| */ |
| #define CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD 1 |
| |
| /* |
| * When CONFIG_ATH_PCIE_MAX_PERF is 0: |
| * To use LIKELY hints, set this to 1 (slightly better performance, more power) |
| * To ignore "LIKELY" hints, set this to 0 (slightly worse performance, less power) |
| */ |
| #if defined(CONFIG_ATH_PCIE_MAX_PERF) |
| #define CONFIG_ATH_PCIE_ACCESS_LIKELY 0 |
| #else |
| #define CONFIG_ATH_PCIE_ACCESS_LIKELY 1 |
| #endif |
| |
| /* |
| * Enable/disable CDC max performance workaround |
| * For max-performace set this to 0 |
| * To allow SoC to enter sleep set this to 1 |
| */ |
| #define CONFIG_DISABLE_CDC_MAX_PERF_WAR 0 |
| |
| /* |
| * PCI-E L1 ASPPM sub-states |
| * To enable clock gating in L1 state, set this to 1. (less power, slightly more wakeup latency) |
| * To disable clock gating in L1 state, set this to 0. (slighly more power) |
| */ |
| #define CONFIG_PCIE_ENABLE_L1_CLOCK_GATE 1 |
| |
| /* |
| * PCIE_ACCESS_LOG_NUM specifies the number of |
| * read/write records to store |
| */ |
| #ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG |
| #define PCIE_ACCESS_LOG_NUM 500 |
| #endif |
| |
| /* 64-bit MSI support */ |
| #define CONFIG_PCIE_64BIT_MSI 0 |
| |
| /* BAR0 ready checking for AR6320v2 */ |
| #define PCIE_BAR0_READY_CHECKING 0 |
| |
| /* AXI gating when L1, L2 to reduce power consumption */ |
| #define CONFIG_PCIE_ENABLE_AXI_CLK_GATE 0 |
| |
| extern A_target_id_t HIFGetTargetId(HIF_DEVICE *hifDevice); |
| extern int HIFTargetSleepStateAdjust(A_target_id_t targid, A_BOOL sleep_ok, A_BOOL wait_for_it); |
| extern void |
| HIFSetTargetSleep(HIF_DEVICE *hif_device, A_BOOL sleep_ok, A_BOOL wait_for_it); |
| extern A_BOOL HIFTargetForcedAwake(A_target_id_t targid); |
| extern void |
| HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device); |
| |
| #define A_TARGET_ID(hifDevice) HIFGetTargetId(hifDevice) |
| |
| #if CONFIG_ATH_PCIE_MAX_PERF |
| #define A_TARGET_ACCESS_BEGIN(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_END(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_OK(targid) 1 |
| |
| #define A_TARGET_ACCESS_LIKELY(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_UNLIKELY(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_READ(targid, offset) \ |
| A_PCI_READ32(TARGID_TO_PCI_ADDR(targid)+(offset)) |
| |
| #if 0 |
| #define A_TARGET_WRITE(targid, offset, value) \ |
| A_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid)+(offset), (value)) |
| #else /* WORKAROUND */ |
| void WAR_PCI_WRITE32(char *addr, u32 offset, u32 value); |
| #define A_TARGET_WRITE(targid, offset, value) \ |
| WAR_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid), (offset), (value)) |
| #endif |
| #define A_TARGET_ACCESS_BEGIN_RET(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_BEGIN_RET_EXT(targid, val) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_BEGIN_RET_PTR(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_END_RET(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_END_RET_EXT(targid, val) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_END_RET_PTR(targid) \ |
| do {A_target_id_t unused = (A_target_id_t)(targid); unused = unused;} while(0) |
| |
| #else /* CONFIG_ATH_PCIE_MAX_PERF */ |
| |
| void WAR_PCI_WRITE32(char *addr, u32 offset, u32 value); |
| |
| #define A_TARGET_ACCESS_BEGIN_RET_EXT(targid, val) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0 ) \ |
| val = -1; |
| |
| #define A_TARGET_ACCESS_BEGIN_RET(targid) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0) \ |
| return -1; |
| |
| #define A_TARGET_ACCESS_BEGIN_RET_PTR(targid) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_BEGIN(targid) < 0) \ |
| return NULL; |
| |
| #define A_TARGET_ACCESS_BEGIN(targid) \ |
| if(Q_TARGET_ACCESS_BEGIN(targid) < 0) \ |
| return; |
| |
| #define Q_TARGET_ACCESS_BEGIN(targid) \ |
| HIFTargetSleepStateAdjust((targid), FALSE, TRUE) |
| |
| #define A_TARGET_ACCESS_END_RET(targid) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ |
| return -1; |
| |
| #define A_TARGET_ACCESS_END_RET_EXT(targid, val) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ |
| val = -1; |
| |
| #define A_TARGET_ACCESS_END_RET_PTR(targid) \ |
| if (!WLAN_IS_EPPING_ENABLED(vos_get_conparam()) && Q_TARGET_ACCESS_END(targid) < 0) \ |
| return NULL; |
| |
| #define A_TARGET_ACCESS_END(targid) \ |
| if (Q_TARGET_ACCESS_END(targid) < 0) \ |
| return; |
| |
| #define Q_TARGET_ACCESS_END(targid) \ |
| HIFTargetSleepStateAdjust((targid), TRUE, FALSE) |
| |
| #define A_TARGET_ACCESS_OK(targid) HIFTargetForcedAwake(targid) |
| |
| #if CONFIG_ATH_PCIE_ACCESS_LIKELY |
| #define A_TARGET_ACCESS_LIKELY(targid) HIFTargetSleepStateAdjust((targid), FALSE, FALSE) |
| #define A_TARGET_ACCESS_UNLIKELY(targid) HIFTargetSleepStateAdjust((targid), TRUE, FALSE) |
| #else /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ |
| #define A_TARGET_ACCESS_LIKELY(targid) \ |
| do {unsigned long unused = (unsigned long)(targid); unused = unused;} while(0) |
| |
| #define A_TARGET_ACCESS_UNLIKELY(targid) \ |
| do {unsigned long unused = (unsigned long)(targid); unused = unused;} while(0) |
| #endif /* CONFIG_ATH_PCIE_ACCESS_LIKELY */ |
| |
| #ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG |
| extern A_UINT32 HIFTargetReadChecked(A_target_id_t targid, A_UINT32 offset); |
| extern void HIFTargetWriteChecked(A_target_id_t targid, A_UINT32 offset, A_UINT32 value); |
| #define A_TARGET_READ(targid, offset) HIFTargetReadChecked((targid), (offset)) |
| #define A_TARGET_WRITE(targid, offset, value) HIFTargetWriteChecked((targid), (offset), (value)) |
| #else /* CONFIG_ATH_PCIE_ACCESS_DEBUG */ |
| #define A_TARGET_READ(targid, offset) A_PCI_READ32(TARGID_TO_PCI_ADDR(targid)+(offset)) |
| #if 0 |
| #define A_TARGET_WRITE(targid, offset, value) \ |
| A_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid)+(offset), (value)) |
| #else /* WORKAROUND */ |
| #define A_TARGET_WRITE(targid, offset, value) \ |
| WAR_PCI_WRITE32(TARGID_TO_PCI_ADDR(targid), (offset), (value)) |
| #endif |
| #endif |
| |
| #endif /* CONFIG_ATH_PCIE_MAX_PERF */ |
| |
| /*Macro to increment the HIF layer packet error count*/ |
| #define OL_ATH_HIF_PKT_ERROR_COUNT_INCR(_hif_state,_hif_ecode);\ |
| {\ |
| if(_hif_ecode==HIF_PIPE_NO_RESOURCE)(_hif_state->sc->ol_sc->pkt_stats.hif_pipe_no_resrc_count)+=1;\ |
| } |
| /* |
| * This macro implementation is exposed for efficiency only. |
| * The implementation may change and callers should |
| * consider the targid to be a completely opaque handle. |
| */ |
| #define TARGID_TO_PCI_ADDR(targid) (*((A_target_id_t *)(targid))) |
| |
| void *HIFDeviceToOsDevice(HIF_DEVICE *hif_device); |
| |
| #elif defined(A_SIMOS_DEVHOST) |
| |
| struct ol_softc; |
| |
| u_int32_t sim_target_register_read(struct ol_softc *scn, u_int32_t addr); |
| void sim_target_register_write(struct ol_softc *scn, u_int32_t addr, u_int32_t val); |
| |
| #define A_TARGET_ID(hifDevice) 0 |
| #define A_TARGET_READ(ar, addr) sim_target_register_read(ar, addr) |
| #define A_TARGET_WRITE(ar, addr, val) sim_target_register_write(ar, addr, val) |
| #define A_TARGET_ACCESS_BEGIN(targid) |
| #define A_TARGET_ACCESS_END(targid) |
| |
| #define HIFDeviceToOsDevice(hif_device) NULL |
| |
| #else |
| |
| #define HIFDeviceToOsDevice(hif_device) NULL |
| |
| #endif |
| |
| #ifdef IPA_UC_OFFLOAD |
| /* |
| * IPA micro controller data path offload feature enabled, |
| * HIF should release copy engine related resource information to IPA UC |
| * IPA UC will access hardware resource with released information |
| */ |
| void HIFIpaGetCEResource(HIF_DEVICE *hif_device, |
| A_UINT32 *ce_sr_base_paddr, |
| A_UINT32 *ce_sr_ring_size, |
| A_UINT32 *ce_reg_paddr); |
| #endif /* IPA_UC_OFFLOAD */ |
| |
| void HIFSetMailboxSwap(HIF_DEVICE *device); |
| |
| int hif_register_driver(void); |
| void hif_unregister_driver(void); |
| /* The API's check if FW can be suspended as part of cfg80211 suspend. |
| * This is done for SDIO drivers, for other bus types it's NO OP, they |
| * enable/disable wow in bus suspend callback. |
| * In SDIO driver bus suspend host will configure 4 bit sdio mode to |
| * 1 bit sdio mode and set the appropriate host flags. |
| */ |
| bool hif_is_80211_fw_wow_required(void); |
| |
| #ifdef FEATURE_RUNTIME_PM |
| /* Runtime power management API of HIF to control |
| * runtime pm. During Runtime Suspend the get API |
| * return -EAGAIN. The caller can queue the cmd or return. |
| * The put API decrements the usage count. |
| * The get API increments the usage count. |
| * The API's are exposed to HTT and WMI Services only. |
| */ |
| int hif_pm_runtime_get(HIF_DEVICE *); |
| int hif_pm_runtime_put(HIF_DEVICE *); |
| void *hif_runtime_pm_prevent_suspend_init(const char *); |
| void hif_runtime_pm_prevent_suspend_deinit(void *data); |
| int hif_pm_runtime_prevent_suspend(void *ol_sc, void *data); |
| int hif_pm_runtime_allow_suspend(void *ol_sc, void *data); |
| int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *data, |
| unsigned int delay); |
| void hif_request_runtime_pm_resume(void *ol_sc); |
| #else |
| static inline int hif_pm_runtime_get(HIF_DEVICE *device) { return 0; } |
| static inline int hif_pm_runtime_put(HIF_DEVICE *device) { return 0; } |
| static inline int |
| hif_pm_runtime_prevent_suspend(void *ol_sc, void *context) { return 0; } |
| static inline int |
| hif_pm_runtime_allow_suspend(void *ol_sc, void *context) { return 0; } |
| static inline int |
| hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *context, |
| unsigned int msec) |
| { |
| return 0; |
| } |
| static inline void * |
| hif_runtime_pm_prevent_suspend_init(const char *name) { return NULL; } |
| static inline void |
| hif_runtime_pm_prevent_suspend_deinit(void *context) { } |
| static inline void hif_request_runtime_pm_resume(void *ol_sc) |
| { } |
| #endif |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd); |
| |
| #ifdef HIF_PCI |
| int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset); |
| #else |
| static inline int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) |
| { |
| return 0; |
| } |
| #endif |
| #endif /* _HIF_H_ */ |