Changes in the Serial Keyboard to disable sofy key mappings for texshell roms.
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// omap3530/beagle_drivers/wb/cyashalbeagleboard_spi.cpp
//
#include <kern_priv.h>
#include <beagle/beagle_gpio.h>
#include <beagle/variant.h>
#include <assp/omap3530_assp/omap3530_assp_priv.h>
#include <assp/omap3530_assp/omap3530_irqmap.h> // GPIO interrupts
#include <assp/omap3530_assp/omap3530_gpio.h>
#include <assp.h> // Required for definition of TIsr
#include <cyasregs.h> // Astoria register definitions
#ifdef __CY_ASTORIA_BEAGLEBOARD_SPI__HAL__
#include "cyashalbeagleboard_spi.h"
#include "cyaserr.h"
#include "cyasregs.h"
#include "cyasdma.h"
#include "cyasintr.h"
#ifdef FIRMWARE_NOPPORT
#ifdef OVERCLOCK_SD
#include "cyastfw_sd_mmc_rel_nopport_Ast121_68.h"
#else
#include "cyastfw_sd_mmc_rel_nopport.h"
#endif
#else
#ifdef OVERCLOCK_SD
#include "cyastfw_sd_mmc_rel_silicon_Ast121_68.h"
#else
#include "cyastfw_sd_mmc_rel_silicon.h"
#endif
#endif
#include "cyasusbinit.h"
/*
* For performance reasons, we handle storage endpoint transfers upto 4 KB
* within the HAL itself.
*/
#define CYASSTORAGE_WRITE_EP_NUM (4)
#define CYASSTORAGE_READ_EP_NUM (8)
#define CYASSTORAGE_MAX_XFER_SIZE (2*32768)
/*#define MONITOR_THREAD 1*/
#define INT_DE 1
/* DFC queue */
TDfc* gpDfc;
/*
* The type of DMA operation, per endpoint
*/
typedef enum CyAsHalDmaType
{
CyAsHalRead,
CyAsHalWrite,
CyAsHalNone
} CyAsHalDmaType ;
typedef struct CyAsHalEndpointDma
{
CyBool buffer_valid ;
uint16_t *data_p ;
uint32_t size ;
/*struct scatterlist* sg_p ;
uint16_t scatter_index ;*/
uint32_t bytes_xfered ;
uint16_t transfer_cnt ;
CyAsHalDmaType type ;
CyBool pending ;
} CyAsHalEndpointDma ;
/*
* The list of OMAP devices (should be one)
*/
static CyAsOmapDevKernel *m_omap_list_p = 0 ;
/*
* The callback to call after DMA operations are complete
*/
static CyAsHalDmaCompleteCallback callback = 0 ;
/*
* Pending data size for the endpoints
*/
static CyAsHalEndpointDma EndPoints[16] ;
/* Forward declaration */
static void CyHandleDRQInterrupt(CyAsOmapDevKernel *dev_p) ;
static volatile uint32_t Intr_Disabled = 0 ;
static volatile CyAsHalDeviceTag gDevTag = 0 ;
#define CYAS_INT_MASK (CY_AS_MEM_P0_INTR_REG_MCUINT | CY_AS_MEM_P0_INTR_REG_MBINT | \
CY_AS_MEM_P0_INTR_REG_PMINT | CY_AS_MEM_P0_INTR_REG_PLLLOCKINT)
#define CYAS_DRQ_MASK (CY_AS_MEM_P0_INTR_REG_DRQINT)
static void
CyAstoriaISR (
void *dev_id)
{
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAstoriaISR...");
#endif
gpDfc->Add();
#ifdef SPI_DEBUG_LOG
Kern::Printf("Disable interrupt");
#endif
/* Disable Interrupt Here, it will be re-enabled by DFCs */
GPIO::DisableInterrupt(KGPIO_INT) ;
}
static void
CyAstoriaIntHandler_DFC (
TAny *aPtr)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)aPtr ;
uint16_t read_val = 0 ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAstoriaIntHandler called...");
#endif
{
read_val = CyAsHalReadRegister((CyAsHalDeviceTag)dev_p, CY_AS_MEM_P0_INTR_REG) ;
if (read_val & CYAS_INT_MASK)
{
CyAsIntrServiceInterrupt((CyAsHalDeviceTag)dev_p) ;
}
if (read_val & CYAS_DRQ_MASK)
{
CyHandleDRQInterrupt(dev_p) ;
}
}
GPIO::EnableInterrupt(KGPIO_INT) ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("Enable interrupt\n");
#endif
}
extern TmtpAstDev * g_pAstDevice ;
static int
CyAsHalConfigureInterrupts (
void *dev_p,
void *handler)
{
return CyAsHalBeagleBoard__SetupISR(handler, dev_p) ;
}
//nxz-debug
void
MyOmapStartIntr(CyAsHalDeviceTag tag)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
int ret ;
const uint16_t mask = CY_AS_MEM_P0_INTR_REG_DRQINT | CY_AS_MEM_P0_INTR_REG_MBINT ;
/* Setup DFC */
gpDfc = new TDfc( CyAstoriaIntHandler_DFC, tag, Kern::DfcQue0(), 1 ) ;
/* Register for interrupts */
ret = CyAsHalConfigureInterrupts (dev_p,(void*)CyAstoriaISR) ;
if ( ret != 0 )
Kern::Printf("ERROR: CyAsHalConfigureInterrupts failed\n");
/* enable only MBox & DRQ interrupts for now */
CyAsHalWriteRegister((CyAsHalDeviceTag)dev_p, CY_AS_MEM_P0_INT_MASK_REG, mask) ;
}
volatile CyBool interrupt_fired = CyFalse;
//This is the Diagnostics Interrupt Handler
void
MyIntTestHandler(
void *dev_id)
{
CyAsOmapDevKernel * dev_tag = (CyAsOmapDevKernel*) dev_id ;
Kern::Printf("Diag: CyAsDiagIntHandler called\n");
if(interrupt_fired == CyFalse)
{
Kern::Printf("Diag: CyAsDiagIntHandler, first instance of INT# \n");
interrupt_fired = CyTrue;
//return INT to high state, only called for override testing
CyAsHalWriteRegister(dev_tag, CY_AS_MEM_P0_VM_SET, 0x0745);
}
//return INT to high state, only called for override testing
CyAsHalWriteRegister(dev_tag, CY_AS_MEM_P0_VM_SET, 0x0745);
}
/*
* These are the functions that are not part of the HAL layer, but are required to be called
* for this HAL.
*/
int StartOMAPKernel(const char *pgm, CyAsHalDeviceTag *tag, CyBool debug)
{
CyAsOmapDevKernel *dev_p ;
CyAsHalSleepChannel channel ;
int i;
(void)debug ; /* No debug mode support as of now */
Kern::Printf ("<1>startOMAPKernel called\n");
/*
* Initialize the HAL level endpoint DMA data.
*/
for(i = 0 ; i < sizeof(EndPoints)/sizeof(EndPoints[0]) ; i++)
{
EndPoints[i].data_p = 0 ;
EndPoints[i].pending = CyFalse ;
EndPoints[i].size = 0 ;
EndPoints[i].type = CyAsHalNone ;
EndPoints[i].bytes_xfered = 0 ;
EndPoints[i].transfer_cnt = 0 ;
}
dev_p = (CyAsOmapDevKernel *)CyAsHalAlloc(sizeof(CyAsOmapDevKernel)) ;
if (dev_p == 0)
{
Kern::Printf("<1>%s: out of memory allocating OMAP device structure\n", pgm) ;
return 0 ;
}
dev_p->m_sig = CY_AS_OMAP_KERNEL_HAL_SIG ;
dev_p->m_addr_base = 0 ;
CyAsHalBeagleBoard__ConfigureSPI();
#ifdef HW_TEST
{
uint16_t readVal = 0 ;
uint16_t timeOutCounter = 0 ;
uint16_t errCnt = 0 ;
Kern::Printf( "<1> Regsiter Test ------------->\n") ;
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_CM_WB_CFG_ID) ;
Kern::Printf("ID reg 0x%04x\n",readVal);
if ( readVal != 0xa200 )
{
Kern::Printf("ERROR: Wrong Antioch ID reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0xa200);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_P0_VM_SET) ;
Kern::Printf("P0_VM_SET 0x%04x\n",readVal);
if ( readVal != 0x45 )
{
Kern::Printf("ERROR: Wrong Antioch P0_VM_SET reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0x45);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_P0_RSE_ALLOCATE) ;
Kern::Printf("P0_RSE_ALLOCATE 0x%04x\n",readVal);
if ( readVal != 0x26 )
{
Kern::Printf("ERROR: Wrong Antioch P0_RSE_ALLOCATE reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0x26);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
CyAsHalWriteRegister(dev_p, CY_AS_MEM_MCU_MAILBOX0, 0x0);
CyAsHalWriteRegister(dev_p, CY_AS_MEM_MCU_MAILBOX1, 0xFFFF);
CyAsHalWriteRegister(dev_p, CY_AS_MEM_MCU_MAILBOX2, 0xAAAA);
CyAsHalWriteRegister(dev_p, CY_AS_MEM_MCU_MAILBOX3, 0x5555);
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_MCU_MAILBOX0) ;
Kern::Printf("mailbox0 0x%04x\n",readVal);
if ( readVal != 0x0 )
{
Kern::Printf("ERROR: Wrong Antioch MAILBOX0 reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0x0);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_MCU_MAILBOX1) ;
Kern::Printf("mailbox1 0x%04x\n",readVal);
if ( readVal != 0xffff )
{
Kern::Printf("ERROR: Wrong Antioch MAILBOX1 reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0xffff);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_MCU_MAILBOX2) ;
Kern::Printf("mailbox2 0x%04x\n",readVal);
if ( readVal != 0xaaaa )
{
Kern::Printf("ERROR: Wrong Antioch MAILBOX2 reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0xaaaa);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
readVal = CyAsHalReadRegister(dev_p, CY_AS_MEM_MCU_MAILBOX3) ;
Kern::Printf("mailbox3 0x%04x\n",readVal);
if ( readVal != 0x5555 )
{
Kern::Printf("ERROR: Wrong Antioch MAILBOX3 reg value\n");
Kern::Printf("ERROR: Exp: 0x%04x\n",0x5555);
Kern::Printf("ERROR: Act: 0x%04x\n",readVal);
errCnt++;
}
Kern::Printf( "<1> Interrupt Test ------------->\n") ;
Kern::Printf("Checking that INT# can execute Procesor ISR:\n");
CyAsHalConfigureInterrupts (dev_p,(void*)MyIntTestHandler) ;
//overrid default INT# value, cause Astoria to assert INT#
CyAsHalWriteRegister(dev_p, CY_AS_MEM_P0_VM_SET, 0x0545);
do {
timeOutCounter++;
}while((interrupt_fired == CyFalse) && (timeOutCounter < 255));
if(interrupt_fired == CyTrue)
{
Kern::Printf("INT# fired Processor ISR\n");
}
else
{
Kern::Printf("ERROR: INT# did not fire processor ISR %i\n", interrupt_fired);
errCnt++;
}
if ( errCnt == 0 )
{
Kern::Printf("HW test passed!!\n") ;
}
else
Kern::Printf("HW test failed (%d)\n",errCnt) ;
Kern::Printf("Reset Astoria\n") ;
CyAsHalWriteRegister(dev_p, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;
return 0 ;
}
#endif
/*
* Now perform a hard reset of the device to have the new settings take
* effect
*/
Kern::Printf("<1>West Bridge Device Enters hard reset\n") ;
CyAsHalWriteRegister(dev_p, CY_AS_MEM_RST_CTRL_REG, CY_AS_MEM_RST_CTRL_REG_HARD) ;
/*
* Sleep for 100 ms to be sure reset is complete.
*/
Kern::Printf("<1>Sleep 100ms\n") ;
CyAsHalCreateSleepChannel (&channel) ;
CyAsHalSleepOn(&channel, 100) ;
CyAsHalDestroySleepChannel(&channel) ;
Kern::Printf("<1>MyOmapStartIntr\n") ;
MyOmapStartIntr(dev_p);
dev_p->m_next_p = m_omap_list_p ;
m_omap_list_p = dev_p ;
*tag = dev_p ;
gDevTag = dev_p ;
return 1 ;
}
int StopOMAPKernel(const char *pgm, CyAsHalDeviceTag tag)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
if (0 == dev_p)
return 1 ;
Kern::Printf ("<1>StopOMAPKernel called\n");
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("<1>%s: %s: bad TAG parameter passed to function\n", pgm, __FUNCTION__) ;
return 1 ;
}
Kern::Printf ("<1>West Bridge OMAP Kernel: Done cleaning thread\n") ;
/* TODO: */
CyAsHalFree(dev_p) ;
return 1 ;
}
/*************************************************************************************************
*
* Below are the functions that communicate with the West Bridge device. These are system dependent
* and must be defined by the HAL layer for a given system.
*
*************************************************************************************************/
void
CyAsHalWriteEP(CyAsHalDeviceTag tag, uint16_t addr, uint8_t* data, uint16_t size)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
GPIO::DisableInterrupt(KGPIO_INT) ;
/* Do additional error checks while in debug mode. */
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("<1>%s: bad TAG parameter passed to function\n", __FUNCTION__) ;
return ;
}
if (addr & 0x80)
{
Kern::Printf ("<1>West Bridge write EP address 0x%x out of range\n", addr);
return ;
}
CyAsHalBeagleBoardMcSPI4Ch0_WriteEP(addr, data, size) ;
GPIO::EnableInterrupt(KGPIO_INT) ;
return ;
}
void
CyAsHalReadEP(CyAsHalDeviceTag tag, uint16_t addr, uint8_t* data, uint16_t size)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
GPIO::DisableInterrupt(KGPIO_INT) ;
/* Do additional error checks while in debug mode. */
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("<1>%s: bad TAG parameter passed to function\n", __FUNCTION__) ;
return ;
}
if (addr & 0x80)
{
Kern::Printf ("<1>West Bridge write EP address 0x%x out of range\n", addr);
return ;
}
CyAsHalBeagleBoardMcSPI4Ch0_ReadEP(addr, data, size) ;
GPIO::EnableInterrupt(KGPIO_INT) ;
return ;
}
/*
* This function must be defined to write a register within the West Bridge
* device. The addr value is the address of the register to write with
* respect to the base address of the West Bridge device.
*/
void
CyAsHalWriteRegister(CyAsHalDeviceTag tag, uint16_t addr, uint16_t data)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
GPIO::DisableInterrupt(KGPIO_INT) ;
/* Do additional error checks while in debug mode. */
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("<1>%s: bad TAG parameter passed to function\n", __FUNCTION__) ;
return ;
}
if (addr > CYAS_DEV_MAX_ADDR)
{
Kern::Printf ("<1>West Bridge write address 0x%x out of range\n", addr);
return ;
}
CyAsHalBeagleBoardMcSPI4Ch0_WriteReg((TUint32) addr, (TUint16) data) ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAsHalWriteRegister(0x%02x,0x%04x)\n",addr,data) ;
#endif
GPIO::EnableInterrupt(KGPIO_INT) ;
return ;
}
/*
* This function must be defined to read a register from the West Bridge
* device. The addr value is the address of the register to read with
* respect to the base address of the West Bridge device.
*/
uint16_t
CyAsHalReadRegister(CyAsHalDeviceTag tag, uint16_t addr)
{
uint16_t data = 0 ;
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag ;
GPIO::DisableInterrupt(KGPIO_INT) ;
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("<1>%s: bad TAG parameter passed to function\n", __FUNCTION__) ;
return 0 ;
}
if (addr > CYAS_DEV_MAX_ADDR)
{
Kern::Printf("<1>West Bridge read address 0x%x out of range\n", addr) ;
return 0 ;
}
CyAsHalBeagleBoardMcSPI4Ch0_ReadReg((TUint32) addr, (TUint16*) &data) ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAsHalReadRegister(0x%02x,0x%04x)\n",addr,data) ;
#endif
GPIO::EnableInterrupt(KGPIO_INT) ;
return data ;
}
static void
CyServiceEPDmaReadRequest(CyAsOmapDevKernel *dev_p, uint8_t ep)
{
CyAsHalDeviceTag tag = (CyAsHalDeviceTag)dev_p ;
uint16_t v ;
uint32_t size ;
uint16_t addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ;
uint8_t *dptr = (uint8_t*)EndPoints[ep].data_p ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyServiceEPDmaReadRequest...");
#endif
/* Read the amount of data available */
v = CyAsHalReadRegister(tag, addr) ;
size = v & CY_AS_MEM_P0_EPn_DMA_REG_COUNT_MASK ;
CyAsHalReadEP(tag, ep, dptr, size) ;
/*
* Now, reset the DMAVAL bit indicating that the data has been read
*/
CyAsHalWriteRegister(tag, addr, 0) ;
EndPoints[ep].pending = CyFalse ;
EndPoints[ep].type = CyAsHalNone ;
EndPoints[ep].buffer_valid = CyFalse ;
if (callback)
callback(tag, ep, size, CY_AS_ERROR_SUCCESS) ;
}
static void
CyServiceEPDmaWriteRequest(CyAsOmapDevKernel *dev_p, uint8_t ep)
{
CyAsHalDeviceTag tag = (CyAsHalDeviceTag)dev_p ;
uint16_t addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ;
uint8_t *dptr = (uint8_t *)EndPoints[ep].data_p ;
uint32_t size ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyServiceEPDmaWriteRequest...");
#endif
if ( ep == CYASSTORAGE_WRITE_EP_NUM )
{
if ( EndPoints[ep].size == 0x180 )
{
size = 0x180 ;
}
else
size = 0x200 ;
}
else
size = EndPoints[ep].size ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("Service DMA write request EP%d, size=%d, ep.size=%d\n",ep,size,EndPoints[ep].size);
#endif
#if 1
CyAsHalWriteEP(tag, ep, dptr, size) ;
#else
{
uint16_t v ;
int i ;
for(i = 0 ; i < size / 2 ; i++)
{
v = dptr[0] | (dptr[1] << 8) ;
CyAsHalWriteRegister(tag, ep, v) ;
dptr++ ;
dptr++ ;
}
}
#endif
/*
* Now, write the DMAVAL bit to indicate we are done transferring data and that the data
* can now be sent via USB to the USB host, sent to storage, or used internally.
*/
CyAsHalWriteRegister(tag, addr, size) ;
/* We have sent the data, mark it as false */
EndPoints[ep].pending = CyFalse ;
EndPoints[ep].type = CyAsHalNone ;
EndPoints[ep].buffer_valid = CyFalse ;
/*
* Finally, tell the USB subsystem that the data is gone and we can accept the
* next request if one exists.
*/
if (callback)
callback(tag, ep, size, CY_AS_ERROR_SUCCESS) ;
}
static void
CyHandleDRQInterrupt(CyAsOmapDevKernel *dev_p)
{
uint16_t v ;
static uint8_t service_ep = 2 ;
static CyBool indrq = CyFalse ;
/*Kern::Printf("<1>DRQ interrupt detected\n") ;*/
if (indrq)
{
#ifndef NDEBUG
Kern::Printf("<1>+++++++++ Nested DRQ interrupt detected\n") ;
v = CyAsHalReadRegister((CyAsHalDeviceTag)dev_p, CY_AS_MEM_P0_INTR_REG) ;
Kern::Printf("<1>+++++++++ INTR_REG = %04x\n",v) ;
v = CyAsHalReadRegister((CyAsHalDeviceTag)dev_p, CY_AS_MEM_P0_DRQ) ;
Kern::Printf("<1>+++++++++ DRQ_REG = %04x\n",v) ;
#endif
return ;
}
indrq = CyTrue ;
/*
* We have received a DMA interrupt
*/
v = CyAsHalReadRegister((CyAsHalDeviceTag)dev_p, CY_AS_MEM_P0_DRQ) ;
if (v == 0)
{
#ifndef NDEBUG
/*Stray DRQ is possible because we will check DRQ register before exit handler*/
Kern::Printf("<1>+++++++++ Stray DRQ interrupt detected\n") ;
#endif
indrq = CyFalse;
return ;
}
/*
* Now, pick a given DMA request to handle, for now, we just go round robin. Each bit
* position in the service_mask represents an endpoint from EP2 to EP15. We rotate through
* each of the endpoints to find one that needs to be serviced.
*/
while ((v & (1 << service_ep)) == 0)
{
if (service_ep == 15)
service_ep = 2 ;
else
service_ep++ ;
}
if ((v & (1 << service_ep)) == 0)
{
Kern::Printf("<1>+++++++++ Internal error, this should not happen\n") ;
indrq = CyFalse;
return ;
}
if (EndPoints[service_ep].type == CyAsHalWrite)
CyServiceEPDmaWriteRequest(dev_p, service_ep) ;
else if (EndPoints[service_ep].type == CyAsHalRead)
CyServiceEPDmaReadRequest(dev_p, service_ep) ;
#ifndef NDEBUG
else
{
Kern::Printf("+++++++ Interrupt occurred, but there is no DMA operation pending - check DRQ_MASK logic\n") ;
}
#endif
/* Now bump the EP ahead, so other endpoints get a shot before the one we just serviced */
if (EndPoints[service_ep].type == CyAsHalNone)
{
if (service_ep == 15)
service_ep = 2 ;
else
service_ep++ ;
}
indrq = CyFalse ;
}
void
CyAsHalDmaCancelRequest(CyAsHalDeviceTag tag, uint8_t ep)
{
if (EndPoints[ep].pending)
CyAsHalWriteRegister(tag, CY_AS_MEM_P0_EP2_DMA_REG + ep - 2, 0) ;
EndPoints[ep].buffer_valid = CyFalse ;
}
/*
* This function must be defined to transfer a block of data to the West Bridge device. This
* function can use the burst write (DMA) capabilities of West Bridge to do this, or it can
* just copy the data using writes.
*/
void
CyAsHalDmaSetupWrite(CyAsHalDeviceTag tag, uint8_t ep, void *buf, uint32_t size, uint16_t maxsize)
{
uint32_t addr ;
uint16_t v ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAsHalDmaSetupWrite (%d,%d)",size,maxsize);
#endif
/* No EP0 or EP1 traffic should get here */
CyAsHalAssert(ep != 0 && ep != 1) ;
/*
* If this asserts, we have an ordering problem. Another DMA request is coming down
* before the previous one has completed.
*/
CyAsHalAssert(EndPoints[ep].buffer_valid == CyFalse) ;
/*
* Store the data for the interrupt service routine
*/
EndPoints[ep].buffer_valid = CyTrue ;
EndPoints[ep].data_p = (uint16_t*)buf ;
EndPoints[ep].size = size ;
EndPoints[ep].type = CyAsHalWrite ;
/*
* Tell West Bridge we are ready to send data on the given endpoint
*/
{
addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ;
v = (size & CY_AS_MEM_P0_EPn_DMA_REG_COUNT_MASK) | CY_AS_MEM_P0_EPn_DMA_REG_DMAVAL ;
}
CyAsHalWriteRegister(tag, addr, v) ;
}
/*
* This function must be defined to transfer a block of data from the West Bridge device. This
* function can use the burst read (DMA) capabilities of West Bridge to do this, or it can just
* copy the data using reads.
*/
void
CyAsHalDmaSetupRead(CyAsHalDeviceTag tag, uint8_t ep, void *buf, uint32_t size, uint16_t maxsize)
{
uint32_t addr ;
uint16_t v ;
#ifdef SPI_DEBUG_LOG
Kern::Printf("CyAsHalDmaSetupRead (%d,%d)",size,maxsize);
#endif
/* No EP0 or EP1 traffic should get here */
CyAsHalAssert(ep != 0 && ep != 1) ;
CyAsHalAssert(EndPoints[ep].buffer_valid == CyFalse) ;
EndPoints[ep].buffer_valid = CyTrue ;
EndPoints[ep].data_p = (uint16_t*)buf ;
EndPoints[ep].size = size ;
EndPoints[ep].type = CyAsHalRead ;
/*
* Program the EP DMA register for Storage endpoints only.
*/
if (ep == 2)
{
if (size == 1)
size = 2 ;
addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ;
v = (size & CY_AS_MEM_P0_EPn_DMA_REG_COUNT_MASK) | CY_AS_MEM_P0_EPn_DMA_REG_DMAVAL;
CyAsHalWriteRegister(tag, addr, v );
}
else if (ep == CYASSTORAGE_READ_EP_NUM)
{
addr = CY_AS_MEM_P0_EP8_DMA_REG ;
/* This transfer is always done in 512 byte chunks. */
v = 0x200 | CY_AS_MEM_P0_EPn_DMA_REG_DMAVAL ;
CyAsHalWriteRegister(tag, addr, v) ;
}
}
/*
* This function must be defined to allow the West Bridge API to register a callback function that is
* called when a DMA transfer is complete.
*/
void
CyAsHalDmaRegisterCallback(CyAsHalDeviceTag tag, CyAsHalDmaCompleteCallback cb)
{
callback = cb ;
}
/*
* This function must be defined to return the maximum size of DMA request that can be handled
* on the given endpoint. The return value should be the maximum size in bytes that the DMA
* module can handle.
*/
uint32_t
CyAsHalDmaMaxRequestSize(CyAsHalDeviceTag tag, CyAsEndPointNumber_t ep)
{
/* Storage reads and writes are always done in 512 byte blocks. So, we do the count
handling within the HAL, and save on some of the data transfer delay.
*/
if ((ep == CYASSTORAGE_READ_EP_NUM) || (ep == CYASSTORAGE_WRITE_EP_NUM))
return CYASSTORAGE_MAX_XFER_SIZE;
else
/*
* For the USB - Processor endpoints, the maximum transfer size depends on
* the speed of USB operation. So, we use the following constant to
* indicate to the API that splitting of the data into chunks less than
* or equal to the max transfer size should be handled internally.
*/
return CY_AS_DMA_MAX_SIZE_HW_SIZE;
}
/*
* This function must be defined to set the state of the WAKEUP pin on the West Bridge device. Generally
* this is done via a GPIO of some type.
*/
CyBool
CyAsHalSetWakeupPin(CyAsHalDeviceTag tag, CyBool state)
{
/* Not supported as of now. */
return CyFalse ;
}
void
CyAsHalPllLockLossHandler(CyAsHalDeviceTag tag)
{
Kern::Printf("Error: West Bridge PLL has lost lock\n") ;
Kern::Printf("Please check the input voltage levels and clock, and restart the system\n") ;
}
#define CYASHAL_REGISTERS_TO_SAVE_COUNT (12)
static uint16_t gAstoriaRegCache[CYASHAL_REGISTERS_TO_SAVE_COUNT][2] = {
{CY_AS_MEM_P0_ENDIAN, 0x0000},
{CY_AS_MEM_PMU_UPDATE, 0x0000},
{CY_AS_MEM_P0_VM_SET, 0x0000},
{CY_AS_MEM_P0_INT_MASK_REG, 0x0000},
{CY_AS_MEM_P0_RSE_ALLOCATE, 0x0000},
{CY_AS_MEM_P0_RSE_MASK, 0x0000},
{CY_AS_MEM_P0_DRQ_MASK, 0x0000},
{CY_AS_MEM_IROS_SLB_DATARET, 0x0000},
{CY_AS_MEM_IROS_IO_CFG, 0x0000},
{CY_AS_MEM_IROS_PLL_CFG, 0x0000},
{CY_AS_MEM_IROS_PXB_DATARET, 0x0000},
{CY_AS_MEM_IROS_SLEEP_CFG, 0x0000}
};
void
CyAsHalReadRegsBeforeStandby (
CyAsHalDeviceTag tag)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag;
int i, pos;
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("%s: bad TAG parameter passed to function\n", __FUNCTION__);
return;
}
{
for (i = 0; i < CYASHAL_REGISTERS_TO_SAVE_COUNT; i++)
{
gAstoriaRegCache[i][1] = CyAsHalReadRegister (tag, gAstoriaRegCache[i][0]);
/* Special handling required for the RSE_ALLOCATE register, so as to
ensure that the SD_IO pin ownership is set correctly.
*/
if (gAstoriaRegCache[i][0] == CY_AS_MEM_P0_RSE_ALLOCATE)
{
/* For each of the 4 two bits fields in the register, set it to 'b01 if the
* resource is currently allocated to the P port, and 'b10 if it is currently
* allocated to Astoria.
*/
for (pos = 0; pos < 8; pos+= 2)
{
if (((gAstoriaRegCache[i][1] >> pos) & 0x03) == 0x03)
gAstoriaRegCache[i][1] = (gAstoriaRegCache[i][1] & (0xFF ^ (0x03 << pos))) | (0x01 << pos);
else
gAstoriaRegCache[i][1] = (gAstoriaRegCache[i][1] & (0xFF ^ (0x03 << pos))) | (0x02 << pos);
}
}
}
}
}
void
CyAsHalRestoreRegsAfterStandby (
CyAsHalDeviceTag tag)
{
CyAsOmapDevKernel *dev_p = (CyAsOmapDevKernel *)tag;
int i;
if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG)
{
Kern::Printf("%s: bad TAG parameter passed to function\n", __FUNCTION__);
return;
}
{
/* Write 0xFF into the mask register so that all fields can be updated.
The mask will get updated to its proper value later.
*/
CyAsHalWriteRegister (tag, CY_AS_MEM_P0_RSE_MASK, 0xFF);
for (i = 0; i < CYASHAL_REGISTERS_TO_SAVE_COUNT; i++)
{
CyAsHalWriteRegister (tag, gAstoriaRegCache[i][0], gAstoriaRegCache[i][1]);
}
}
}
void
CyAsHalInitDevRegisters(
CyAsHalDeviceTag tag,
CyBool is_standby_wakeup)
{
(void)tag;
(void)is_standby_wakeup;
Kern::Printf("CyAsHalInitDevRegisters...");
return ;
}
void
CyAsHalPrintMessage2(const char* msg)
{
Kern::Printf("%s",msg);
}
/*************************************************************************************************
*
* Below are the functions that must be defined to provide the basic operating system services
* required by the API.
*
*************************************************************************************************/
/*
* This function is required by the API to allocate memory. This function is expected to work
* exactly like malloc().
*/
void *
CyAsHalAlloc(uint32_t cnt)
{
void *ret_p ;
/*ret_p = kmalloc(cnt, GFP_KERNEL) ;*/
ret_p = (void*) new TUint8[cnt];
return ret_p ;
}
/*
* This function is required by the API to free memory allocated with CyAsHalAlloc(). This function is
* expected to work exacly like free().
*/
void
CyAsHalFree(void *mem_p)
{
delete [] (mem_p) ;
}
/*
* Allocator that can be used in interrupt context. We have to ensure that the kmalloc
* call does not sleep in this case.
*/
void *
CyAsHalCBAlloc(uint32_t cnt)
{
void *ret_p ;
/* TODO:
ret_p = kmalloc(cnt, GFP_ATOMIC) ;*/
ret_p = (void*) new TUint8[cnt];
return ret_p ;
}
/*
* This function is required to set a block of memory to a specific value. This function is
* expected to work exactly like memset()
*/
void
CyAsHalMemSet(void *ptr, uint8_t value, uint32_t cnt)
{
/*uint32_t i ;
uint8_t* b = (uint8_t*) ptr ;
for ( i = 0 ; i < cnt ; i++ )
*b = value ;
TODO: */
memset(ptr, value, cnt) ;
}
/*
* This function is expected to create a sleep channel. The data structure that represents the
* sleep channel is given by the pointer in the argument.
*/
CyBool
CyAsHalCreateSleepChannel(CyAsHalSleepChannel *channel)
{
/* TODO:
init_waitqueue_head(&channel->wq) ;
return CyTrue ;*/
if (channel)
channel->wq = 0 ;
return CyTrue ;
}
/*
* This function is expected to destroy a sleep channel. The data structure that represents the
* sleep channel is given by the pointer in the argument.
*/
CyBool
CyAsHalDestroySleepChannel(CyAsHalSleepChannel *channel)
{
/* TODO:
return CyTrue ;*/
channel->wq =1 ;
return CyTrue ;
}
CyBool
CyAsHalSleepOn(CyAsHalSleepChannel *channel, uint32_t ms)
{
/* TODO:
interruptible_sleep_on_timeout (&channel->wq, (ms * HZ/1000)) ;
return CyTrue ;*/
NKern::Sleep(ms);
return CyTrue;
}
CyBool
CyAsHalWake(CyAsHalSleepChannel *channel)
{
/* TODO:
wake_up (&channel->wq) ;
return CyTrue ;*/
channel->wq = 1 ;
return CyTrue ;
}
uint32_t
CyAsHalDisableInterrupts()
{
uint16_t v = CyAsHalReadRegister(gDevTag,CY_AS_MEM_P0_INT_MASK_REG);
if ( !Intr_Disabled )
{
CyAsHalWriteRegister(gDevTag,CY_AS_MEM_P0_INT_MASK_REG,0);
}
Intr_Disabled++ ;
return (uint32_t)v ;
}
void
CyAsHalEnableInterrupts(uint32_t val)
{
Intr_Disabled-- ;
if ( !Intr_Disabled )
{
val = CYAS_INT_MASK | CYAS_DRQ_MASK ;
CyAsHalWriteRegister(gDevTag,CY_AS_MEM_P0_INT_MASK_REG,(uint16_t)val);
/*CyAsHalWriteRegister(gDevTag,CY_AS_MEM_P0_INT_MASK_REG,0x1800);*/
}
}
void
CyAsHalSleep150 (void) /* Sleep atleast 150ns */
{
uint32_t i, j;
j = 0;
for (i = 0; i < 100; i++)
j += (~i);
}
int j = 0;
void
CyAsHalSleep(uint32_t ms)
{
int i;
while (ms--)
{
i = 60000;
while (i--)
{
j += ((i * ~i) + 3 * i + 79);
}
}
}
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
int gInitComplete = 0 ;
/*
* This callback function is called for events from the MISC module. The primary event
* processed by this function is the CyAsEventMiscInitialized which is sent once the
* West Bridge device is initialized and ready to accept requests.
*/
static void
CyMiscCallback(CyAsDeviceHandle h, CyAsMiscEventType evtype, void *evdata)
{
(void)h ;
(void)evdata ;
switch(evtype)
{
case CyAsEventMiscInitialized:
Kern::Printf("Firmware initialized");
gInitComplete = CyTrue ;
break ;
default:
break ;
}
}
int
CyAsHalAstoriaInit(void)
{
uint32_t ret = 0 ;
char* pgm = "Beagleboard HAL";
CyAsDeviceHandle dev_handle ;
CyAsDeviceConfig config ;
CyAsHalDeviceTag tag ;
if (!StartOMAPKernel(pgm, &tag, CyFalse))
{
#ifndef HW_TEST
Kern::Printf("ERROR: Cannot start OMAPKernel\n") ;
#endif
return 1 ;
}
/*
* Create a handle to a West Bridge device. It tag is used to identifiy the specific hardware
* we are talking to.
*/
Kern::Printf("** Create API device\n") ;
ret = CyAsMiscCreateDevice(&dev_handle, tag) ;
if (ret != CY_AS_ERROR_SUCCESS)
{
Kern::Printf("%s: cannot initailize the West Bridge API - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** API device created\n") ;
/*
* Configure the physical bus so we can talk to the West Bridge device. This is the first required
* API call after creating a device.
*/
Kern::Printf("** API device configuring...\n");
memset(&config, 0, sizeof(config)) ;
ret = CyAsMiscConfigureDevice(dev_handle, &config) ;
if (ret != CY_AS_ERROR_SUCCESS)
{
Kern::Printf("%s: cannot configure the West Bridge device - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** API device configured\n") ;
/*
* Register a callback to process events from the MISC module.
*/
Kern::Printf("** Register Callback...\n") ;
ret = CyAsMiscRegisterCallback(dev_handle, CyMiscCallback) ;
if (ret != CY_AS_ERROR_SUCCESS)
{
Kern::Printf("%s: cannot configure the West Bridge device - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** Register Callback done\n") ;
/*
* Download the firmware to the device. Until the firmware has been downloaded, the West Bridge
* device cannot response to requests from the P port processor.
*/
Kern::Printf("** Download firmware...\n") ;
#ifdef FIRMWARE_NOPPORT
#ifdef OVERCLOCK_SD
ret = CyAsMiscDownloadFirmware(dev_handle, CyAnFirmware.fw_image,
(uint16_t)CYANFW_SIZE, 0, 0) ;
#else
ret = CyAsMiscDownloadFirmware(dev_handle, cyastfw_sd_mmc_rel_nopport_array.fw_image,
(uint16_t)CYASTFW_SD_MMC_REL_NOPPORT_SIZE, 0, 0) ;
#endif
#else
#ifdef OVERCLOCK_SD
ret = CyAsMiscDownloadFirmware(dev_handle, CyAnFirmware.fw_image,
(uint16_t)CYANFW_SIZE, 0, 0) ;
#else
ret = CyAsMiscDownloadFirmware(dev_handle, cyastfw_sd_mmc_rel_silicon_array.fw_image,
(uint16_t)CYASTFW_SD_MMC_REL_SILICON_SIZE, 0, 0) ;
#endif
#endif
if (ret != CY_AS_ERROR_SUCCESS)
{
Kern::Printf("%s: cannot download the antioch firmware - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** API device loaded firmware\n") ;
/*
* Note, if a firmware image is not provided, the firmware can still be loaded if the West Bridge device
* is in DEBUG mode. In debug mode, the firmware can be loaded via USB. In general however, the firmware
* should be loaded via the P Port and therefore a firmware file name should be provided.
*/
/*
* Wait for the initialization event telling me that the firmware
* has completed initialization and is ready to go. The sleep of 100 ms
* is used to insure that we do not burn too many CPU cycles while waiting on
* the firmware initialization to finish.
*/
#ifndef FIRMWARE_NOPPORT
while (!gInitComplete)
{
NKern::Sleep(1000);
}
Kern::Printf("Firmware donwloaded successfully!!") ;
#if 0
#ifdef STORAGE_TEST
ret = CyAsSymbianStorageTest("Symbian WB Test",dev_handle, tag);
if ( !ret )
{
Kern::Printf("%s: CyAsSymbianStorageTest failed - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** CyAsSymbianStorageTest done\n") ;
#else
ret = CyAsAPIUsbInit("Symbian WB Test",dev_handle, tag);
if ( !ret )
{
Kern::Printf("%s: CyAsAPIUsbInit failed - code %d\n", pgm, ret) ;
return 1 ;
}
Kern::Printf("** CyAsAPIUsbInit done\n") ;
#endif
#endif
#endif
ret = CyAsAPIGetHandle(dev_handle, tag);
Kern::Printf("** CyAsAPIGetHandle done\n") ;
return 0 ;
}
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
#else
/*
* Some compilers do not like empty C files, so if the OMAP hal is not being
* compiled, we compile this single function. We do this so that for a given target
* HAL there are not multiple sources for the HAL functions.
*/
void MyOMAPKernelHalDummyFunction(
void)
{
}
#endif