1 /* 2 * Copyright (c) 2009 Wind River Systems, Inc. 3 * Tom Rix <Tom.Rix@windriver.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0 6 * 7 * This work is derived from the linux 2.6.27 kernel source 8 * To fetch, use the kernel repository 9 * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 10 * Use the v2.6.27 tag. 11 * 12 * Below is the original's header including its copyright 13 * 14 * linux/arch/arm/plat-omap/gpio.c 15 * 16 * Support functions for OMAP GPIO 17 * 18 * Copyright (C) 2003-2005 Nokia Corporation 19 * Written by Juha Yrjölä <juha.yrjola@nokia.com> 20 */ 21 #include <common.h> 22 #include <dm.h> 23 #include <asm/gpio.h> 24 #include <asm/io.h> 25 #include <asm/errno.h> 26 27 #define OMAP_GPIO_DIR_OUT 0 28 #define OMAP_GPIO_DIR_IN 1 29 30 #ifdef CONFIG_DM_GPIO 31 32 #define GPIO_NAME_SIZE 20 33 #define GPIO_PER_BANK 32 34 35 struct gpio_bank { 36 char label[GPIO_PER_BANK][GPIO_NAME_SIZE]; 37 /* TODO(sjg@chromium.org): Can we use a struct here? */ 38 void *base; /* address of registers in physical memory */ 39 enum gpio_method method; 40 }; 41 42 #endif 43 44 static inline int get_gpio_index(int gpio) 45 { 46 return gpio & 0x1f; 47 } 48 49 int gpio_is_valid(int gpio) 50 { 51 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); 52 } 53 54 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, 55 int is_input) 56 { 57 void *reg = bank->base; 58 u32 l; 59 60 switch (bank->method) { 61 case METHOD_GPIO_24XX: 62 reg += OMAP_GPIO_OE; 63 break; 64 default: 65 return; 66 } 67 l = __raw_readl(reg); 68 if (is_input) 69 l |= 1 << gpio; 70 else 71 l &= ~(1 << gpio); 72 __raw_writel(l, reg); 73 } 74 75 /** 76 * Get the direction of the GPIO by reading the GPIO_OE register 77 * corresponding to the specified bank. 78 */ 79 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) 80 { 81 void *reg = bank->base; 82 u32 v; 83 84 switch (bank->method) { 85 case METHOD_GPIO_24XX: 86 reg += OMAP_GPIO_OE; 87 break; 88 default: 89 return -1; 90 } 91 92 v = __raw_readl(reg); 93 94 if (v & (1 << gpio)) 95 return OMAP_GPIO_DIR_IN; 96 else 97 return OMAP_GPIO_DIR_OUT; 98 } 99 100 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, 101 int enable) 102 { 103 void *reg = bank->base; 104 u32 l = 0; 105 106 switch (bank->method) { 107 case METHOD_GPIO_24XX: 108 if (enable) 109 reg += OMAP_GPIO_SETDATAOUT; 110 else 111 reg += OMAP_GPIO_CLEARDATAOUT; 112 l = 1 << gpio; 113 break; 114 default: 115 printf("omap3-gpio unknown bank method %s %d\n", 116 __FILE__, __LINE__); 117 return; 118 } 119 __raw_writel(l, reg); 120 } 121 122 static int _get_gpio_value(const struct gpio_bank *bank, int gpio) 123 { 124 void *reg = bank->base; 125 int input; 126 127 switch (bank->method) { 128 case METHOD_GPIO_24XX: 129 input = _get_gpio_direction(bank, gpio); 130 switch (input) { 131 case OMAP_GPIO_DIR_IN: 132 reg += OMAP_GPIO_DATAIN; 133 break; 134 case OMAP_GPIO_DIR_OUT: 135 reg += OMAP_GPIO_DATAOUT; 136 break; 137 default: 138 return -1; 139 } 140 break; 141 default: 142 return -1; 143 } 144 145 return (__raw_readl(reg) & (1 << gpio)) != 0; 146 } 147 148 #ifndef CONFIG_DM_GPIO 149 150 static inline const struct gpio_bank *get_gpio_bank(int gpio) 151 { 152 return &omap_gpio_bank[gpio >> 5]; 153 } 154 155 static int check_gpio(int gpio) 156 { 157 if (!gpio_is_valid(gpio)) { 158 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); 159 return -1; 160 } 161 return 0; 162 } 163 164 /** 165 * Set value of the specified gpio 166 */ 167 int gpio_set_value(unsigned gpio, int value) 168 { 169 const struct gpio_bank *bank; 170 171 if (check_gpio(gpio) < 0) 172 return -1; 173 bank = get_gpio_bank(gpio); 174 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 175 176 return 0; 177 } 178 179 /** 180 * Get value of the specified gpio 181 */ 182 int gpio_get_value(unsigned gpio) 183 { 184 const struct gpio_bank *bank; 185 186 if (check_gpio(gpio) < 0) 187 return -1; 188 bank = get_gpio_bank(gpio); 189 190 return _get_gpio_value(bank, get_gpio_index(gpio)); 191 } 192 193 /** 194 * Set gpio direction as input 195 */ 196 int gpio_direction_input(unsigned gpio) 197 { 198 const struct gpio_bank *bank; 199 200 if (check_gpio(gpio) < 0) 201 return -1; 202 203 bank = get_gpio_bank(gpio); 204 _set_gpio_direction(bank, get_gpio_index(gpio), 1); 205 206 return 0; 207 } 208 209 /** 210 * Set gpio direction as output 211 */ 212 int gpio_direction_output(unsigned gpio, int value) 213 { 214 const struct gpio_bank *bank; 215 216 if (check_gpio(gpio) < 0) 217 return -1; 218 219 bank = get_gpio_bank(gpio); 220 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 221 _set_gpio_direction(bank, get_gpio_index(gpio), 0); 222 223 return 0; 224 } 225 226 /** 227 * Request a gpio before using it. 228 * 229 * NOTE: Argument 'label' is unused. 230 */ 231 int gpio_request(unsigned gpio, const char *label) 232 { 233 if (check_gpio(gpio) < 0) 234 return -1; 235 236 return 0; 237 } 238 239 /** 240 * Reset and free the gpio after using it. 241 */ 242 int gpio_free(unsigned gpio) 243 { 244 return 0; 245 } 246 247 #else /* new driver model interface CONFIG_DM_GPIO */ 248 249 /** 250 * gpio_is_requested() - check if a GPIO has been requested 251 * 252 * @bank: Bank to check 253 * @offset: GPIO offset within bank to check 254 * @return true if marked as requested, false if not 255 */ 256 static inline bool gpio_is_requested(struct gpio_bank *bank, int offset) 257 { 258 return *bank->label[offset] != '\0'; 259 } 260 261 static int omap_gpio_is_output(struct gpio_bank *bank, int offset) 262 { 263 return _get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT; 264 } 265 266 static int check_requested(struct udevice *dev, unsigned offset, 267 const char *func) 268 { 269 struct gpio_bank *bank = dev_get_priv(dev); 270 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 271 272 if (!gpio_is_requested(bank, offset)) { 273 printf("omap_gpio: %s: error: gpio %s%d not requested\n", 274 func, uc_priv->bank_name, offset); 275 return -EPERM; 276 } 277 278 return 0; 279 } 280 281 /* set GPIO pin 'gpio' as an input */ 282 static int omap_gpio_direction_input(struct udevice *dev, unsigned offset) 283 { 284 struct gpio_bank *bank = dev_get_priv(dev); 285 int ret; 286 287 ret = check_requested(dev, offset, __func__); 288 if (ret) 289 return ret; 290 291 /* Configure GPIO direction as input. */ 292 _set_gpio_direction(bank, offset, 1); 293 294 return 0; 295 } 296 297 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 298 static int omap_gpio_direction_output(struct udevice *dev, unsigned offset, 299 int value) 300 { 301 struct gpio_bank *bank = dev_get_priv(dev); 302 int ret; 303 304 ret = check_requested(dev, offset, __func__); 305 if (ret) 306 return ret; 307 308 _set_gpio_dataout(bank, offset, value); 309 _set_gpio_direction(bank, offset, 0); 310 311 return 0; 312 } 313 314 /* read GPIO IN value of pin 'gpio' */ 315 static int omap_gpio_get_value(struct udevice *dev, unsigned offset) 316 { 317 struct gpio_bank *bank = dev_get_priv(dev); 318 int ret; 319 320 ret = check_requested(dev, offset, __func__); 321 if (ret) 322 return ret; 323 324 return _get_gpio_value(bank, offset); 325 } 326 327 /* write GPIO OUT value to pin 'gpio' */ 328 static int omap_gpio_set_value(struct udevice *dev, unsigned offset, 329 int value) 330 { 331 struct gpio_bank *bank = dev_get_priv(dev); 332 int ret; 333 334 ret = check_requested(dev, offset, __func__); 335 if (ret) 336 return ret; 337 338 _set_gpio_dataout(bank, offset, value); 339 340 return 0; 341 } 342 343 static int omap_gpio_get_state(struct udevice *dev, unsigned int offset, 344 char *buf, int bufsize) 345 { 346 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 347 struct gpio_bank *bank = dev_get_priv(dev); 348 const char *label; 349 bool requested; 350 bool is_output; 351 int size; 352 353 label = bank->label[offset]; 354 is_output = omap_gpio_is_output(bank->base, offset); 355 size = snprintf(buf, bufsize, "%s%d: ", 356 uc_priv->bank_name ? uc_priv->bank_name : "", offset); 357 buf += size; 358 bufsize -= size; 359 requested = gpio_is_requested(bank, offset); 360 snprintf(buf, bufsize, "%s: %d [%c]%s%s", 361 is_output ? "out" : " in", 362 _get_gpio_value(bank, offset), 363 requested ? 'x' : ' ', 364 requested ? " " : "", 365 label); 366 367 return 0; 368 } 369 370 static int omap_gpio_request(struct udevice *dev, unsigned offset, 371 const char *label) 372 { 373 struct gpio_bank *bank = dev_get_priv(dev); 374 375 if (gpio_is_requested(bank, offset)) 376 return -EBUSY; 377 378 strncpy(bank->label[offset], label, GPIO_NAME_SIZE); 379 bank->label[offset][GPIO_NAME_SIZE - 1] = '\0'; 380 381 return 0; 382 } 383 384 static int omap_gpio_free(struct udevice *dev, unsigned offset) 385 { 386 struct gpio_bank *bank = dev_get_priv(dev); 387 int ret; 388 389 ret = check_requested(dev, offset, __func__); 390 if (ret) 391 return ret; 392 bank->label[offset][0] = '\0'; 393 394 return 0; 395 } 396 397 static int omap_gpio_get_function(struct udevice *dev, unsigned offset) 398 { 399 struct gpio_bank *bank = dev_get_priv(dev); 400 401 if (!gpio_is_requested(bank, offset)) 402 return GPIOF_UNUSED; 403 404 /* GPIOF_FUNC is not implemented yet */ 405 if (_get_gpio_direction(bank->base, offset)) 406 return GPIOF_OUTPUT; 407 else 408 return GPIOF_INPUT; 409 } 410 411 static const struct dm_gpio_ops gpio_omap_ops = { 412 .request = omap_gpio_request, 413 .free = omap_gpio_free, 414 .direction_input = omap_gpio_direction_input, 415 .direction_output = omap_gpio_direction_output, 416 .get_value = omap_gpio_get_value, 417 .set_value = omap_gpio_set_value, 418 .get_function = omap_gpio_get_function, 419 .get_state = omap_gpio_get_state, 420 }; 421 422 static int omap_gpio_probe(struct udevice *dev) 423 { 424 struct gpio_bank *bank = dev_get_priv(dev); 425 struct omap_gpio_platdata *plat = dev_get_platdata(dev); 426 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 427 char name[18], *str; 428 429 sprintf(name, "GPIO%d_", plat->bank_index); 430 str = strdup(name); 431 if (!str) 432 return -ENOMEM; 433 uc_priv->bank_name = str; 434 uc_priv->gpio_count = GPIO_PER_BANK; 435 bank->base = (void *)plat->base; 436 bank->method = plat->method; 437 438 return 0; 439 } 440 441 U_BOOT_DRIVER(gpio_omap) = { 442 .name = "gpio_omap", 443 .id = UCLASS_GPIO, 444 .ops = &gpio_omap_ops, 445 .probe = omap_gpio_probe, 446 .priv_auto_alloc_size = sizeof(struct gpio_bank), 447 }; 448 449 #endif /* CONFIG_DM_GPIO */ 450