[PATCH] PPC4xx: Add support for multiple I2C busses

This patch adds support for multiple I2C busses on the PPC4xx
platforms. Define CONFIG_I2C_MULTI_BUS in the board config file
to make use of this feature.

It also merges the 405 and 440 i2c header files into one common
file 4xx_i2c.h.

Also the 4xx i2c reset procedure is reworked since I experienced
some problems with the first access on the 440SPe Katmai board.

Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
Stefan Roese 2007-02-20 10:27:08 +01:00
parent 7372ca6822
commit 79b2d0bb2e
11 changed files with 381 additions and 361 deletions

View File

@ -23,7 +23,7 @@
#include <common.h>
#include <asm/processor.h>
#include <405gp_i2c.h>
#include <4xx_i2c.h>
#include <command.h>
#include <rtc.h>
#include <post.h>

View File

@ -25,7 +25,7 @@
#include "du405.h"
#include <asm/processor.h>
#include <ppc4xx.h>
#include <405gp_i2c.h>
#include <4xx_i2c.h>
#include <command.h>
DECLARE_GLOBAL_DATA_PTR;

View File

@ -48,7 +48,7 @@ int testdram (void)
#include <common.h>
#include <asm/processor.h>
#include <405gp_i2c.h>
#include <4xx_i2c.h>
DECLARE_GLOBAL_DATA_PTR;

View File

@ -65,7 +65,7 @@
#include <common.h>
#include "mip405.h"
#include <asm/processor.h>
#include <405gp_i2c.h>
#include <4xx_i2c.h>
#include <miiphy.h>
#include "../common/common_util.h"
#include <i2c.h>

View File

@ -27,13 +27,8 @@
*/
#include <common.h>
#include <ppc4xx.h>
#if defined(CONFIG_440)
# include <440_i2c.h>
#else
# include <405gp_i2c.h>
#endif
#include <4xx_i2c.h>
#include <i2c.h>
#include <440_i2c.h>
#include <command.h>
#include "ppc440gx_i2c.h"

View File

@ -27,11 +27,7 @@
*/
#include <common.h>
#include <ppc4xx.h>
#if defined(CONFIG_440)
# include <440_i2c.h>
#else
# include <405gp_i2c.h>
#endif
#include <4xx_i2c.h>
#include <i2c.h>
#ifdef CONFIG_HARD_I2C

View File

@ -1,91 +1,100 @@
/*****************************************************************************/
/* I2C Bus interface initialisation and I2C Commands */
/* for PPC405GP */
/* Author : AS HARNOIS */
/* Date : 13.Dec.00 */
/*****************************************************************************/
/*
* (C) Copyright 2007
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* based on work by Anne Sophie Harnois <anne-sophie.harnois@nextream.fr>
*
* (C) Copyright 2001
* Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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 program is distributed in the hope that 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
*/
#include <common.h>
#include <ppc4xx.h>
#if defined(CONFIG_440)
# include <440_i2c.h>
#else
# include <405gp_i2c.h>
#endif
#include <4xx_i2c.h>
#include <i2c.h>
#include <asm-ppc/io.h>
#ifdef CONFIG_HARD_I2C
DECLARE_GLOBAL_DATA_PTR;
#define IIC_OK 0
#define IIC_NOK 1
#define IIC_NOK_LA 2 /* Lost arbitration */
#define IIC_NOK_ICT 3 /* Incomplete transfer */
#define IIC_NOK_XFRA 4 /* Transfer aborted */
#define IIC_NOK_DATA 5 /* No data in buffer */
#define IIC_NOK_TOUT 6 /* Transfer timeout */
#if defined(CONFIG_I2C_MULTI_BUS)
/* Initialize the bus pointer to whatever one the SPD EEPROM is on.
* Default is bus 0. This is necessary because the DDR initialization
* runs from ROM, and we can't switch buses because we can't modify
* the global variables.
*/
#ifdef CFG_SPD_BUS_NUM
static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = CFG_SPD_BUS_NUM;
#else
static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0;
#endif
#endif /* CONFIG_I2C_MULTI_BUS */
#define IIC_TIMEOUT 1 /* 1 seconde */
static void _i2c_bus_reset (void)
static void _i2c_bus_reset(void)
{
int i, status;
int i;
u8 dc;
/* Reset status register */
/* write 1 in SCMP and IRQA to clear these fields */
out8 (IIC_STS, 0x0A);
out_8((u8 *)IIC_STS, 0x0A);
/* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */
out8 (IIC_EXTSTS, 0x8F);
__asm__ volatile ("eieio");
out_8((u8 *)IIC_EXTSTS, 0x8F);
/*
* Get current state, reset bus
* only if no transfers are pending.
*/
i = 10;
do {
/* Get status */
status = in8 (IIC_STS);
udelay (500); /* 500us */
i--;
} while ((status & IIC_STS_PT) && (i > 0));
/* Soft reset controller */
status = in8 (IIC_XTCNTLSS);
out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST));
__asm__ volatile ("eieio");
/* Place chip in the reset state */
out_8((u8 *)IIC_XTCNTLSS, IIC_XTCNTLSS_SRST);
/* make sure where in initial state, data hi, clock hi */
out8 (IIC_DIRECTCNTL, 0xC);
for (i = 0; i < 10; i++) {
if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) {
/* clock until we get to known state */
out8 (IIC_DIRECTCNTL, 0x8); /* clock lo */
udelay (100); /* 100us */
out8 (IIC_DIRECTCNTL, 0xC); /* clock hi */
udelay (100); /* 100us */
} else {
break;
/* Check if bus is free */
dc = in_8((u8 *)IIC_DIRECTCNTL);
if (!DIRCTNL_FREE(dc)){
/* Try to set bus free state */
out_8((u8 *)IIC_DIRECTCNTL, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC);
/* Wait until we regain bus control */
for (i = 0; i < 100; ++i) {
dc = in_8((u8 *)IIC_DIRECTCNTL);
if (DIRCTNL_FREE(dc))
break;
/* Toggle SCL line */
dc ^= IIC_DIRCNTL_SCC;
out_8((u8 *)IIC_DIRECTCNTL, dc);
udelay(10);
dc ^= IIC_DIRCNTL_SCC;
out_8((u8 *)IIC_DIRECTCNTL, dc);
}
}
/* send start condition */
out8 (IIC_DIRECTCNTL, 0x4);
udelay (1000); /* 1ms */
/* send stop condition */
out8 (IIC_DIRECTCNTL, 0xC);
udelay (1000); /* 1ms */
/* Unreset controller */
out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST));
udelay (1000); /* 1ms */
/* Remove reset */
out_8((u8 *)IIC_XTCNTLSS, 0);
}
void i2c_init (int speed, int slaveadd)
void i2c_init(int speed, int slaveadd)
{
sys_info_t sysInfo;
unsigned long freqOPB;
int val, divisor;
int bus;
#ifdef CFG_I2C_INIT_BOARD
/* call board specific i2c bus reset routine before accessing the */
@ -94,101 +103,100 @@ void i2c_init (int speed, int slaveadd)
i2c_init_board();
#endif
/* Handle possible failed I2C state */
/* FIXME: put this into i2c_init_board()? */
_i2c_bus_reset ();
for (bus = 0; bus < CFG_MAX_I2C_BUS; bus++) {
I2C_SET_BUS(bus);
/* clear lo master address */
out8 (IIC_LMADR, 0);
/* Handle possible failed I2C state */
/* FIXME: put this into i2c_init_board()? */
_i2c_bus_reset();
/* clear hi master address */
out8 (IIC_HMADR, 0);
/* clear lo master address */
out_8((u8 *)IIC_LMADR, 0);
/* clear lo slave address */
out8 (IIC_LSADR, 0);
/* clear hi master address */
out_8((u8 *)IIC_HMADR, 0);
/* clear hi slave address */
out8 (IIC_HSADR, 0);
/* clear lo slave address */
out_8((u8 *)IIC_LSADR, 0);
/* Clock divide Register */
/* get OPB frequency */
get_sys_info (&sysInfo);
freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
/* set divisor according to freqOPB */
divisor = (freqOPB - 1) / 10000000;
if (divisor == 0)
divisor = 1;
out8 (IIC_CLKDIV, divisor);
/* clear hi slave address */
out_8((u8 *)IIC_HSADR, 0);
/* no interrupts */
out8 (IIC_INTRMSK, 0);
/* Clock divide Register */
/* get OPB frequency */
get_sys_info(&sysInfo);
freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv;
/* set divisor according to freqOPB */
divisor = (freqOPB - 1) / 10000000;
if (divisor == 0)
divisor = 1;
out_8((u8 *)IIC_CLKDIV, divisor);
/* clear transfer count */
out8 (IIC_XFRCNT, 0);
/* no interrupts */
out_8((u8 *)IIC_INTRMSK, 0);
/* clear extended control & stat */
/* write 1 in SRC SRS SWC SWS to clear these fields */
out8 (IIC_XTCNTLSS, 0xF0);
/* clear transfer count */
out_8((u8 *)IIC_XFRCNT, 0);
/* Mode Control Register
Flush Slave/Master data buffer */
out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
__asm__ volatile ("eieio");
/* clear extended control & stat */
/* write 1 in SRC SRS SWC SWS to clear these fields */
out_8((u8 *)IIC_XTCNTLSS, 0xF0);
/* Mode Control Register
Flush Slave/Master data buffer */
out_8((u8 *)IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
val = in8(IIC_MDCNTL);
__asm__ volatile ("eieio");
val = in_8((u8 *)IIC_MDCNTL);
/* Ignore General Call, slave transfers are ignored,
disable interrupts, exit unknown bus state, enable hold
SCL
100kHz normaly or FastMode for 400kHz and above
*/
/* Ignore General Call, slave transfers are ignored,
* disable interrupts, exit unknown bus state, enable hold
* SCL 100kHz normaly or FastMode for 400kHz and above
*/
val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
if( speed >= 400000 ){
val |= IIC_MDCNTL_FSM;
val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
if (speed >= 400000)
val |= IIC_MDCNTL_FSM;
out_8((u8 *)IIC_MDCNTL, val);
/* clear control reg */
out_8((u8 *)IIC_CNTL, 0x00);
}
out8 (IIC_MDCNTL, val);
/* clear control reg */
out8 (IIC_CNTL, 0x00);
__asm__ volatile ("eieio");
/* set to SPD bus as default bus upon powerup */
I2C_SET_BUS(CFG_SPD_BUS_NUM);
}
/*
This code tries to use the features of the 405GP i2c
controller. It will transfer up to 4 bytes in one pass
on the loop. It only does out8(lbz) to the buffer when it
is possible to do out16(lhz) transfers.
cmd_type is 0 for write 1 for read.
addr_len can take any value from 0-255, it is only limited
by the char, we could make it larger if needed. If it is
0 we skip the address write cycle.
Typical case is a Write of an addr followd by a Read. The
IBM FAQ does not cover this. On the last byte of the write
we don't set the creg CHT bit, and on the first bytes of the
read we set the RPST bit.
It does not support address only transfers, there must be
a data part. If you want to write the address yourself, put
it in the data pointer.
It does not support transfer to/from address 0.
It does not check XFRCNT.
*/
static
int i2c_transfer(unsigned char cmd_type,
unsigned char chip,
unsigned char addr[],
unsigned char addr_len,
unsigned char data[],
unsigned short data_len )
* This code tries to use the features of the 405GP i2c
* controller. It will transfer up to 4 bytes in one pass
* on the loop. It only does out_8((u8 *)lbz) to the buffer when it
* is possible to do out16(lhz) transfers.
*
* cmd_type is 0 for write 1 for read.
*
* addr_len can take any value from 0-255, it is only limited
* by the char, we could make it larger if needed. If it is
* 0 we skip the address write cycle.
*
* Typical case is a Write of an addr followd by a Read. The
* IBM FAQ does not cover this. On the last byte of the write
* we don't set the creg CHT bit, and on the first bytes of the
* read we set the RPST bit.
*
* It does not support address only transfers, there must be
* a data part. If you want to write the address yourself, put
* it in the data pointer.
*
* It does not support transfer to/from address 0.
*
* It does not check XFRCNT.
*/
static int i2c_transfer(unsigned char cmd_type,
unsigned char chip,
unsigned char addr[],
unsigned char addr_len,
unsigned char data[],
unsigned short data_len)
{
unsigned char* ptr;
int reading;
@ -198,97 +206,88 @@ int i2c_transfer(unsigned char cmd_type,
int i;
uchar creg;
if( data == 0 || data_len == 0 ){
/*Don't support data transfer of no length or to address 0*/
if (data == 0 || data_len == 0) {
/* Don't support data transfer of no length or to address 0 */
printf( "i2c_transfer: bad call\n" );
return IIC_NOK;
}
if( addr && addr_len ){
if (addr && addr_len) {
ptr = addr;
cnt = addr_len;
reading = 0;
}else{
} else {
ptr = data;
cnt = data_len;
reading = cmd_type;
}
/*Clear Stop Complete Bit*/
out8(IIC_STS,IIC_STS_SCMP);
/* Clear Stop Complete Bit */
out_8((u8 *)IIC_STS, IIC_STS_SCMP);
/* Check init */
i=10;
i = 10;
do {
/* Get status */
status = in8(IIC_STS);
__asm__ volatile("eieio");
status = in_8((u8 *)IIC_STS);
i--;
} while ((status & IIC_STS_PT) && (i>0));
} while ((status & IIC_STS_PT) && (i > 0));
if (status & IIC_STS_PT) {
result = IIC_NOK_TOUT;
return(result);
}
/*flush the Master/Slave Databuffers*/
out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
/*need to wait 4 OPB clocks? code below should take that long*/
/* flush the Master/Slave Databuffers */
out_8((u8 *)IIC_MDCNTL, ((in_8((u8 *)IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
/* need to wait 4 OPB clocks? code below should take that long */
/* 7-bit adressing */
out8(IIC_HMADR,0);
out8(IIC_LMADR, chip);
__asm__ volatile("eieio");
out_8((u8 *)IIC_HMADR, 0);
out_8((u8 *)IIC_LMADR, chip);
tran = 0;
result = IIC_OK;
creg = 0;
while ( tran != cnt && (result == IIC_OK)) {
while (tran != cnt && (result == IIC_OK)) {
int bc,j;
/* Control register =
Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
Transfer is a sequence of transfers
*/
* Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
* Transfer is a sequence of transfers
*/
creg |= IIC_CNTL_PT;
bc = (cnt - tran) > 4 ? 4 :
cnt - tran;
creg |= (bc-1)<<4;
/* if the real cmd type is write continue trans*/
if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
bc = (cnt - tran) > 4 ? 4 : cnt - tran;
creg |= (bc - 1) << 4;
/* if the real cmd type is write continue trans */
if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt))
creg |= IIC_CNTL_CHT;
if (reading)
creg |= IIC_CNTL_READ;
else {
for(j=0; j<bc; j++) {
else
for(j=0; j < bc; j++)
/* Set buffer */
out8(IIC_MDBUF,ptr[tran+j]);
__asm__ volatile("eieio");
}
}
out8(IIC_CNTL, creg );
__asm__ volatile("eieio");
out_8((u8 *)IIC_MDBUF, ptr[tran+j]);
out_8((u8 *)IIC_CNTL, creg);
/* Transfer is in progress
we have to wait for upto 5 bytes of data
1 byte chip address+r/w bit then bc bytes
of data.
udelay(10) is 1 bit time at 100khz
Doubled for slop. 20 is too small.
*/
i=2*5*8;
* we have to wait for upto 5 bytes of data
* 1 byte chip address+r/w bit then bc bytes
* of data.
* udelay(10) is 1 bit time at 100khz
* Doubled for slop. 20 is too small.
*/
i = 2*5*8;
do {
/* Get status */
status = in8(IIC_STS);
__asm__ volatile("eieio");
udelay (10);
status = in_8((u8 *)IIC_STS);
udelay(10);
i--;
} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
&& (i>0));
} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i > 0));
if (status & IIC_STS_ERR) {
result = IIC_NOK;
status = in8 (IIC_EXTSTS);
status = in_8((u8 *)IIC_EXTSTS);
/* Lost arbitration? */
if (status & IIC_EXTSTS_LA)
result = IIC_NOK_LA;
@ -306,34 +305,32 @@ int i2c_transfer(unsigned char cmd_type,
/* Are there data in buffer */
if (status & IIC_STS_MDBS) {
/*
even if we have data we have to wait 4OPB clocks
for it to hit the front of the FIFO, after that
we can just read. We should check XFCNT here and
if the FIFO is full there is no need to wait.
*/
udelay (1);
for(j=0;j<bc;j++) {
ptr[tran+j] = in8(IIC_MDBUF);
__asm__ volatile("eieio");
}
* even if we have data we have to wait 4OPB clocks
* for it to hit the front of the FIFO, after that
* we can just read. We should check XFCNT here and
* if the FIFO is full there is no need to wait.
*/
udelay(1);
for (j=0; j<bc; j++)
ptr[tran+j] = in_8((u8 *)IIC_MDBUF);
} else
result = IIC_NOK_DATA;
}
creg = 0;
tran+=bc;
if( ptr == addr && tran == cnt ) {
tran += bc;
if (ptr == addr && tran == cnt) {
ptr = data;
cnt = data_len;
tran = 0;
reading = cmd_type;
if( reading )
if (reading)
creg = IIC_CNTL_RPST;
}
}
return (result);
}
int i2c_probe (uchar chip)
int i2c_probe(uchar chip)
{
uchar buf[1];
@ -344,21 +341,21 @@ int i2c_probe (uchar chip)
* address was <ACK>ed (i.e. there was a chip at that address which
* drove the data line low).
*/
return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0);
return (i2c_transfer(1, chip << 1, 0,0, buf, 1) != 0);
}
int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)
{
uchar xaddr[4];
int ret;
if ( alen > 4 ) {
if (alen > 4) {
printf ("I2C read: addr len %d not supported\n", alen);
return 1;
}
if ( alen > 0 ) {
if (alen > 0) {
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
@ -378,10 +375,10 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address.
*/
if( alen > 0 )
if (alen > 0)
chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
#endif
if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
if ((ret = i2c_transfer(1, chip<<1, &xaddr[4-alen], alen, buffer, len)) != 0) {
if (gd->have_console)
printf( "I2c read: failed %d\n", ret);
return 1;
@ -389,16 +386,17 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
return 0;
}
int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len)
{
uchar xaddr[4];
if ( alen > 4 ) {
if (alen > 4) {
printf ("I2C write: addr len %d not supported\n", alen);
return 1;
}
if ( alen > 0 ) {
if (alen > 0) {
xaddr[0] = (addr >> 24) & 0xFF;
xaddr[1] = (addr >> 16) & 0xFF;
xaddr[2] = (addr >> 8) & 0xFF;
@ -417,11 +415,11 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
* still be one byte because the extra address bits are
* hidden in the chip address.
*/
if( alen > 0 )
if (alen > 0)
chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
#endif
return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
return (i2c_transfer(0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
}
/*-----------------------------------------------------------------------
@ -433,7 +431,7 @@ uchar i2c_reg_read(uchar i2c_addr, uchar reg)
i2c_read(i2c_addr, reg, 1, &buf, 1);
return(buf);
return (buf);
}
/*-----------------------------------------------------------------------
@ -443,4 +441,38 @@ void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)
{
i2c_write(i2c_addr, reg, 1, &val, 1);
}
#if defined(CONFIG_I2C_MULTI_BUS)
/*
* Functions for multiple I2C bus handling
*/
unsigned int i2c_get_bus_num(void)
{
return i2c_bus_num;
}
int i2c_set_bus_num(unsigned int bus)
{
if (bus >= CFG_MAX_I2C_BUS)
return -1;
i2c_bus_num = bus;
return 0;
}
/* TODO: add 100/400k switching */
unsigned int i2c_get_bus_speed(void)
{
return CFG_I2C_SPEED;
}
int i2c_set_bus_speed(unsigned int speed)
{
if (speed != CFG_I2C_SPEED)
return -1;
return 0;
}
#endif /* CONFIG_I2C_MULTI_BUS */
#endif /* CONFIG_HARD_I2C */

View File

@ -1,64 +0,0 @@
#ifndef _405gp_i2c_h_
#define _405gp_i2c_h_
#define I2C_REGISTERS_BASE_ADDRESS 0xEF600500
#define IIC_MDBUF (I2C_REGISTERS_BASE_ADDRESS+IICMDBUF)
#define IIC_SDBUF (I2C_REGISTERS_BASE_ADDRESS+IICSDBUF)
#define IIC_LMADR (I2C_REGISTERS_BASE_ADDRESS+IICLMADR)
#define IIC_HMADR (I2C_REGISTERS_BASE_ADDRESS+IICHMADR)
#define IIC_CNTL (I2C_REGISTERS_BASE_ADDRESS+IICCNTL)
#define IIC_MDCNTL (I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL)
#define IIC_STS (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
#define IIC_EXTSTS (I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS)
#define IIC_LSADR (I2C_REGISTERS_BASE_ADDRESS+IICLSADR)
#define IIC_HSADR (I2C_REGISTERS_BASE_ADDRESS+IICHSADR)
#define IIC_CLKDIV (I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV)
#define IIC_INTRMSK (I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK)
#define IIC_XFRCNT (I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT)
#define IIC_XTCNTLSS (I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS)
#define IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL)
/* MDCNTL Register Bit definition */
#define IIC_MDCNTL_HSCL 0x01
#define IIC_MDCNTL_EUBS 0x02
#define IIC_MDCNTL_EINT 0x04
#define IIC_MDCNTL_ESM 0x08
#define IIC_MDCNTL_FSM 0x10
#define IIC_MDCNTL_EGC 0x20
#define IIC_MDCNTL_FMDB 0x40
#define IIC_MDCNTL_FSDB 0x80
/* CNTL Register Bit definition */
#define IIC_CNTL_PT 0x01
#define IIC_CNTL_READ 0x02
#define IIC_CNTL_CHT 0x04
#define IIC_CNTL_RPST 0x08
/* bit 2/3 for Transfer count*/
#define IIC_CNTL_AMD 0x40
#define IIC_CNTL_HMT 0x80
/* STS Register Bit definition */
#define IIC_STS_PT 0X01
#define IIC_STS_IRQA 0x02
#define IIC_STS_ERR 0X04
#define IIC_STS_SCMP 0x08
#define IIC_STS_MDBF 0x10
#define IIC_STS_MDBS 0X20
#define IIC_STS_SLPR 0x40
#define IIC_STS_SSS 0x80
/* EXTSTS Register Bit definition */
#define IIC_EXTSTS_XFRA 0X01
#define IIC_EXTSTS_ICT 0X02
#define IIC_EXTSTS_LA 0X04
/* XTCNTLSS Register Bit definition */
#define IIC_XTCNTLSS_SRST 0x01
#define IIC_XTCNTLSS_EPI 0x02
#define IIC_XTCNTLSS_SDBF 0x04
#define IIC_XTCNTLSS_SBDD 0x08
#define IIC_XTCNTLSS_SWS 0x10
#define IIC_XTCNTLSS_SWC 0x20
#define IIC_XTCNTLSS_SRS 0x40
#define IIC_XTCNTLSS_SRC 0x80
#endif

View File

@ -1,71 +0,0 @@
#ifndef _440_i2c_h_
#define _440_i2c_h_
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
#define I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000700)
#else
#define I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000400)
#endif /*CONFIG_440EP CONFIG_440GR*/
#define I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR
#define IIC_MDBUF (I2C_REGISTERS_BASE_ADDRESS+IICMDBUF)
#define IIC_SDBUF (I2C_REGISTERS_BASE_ADDRESS+IICSDBUF)
#define IIC_LMADR (I2C_REGISTERS_BASE_ADDRESS+IICLMADR)
#define IIC_HMADR (I2C_REGISTERS_BASE_ADDRESS+IICHMADR)
#define IIC_CNTL (I2C_REGISTERS_BASE_ADDRESS+IICCNTL)
#define IIC_MDCNTL (I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL)
#define IIC_STS (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
#define IIC_EXTSTS (I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS)
#define IIC_LSADR (I2C_REGISTERS_BASE_ADDRESS+IICLSADR)
#define IIC_HSADR (I2C_REGISTERS_BASE_ADDRESS+IICHSADR)
#define IIC_CLKDIV (I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV)
#define IIC_INTRMSK (I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK)
#define IIC_XFRCNT (I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT)
#define IIC_XTCNTLSS (I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS)
#define IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL)
/* MDCNTL Register Bit definition */
#define IIC_MDCNTL_HSCL 0x01
#define IIC_MDCNTL_EUBS 0x02
#define IIC_MDCNTL_EINT 0x04
#define IIC_MDCNTL_ESM 0x08
#define IIC_MDCNTL_FSM 0x10
#define IIC_MDCNTL_EGC 0x20
#define IIC_MDCNTL_FMDB 0x40
#define IIC_MDCNTL_FSDB 0x80
/* CNTL Register Bit definition */
#define IIC_CNTL_PT 0x01
#define IIC_CNTL_READ 0x02
#define IIC_CNTL_CHT 0x04
#define IIC_CNTL_RPST 0x08
/* bit 2/3 for Transfer count*/
#define IIC_CNTL_AMD 0x40
#define IIC_CNTL_HMT 0x80
/* STS Register Bit definition */
#define IIC_STS_PT 0X01
#define IIC_STS_IRQA 0x02
#define IIC_STS_ERR 0X04
#define IIC_STS_SCMP 0x08
#define IIC_STS_MDBF 0x10
#define IIC_STS_MDBS 0X20
#define IIC_STS_SLPR 0x40
#define IIC_STS_SSS 0x80
/* EXTSTS Register Bit definition */
#define IIC_EXTSTS_XFRA 0X01
#define IIC_EXTSTS_ICT 0X02
#define IIC_EXTSTS_LA 0X04
/* XTCNTLSS Register Bit definition */
#define IIC_XTCNTLSS_SRST 0x01
#define IIC_XTCNTLSS_EPI 0x02
#define IIC_XTCNTLSS_SDBF 0x04
#define IIC_XTCNTLSS_SBDD 0x08
#define IIC_XTCNTLSS_SWS 0x10
#define IIC_XTCNTLSS_SWC 0x20
#define IIC_XTCNTLSS_SRS 0x40
#define IIC_XTCNTLSS_SRC 0x80
#endif

122
include/4xx_i2c.h Normal file
View File

@ -0,0 +1,122 @@
/*
* (C) Copyright 2007
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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 program is distributed in the hope that 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
*/
#ifndef _4xx_i2c_h_
#define _4xx_i2c_h_
#define IIC_OK 0
#define IIC_NOK 1
#define IIC_NOK_LA 2 /* Lost arbitration */
#define IIC_NOK_ICT 3 /* Incomplete transfer */
#define IIC_NOK_XFRA 4 /* Transfer aborted */
#define IIC_NOK_DATA 5 /* No data in buffer */
#define IIC_NOK_TOUT 6 /* Transfer timeout */
#define IIC_TIMEOUT 1 /* 1 second */
#if defined(CONFIG_I2C_MULTI_BUS)
#define I2C_BUS_OFFS (i2c_bus_num * 0x100)
#else
#define I2C_BUS_OFFS (0x000)
#endif /* CONFIG_I2C_MULTI_BUS */
#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
#define I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000700 + I2C_BUS_OFFS)
#elif defined(CONFIG_440)
/* all remaining 440 variants */
#define I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000400 + I2C_BUS_OFFS)
#else
/* all 405 variants */
#define I2C_BASE_ADDR (0xEF600500 + I2C_BUS_OFFS)
#endif
#define I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR
#define IIC_MDBUF (I2C_REGISTERS_BASE_ADDRESS+IICMDBUF)
#define IIC_SDBUF (I2C_REGISTERS_BASE_ADDRESS+IICSDBUF)
#define IIC_LMADR (I2C_REGISTERS_BASE_ADDRESS+IICLMADR)
#define IIC_HMADR (I2C_REGISTERS_BASE_ADDRESS+IICHMADR)
#define IIC_CNTL (I2C_REGISTERS_BASE_ADDRESS+IICCNTL)
#define IIC_MDCNTL (I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL)
#define IIC_STS (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
#define IIC_EXTSTS (I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS)
#define IIC_LSADR (I2C_REGISTERS_BASE_ADDRESS+IICLSADR)
#define IIC_HSADR (I2C_REGISTERS_BASE_ADDRESS+IICHSADR)
#define IIC_CLKDIV (I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV)
#define IIC_INTRMSK (I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK)
#define IIC_XFRCNT (I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT)
#define IIC_XTCNTLSS (I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS)
#define IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL)
/* MDCNTL Register Bit definition */
#define IIC_MDCNTL_HSCL 0x01
#define IIC_MDCNTL_EUBS 0x02
#define IIC_MDCNTL_EINT 0x04
#define IIC_MDCNTL_ESM 0x08
#define IIC_MDCNTL_FSM 0x10
#define IIC_MDCNTL_EGC 0x20
#define IIC_MDCNTL_FMDB 0x40
#define IIC_MDCNTL_FSDB 0x80
/* CNTL Register Bit definition */
#define IIC_CNTL_PT 0x01
#define IIC_CNTL_READ 0x02
#define IIC_CNTL_CHT 0x04
#define IIC_CNTL_RPST 0x08
/* bit 2/3 for Transfer count*/
#define IIC_CNTL_AMD 0x40
#define IIC_CNTL_HMT 0x80
/* STS Register Bit definition */
#define IIC_STS_PT 0x01
#define IIC_STS_IRQA 0x02
#define IIC_STS_ERR 0x04
#define IIC_STS_SCMP 0x08
#define IIC_STS_MDBF 0x10
#define IIC_STS_MDBS 0x20
#define IIC_STS_SLPR 0x40
#define IIC_STS_SSS 0x80
/* EXTSTS Register Bit definition */
#define IIC_EXTSTS_XFRA 0x01
#define IIC_EXTSTS_ICT 0x02
#define IIC_EXTSTS_LA 0x04
/* XTCNTLSS Register Bit definition */
#define IIC_XTCNTLSS_SRST 0x01
#define IIC_XTCNTLSS_EPI 0x02
#define IIC_XTCNTLSS_SDBF 0x04
#define IIC_XTCNTLSS_SBDD 0x08
#define IIC_XTCNTLSS_SWS 0x10
#define IIC_XTCNTLSS_SWC 0x20
#define IIC_XTCNTLSS_SRS 0x40
#define IIC_XTCNTLSS_SRC 0x80
/* IICx_DIRECTCNTL register */
#define IIC_DIRCNTL_SDAC 0x08
#define IIC_DIRCNTL_SCC 0x04
#define IIC_DIRCNTL_MSDA 0x02
#define IIC_DIRCNTL_MSC 0x01
#define DIRCTNL_FREE(v) (((v) & 0x0f) == 0x0f)
#endif

View File

@ -46,6 +46,16 @@
*/
#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */
#if defined(CONFIG_I2C_MULTI_BUS)
#define CFG_MAX_I2C_BUS 2
#define I2C_GET_BUS() i2c_get_bus_num()
#define I2C_SET_BUS(a) i2c_set_bus_num(a)
#else
#define CFG_MAX_I2C_BUS 1
#define I2C_GET_BUS() 0
#define I2C_SET_BUS(a)
#endif
/*
* Initialization, must be called once on start up, may be called
* repeatedly to change the speed and slave addresses.