RTEMS and I2C APIs

Joel Sherrill joel.sherrill at oarcorp.com
Fri Jul 27 17:01:13 UTC 2007


Till Straumann wrote:
> Thomas Doerfler wrote:
>> Hi,
>>
>> I found out, that RTEMS actually has two I2C APIs defined.
>>
>> 1.) Till Straumann has implemented a high level API, which resides in
>> "cpukit/libi2c". It seems to be well structured, supports multiple
>> busses and integrates into the filesystem. Some drivers are implemented
>> on top of this API to access an EEPROM and an RTC in 
>> "c/src/libchip/i2c".
>> But: There is no sample driver implementation for the actual low-level
>> I2C driver.
>>
>> 2.) A different API has been implemented by OKTET in
>> "c/src/lib/libbsp/m68k/mcf5206elite/i2c", which is also split into a low
>> level driver and a HW independent layer. This driver has been ported at
>> least to the gen5200 BSP and has at least an RTC driver based on this 
>> API.
>>
>> Now I want to implement another low level I2C interface, which is quite
>> similar to the MCF5206. A decision is needed which API should live on,
>> because I think it is not a good idea to have two APIs for the same
>> thing. From a first glance, the API in cpukit seems to have a better
>> structure, but I would like to get other opinions, and maybe a sample
>> low level driver would help to decide, which way to go.
>>
>> Any opinions?
You are right.  It is time to get to one API.  Without looking at either
API, both were implemented by talented submitters.  Is there anyway
you can unify them?

Technically anything in CPUKIT is "the official API" but there was
never a formal review of the either API or attempt to unify them.

Since you have a real interest in using the unified API, I suggest
that you assume the cpukit one is the official one and migrate
the other code to it.  If there are missing features in the cpukit
one, merge them from the Oktet one.  Do a best effort conversion
on their code so it still compiles.

Serious disclaimer: I know nothing about the technical merits of
either API.  But anything in cpukit has the potential for more
users than something in a BSP.  So by virtue of not being treated
as a cross-platform API, it is unfortunately BSP specific.  Better to
make it conform to the cpukit API and resolve functional differences
where one had a better approach.

That's how I lean but I could be wrong. :)
>>
>> Till: any sample driver available?
>>
>>   
> Essentially, the netbsd driver for the marvell 64240 chip
> (but I made some changes)...
>
This code appears to be BSP specific, right?  So am I
right that there is no reason to consider merging it into libchip.

Plus it has yet another license variation so we would have
to publish that.  No big deal.  Just something else. :)

--joel
> T.
>> wkr,
>> Thomas.
>>
>>
>>   
>
> ------------------------------------------------------------------------
>
> /*	$NetBSD: gti2c.c,v 1.2 2005/02/27 00:27:21 perry Exp $	*/
>
> /*
>  * Copyright (c) 2005 Brocade Communcations, inc.
>  * All rights reserved.
>  *
>  * Written by Matt Thomas for Brocade Communcations, Inc.
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in the
>  *    documentation and/or other materials provided with the distribution.
>  * 3. The name of Brocade Communications, Inc. may not be used to endorse
>  *    or promote products derived from this software without specific prior
>  *    written permission.
>  *
>  * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
>  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>  * ARE DISCLAIMED.  IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. 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.
>  */
>
> /* Fixed many things + ported to RTEMS by Till Straumann, 2005 */
>
> #include <stdio.h>
> #include <rtems.h>
> #include <libcpu/io.h>
> #include <sys/errno.h>
> #include <rtems/bspIo.h>
> #include <rtems/score/sysstate.h>
> #include <bsp/irq.h>
> #include <rtems/libi2c.h>
>
> #include <sys/cdefs.h>
>
> #include <bsp/gtintrreg.h>
> #include <bsp/gti2creg.h>
> #include <bsp/gti2c_busdrv.h>
>
> #define ENABLE_IRQ_AT_PIC_HACK	/* workaround for a bad HW bug */
> #undef  DEBUG
>
> #ifndef BSP_IRQ_MIN_PRIO
> #define BSP_IRQ_MIN_PRIO 1
> #endif
>
> struct gti2c_softc {
> 	uint32_t	sc_gt;
> 	uint32_t	sc_cntl;
> 	int			sc_inited;
> 	rtems_id	sc_sync;
> 	int			sc_irqs; /* statistics */
> };
>
> #ifdef DEBUG
> #define STATIC
> #else
> #define STATIC static
> #endif
>
> typedef struct {
> 	rtems_libi2c_bus_t	bus_desc;	
> 	struct gti2c_softc	pvt;
> } gti2c_desc_rec, *gti2c_desc;
>
> STATIC rtems_status_code
> gt_i2c_init(rtems_libi2c_bus_t *bh);
> STATIC rtems_status_code
> gt_i2c_send_start(rtems_libi2c_bus_t *bh);
> STATIC rtems_status_code
> gt_i2c_send_stop(rtems_libi2c_bus_t *bh);
> STATIC rtems_status_code
> gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw);
> STATIC int
> gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
> STATIC int
> gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
>
> static rtems_libi2c_bus_ops_t myops = {
> 	init:			gt_i2c_init,
> 	send_start:		gt_i2c_send_start,
> 	send_stop:		gt_i2c_send_stop,
> 	send_addr:		gt_i2c_send_addr,
> 	read_bytes:		gt_i2c_read_bytes,
> 	write_bytes:	gt_i2c_write_bytes,
> };
>
> static gti2c_desc_rec my_bus_tbl = {
> 	{
> 		ops:	&myops,
> 		size:	sizeof(my_bus_tbl),
> 	},/* public fields */
> 	{
> 		sc_gt:		BSP_MV64x60_BASE,
> 		sc_cntl:	I2C_Control_TWSIEn,
> 		sc_inited:	0,
> 		sc_sync:	0
> 	} /* our private fields */
> };
>
>
> static inline uint32_t
> gt_read(uint32_t base, uint32_t off)
> {
> 	return in_le32((volatile unsigned*)(base+off));
> }
>
> static inline void
> gt_write(uint32_t base, uint32_t off, uint32_t val)
> {
> 	out_le32((volatile unsigned*)(base+off), val);
> }
>
>
> static inline void
> disable_irq(struct gti2c_softc *sc)
> {
> uint32_t v = gt_read(sc->sc_gt, I2C_REG_Control);
> 	gt_write(sc->sc_gt, I2C_REG_Control, v & ~I2C_Control_IntEn);
> }
>
>
> static rtems_status_code
> gt_i2c_wait(struct gti2c_softc *sc, uint32_t control, uint32_t desired_status)
> {
> 	uint32_t status;
> 	rtems_status_code rval;
>
> 	control |= I2C_Control_IntEn;
>
> 	gt_write(sc->sc_gt, I2C_REG_Control, control | sc->sc_cntl);
>
> 	if ( sc->sc_inited ) {
>
> #ifdef ENABLE_IRQ_AT_PIC_HACK
> 		BSP_enable_irq_at_pic(BSP_IRQ_I2C);
> #endif
>
> 		rval = rtems_semaphore_obtain(sc->sc_sync, RTEMS_WAIT, 100);
>
> 		if ( RTEMS_SUCCESSFUL != rval )
> 			return rval;
> 	} else {
> 		uint32_t then, now;
>
> 		/* run in polling mode - useful during init */
> 		if ( _System_state_Is_up(_System_state_Get()) ) {
> 			printk("WARNING: gti2c running in polled mode -- should initialize properly!\n");
> 		}
>
> 		asm volatile("mftb %0":"=r"(then));
>
> 		do {
> 			asm volatile("mftb %0":"=r"(now));
> 			/* poll timebase for .2 seconds assuming a bus clock of 100MHz */
> 			if ( now - then > (uint32_t)100000000/4/5 )
> 				return RTEMS_TIMEOUT;
> 		} while ( ! (I2C_Control_IFlg & gt_read(sc->sc_gt, I2C_REG_Control)) );
> 	}
>
> 	status = gt_read(sc->sc_gt, I2C_REG_Status);
>
> 	if ( status != desired_status && (status!=I2C_Status_ReStarted || desired_status!=I2C_Status_Started) )
> 		return RTEMS_IO_ERROR;
>
> 	return RTEMS_SUCCESSFUL;
> }
>
> /* the usual suspects */
> static void noop() {}
> static int inoop() {return 1;}
>
> static void
> gt_i2c_intr()
> {
> struct gti2c_softc * const sc = &my_bus_tbl.pvt;
> 	uint32_t v;
>
> 	v = gt_read(sc->sc_gt, I2C_REG_Control);
> 	if ((v & I2C_Control_IFlg) == 0) {
> 		printk("gt_i2c_intr: IRQ but IFlg not set??\n");
> 		return;
> 	}
> 	gt_write(sc->sc_gt, I2C_REG_Control, v & ~(I2C_Control_IntEn));
> #if 0
> 	gt_read(sc->sc_gt, I2C_REG_Control);
> 	asm volatile("sync");
> /* This is how bad it is: after turning off the IntEn bit, the line
>  * still remains asserted! (shame on you.)
>  *
>  * The test below (on MVME6100; the MVME5500 has the same problem
>  * but the main cause register address is different; substitute
>  * 0xf100000c for 0xf1000c68 on a 5500).
>  * 
>  * The skew was 101 TB ticks or ~3us (bus freq 133MHz) which
>  * really sucks.
>  *
>  * Therefore, we must disable the interrupt at the PIC 
>  */
> {unsigned from,to;
> 	asm volatile("mftb %0":"=r"(from));
> 	while ( in_le32((volatile unsigned*)0xf100000c) & 0x20 )
> 		;
> 	asm volatile("mftb %0":"=r"(to));
> 	printk("I2C IRQ remained asserted for %i TB ticks!\n",to-from);
> }
> #endif
> #ifdef ENABLE_IRQ_AT_PIC_HACK
> 	BSP_disable_irq_at_pic(BSP_IRQ_I2C);
> #endif
>
> 	sc->sc_irqs++;
>
> 	rtems_semaphore_release(sc->sc_sync);
> }
>
> STATIC rtems_status_code
> gt_i2c_init(rtems_libi2c_bus_t *bh)
> {
> struct gti2c_softc * const	sc = &((gti2c_desc)bh)->pvt;
> unsigned					m,n,N;
>
> 	disable_irq(sc);
>
> 	/* reset */
> 	gt_write(sc->sc_gt, I2C_REG_SoftReset, 0);
> 	gt_write(sc->sc_gt, I2C_REG_SlaveAddr, 0);
> 	gt_write(sc->sc_gt, I2C_REG_ExtSlaveAddr, 0);
>
> 	/* Set baud rate; I don't know the details
> 	 * but have to assume that it has to fit into 7 bits
> 	 * (as indicated by some experiment)
> 	 */
> 	n = 0, N=1<<n;
> 	do {
> 		n++, N<<=1;
> 		/* increase 2^n until m becomes small enough */
> 		m = BSP_bus_frequency / 10 / 62500 / N;
> 	} while ( m > 16 );
>
> 	/* n is at least 1 */
> 	if ( n > 8 ) {
> 		n = 8; m = 16;	/* nothing else we can do */
> 	}
> 	if ( 0 == m )
> 		m = 1; /* nothing we can do */
>
> 	gt_write(sc->sc_gt, I2C_REG_BaudRate, I2C_BaudRate(m-1, n-1));
>
> 	if ( !sc->sc_inited ) { 
>
> 		if ( _System_state_Is_up(_System_state_Get()) ) {
> 			rtems_irq_connect_data ii = {
> 				name:	BSP_IRQ_I2C,
> 				hdl:	gt_i2c_intr,
> 				on:		noop,
> 				off:	noop,
> 				isOn:	inoop
> 			};
> 			rtems_status_code err;
> 			/* synchronization semaphore */
> 			err = rtems_semaphore_create(
> 					rtems_build_name('g','i','2','c'),
> 					0, 
> 					RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_LOCAL,
> 					0,
> 					&sc->sc_sync);
> 			if ( err ) {
> 				sc->sc_sync = 0;
> 				return err;
> 			}
> 			if ( !BSP_install_rtems_irq_handler(&ii) ) {
> 				fprintf(stderr,"Unable to install interrupt handler\n");
> 				rtems_semaphore_delete(sc->sc_sync);
> 				return RTEMS_INTERNAL_ERROR;
> 			}
> 			BSP_irq_set_priority(BSP_IRQ_I2C, BSP_IRQ_MIN_PRIO);
> 			sc->sc_inited = 1;
> 		} else {
> 		}
> 	} else {
> 		rtems_semaphore_flush(sc->sc_sync);
> 	}
> 	return RTEMS_SUCCESSFUL;
> }
>
> STATIC rtems_status_code
> gt_i2c_send_start(rtems_libi2c_bus_t *bh)
> {
> struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
>
> 	return gt_i2c_wait(sc, I2C_Control_Start, I2C_Status_Started);
> }
>
> STATIC rtems_status_code
> gt_i2c_send_stop(rtems_libi2c_bus_t *bh)
> {
> struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
> uint32_t	data;
>
> 	data = gt_read(sc->sc_gt, I2C_REG_Status);
> 	if ( I2C_Status_Started == data || I2C_Status_ReStarted == data ) {
> 		/* According to the spec, a void message (start - stop sequence)
> 		 * is illegal and indeed, the chip plays bad tricks with us, i.e.,
> 		 * sometimes it hangs the bus so that it remains idle forever.
> 		 * so we have to address someone...
> 		 */
> 		gt_i2c_send_addr(bh, /*just something... */ 8, 1);
> 		data = gt_read(sc->sc_gt, I2C_REG_Status);
> 	}
>
> 	if ( I2C_Status_AddrReadAck == data ) {
> 		/* Another thing: spec says that the master generates stop only after
> 		 * not acknowledging the last byte. Again, the chip doesn't like
> 		 * to be stopped in this condition - hence we just do it the favor
> 		 * and read a single byte...
> 		 */
> 		gt_i2c_read_bytes(bh, (unsigned char *)&data, 1);
> 	}
>
> 	gt_write(sc->sc_gt, I2C_REG_Control, I2C_Control_Stop | sc->sc_cntl);
>
> 	/* should we poll for idle? There seems to be in IRQ when this completes */
> 	return RTEMS_SUCCESSFUL;
> }
>
> STATIC rtems_status_code
> gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw)
> {
> struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
> uint32_t data, wanted_status;
> uint8_t read_mask = rw ? 1 : 0;
> rtems_status_code error;
>
> 	if (read_mask) {
> 		wanted_status = I2C_Status_AddrReadAck;
> 	} else {
> 		wanted_status = I2C_Status_AddrWriteAck;
> 	}
> 	/*
> 	 * First byte contains whether this xfer is a read or write.
> 	 */
> 	data = read_mask;
> 	if (addr > 0x7f) {
> 		/*
> 		 * If this is a 10bit request, the first address byte is
> 		 * 0b11110<b9><b8><r/w>.
> 		 */
> 		data |= 0xf0 | ((addr & 0x300) >> 7);
> 		gt_write(sc->sc_gt, I2C_REG_Data, data);
> 		error = gt_i2c_wait(sc, 0, wanted_status);
> 		if (error)
> 			return error;
> 		/*
> 		 * The first address byte has been sent, now to send
> 		 * the second one.
> 		 */
> 		if (read_mask) {
> 			wanted_status = I2C_Status_2ndAddrReadAck;
> 		} else {
> 			wanted_status = I2C_Status_2ndAddrWriteAck;
> 		}
> 		data = (uint8_t) addr;
> 	} else {
> 		data |= (addr << 1);
> 	}
>
> 	gt_write(sc->sc_gt, I2C_REG_Data, data);
> 	return gt_i2c_wait(sc, 0, wanted_status);
> }
>
> STATIC int
> gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
> {
> struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
> rtems_status_code error;
> register unsigned char *p=buf;
>
> 	while ( len-- > 0 ) {
> 		error = gt_i2c_wait(
> 					sc,
> 					len ? I2C_Control_ACK : 0,
> 					len ? I2C_Status_MasterReadAck : I2C_Status_MasterReadNoAck);
> 		if ( error ) {
> 			return -error;
> 		}
> 		*p++ = gt_read(sc->sc_gt, I2C_REG_Data);
> 	}
>
> 	return p-buf;
> }
>
> STATIC int
> gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
> {
> struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
> int rval = 0;
> rtems_status_code error;
>
> 	while ( len-- > 0 ) {
> 		gt_write(sc->sc_gt, I2C_REG_Data, buf[rval]);
> 		error = gt_i2c_wait(sc, 0, I2C_Status_MasterWriteAck);
> 		if ( error ) {
> 			return -error;
> 		}
> 		rval++;
> 	}
>
> 	return rval;
> }
>
> rtems_libi2c_bus_t *gt64260_i2c_bus_descriptor = &my_bus_tbl.bus_desc;
>
> #ifdef DEBUG_MODULAR
>
> void
> _cexpModuleInitialize(void *arg)
> {
> 	gt_i2c_init(&gt64260_i2c_bus_descriptor->bus_desc);
> }
>
> int
> _cexpModuleFinalize(void * arg)
> {
> struct gti2c_softc * const sc = &gt64260_i2c_bus_descriptor->pvt;
>
> 	rtems_irq_connect_data ii = {
> 			name:	BSP_IRQ_I2C,
> 			hdl:	gt_i2c_intr,
> 			on:		noop,
> 			off:	noop,
> 			isOn:	inoop
> 	};
>
> 	rtems_semaphore_delete(sc->sc_sync);
>
> 	return !BSP_remove_rtems_irq_handler(&ii);
> }
>
> #endif
>   
> ------------------------------------------------------------------------
>
> #ifndef GT_64260_BUS_DRIVER_H
> #define GT_64260_BUS_DRIVER_H
> /* 
>  * Authorship
>  * ----------
>  * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
>  *     created by Till Straumann <strauman at slac.stanford.edu>, 2005-2007,
>  * 	   Stanford Linear Accelerator Center, Stanford University.
>  * 
>  * Acknowledgement of sponsorship
>  * ------------------------------
>  * The 'beatnik' BSP was produced by
>  *     the Stanford Linear Accelerator Center, Stanford University,
>  * 	   under Contract DE-AC03-76SFO0515 with the Department of Energy.
>  * 
>  * Government disclaimer of liability
>  * ----------------------------------
>  * Neither the United States nor the United States Department of Energy,
>  * nor any of their employees, makes any warranty, express or implied, or
>  * assumes any legal liability or responsibility for the accuracy,
>  * completeness, or usefulness of any data, apparatus, product, or process
>  * disclosed, or represents that its use would not infringe privately owned
>  * rights.
>  * 
>  * Stanford disclaimer of liability
>  * --------------------------------
>  * Stanford University makes no representations or warranties, express or
>  * implied, nor assumes any liability for the use of this software.
>  * 
>  * Stanford disclaimer of copyright
>  * --------------------------------
>  * Stanford University, owner of the copyright, hereby disclaims its
>  * copyright and all other rights in this software.  Hence, anyone may
>  * freely use it for any purpose without restriction.  
>  * 
>  * Maintenance of notices
>  * ----------------------
>  * In the interest of clarity regarding the origin and status of this
>  * SLAC software, this and all the preceding Stanford University notices
>  * are to remain affixed to any copy or derivative of this software made
>  * or distributed by the recipient and are to be affixed to any copy of
>  * software made or distributed by the recipient that contains a copy or
>  * derivative of this software.
>  * 
>  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
>  */ 
>
> #ifdef __cplusplus
>   extern "C" {
> #endif
>
> #include <rtems.h>
> #include <rtems/libi2c.h>
>
> /* for registration with libi2c */
> extern rtems_libi2c_bus_t *gt64260_i2c_bus_descriptor;
>
> #ifdef __cplusplus
>   }
> #endif
>
> #endif
>   
> ------------------------------------------------------------------------
>
> /*	$NetBSD: gti2creg.h,v 1.2 2005/02/27 00:27:21 perry Exp $	*/
>
> /*
>  * Copyright (c) 2005 Brocade Communcations, inc.
>  * All rights reserved.
>  *
>  * Written by Matt Thomas for Brocade Communcations, Inc.
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in the
>  *    documentation and/or other materials provided with the distribution.
>  * 3. The name of Brocade Communications, Inc. may not be used to endorse
>  *    or promote products derived from this software without specific prior
>  *    written permission.
>  *
>  * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
>  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>  * ARE DISCLAIMED.  IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. 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.
>  */
>
> #ifndef _DEV_MARVELL_GTI2CREG_H_
> #define	_DEV_MARVELL_GTI2CREG_H_
>
> #define	I2C_REG_SlaveAddr	0xc000
> #define	I2C_REG_ExtSlaveAddr	0xc010
> #define	I2C_REG_Data		0xc004
> #define	I2C_REG_Control		0xc008
> #define	I2C_REG_Status		0xc00c
> #define	I2C_REG_BaudRate	0xc00c
> #define	I2C_REG_SoftReset	0xc01c
>
> #define	I2C_SlaveAddr_GCE	0x0001	/* Act as Slave */
> #define	I2C_SlaveAddr_SAddr	0x7E
>
> #define	I2C_Control_ACK		0x04
> #define	I2C_Control_IFlg	0x08
> #define	I2C_Control_Stop	0x10
> #define	I2C_Control_Start	0x20
> #define	I2C_Control_TWSIEn	0x40
> #define	I2C_Control_IntEn	0x80
>
> /*
>  * F(I2C) = F(Tclk) / ( 10 * (M + 1) * (2^(N+1)))
>  * For Tclk = 100MHz, M =  4, N = 4: F = 62.5KHz
>  * For Tclk = 100MHz, M = 13, N = 3: F = 96.2KHz
>  */
> #define	I2C_BaudRate(M, N)	(((M) << 3) | (N))
> #define	I2C_BaudRate_62_5K	I2C_BaudRate(4, 4)
> #define	I2C_BaudRate_96_2K	I2C_BaudRate(13, 3)
>
> #define	I2C_Status_BusError	0x00	/* Bus error */
> #define I2C_Status_Started	0x08	/* Start condition xmitted */
> #define	I2C_Status_ReStarted	0x10	/* Repeated start condition xmitted */
> #define	I2C_Status_AddrWriteAck	0x18	/* Adr + wr bit xmtd, ack rcvd */
> #define	I2C_Status_AddrWriteNoAck 0x20	/* Adr + wr bit xmtd, NO ack rcvd */
> #define	I2C_Status_MasterWriteAck 0x28	/* Master xmtd data byte, ack rcvd */
> #define	I2C_Status_MasterWriteNoAck 0x30 /* Master xmtd data byte, NO ack rcvd*/
> #define	I2C_Status_MasterLostArb 0x38	/* Master lost arbitration during
> 					   address or data transfer */
> #define	I2C_Status_AddrReadAck	0x40	/* Adr + rd bit xmtd, ack rcvd */
> #define	I2C_Status_AddrReadNoAck 0x48	/* Adr + rd bit xmtd, NO ack rcvd */
> #define	I2C_Status_MasterReadAck 0x50	/* Master rcvd data bye, ack rcvd */
> #define	I2C_Status_MasterReadNoAck 0x58	/* Master rcvd data bye, NO ack rcvd */
> #define	I2C_Status_2ndAddrWriteAck 0xd0	/* 2nd adr + wr bit xmid, ack rcvd */
> #define	I2C_Status_2ndAddrWriteNoAck 0xd8 /* 2nd adr + wr bit xmid, NO ack rcvd */
> #define	I2C_Status_2ndAddrReadAck 0xe0	/* 2nd adr + rd bit xmid, ack rcvd */
> #define	I2C_Status_2ndAddrReadNoAck 0xe8 /* 2nd adr + rd bit xmtd, NO ack rcvd */
> #define	I2C_Status_Idle		0xf8	/* Idle */
>
> #endif /* _DEV_MARVELL_GTI2CREG_H_ */
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> rtems-users mailing list
> rtems-users at rtems.com
> http://rtems.rtems.org/mailman/listinfo/rtems-users
>   




More information about the users mailing list