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