1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * See file CREDITS for list of people who contributed to this 4 * project. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 * MA 02111-1307 USA 20 */ 21 22 #include <common.h> 23 #include <asm/gpio.h> 24 25 /* Flags for each GPIO */ 26 #define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ 27 #define GPIOF_HIGH (1 << 1) /* Currently set high */ 28 #define GPIOF_RESERVED (1 << 2) /* Is in use / requested */ 29 30 struct gpio_state { 31 const char *label; /* label given by requester */ 32 u8 flags; /* flags (GPIOF_...) */ 33 }; 34 35 /* 36 * State of GPIOs 37 * TODO: Put this into sandbox state 38 */ 39 static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT]; 40 41 /* Access routines for GPIO state */ 42 static u8 *get_gpio_flags(unsigned gp) 43 { 44 /* assert()'s could be disabled, so make sure we handle that */ 45 assert(gp < ARRAY_SIZE(state)); 46 if (gp >= ARRAY_SIZE(state)) { 47 static u8 invalid_flags; 48 printf("sandbox_gpio: error: invalid gpio %u\n", gp); 49 return &invalid_flags; 50 } 51 52 return &state[gp].flags; 53 } 54 55 static int get_gpio_flag(unsigned gp, int flag) 56 { 57 return (*get_gpio_flags(gp) & flag) != 0; 58 } 59 60 static int set_gpio_flag(unsigned gp, int flag, int value) 61 { 62 u8 *gpio = get_gpio_flags(gp); 63 64 if (value) 65 *gpio |= flag; 66 else 67 *gpio &= ~flag; 68 69 return 0; 70 } 71 72 static int check_reserved(unsigned gpio, const char *func) 73 { 74 if (!get_gpio_flag(gpio, GPIOF_RESERVED)) { 75 printf("sandbox_gpio: %s: error: gpio %u not reserved\n", 76 func, gpio); 77 return -1; 78 } 79 80 return 0; 81 } 82 83 /* 84 * Back-channel sandbox-internal-only access to GPIO state 85 */ 86 87 int sandbox_gpio_get_value(unsigned gp) 88 { 89 if (get_gpio_flag(gp, GPIOF_OUTPUT)) 90 debug("sandbox_gpio: get_value on output gpio %u\n", gp); 91 return get_gpio_flag(gp, GPIOF_HIGH); 92 } 93 94 int sandbox_gpio_set_value(unsigned gp, int value) 95 { 96 return set_gpio_flag(gp, GPIOF_HIGH, value); 97 } 98 99 int sandbox_gpio_get_direction(unsigned gp) 100 { 101 return get_gpio_flag(gp, GPIOF_OUTPUT); 102 } 103 104 int sandbox_gpio_set_direction(unsigned gp, int output) 105 { 106 return set_gpio_flag(gp, GPIOF_OUTPUT, output); 107 } 108 109 /* 110 * These functions implement the public interface within U-Boot 111 */ 112 113 /* set GPIO port 'gp' as an input */ 114 int gpio_direction_input(unsigned gp) 115 { 116 debug("%s: gp:%u\n", __func__, gp); 117 118 if (check_reserved(gp, __func__)) 119 return -1; 120 121 return sandbox_gpio_set_direction(gp, 0); 122 } 123 124 /* set GPIO port 'gp' as an output, with polarity 'value' */ 125 int gpio_direction_output(unsigned gp, int value) 126 { 127 debug("%s: gp:%u, value = %d\n", __func__, gp, value); 128 129 if (check_reserved(gp, __func__)) 130 return -1; 131 132 return sandbox_gpio_set_direction(gp, 1) | 133 sandbox_gpio_set_value(gp, value); 134 } 135 136 /* read GPIO IN value of port 'gp' */ 137 int gpio_get_value(unsigned gp) 138 { 139 debug("%s: gp:%u\n", __func__, gp); 140 141 if (check_reserved(gp, __func__)) 142 return -1; 143 144 return sandbox_gpio_get_value(gp); 145 } 146 147 /* write GPIO OUT value to port 'gp' */ 148 int gpio_set_value(unsigned gp, int value) 149 { 150 debug("%s: gp:%u, value = %d\n", __func__, gp, value); 151 152 if (check_reserved(gp, __func__)) 153 return -1; 154 155 if (!sandbox_gpio_get_direction(gp)) { 156 printf("sandbox_gpio: error: set_value on input gpio %u\n", gp); 157 return -1; 158 } 159 160 return sandbox_gpio_set_value(gp, value); 161 } 162 163 int gpio_request(unsigned gp, const char *label) 164 { 165 debug("%s: gp:%u, label:%s\n", __func__, gp, label); 166 167 if (gp >= ARRAY_SIZE(state)) { 168 printf("sandbox_gpio: error: invalid gpio %u\n", gp); 169 return -1; 170 } 171 172 if (get_gpio_flag(gp, GPIOF_RESERVED)) { 173 printf("sandbox_gpio: error: gpio %u already reserved\n", gp); 174 return -1; 175 } 176 177 state[gp].label = label; 178 return set_gpio_flag(gp, GPIOF_RESERVED, 1); 179 } 180 181 int gpio_free(unsigned gp) 182 { 183 debug("%s: gp:%u\n", __func__, gp); 184 185 if (check_reserved(gp, __func__)) 186 return -1; 187 188 state[gp].label = NULL; 189 return set_gpio_flag(gp, GPIOF_RESERVED, 0); 190 } 191 192 /* Display GPIO information */ 193 void gpio_info(void) 194 { 195 unsigned gpio; 196 197 puts("Sandbox GPIOs\n"); 198 199 for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) { 200 const char *label = state[gpio].label; 201 202 printf("%4d: %s: %d [%c] %s\n", 203 gpio, 204 sandbox_gpio_get_direction(gpio) ? "out" : " in", 205 sandbox_gpio_get_value(gpio), 206 get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ', 207 label ? label : ""); 208 } 209 } 210