blob: cae3d08f2c6f7593193bd8f7b28d5df9838e4364 [file] [log] [blame]
/*
* 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.
*/
#ifdef WIN_MOBILE7
#include <ntddk.h>
#endif
#include "hif_trace.h"
#ifndef HIF_SDIO_COMMON_H_
#define HIF_SDIO_COMMON_H_
#ifndef INLINE
#ifdef __GNUC__
#define INLINE __inline__
#else
#define INLINE __inline
#endif
#endif
/* SDIO manufacturer ID and Codes */
#define MANUFACTURER_ID_AR6002_BASE 0x200
#define MANUFACTURER_ID_AR6003_BASE 0x300
#define MANUFACTURER_ID_AR6004_BASE 0x400
#define MANUFACTURER_ID_AR6320_BASE 0x500 /* AR6320_TBDXXX */
#define MANUFACTURER_ID_QCA9377_BASE 0x700 /* QCA9377 */
#define MANUFACTURER_ID_QCA9379_BASE 0x800 /* QCA9379 */
#define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00
#define MANUFACTURER_ID_AR6K_REV_MASK 0x00FF
#define FUNCTION_CLASS 0x0
#define MANUFACTURER_CODE 0x271 /* Atheros */
/* Mailbox address in SDIO address space */
#if defined(SDIO_3_0)
#define HIF_MBOX_BASE_ADDR 0x1000
#define HIF_MBOX_DUMMY_WIDTH 0x800
#else
#define HIF_MBOX_BASE_ADDR 0x800
#define HIF_MBOX_DUMMY_WIDTH 0
#endif
#define HIF_MBOX_WIDTH 0x800
#define HIF_MBOX_START_ADDR(mbox) \
( HIF_MBOX_BASE_ADDR + mbox * (HIF_MBOX_WIDTH + HIF_MBOX_DUMMY_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*/
#if defined(SDIO_3_0)
#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x5000
#else
#define HIF_MBOX0_EXTENDED_BASE_ADDR 0x2800
#endif
#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)
#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004 0x2800
#define HIF_MBOX0_EXTENDED_WIDTH_AR6004 (18*1024)
#if defined(SDIO_3_0)
#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320 0x5000
#define HIF_MBOX0_EXTENDED_WIDTH_AR6320 (36*1024)
#define HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0 (56*1024)
#define HIF_MBOX1_EXTENDED_WIDTH_AR6320 (36*1024)
#define HIF_MBOX_DUMMY_SPACE_SIZE_AR6320 (2*1024)
#else
#define HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320 0x2800
#define HIF_MBOX0_EXTENDED_WIDTH_AR6320 (24*1024)
#define HIF_MBOX1_EXTENDED_WIDTH_AR6320 (24*1024)
#define HIF_MBOX_DUMMY_SPACE_SIZE_AR6320 0
#endif
/* GMBOX addresses */
#define HIF_GMBOX_BASE_ADDR 0x7000
#define HIF_GMBOX_WIDTH 0x4000
/* for SDIO we recommend a 128-byte block size */
#if defined(WITH_BACKPORTS)
#define HIF_DEFAULT_IO_BLOCK_SIZE 128
#else
#define HIF_DEFAULT_IO_BLOCK_SIZE 256
#endif
/* 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 .. AR6004 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 AR6004 ****/
//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;
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6004;
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_AR6004_BASE :
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6004;
pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
pInfo->GMboxSize = HIF_GMBOX_WIDTH;
break;
case MANUFACTURER_ID_AR6320_BASE :{
A_UINT16 ManuRevID = Manfid & MANUFACTURER_ID_AR6K_REV_MASK;
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
if (ManuRevID < 4){
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320;
} else {
/* from rome 2.0(0x504), the width has been extended to 56K */
#if defined(SDIO_3_0)
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
#else
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320;
#endif
}
#if defined(SDIO_3_0)
pInfo->MboxProp[1].ExtendedAddress = pInfo->MboxProp[0].ExtendedAddress +
pInfo->MboxProp[0].ExtendedSize + HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
pInfo->MboxProp[1].ExtendedSize = HIF_MBOX1_EXTENDED_WIDTH_AR6320;
#endif
pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
pInfo->GMboxSize = HIF_GMBOX_WIDTH;
break;
}
case MANUFACTURER_ID_QCA9377_BASE :
case MANUFACTURER_ID_QCA9379_BASE :
pInfo->MboxProp[0].ExtendedAddress = HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
pInfo->MboxProp[0].ExtendedSize = HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
pInfo->MboxProp[1].ExtendedAddress = pInfo->MboxProp[0].ExtendedAddress +
pInfo->MboxProp[0].ExtendedSize + HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
pInfo->MboxProp[1].ExtendedSize = HIF_MBOX1_EXTENDED_WIDTH_AR6320;
pInfo->GMboxAddress = HIF_GMBOX_BASE_ADDR;
pInfo->GMboxSize = HIF_GMBOX_WIDTH;
break;
default:
A_ASSERT(FALSE);
break;
}
}
#define FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868
#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
/*
In SDIO 2.0, asynchronous interrupt is not in SPEC requirement, but AR6003 support it, so the register
is placed in vendor specific field 0xF0(bit0)
In SDIO 3.0, the register is defined in SPEC, and its address is 0x16(bit1)
*/
#define CCCR_SDIO_IRQ_MODE_REG_AR6003 0xF0 /* interrupt mode register of AR6003*/
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003 (1 << 0) /* mode to enable special 4-bit interrupt assertion without clock*/
#define CCCR_SDIO_IRQ_MODE_REG_AR6320 0x16 /* interrupt mode register of AR6320*/
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320 (1 << 1) /* mode to enable special 4-bit interrupt assertion without clock*/
#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS 0xF0
#define CCCR_SDIO_ASYNC_INT_DELAY_LSB 0x06
#define CCCR_SDIO_ASYNC_INT_DELAY_MASK 0xC0
/* Vendor Specific Driver Strength Settings */
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR 0xf2
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK 0x0e
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A 0x02
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C 0x04
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D 0x08
#endif /*HIF_SDIO_COMMON_H_*/