diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c b/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c deleted file mode 100644 index 9e386f7cb6..0000000000 --- a/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Driver for GRLIB port of OpenCores I2C-master - * - * COPYRIGHT (c) 2007 Cobham Gaisler AB - * based on the RTEMS MPC83xx I2C driver (c) 2007 Embedded Brains GmbH. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * This file contains the driver and initialization code - */ - -#include <bsp.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ambapp.h> -#include <rtems/libi2c.h> -#include <drvmgr/drvmgr.h> -#include <drvmgr/ambapp_bus.h> - -#include <bsp/i2cmst.h> - -/* Enable debug printks? */ -/*#define DEBUG*/ - -#ifdef DEBUG - #define DBG(args...) printk(args) -#else - #define DBG(args...) -#endif - -/* The OC I2C core will perform a write after a start unless the RD bit - in the command register has been set. Since the rtems framework has - a send_start function we buffer that command and use it when the first - data is written. The START is buffered in the sendstart member below */ -typedef struct gr_i2cmst_prv { - rtems_libi2c_bus_t i2clib_desc; - struct drvmgr_dev *dev; - gr_i2cmst_regs_t *reg_ptr; - unsigned int sysfreq; /* System clock frequency in kHz */ - int minor; - unsigned char sendstart; /* START events are buffered here */ - /* rtems_irq_number irq_number; */ - /* rtems_id irq_sema_id; */ -} gr_i2cmst_prv_t; - -/* Calculates the scaler value for 100 kHz operation */ -static int gr_i2cmst_calc_scaler(int sysfreq) -{ - return sysfreq/500 - 1; -} - -/* Wait for the current transfer to end */ -static int gr_i2cmst_wait(gr_i2cmst_prv_t *prv_ptr, uint8_t expected_sts) -{ - uint32_t tout = 0; - int current_sts; - - DBG("(gr_i2cmst_wait called..."); - - do { - if (tout++ > 1000000) { - DBG("gr_i2cmst_wait: TIMEOUT\n"); - return RTEMS_TIMEOUT; - } - } while (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP); - - current_sts = prv_ptr->reg_ptr->cmdsts & ~GRI2C_STS_IF & ~GRI2C_STS_BUSY; - - if (current_sts != expected_sts) { -#if defined(DEBUG) - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_RXACK) { - DBG("Transfer NAKed.."); - } - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_AL) { - DBG("arbitration lost.."); - } - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP) { - DBG("transfer still in progress, huh?.."); - } - DBG("exited with IO error..)"); -#endif - DBG("gr_i2cmst_wait: IO-ERROR\n"); - return RTEMS_IO_ERROR; - } - - DBG("exited...)"); - - return RTEMS_SUCCESSFUL; -} - -/* Initialize hardware core */ -static rtems_status_code gr_i2cmst_init(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_init called..."); - - /* Disable core before changing prescale register */ - prv_ptr->reg_ptr->ctrl = 0; - - /* Calculate and set prescale value */ - prv_ptr->reg_ptr->prescl = gr_i2cmst_calc_scaler(prv_ptr->sysfreq); - - /* Enable core, interrupts are not enabled */ - prv_ptr->reg_ptr->ctrl = GRI2C_CTRL_EN; - - /* Clear possible START condition */ - prv_ptr->sendstart = 0; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_start(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_send_start called..."); - - /* The OC I2C core does not work with stand alone START events, - instead the event is buffered */ - prv_ptr->sendstart = GRI2C_CMD_STA; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_stop(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_send_stop called..."); - - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_STO; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_addr(rtems_libi2c_bus_t *bushdl, - uint32_t addr, int rw) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - uint8_t addr_byte; - rtems_status_code rc; - - DBG("gr_i2cmst_send_addr called, addr = 0x%x, rw = %d...", - addr, rw); - - /* Check if long address is needed */ - if (addr > 0x7f) { - addr_byte = ((addr >> 7) & 0x06) | (rw ? 1 : 0); - - prv_ptr->reg_ptr->tdrd = addr_byte; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - if (rc != RTEMS_SUCCESSFUL) { - - DBG("exited with error\n"); - - return -rc; - } - } - - /* For 10-bit adresses the last byte should only be written for a - write operation */ - rc = RTEMS_SUCCESSFUL; - if (addr <= 0x7f || rw == 0) { - addr_byte = (addr << 1) | (rw ? 1 : 0); - - prv_ptr->reg_ptr->tdrd = addr_byte; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - } - - DBG("exited\n"); - return rc; -} - - -static int gr_i2cmst_read_bytes(rtems_libi2c_bus_t *bushdl, - unsigned char *bytes, int nbytes) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - unsigned char *buf = bytes; - rtems_status_code rc; - unsigned char expected_sts = GRI2C_STATUS_IDLE; - - DBG("gr_i2cmst_read_bytes called, nbytes = %d...", nbytes); - - while (nbytes-- > 0) { - if (nbytes == 0) { - /* Respond with NAK to end sequential read */ - prv_ptr->reg_ptr->cmdsts = (GRI2C_CMD_RD | GRI2C_CMD_ACK | - prv_ptr->sendstart); - expected_sts = GRI2C_STS_RXACK; - } else { - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_RD | prv_ptr->sendstart; - } - prv_ptr->sendstart = 0; - /* Wait until end of transfer */ - rc = gr_i2cmst_wait(prv_ptr, expected_sts); - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - *buf++ = prv_ptr->reg_ptr->tdrd; - } - - DBG("exited\n"); - - return buf - bytes; -} - -static int gr_i2cmst_write_bytes(rtems_libi2c_bus_t *bushdl, - unsigned char *bytes, int nbytes) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - unsigned char *buf = bytes; - rtems_status_code rc; - - DBG("gr_i2cmst_write_bytes called, nbytes = %d...", nbytes); - - while (nbytes-- > 0) { - - DBG("writing byte 0x%02X...", *buf); - - prv_ptr->reg_ptr->tdrd = *buf++; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - } - - DBG("exited\n"); - - return buf - bytes; -} - -static rtems_libi2c_bus_ops_t gr_i2cmst_ops = { - init: gr_i2cmst_init, - send_start: gr_i2cmst_send_start, - send_stop: gr_i2cmst_send_stop, - send_addr: gr_i2cmst_send_addr, - read_bytes: gr_i2cmst_read_bytes, - write_bytes: gr_i2cmst_write_bytes, -}; - -/* Get Hardware and disable it */ -static int i2cmst_device_init(gr_i2cmst_prv_t *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->reg_ptr = (gr_i2cmst_regs_t *)pnpinfo->apb_slv->start; - - /* Disable core */ - priv->reg_ptr->ctrl = 0; - - priv->i2clib_desc.ops = &gr_i2cmst_ops; - priv->i2clib_desc.size = sizeof(gr_i2cmst_ops); - return 0; -} - - -/******************* Driver Manager Part ***********************/ - -int i2cmst_init2(struct drvmgr_dev *dev); -int i2cmst_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops i2cmst_ops = -{ - .init = {NULL, i2cmst_init2, i2cmst_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id i2cmst_ids[] = -{ - {VENDOR_GAISLER, GAISLER_I2CMST}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info i2cmst_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_I2CMST_ID, /* Driver ID */ - "I2CMST_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &i2cmst_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &i2cmst_ids[0] -}; - -void i2cmst_register_drv (void) -{ - DBG("Registering I2CMST driver\n"); - drvmgr_drv_register(&i2cmst_drv_info.general); -} - -/* The I2CMST Driver is informed about a new hardware device */ -int i2cmst_init2(struct drvmgr_dev *dev) -{ - gr_i2cmst_prv_t *priv; - - DBG("I2CMST[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - priv = dev->priv = malloc(sizeof(gr_i2cmst_prv_t)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -/* Init stage 2 */ -int i2cmst_init3(struct drvmgr_dev *dev) -{ - gr_i2cmst_prv_t *priv; - char prefix[32]; - char devName[32]; - int rc; - - priv = (gr_i2cmst_prv_t *)dev->priv; - - /* Do initialization */ - - /* Initialize i2c library */ - rc = rtems_libi2c_initialize(); - if (rc != 0) { - DBG("I2CMST: rtems_libi2c_initialize failed, exiting...\n"); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - /* Get frequency */ - if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->sysfreq) ) { - return DRVMGR_FAIL; - } - priv->sysfreq = priv->sysfreq / 1000; /* Convert to kHz */ - - if ( i2cmst_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(devName, "/dev/i2c%d", dev->minor_drv+1); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(devName, "/dev/%si2c%d", prefix, dev->minor_bus+1); - } - - /* Register Bus for this Device */ - rc = rtems_libi2c_register_bus(devName, &priv->i2clib_desc); - if (rc < 0) { - DBG("I2CMST: rtems_libi2c_register_bus(%s) failed, exiting..\n", devName); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - priv->minor = rc; - - return DRVMGR_OK; -} |