📄 phy3250_otg_core.cpp
字号:
//
// 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.
//
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include "ist.h"
#include "phy3250_xcvr.h"
#include "phy3250_otg_core.h"
#define VENDOR_ID 0x00 // Microsoft = 0x0045E
#define PRODUCT_ID 0x02
#define VERSION_ID 0x14
void PHY3250_OTG::host_pll_init(void)
{
// Enable host need clock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBHSTND_EN;
// Enable oscillator to PLL clock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_CLK_EN1;
// Setup and enable PLL for 48MHz
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~0x1FE;
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (191 << 1); // M=192
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(3 << 9); // N=1
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (1 << 11); // P=2 (div by 4)
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 13); // Feed CCO back to PLL
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 14); // Output of PLL is postdiv
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 15); // Feed CCO sent to postdiv
// Enable PLL and wait for lock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (1 << 16); // Enable PLL
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & 0x1) == 0); // Wait for PLL lock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBHSTND_EN;
}
void PHY3250_OTG::host_clock_init(void)
{
// Clock into PLL is 13MHz / (1 + 12) = 1MHz
m_pCLKPWRRegs->clkpwr_usbclk_pdiv = 0x0C; // 1 Mhz clock into PLL
// USB clock is always on
m_pCLKPWRRegs->clkpwr_autoclock |= CLKPWR_AUTOCLK_USB_EN;
// Restore USB control to it's default state
m_pCLKPWRRegs->clkpwr_usb_ctrl = CLKPWR_USBCTRL_BUS_KEEPER;
while (m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_PLL_PWRUP);
// Enable host need clock and slave clock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (CLKPWR_USBCTRL_HCLK_EN |
CLKPWR_USBCTRL_USBHSTND_EN);
// Enable all OTG related clocks
m_pOTGRegs->otg_clk_ctrl = (OTG_CLK_AHB_EN | OTG_CLK_OTG_EN |
OTG_CLK_I2C_EN | OTG_CLK_DEV_EN | OTG_CLK_HOST_EN);
DEBUGMSG(1, (L"CLOCK VERI 1\r\n"));
while (m_pOTGRegs->otg_clk_ctrl != (OTG_CLK_AHB_EN |
OTG_CLK_OTG_EN | OTG_CLK_I2C_EN | OTG_CLK_DEV_EN |
OTG_CLK_HOST_EN));
DEBUGMSG(1, (L"CLOCK VERI 2\r\n"));
// Setup the USB PLL
host_pll_init();
// Enable USBCLKEN2 and PLL and USB clock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_CLK_EN2;
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_CLK_EN2) !=
CLKPWR_USBCTRL_CLK_EN2);
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBDVND_EN;
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_USBDVND_EN) !=
CLKPWR_USBCTRL_USBDVND_EN);
// This is needed even if done before
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_HCLK_EN;
// ISP1301 reg MODE_CONTROL_1 = 0x04
// ISP1301 reg CTRL = 0x20
// m_pOTGRegs->otg_sts_ctrl = OTG_HOST_EN;
}
PHY3250_OTG::PHY3250_OTG(LPCTSTR lpActivePath)
: USBOTG(lpActivePath), CIST(lpActivePath, INFINITE)
{
DWORD dwLength;
DEBUGMSG(1, (L"PHY3250_OTG::PHY3250_OTG\r\n"));
m_hParent = CreateBusAccessHandle(lpActivePath);
// m_hOTGFeatureEvent = NULL;
m_pP1301Tranceiver = NULL;
m_ActiveKeyPath = NULL;
m_LPCI2C = NULL;
m_pOTGRegs = NULL;
m_pCLKPWRRegs = NULL;
if (lpActivePath)
{
dwLength = _tcslen(lpActivePath) + 1;
m_ActiveKeyPath = new TCHAR [dwLength];
if (m_ActiveKeyPath)
{
StringCchCopy(m_ActiveKeyPath, dwLength, lpActivePath);
}
}
}
PHY3250_OTG::~PHY3250_OTG(void)
{
BOOL fTerminated = FALSE;
DEBUGMSG(1, (L"PHY3250_OTG::~PHY3250_OTG\r\n"));
if (m_pP1301Tranceiver)
{
m_pP1301Tranceiver->Terminate();
}
fTerminated = ThreadTerminated(m_TerminationTimeout);
ASSERT(fTerminated);
if (m_pP1301Tranceiver)
{
delete m_pP1301Tranceiver;
}
if (m_hParent)
{
::SetDevicePowerState(m_hParent, D4, NULL);
CloseBusAccessHandle(m_hParent);
}
if (m_pOTGRegs)
{
MmUnmapIoSpace(m_pOTGRegs, sizeof(OTG_REGS_T));
}
if (m_pCLKPWRRegs)
{
MmUnmapIoSpace(m_pCLKPWRRegs, sizeof(CLKPWR_REGS_T));
}
if (m_LPCI2C)
{
delete m_LPCI2C;
}
if (m_ActiveKeyPath)
{
delete[] m_ActiveKeyPath;
}
// if (m_hOTGFeatureEvent)
// {
// CloseHandle(m_hOTGFeatureEvent);
// }
}
#define VENDOR_ID 0x00
#define PRODUCT_ID 0x02
#define VERSION_ID 0x14
BOOL PHY3250_OTG::Init(void)
{
GIISR_INFO Info;
PHYSICAL_ADDRESS pa;
// int to;
BOOL fRet = FALSE;
DEBUGMSG(1, (L"PHY3250_OTG::Init\r\n"));
m_SyncAccess.Lock();
if (m_ActiveKeyPath == NULL)
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() m_ActiveKeyPath is NULL failure\r\n"));
goto cleanup;
}
// m_hOTGFeatureEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// if (m_hOTGFeatureEvent == NULL)
// {
// DEBUGMSG(1, (L"PHY3250_OTG::Init() event allocation failure\r\n"));
// goto cleanup;
// }
// Setup mapped register space
pa.QuadPart = USB_OTG_BASE;
m_pOTGRegs = (OTG_REGS_T *) MmMapIoSpace(pa,
sizeof (OTG_REGS_T), FALSE);
pa.QuadPart = CLK_PM_BASE;
m_pCLKPWRRegs = (CLKPWR_REGS_T *) MmMapIoSpace(pa,
sizeof (CLKPWR_REGS_T), FALSE);
if ((m_pOTGRegs == NULL) || (m_pCLKPWRRegs == NULL))
{
RETAILMSG(1,
(TEXT("PHY3250_OTG::Init() failed to map registers\r\n")));
goto cleanup;
}
RETAILMSG(1,
(TEXT("0x%x 0x%x\r\n"), m_pOTGRegs, m_pCLKPWRRegs));
// Setup system and clocking
host_clock_init();
//Create I2C class
m_LPCI2C = new LPC32XX_OTGI2C;
if (m_LPCI2C == NULL)
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failed to create I2C class()\r\n"));
goto cleanup;
}
if (!m_LPCI2C->Init())
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failed I2C init\r\n"));
goto cleanup;
}
if (!USBOTG::Init())
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failed USBOTG::Init()\r\n"));
goto cleanup;
}
if (!CIST::Init())
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failed thread init\r\n"));
goto cleanup;
}
if (!IsIISRLoaded())
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failure:ISR is not loaded\r\n"));
goto cleanup;
}
if (m_pP1301Tranceiver != NULL)
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() failure:ISR is not loaded\r\n"));
goto cleanup;
}
if (IsKeyOpened()) {
// Get OTG transceiver info
WORD vendorId,productId,versionId;
if (
!ReadXCVR( VENDOR_ID, &vendorId) ||
!ReadXCVR( PRODUCT_ID, &productId) ||
!ReadXCVR( VERSION_ID, &versionId)
) {
return FALSE;
}
DWORD dwTransMode = TRANSCEIVER_4_PIN ;
if (!GetRegValue(TEXT("USBTrxMode"), (PBYTE)&dwTransMode,sizeof(dwTransMode))) {
dwTransMode = TRANSCEIVER_4_PIN;
}
// Print vendor, product & version
DEBUGMSG(1, (L"USBOTGTransceiverISP1301::Init:USB OTG Transceiver Vendor %04x Product %04x Version %04x\r\n",
vendorId, productId, versionId ));
DEBUGMSG(1, (L"USBOTGTransceiverISP1301::Init:USB OTG Transceiver mode %04x\r\n", dwTransMode));
}
#if 0
// Enable USB clocks based on 13MHz crystal
m_pCLKPWRRegs->clkpwr_usbclk_pdiv = 0x0C; // 1 Mhz clock into PLL
m_pCLKPWRRegs->clkpwr_autoclock |= CLKPWR_AUTOCLK_USB_EN;
m_pCLKPWRRegs->clkpwr_usb_ctrl = CLKPWR_USBCTRL_BUS_KEEPER;
while (m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_PLL_PWRUP);
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_HCLK_EN;
/* USB PLL configuration */
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBHSTND_EN;
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_CLK_EN1;
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~0x1FE;
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (191 << 1); // M=192
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(3 << 9); // N=1
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (1 << 11); // P=2 (div by 4)
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 13); // Feed CCO back to PLL
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 14); // Output of PLL is postdiv
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~(1 << 15); // Feed CCO sent to postdiv
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (1 << 16); // Enable PLL
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & 0x1) == 0); // Wait for PLL lock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBHSTND_EN;
/* Enable USB CLKEN2 and device clock */
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_CLK_EN2;
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_CLK_EN2) !=
CLKPWR_USBCTRL_CLK_EN2);
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_USBDVND_EN;
while ((m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_USBDVND_EN) !=
CLKPWR_USBCTRL_USBDVND_EN);
/* Required even if done before! */
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_HCLK_EN;
#if 0
// Setup USB for a 48MHz clock
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (0x0000097D | // 48x 1MHz
CLKPWR_USBCTRL_USBDVND_EN | CLKPWR_USBCTRL_CLK_EN2 |
CLKPWR_USBCTRL_CLK_EN1);
m_pCLKPWRRegs->clkpwr_usb_ctrl |= CLKPWR_USBCTRL_PLL_PWRUP;
// Wait for USB PLL to lock
to = 10;
while (((m_pCLKPWRRegs->clkpwr_usb_ctrl & CLKPWR_USBCTRL_PLL_STS) == 0) &&
(to > 0))
{
Sleep(10);
to--;
}
if (to == 0)
{
// PLL didn't lock
DEBUGMSG(1, (L"PHY3250_OTG::Init() failure:USB PLL not locked\r\n"));
goto cleanup;
}
/* Add pullup */
m_pCLKPWRRegs->clkpwr_usb_ctrl &= ~CLKPWR_USBCTRL_PD_ADD;
m_pCLKPWRRegs->clkpwr_usb_ctrl |= (0x2 << 19);
#endif
// Enable clock for OTG
m_pOTGRegs->otg_clk_ctrl = (OTG_CLK_AHB_EN | OTG_CLK_OTG_EN |
OTG_CLK_I2C_EN | OTG_CLK_DEV_EN | OTG_CLK_HOST_EN);
// Enable OTG interrupts
// m_pUSBDReg->udc_otgicr = 0 ;
// m_pUSBDReg->udc_otgisr = m_pUSBDReg->udc_otgisr;
m_pOTGRegs->otg_sts_ctrl = OTG_HOST_EN;
// | OTG_PLLUP_REMD | OTG_AB_HNP_TRK | OTG_BA_HNP_TRK); // TBD
m_pOTGRegs->otg_int_clr = (OTG_INT_HNP_SUCC | OTG_INT_HNP_FAIL |
OTG_INT_REM_PLLUP);
m_pOTGRegs->otg_int_enab = 0;
#endif
// Setup IISR
Info.SysIntr = CIST::GetSysIntr();
Info.CheckPort = FALSE;
Info.PortIsIO = FALSE;
Info.UseMaskReg = FALSE;
Info.PortAddr = (DWORD) &m_pOTGRegs->otg_int_sts;
Info.Mask = (OTG_INT_HNP_SUCC | OTG_INT_HNP_FAIL | OTG_INT_REM_PLLUP);
Info.PortSize = sizeof(DWORD);
if (!IntChainHandlerIoControl(IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL,
0, NULL))
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() Int chain handler error\r\n"));
goto cleanup;
}
DEBUGMSG(1, (L"PHY3250_OTG::Init() Setting up m_pP1301Tranceiver\r\n"));
m_pP1301Tranceiver = new PHY3250_XCVR(m_ActiveKeyPath, this);
if (!(m_pP1301Tranceiver && m_pP1301Tranceiver->Init()))
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() 1301 transceiver init error\r\n"));
goto cleanup;
}
// Enable PSW for VBUS control
{
BYTE ctrl;
if (ReadXCVR(0x12, &ctrl) == FALSE)
{
DEBUGMSG(1, (L"PHY3250_OTG::Init() 1301 transceiver VBUS control error\r\n"));
}
ctrl |= 0x40;
WriteXCVR(0x12, ctrl);
}
m_SyncAccess.Unlock();
fRet = TRUE;
cleanup:
return fRet;
}
BOOL PHY3250_OTG::PostInit()
{
BOOL fReturn = FALSE;
DEBUGMSG(1, (L"PHY3250_OTG::PostInit\r\n"));
m_SyncAccess.Lock();
if (USBOTG::PostInit()) {
#if 0
// Enable OTG Hardware
m_pOTGRegs->otg_int_clr = (OTG_INT_HNP_SUCC |
OTG_INT_HNP_FAIL | OTG_INT_REM_PLLUP);
m_pOTGRegs->otg_int_enab = (OTG_INT_HNP_SUCC |
OTG_INT_HNP_FAIL | OTG_INT_REM_PLLUP);
// 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 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -