//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
bul_usbotg.cpp
Abstract:
Bulverde USB OTG Driver.
--*/
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include <bulverde_usbotg.h>
#include "bul_usbotg.h"
#include <bulverde_base_regs.h>
CBulverdeI2COTG::CBulverdeI2COTG ()
{
v_pI2C = NULL;
v_pGPIORegs = NULL;
v_pClkRegs = NULL ;
v_pOSTRegs = NULL;
}
#define VENDOR_ID 0x00
#define PRODUCT_ID 0x02
#define VERSION_ID 0x14
BOOL CBulverdeI2COTG::Init()
{
PHYSICAL_ADDRESS PA;
PA.QuadPart = BULVERDE_BASE_REG_PA_I2C;
v_pI2C = (P_XLLP_I2C_T) MmMapIoSpace(PA, sizeof(XLLP_I2C_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_OST;
v_pOSTRegs = (P_XLLP_OST_T) MmMapIoSpace(PA, sizeof(XLLP_OST_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_CLKMGR;
v_pClkRegs = (P_XLLP_CLKMGR_T) MmMapIoSpace(PA, sizeof(XLLP_CLKMGR_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_GPIO;
v_pGPIORegs = (P_XLLP_GPIO_T) MmMapIoSpace(PA, sizeof(XLLP_GPIO_T), FALSE);
PA.QuadPart = MAINSTONEII_BASE_REG_PA_FPGA;
m_pBCRReg =(PMAINSTONEII_BLR_REGS) MmMapIoSpace(PA, sizeof(MAINSTONEII_BLR_REGS),FALSE) ;
if (v_pI2C && v_pGPIORegs && v_pClkRegs && v_pOSTRegs && m_pBCRReg ) {
ReInit();
return TRUE;
}
else
return FALSE;
};
VOID CBulverdeI2COTG::ReInit()
{
m_pBCRReg->misc_wr2 |= XLLP_BCR_MISCWR2_USB_OTG_SEL;
m_pBCRReg->misc_wr3 |= (1<<3);
m_pBCRReg->misc_wr2 |= XLLP_BCR_MISCWR2_USB_OTG_RST;
StallExecution(20);
m_pBCRReg->misc_wr2 &= ~XLLP_BCR_MISCWR2_USB_OTG_RST;
m_pBCRReg->misc_wr2 |= XLLP_BCR_MISCWR2_NUSBC_SC; // Disable USB Client Driver Software Connect.
XllpI2cInit((P_XLLP_I2C_T)(v_pI2C), (P_XLLP_GPIO_T) v_pGPIORegs, (P_XLLP_CLKMGR_T) v_pClkRegs, (XLLP_UINT32_T) 0);
}
CBulverdeI2COTG::~CBulverdeI2COTG()
{
if (m_pBCRReg)
MmUnmapIoSpace(m_pBCRReg, sizeof(MAINSTONEII_BLR_REGS));
if (v_pI2C)
MmUnmapIoSpace( v_pI2C,sizeof(XLLP_I2C_T));
if (v_pOSTRegs)
MmUnmapIoSpace(v_pOSTRegs,sizeof(XLLP_OST_T));
if (v_pClkRegs)
MmUnmapIoSpace (v_pClkRegs,sizeof(XLLP_CLKMGR_T));
if (v_pGPIORegs)
MmUnmapIoSpace(v_pGPIORegs,sizeof(XLLP_GPIO_T));
}
#ifdef DEBUG
const DWORD cISTTimeOut = (30*1000);
#else
const DWORD cISTTimeOut = INFINITE ;
#endif
CBulverdeOTG::CBulverdeOTG(LPCTSTR lpActivePath)
: USBOTG(lpActivePath)
, CIST(lpActivePath, cISTTimeOut )
{
m_hParent = CreateBusAccessHandle(lpActivePath);
m_hOTGFeatureEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
m_pP1301Tranceiver = NULL;
m_ActiveKeyPath = NULL;
m_pUSBDReg = NULL;
v_pGPIORegs = NULL;
if (lpActivePath) {
DWORD dwLength = _tcslen(lpActivePath) + 1;
m_ActiveKeyPath = new TCHAR [ dwLength ] ;
if (m_ActiveKeyPath)
StringCchCopy( m_ActiveKeyPath, dwLength, lpActivePath );
}
}
BOOL CBulverdeOTG::Init()
{
m_SyncAccess.Lock();
BOOL fRet = FALSE;
if (m_ActiveKeyPath!=NULL && m_hOTGFeatureEvent != NULL
&& USBOTG::Init()
&& m_BulverdeI2COtg.Init()
&& CIST::Init()
&& MapHardware()
&& IsIISRLoaded()
&& m_pP1301Tranceiver==NULL) {
fRet = TRUE;
// Setup IISR
m_pUSBDReg->udc_otgicr = 0 ;
m_pUSBDReg->udc_otgisr = m_pUSBDReg->udc_otgisr;
GIISR_INFO Info;
Info.SysIntr = CIST::GetSysIntr();
Info.CheckPort = TRUE;
Info.PortIsIO = FALSE;
Info.UseMaskReg = FALSE;
Info.PortAddr = ( DWORD ) m_pUSBDStaticAddr + 0x1c; // Offset to udc_otgisr
Info.Mask = MAXDWORD ;
Info.PortSize = sizeof( DWORD );
if ( fRet && !IntChainHandlerIoControl( IOCTL_GIISR_INFO,&Info, sizeof( Info ), NULL, 0, NULL ) ) {
fRet = FALSE;
}
if (fRet && !ConfigurePinout()) {
fRet = FALSE;
}
if (fRet) {
m_pP1301Tranceiver = new BulverExternTranscever(m_ActiveKeyPath,this);
if (!(m_pP1301Tranceiver && m_pP1301Tranceiver->Init())) {
fRet = FALSE;
}
}
}
m_SyncAccess.Unlock();
return fRet;
}
BOOL CBulverdeOTG::PostInit()
{
m_SyncAccess.Lock();
BOOL fReturn = FALSE;
if (USBOTG::PostInit()) {
// Enable OTG Hardware.
UDCCR udccr;
udccr.ulValue = m_pUSBDReg->udc_cr;
udccr.bit.UDE=udccr.bit.OEN = 1;
m_pUSBDReg->udc_cr = udccr.ulValue ;
m_pUSBDReg->udc_otgicr = MAXDWORD ;
UP2OCR up2ocr;
up2ocr.ul = 0;
up2ocr.bit.HXS=0;
up2ocr.bit.SEOS= 4;
m_pUSBDReg->up2ocr = up2ocr.ul;
m_pUSBDReg->up3ocr = 0;
ASSERT(m_pP1301Tranceiver!=NULL);
CIST::CeSetPriority(m_iThreadPriority);
CIST::IntializeInterrupt();
fReturn = TRUE;
// Let following run to handle the outstanding interrupt.
m_pP1301Tranceiver->ISTThreadRun();
ISTProcess();
InterruptDone(GetSysIntr());
DEBUGMSG(ZONE_OTG_FUNCTION, (L"CBulverdeOTG::PostInit: m_pUSBDReg->udc_otgicr = 0x%x\r\n",m_pUSBDReg->udc_otgicr));
m_pUSBDReg->udc_otgicr = MAXDWORD ;
}
m_SyncAccess.Unlock();
return fReturn;
}
CBulverdeOTG::~CBulverdeOTG()
{
m_bTerminated = FALSE;
if (m_pP1301Tranceiver)
m_pP1301Tranceiver->Terminate();
BOOL fTermianted = ThreadTerminated( m_TerminationTimeout );
ASSERT(fTermianted);
if (m_pP1301Tranceiver)
delete m_pP1301Tranceiver ;
if (v_pGPIORegs != NULL) {
MmUnmapIoSpace(v_pGPIORegs,sizeof(XLLP_GPIO_T));
}
if (m_hParent) {
::SetDevicePowerState(m_hParent, D4, NULL);
CloseBusAccessHandle(m_hParent);
}
if (m_pUSBDReg!=NULL)
MmUnmapIoSpace(m_pUSBDReg,sizeof(BULVERDE_USBD_REG));
if (m_ActiveKeyPath)
delete[] m_ActiveKeyPath;
if (m_hOTGFeatureEvent)
CloseHandle(m_hOTGFeatureEvent);
}
//
// device is turn off by Power Down, we need reintialize everything
BOOL CBulverdeOTG::PowerUp()
{
m_BulverdeI2COtg.ReInit();
ConfigurePinout();
UDCCR udccr;
udccr.ulValue = m_pUSBDReg->udc_cr;
udccr.bit.UDE=udccr.bit.OEN = 1;
m_pUSBDReg->udc_cr = udccr.ulValue ;
m_pUSBDReg->udc_otgicr = MAXDWORD ;
UP2OCR up2ocr;
up2ocr.ul = 0;
up2ocr.bit.HXS=0;
up2ocr.bit.SEOS= 4;
m_UsbOtgState = USBOTG_b_idle;
m_pUSBDReg->up2ocr = up2ocr.ul;
m_pUSBDReg->up3ocr = 0;
ISTTimeout();
return TRUE;
}
BOOL CBulverdeOTG::PowerDown()
{
USBOTG_TRANSCEIVER_CTL usbOtgTransCtl;
usbOtgTransCtl.ul = 0;
usbOtgTransCtl.bit.DM_PullDown = 1;
usbOtgTransCtl.bit.DP_PullDown =1;
m_pP1301Tranceiver->SetTransceiver(usbOtgTransCtl);
return