// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
 * Copyright (c) 2020 MediaTek Inc.
 */
#include <linux/string.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include "mtk_pcmcia_hal_diff.h"
#include "mtk_pcmcia.h"
#include "mtk_pcmcia_drv.h"
#include "mtk_pcmcia_hal.h"
#include "mtk_pcmcia_private.h"

#include "mtk_pcmcia_stub.h"


#define MLP_CI_CORE_ENTRY(fmt, arg...)	//pr_info("[mdbgin_CADD_CI_DRV]" fmt, ##arg)
#define DEBUG_READ_TIME 0
int mtk_pcmcia_drv_stub;
int mtk_pcmcia_drv_debug;

static int drv_companion_chip;
module_param_named(cam_drv_stub, mtk_pcmcia_drv_stub, int, 0644);
MODULE_PARM_DESC(cam_drv_stub, "enable stub messages");
module_param_named(drv_debug, mtk_pcmcia_drv_debug, int, 0644);
MODULE_PARM_DESC(drv_debug, "enable drv debug");

#define PCMCIA_MAX_DETECT_COUNT			1UL
#define PCMCIA_MAX_POLLING_COUNT		20000UL
#define PCMCIA_DEFAULT_RESET_DURATION	20UL
#define PCMCIA_HW_MAX_RETRY_COUNT		100UL
#define PCMCIA_RESET_RETRY_COUNT		3
#define PCMCIA_DELAY_LOOP_COUNT			50

#define REG_COMPANION_PCM_1035		 0x103500
#define REG_COMPANION_PCM_1036		 0x103600
#define REG_COMPANION_PCM_101E		 0x101E00

#define PCMCIA_UTOPIA2					TRUE

#define SCALE_FACTOR 2
#define SHIFT_FACTOR 8
#define H_8 0x8
#define H_F 0xf
#define H_FF 0xff
#define D_7 7
#define D_6 6
#define INT_MAKS 0x3C
#if PCMCIA_IRQ_ENABLE
static unsigned char _gbPCMCIA_Irq[E_PCMCIA_MODULE_MAX] = { 0 };
static unsigned char _gbPCMCIA_IrqStatus[E_PCMCIA_MODULE_MAX] = { FALSE };
#endif
static unsigned char _gu8PCMCIA_Command[E_PCMCIA_MODULE_MAX] = { 0 };

static unsigned char _gu8HW_ResetDuration = PCMCIA_DEFAULT_RESET_DURATION;

#if defined(MSOS_TYPE_LINUX) || defined(MSOS_TYPE_LINUX_KERNEL)
static signed int SYS_fd = -1;

#if PCMCIA_UTOPIA2
extern void *pModulePcm;

#else
static signed int Pcmcia_Mutex = -1;
#endif
/* PCMCIA_MAP_IOC_INFO */
typedef struct {
	unsigned short addr;
	unsigned char u8Value;
	unsigned char u8Type;		// 1: AttribMem, 2: IOMem
	unsigned short data_len;
	unsigned char *read_buffer;
	unsigned char *u8pWriteBuffer;
} PCMCIA_Map_Info_t;
#endif
//extern int ci_interrupt_irq;

#define TAG_PCMCIA "PCMCIA"

#define MsOS_EnableInterrupt(x)	 enable_irq((int)x)
#define MsOS_CompleteInterrupt(x)	//wait
#define MsOS_DisableInterrupt(x) disable_irq_nosync((int)x)
#define MsOS_AttachInterrupt(x, x1)
#define UTOPIA_STATUS_SUCCESS				0x00000000
#define UTOPIA_STATUS_FAIL					0x00000001
#define MsOS_DelayTask(x)  msleep_interruptible((unsigned int)x)

#define PCMCIA_PERF 0



#define PCM_ENTER()
#define PCM_EXIT()


#define BIT0  0x0001UL
#define BIT1  0x0002UL
#define BIT2  0x0004UL
#define BIT3  0x0008UL
#define BIT4  0x0010UL
#define BIT5  0x0020UL
#define BIT6  0x0040UL
#define BIT7  0x0080UL
#define BIT8  0x0100UL
#define BIT9  0x0200UL
#define BIT10 0x0400UL
#define BIT11 0x0800UL
#define BIT12 0x1000UL
#define BIT13 0x2000UL
#define BIT14 0x4000UL
#define BIT15 0x8000UL
#define EIGHT 8
#define TEN 10
#define ZERO 0x00
#define MASK_BYTE 0xFF
#define MASK_2BYTE 0xFFFF

#define PCMCIA_FIRE_COMMAND			BIT0
#define PCMCIA_CLEAN_STATE_RD_DONE	BIT1
#define PCMCIA_STATE_RD_DONE		BIT0
#define PCMCIA_STATE_BUS_IDLE		BIT1
#define PCMCIA_STATE_WD_DONE		BIT4
#define PCMCIA_DETECT_PIN_MODULEA	BIT2
#define PCMCIA_DETECT_PIN_MODULEB	BIT3

#ifdef MSOS_TYPE_LINUX_KERNEL
#define PCM_TASK_EVENTS				   0xFFFFFFFF
#define PCM_EVENT(type)				   (0x1 << type)
#define PCM_EVENT_GET(event, type)		(event & (0x1 << type))
#endif

/// Version string

static unsigned char _gbHighActive;
static unsigned char _gbCardInside[E_PCMCIA_MODULE_MAX];
static unsigned char _gbPCMCIA_Detect_Enable;
static unsigned int _gu32PCMCIA_CD_To_HWRST_Timer[E_PCMCIA_MODULE_MAX];
static unsigned char _u8PCMCIACurModule = PCMCIA_DEFAULT_MODULE;
static unsigned char _u8PCMCIACurIOCmd = ZERO;
static unsigned char _u8PCMCIACurAddr1 = MASK_BYTE;
static unsigned char _u8PCMCIACurAddr0 = MASK_BYTE;
static unsigned short _u16PCMCIACurAddr = MASK_2BYTE;

#if PCMCIA_IRQ_ENABLE
static IsrCallback _fnIsrCallback[E_PCMCIA_MODULE_MAX] = { NULL };

//static PCMCIA_ISR _gPCMCIA_ISR;
#endif
static unsigned char _gbCardReady = FALSE;

static void _mdrv_pcmcia_COMPANION_SetGPIO(PCMCIA_MODULE module,
					   unsigned char bHigh);
#if DEBUG_READ_TIME
ktime_t read_io;
#endif


void _dump_pcmcia_bank(unsigned int bank)
{
	unsigned int u8Reg;

	if (bank == REG_COMPANION_PCM_1036) {
		for (u8Reg = 0; u8Reg <= 0x1; u8Reg++)
			MTK_CI_ERR("[pcm_bank][%x]8bit=0x%02x\n",
			u8Reg, HAL_PCMCIA_Read_Byte_Dbg((u8Reg * SCALE_FACTOR), bank));
	} else if (bank == REG_COMPANION_PCM_1035) {
		for (u8Reg = 0; u8Reg <= 0x1f; u8Reg++)
			MTK_CI_ERR("[pcm_bank][%x]8bit=0x%02x\n",
			u8Reg, HAL_PCMCIA_Read_Byte_Dbg(u8Reg, bank));
	} else if (bank == REG_COMPANION_PCM_101E) {
		for (u8Reg = 0; u8Reg <= H_FF; u8Reg++)
			MTK_CI_ERR("[pcm_bank][%x]8bit=0x%02x\n",
			u8Reg, HAL_PCMCIA_Read_Byte_Dbg(u8Reg, bank));
	}
}

void _write_pcmcia_bank(unsigned int u8Reg, unsigned char u8Val, unsigned int bank)
{

	MTK_CI_ERR("[pcm_bank][%x]8bit=0x%02x\n", u8Reg, u8Val);
	HAL_PCMCIA_Write_Byte_Dbg((u8Reg * SCALE_FACTOR), u8Val, bank);
}


static unsigned char _mdrv_pcmcia_WriteReg_2Byte(unsigned int u32Addr, unsigned short u16Value)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	HAL_PCMCIA_Write_2Byte(u32Addr, u16Value);

	return TRUE;
}
static void _mdrv_pcmcia_SwitchModule(PCMCIA_MODULE module)
{
	unsigned char u8Reg = 0x0;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (_u8PCMCIACurModule == module)
		return;

	u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_MODULE_VCC_OOB);
	u8Reg &= ~(BIT0 | BIT1);

	//	MODULE_SEL[1:0] 1:0		Module select.
	//	00: No destination selected.
	//	01: Select module A.
	//	10: Select module B.
	//	11: Reserved.

	if (module == E_PCMCIA_MODULE_A)
		u8Reg |= BIT0;
	else
		u8Reg |= BIT1;


	HAL_PCMCIA_Write_Byte(REG_PCMCIA_MODULE_VCC_OOB, u8Reg);
	_u8PCMCIACurModule = module;
}

static void _mdrv_pcmcia_write_io_cmd(unsigned char io_cmd)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (_u8PCMCIACurIOCmd == io_cmd)
		return;

	HAL_PCMCIA_Write_Byte(REG_PCMCIA_PCM_MEM_IO_CMD, io_cmd);

	_u8PCMCIACurIOCmd = io_cmd;
}
static void _mdrv_pcmcia_write_addr1(unsigned char addr1)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (_u8PCMCIACurAddr1 == addr1)
		return;

	HAL_PCMCIA_Write_Byte(REG_PCMCIA_ADDR1, addr1);

	_u8PCMCIACurAddr1 = addr1;
}
static void _mdrv_pcmcia_write_addr0(unsigned char addr0)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (_u8PCMCIACurAddr0 == addr0)
		return;

	HAL_PCMCIA_Write_Byte(REG_PCMCIA_ADDR0, addr0);

	_u8PCMCIACurAddr0 = addr0;
}
static void _mdrv_pcmcia_write_addr(unsigned short addr)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (_u16PCMCIACurAddr == addr)
		return;

	_mdrv_pcmcia_WriteReg_2Byte(REG_PCMCIA_ADDR0, addr);

	_u16PCMCIACurAddr = addr;
}

#if PCMCIA_IRQ_ENABLE
void mdrv_pcmcia_isr(void)
{
	//ISR_STS IsrSts;
	//PCMCIA_MODULE module = E_PCMCIA_MODULE_A;

	//MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);

	//memset(&_gPCMCIA_ISR, 0x00, sizeof(_gPCMCIA_ISR));
	//memset(&IsrSts, 0x00, sizeof(ISR_STS));

	/* MASK PCMCIA IRQ */
	//HAL_PCMCIA_GetIntStatus(&IsrSts);
	HAL_PCMCIA_MaskInt(0x0, TRUE);
	HAL_PCMCIA_ClrInt(0x0);
#if 0
	if (IsrSts.bCardAInsert || IsrSts.bCardARemove || IsrSts.bCardAData) {
		//MTK_CI_INFO("[%s][%d]\n", __FUNCTION__, __LINE__);
		if (_gbPCMCIA_Irq[E_PCMCIA_MODULE_A])
			_gbPCMCIA_IrqStatus[E_PCMCIA_MODULE_A] = TRUE;

		if (IsrSts.bCardAInsert) {
			_gPCMCIA_ISR.bISRCardInsert = TRUE;
			MTK_CI_INFO("bISRCardInsert\n");
		}
		if (IsrSts.bCardARemove) {
			_gPCMCIA_ISR.bISRCardRemove = TRUE;
			MTK_CI_INFO("bISRCardRemove\n");
		}
		if (IsrSts.bCardAData) {
			_gPCMCIA_ISR.bISRCardData = TRUE;
			//MTK_CI_INFO("bISRCardData\n");
		}
		if (_fnIsrCallback[E_PCMCIA_MODULE_A] != NULL) {
			module = E_PCMCIA_MODULE_A;
			_fnIsrCallback[E_PCMCIA_MODULE_A] ((void
								*)(&_gPCMCIA_ISR),
							   (void *)&module);
		}
	} else if (IsrSts.bCardBInsert || IsrSts.bCardBRemove
		   || IsrSts.bCardBData) {
		if (_gbPCMCIA_Irq[E_PCMCIA_MODULE_B])
			_gbPCMCIA_IrqStatus[E_PCMCIA_MODULE_B] = TRUE;

		if (IsrSts.bCardBInsert)
			_gPCMCIA_ISR.bISRCardInsert = TRUE;

		if (IsrSts.bCardBRemove)
			_gPCMCIA_ISR.bISRCardRemove = TRUE;

		if (IsrSts.bCardBData)
			_gPCMCIA_ISR.bISRCardData = TRUE;

		if (_fnIsrCallback[E_PCMCIA_MODULE_B] != NULL) {
			module = E_PCMCIA_MODULE_B;
			_fnIsrCallback[E_PCMCIA_MODULE_B] ((void
								*)(&_gPCMCIA_ISR),
							   (void *)&module);
		}
	} else {
#ifndef CONFIG_PCMCIA_MSPI
		MTK_CI_INFO("[PCMCIA] IRQ but nothing happen\n");
		//MS_ASSERT( 0 );
#endif
	}
#endif


	/* Enable HK PCMCIA IRQ */
	//MsOS_EnableInterrupt(ci_interrupt_irq);
	//MsOS_CompleteInterrupt(E_INT_IRQ_PCM); kernel mode not need

	/* UNMASK PCMCIA IRQ */
	//HAL_PCMCIA_MaskInt(0x0, FALSE);

}
#endif

void _mdrv_pcmcia_Exit(unsigned char bSuspend)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	if (bSuspend == FALSE) {

	} else {
		// suspend
#if PCMCIA_IRQ_ENABLE
		//MsOS_DisableInterrupt(ci_interrupt_irq);
#endif
	}
	HAL_PCMCIA_ClkCtrl(FALSE);

}


void mdrv_pcmcia_init_sw(void __iomem *riu_vaddr,
			 unsigned char bHighActiveTrigger)
{
	unsigned int i = 0;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (riu_vaddr) {
		MTK_CI_INFO("riu base not zero\n");
		HAL_PCMCIA_Set_RIU_base(riu_vaddr);
	}

	_gbHighActive = bHighActiveTrigger;

	for (i = 0; i < E_PCMCIA_MODULE_MAX; i++) {
		_gbCardInside[i] = FALSE;
		_gu32PCMCIA_CD_To_HWRST_Timer[i] = 0;
		_gu8PCMCIA_Command[i] = 0;
#if PCMCIA_IRQ_ENABLE
		_fnIsrCallback[i] = NULL;
		_gbPCMCIA_Irq[i] = false;
		_gbPCMCIA_IrqStatus[i] = false;
#endif
	}

	_u8PCMCIACurModule = PCMCIA_DEFAULT_MODULE;
	_gbPCMCIA_Detect_Enable = TRUE;

}
extern void _MSPI_BurstRst(void);
void _mdrv_pcmcia_InitHW(unsigned char bResume)
{
	unsigned char u8Reg;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	HAL_PCMCIA_ClkCtrl(TRUE);

	//MTK_CI_INFO("_MSPI_BurstRst Init\n");
	if (drv_companion_chip)
		_MSPI_BurstRst();
	/* Initailze PCMCIA Registers. */
	u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_MODULE_VCC_OOB);

	u8Reg = (BIT6 | BIT0);	// reg_module_sel(BIT 1~0): module select
	//							01: select module A
	// reg_single_card(BIT4):	Only support single card
	//							1: support 1 card only
	// reg_vcc_en(BIT5):		0: VCC Disable
	// reg_oob_en(BIT6):		1: OOB enable

	HAL_PCMCIA_Write_Byte(REG_PCMCIA_MODULE_VCC_OOB, u8Reg);


#if PCMCIA_IRQ_ENABLE

	if (bResume == FALSE)
		MsOS_AttachInterrupt(E_INT_IRQ_PCM, (InterruptCb) _mdrv_pcmcia_Isr);

	MTK_CI_INFO("@ INT_MAKS = 0x%x\n", INT_MAKS);
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_INT_MASK_CLEAR, INT_MAKS);

#endif

}

unsigned int mdrv_pcmcia_set_power_state(EN_POWER_MODE power_state)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	switch (power_state) {
	case E_POWER_RESUME:
		_mdrv_pcmcia_InitHW(TRUE);
		_gbCardInside[0] = FALSE; //for STR
		_u8PCMCIACurIOCmd = ZERO;
		_u8PCMCIACurAddr1 = MASK_BYTE;
		_u8PCMCIACurAddr0 = MASK_BYTE;
		_u16PCMCIACurAddr = MASK_2BYTE;
		//_gbCardReady = FALSE;
		//MTK_CI_INFO("not _gbCardReady=FALSE\n");
		break;
	case E_POWER_SUSPEND:
		_mdrv_pcmcia_Exit(TRUE);
		break;
	case E_POWER_MECHANICAL:
	case E_POWER_SOFT_OFF:
	default:
		break;
	}
	return UTOPIA_STATUS_SUCCESS;
}
extern unsigned char mtk_msb9121_ChcekPCMCIAMode(void);
extern unsigned char mtk_msb9121_GPIO_Polling_CardDetect(void);
unsigned char _mdrv_pcmcia_DetectV2(PCMCIA_MODULE module)
{
	unsigned char u8value = 0;
	unsigned char u8DetectPin =
		(module ==
		 E_PCMCIA_MODULE_A) ? PCMCIA_DETECT_PIN_MODULEA :
		PCMCIA_DETECT_PIN_MODULEB;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

//	  if(module >= E_PCMCIA_MODULE_MAX)
//	  {
//		  MTK_CI_ERR("ERROR: Module 0x%x not support\n", (int)module);
//		  return FALSE;
//	  }

	if (!_gbPCMCIA_Detect_Enable)
		return FALSE;

	if (mtk_pcmcia_drv_stub) {
		set_stub_statue(STUB_STATE_CARD_DETECT,
						STUB_READ,
						REG_PCMCIA_READ_DATA_DONE_BUS_IDLE,
						&u8value,
						~u8DetectPin);
	} else {
		if (drv_companion_chip) {
			if (mtk_msb9121_ChcekPCMCIAMode()) {
				//PCM mode
				u8value = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);
				if ((u8value & u8DetectPin) != 0) {
					//MTK_CI_INFO("PCM mode_Polling_CardDetect out!!");
					return FALSE;
				}

				//MTK_CI_INFO("PCM mode_Polling_CardDetect in!!");
				return TRUE;

			} else
				return mtk_msb9121_GPIO_Polling_CardDetect();
		} else {
			u8value = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);
		}
	}

	if ((u8value & u8DetectPin) != 0) {
		//MTK_CI_INFO("return false\n");
		return FALSE;
	} else {
		//MTK_CI_INFO("return true\n");
		return TRUE;
	}
}

unsigned char mdrv_pcmcia_polling(PCMCIA_MODULE module)
{
	unsigned char bCardDetect;
	unsigned char bModuleStatusChange = FALSE;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return FALSE;
	}

	bCardDetect = _mdrv_pcmcia_DetectV2(module);

	if (_gbCardInside[module] != bCardDetect)
		bModuleStatusChange = TRUE;

	_gbCardInside[module] = bCardDetect;

	if (bModuleStatusChange) {
		//_gbCardInside[module] = bCardDetect;
		if (_gbCardInside[module]) {
			//_gu32PCMCIA_CD_To_HWRST_Timer[module] = MsOS_GetSystemTime();//mark nuused
			_mdrv_pcmcia_COMPANION_SetGPIO(module, TRUE);
			//MTK_CI_INFO("[%s][%d]Card detected\n", __FUNCTION__,__LINE__);
		} else {
			//_gbCardReady = FALSE;
			_mdrv_pcmcia_COMPANION_SetGPIO(module, FALSE);
			//MTK_CI_INFO("[%s][%d]Card removed\n", __FUNCTION__,__LINE__);
		}
	}

	return bModuleStatusChange;
}

void mdrv_pcmcia_reset_hw(PCMCIA_MODULE module)
{
	unsigned char u8Reg = 0, u8RawReg = 0;
	unsigned char u8ResetRetry = 0, u8DelayLoop = 0;
	unsigned char bit = (module == E_PCMCIA_MODULE_A) ? BIT2 : BIT3;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}

	PCM_ENTER();

#if PCMCIA_IRQ_ENABLE
	//mdrv_pcmcia_Enable_Interrupt( DISABLE );
#endif
	_gbCardReady = FALSE;
	MTK_CI_INFO("_gbCardReady=FALSE\n");
	for (u8ResetRetry = 0; u8ResetRetry < PCMCIA_RESET_RETRY_COUNT;
		 u8ResetRetry++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_MODULE_VCC_OOB);
		u8Reg |= bit;	//1: RESET = HIGH

		HAL_PCMCIA_Write_Byte(REG_PCMCIA_MODULE_VCC_OOB, u8Reg);
		MsOS_DelayTask(_gu8HW_ResetDuration);	// MUST...for HW reset
		u8Reg &= ~bit;	//0: RESET = LOW

		HAL_PCMCIA_Write_Byte(REG_PCMCIA_MODULE_VCC_OOB, u8Reg);
		MTK_CI_INFO("u8ResetRetry=%d\n", u8ResetRetry);
		for (u8DelayLoop = 0; u8DelayLoop < PCMCIA_DELAY_LOOP_COUNT;
			 u8DelayLoop++) {
			MsOS_DelayTask(100);
			if (mtk_pcmcia_drv_stub) {
				set_stub_statue(STUB_STATE_CARD_RESET,
					STUB_READ,
					REG_PCMCIA_STAT_INT_RAW_INT,
					&u8RawReg,
					0x00);
			} else
				u8RawReg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_STAT_INT_RAW_INT);
			MTK_CI_INFO("u8RawReg=%x\n", u8RawReg);
			if (!u8RawReg) {
				_gbCardReady = TRUE;
				MTK_CI_INFO
					("_gbCardReady=TRUE u8DelayLoop=%d\n",
					u8DelayLoop);
				goto HW_RESET_SUCCESS;
			}

		}
	}

HW_RESET_SUCCESS:

	PCM_EXIT();
}

void mdrv_pcmcia_write_attrib_mem(PCMCIA_MODULE module, unsigned short addr,
				   unsigned char value)
{
	unsigned char u8Reg = 0;
	unsigned short i;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}


	_mdrv_pcmcia_SwitchModule(module);

	// select attribute memory write, low byte
	_mdrv_pcmcia_write_io_cmd(PCMCIA_ATTRIBMEMORY_WRITE);

	// write address
	if (drv_companion_chip)
		_mdrv_pcmcia_write_addr(addr);
	else {
		_mdrv_pcmcia_write_addr1(addr >> EIGHT);
		_mdrv_pcmcia_write_addr0(addr);
	}

	// write data
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_WRITE_DATA, value);

	// fire command
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
				  PCMCIA_FIRE_COMMAND);

	// polling if bus is idle
	for (i = 0; i < PCMCIA_MAX_POLLING_COUNT; i++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (u8Reg & PCMCIA_STATE_BUS_IDLE)
			break;

	}

	if (mtk_pcmcia_drv_debug)
		MTK_CI_INFO("addr=%x, value=%x\n", addr, value);

}

void mdrv_pcmcia_read_attrib_mem(PCMCIA_MODULE module, unsigned short addr,
				  unsigned char *dest)
{
	unsigned short u16TryLoop = 0;
	unsigned char u8Reg = 0;
	unsigned int u8Val;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}
	// CIS readout with 8Bit I/O accesses
	// requires that we read only every second
	// byte. (The result of reading the even addresses does not seem to work on most modules)

	_mdrv_pcmcia_SwitchModule(module);

	// select attribute memory read, low byte
	_mdrv_pcmcia_write_io_cmd(PCMCIA_ATTRIBMEMORY_READ);

	// read address
	if (mtk_pcmcia_drv_stub) {
		unsigned char write_value;

		write_value = (addr >> SHIFT_FACTOR);
		set_stub_statue(STUB_STATE_READ_CIS,
						STUB_WRITE,
						REG_PCMCIA_ADDR1,
						&write_value,
						0);

		write_value = addr;
		set_stub_statue(STUB_STATE_READ_CIS,
						STUB_WRITE,
						REG_PCMCIA_ADDR0,
						&write_value,
						0);
	} else {

		if (drv_companion_chip)
			_mdrv_pcmcia_write_addr(addr * SCALE_FACTOR);
		else {
			_mdrv_pcmcia_write_addr1((addr * SCALE_FACTOR) >> SHIFT_FACTOR);
			_mdrv_pcmcia_write_addr0(addr * SCALE_FACTOR);
		}
	}

	// fire command
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
				  PCMCIA_FIRE_COMMAND);

	//polling if data ready
	while (1) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (u8Reg & PCMCIA_STATE_RD_DONE) {
			if (mtk_pcmcia_drv_stub) {
				set_stub_statue(STUB_STATE_READ_CIS,
								STUB_READ,
								REG_PCMCIA_READ_DATA,
								dest,
								0);
			} else
				*dest = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA);
			break;
		}

		u16TryLoop++;
		if (u16TryLoop > PCMCIA_HW_MAX_RETRY_COUNT) {
			u16TryLoop = 0;
			MTK_CI_ERR(
				  "[%s:%d][Warning!][PCMCIA] Timeout!\n",
				  __FILE__, __LINE__);


			MTK_CI_ERR("=== 1.test dump bank : 0x%x ===\n", REG_COMPANION_PCM_1035);
			_dump_pcmcia_bank(REG_COMPANION_PCM_1035);
			MTK_CI_ERR("=== 1.test dump done ===\n\n");


			MTK_CI_ERR("=== 2.test dump bank : 0x%x ===\n", REG_COMPANION_PCM_101E);
			_dump_pcmcia_bank(REG_COMPANION_PCM_101E);
			MTK_CI_ERR("=== 2.test dump done ===\n\n");


			MTK_CI_ERR("=== 3.test write/dump bank : 0x%x ===\n",
			REG_COMPANION_PCM_1036);
			for (u8Val = H_8; u8Val <= H_F; u8Val++) {
				_write_pcmcia_bank(0x0, u8Val, REG_COMPANION_PCM_1036);
				_dump_pcmcia_bank(REG_COMPANION_PCM_1036);
			}
			MTK_CI_ERR("=== 3.test write done ===\n");


			return;
		}

	}

	// clean stat_rd done
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
				  PCMCIA_CLEAN_STATE_RD_DONE);

	// polling if bus is idle
	while (1) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (PCMCIA_STATE_BUS_IDLE ==
			(u8Reg & (PCMCIA_STATE_BUS_IDLE | PCMCIA_STATE_RD_DONE))) {
			break;
		}

		u16TryLoop++;
		if (u16TryLoop > PCMCIA_HW_MAX_RETRY_COUNT) {
			u16TryLoop = 0;
			MTK_CI_ERR(
				  "[%s:%d][Warning!][PCMCIA] Timeout!\n",
				  __FILE__, __LINE__);


			MTK_CI_ERR("=== 1.test dump bank : 0x%x ===\n", REG_COMPANION_PCM_1035);
			_dump_pcmcia_bank(REG_COMPANION_PCM_1035);
			MTK_CI_ERR("=== 1.test dump done ===\n\n");


			MTK_CI_ERR("=== 2.test dump bank : 0x%x ===\n", REG_COMPANION_PCM_101E);
			_dump_pcmcia_bank(REG_COMPANION_PCM_101E);
			MTK_CI_ERR("=== 2.test dump done ===\n\n");


			MTK_CI_ERR("=== 3.test write/dump bank : 0x%x ===\n",
			REG_COMPANION_PCM_1036);
			for (u8Val = H_8; u8Val <= H_F; u8Val++) {
				_write_pcmcia_bank(0x0, u8Val, REG_COMPANION_PCM_1036);
				_dump_pcmcia_bank(REG_COMPANION_PCM_1036);
			}
			MTK_CI_ERR("=== 3.test write done ===\n");



			return;
		}

	}
	if (mtk_pcmcia_drv_debug)
		MTK_CI_INFO("addr=%x, value=%x\n", addr, *dest);

	//MTK_CI_INFO("Read Type %bx, Addr %x, value %bx\n", u8AccessType, Addr, u8mem);
}

void mdrv_pcmcia_write_io_mem(PCMCIA_MODULE module, unsigned short addr,
				   unsigned char value)
{
	unsigned char u8Reg = 0;
	unsigned short i;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}

	_mdrv_pcmcia_SwitchModule(module);

	// select attribute memory write, low byte
	_mdrv_pcmcia_write_io_cmd(PCMCIA_IO_WRITE);

	if (mtk_pcmcia_drv_stub) {
		unsigned char write_value;

		write_value = (addr >> SHIFT_FACTOR);
		set_stub_statue(STUB_STATE_WRITE_IO_MEM,
						STUB_WRITE,
						REG_PCMCIA_ADDR1,
						&write_value,
						0);

		write_value = addr;
		set_stub_statue(STUB_STATE_WRITE_IO_MEM,
						STUB_WRITE,
						REG_PCMCIA_ADDR0,
						&write_value,
						0);

		write_value = value;
		set_stub_statue(STUB_STATE_WRITE_IO_MEM,
						STUB_WRITE,
						REG_PCMCIA_WRITE_DATA,
						&write_value,
						0);

	} else {
		// write address
		if (drv_companion_chip)
			_mdrv_pcmcia_write_addr(addr);
		else {
			_mdrv_pcmcia_write_addr1(addr >> SHIFT_FACTOR);
			_mdrv_pcmcia_write_addr0(addr);
		}
		// write data
		HAL_PCMCIA_Write_Byte(REG_PCMCIA_WRITE_DATA, value);
	}
	// fire command
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
				  PCMCIA_FIRE_COMMAND);

	// polling if write idle
	for (i = 0; i < PCMCIA_MAX_POLLING_COUNT; i++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (u8Reg & PCMCIA_STATE_WD_DONE)
			break;

	}


	// polling if bus is idle
	for (i = 0; i < PCMCIA_MAX_POLLING_COUNT; i++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (u8Reg & PCMCIA_STATE_BUS_IDLE)
			break;


		if (!mdrv_pcmcia_is_module_still_plugged(module))
			return;


	}
	//MTK_CI_ERR("addr 0x%02x value 0x%02x\n", addr, value);
}
extern unsigned char _MSPI_RWLong(unsigned char u8Cmd, unsigned short u16Addr, unsigned char *u8data,
				unsigned short u16Len, const unsigned char *u8pWriteBuffer);

void mdrv_pcmcia_write_io_mem_long(PCMCIA_MODULE module, unsigned short addr,
				   unsigned short data_len, unsigned char *write_buffer)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}
	_mdrv_pcmcia_SwitchModule(module);

#if PCMCIA_PERF
	unsigned int u32Time1, u32Time2;

	u32Time1 = MsOS_GetSystemTime();
#endif
	if (mtk_pcmcia_drv_debug)
		MTK_CI_INFO("data_len 0x%02x\n", data_len);

	if (mtk_pcmcia_drv_stub || drv_companion_chip)
		_MSPI_RWLong(PCMCIA_IO_WRITE, addr, NULL, data_len, write_buffer);
	else{
		unsigned short i = 0;

		for (i = 0; i < data_len; i++) {
			mdrv_pcmcia_write_io_mem(module, addr, write_buffer[i]);
		}

	}
	if (mtk_pcmcia_drv_debug) {
		int i;

		for (i = 0; i < data_len; i++)
			MTK_CI_INFO("write_buffer[%u]=%02x\n", i, write_buffer[i]);
	}

#if PCMCIA_PERF
	u32Time2 = MsOS_GetSystemTime();
	if (data_len > TEN) {
		MTK_CI_INFO("\n\n[%s]: Len(%d), Diff(%d ms)\n\n",
			   __func__, data_len, (int)(u32Time2 - u32Time1));
	}
#endif
}
//! This function is read one byte of from the card IO memory at address addr.
unsigned char mdrv_pcmcia_read_io_mem(PCMCIA_MODULE module, unsigned short addr)
{
	unsigned char u8Reg = 0;
	unsigned char value = 0;
	unsigned short i;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return 0;
	}
	_mdrv_pcmcia_SwitchModule(module);

	// select attribute memory read, low byte
	_mdrv_pcmcia_write_io_cmd(PCMCIA_IO_READ);

	// read address
	if (mtk_pcmcia_drv_stub) {
		unsigned char write_value;

		write_value = (addr >> SHIFT_FACTOR);
		set_stub_statue(STUB_STATE_READ_IO_MEM,
						STUB_WRITE,
						REG_PCMCIA_ADDR1,
						&write_value,
						0);

		write_value = addr;
		set_stub_statue(STUB_STATE_READ_IO_MEM,
						STUB_WRITE,
						REG_PCMCIA_ADDR0,
						&write_value,
						0);
	} else {
		if (drv_companion_chip)
			_mdrv_pcmcia_write_addr(addr);
		else {
			_mdrv_pcmcia_write_addr1(addr >> SHIFT_FACTOR);
			_mdrv_pcmcia_write_addr0(addr);
		}
	}

	// fire command
#if DEBUG_READ_TIME
	read_io = ktime_get();
#endif

	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
			  PCMCIA_FIRE_COMMAND);

#if DEBUG_READ_TIME
	trace_printk("%d 50221 fire cost:%lld\n", __LINE__, ktime_to_ns(ktime_sub(ktime_get(), read_io)));
	read_io = ktime_get();
#endif

	//polling if data ready
	for (i = 0; i < PCMCIA_MAX_POLLING_COUNT; i++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (u8Reg & PCMCIA_STATE_RD_DONE) {
			if (mtk_pcmcia_drv_stub) {
				set_stub_statue(STUB_STATE_READ_IO_MEM,
								STUB_READ,
								REG_PCMCIA_READ_DATA,
								&value,
								0);
			} else {
#if DEBUG_READ_TIME
				trace_printk("%d 50221 read done cost:%lld\n",__LINE__, ktime_to_ns(ktime_sub(ktime_get(), read_io)));
				read_io = ktime_get();
#endif

				value = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA);

#if DEBUG_READ_TIME
				trace_printk("%d 50221 read data cost:%lld\n",__LINE__, ktime_to_ns(ktime_sub(ktime_get(), read_io)));
				read_io = ktime_get();
#endif
			}

			break;
		}

		if (!mdrv_pcmcia_is_module_still_plugged(module))
			return 0x00;
	}

	// clean stat_rd done
	HAL_PCMCIA_Write_Byte(REG_PCMCIA_FIRE_READ_DATA_CLEAR,
			  PCMCIA_CLEAN_STATE_RD_DONE);

#if DEBUG_READ_TIME
	trace_printk("%d 50221 clean RD_Done cost:%lld\n",__LINE__, ktime_to_ns(ktime_sub(ktime_get(), read_io)));
	read_io = ktime_get();
#endif
	// polling if bus is idle
	for (i = 0; i < PCMCIA_MAX_POLLING_COUNT; i++) {
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_READ_DATA_DONE_BUS_IDLE);

		if (PCMCIA_STATE_BUS_IDLE ==
			(u8Reg & (PCMCIA_STATE_BUS_IDLE | PCMCIA_STATE_RD_DONE))) {
			break;
		}

		if (!mdrv_pcmcia_is_module_still_plugged(module))
			return 0x00;


	}

	//MTK_CI_INFO("Read Addr %x, value %bx\n", addr, u8mem);
#if DEBUG_READ_TIME
	trace_printk("%d 50221 bus idle cost:%lld\n",__LINE__, ktime_to_ns(ktime_sub(ktime_get(), read_io)));
#endif
	return value;
}

unsigned char mdrv_pcmcia_is_module_still_plugged(PCMCIA_MODULE module)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return FALSE;
	}

	return (_gbCardInside[module]);
}
unsigned short mdrv_pcmcia_read_data(PCMCIA_MODULE module, unsigned char *read_buffer,
				   unsigned short read_buffer_size)
{
	unsigned short data_len = 0;
#if DEBUG_READ_TIME
	ktime_t ci_stime1;
#endif
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	if (module >= E_PCMCIA_MODULE_MAX) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return FALSE;
	}


	data_len =
		(unsigned short) mdrv_pcmcia_read_io_mem(module, PCMCIA_PHYS_REG_SIZEHIGH) << EIGHT |
		(unsigned short) mdrv_pcmcia_read_io_mem(module, PCMCIA_PHYS_REG_SIZELOW);

	if ((read_buffer_size != 0) & (data_len > read_buffer_size))
		data_len = read_buffer_size;
#ifdef MTK_CI_DATA_LEN_7_TO_6_ENABLE
	if (data_len == D_7) {
		data_len = D_6;
		MTK_CI_ERR("data_len 7 error change to 0x%02x\n", data_len);
	}
#endif //#ifdef MTK_CI_DATA_LEN_7_TO_6_ENABLE
	if (mtk_pcmcia_drv_debug)
		MTK_CI_INFO("data_len 0x%02x\n", data_len);

	//if(data_len > 2000){

	//	MTK_CI_ERR("delay TR 20000ms.................\n");
	//	MsOS_DelayTask(20000);
	//}

#if PCMCIA_PERF
	unsigned int u32Time1, u32Time2;

	u32Time1 = MsOS_GetSystemTime();
#endif
	if (mtk_pcmcia_drv_stub || drv_companion_chip)
		_MSPI_RWLong(PCMCIA_IO_READ, PCMCIA_PHYS_REG_DATA, read_buffer, data_len, NULL);
	else {
		unsigned short i = 0;
#if DEBUG_READ_TIME
		trace_printk("%d 50221 rev%d\n", __LINE__, data_len);
		ci_stime1 = ktime_get();
#endif
		for (i = 0; i < data_len; i++) {
			//ci_stime1 = ktime_get();
			read_buffer[i] =
				mdrv_pcmcia_read_io_mem(module, PCMCIA_PHYS_REG_DATA);
			//trace_printk("%s 50221 rev%d %lld us\n", __func__, data_len, ktime_to_us(ktime_sub(ktime_get(), ci_stime1)));
		}
#if DEBUG_READ_TIME
		trace_printk("%%d 50221 rev%d %lld us\n",__LINE__, data_len, ktime_to_us(ktime_sub(ktime_get(), ci_stime1)));
#endif
	}
	if (mtk_pcmcia_drv_debug) {
		int i;

		for (i = 0; i < data_len; i++)
			MTK_CI_INFO("read_buffer[%u]=%02x\n", i, read_buffer[i]);
	}

#if PCMCIA_PERF
	u32Time2 = MsOS_GetSystemTime();
	if (data_len > TEN) {
		MTK_CI_INFO("\n\n[%s]: Len(%d), Diff(%d ms)\n\n",
			   __func__, data_len, (int)(u32Time2 - u32Time1));
	}
#endif

	return data_len;
}
unsigned char mdrv_pcmcia_ready_status(void)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
	if (_gbCardReady) {
		//MTK_CI_INFO("_gbCardReady=TRUE\n");
		return TRUE;
	}

	//MTK_CI_INFO("_gbCardReady=FALSE\n");
	return FALSE;

}

#if PCMCIA_IRQ_ENABLE
void _mdrv_pcmcia_Enable_InterruptV2(PCMCIA_MODULE module, unsigned char bEnable)
{
	unsigned char u8Reg;

	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);

	if (module >= E_PCMCIA_MODULE_MAX || module < 0) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}

	//_mdrv_pcmcia_Set_InterruptStatusV2(module, FALSE);

	if (bEnable == true) {
		_gbPCMCIA_Irq[module] = true;
		//MTK_CI_INFO("ci irq = %x\n", ci_interrupt_irq);
		/* Enable MPU PCMCIA IRQ. */
		//MsOS_EnableInterrupt( ci_interrupt_irq );


		/* Enable IP PCMCIA IRQ. */
		u8Reg = HAL_PCMCIA_Read_Byte(REG_PCMCIA_INT_MASK_CLEAR);
		if (module == E_PCMCIA_MODULE_A) {
			//only enaable card data
			u8Reg &= (~BIT2);
			//u8Reg &= (~BIT1);
			//u8Reg &= (~BIT0);
		} else {	// Module B
			u8Reg &= (~BIT5);
			u8Reg &= (~BIT4);
			u8Reg &= (~BIT3);
		}
		HAL_PCMCIA_Write_Byte(REG_PCMCIA_INT_MASK_CLEAR, u8Reg);
	} else {
		_gbPCMCIA_Irq[module] = false;

		/* Here DON"T Disable MPU PCMCIA IRQ. */
		/* Disable IP PCMCIA IRQ. */
		u8Reg= HAL_PCMCIA_Read_Byte(REG_PCMCIA_INT_MASK_CLEAR);
		if (module == E_PCMCIA_MODULE_A) {
			//DIABLE ALL INTERRUPT
			u8Reg |= BIT7;
			u8Reg |= BIT6;
			u8Reg |= BIT5;
			u8Reg |= BIT4;
			u8Reg |= BIT3;
			u8Reg |= BIT2;
			u8Reg |= BIT1;
			u8Reg |= BIT0;
		} else {	// Module B
			u8Reg |= BIT5;
		}
		HAL_PCMCIA_Write_Byte(REG_PCMCIA_INT_MASK_CLEAR, u8Reg);
	}
}

void _mdrv_pcmcia_Set_InterruptStatusV2(PCMCIA_MODULE module, unsigned char Status)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	if (module >= E_PCMCIA_MODULE_MAX || module < 0) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}
	_gbPCMCIA_IrqStatus[module] = Status;
}

unsigned char _mdrv_pcmcia_Get_InterruptStatusV2(PCMCIA_MODULE module)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	if (module >= E_PCMCIA_MODULE_MAX || module < 0) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return 0;
	}
	return _gbPCMCIA_IrqStatus[module];
}

void _mdrv_pcmcia_InstarllIsrCallbackV2(PCMCIA_MODULE module,
					IsrCallback fnIsrCallback)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	if (module >= E_PCMCIA_MODULE_MAX || module < 0) {
		MTK_CI_ERR("ERROR: Module 0x%x not support\n",
			  (int)module);
		return;
	}
	_fnIsrCallback[module] = fnIsrCallback;
}

#if defined(MSOS_TYPE_LINUX_KERNEL) && defined(PCMCIA_IRQ_ENABLE)
unsigned char _mdrv_pcmcia_IsrStatus(PCMCIA_MODULE *module, PCMCIA_ISR *pStIsr)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	return TRUE;
}
#endif
#endif

static void _mdrv_pcmcia_COMPANION_SetGPIO(PCMCIA_MODULE module, unsigned char bHigh)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check
}

// backward compatible

#if PCMCIA_IRQ_ENABLE

void mdrv_pcmcia_Enable_InterruptV2(PCMCIA_MODULE module, unsigned char bEnable)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	_mdrv_pcmcia_Enable_InterruptV2(module, bEnable);
}

void mdrv_pcmcia_Set_InterruptStatus(unsigned char Status)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	_mdrv_pcmcia_Set_InterruptStatusV2(PCMCIA_DEFAULT_MODULE, Status);
}

unsigned char mdrv_pcmcia_Get_InterruptStatus(void)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	return _mdrv_pcmcia_Get_InterruptStatusV2(PCMCIA_DEFAULT_MODULE);
}

void mdrv_pcmcia_InstarllIsrCallback(IsrCallback fnIsrCallback)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	_mdrv_pcmcia_InstarllIsrCallbackV2(PCMCIA_DEFAULT_MODULE,
					   fnIsrCallback);
}

#endif				// PCMCIA_IRQ_ENABLE

unsigned char _bInited_Drv = FALSE;
void mdrv_pcmcia_init_hw(void)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);//check

	//_mdrv_pcmcia_InitSW(bCD_Reverse); change to .prob
	if (_bInited_Drv == FALSE) {
		_mdrv_pcmcia_InitHW(FALSE);
		_bInited_Drv = TRUE;
	}
}

void mdrv_pcmcia_exit(void)
{
	MLP_CI_CORE_ENTRY("[%s][%d]\n", __func__, __LINE__);
	_mdrv_pcmcia_Exit(FALSE);
	_bInited_Drv = FALSE;
}

void mdrv_pcmcia_set_companion_chip(int companion_chip)
{

	MTK_CI_INFO("\n");
	drv_companion_chip = companion_chip;
	hal_pcmcia_set_companion_chip(companion_chip);

	MTK_CI_INFO("pass\n");
}
