diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/gpio/grgpio.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/gpio/grgpio.c | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c b/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c deleted file mode 100644 index 7b02298fa4..0000000000 --- a/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c +++ /dev/null @@ -1,449 +0,0 @@ -/* GRGPIO GPIO Driver interface. - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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. - */ - -#include <bsp.h> -#include <rtems/libio.h> -#include <stdlib.h> -#include <assert.h> -#include <rtems/bspIo.h> -#include <string.h> -#include <stdio.h> - -#include <drvmgr/drvmgr.h> -#include <drvmgr/ambapp_bus.h> -#include <bsp/grgpio.h> -#include <bsp/gpiolib.h> -#include <ambapp.h> -#include <grlib.h> - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#define STATIC -#else -#define DBG(x...) -#define STATIC static -#endif - -struct grgpio_isr { - drvmgr_isr isr; - void *arg; -}; - -struct grgpio_priv { - struct drvmgr_dev *dev; - struct grgpio_regs *regs; - int irq; - int minor; - - /* Driver implementation */ - int port_cnt; - unsigned char port_handles[32]; - struct grgpio_isr isrs[32]; - struct gpiolib_drv gpiolib_desc; - unsigned int bypass; - unsigned int imask; -}; - -/******************* Driver Manager Part ***********************/ - -int grgpio_device_init(struct grgpio_priv *priv); - -int grgpio_init1(struct drvmgr_dev *dev); -int grgpio_init2(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops grgpio_ops = -{ - .init = {grgpio_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id grgpio_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GPIO}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info grgpio_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRGPIO_ID, /* Driver ID */ - "GRGPIO_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grgpio_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &grgpio_ids[0] -}; - -void grgpio_register_drv (void) -{ - DBG("Registering GRGPIO driver\n"); - drvmgr_drv_register(&grgpio_drv_info.general); -} - -/* Register GRGPIO pins as quick as possible to the GPIO library, - * other drivers may depend upon them in INIT LEVEL 2. - * Note that since IRQ may not be available in init1, it is assumed - * that the GPIOLibrary does not request IRQ routines until LEVEL 2. - */ -int grgpio_init1(struct drvmgr_dev *dev) -{ - struct grgpio_priv *priv; - int status, port; - - DBG("GRGPIO[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - /* This core will not find other cores, but other driver may depend upon - * the GPIO library to function. So, we set up GPIO right away. - */ - - /* Initialize library if not already done */ - status = gpiolib_initialize(); - if ( status < 0 ) - return DRVMGR_FAIL; - - priv = dev->priv = malloc(sizeof(struct grgpio_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - if ( grgpio_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Register all ports available on this core as GPIO port to - * upper layer - */ - for(port=0; port<priv->port_cnt; port++) { - priv->port_handles[port] = port; - gpiolib_drv_register(&priv->gpiolib_desc, - &priv->port_handles[port]); - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -/* Find port from handle, returns -1 if not found */ -static int grgpio_find_port(void *handle, struct grgpio_priv **priv) -{ - unsigned char portnr; - - portnr = *(unsigned char *)handle; - if ( portnr > 31 ) - return -1; - *priv = (struct grgpio_priv *) - (((unsigned int)handle - portnr*sizeof(unsigned char)) - - offsetof(struct grgpio_priv, port_handles)); - return portnr; -} - -static int grgpio_gpiolib_open(void *handle) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO[0x%08x][%d]: OPENING\n", priv->regs, portnr); - - /* Open the device, nothing to be done... */ - - return 0; -} - -static int grgpio_grpiolib_config(void *handle, struct gpiolib_config *cfg) -{ - struct grgpio_priv *priv; - int portnr; - unsigned int mask; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: CONFIG\n", priv->regs, portnr); - - /* Configure the device. And check that operation is supported, - * not all I/O Pins have IRQ support. - */ - mask = (1<<portnr); - - /* Return error when IRQ not supported by this I/O Line and it - * is beeing enabled by user. - */ - if ( ((mask & priv->imask) == 0) && cfg->mask ) - return -1; - - priv->regs->imask &= ~mask; /* Disable interrupt temporarily */ - - /* Configure settings before enabling interrupt */ - priv->regs->ipol = (priv->regs->ipol & ~mask) | (cfg->irq_polarity ? mask : 0); - priv->regs->iedge = (priv->regs->iedge & ~mask) | (cfg->irq_level ? 0 : mask); - priv->regs->imask |= cfg->mask ? mask : 0; - - return 0; -} - -static int grgpio_grpiolib_get(void *handle, int *inval) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: GET\n", priv->regs, portnr); - - /* Get current status of the port */ - if ( inval ) - *inval = (priv->regs->data >> portnr) & 0x1; - - return 0; -} - -static int grgpio_grpiolib_irq_opts(void *handle, unsigned int options) -{ - struct grgpio_priv *priv; - int portnr; - drvmgr_isr isr; - void *arg; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: IRQ OPTS 0x%x\n", priv->regs, portnr, options); - - if ( options & GPIOLIB_IRQ_FORCE ) - return -1; - - isr = priv->isrs[portnr].isr; - arg = priv->isrs[portnr].arg; - - if ( options & GPIOLIB_IRQ_DISABLE ) { - /* Disable interrupt at interrupt controller */ - if ( drvmgr_interrupt_unregister(priv->dev, portnr, isr, arg) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_CLEAR ) { - /* Clear interrupt at interrupt controller */ - if ( drvmgr_interrupt_clear(priv->dev, portnr) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_ENABLE ) { - /* Enable interrupt at interrupt controller */ - if ( drvmgr_interrupt_register(priv->dev, portnr, "grgpio", isr, arg) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_MASK ) { - /* Mask (disable) interrupt at interrupt controller */ - if ( drvmgr_interrupt_mask(priv->dev, portnr) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_UNMASK ) { - /* Unmask (enable) interrupt at interrupt controller */ - if ( drvmgr_interrupt_unmask(priv->dev, portnr) ) { - return -1; - } - } - - return 0; -} - -static int grgpio_grpiolib_irq_register(void *handle, void *func, void *arg) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO: OPENING %d at [0x%08x]\n", portnr, priv->regs); - - /* Since the user doesn't provide the ISR and argument, we must... */ - priv->isrs[portnr].isr = func; - priv->isrs[portnr].arg = arg; - - return 0; -} - -static int grgpio_grpiolib_set(void *handle, int dir, int outval) -{ - struct grgpio_priv *priv; - int portnr; - unsigned int mask; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO: OPENING %d at [0x%08x]\n", portnr, priv->regs); - - /* Set Direction and Output */ - mask = 1<<portnr; - priv->regs->dir = (priv->regs->dir & ~mask) | (dir ? mask : 0); - priv->regs->output = (priv->regs->output & ~mask) | (outval ? mask : 0); - - return 0; -} - -static int grgpio_gpiolib_show(void *handle) -{ - struct grgpio_priv *priv; - int portnr, i, regs[7]; - volatile unsigned int *reg; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED SHOWING HANDLE 0x%08x\n", handle); - return -1; - } - for (i=0, reg=&priv->regs->data; i<7; i++, reg++) { - regs[i] = ( *reg >> portnr) & 1; - } - printf("GRGPIO[%p] PORT[%d]: IN/OUT/DIR: [%d,%d,%d], MASK/POL/EDGE: [%d,%d,%d], BYPASS: %d\n", - priv->regs, portnr, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6]); - return 0; -} - -static int grgpio_gpiolib_get_info(void *handle, struct gpiolib_info *pinfo) -{ - struct grgpio_priv *priv; - int portnr; - char prefix[48]; - struct drvmgr_dev *dev; - - if ( !pinfo ) - return -1; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED GET_INFO HANDLE 0x%08x\n", handle); - return -1; - } - - /* Get Filesystem name prefix */ - dev = priv->dev; - 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. - */ - snprintf(pinfo->devName, 64, "/dev/grgpio%d/%d", dev->minor_drv, portnr); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - snprintf(pinfo->devName, 64, "/dev/%sgrgpio%d/%d", prefix, dev->minor_bus, portnr); - } - - return 0; -} - -static struct gpiolib_drv_ops grgpio_gpiolib_ops = -{ - .config = grgpio_grpiolib_config, - .get = grgpio_grpiolib_get, - .irq_opts = grgpio_grpiolib_irq_opts, - .irq_register = grgpio_grpiolib_irq_register, - .open = grgpio_gpiolib_open, - .set = grgpio_grpiolib_set, - .show = grgpio_gpiolib_show, - .get_info = grgpio_gpiolib_get_info, -}; - -int grgpio_device_init(struct grgpio_priv *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - unsigned int mask; - int port_cnt; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->irq = pnpinfo->irq; - priv->regs = (struct grgpio_regs *)pnpinfo->apb_slv->start; - - DBG("GRGPIO: 0x%08x irq %d\n", (unsigned int)priv->regs, priv->irq); - - /* Mask all Interrupts */ - priv->regs->imask = 0; - - /* Make IRQ Rising edge triggered default */ - priv->regs->ipol = 0xfffffffe; - priv->regs->iedge = 0xfffffffe; - - /* Read what I/O lines have IRQ support */ - priv->imask = priv->regs->ipol; - - /* Let the user configure the port count, this might be needed - * when the GPIO lines must not be changed (assigned during bootup) - */ - value = drvmgr_dev_key_get(priv->dev, "nBits", DRVMGR_KT_INT); - if ( value ) { - priv->port_cnt = value->i; - } else { - /* Auto detect number of GPIO ports */ - priv->regs->dir = 0; - priv->regs->output = 0xffffffff; - mask = priv->regs->output; - priv->regs->output = 0; - - for(port_cnt=0; port_cnt<32; port_cnt++) - if ( (mask & (1<<port_cnt)) == 0 ) - break; - priv->port_cnt = port_cnt; - } - - /* Let the user configure the BYPASS register, this might be needed - * to select which cores can do I/O on a pin. - */ - value = drvmgr_dev_key_get(priv->dev, "bypass", DRVMGR_KT_INT); - if ( value ) { - priv->bypass = value->i; - } else { - priv->bypass = 0; - } - priv->regs->bypass = priv->bypass; - - /* Prepare GPIOLIB layer */ - priv->gpiolib_desc.ops = &grgpio_gpiolib_ops; - - return 0; -} |