rockbox/firmware/target/mips/ingenic_jz47xx/i2c-jz4740.c

249 lines
5.2 KiB
C
Raw Normal View History

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Maurus Cuelenaere
*
* based on linux/arch/mips/jz4740/i2c.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "jz4740.h"
#include "logf.h"
/*
* Jz4740 I2C routines.
*
* Copyright (C) 2005,2006 Ingenic Semiconductor Inc.
* Author: <lhhuang@ingenic.cn>
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
*/
/* I2C protocol */
#define I2C_READ 1
#define I2C_WRITE 0
#define TIMEOUT 1000
/*
* I2C bus protocol basic routines
*/
static int i2c_put_data(unsigned char data)
{
unsigned int timeout = TIMEOUT*10;
__i2c_write(data);
__i2c_set_drf();
while (__i2c_check_drf() != 0);
while (!__i2c_transmit_ended());
while (!__i2c_received_ack() && timeout)
timeout--;
if (timeout)
return 0;
else
return -1;
}
#if 0
static int i2c_put_data_nack(unsigned char data)
{
unsigned int timeout = TIMEOUT*10;
__i2c_write(data);
__i2c_set_drf();
while (__i2c_check_drf() != 0);
while (!__i2c_transmit_ended());
while (timeout--);
return 0;
}
#endif
static int i2c_get_data(unsigned char *data, int ack)
{
int timeout = TIMEOUT*10;
if (!ack)
__i2c_send_nack();
else
__i2c_send_ack();
while (__i2c_check_drf() == 0 && timeout)
timeout--;
if (timeout)
{
if (!ack)
__i2c_send_stop();
*data = __i2c_read();
__i2c_clear_drf();
return 0;
}
else
return -1;
}
void i2c_setclk(unsigned int i2cclk)
{
__i2c_set_clk(__cpm_get_i2sclk(), i2cclk);
}
/*
* I2C interface
*/
static void i2c_open(void)
{
i2c_setclk(10000); /* default 10 KHz */
__i2c_enable();
}
static void i2c_close(void)
{
udelay(300); /* wait for STOP goes over. */
__i2c_disable();
}
int i2c_read(int device, unsigned char *buf, int count)
{
int cnt = count;
int timeout = 5;
device &= 0xFF;
i2c_open();
L_try_again:
if (timeout < 0)
goto L_timeout;
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
__i2c_send_start();
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
goto device_err;
__i2c_send_ack(); /* Master sends ACK for continue reading */
while (cnt)
{
if (cnt == 1)
{
if (i2c_get_data(buf, 0) < 0)
break;
}
else
{
if (i2c_get_data(buf, 1) < 0)
break;
}
cnt--;
buf++;
}
__i2c_send_stop();
return count - cnt;
device_err:
timeout--;
__i2c_send_stop();
goto L_try_again;
L_timeout:
__i2c_send_stop();
logf("Read I2C device 0x%2x failed.", device);
i2c_close();
return -1;
}
int i2c_write(int device, unsigned char *buf, int count)
{
int cnt = count;
int timeout = 5;
device &= 0xFF;
i2c_open();
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
W_try_again:
if (timeout < 0)
goto W_timeout;
cnt = count;
__i2c_send_start();
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
goto device_err;
#if 0 //CONFIG_JZ_TPANEL_ATA2508
if (address == 0xff)
{
while (cnt)
{
if (i2c_put_data_nack(*buf) < 0)
break;
cnt--;
buf++;
}
}
else
#endif
{
while (cnt)
{
if (i2c_put_data(*buf) < 0)
break;
cnt--;
buf++;
}
}
__i2c_send_stop();
return count - cnt;
device_err:
timeout--;
__i2c_send_stop();
goto W_try_again;
W_timeout:
logf("Write I2C device 0x%2x failed.", device);
__i2c_send_stop();
i2c_close();
return -1;
}
void i2c_init(void)
{
__gpio_as_i2c();
}