diff options
Diffstat (limited to 'src/core/gpio.c')
| -rw-r--r-- | src/core/gpio.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/core/gpio.c b/src/core/gpio.c new file mode 100644 index 000000000..f57139a11 --- /dev/null +++ b/src/core/gpio.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdlib.h> +#include <errno.h> +#include <ipxe/gpio.h> + +/** @file + * + * General purpose I/O + * + */ + +/** List of GPIO controllers */ +static LIST_HEAD ( all_gpios ); + +/** + * Allocate GPIO controller + * + * @v count Number of GPIO pins + * @v priv_len Size of driver-private data + * @ret gpios GPIO controller, or NULL + */ +struct gpios * alloc_gpios ( unsigned int count, size_t priv_len ) { + struct gpios *gpios; + struct gpio *gpio; + size_t len; + unsigned int i; + + /* Allocate and initialise structure */ + len = ( sizeof ( *gpios ) + ( count * sizeof ( *gpio ) ) + priv_len ); + gpios = zalloc ( len ); + if ( ! gpios ) + return NULL; + gpios->count = count; + gpios->gpio = ( ( ( void * ) gpios ) + sizeof ( *gpios ) ); + gpios->priv = ( ( ( void * ) gpios ) + sizeof ( *gpios ) + + ( count * sizeof ( *gpio ) ) ); + + /* Initialise GPIO pins */ + for ( i = 0 ; i < count ; i++ ) { + gpio = &gpios->gpio[i]; + gpio->gpios = gpios; + gpio->index = i; + } + + return gpios; +} + +/** + * Register GPIO controller + * + * @v gpios GPIO controller + * @ret rc Return status code + */ +int gpios_register ( struct gpios *gpios ) { + + /* Add to list of GPIO controllers */ + gpios_get ( gpios ); + list_add_tail ( &gpios->list, &all_gpios ); + DBGC ( gpios, "GPIO %s registered with %d GPIOs\n", + gpios->dev->name, gpios->count ); + + return 0; +} + +/** + * Unregister GPIO controller + * + * @v gpios GPIO controller + */ +void gpios_unregister ( struct gpios *gpios ) { + + /* Remove from list of GPIO controllers */ + DBGC ( gpios, "GPIO %s unregistered\n", gpios->dev->name ); + list_del ( &gpios->list ); + gpios_put ( gpios ); +} + +/** + * Find GPIO controller + * + * @v bus_type Bus type + * @v location Bus location + * @ret gpios GPIO controller, or NULL + */ +struct gpios * gpios_find ( unsigned int bus_type, unsigned int location ) { + struct gpios *gpios; + + /* Scan through list of registered GPIO controllers */ + list_for_each_entry ( gpios, &all_gpios, list ) { + if ( ( gpios->dev->desc.bus_type == bus_type ) && + ( gpios->dev->desc.location == location ) ) + return gpios; + } + + return NULL; +} + +/** + * Get null GPIO input value + * + * @v gpios GPIO controller + * @v gpio GPIO pin + * @ret active Pin is in the active state + */ +static int null_gpio_in ( struct gpios *gpios __unused, + struct gpio *gpio __unused ) { + return 0; +} + +/** + * Set null GPIO output value + * + * @v gpios GPIO controller + * @v gpio GPIO pin + * @v active Set pin to active state + */ +static void null_gpio_out ( struct gpios *gpios __unused, + struct gpio *gpio __unused, int active __unused ) { + /* Nothing to do */ +} + +/** + * Configure null GPIO pin + * + * @v gpios GPIO controller + * @v gpio GPIO pin + * @v config Configuration + * @ret rc Return status code + */ +static int null_gpio_config ( struct gpios *gpios __unused, + struct gpio *gpio __unused, + unsigned int config __unused ) { + return -ENODEV; +} + +/** Null GPIO operations */ +struct gpio_operations null_gpio_operations = { + .in = null_gpio_in, + .out = null_gpio_out, + .config = null_gpio_config, +}; |
