1 /* 2 * Copyright (c) 2013 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <errno.h> 10 #include <asm/gpio.h> 11 12 /** 13 * gpio_to_device() - Convert global GPIO number to device, number 14 * gpio: The numeric representation of the GPIO 15 * 16 * Convert the GPIO number to an entry in the list of GPIOs 17 * or GPIO blocks registered with the GPIO controller. Returns 18 * entry on success, NULL on error. 19 */ 20 static int gpio_to_device(unsigned int gpio, struct device **devp, 21 unsigned int *offset) 22 { 23 struct gpio_dev_priv *uc_priv; 24 struct device *dev; 25 int ret; 26 27 for (ret = uclass_first_device(UCLASS_GPIO, &dev); 28 dev; 29 ret = uclass_next_device(&dev)) { 30 uc_priv = dev->uclass_priv; 31 if (gpio >= uc_priv->gpio_base && 32 gpio < uc_priv->gpio_base + uc_priv->gpio_count) { 33 *devp = dev; 34 *offset = gpio - uc_priv->gpio_base; 35 return 0; 36 } 37 } 38 39 /* No such GPIO */ 40 return ret ? ret : -EINVAL; 41 } 42 43 int gpio_lookup_name(const char *name, struct device **devp, 44 unsigned int *offsetp, unsigned int *gpiop) 45 { 46 struct gpio_dev_priv *uc_priv; 47 struct device *dev; 48 int ret; 49 50 if (devp) 51 *devp = NULL; 52 for (ret = uclass_first_device(UCLASS_GPIO, &dev); 53 dev; 54 ret = uclass_next_device(&dev)) { 55 ulong offset; 56 int len; 57 58 uc_priv = dev->uclass_priv; 59 len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0; 60 61 if (!strncmp(name, uc_priv->bank_name, len)) { 62 if (strict_strtoul(name + len, 10, &offset)) 63 continue; 64 if (devp) 65 *devp = dev; 66 if (offsetp) 67 *offsetp = offset; 68 if (gpiop) 69 *gpiop = uc_priv->gpio_base + offset; 70 return 0; 71 } 72 } 73 74 return ret ? ret : -EINVAL; 75 } 76 77 /** 78 * gpio_request() - [COMPAT] Request GPIO 79 * gpio: GPIO number 80 * label: Name for the requested GPIO 81 * 82 * This function implements the API that's compatible with current 83 * GPIO API used in U-Boot. The request is forwarded to particular 84 * GPIO driver. Returns 0 on success, negative value on error. 85 */ 86 int gpio_request(unsigned gpio, const char *label) 87 { 88 unsigned int offset; 89 struct device *dev; 90 int ret; 91 92 ret = gpio_to_device(gpio, &dev, &offset); 93 if (ret) 94 return ret; 95 96 if (!gpio_get_ops(dev)->request) 97 return 0; 98 99 return gpio_get_ops(dev)->request(dev, offset, label); 100 } 101 102 /** 103 * gpio_free() - [COMPAT] Relinquish GPIO 104 * gpio: GPIO number 105 * 106 * This function implements the API that's compatible with current 107 * GPIO API used in U-Boot. The request is forwarded to particular 108 * GPIO driver. Returns 0 on success, negative value on error. 109 */ 110 int gpio_free(unsigned gpio) 111 { 112 unsigned int offset; 113 struct device *dev; 114 int ret; 115 116 ret = gpio_to_device(gpio, &dev, &offset); 117 if (ret) 118 return ret; 119 120 if (!gpio_get_ops(dev)->free) 121 return 0; 122 return gpio_get_ops(dev)->free(dev, offset); 123 } 124 125 /** 126 * gpio_direction_input() - [COMPAT] Set GPIO direction to input 127 * gpio: GPIO number 128 * 129 * This function implements the API that's compatible with current 130 * GPIO API used in U-Boot. The request is forwarded to particular 131 * GPIO driver. Returns 0 on success, negative value on error. 132 */ 133 int gpio_direction_input(unsigned gpio) 134 { 135 unsigned int offset; 136 struct device *dev; 137 int ret; 138 139 ret = gpio_to_device(gpio, &dev, &offset); 140 if (ret) 141 return ret; 142 143 return gpio_get_ops(dev)->direction_input(dev, offset); 144 } 145 146 /** 147 * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value 148 * gpio: GPIO number 149 * value: Logical value to be set on the GPIO pin 150 * 151 * This function implements the API that's compatible with current 152 * GPIO API used in U-Boot. The request is forwarded to particular 153 * GPIO driver. Returns 0 on success, negative value on error. 154 */ 155 int gpio_direction_output(unsigned gpio, int value) 156 { 157 unsigned int offset; 158 struct device *dev; 159 int ret; 160 161 ret = gpio_to_device(gpio, &dev, &offset); 162 if (ret) 163 return ret; 164 165 return gpio_get_ops(dev)->direction_output(dev, offset, value); 166 } 167 168 /** 169 * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value 170 * gpio: GPIO number 171 * 172 * This function implements the API that's compatible with current 173 * GPIO API used in U-Boot. The request is forwarded to particular 174 * GPIO driver. Returns the value of the GPIO pin, or negative value 175 * on error. 176 */ 177 int gpio_get_value(unsigned gpio) 178 { 179 unsigned int offset; 180 struct device *dev; 181 int ret; 182 183 ret = gpio_to_device(gpio, &dev, &offset); 184 if (ret) 185 return ret; 186 187 return gpio_get_ops(dev)->get_value(dev, offset); 188 } 189 190 /** 191 * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin 192 * gpio: GPIO number 193 * value: Logical value to be set on the GPIO pin. 194 * 195 * This function implements the API that's compatible with current 196 * GPIO API used in U-Boot. The request is forwarded to particular 197 * GPIO driver. Returns 0 on success, negative value on error. 198 */ 199 int gpio_set_value(unsigned gpio, int value) 200 { 201 unsigned int offset; 202 struct device *dev; 203 int ret; 204 205 ret = gpio_to_device(gpio, &dev, &offset); 206 if (ret) 207 return ret; 208 209 return gpio_get_ops(dev)->set_value(dev, offset, value); 210 } 211 212 const char *gpio_get_bank_info(struct device *dev, int *bit_count) 213 { 214 struct gpio_dev_priv *priv; 215 216 /* Must be called on an active device */ 217 priv = dev->uclass_priv; 218 assert(priv); 219 220 *bit_count = priv->gpio_count; 221 return priv->bank_name; 222 } 223 224 /* We need to renumber the GPIOs when any driver is probed/removed */ 225 static int gpio_renumber(void) 226 { 227 struct gpio_dev_priv *uc_priv; 228 struct device *dev; 229 struct uclass *uc; 230 unsigned base; 231 int ret; 232 233 ret = uclass_get(UCLASS_GPIO, &uc); 234 if (ret) 235 return ret; 236 237 /* Ensure that we have a base for each bank */ 238 base = 0; 239 uclass_foreach_dev(dev, uc) { 240 if (device_active(dev)) { 241 uc_priv = dev->uclass_priv; 242 uc_priv->gpio_base = base; 243 base += uc_priv->gpio_count; 244 } 245 } 246 247 return 0; 248 } 249 250 static int gpio_post_probe(struct device *dev) 251 { 252 return gpio_renumber(); 253 } 254 255 static int gpio_pre_remove(struct device *dev) 256 { 257 return gpio_renumber(); 258 } 259 260 UCLASS_DRIVER(gpio) = { 261 .id = UCLASS_GPIO, 262 .name = "gpio", 263 .post_probe = gpio_post_probe, 264 .pre_remove = gpio_pre_remove, 265 .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), 266 }; 267