1 /* 2 * NVIDIA Tegra20 GPIO handling. 3 * (C) Copyright 2010-2012 4 * NVIDIA Corporation <www.nvidia.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 /* 10 * Based on (mostly copied from) kw_gpio.c based Linux 2.6 kernel driver. 11 * Tom Warren (twarren@nvidia.com) 12 */ 13 14 #include <common.h> 15 #include <asm/io.h> 16 #include <asm/bitops.h> 17 #include <asm/arch/tegra.h> 18 #include <asm/gpio.h> 19 20 enum { 21 TEGRA_CMD_INFO, 22 TEGRA_CMD_PORT, 23 TEGRA_CMD_OUTPUT, 24 TEGRA_CMD_INPUT, 25 }; 26 27 static struct gpio_names { 28 char name[GPIO_NAME_SIZE]; 29 } gpio_names[MAX_NUM_GPIOS]; 30 31 static char *get_name(int i) 32 { 33 return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN"; 34 } 35 36 /* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */ 37 static int get_config(unsigned gpio) 38 { 39 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 40 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 41 u32 u; 42 int type; 43 44 u = readl(&bank->gpio_config[GPIO_PORT(gpio)]); 45 type = (u >> GPIO_BIT(gpio)) & 1; 46 47 debug("get_config: port = %d, bit = %d is %s\n", 48 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO"); 49 50 return type; 51 } 52 53 /* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */ 54 static void set_config(unsigned gpio, int type) 55 { 56 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 57 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 58 u32 u; 59 60 debug("set_config: port = %d, bit = %d, %s\n", 61 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO"); 62 63 u = readl(&bank->gpio_config[GPIO_PORT(gpio)]); 64 if (type) /* GPIO */ 65 u |= 1 << GPIO_BIT(gpio); 66 else 67 u &= ~(1 << GPIO_BIT(gpio)); 68 writel(u, &bank->gpio_config[GPIO_PORT(gpio)]); 69 } 70 71 /* Return GPIO pin 'gpio' direction - 0 = input or 1 = output */ 72 static int get_direction(unsigned gpio) 73 { 74 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 75 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 76 u32 u; 77 int dir; 78 79 u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]); 80 dir = (u >> GPIO_BIT(gpio)) & 1; 81 82 debug("get_direction: port = %d, bit = %d, %s\n", 83 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN"); 84 85 return dir; 86 } 87 88 /* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */ 89 static void set_direction(unsigned gpio, int output) 90 { 91 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 92 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 93 u32 u; 94 95 debug("set_direction: port = %d, bit = %d, %s\n", 96 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN"); 97 98 u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]); 99 if (output) 100 u |= 1 << GPIO_BIT(gpio); 101 else 102 u &= ~(1 << GPIO_BIT(gpio)); 103 writel(u, &bank->gpio_dir_out[GPIO_PORT(gpio)]); 104 } 105 106 /* set GPIO pin 'gpio' output bit as 0 or 1 as per 'high' */ 107 static void set_level(unsigned gpio, int high) 108 { 109 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 110 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 111 u32 u; 112 113 debug("set_level: port = %d, bit %d == %d\n", 114 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), high); 115 116 u = readl(&bank->gpio_out[GPIO_PORT(gpio)]); 117 if (high) 118 u |= 1 << GPIO_BIT(gpio); 119 else 120 u &= ~(1 << GPIO_BIT(gpio)); 121 writel(u, &bank->gpio_out[GPIO_PORT(gpio)]); 122 } 123 124 /* 125 * Generic_GPIO primitives. 126 */ 127 128 int gpio_request(unsigned gpio, const char *label) 129 { 130 if (gpio >= MAX_NUM_GPIOS) 131 return -1; 132 133 if (label != NULL) { 134 strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE); 135 gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0'; 136 } 137 138 /* Configure as a GPIO */ 139 set_config(gpio, 1); 140 141 return 0; 142 } 143 144 int gpio_free(unsigned gpio) 145 { 146 if (gpio >= MAX_NUM_GPIOS) 147 return -1; 148 149 gpio_names[gpio].name[0] = '\0'; 150 /* Do not configure as input or change pin mux here */ 151 return 0; 152 } 153 154 /* read GPIO OUT value of pin 'gpio' */ 155 static int gpio_get_output_value(unsigned gpio) 156 { 157 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 158 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 159 int val; 160 161 debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n", 162 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio)); 163 164 val = readl(&bank->gpio_out[GPIO_PORT(gpio)]); 165 166 return (val >> GPIO_BIT(gpio)) & 1; 167 } 168 169 /* set GPIO pin 'gpio' as an input */ 170 int gpio_direction_input(unsigned gpio) 171 { 172 debug("gpio_direction_input: pin = %d (port %d:bit %d)\n", 173 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio)); 174 175 /* Configure GPIO direction as input. */ 176 set_direction(gpio, 0); 177 178 return 0; 179 } 180 181 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 182 int gpio_direction_output(unsigned gpio, int value) 183 { 184 debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n", 185 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), 186 value ? "HIGH" : "LOW"); 187 188 /* Configure GPIO output value. */ 189 set_level(gpio, value); 190 191 /* Configure GPIO direction as output. */ 192 set_direction(gpio, 1); 193 194 return 0; 195 } 196 197 /* read GPIO IN value of pin 'gpio' */ 198 int gpio_get_value(unsigned gpio) 199 { 200 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE; 201 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)]; 202 int val; 203 204 debug("gpio_get_value: pin = %d (port %d:bit %d)\n", 205 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio)); 206 207 val = readl(&bank->gpio_in[GPIO_PORT(gpio)]); 208 209 return (val >> GPIO_BIT(gpio)) & 1; 210 } 211 212 /* write GPIO OUT value to pin 'gpio' */ 213 int gpio_set_value(unsigned gpio, int value) 214 { 215 debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n", 216 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value); 217 218 /* Configure GPIO output value. */ 219 set_level(gpio, value); 220 221 return 0; 222 } 223 224 /* 225 * Display Tegra GPIO information 226 */ 227 void gpio_info(void) 228 { 229 unsigned c; 230 int type; 231 232 for (c = 0; c < MAX_NUM_GPIOS; c++) { 233 type = get_config(c); /* GPIO, not SFPIO */ 234 if (type) { 235 printf("GPIO_%d:\t%s is an %s, ", c, 236 get_name(c), 237 get_direction(c) ? "OUTPUT" : "INPUT"); 238 if (get_direction(c)) 239 printf("value = %d", gpio_get_output_value(c)); 240 else 241 printf("value = %d", gpio_get_value(c)); 242 printf("\n"); 243 } else 244 continue; 245 } 246 } 247