⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phy3250_otg_core.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -