1 /* 2 * ADI GPIO2 Abstraction Layer 3 * Support BF54x, BF60x and future processors. 4 * 5 * Copyright 2008-2013 Analog Devices Inc. 6 * 7 * Licensed under the GPL-2 or later 8 */ 9 10 #include <common.h> 11 #include <asm/errno.h> 12 #include <asm/gpio.h> 13 14 #define RESOURCE_LABEL_SIZE 16 15 16 static struct str_ident { 17 char name[RESOURCE_LABEL_SIZE]; 18 } str_ident[MAX_RESOURCES]; 19 20 static void gpio_error(unsigned gpio) 21 { 22 printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio); 23 } 24 25 static void set_label(unsigned short ident, const char *label) 26 { 27 if (label) { 28 strncpy(str_ident[ident].name, label, 29 RESOURCE_LABEL_SIZE); 30 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; 31 } 32 } 33 34 static char *get_label(unsigned short ident) 35 { 36 return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"; 37 } 38 39 static int cmp_label(unsigned short ident, const char *label) 40 { 41 if (label == NULL) 42 printf("adi_gpio2: please provide none-null label\n"); 43 44 if (label) 45 return strcmp(str_ident[ident].name, label); 46 else 47 return -EINVAL; 48 } 49 50 #define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] 51 #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) 52 #define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) 53 #define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) 54 #define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c] 55 56 static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); 57 static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); 58 59 inline int check_gpio(unsigned gpio) 60 { 61 #if defined(CONFIG_BF54x) 62 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 || 63 gpio == GPIO_PH14 || gpio == GPIO_PH15 || 64 gpio == GPIO_PJ14 || gpio == GPIO_PJ15) 65 return -EINVAL; 66 #endif 67 if (gpio >= MAX_GPIOS) 68 return -EINVAL; 69 return 0; 70 } 71 72 static void port_setup(unsigned gpio, unsigned short usage) 73 { 74 #if defined(CONFIG_BF54x) 75 if (usage == GPIO_USAGE) 76 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); 77 else 78 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); 79 #else 80 if (usage == GPIO_USAGE) 81 gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio); 82 else 83 gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio); 84 #endif 85 } 86 87 inline void portmux_setup(unsigned short per) 88 { 89 u32 pmux; 90 u16 ident = P_IDENT(per); 91 u16 function = P_FUNCT2MUX(per); 92 93 pmux = gpio_array[gpio_bank(ident)]->port_mux; 94 95 pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); 96 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); 97 98 gpio_array[gpio_bank(ident)]->port_mux = pmux; 99 } 100 101 inline u16 get_portmux(unsigned short per) 102 { 103 u32 pmux; 104 u16 ident = P_IDENT(per); 105 106 pmux = gpio_array[gpio_bank(ident)]->port_mux; 107 108 return pmux >> (2 * gpio_sub_n(ident)) & 0x3; 109 } 110 111 unsigned short get_gpio_dir(unsigned gpio) 112 { 113 return 0x01 & 114 (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)); 115 } 116 117 /*********************************************************** 118 * 119 * FUNCTIONS: Peripheral Resource Allocation 120 * and PortMux Setup 121 * 122 * INPUTS/OUTPUTS: 123 * per Peripheral Identifier 124 * label String 125 * 126 * DESCRIPTION: Peripheral Resource Allocation and Setup API 127 **************************************************************/ 128 129 int peripheral_request(unsigned short per, const char *label) 130 { 131 unsigned short ident = P_IDENT(per); 132 133 /* 134 * Don't cares are pins with only one dedicated function 135 */ 136 137 if (per & P_DONTCARE) 138 return 0; 139 140 if (!(per & P_DEFINED)) 141 return -ENODEV; 142 143 BUG_ON(ident >= MAX_RESOURCES); 144 145 /* If a pin can be muxed as either GPIO or peripheral, make 146 * sure it is not already a GPIO pin when we request it. 147 */ 148 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { 149 printf("%s: Peripheral %d is already reserved as GPIO by %s!\n", 150 __func__, ident, get_label(ident)); 151 return -EBUSY; 152 } 153 154 if (unlikely(is_reserved(peri, ident, 1))) { 155 /* 156 * Pin functions like AMC address strobes my 157 * be requested and used by several drivers 158 */ 159 160 if (!((per & P_MAYSHARE) && 161 get_portmux(per) == P_FUNCT2MUX(per))) { 162 /* 163 * Allow that the identical pin function can 164 * be requested from the same driver twice 165 */ 166 167 if (cmp_label(ident, label) == 0) 168 goto anyway; 169 170 printf("%s: Peripheral %d function %d is already " 171 "reserved by %s!\n", __func__, ident, 172 P_FUNCT2MUX(per), get_label(ident)); 173 return -EBUSY; 174 } 175 } 176 177 anyway: 178 reserve(peri, ident); 179 180 portmux_setup(per); 181 port_setup(ident, PERIPHERAL_USAGE); 182 183 set_label(ident, label); 184 185 return 0; 186 } 187 188 int peripheral_request_list(const unsigned short per[], const char *label) 189 { 190 u16 cnt; 191 int ret; 192 193 for (cnt = 0; per[cnt] != 0; cnt++) { 194 ret = peripheral_request(per[cnt], label); 195 196 if (ret < 0) { 197 for (; cnt > 0; cnt--) 198 peripheral_free(per[cnt - 1]); 199 200 return ret; 201 } 202 } 203 204 return 0; 205 } 206 207 void peripheral_free(unsigned short per) 208 { 209 unsigned short ident = P_IDENT(per); 210 211 if (per & P_DONTCARE) 212 return; 213 214 if (!(per & P_DEFINED)) 215 return; 216 217 if (unlikely(!is_reserved(peri, ident, 0))) 218 return; 219 220 if (!(per & P_MAYSHARE)) 221 port_setup(ident, GPIO_USAGE); 222 223 unreserve(peri, ident); 224 225 set_label(ident, "free"); 226 } 227 228 void peripheral_free_list(const unsigned short per[]) 229 { 230 u16 cnt; 231 for (cnt = 0; per[cnt] != 0; cnt++) 232 peripheral_free(per[cnt]); 233 } 234 235 /*********************************************************** 236 * 237 * FUNCTIONS: GPIO Driver 238 * 239 * INPUTS/OUTPUTS: 240 * gpio PIO Number between 0 and MAX_GPIOS 241 * label String 242 * 243 * DESCRIPTION: GPIO Driver API 244 **************************************************************/ 245 246 int gpio_request(unsigned gpio, const char *label) 247 { 248 if (check_gpio(gpio) < 0) 249 return -EINVAL; 250 251 /* 252 * Allow that the identical GPIO can 253 * be requested from the same driver twice 254 * Do nothing and return - 255 */ 256 257 if (cmp_label(gpio, label) == 0) 258 return 0; 259 260 if (unlikely(is_reserved(gpio, gpio, 1))) { 261 printf("adi_gpio2: GPIO %d is already reserved by %s!\n", 262 gpio, get_label(gpio)); 263 return -EBUSY; 264 } 265 if (unlikely(is_reserved(peri, gpio, 1))) { 266 printf("adi_gpio2: GPIO %d is already reserved as Peripheral " 267 "by %s!\n", gpio, get_label(gpio)); 268 return -EBUSY; 269 } 270 271 reserve(gpio, gpio); 272 set_label(gpio, label); 273 274 port_setup(gpio, GPIO_USAGE); 275 276 return 0; 277 } 278 279 int gpio_free(unsigned gpio) 280 { 281 if (check_gpio(gpio) < 0) 282 return -1; 283 284 if (unlikely(!is_reserved(gpio, gpio, 0))) { 285 gpio_error(gpio); 286 return -1; 287 } 288 289 unreserve(gpio, gpio); 290 291 set_label(gpio, "free"); 292 293 return 0; 294 } 295 296 #ifdef ADI_SPECIAL_GPIO_BANKS 297 static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); 298 299 int special_gpio_request(unsigned gpio, const char *label) 300 { 301 /* 302 * Allow that the identical GPIO can 303 * be requested from the same driver twice 304 * Do nothing and return - 305 */ 306 307 if (cmp_label(gpio, label) == 0) 308 return 0; 309 310 if (unlikely(is_reserved(special_gpio, gpio, 1))) { 311 printf("adi_gpio2: GPIO %d is already reserved by %s!\n", 312 gpio, get_label(gpio)); 313 return -EBUSY; 314 } 315 if (unlikely(is_reserved(peri, gpio, 1))) { 316 printf("adi_gpio2: GPIO %d is already reserved as Peripheral " 317 "by %s!\n", gpio, get_label(gpio)); 318 319 return -EBUSY; 320 } 321 322 reserve(special_gpio, gpio); 323 reserve(peri, gpio); 324 325 set_label(gpio, label); 326 port_setup(gpio, GPIO_USAGE); 327 328 return 0; 329 } 330 331 void special_gpio_free(unsigned gpio) 332 { 333 if (unlikely(!is_reserved(special_gpio, gpio, 0))) { 334 gpio_error(gpio); 335 return; 336 } 337 338 unreserve(special_gpio, gpio); 339 unreserve(peri, gpio); 340 set_label(gpio, "free"); 341 } 342 #endif 343 344 static inline void __gpio_direction_input(unsigned gpio) 345 { 346 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); 347 #if defined(CONFIG_BF54x) 348 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); 349 #else 350 gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio); 351 #endif 352 } 353 354 int gpio_direction_input(unsigned gpio) 355 { 356 unsigned long flags; 357 358 if (!is_reserved(gpio, gpio, 0)) { 359 gpio_error(gpio); 360 return -EINVAL; 361 } 362 363 local_irq_save(flags); 364 __gpio_direction_input(gpio); 365 local_irq_restore(flags); 366 367 return 0; 368 } 369 370 int gpio_set_value(unsigned gpio, int arg) 371 { 372 if (arg) 373 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); 374 else 375 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); 376 377 return 0; 378 } 379 380 int gpio_direction_output(unsigned gpio, int value) 381 { 382 unsigned long flags; 383 384 if (!is_reserved(gpio, gpio, 0)) { 385 gpio_error(gpio); 386 return -EINVAL; 387 } 388 389 local_irq_save(flags); 390 391 #if defined(CONFIG_BF54x) 392 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); 393 #else 394 gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio); 395 #endif 396 gpio_set_value(gpio, value); 397 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); 398 399 local_irq_restore(flags); 400 401 return 0; 402 } 403 404 int gpio_get_value(unsigned gpio) 405 { 406 return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); 407 } 408 409 void gpio_labels(void) 410 { 411 int c, gpio; 412 413 for (c = 0; c < MAX_RESOURCES; c++) { 414 gpio = is_reserved(gpio, c, 1); 415 if (!check_gpio(c) && gpio) 416 printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c), 417 get_gpio_dir(c) ? "OUTPUT" : "INPUT"); 418 else if (is_reserved(peri, c, 1)) 419 printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c)); 420 else 421 continue; 422 } 423 } 424