📄 wmxscale2wire.c
字号:
/*-----------------------------------------------------------------------------
* Copyright (c) Wolfson Microelectronics plc. All rights reserved.
*
* This software as well as any related documentation is furnished under
* license and may only be used or copied in accordance with the terms of the
* license. The information in this file is furnished for informational use
* only, is subject to change without notice, and should not be construed as
* a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
* assumes no responsibility or liability for any errors or inaccuracies that
* may appear in this document or any software that may be provided in
* association with this document.
*
* Except as permitted by such license, no part of this document may be
* reproduced, stored in a retrieval system, or transmitted in any form or by
* any means without the express written consent of Wolfson Microelectronics plc.
*
* $Id: WMXScale2Wire.c 2326 2005-10-20 08:40:38Z ib $
*
* Functionality for configuring and using XScale I2C controller.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
*---------------------------------------------------------------------------*/
/*
* Include files
*/
#include "WMCommon.h"
#include "WMDevice.h"
#include "WMControlLink.h"
#include "WMPlatformDeviceContext.h"
#include "WMPlatform2Wire.h"
#include "Test/WMTestCommon.h"
#include "Test/WMInternalTests.h"
#if XLLP_AVAILABLE
#include <xllp_clkmgr.h>
#endif /* XLLP_AVAILABLE */
#if WM_I2S
/*
* Global definitions
*/
#define WRITE_TIMEOUT 65535
/*
* Function prototypes
*/
static WMSTATUS private_2WireWriteByte( WM_DEVICE_HANDLE hDevice,
unsigned char value,
WM_BOOL isStart,
WM_BOOL isEnd
);
/*-----------------------------------------------------------------------------
* Function: WMPlatform2WireInit
*
* Initialise the XScale I2C controller.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatform2WireInit( WM_DEVICE_HANDLE hDevice )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status;
/*
* Check our internals code.
*/
WMTEST_RUN( WMTestPlatformInternals( hDevice ) );
/*
* Enable the I2C Clock.
*/
pDeviceContext->v_pClkRegs->cken |= XLLP_CLKEN_I2C;
if ( ! ( pDeviceContext->v_pClkRegs->cken & XLLP_CLKEN_I2C ) )
{
WM_TRACE( hDevice, ( "WMPlatform2WireInit: Could not enable I2C clock" ));
status = WMS_CODEC_NOT_READY;
goto error0;
}
/*
* Set up the I2C GPIOs.
*/
pDeviceContext->v_pGPIORegs->GPDR3 |= XLLP_GPIO_BIT_SCL;
pDeviceContext->v_pGPIORegs->GPDR3 &= ~XLLP_GPIO_BIT_SDA;
pDeviceContext->v_pGPIORegs->GAFR3_U |= XLLP_GPIO_AF_BIT_SCL |
XLLP_GPIO_AF_BIT_SDA;
/*
* Setup the I2C slave address with a dummy value to check that
* it's working.
*/
pDeviceContext->v_pI2CRegs->ISAR = 0;
if ( 0 != pDeviceContext->v_pI2CRegs->ISAR )
{
WM_TRACE( hDevice, ( "WMPlatform2WireInit: Could not enable I2C controller" ));
status = WMS_CODEC_NOT_READY;
goto error0;
}
/*
* Enable the I2C interface and make it master the clock.
*/
pDeviceContext->v_pI2CRegs->ICR = XLLP_ICR_UIE | XLLP_ICR_SCLEA;
/*
* Try to read the device ID to make sure we can talk to the codec.
*/
status = WMInitDeviceId( hDevice );
if ( WMS_UNSUPPORTED == status )
{
WM_REGVAL regVal = 0xFFFF;
/*
* If reading the device ID is unsupported, it's probably a write-only
* codec. Try writing to a nonexistent register
* (WM_I2S_INIT_TEST_REGISTER) to see if we get a response to that.
* Note - We are assuming that all our 2 wire devices do not have
* register WM_I2S_INIT_TEST_REGISTER.
*
* - For Write-only devices: All reads MUST use cached values,
* so we are allowed to do the read below.
*
* - WM_I2S_INIT_TEST_REGISTER is used because a write to set the
* device's register back to its original value would cause
* a real register in the generic drivers to have non-default
* value as the default values are unknown.
*/
/*
* Attempt to read back the original value [in case the register exists]
* so that we can write it back again.
*/
status = WMRead( hDevice, WM_I2S_INIT_TEST_REGISTER, ®Val );
if ( WM_ERROR( status ) )
{
/* Make sure we've got a value for regVal */
regVal = 0xFFFF;
}
status = WMWrite( hDevice, WM_I2S_INIT_TEST_REGISTER, regVal );
}
if ( WM_ERROR( status ) && WMS_UNSUPPORTED != status )
{
/*
* If both the above failed, assume we can't talk to the device.
*/
WM_TRACE( hDevice, ( "WMPlatform2WireInit: no response from codec" ));
status = WMS_CODEC_NOT_READY;
goto error1;
}
/*
* It worked.
*/
pDeviceContext->flags |= DEVICE_INITIALISED;
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error1:
WMPlatform2WireShutdown( hDevice );
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMPlatform2WireShutdown
*
* Shutdown the XScale I2C controller.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*
*---------------------------------------------------------------------------*/
void WMPlatform2WireShutdown( WM_DEVICE_HANDLE hDevice )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
/*
* Disable the I2C interface.
*/
pDeviceContext->v_pI2CRegs->ICR &= ~ ( XLLP_ICR_UIE | XLLP_ICR_SCLEA );
/*
* Disable the I2C Clock.
*/
pDeviceContext->v_pClkRegs->cken &= ~XLLP_CLKEN_I2C;
}
/*-----------------------------------------------------------------------------
* Function: WMPlatform2WireWrite
*
* Writes some bytes to the device across the 2-wire interface.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* address 2-wire device address
* data data to write
* length data length in bytes
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatform2WireWrite( WM_DEVICE_HANDLE hDevice,
unsigned char address,
unsigned char *data,
unsigned int length
)
{
WMSTATUS status;
unsigned int byte;
/*
* Send the address.
*/
status = private_2WireWriteByte( hDevice,
address,
TRUE, /* start */
(0 == length) /* end */
);
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Now send each byte.
*/
for ( byte = 0; byte < length; byte++ )
{
WM_BOOL isEnd = (length-1 == byte);
status = private_2WireWriteByte( hDevice,
data[byte],
FALSE, /* start */
isEnd /* end */
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* We're done.
*/
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_2WireWriteByte
*
* Writes a byte to the device across the 2-wire interface.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* value byte to write
* isStart if this is the first byte of the write
* isEnd if this is the last byte of the write
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
static WMSTATUS private_2WireWriteByte( WM_DEVICE_HANDLE hDevice,
unsigned char value,
WM_BOOL isStart,
WM_BOOL isEnd
)
{
WMSTATUS status;
int icr;
int timeout = 0;
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
if ( isStart )
{
/*
* We're master so set slave address to 0.
*/
pDeviceContext->v_pI2CRegs->ISAR = 0x0;
/*
* Make sure everything's clear before we start.
*/
pDeviceContext->v_pI2CRegs->ICR = 0;
}
/*
* Prepare the byte value.
*/
pDeviceContext->v_pI2CRegs->IDBR = value;
/*
* And do the write.
*/
icr = XLLP_ICR_UIE | XLLP_ICR_SCLEA | XLLP_ICR_TB;
if ( isStart )
icr |= XLLP_ICR_START;
else
icr &= ~XLLP_ICR_START;
if ( isEnd )
icr |= XLLP_ICR_STOP;
else
icr &= ~XLLP_ICR_STOP;
pDeviceContext->v_pI2CRegs->ICR = icr;
/*
* Wait for it to finish.
*/
while ( !( pDeviceContext->v_pI2CRegs->ISR & XLLP_ISR_ITE ) )
{
if ( WRITE_TIMEOUT < ++timeout )
{
status = WMS_DATA_TIMED_OUT;
goto error;
}
}
/*
* And clear the transmit-end flag.
*/
pDeviceContext->v_pI2CRegs->ISR |= XLLP_ISR_ITE;
/*
* We're done.
*/
return WMS_SUCCESS;
error:
return status;
}
#endif /* WM_I2S */
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -