1 /* 2 * Copyright (c) 2009 Wind River Systems, Inc. 3 * Tom Rix <Tom.Rix@windriver.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of 8 * the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 18 * MA 02111-1307 USA 19 * 20 * This work is derived from the linux 2.6.27 kernel source 21 * To fetch, use the kernel repository 22 * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 23 * Use the v2.6.27 tag. 24 * 25 * Below is the original's header including its copyright 26 * 27 * linux/arch/arm/plat-omap/gpio.c 28 * 29 * Support functions for OMAP GPIO 30 * 31 * Copyright (C) 2003-2005 Nokia Corporation 32 * Written by Juha Yrjölä <juha.yrjola@nokia.com> 33 * 34 * This program is free software; you can redistribute it and/or modify 35 * it under the terms of the GNU General Public License version 2 as 36 * published by the Free Software Foundation. 37 */ 38 #include <common.h> 39 #include <asm/gpio.h> 40 #include <asm/io.h> 41 #include <asm/errno.h> 42 43 #define OMAP_GPIO_DIR_OUT 0 44 #define OMAP_GPIO_DIR_IN 1 45 46 static inline const struct gpio_bank *get_gpio_bank(int gpio) 47 { 48 return &omap_gpio_bank[gpio >> 5]; 49 } 50 51 static inline int get_gpio_index(int gpio) 52 { 53 return gpio & 0x1f; 54 } 55 56 static inline int gpio_valid(int gpio) 57 { 58 if (gpio < 0) 59 return -1; 60 if (gpio < 192) 61 return 0; 62 return -1; 63 } 64 65 static int check_gpio(int gpio) 66 { 67 if (gpio_valid(gpio) < 0) { 68 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); 69 return -1; 70 } 71 return 0; 72 } 73 74 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, 75 int is_input) 76 { 77 void *reg = bank->base; 78 u32 l; 79 80 switch (bank->method) { 81 case METHOD_GPIO_24XX: 82 reg += OMAP_GPIO_OE; 83 break; 84 default: 85 return; 86 } 87 l = __raw_readl(reg); 88 if (is_input) 89 l |= 1 << gpio; 90 else 91 l &= ~(1 << gpio); 92 __raw_writel(l, reg); 93 } 94 95 /** 96 * Get the direction of the GPIO by reading the GPIO_OE register 97 * corresponding to the specified bank. 98 */ 99 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) 100 { 101 void *reg = bank->base; 102 u32 v; 103 104 switch (bank->method) { 105 case METHOD_GPIO_24XX: 106 reg += OMAP_GPIO_OE; 107 break; 108 default: 109 return -1; 110 } 111 112 v = __raw_readl(reg); 113 114 if (v & (1 << gpio)) 115 return OMAP_GPIO_DIR_IN; 116 else 117 return OMAP_GPIO_DIR_OUT; 118 } 119 120 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, 121 int enable) 122 { 123 void *reg = bank->base; 124 u32 l = 0; 125 126 switch (bank->method) { 127 case METHOD_GPIO_24XX: 128 if (enable) 129 reg += OMAP_GPIO_SETDATAOUT; 130 else 131 reg += OMAP_GPIO_CLEARDATAOUT; 132 l = 1 << gpio; 133 break; 134 default: 135 printf("omap3-gpio unknown bank method %s %d\n", 136 __FILE__, __LINE__); 137 return; 138 } 139 __raw_writel(l, reg); 140 } 141 142 /** 143 * Set value of the specified gpio 144 */ 145 int gpio_set_value(unsigned gpio, int value) 146 { 147 const struct gpio_bank *bank; 148 149 if (check_gpio(gpio) < 0) 150 return -1; 151 bank = get_gpio_bank(gpio); 152 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 153 154 return 0; 155 } 156 157 /** 158 * Get value of the specified gpio 159 */ 160 int gpio_get_value(unsigned gpio) 161 { 162 const struct gpio_bank *bank; 163 void *reg; 164 int input; 165 166 if (check_gpio(gpio) < 0) 167 return -1; 168 bank = get_gpio_bank(gpio); 169 reg = bank->base; 170 switch (bank->method) { 171 case METHOD_GPIO_24XX: 172 input = _get_gpio_direction(bank, get_gpio_index(gpio)); 173 switch (input) { 174 case OMAP_GPIO_DIR_IN: 175 reg += OMAP_GPIO_DATAIN; 176 break; 177 case OMAP_GPIO_DIR_OUT: 178 reg += OMAP_GPIO_DATAOUT; 179 break; 180 default: 181 return -1; 182 } 183 break; 184 default: 185 return -1; 186 } 187 return (__raw_readl(reg) 188 & (1 << get_gpio_index(gpio))) != 0; 189 } 190 191 /** 192 * Set gpio direction as input 193 */ 194 int gpio_direction_input(unsigned gpio) 195 { 196 const struct gpio_bank *bank; 197 198 if (check_gpio(gpio) < 0) 199 return -1; 200 201 bank = get_gpio_bank(gpio); 202 _set_gpio_direction(bank, get_gpio_index(gpio), 1); 203 204 return 0; 205 } 206 207 /** 208 * Set gpio direction as output 209 */ 210 int gpio_direction_output(unsigned gpio, int value) 211 { 212 const struct gpio_bank *bank; 213 214 if (check_gpio(gpio) < 0) 215 return -1; 216 217 bank = get_gpio_bank(gpio); 218 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 219 _set_gpio_direction(bank, get_gpio_index(gpio), 0); 220 221 return 0; 222 } 223 224 /** 225 * Request a gpio before using it. 226 * 227 * NOTE: Argument 'label' is unused. 228 */ 229 int gpio_request(unsigned gpio, const char *label) 230 { 231 if (check_gpio(gpio) < 0) 232 return -1; 233 234 return 0; 235 } 236 237 /** 238 * Reset and free the gpio after using it. 239 */ 240 int gpio_free(unsigned gpio) 241 { 242 return 0; 243 } 244