1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * SPDX-License-Identifier: GPL-2.0+ 4 */ 5 6 #include <common.h> 7 #include <asm/gpio.h> 8 9 /* Flags for each GPIO */ 10 #define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ 11 #define GPIOF_HIGH (1 << 1) /* Currently set high */ 12 #define GPIOF_RESERVED (1 << 2) /* Is in use / requested */ 13 14 struct gpio_state { 15 const char *label; /* label given by requester */ 16 u8 flags; /* flags (GPIOF_...) */ 17 }; 18 19 /* 20 * State of GPIOs 21 * TODO: Put this into sandbox state 22 */ 23 static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT]; 24 25 /* Access routines for GPIO state */ 26 static u8 *get_gpio_flags(unsigned gp) 27 { 28 /* assert()'s could be disabled, so make sure we handle that */ 29 assert(gp < ARRAY_SIZE(state)); 30 if (gp >= ARRAY_SIZE(state)) { 31 static u8 invalid_flags; 32 printf("sandbox_gpio: error: invalid gpio %u\n", gp); 33 return &invalid_flags; 34 } 35 36 return &state[gp].flags; 37 } 38 39 static int get_gpio_flag(unsigned gp, int flag) 40 { 41 return (*get_gpio_flags(gp) & flag) != 0; 42 } 43 44 static int set_gpio_flag(unsigned gp, int flag, int value) 45 { 46 u8 *gpio = get_gpio_flags(gp); 47 48 if (value) 49 *gpio |= flag; 50 else 51 *gpio &= ~flag; 52 53 return 0; 54 } 55 56 static int check_reserved(unsigned gpio, const char *func) 57 { 58 if (!get_gpio_flag(gpio, GPIOF_RESERVED)) { 59 printf("sandbox_gpio: %s: error: gpio %u not reserved\n", 60 func, gpio); 61 return -1; 62 } 63 64 return 0; 65 } 66 67 /* 68 * Back-channel sandbox-internal-only access to GPIO state 69 */ 70 71 int sandbox_gpio_get_value(unsigned gp) 72 { 73 if (get_gpio_flag(gp, GPIOF_OUTPUT)) 74 debug("sandbox_gpio: get_value on output gpio %u\n", gp); 75 return get_gpio_flag(gp, GPIOF_HIGH); 76 } 77 78 int sandbox_gpio_set_value(unsigned gp, int value) 79 { 80 return set_gpio_flag(gp, GPIOF_HIGH, value); 81 } 82 83 int sandbox_gpio_get_direction(unsigned gp) 84 { 85 return get_gpio_flag(gp, GPIOF_OUTPUT); 86 } 87 88 int sandbox_gpio_set_direction(unsigned gp, int output) 89 { 90 return set_gpio_flag(gp, GPIOF_OUTPUT, output); 91 } 92 93 /* 94 * These functions implement the public interface within U-Boot 95 */ 96 97 /* set GPIO port 'gp' as an input */ 98 int gpio_direction_input(unsigned gp) 99 { 100 debug("%s: gp:%u\n", __func__, gp); 101 102 if (check_reserved(gp, __func__)) 103 return -1; 104 105 return sandbox_gpio_set_direction(gp, 0); 106 } 107 108 /* set GPIO port 'gp' as an output, with polarity 'value' */ 109 int gpio_direction_output(unsigned gp, int value) 110 { 111 debug("%s: gp:%u, value = %d\n", __func__, gp, value); 112 113 if (check_reserved(gp, __func__)) 114 return -1; 115 116 return sandbox_gpio_set_direction(gp, 1) | 117 sandbox_gpio_set_value(gp, value); 118 } 119 120 /* read GPIO IN value of port 'gp' */ 121 int gpio_get_value(unsigned gp) 122 { 123 debug("%s: gp:%u\n", __func__, gp); 124 125 if (check_reserved(gp, __func__)) 126 return -1; 127 128 return sandbox_gpio_get_value(gp); 129 } 130 131 /* write GPIO OUT value to port 'gp' */ 132 int gpio_set_value(unsigned gp, int value) 133 { 134 debug("%s: gp:%u, value = %d\n", __func__, gp, value); 135 136 if (check_reserved(gp, __func__)) 137 return -1; 138 139 if (!sandbox_gpio_get_direction(gp)) { 140 printf("sandbox_gpio: error: set_value on input gpio %u\n", gp); 141 return -1; 142 } 143 144 return sandbox_gpio_set_value(gp, value); 145 } 146 147 int gpio_request(unsigned gp, const char *label) 148 { 149 debug("%s: gp:%u, label:%s\n", __func__, gp, label); 150 151 if (gp >= ARRAY_SIZE(state)) { 152 printf("sandbox_gpio: error: invalid gpio %u\n", gp); 153 return -1; 154 } 155 156 if (get_gpio_flag(gp, GPIOF_RESERVED)) { 157 printf("sandbox_gpio: error: gpio %u already reserved\n", gp); 158 return -1; 159 } 160 161 state[gp].label = label; 162 return set_gpio_flag(gp, GPIOF_RESERVED, 1); 163 } 164 165 int gpio_free(unsigned gp) 166 { 167 debug("%s: gp:%u\n", __func__, gp); 168 169 if (check_reserved(gp, __func__)) 170 return -1; 171 172 state[gp].label = NULL; 173 return set_gpio_flag(gp, GPIOF_RESERVED, 0); 174 } 175 176 /* Display GPIO information */ 177 void gpio_info(void) 178 { 179 unsigned gpio; 180 181 puts("Sandbox GPIOs\n"); 182 183 for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) { 184 const char *label = state[gpio].label; 185 186 printf("%4d: %s: %d [%c] %s\n", 187 gpio, 188 sandbox_gpio_get_direction(gpio) ? "out" : " in", 189 sandbox_gpio_get_value(gpio), 190 get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ', 191 label ? label : ""); 192 } 193 } 194