| /* |
| * 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, |
| }; |