1 /* 2 * GPIO driver definitions. 3 * (See below for additional copyright and licensing notices.) 4 * 5 * Copyright (C) 2017, 2018, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA 21 * 22 * 23 * Subject to other copyrights, being derived from the gpio headers in the io 24 * package. 25 * 26 * This file is part of TUD:OS and distributed under the terms of the 27 * GNU General Public License 2. 28 * Please see the COPYING-GPL-2 file for details. 29 */ 30 31 #pragma once 32 33 #include <l4/sys/err.h> 34 #include <l4/vbus/vbus_gpio.h> 35 #include <stdint.h> 36 37 struct gpio_port 38 { 39 uint32_t pull_ups, pull_downs; 40 }; 41 42 typedef struct Pin_slice 43 { 44 unsigned offset; 45 unsigned mask; 46 } Pin_slice; 47 48 #ifdef __cplusplus 49 50 namespace Hw { 51 52 // IRQ control for each GPIO pin. 53 54 class Gpio_irq_pin 55 { 56 public: 57 virtual void do_mask() = 0; 58 virtual void do_unmask() = 0; 59 virtual bool do_set_mode(unsigned mode) = 0; 60 virtual int clear() = 0; 61 virtual bool enabled() = 0; 62 }; 63 64 // GPIO peripheral control. 65 66 class Gpio_chip 67 { 68 protected: 69 unsigned _nr_pins; 70 71 // Convenience method for obtaining the bit corresponding to a pin. 72 73 l4_uint32_t _pin_bit(unsigned pin) 74 { return 1 << (pin & 31); } 75 76 // Convenience method for obtaining the bit position of a pin. 77 78 unsigned _pin_shift(unsigned pin) 79 { return pin % 32; } 80 81 // Permit only "aligned" accesses to registers. 82 83 unsigned _reg_offset_check(unsigned pin_offset) const 84 { 85 switch (pin_offset) 86 { 87 case 0: 88 return 0; 89 90 default: 91 throw -L4_EINVAL; 92 } 93 } 94 95 public: 96 explicit Gpio_chip(unsigned nr_pins) 97 : _nr_pins(nr_pins) 98 { 99 } 100 101 /// Modes used for setup() 102 enum Fix_mode 103 { 104 Input = L4VBUS_GPIO_SETUP_INPUT, ///< Configure as input pin 105 Output = L4VBUS_GPIO_SETUP_OUTPUT, ///< Configure as output pin 106 Irq = L4VBUS_GPIO_SETUP_IRQ, ///< Configure as IRQ source 107 }; 108 109 /// Modes used for pull up / pull down (config_pull()) 110 enum Pull_mode 111 { 112 Pull_none = L4VBUS_GPIO_PIN_PULL_NONE, ///< No pull up or pull down resistors 113 Pull_up = L4VBUS_GPIO_PIN_PULL_UP, ///< Enable pull up resistor 114 Pull_down = L4VBUS_GPIO_PIN_PULL_DOWN, ///< Enable pull down resistor 115 }; 116 117 // Generic function options 118 enum Function_levels 119 { 120 Function_gpio, 121 Function_alt, 122 Function_irq, 123 }; 124 125 /** 126 * \brief Request number of pins from GPIO chip 127 * \return Number of pins of this GPIO chip 128 */ 129 virtual unsigned nr_pins() const 130 { return _nr_pins; } 131 132 /** 133 * \brief Generic (platform independent) setup for a pin. 134 * \param pin the pin number to configure. 135 * \param mode the mode for the pin (see Fix_mode). 136 * \param value the value if the pin is configured as output. 137 */ 138 virtual void setup(unsigned pin, unsigned mode, int value = 0) = 0; 139 140 /** 141 * \brief Generic (platform independet) function to set a pin's pull up/down mode 142 * \param pin The pin number to configure. 143 * \param mode The pull up/down mode (see Pull_mode). 144 */ 145 virtual void config_pull(unsigned pin, unsigned mode) = 0; 146 147 /** 148 * \brief Set platform specific pad configuration. 149 * \param pin the pin to configure. 150 * \param func a platform specific sub-function of a pad to be configured 151 * \param value a platform specific value for the given sub-function. 152 */ 153 virtual void config_pad(unsigned pin, unsigned func, unsigned value) = 0; 154 155 /** 156 * \brief Get Platform specific pad configuration. 157 * \param pin the pin to configure. 158 * \param func a platform specific sub-function of a pad to be configured 159 * \retparam value a platform specific value for the given sub-function. 160 */ 161 virtual void config_get(unsigned pin, unsigned func, unsigned *value) = 0; 162 163 /** 164 * \brief Get platform specific pad configuration. 165 * \param pin the pin to configure. 166 * \param func a platform specific sub-function of a pad to be configured 167 * \param value a platform specific value for the given sub-function. 168 */ 169 virtual void config_pad_get(unsigned pin, unsigned *func, unsigned *value) = 0; 170 171 /** 172 * \brief Get the value of the given pin (generic API). 173 * \param pin the pin to read the value from. 174 */ 175 virtual int get(unsigned pin) = 0; 176 177 /** 178 * \brief Set the value of the given pin (generic API). 179 * \pre The pin has to be configured as output before using this function, 180 * otherwise this call will be ignored. 181 * \param pin the pin to write the value to. 182 * \param value the value to program for output (0 or 1). 183 */ 184 virtual void set(unsigned pin, int value) = 0; 185 186 /** 187 * \brief Setup multiple pins (generic API) 188 * \param mask the pins to actually set up. 189 * \param mode the mode for the pins (see Fix_mode). 190 * \param outvalue the value if configured as output. 191 */ 192 virtual void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalue = 0) = 0; 193 194 /** 195 * \brief Configure multiple pads at once (platform specific API). 196 * \param mask the pads to configure. 197 * \param func the platform-specific sub-function to configure. 198 * \param value the platform-specific value to set for the sub-function. 199 * \see config_pad() 200 */ 201 virtual void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value) = 0; 202 203 /** 204 * \brief Set the value for multiple output pins at once. 205 * \param mask the pins that shall actually be set to the given values. 206 * \param data the bit-wise value for each pin to set (according to mask). 207 */ 208 virtual void multi_set(Pin_slice const &mask, unsigned data) = 0; 209 210 /** 211 * \brief Get the value for all pins at once. 212 */ 213 virtual unsigned multi_get(unsigned offset) = 0; 214 215 216 void output(unsigned pin, int value) 217 { setup(pin, Output, value); } 218 219 void input(unsigned pin) 220 { setup(pin, Input); } 221 222 void multi_output(Pin_slice const &mask, unsigned data) 223 { multi_setup(mask, mask.mask, data); } 224 225 void multi_input(Pin_slice const &mask) 226 { multi_setup(mask, ~mask.mask); } 227 }; 228 229 } 230 231 #else 232 233 typedef enum { 234 false = 0, 235 true = 1 236 } bool; 237 238 /// Modes used for setup() 239 enum Fix_mode 240 { 241 Fix_input = L4VBUS_GPIO_SETUP_INPUT, ///< Configure as input pin 242 Fix_output = L4VBUS_GPIO_SETUP_OUTPUT, ///< Configure as output pin 243 Fix_irq = L4VBUS_GPIO_SETUP_IRQ, ///< Configure as IRQ source 244 }; 245 246 /// Modes used for pull up / pull down (config_pull()) 247 enum Pull_mode 248 { 249 Pull_none = L4VBUS_GPIO_PIN_PULL_NONE, ///< No pull up or pull down resistors 250 Pull_up = L4VBUS_GPIO_PIN_PULL_UP, ///< Enable pull up resistor 251 Pull_down = L4VBUS_GPIO_PIN_PULL_DOWN, ///< Enable pull down resistor 252 }; 253 254 // Generic function options 255 enum Function_levels 256 { 257 Function_gpio, 258 Function_alt, 259 Function_irq, 260 }; 261 262 #endif /* __cplusplus */