From 55a685bddc84cb5c74f8ece914703f2a1e72a1c4 Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Thu, 25 Oct 2007 16:17:56 +0000 Subject: added SPI support to libi2c added IRQ support to MPC83xx i2c driver added mpc83xx spi driver --- cpukit/libi2c/libi2c.c | 98 +++++++++++++++++++++++++++++++++++++++++++++----- cpukit/libi2c/libi2c.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 186 insertions(+), 10 deletions(-) (limited to 'cpukit/libi2c') diff --git a/cpukit/libi2c/libi2c.c b/cpukit/libi2c/libi2c.c index 0adf2f1ae4..7069b35527 100644 --- a/cpukit/libi2c/libi2c.c +++ b/cpukit/libi2c/libi2c.c @@ -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 #include #include +#include #include #include @@ -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); diff --git a/cpukit/libi2c/libi2c.h b/cpukit/libi2c/libi2c.h index 2dfbddd458..d243574333 100644 --- a/cpukit/libi2c/libi2c.h +++ b/cpukit/libi2c/libi2c.h @@ -46,6 +46,7 @@ * * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 */ + #include #include @@ -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 -- cgit v1.2.3