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 <asm/gpio.h> 23 #include <asm/io.h> 24 #include <asm/errno.h> 25 26 #define OMAP_GPIO_DIR_OUT 0 27 #define OMAP_GPIO_DIR_IN 1 28 29 static inline const struct gpio_bank *get_gpio_bank(int gpio) 30 { 31 return &omap_gpio_bank[gpio >> 5]; 32 } 33 34 static inline int get_gpio_index(int gpio) 35 { 36 return gpio & 0x1f; 37 } 38 39 int gpio_is_valid(int gpio) 40 { 41 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); 42 } 43 44 static int check_gpio(int gpio) 45 { 46 if (!gpio_is_valid(gpio)) { 47 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); 48 return -1; 49 } 50 return 0; 51 } 52 53 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, 54 int is_input) 55 { 56 void *reg = bank->base; 57 u32 l; 58 59 switch (bank->method) { 60 case METHOD_GPIO_24XX: 61 reg += OMAP_GPIO_OE; 62 break; 63 default: 64 return; 65 } 66 l = __raw_readl(reg); 67 if (is_input) 68 l |= 1 << gpio; 69 else 70 l &= ~(1 << gpio); 71 __raw_writel(l, reg); 72 } 73 74 /** 75 * Get the direction of the GPIO by reading the GPIO_OE register 76 * corresponding to the specified bank. 77 */ 78 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) 79 { 80 void *reg = bank->base; 81 u32 v; 82 83 switch (bank->method) { 84 case METHOD_GPIO_24XX: 85 reg += OMAP_GPIO_OE; 86 break; 87 default: 88 return -1; 89 } 90 91 v = __raw_readl(reg); 92 93 if (v & (1 << gpio)) 94 return OMAP_GPIO_DIR_IN; 95 else 96 return OMAP_GPIO_DIR_OUT; 97 } 98 99 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, 100 int enable) 101 { 102 void *reg = bank->base; 103 u32 l = 0; 104 105 switch (bank->method) { 106 case METHOD_GPIO_24XX: 107 if (enable) 108 reg += OMAP_GPIO_SETDATAOUT; 109 else 110 reg += OMAP_GPIO_CLEARDATAOUT; 111 l = 1 << gpio; 112 break; 113 default: 114 printf("omap3-gpio unknown bank method %s %d\n", 115 __FILE__, __LINE__); 116 return; 117 } 118 __raw_writel(l, reg); 119 } 120 121 /** 122 * Set value of the specified gpio 123 */ 124 int gpio_set_value(unsigned gpio, int value) 125 { 126 const struct gpio_bank *bank; 127 128 if (check_gpio(gpio) < 0) 129 return -1; 130 bank = get_gpio_bank(gpio); 131 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 132 133 return 0; 134 } 135 136 /** 137 * Get value of the specified gpio 138 */ 139 int gpio_get_value(unsigned gpio) 140 { 141 const struct gpio_bank *bank; 142 void *reg; 143 int input; 144 145 if (check_gpio(gpio) < 0) 146 return -1; 147 bank = get_gpio_bank(gpio); 148 reg = bank->base; 149 switch (bank->method) { 150 case METHOD_GPIO_24XX: 151 input = _get_gpio_direction(bank, get_gpio_index(gpio)); 152 switch (input) { 153 case OMAP_GPIO_DIR_IN: 154 reg += OMAP_GPIO_DATAIN; 155 break; 156 case OMAP_GPIO_DIR_OUT: 157 reg += OMAP_GPIO_DATAOUT; 158 break; 159 default: 160 return -1; 161 } 162 break; 163 default: 164 return -1; 165 } 166 return (__raw_readl(reg) 167 & (1 << get_gpio_index(gpio))) != 0; 168 } 169 170 /** 171 * Set gpio direction as input 172 */ 173 int gpio_direction_input(unsigned gpio) 174 { 175 const struct gpio_bank *bank; 176 177 if (check_gpio(gpio) < 0) 178 return -1; 179 180 bank = get_gpio_bank(gpio); 181 _set_gpio_direction(bank, get_gpio_index(gpio), 1); 182 183 return 0; 184 } 185 186 /** 187 * Set gpio direction as output 188 */ 189 int gpio_direction_output(unsigned gpio, int value) 190 { 191 const struct gpio_bank *bank; 192 193 if (check_gpio(gpio) < 0) 194 return -1; 195 196 bank = get_gpio_bank(gpio); 197 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 198 _set_gpio_direction(bank, get_gpio_index(gpio), 0); 199 200 return 0; 201 } 202 203 /** 204 * Request a gpio before using it. 205 * 206 * NOTE: Argument 'label' is unused. 207 */ 208 int gpio_request(unsigned gpio, const char *label) 209 { 210 if (check_gpio(gpio) < 0) 211 return -1; 212 213 return 0; 214 } 215 216 /** 217 * Reset and free the gpio after using it. 218 */ 219 int gpio_free(unsigned gpio) 220 { 221 return 0; 222 } 223