added SPI support to libi2c

added IRQ support to MPC83xx i2c driver
added mpc83xx spi driver
This commit is contained in:
Thomas Doerfler
2007-10-25 16:17:56 +00:00
parent 0a23c71433
commit 55a685bddc
16 changed files with 506 additions and 92 deletions
+6
View File
@@ -1,3 +1,9 @@
2007-09-24 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* libchip/i2c/spi-flash-m25p40.c, libchip/i2c/spi-flash-m25p40.c,
* libchip/Makefile.am:
added SPI flash driver for a M25P40 chip (based on libi2c extensions)
2007-09-25 Joel Sherrill <joel.sherrill@OARcorp.com>
* libchip/shmdr/dump.c, libchip/shmdr/shm_driver.h: Fix warnings.
@@ -1,3 +1,11 @@
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* include/bsp.h: fixed some typos
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* Makefile.am, spi/spi_init.c, include/bsp.h: add spi support
2007-09-17 Joel Sherrill <joel.sherrill@OARcorp.com>
* console/console.c, irq/irq_init.c: Eliminate warnings.
+10 -3
View File
@@ -76,7 +76,7 @@ irq_rel_CPPFLAGS = $(AM_CPPFLAGS)
irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += console.rel
console_rel_SOURCES = console/console.c console/ns16550cfg.c
console_rel_SOURCES = console/console.c console/ns16550cfg.c
console_rel_CPPFLAGS = $(AM_CPPFLAGS)
console_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -93,10 +93,16 @@ bsp_i2c_rel_SOURCES = i2c/i2c_init.c
bsp_i2c_rel_CPPFLAGS = $(AM_CPPFLAGS)
bsp_i2c_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_PROGRAMS += bsp_spi.rel
bsp_spi_rel_SOURCES = spi/spi_init.c
bsp_spi_rel_CPPFLAGS = $(AM_CPPFLAGS)
bsp_spi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
noinst_LIBRARIES = libbsp.a
libbsp_a_SOURCES =
libbsp_a_LIBADD = startup.rel pclock.rel console.rel vectors.rel irq.rel \
mpc83xx_regs.rel bsp_i2c.rel
mpc83xx_regs.rel bsp_i2c.rel bsp_spi.rel
libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
../../../libcpu/@RTEMS_CPU@/shared/cache.rel \
../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
@@ -106,7 +112,8 @@ libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
../../../libcpu/@RTEMS_CPU@/mpc6xx/clock.rel \
../../../libcpu/@RTEMS_CPU@/mpc6xx/mmu.rel \
../../../libcpu/@RTEMS_CPU@/mpc6xx/timer.rel \
../../../libcpu/@RTEMS_CPU@/mpc83xx/i2c.rel
../../../libcpu/@RTEMS_CPU@/mpc83xx/i2c.rel \
../../../libcpu/@RTEMS_CPU@/mpc83xx/spi.rel
if HAS_NETWORKING
libbsp_a_LIBADD += network.rel
@@ -73,9 +73,10 @@ rtems_status_code bsp_register_i2c
{
int ret_code;
int i2c1_busno,i2c2_busno;
/*
* init I2C library
* init I2C library (if not already done)
*/
rtems_libi2c_initialize ();
@@ -87,6 +88,7 @@ rtems_status_code bsp_register_i2c
if (ret_code < 0) {
return -ret_code;
}
i2c1_busno = ret_code;
/*
* register second I2C bus
*/
@@ -95,12 +97,13 @@ rtems_status_code bsp_register_i2c
if (ret_code < 0) {
return -ret_code;
}
i2c2_busno = ret_code;
/*
* register EEPROM to bus 1, Address 0x50
*/
ret_code = rtems_libi2c_register_drv(RTEMS_BSP_I2C_EEPROM_DEVICE_NAME,
i2c_2b_eeprom_driver_descriptor,
0,0x50);
i2c1_busno,0x50);
if (ret_code < 0) {
return -ret_code;
}
@@ -239,6 +239,7 @@ extern rtems_configuration_table BSP_Configuration;
void bsp_cleanup(void);
rtems_status_code bsp_register_i2c(void);
rtems_status_code bsp_register_spi(void);
/* console modes (only termios) */
#ifdef PRINTK_MINOR
@@ -280,6 +281,12 @@ extern int BSP_tsec_attach(struct rtems_bsdnet_ifconfig *config,int attaching);
#define RTEMS_BSP_I2C_EEPROM_DEVICE_NAME "eeprom"
#define RTEMS_BSP_I2C_EEPROM_DEVICE_PATH "/dev/i2c1.eeprom"
/*
* SPI Flash device name
*/
#define RTEMS_BSP_SPI_FLASH_DEVICE_NAME "flash"
#define RTEMS_BSP_SPI_FLASH_DEVICE_PATH "/dev/spi.flash"
#ifdef __cplusplus
}
#endif
+21
View File
@@ -1,3 +1,24 @@
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* mpc83xx/network/tsec.c:
fixed typo in comment of attach function
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* Makefile.am, mpc83xx/spi/mpc83xx_spidrv.c,
* mpc83xx/spi/mpc83xx_spidrv.h, mpc83xx/include/mpc83xx.h:
added spi driver
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* mpc83xx/i2c/mpc83xx_i2cdrv.c:
added IRQ support in I2C driver
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* mpc83xx/network/tsec.c:
added statistics counters to tsec
2007-09-12 Joel Sherrill <joel.sherrill@OARcorp.com>
PR 1257/bsps
+8
View File
@@ -348,6 +348,14 @@ mpc83xx_i2c_rel_SOURCES = mpc83xx/i2c/mpc83xx_i2cdrv.c \
mpc83xx_i2c_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc83xx_i2c_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc83xx/spi
include_mpc83xx_HEADERS += mpc83xx/spi/mpc83xx_spidrv.h
noinst_PROGRAMS += mpc83xx/spi.rel
mpc83xx_spi_rel_SOURCES = mpc83xx/spi/mpc83xx_spidrv.c \
mpc83xx/spi/mpc83xx_spidrv.h
mpc83xx_spi_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc83xx_spi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
include $(srcdir)/preinstall.am
@@ -26,11 +26,7 @@
#include <errno.h>
#include <rtems/libi2c.h>
/* #define DEBUG */
/*
* XXX: for the beginning, this driver works polled
*/
#define DEBUG
/*=========================================================================*\
| Function: |
@@ -110,9 +106,12 @@ static int mpc83xx_i2c_wait
#if defined(DEBUG)
printk("mpc83xx_i2c_wait called... ");
#endif
softc_ptr->reg_ptr->i2ccr |= MPC83XX_I2CCR_MIEN;
if (softc_ptr->initialized) {
/*
* enable interrupt mask
*/
softc_ptr->reg_ptr->i2ccr |= MPC83XX_I2CCR_MIEN;
rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100);
if (rc != RTEMS_SUCCESSFUL) {
return rc;
@@ -131,8 +130,8 @@ static int mpc83xx_i2c_wait
}
softc_ptr->reg_ptr->i2ccr &= ~MPC83XX_I2CCR_MIEN;
act_status = softc_ptr->reg_ptr->i2csr & status_mask;
if (act_status != desired_status) {
act_status = softc_ptr->reg_ptr->i2csr;
if ((act_status & status_mask) != desired_status) {
#if defined(DEBUG)
printk("... exit with RTEMS_IO_ERROR\r\n");
#endif
@@ -144,6 +143,145 @@ static int mpc83xx_i2c_wait
return RTEMS_SUCCESSFUL;
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
static void mpc83xx_i2c_irq_handler
(
/*-------------------------------------------------------------------------*\
| Purpose: |
| handle interrupts |
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
rtems_irq_hdl_param handle /* handle, is softc_ptr structure */
)
/*-------------------------------------------------------------------------*\
| Return Value: |
| <none> |
\*=========================================================================*/
{
mpc83xx_i2c_softc_t *softc_ptr = (mpc83xx_i2c_softc_t *)handle;
/*
* disable interrupt mask
*/
softc_ptr->reg_ptr->i2ccr &= ~MPC83XX_I2CCR_MIEN;
if (softc_ptr->initialized) {
rtems_semaphore_release(softc_ptr->irq_sema_id);
}
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
static void mpc83xx_i2c_irq_on_off
(
/*-------------------------------------------------------------------------*\
| Purpose: |
| enable/disable interrupts (void, handled at different position) |
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
const
rtems_irq_connect_data *irq_conn_data /* irq connect data */
)
/*-------------------------------------------------------------------------*\
| Return Value: |
| <none> |
\*=========================================================================*/
{
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
static int mpc83xx_i2c_irq_isOn
(
/*-------------------------------------------------------------------------*\
| Purpose: |
| check state of interrupts, void, done differently |
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
const
rtems_irq_connect_data *irq_conn_data /* irq connect data */
)
/*-------------------------------------------------------------------------*\
| Return Value: |
| TRUE, if enabled |
\*=========================================================================*/
{
return (TRUE);
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
static void mpc83xx_i2c_install_irq_handler
(
/*-------------------------------------------------------------------------*\
| Purpose: |
| (un-)install the interrupt handler |
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
mpc83xx_i2c_softc_t *softc_ptr, /* ptr to control structure */
int install /* TRUE: install, FALSE: remove */
)
/*-------------------------------------------------------------------------*\
| Return Value: |
| <none> |
\*=========================================================================*/
{
rtems_status_code rc = RTEMS_SUCCESSFUL;
rtems_irq_connect_data irq_conn_data = {
softc_ptr->irq_number,
mpc83xx_i2c_irq_handler, /* rtems_irq_hdl */
(rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */
mpc83xx_i2c_irq_on_off, /* (rtems_irq_enable) */
mpc83xx_i2c_irq_on_off, /* (rtems_irq_disable) */
mpc83xx_i2c_irq_isOn /* (rtems_irq_is_enabled) */
};
/*
* (un-)install handler for I2C device
*/
if (install) {
/*
* create semaphore for IRQ synchronization
*/
rc = rtems_semaphore_create(rtems_build_name('i','2','c','s'),
0,
RTEMS_FIFO
| RTEMS_SIMPLE_BINARY_SEMAPHORE,
0,
&softc_ptr->irq_sema_id);
if (rc != RTEMS_SUCCESSFUL) {
rtems_panic("I2C: cannot create semaphore");
}
if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
rtems_panic("I2C: cannot install IRQ handler");
}
}
else {
if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) {
rtems_panic("I2C: cannot uninstall IRQ handler");
}
/*
* delete sync semaphore
*/
if (softc_ptr->irq_sema_id != 0) {
rc = rtems_semaphore_delete(softc_ptr->irq_sema_id);
if (rc != RTEMS_SUCCESSFUL) {
rtems_panic("I2C: cannot delete semaphore");
}
}
}
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
@@ -185,7 +323,7 @@ static rtems_status_code mpc83xx_i2c_init
*/
softc_ptr->reg_ptr->i2cdfsrr = 0x10 ; /* no special filtering needed */
/*
* set own slave address to broadcasr (0x00)
* set own slave address to broadcast (0x00)
*/
softc_ptr->reg_ptr->i2cadr = 0x00 ;
@@ -195,11 +333,14 @@ static rtems_status_code mpc83xx_i2c_init
softc_ptr->reg_ptr->i2ccr = MPC83XX_I2CCR_MEN;
/*
* FIXME: init interrupt stuff
*/
/*
* FIXME: init other stuff
* init interrupt stuff
*/
mpc83xx_i2c_install_irq_handler(softc_ptr,TRUE);
/*
* mark, that we have initialized
*/
softc_ptr->initialized = TRUE;
#if defined(DEBUG)
printk("... exit OK\r\n");
#endif
@@ -376,6 +376,29 @@ typedef struct m83xxSPIRegisters_ {
volatile uint32_t spird; /* 0x0_7034 SPI receive register R 0xFFFF_FFFF 19.4.1.6/19-15 */
uint8_t reserved0_7038[0x07100-0x07038];/* 0x0_7038-70FF Reserved */
} m83xxSPIRegisters_t;
/* SPIMODE register fields */
#define MPC83XX_SPIMODE_LOOP (1 << (31- 1)) /* loopback */
#define MPC83XX_SPIMODE_CI (1 << (31- 2)) /* clock invert */
#define MPC83XX_SPIMODE_CP (1 << (31- 3)) /* clock phase */
#define MPC83XX_SPIMODE_DIV16 (1 << (31- 4)) /* divide by 16 */
#define MPC83XX_SPIMODE_REV (1 << (31- 5)) /* LSB first */
#define MPC83XX_SPIMODE_M_S (1 << (31- 6)) /* master/slave */
#define MPC83XX_SPIMODE_EN (1 << (31- 7)) /* enable */
#define MPC83XX_SPIMODE_LEN(n) ((n) << (31-11)) /* length code */
#define MPC83XX_SPIMODE_PM(n) ((n) << (31-15)) /* prescaler */
#define MPC83XX_SPIMODE_OD (1 << (31-19)) /* open drain */
/* SPCOM register fields */
#define MPC83XX_SPCOM_LST (1 << (31- 9)) /* last transfer */
/* SPIE/M register fields */
#define MPC83XX_SPIE_LT (1 << (31-17)) /* last character transmitted */
#define MPC83XX_SPIE_DNR (1 << (31-18)) /* data not ready */
#define MPC83XX_SPIE_OV (1 << (31-19)) /* overrun */
#define MPC83XX_SPIE_UN (1 << (31-20)) /* unterrun */
#define MPC83XX_SPIE_MME (1 << (31-21)) /* multi-master error */
#define MPC83XX_SPIE_NE (1 << (31-22)) /* not empty */
#define MPC83XX_SPIE_NF (1 << (31-23)) /* not full */
typedef struct m83xxDMARegisters_ {
/* DMA Registers */
@@ -774,6 +797,10 @@ typedef struct m83xxTSEC_Registers_ {
*/
#define M83xx_TSEC_TSTAT_THLT (1<<(31-0))
/*
* TSEC RSTAT bit definitions
*/
#define M83xx_TSEC_RSTAT_QHLT (1<<(31-8))
/*
* TSEC ECNTRL bit positions
*/
+56 -62
View File
@@ -94,23 +94,12 @@ struct mpc83xx_tsec_struct {
* statistic counters Rx
*/
unsigned long rxInterrupts;
unsigned long rxNotLast;
unsigned long rxGiant;
unsigned long rxNonOctet;
unsigned long rxBadCRC;
unsigned long rxOverrun;
unsigned long rxCollision;
unsigned long rxErrors;
/*
* statistic counters Tx
*/
unsigned long txInterrupts;
unsigned long txDeferred;
unsigned long txLateCollision;
unsigned long txUnderrun;
unsigned long txMisaligned;
unsigned long rxNotFirst;
unsigned long txRetryLimit;
unsigned long txErrors;
};
static struct mpc83xx_tsec_struct tsec_driver[M83xx_TSEC_NIFACES];
@@ -238,10 +227,14 @@ static void mpc83xx_tsec_hwinit
* due to alignment */
/*
* init EDIS register: enable all error reportings
* FIXME: make sure we handle these errors correctly
* init EDIS register: disable all error reportings
*/
reg_ptr->edis = 0;
reg_ptr->edis = (M83xx_TSEC_EDIS_BSYDIS |
M83xx_TSEC_EDIS_EBERRDIS |
M83xx_TSEC_EDIS_TXEDIS |
M83xx_TSEC_EDIS_LCDIS |
M83xx_TSEC_EDIS_CRLXDADIS |
M83xx_TSEC_EDIS_FUNDIS);
/*
* init minimum frame length register
*/
@@ -616,26 +609,6 @@ static void mpc83xx_tsec_receive_packets
* throw away mbuf
*/
MFREE(m,n);
/*
* update statistics
*/
if (0 != (status & M83xx_BD_LAST))
sc->rxNotLast++;
if (0 != (status & M83xx_BD_FIRST_IN_FRAME))
sc->rxNotFirst++;
if (0 == (status & M83xx_BD_LONG)) {
sc->rxGiant++;
}
if (0 == (status & M83xx_BD_NONALIGNED)) {
sc->rxNonOctet++;
}
if (0 == (status & M83xx_BD_CRC_ERROR)) {
sc->rxBadCRC++;
}
if (0 == (status & M83xx_BD_OVERRUN)) {
sc->rxOverrun++;
}
}
/*
* mark buffer as non-allocated (for refill)
@@ -1234,18 +1207,26 @@ static void mpc83xx_tsec_err_irq_handler
| <none> |
\*=========================================================================*/
{
struct mpc83xx_tsec_struct *sc =
(struct mpc83xx_tsec_struct *)handle;
/*
* FIXME: check error conditions, do something useful
* clear error events in IEVENT
*/
#if 0
sc->reg_ptr->tstat = M83xx_IEVENT_ERRALL;
/*
* disable error interrupts
* has Rx been stopped? then restart it
*/
M83xx_TSEC_IMASK_SET(sc->reg_ptr->imask,M83xx_IEVENT_ERRALL,0);
if (0 != (sc->reg_ptr->rstat & M83xx_TSEC_RSTAT_QHLT)) {
sc->rxErrors++;
sc->reg_ptr->rstat = M83xx_TSEC_RSTAT_QHLT;
}
/*
* FIXME: do something :-)
* has Tx been stopped? then restart it
*/
#endif
if (0 != (sc->reg_ptr->tstat & M83xx_TSEC_TSTAT_THLT)) {
sc->txErrors++;
sc->reg_ptr->tstat = M83xx_TSEC_TSTAT_THLT;
}
}
@@ -1529,7 +1510,7 @@ static void mpc83xx_tsec_off
\*=========================================================================*/
{
/*
* FIXME: deinitialize driver
* deinitialize driver?
*/
}
@@ -1540,7 +1521,7 @@ static void mpc83xx_tsec_stats
(
/*-------------------------------------------------------------------------*\
| Purpose: |
| perform io control functions |
| print statistics |
+---------------------------------------------------------------------------+
| Input Parameters: |
\*-------------------------------------------------------------------------*/
@@ -1568,21 +1549,35 @@ static void mpc83xx_tsec_stats
/*
* print some statistics
*/
printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
printf (" Not First:%-8lu", sc->rxNotFirst);
printf (" Not Last:%-8lu\n", sc->rxNotLast);
printf (" Giant:%-8lu", sc->rxGiant);
printf (" Non-octet:%-8lu\n", sc->rxNonOctet);
printf (" Bad CRC:%-8lu", sc->rxBadCRC);
printf (" Overrun:%-8lu", sc->rxOverrun);
printf (" Collision:%-8lu\n", sc->rxCollision);
printf (" Rx Interrupts:%-8lu", sc->rxInterrupts);
printf (" Rx Errors:%-8lu", sc->rxErrors);
printf (" Rx packets:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rpkt]);
printf (" Rx broadcasts:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rbca]);
printf (" Rx multicasts:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rmca]);
printf (" Giant:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rovr]);
printf (" Non-octet:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_raln]);
printf (" Bad CRC:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rfcs]);
printf (" Overrun:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_rdrp]);
printf (" Tx Interrupts:%-8lu", sc->txInterrupts);
printf (" Deferred:%-8lu", sc->txDeferred);
printf (" Late Collision:%-8lu\n", sc->txLateCollision);
printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
printf (" Underrun:%-8lu", sc->txUnderrun);
printf (" Misaligned:%-8lu\n", sc->txMisaligned);
printf (" Tx Interrupts:%-8lu", sc->txInterrupts);
printf (" Tx Errors:%-8lu", sc->txErrors);
printf (" Tx packets:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_tpkt]);
printf (" Deferred:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_tdfr]);
printf (" Late Collision:%-8lu",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_tlcl]);
printf ("Retransmit Limit:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_tedf]);
printf (" Underrun:%-8lu\n",
sc->reg_ptr->rmon_mib[m83xx_tsec_rmon_tund]);
}
/*=========================================================================*\
@@ -1632,7 +1627,7 @@ static int mpc83xx_tsec_ioctl
mpc83xx_tsec_off(sc);
}
if (ifp->if_flags & IFF_UP) {
mpc83xx_tsec_off(sc);
mpc83xx_tsec_init(sc);
}
break;
@@ -1644,7 +1639,7 @@ static int mpc83xx_tsec_ioctl
break;
/*
* FIXME: All sorts of multicast commands need to be added here!
* All sorts of multicast commands need to be added here!
*/
default:
error = EINVAL;
@@ -1799,7 +1794,7 @@ static int mpc83xx_tsec_driver_attach
)
/*-------------------------------------------------------------------------*\
| Return Value: |
| zero, if success |
| 1, if success |
\*=========================================================================*/
{
struct mpc83xx_tsec_struct *sc;
@@ -1900,7 +1895,6 @@ static int mpc83xx_tsec_driver_attach
return 1;
}
/*=========================================================================*\
| Function: |
\*-------------------------------------------------------------------------*/
+4
View File
@@ -211,4 +211,8 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/tsec.h
$(PROJECT_INCLUDE)/mpc83xx/mpc83xx_i2cdrv.h: mpc83xx/i2c/mpc83xx_i2cdrv.h $(PROJECT_INCLUDE)/mpc83xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_i2cdrv.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_i2cdrv.h
$(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h: mpc83xx/spi/mpc83xx_spidrv.h $(PROJECT_INCLUDE)/mpc83xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h
endif
+4 -2
View File
@@ -64,12 +64,14 @@ EXTRA_DIST += rtc/README.ds1643 rtc/README.icm7170 rtc/README.m48t08 \
# i2c
if LIBCHIP
include_libchip_HEADERS += i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h
include_libchip_HEADERS += i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h \
i2c/spi-flash-m25p40.h
noinst_LIBRARIES += libi2cio.a
libi2cio_a_CPPFLAGS = $(AM_CPPFLAGS)
libi2cio_a_SOURCES = i2c/i2c-ds1621.c i2c/i2c-2b-eeprom.c \
i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h
i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h \
i2c/spi-flash-m25p40.c i2c/spi-flash-m25p40.h
endif
# serial
+4
View File
@@ -115,6 +115,10 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/i2c-ds1621.h
$(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h: i2c/i2c-2b-eeprom.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h
$(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h: i2c/spi-flash-m25p40.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h
endif
if LIBCHIP
$(PROJECT_INCLUDE)/libchip/mc68681.h: serial/mc68681.h $(PROJECT_INCLUDE)/libchip/$(dirstamp)
+6
View File
@@ -1,3 +1,9 @@
2007-10-25 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
* libi2c/libi2c.c, libi2c/libi2c.h:
extend API to support SPI devices
made libi2c.h C++-proof
2007-10-19 Joel Sherrill <joel.sherrill@OARcorp.com>
* libcsupport/src/assoc.c: Removed. Accidentally included routine
+90 -8
View File
@@ -46,6 +46,10 @@
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
/*
* adaptations to also handle SPI devices
* by Thomas Doerfler, embedded brains GmbH, Puchheim, Germany
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -55,6 +59,7 @@
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <stdarg.h>
#include <rtems.h>
#include <rtems/error.h>
@@ -318,7 +323,15 @@ int
rtems_libi2c_initialize ()
{
rtems_status_code sc;
static boolean is_initialized = FALSE;
if (is_initialized) {
/*
* already called before? then skip this step
*/
return 0;
}
if (!(libmutex = mutexCreate (rtems_build_name ('l', 'I', '2', 'C'))))
return -1;
@@ -331,6 +344,7 @@ rtems_libi2c_initialize ()
libmutex = 0;
return -1;
}
is_initialized = TRUE;
return 0;
}
@@ -428,7 +442,7 @@ not_started (int busno)
}
rtems_status_code
rtems_libi2c_send_start (uint32_t minor)
rtems_libi2c_send_start (rtems_device_minor_number minor)
{
int rval;
DECL_CHECKED_BH (busno, bush, minor, +)
@@ -459,7 +473,7 @@ rtems_libi2c_send_start (uint32_t minor)
}
rtems_status_code
rtems_libi2c_send_stop (uint32_t minor)
rtems_libi2c_send_stop (rtems_device_minor_number minor)
{
rtems_status_code rval;
DECL_CHECKED_BH (busno, bush, minor, +)
@@ -476,7 +490,7 @@ rtems_libi2c_send_stop (uint32_t minor)
}
rtems_status_code
rtems_libi2c_send_addr (uint32_t minor, int rw)
rtems_libi2c_send_addr (rtems_device_minor_number minor, int rw)
{
rtems_status_code sc;
DECL_CHECKED_BH (busno, bush, minor, +)
@@ -491,7 +505,9 @@ rtems_libi2c_send_addr (uint32_t minor, int rw)
}
int
rtems_libi2c_read_bytes (uint32_t minor, unsigned char *bytes, int nbytes)
rtems_libi2c_read_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes)
{
int sc;
DECL_CHECKED_BH (busno, bush, minor, -)
@@ -506,7 +522,9 @@ rtems_libi2c_read_bytes (uint32_t minor, unsigned char *bytes, int nbytes)
}
int
rtems_libi2c_write_bytes (uint32_t minor, unsigned char *bytes, int nbytes)
rtems_libi2c_write_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes)
{
int sc;
DECL_CHECKED_BH (busno, bush, minor, -)
@@ -520,8 +538,70 @@ rtems_libi2c_write_bytes (uint32_t minor, unsigned char *bytes, int nbytes)
return sc;
}
int
rtems_libi2c_ioctl (rtems_device_minor_number minor,
int cmd,
...)
{
va_list ap;
int sc = 0;
void *args;
DECL_CHECKED_BH (busno, bush, minor, -)
if (not_started (busno))
return -RTEMS_NOT_OWNER_OF_RESOURCE;
va_start(ap, cmd);
args = va_arg(ap, void *);
switch(cmd) {
/*
* add ioctls defined for this level here:
*/
case RTEMS_LIBI2C_IOCTL_START_TFM_READ_WRITE:
/*
* address device, then set transfer mode and perform read_write transfer
*/
/*
* perform start/address
*/
if (sc == 0) {
sc = rtems_libi2c_send_start (minor);
}
/*
* set tfr mode
*/
if (sc == 0) {
sc = bush->ops->ioctl
(bush,
RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
&((rtems_libi2c_tfm_read_write_t *)args)->tfr_mode);
}
/*
* perform read_write
*/
if (sc == 0) {
sc = bush->ops->ioctl
(bush,
RTEMS_LIBI2C_IOCTL_READ_WRITE,
&((rtems_libi2c_tfm_read_write_t *)args)->rd_wr);
}
break;
default:
sc = bush->ops->ioctl (bush, cmd, args);
break;
}
if (sc < 0)
rtems_libi2c_send_stop (minor);
return sc;
}
static int
do_s_rw (uint32_t minor, unsigned char *bytes, int nbytes, int rw)
do_s_rw (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes,
int rw)
{
rtems_status_code sc;
rtems_libi2c_bus_t *bush;
@@ -549,14 +629,16 @@ do_s_rw (uint32_t minor, unsigned char *bytes, int nbytes, int rw)
}
int
rtems_libi2c_start_read_bytes (uint32_t minor, unsigned char *bytes,
rtems_libi2c_start_read_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes)
{
return do_s_rw (minor, bytes, nbytes, 1);
}
int
rtems_libi2c_start_write_bytes (uint32_t minor, unsigned char *bytes,
rtems_libi2c_start_write_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes)
{
return do_s_rw (minor, bytes, nbytes, 0);
+96 -2
View File
@@ -46,6 +46,7 @@
*
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
*/
#include <rtems.h>
#include <rtems/io.h>
@@ -101,6 +102,11 @@ typedef struct rtems_libi2c_bus_ops_
/* write a number of bytes */
int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
int nbytes);
/* ioctl misc functions */
int (*ioctl) (rtems_libi2c_bus_t * bushdl,
int cmd,
void *buffer;
);
} rtems_libi2c_bus_ops_t;
@@ -265,14 +271,102 @@ rtems_libi2c_write_bytes (rtems_device_minor_number minor,
/* Send start, send address and read bytes */
int
rtems_libi2c_start_read_bytes (uint32_t minor, unsigned char *bytes,
rtems_libi2c_start_read_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes);
/* Send start, send address and write bytes */
int
rtems_libi2c_start_write_bytes (uint32_t minor, unsigned char *bytes,
rtems_libi2c_start_write_bytes (rtems_device_minor_number minor,
unsigned char *bytes,
int nbytes);
/* call misc iocontrol function */
int
rtems_libi2c_ioctl (rtems_device_minor_number minor,
int cmd,
...);
/*
* NOTE: any low-level driver ioctl returning a negative
* result for release the bus (perform a STOP condition)
*/
/*******************************
* defined IOCTLs:
*******************************/
#define RTEMS_LIBI2C_IOCTL_READ_WRITE 1
/*
* retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
* RTEMS_LIBI2C_IOCTL_READ_WRITE,
* rtems_libi2c_read_write_t *arg);
*
* This call performs a simultanous read/write transfer,
* which is possible (and sometimes needed) for SPI devices
*
* arg is a pointer to a rd_wr info data structure
*
* This call is only needed for SPI devices
*/
#define RTEMS_LIBI2C_IOCTL_START_TFM_READ_WRITE 2
/*
* retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
* RTEMS_LIBI2C_IOCTL_START_READ_WRITE,
* unsigned char *rd_buffer,
* const unsigned char *wr_buffer,
* int byte_cnt,
* const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
*
* This call addresses a slave and then:
* - sets the proper transfer mode,
* - performs a simultanous read/write transfer,
* (which is possible and sometimes needed for SPI devices)
* NOTE: - if rd_buffer is NULL, receive data will be dropped
* - if wr_buffer is NULL, bytes with content 0 will transmitted
*
* rd_buffer is a pointer to a receive buffer (or NULL)
* wr_buffer is a pointer to the data to be sent (or NULL)
*
* This call is only needed for SPI devices
*/
#define RTEMS_LIBI2C_IOCTL_SET_TFRMODE 3
/*
* retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
* RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
* const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
*
* This call sets an SPI device to the transfer mode needed (baudrate etc.)
*
* tfr_mode is a pointer to a structure defining the SPI transfer mode needed
* (see below).
*
* This call is only needed for SPI devices
*/
/*
* arguemtn data structures for IOCTLs defined above
*/
typedef struct {
unsigned char *rd_buf;
const unsigned char *wr_buf;
int byte_cnt;
} rtems_libi2c_read_write_t;
typedef struct {
uint32_t baudrate; /* maximum bits per second */
/* only valid for SPI drivers: */
uint8_t bits_per_char; /* how many bits per byte/word/longword? */
boolean lsb_first; /* TRUE: send LSB first */
boolean clock_inv; /* TRUE: inverted clock (high active) */
boolean clock_phs; /* TRUE: clock starts toggling at start of data tfr */
} rtems_libi2c_tfr_mode_t;
typedef struct {
rtems_libi2c_tfr_mode_t tfr_mode;
rtems_libi2c_read_write_t rd_wr;
} rtems_libi2c_tfm_read_write_t;
#ifdef __cplusplus
}
#endif