/* --------------------------------------------------------------------
**
** Synopsys DesignWare DW_apb_i2c Software Driver Kit and
** documentation (hereinafter, "Software") is an Unsupported
** proprietary work of Synopsys, Inc. unless otherwise expressly
** agreed to in writing between Synopsys and you.
**
** The Software IS NOT an item of Licensed Software or Licensed
** Product under any End User Software License Agreement or Agreement
** for Licensed Product with Synopsys or any supplement thereto. You
** are permitted to use and redistribute this Software in source and
** binary forms, with or without modification, provided that
** redistributions of source code must retain this notice. You may not
** view, use, disclose, copy or distribute this file or any information
** contained herein except pursuant to this license grant from Synopsys.
** If you do not agree with this notice, including the disclaimer
** below, then you are not authorized to use the Software.
**
** THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
** BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
** SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
** OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
** DAMAGE.
**
** --------------------------------------------------------------------
*/
#include "DW_common.h" // common header for all drivers
#include "DW_apb_i2c_public.h" // DW_apb_i2c public header
#include "DW_apb_i2c_private.h" // DW_apb_i2c private header
// This definition is used by the assetion macros to determine the
// current file name. It is defined in the DW_common_dbc.h header.
DW_DEFINE_THIS_FILE;
/**********************************************************************/
int dw_i2c_init(struct dw_device *dev)
{
int retval;
I2C_COMMON_REQUIREMENTS(dev);
// disable device
retval = dw_i2c_disable(dev);
// if device is not busy (i.e. it is now disabled)
if(retval == 0) {
// disable all interrupts
dw_i2c_maskIrq(dev, I2c_irq_all);
dw_i2c_clearIrq(dev, I2c_irq_all);
// reset instance variables
dw_i2c_resetInstance(dev);
// autoConfigure component parameters if possible
retval = dw_i2c_autoCompParams(dev);
}
return retval;
}
/**********************************************************************/
void dw_i2c_enable(struct dw_device *dev)
{
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
reg = 0;
DW_BIT_SET(reg, I2C_ENABLE_ENABLE, 0x1);
I2C_OUTP(reg, portmap->enable);
}
/**********************************************************************/
int dw_i2c_disable(struct dw_device *dev)
{
int retval;
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
if(dw_i2c_isBusy(dev) == false) {
reg = retval = 0;
DW_BIT_SET(reg, I2C_ENABLE_ENABLE, 0);
I2C_OUTP(reg, portmap->enable);
}
else
retval = -DW_EBUSY;
return retval;
}
/**********************************************************************/
bool dw_i2c_isEnabled(struct dw_device *dev)
{
bool retval;
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
reg = I2C_INP(portmap->enable);
retval = (bool) DW_BIT_GET(reg, I2C_ENABLE_ENABLE);
return retval;
}
/**********************************************************************/
bool dw_i2c_isBusy(struct dw_device *dev)
{
bool retval;
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
reg = I2C_INP(portmap->status);
if(DW_BIT_GET(reg, I2C_STATUS_ACTIVITY) == 0x0)
retval = false;
else
retval = true;
return retval;
}
/**********************************************************************/
int dw_i2c_setSpeedMode(struct dw_device *dev, enum dw_i2c_speed_mode
mode)
{
int retval;
uint32_t reg;
struct dw_i2c_param *param;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
param = (struct dw_i2c_param *) dev->comp_param;
portmap = (struct dw_i2c_portmap *) dev->base_address;
if(mode > param->max_speed_mode)
retval = -DW_ENOSYS;
else if(dw_i2c_isEnabled(dev) == false) {
retval = 0;
reg = I2C_INP(portmap->con);
// avoid bus write if possible
if(DW_BIT_GET(reg, I2C_CON_SPEED) != mode) {
DW_BIT_SET(reg, I2C_CON_SPEED, mode);
I2C_OUTP(reg, portmap->con);
}
}
else
retval = -DW_EPERM;
return retval;
}
/**********************************************************************/
enum dw_i2c_speed_mode dw_i2c_getSpeedMode(struct dw_device *dev)
{
uint32_t reg;
enum dw_i2c_speed_mode retval;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
reg = I2C_INP(portmap->con);
retval = (enum dw_i2c_speed_mode) DW_BIT_GET(reg, I2C_CON_SPEED);
return retval;
}
/**********************************************************************/
int dw_i2c_setMasterAddressMode(struct dw_device *dev, enum
dw_i2c_address_mode mode)
{
int retval;
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
if(dw_i2c_isEnabled(dev) == false) {
retval = 0;
reg = I2C_INP(portmap->con);
if(DW_BIT_GET(reg, I2C_CON_10BITADDR_MASTER) != mode) {
DW_BIT_SET(reg, I2C_CON_10BITADDR_MASTER, mode);
I2C_OUTP(reg, portmap->con);
}
}
else
retval = -DW_EPERM;
return retval;
}
/**********************************************************************/
enum dw_i2c_address_mode dw_i2c_getMasterAddressMode(struct dw_device
*dev)
{
uint32_t reg;
enum dw_i2c_address_mode retval;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
reg = I2C_INP(portmap->con);
retval = (enum dw_i2c_address_mode) DW_BIT_GET(reg,
I2C_CON_10BITADDR_MASTER);
return retval;
}
/**********************************************************************/
int dw_i2c_setSlaveAddressMode(struct dw_device *dev, enum
dw_i2c_address_mode mode)
{
int retval;
uint32_t reg;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (struct dw_i2c_portmap *) dev->base_address;
if(dw_i2c_isEnabled(dev) == false) {
retval = 0;
reg = I2C_INP(portmap->con);
// avoid bus write if possible
if(DW_BIT_GET(reg, I2C_CON_10BITADDR_SLAVE) != mode) {
DW_BIT_SET(reg, I2C_CON_10BITADDR_SLAVE, mode);
I2C_OUTP(reg, portmap->con);
}
}
else
retval = -DW_EPERM;
return retval;
}
/**********************************************************************/
enum dw_i2c_address_mode dw_i2c_getSlaveAddressMode(struct dw_device
*dev)
{
uint32_t reg;
enum dw_i2c_address_mode retval;
struct dw_i2c_portmap *portmap;
I2C_COMMON_REQUIREMENTS(dev);
portmap = (
- 1
- 2
前往页