Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GPIOLIB interface implementation
0004  *
0005  *  COPYRIGHT (c) 2009.
0006  *  Cobham Gaisler AB.
0007  *
0008  * Redistribution and use in source and binary forms, with or without
0009  * modification, are permitted provided that the following conditions
0010  * are met:
0011  * 1. Redistributions of source code must retain the above copyright
0012  *    notice, this list of conditions and the following disclaimer.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  *
0017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0027  * POSSIBILITY OF SUCH DAMAGE.
0028  */
0029 
0030 #include <stdlib.h>
0031 #include <stdio.h>
0032 #include <string.h>
0033 
0034 #include <grlib/gpiolib.h>
0035 
0036 #include <grlib/grlib_impl.h>
0037 
0038 struct gpiolib_port;
0039 
0040 struct gpiolib_port {
0041     struct gpiolib_port *next;
0042     int         minor;
0043     struct gpiolib_drv  *drv;
0044     void            *handle;
0045 
0046     int         open;
0047 };
0048 
0049 /* Root of GPIO Ports */
0050 struct gpiolib_port *gpiolib_ports;
0051 
0052 /* Number of GPIO ports registered */
0053 static int port_nr;
0054 
0055 /* 1 if libraray initialized */
0056 static int gpiolib_initied = 0;
0057 
0058 /* Insert a port first in ports list */
0059 static void gpiolib_list_add(struct gpiolib_port *port)
0060 {
0061     port->next = gpiolib_ports;
0062     gpiolib_ports = port;
0063 }
0064 
0065 static struct gpiolib_port *gpiolib_find(int minor)
0066 {
0067     struct gpiolib_port *p;
0068 
0069     p = gpiolib_ports;
0070     while ( p && (p->minor != minor) ) {
0071         p = p->next;
0072     }
0073     return p;
0074 }
0075 
0076 static struct gpiolib_port *gpiolib_find_by_name(char *name)
0077 {
0078     struct gpiolib_port *p;
0079     struct gpiolib_info info;
0080     int (*get_info)(void *, struct gpiolib_info *);
0081 
0082     p = gpiolib_ports;
0083     while ( p ) {
0084         get_info = p->drv->ops->get_info;
0085         if ( get_info && (get_info(p->handle, &info) == 0) ) {
0086             if ( strncmp(name, (char *)&info.devName[0], 64) == 0 ) {
0087                 break;
0088             }
0089         }
0090         p = p->next;
0091     }
0092     return p;
0093 }
0094 
0095 int gpiolib_drv_register(struct gpiolib_drv *drv, void *handle)
0096 {
0097     struct gpiolib_port *port;
0098 
0099     if ( !drv || !drv->ops )
0100         return -1;
0101 
0102     port = grlib_calloc(1, sizeof(*port));
0103     if ( port == NULL )
0104         return -1;
0105 
0106     port->handle = handle;
0107     port->minor = port_nr++;
0108     port->drv = drv;
0109 
0110     gpiolib_list_add(port);
0111 
0112     return 0;
0113 }
0114 
0115 void gpiolib_show(int port, void *handle)
0116 {
0117     struct gpiolib_port *p;
0118 
0119     if ( port == -1 ) {
0120         p = gpiolib_ports;
0121         while (p != NULL) {
0122             if ( p->drv->ops->show )
0123                 p->drv->ops->show(p->handle);
0124             p = p->next;
0125         }
0126     } else {
0127         if ( handle ) {
0128             p = handle;
0129         } else {
0130             p = gpiolib_find(port);
0131         }
0132         if ( p == NULL ) {
0133             printf("PORT %d NOT FOUND\n", port);
0134             return;
0135         }
0136         if ( p->drv->ops->show )
0137             p->drv->ops->show(p->handle);
0138     }
0139 }
0140 
0141 static void *gpiolib_open_internal(int port, char *devName)
0142 {
0143     struct gpiolib_port *p;
0144 
0145     if ( gpiolib_initied == 0 )
0146         return NULL;
0147 
0148     /* Find */
0149     if ( port >= 0 ) {
0150         p = gpiolib_find(port);
0151     } else {
0152         p = gpiolib_find_by_name(devName);
0153     }
0154     if ( p == NULL )
0155         return NULL;
0156 
0157     if ( p->open )
0158         return NULL;
0159 
0160     p->open = 1;
0161     return p;
0162 }
0163 
0164 void *gpiolib_open(int port)
0165 {
0166     return gpiolib_open_internal(port, NULL);
0167 }
0168 
0169 void *gpiolib_open_by_name(char *devName)
0170 {
0171     return gpiolib_open_internal(-1, devName);
0172 }
0173 
0174 void gpiolib_close(void *handle)
0175 {
0176     struct gpiolib_port *p = handle;
0177 
0178     if ( p && p->open ) {
0179         p->open = 0;
0180     }
0181 }
0182 
0183 int gpiolib_set_config(void *handle, struct gpiolib_config *cfg)
0184 {
0185     struct gpiolib_port *port = handle;
0186 
0187     if ( !port || !cfg )
0188         return -1;
0189 
0190     if ( !port->drv->ops->config )
0191         return -1;
0192 
0193     return port->drv->ops->config(port->handle, cfg);
0194 }
0195 
0196 int gpiolib_set(void *handle, int dir, int outval)
0197 {
0198     struct gpiolib_port *port = handle;
0199 
0200     if ( !port )
0201         return -1;
0202 
0203     if ( !port->drv->ops->set )
0204         return -1;
0205 
0206     return port->drv->ops->set(port->handle, dir, outval);  
0207 }
0208 
0209 int gpiolib_get(void *handle, int *inval)
0210 {
0211     struct gpiolib_port *port = handle;
0212 
0213     if ( !port || !inval)
0214         return -1;
0215 
0216     if ( !port->drv->ops->get )
0217         return -1;
0218 
0219     return port->drv->ops->get(port->handle, inval);
0220 }
0221 
0222 /*** IRQ Functions ***/
0223 int gpiolib_irq_register(void *handle, void *func, void *arg)
0224 {
0225     struct gpiolib_port *port = handle;
0226 
0227     if ( !port )
0228         return -1;
0229 
0230     if ( !port->drv->ops->irq_register )
0231         return -1;
0232 
0233     return port->drv->ops->irq_register(port->handle, func, arg);
0234 }
0235 
0236 static int gpiolib_irq_opts(void *handle, unsigned int options)
0237 {
0238     struct gpiolib_port *port = handle;
0239 
0240     if ( !port )
0241         return -1;
0242 
0243     if ( !port->drv->ops->irq_opts )
0244         return -1;
0245 
0246     return port->drv->ops->irq_opts(port->handle, options);
0247 }
0248 
0249 int gpiolib_irq_clear(void *handle)
0250 {
0251     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_CLEAR);
0252 }
0253 
0254 int gpiolib_irq_force(void *handle)
0255 {
0256     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_FORCE);
0257 }
0258 
0259 int gpiolib_irq_enable(void *handle)
0260 {
0261     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_ENABLE);
0262 }
0263 
0264 int gpiolib_irq_disable(void *handle)
0265 {
0266     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_DISABLE);
0267 }
0268 
0269 int gpiolib_irq_mask(void *handle)
0270 {
0271     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_MASK);
0272 }
0273 
0274 int gpiolib_irq_unmask(void *handle)
0275 {
0276     return gpiolib_irq_opts(handle, GPIOLIB_IRQ_UNMASK);
0277 }
0278 
0279 
0280 /*** Initialization ***/
0281 int gpiolib_initialize(void)
0282 {
0283     if ( gpiolib_initied != 0 )
0284         return 0;
0285 
0286     /* Initialize Libarary */
0287     port_nr = 0;
0288     gpiolib_ports = 0;
0289     gpiolib_initied = 1;
0290     return 0;
0291 }