M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,382 @@
//------------------------------------------------------------------------------
// ISC License (ISC)
//
// Copyright (c) 2010, The Linux Foundation
// All rights reserved.
// Software was previously licensed under 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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// common BMI access handling for register-based HIFs
// This module implements BMI message exchanges on behalf of the BMI module for
// HIFs that are based on a register access model
//
// Author(s): ="Atheros"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME bmi
#include "a_debug.h"
#define ATH_DEBUG_BMI ATH_DEBUG_MAKE_MODULE_MASK(0)
#include "hif.h"
#include "bmi.h"
#include "htc_api.h"
#include "target_reg_table.h"
#include "host_reg_table.h"
#define BMI_COMMUNICATION_TIMEOUT 100000
static A_BOOL pendingEventsFuncCheck = FALSE;
static A_UINT32 commandCredits = 0;
static A_UINT32 *pBMICmdCredits = &commandCredits;
/* BMI Access routines */
static A_STATUS
bmiBufferSend(HIF_DEVICE *device,
A_UCHAR *buffer,
A_UINT32 length)
{
A_STATUS status;
A_UINT32 timeout;
A_UINT32 address;
A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
&mboxAddress[0], sizeof(mboxAddress));
*pBMICmdCredits = 0;
timeout = BMI_COMMUNICATION_TIMEOUT;
while(timeout-- && !(*pBMICmdCredits)) {
/* Read the counter register to get the command credits */
address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
/* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
* a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
* make all HIF accesses 4-byte aligned */
status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4,
HIF_RD_SYNC_BYTE_INC, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
return A_ERROR;
}
/* the counter is only 8=bits, ignore anything in the upper 3 bytes */
(*pBMICmdCredits) &= 0xFF;
}
if (*pBMICmdCredits) {
address = mboxAddress[ENDPOINT1];
status = HIFReadWrite(device, address, buffer, length,
HIF_WR_SYNC_BYTE_INC, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
return A_ERROR;
}
} else {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
return A_ERROR;
}
return status;
}
static A_STATUS
bmiBufferReceive(HIF_DEVICE *device,
A_UCHAR *buffer,
A_UINT32 length,
A_BOOL want_timeout)
{
A_STATUS status;
A_UINT32 address;
A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
HIF_PENDING_EVENTS_INFO hifPendingEvents;
static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
if (!pendingEventsFuncCheck) {
/* see if the HIF layer implements an alternative function to get pending events
* do this only once! */
HIFConfigureDevice(device,
HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
&getPendingEventsFunc,
sizeof(HIF_PENDING_EVENTS_FUNC));
pendingEventsFuncCheck = TRUE;
}
HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
&mboxAddress[0], sizeof(mboxAddress));
/*
* During normal bootup, small reads may be required.
* Rather than issue an HIF Read and then wait as the Target
* adds successive bytes to the FIFO, we wait here until
* we know that response data is available.
*
* This allows us to cleanly timeout on an unexpected
* Target failure rather than risk problems at the HIF level. In
* particular, this avoids SDIO timeouts and possibly garbage
* data on some host controllers. And on an interconnect
* such as Compact Flash (as well as some SDIO masters) which
* does not provide any indication on data timeout, it avoids
* a potential hang or garbage response.
*
* Synchronization is more difficult for reads larger than the
* size of the MBOX FIFO (128B), because the Target is unable
* to push the 129th byte of data until AFTER the Host posts an
* HIF Read and removes some FIFO data. So for large reads the
* Host proceeds to post an HIF Read BEFORE all the data is
* actually available to read. Fortunately, large BMI reads do
* not occur in practice -- they're supported for debug/development.
*
* So Host/Target BMI synchronization is divided into these cases:
* CASE 1: length < 4
* Should not happen
*
* CASE 2: 4 <= length <= 128
* Wait for first 4 bytes to be in FIFO
* If CONSERVATIVE_BMI_READ is enabled, also wait for
* a BMI command credit, which indicates that the ENTIRE
* response is available in the the FIFO
*
* CASE 3: length > 128
* Wait for the first 4 bytes to be in FIFO
*
* For most uses, a small timeout should be sufficient and we will
* usually see a response quickly; but there may be some unusual
* (debug) cases of BMI_EXECUTE where we want an larger timeout.
* For now, we use an unbounded busy loop while waiting for
* BMI_EXECUTE.
*
* If BMI_EXECUTE ever needs to support longer-latency execution,
* especially in production, this code needs to be enhanced to sleep
* and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
* a function of Host processor speed.
*/
if (length >= 4) { /* NB: Currently, always true */
/*
* NB: word_available is declared static for esoteric reasons
* having to do with protection on some OSes.
*/
static A_UINT32 word_available;
A_UINT32 timeout;
word_available = 0;
timeout = BMI_COMMUNICATION_TIMEOUT;
while((!want_timeout || timeout--) && !word_available) {
if (getPendingEventsFunc != NULL) {
status = getPendingEventsFunc(device,
&hifPendingEvents,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
break;
}
if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) {
word_available = 1;
}
continue;
}
status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available,
sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
return A_ERROR;
}
/* We did a 4-byte read to the same register; all we really want is one bit */
word_available &= (1 << ENDPOINT1);
}
if (!word_available) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
return A_ERROR;
}
}
#define CONSERVATIVE_BMI_READ 0
#if CONSERVATIVE_BMI_READ
/*
* This is an extra-conservative CREDIT check. It guarantees
* that ALL data is available in the FIFO before we start to
* read from the interconnect.
*
* This credit check is useless when firmware chooses to
* allow multiple outstanding BMI Command Credits, since the next
* credit will already be present. To restrict the Target to one
* BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
*
* And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
* we cannot wait for the next credit because the Target's FIFO
* will not hold the entire response. So we need the Host to
* start to empty the FIFO sooner. (And again, large reads are
* not used in practice; they are for debug/development only.)
*
* For a more conservative Host implementation (which would be
* safer for a Compact Flash interconnect):
* Set CONSERVATIVE_BMI_READ (above) to 1
* Set HI_OPTION_BMI_CRED_LIMIT and
* reduce BMI_DATASZ_MAX to 32 or 64
*/
if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
A_UINT32 timeout;
*pBMICmdCredits = 0;
timeout = BMI_COMMUNICATION_TIMEOUT;
while((!want_timeout || timeout--) && !(*pBMICmdCredits)) {
/* Read the counter register to get the command credits */
address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
/* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
* we can read this counter multiple times using a non-incrementing address mode.
* The rationale here is to make all HIF accesses a multiple of 4 bytes */
status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
HIF_RD_SYNC_BYTE_FIX, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
return A_ERROR;
}
/* we did a 4-byte read to the same count register so mask off upper bytes */
(*pBMICmdCredits) &= 0xFF;
}
if (!(*pBMICmdCredits)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
return A_ERROR;
}
}
#endif
address = mboxAddress[ENDPOINT1];
status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
return A_ERROR;
}
return A_OK;
}
A_STATUS HIFRegBasedGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
{
A_STATUS status;
A_UINT32 cid;
AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
cid = BMI_GET_TARGET_INFO;
status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
return A_ERROR;
}
status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
sizeof(targ_info->target_ver), TRUE);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
return A_ERROR;
}
if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
/* Determine how many bytes are in the Target's targ_info */
status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
sizeof(targ_info->target_info_byte_count), TRUE);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
return A_ERROR;
}
/*
* The Target's targ_info doesn't match the Host's targ_info.
* We need to do some backwards compatibility work to make this OK.
*/
A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
/* Read the remainder of the targ_info */
status = bmiBufferReceive(device,
((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
targ_info->target_info_byte_count));
return A_ERROR;
}
} else {
/*
* Target must be an AR6001 whose firmware does not
* support BMI_GET_TARGET_INFO. Construct the data
* that it would have sent.
*/
targ_info->target_info_byte_count=sizeof(*targ_info);
targ_info->target_type=TARGET_TYPE_AR6001;
}
AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
targ_info->target_ver, targ_info->target_type));
return A_OK;
}
A_STATUS HIFExchangeBMIMsg(HIF_DEVICE *device,
A_UINT8 *pSendMessage,
A_UINT32 Length,
A_UINT8 *pResponseMessage,
A_UINT32 *pResponseLength,
A_UINT32 TimeoutMS)
{
A_STATUS status = A_OK;
do {
status = bmiBufferSend(device, pSendMessage, Length);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to Send Message to device \n"));
break;
}
if (pResponseMessage != NULL) {
status = bmiBufferReceive(device, pResponseMessage, *pResponseLength, TimeoutMS ? TRUE : FALSE);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI : Unable to read response from device \n"));
break;
}
}
} while (FALSE);
return status;
}
/* TODO .. the following APIs are a relic of the old register based interface */
A_STATUS
BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
{
return bmiBufferSend(device, buffer, length);
}
A_STATUS
BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
{
return bmiBufferReceive(device, buffer, length, want_timeout);
}

View File

@@ -0,0 +1,269 @@
//------------------------------------------------------------------------------
// ISC License (ISC)
//
// Copyright (c) 2010, The Linux Foundation
// All rights reserved.
// Software was previously licensed under 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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// common Diagnostic access handling for register-based HIFs
// This module implements diagnostic accesses on behalf of the diagnostic window module for
// HIFs that are based on a register access model
//
//
// Author(s): ="Atheros"
//==============================================================================
#include "a_config.h"
#include "athdefs.h"
#include "a_types.h"
#include "a_osapi.h"
#define ATH_MODULE_NAME misc
#include "a_debug.h"
#include "targaddrs.h"
#include "hif.h"
#include "host_reg_table.h"
#define CPU_DBG_SEL_ADDRESS 0x00000483
#define CPU_DBG_ADDRESS 0x00000484
#ifdef USE_4BYTE_REGISTER_ACCESS
/* set the window address register (using 4-byte register access ).
* This mitigates host interconnect issues with non-4byte aligned bus requests, some
* interconnects use bus adapters that impose strict limitations.
* Since diag window access is not intended for performance critical operations, the 4byte mode should
* be satisfactory even though it generates 4X the bus activity. */
static A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
{
A_STATUS status;
static A_UINT8 addrValue[4];
A_INT32 i;
static A_UINT32 address;
address = Address;
/* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
* last to initiate the access cycle */
for (i = 1; i <= 3; i++) {
/* fill the buffer with the address byte value we want to hit 4 times*/
addrValue[0] = ((A_UINT8 *)&Address)[i];
addrValue[1] = addrValue[0];
addrValue[2] = addrValue[0];
addrValue[3] = addrValue[0];
/* hit each byte of the register address with a 4-byte write operation to the same address,
* this is a harmless operation */
status = HIFReadWrite(hifDevice,
RegisterAddr+i,
addrValue,
4,
HIF_WR_SYNC_BYTE_FIX,
NULL);
if (status != A_OK) {
break;
}
}
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
Address, RegisterAddr));
return status;
}
/* write the address register again, this time write the whole 4-byte value.
* The effect here is that the LSB write causes the cycle to start, the extra
* 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
status = HIFReadWrite(hifDevice,
RegisterAddr,
(A_UCHAR *)(&address),
4,
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
Address, RegisterAddr));
return status;
}
return A_OK;
}
#else
/* set the window address register */
A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
{
A_STATUS status;
/* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
* last to initiate the access cycle */
status = HIFReadWrite(hifDevice,
RegisterAddr+1, /* write upper 3 bytes */
((A_UCHAR *)(&Address))+1,
sizeof(A_UINT32)-1,
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
RegisterAddr, Address));
return status;
}
/* write the LSB of the register, this initiates the operation */
status = HIFReadWrite(hifDevice,
RegisterAddr,
(A_UCHAR *)(&Address),
sizeof(A_UINT8),
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
RegisterAddr, Address));
return status;
}
return A_OK;
}
#endif //USE_4BYTE_REGISTER_ACCESS
/*
* Read from the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS
HIFDiagReadAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 *data)
{
A_STATUS status;
static A_UINT32 readvalue;
/* set window register to start read cycle */
status = ar6000_SetAddressWindowRegister(hifDevice,
WINDOW_READ_ADDR_ADDRESS,
address);
if (status != A_OK) {
return status;
}
/* read the data */
status = HIFReadWrite(hifDevice,
WINDOW_DATA_ADDRESS,
(A_UCHAR *)&readvalue,
sizeof(A_UINT32),
HIF_RD_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
return status;
}
*data = readvalue;
return status;
}
/*
* Write to the AR6000 through its diagnostic window.
* No cooperation from the Target is required for this.
*/
A_STATUS HIFDiagWriteAccess(HIF_DEVICE *hifDevice, A_UINT32 address, A_UINT32 data)
{
A_STATUS status;
static A_UINT32 writeValue;
writeValue = data;
/* set write data */
status = HIFReadWrite(hifDevice,
WINDOW_DATA_ADDRESS,
(A_UCHAR *)&writeValue,
sizeof(A_UINT32),
HIF_WR_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", data));
return status;
}
/* set window register, which starts the write cycle */
return ar6000_SetAddressWindowRegister(hifDevice,
WINDOW_WRITE_ADDR_ADDRESS,
address);
}
/* TODO .. the following APIs are only available on register-based HIFs where the CPU_DBG_SEL_ADDRESS
* register is available */
A_STATUS
ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
{
A_STATUS status;
A_UCHAR vals[4];
A_UCHAR register_selection[4];
register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff);
status = HIFReadWrite(hifDevice,
CPU_DBG_SEL_ADDRESS,
register_selection,
4,
HIF_WR_SYNC_BYTE_FIX,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
return status;
}
status = HIFReadWrite(hifDevice,
CPU_DBG_ADDRESS,
(A_UCHAR *)vals,
sizeof(vals),
HIF_RD_SYNC_BYTE_INC,
NULL);
if (status != A_OK) {
AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n"));
return status;
}
*regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24;
return status;
}
void
ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
{
int i;
A_UINT32 val;
for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
val=0xffffffff;
(void)ar6k_ReadTargetRegister(hifDevice, i, &val);
targregs[i] = val;
}
}

View File

@@ -0,0 +1,106 @@
//------------------------------------------------------------------------------
// ISC License (ISC)
//
// Copyright (c) 2009-2010, The Linux Foundation
// All rights reserved.
// Software was previously licensed under 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.
//
//
//------------------------------------------------------------------------------
//==============================================================================
// common header file for HIF modules designed for SDIO
//
// Author(s): ="Atheros"
//==============================================================================
#ifndef HIF_SDIO_COMMON_H_
#define HIF_SDIO_COMMON_H_
/* SDIO manufacturer ID and Codes */
#define MANUFACTURER_ID_AR6002_BASE 0x200
#define MANUFACTURER_ID_AR6003_BASE 0x300
#define MANUFACTURER_ID_MCKINLEY_BASE 0x400 /*FIXME use the correct ID,
Right now MCKINLEY masquerades as AR6002*/
#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00
#define FUNCTION_CLASS 0x0
#define MANUFACTURER_CODE 0x271 /* Atheros */
/* Mailbox address in SDIO address space */
#define HIF_MBOX_BASE_ADDR 0x800
#define HIF_MBOX_WIDTH 0x800
#define HIF_MBOX_START_ADDR(mbox) \
( HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH)
#define HIF_MBOX_END_ADDR(mbox) \
(HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1)
/* extended MBOX address for larger MBOX writes to MBOX 0*/
#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800
#define HIF_MBOX0_EXTENDED_WIDTH_AR6002 (6*1024)
#define HIF_MBOX0_EXTENDED_WIDTH_AR6003 (18*1024)
/* version 1 of the chip has only a 12K extended mbox range */
#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1 0x4000
#define HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1 (12*1024)
/* GMBOX addresses */
#define HIF_GMBOX_BASE_ADDR 0x7000
#define HIF_GMBOX_WIDTH 0x4000
/* for SDIO we recommend a 128-byte block size */
#define HIF_DEFAULT_IO_BLOCK_SIZE 128
/* set extended MBOX window information for SDIO interconnects */
static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_INFO *pInfo)
{
switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) {
case MANUFACTURER_ID_AR6002_BASE :
/* MBOX 0 has an extended range */
/**** FIXME .. MCKINLEY currently masquerades as an AR6002 device
* and thus it's actual extended window size will be incorrectly
* set. Temporarily force the location and size to match MCKINLEY ****/
//pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR;
//pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6002;
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
break;
case MANUFACTURER_ID_AR6003_BASE :
/* MBOX 0 has an extended range */
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
pInfo->GMboxSize = HIF_GMBOX_WIDTH;
break;
case MANUFACTURER_ID_MCKINLEY_BASE :
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1; /* TBDXXX */
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
break;
default:
A_ASSERT(FALSE);
break;
}
}
/* special CCCR (func 0) registers */
#define CCCR_SDIO_IRQ_MODE_REG 0xF0 /* interrupt mode register */
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/
#endif /*HIF_SDIO_COMMON_H_*/