1 /* 2 * Copyright (C) 2009 3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4 * 5 * Copyright (C) 2011 6 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 #include <common.h> 11 #include <errno.h> 12 #include <dm.h> 13 #include <malloc.h> 14 #include <asm/arch/imx-regs.h> 15 #include <asm/gpio.h> 16 #include <asm/io.h> 17 18 enum mxc_gpio_direction { 19 MXC_GPIO_DIRECTION_IN, 20 MXC_GPIO_DIRECTION_OUT, 21 }; 22 23 #define GPIO_NAME_SIZE 20 24 #define GPIO_PER_BANK 32 25 26 struct mxc_gpio_plat { 27 struct gpio_regs *regs; 28 }; 29 30 struct mxc_bank_info { 31 char label[GPIO_PER_BANK][GPIO_NAME_SIZE]; 32 struct gpio_regs *regs; 33 }; 34 35 #ifndef CONFIG_DM_GPIO 36 #define GPIO_TO_PORT(n) (n / 32) 37 38 /* GPIO port description */ 39 static unsigned long gpio_ports[] = { 40 [0] = GPIO1_BASE_ADDR, 41 [1] = GPIO2_BASE_ADDR, 42 [2] = GPIO3_BASE_ADDR, 43 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 44 defined(CONFIG_MX53) || defined(CONFIG_MX6) 45 [3] = GPIO4_BASE_ADDR, 46 #endif 47 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 48 [4] = GPIO5_BASE_ADDR, 49 [5] = GPIO6_BASE_ADDR, 50 #endif 51 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 52 [6] = GPIO7_BASE_ADDR, 53 #endif 54 }; 55 56 static int mxc_gpio_direction(unsigned int gpio, 57 enum mxc_gpio_direction direction) 58 { 59 unsigned int port = GPIO_TO_PORT(gpio); 60 struct gpio_regs *regs; 61 u32 l; 62 63 if (port >= ARRAY_SIZE(gpio_ports)) 64 return -1; 65 66 gpio &= 0x1f; 67 68 regs = (struct gpio_regs *)gpio_ports[port]; 69 70 l = readl(®s->gpio_dir); 71 72 switch (direction) { 73 case MXC_GPIO_DIRECTION_OUT: 74 l |= 1 << gpio; 75 break; 76 case MXC_GPIO_DIRECTION_IN: 77 l &= ~(1 << gpio); 78 } 79 writel(l, ®s->gpio_dir); 80 81 return 0; 82 } 83 84 int gpio_set_value(unsigned gpio, int value) 85 { 86 unsigned int port = GPIO_TO_PORT(gpio); 87 struct gpio_regs *regs; 88 u32 l; 89 90 if (port >= ARRAY_SIZE(gpio_ports)) 91 return -1; 92 93 gpio &= 0x1f; 94 95 regs = (struct gpio_regs *)gpio_ports[port]; 96 97 l = readl(®s->gpio_dr); 98 if (value) 99 l |= 1 << gpio; 100 else 101 l &= ~(1 << gpio); 102 writel(l, ®s->gpio_dr); 103 104 return 0; 105 } 106 107 int gpio_get_value(unsigned gpio) 108 { 109 unsigned int port = GPIO_TO_PORT(gpio); 110 struct gpio_regs *regs; 111 u32 val; 112 113 if (port >= ARRAY_SIZE(gpio_ports)) 114 return -1; 115 116 gpio &= 0x1f; 117 118 regs = (struct gpio_regs *)gpio_ports[port]; 119 120 val = (readl(®s->gpio_psr) >> gpio) & 0x01; 121 122 return val; 123 } 124 125 int gpio_request(unsigned gpio, const char *label) 126 { 127 unsigned int port = GPIO_TO_PORT(gpio); 128 if (port >= ARRAY_SIZE(gpio_ports)) 129 return -1; 130 return 0; 131 } 132 133 int gpio_free(unsigned gpio) 134 { 135 return 0; 136 } 137 138 int gpio_direction_input(unsigned gpio) 139 { 140 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); 141 } 142 143 int gpio_direction_output(unsigned gpio, int value) 144 { 145 int ret = gpio_set_value(gpio, value); 146 147 if (ret < 0) 148 return ret; 149 150 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); 151 } 152 #endif 153 154 #ifdef CONFIG_DM_GPIO 155 /** 156 * gpio_is_requested() - check if a GPIO has been requested 157 * 158 * @bank: Bank to check 159 * @offset: GPIO offset within bank to check 160 * @return true if marked as requested, false if not 161 */ 162 static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset) 163 { 164 return *bank->label[offset] != '\0'; 165 } 166 167 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset) 168 { 169 u32 val; 170 171 val = readl(®s->gpio_dir); 172 173 return val & (1 << offset) ? 1 : 0; 174 } 175 176 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset, 177 enum mxc_gpio_direction direction) 178 { 179 u32 l; 180 181 l = readl(®s->gpio_dir); 182 183 switch (direction) { 184 case MXC_GPIO_DIRECTION_OUT: 185 l |= 1 << offset; 186 break; 187 case MXC_GPIO_DIRECTION_IN: 188 l &= ~(1 << offset); 189 } 190 writel(l, ®s->gpio_dir); 191 } 192 193 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset, 194 int value) 195 { 196 u32 l; 197 198 l = readl(®s->gpio_dr); 199 if (value) 200 l |= 1 << offset; 201 else 202 l &= ~(1 << offset); 203 writel(l, ®s->gpio_dr); 204 } 205 206 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset) 207 { 208 return (readl(®s->gpio_psr) >> offset) & 0x01; 209 } 210 211 static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset) 212 { 213 return (readl(®s->gpio_dr) >> offset) & 0x01; 214 } 215 216 static int check_requested(struct udevice *dev, unsigned offset, 217 const char *func) 218 { 219 struct mxc_bank_info *bank = dev_get_priv(dev); 220 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 221 222 if (!gpio_is_requested(bank, offset)) { 223 printf("mxc_gpio: %s: error: gpio %s%d not requested\n", 224 func, uc_priv->bank_name, offset); 225 return -EPERM; 226 } 227 228 return 0; 229 } 230 231 /* set GPIO pin 'gpio' as an input */ 232 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset) 233 { 234 struct mxc_bank_info *bank = dev_get_priv(dev); 235 int ret; 236 237 ret = check_requested(dev, offset, __func__); 238 if (ret) 239 return ret; 240 241 /* Configure GPIO direction as input. */ 242 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN); 243 244 return 0; 245 } 246 247 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 248 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset, 249 int value) 250 { 251 struct mxc_bank_info *bank = dev_get_priv(dev); 252 int ret; 253 254 ret = check_requested(dev, offset, __func__); 255 if (ret) 256 return ret; 257 258 /* Configure GPIO output value. */ 259 mxc_gpio_bank_set_value(bank->regs, offset, value); 260 261 /* Configure GPIO direction as output. */ 262 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT); 263 264 return 0; 265 } 266 267 /* read GPIO IN value of pin 'gpio' */ 268 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset) 269 { 270 struct mxc_bank_info *bank = dev_get_priv(dev); 271 int ret; 272 273 ret = check_requested(dev, offset, __func__); 274 if (ret) 275 return ret; 276 277 return mxc_gpio_bank_get_value(bank->regs, offset); 278 } 279 280 /* write GPIO OUT value to pin 'gpio' */ 281 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset, 282 int value) 283 { 284 struct mxc_bank_info *bank = dev_get_priv(dev); 285 int ret; 286 287 ret = check_requested(dev, offset, __func__); 288 if (ret) 289 return ret; 290 291 mxc_gpio_bank_set_value(bank->regs, offset, value); 292 293 return 0; 294 } 295 296 static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset, 297 char *buf, int bufsize) 298 { 299 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 300 struct mxc_bank_info *bank = dev_get_priv(dev); 301 const char *label; 302 bool requested; 303 bool is_output; 304 int size; 305 306 label = bank->label[offset]; 307 is_output = mxc_gpio_is_output(bank->regs, offset); 308 size = snprintf(buf, bufsize, "%s%d: ", 309 uc_priv->bank_name ? uc_priv->bank_name : "", offset); 310 buf += size; 311 bufsize -= size; 312 requested = gpio_is_requested(bank, offset); 313 snprintf(buf, bufsize, "%s: %d [%c]%s%s", 314 is_output ? "out" : " in", 315 is_output ? 316 mxc_gpio_bank_get_output_value(bank->regs, offset) : 317 mxc_gpio_bank_get_value(bank->regs, offset), 318 requested ? 'x' : ' ', 319 requested ? " " : "", 320 label); 321 322 return 0; 323 } 324 325 static int mxc_gpio_request(struct udevice *dev, unsigned offset, 326 const char *label) 327 { 328 struct mxc_bank_info *bank = dev_get_priv(dev); 329 330 if (gpio_is_requested(bank, offset)) 331 return -EBUSY; 332 333 strncpy(bank->label[offset], label, GPIO_NAME_SIZE); 334 bank->label[offset][GPIO_NAME_SIZE - 1] = '\0'; 335 336 return 0; 337 } 338 339 static int mxc_gpio_free(struct udevice *dev, unsigned offset) 340 { 341 struct mxc_bank_info *bank = dev_get_priv(dev); 342 int ret; 343 344 ret = check_requested(dev, offset, __func__); 345 if (ret) 346 return ret; 347 bank->label[offset][0] = '\0'; 348 349 return 0; 350 } 351 352 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset) 353 { 354 struct mxc_bank_info *bank = dev_get_priv(dev); 355 356 if (!gpio_is_requested(bank, offset)) 357 return GPIOF_UNUSED; 358 359 /* GPIOF_FUNC is not implemented yet */ 360 if (mxc_gpio_is_output(bank->regs, offset)) 361 return GPIOF_OUTPUT; 362 else 363 return GPIOF_INPUT; 364 } 365 366 static const struct dm_gpio_ops gpio_mxc_ops = { 367 .request = mxc_gpio_request, 368 .free = mxc_gpio_free, 369 .direction_input = mxc_gpio_direction_input, 370 .direction_output = mxc_gpio_direction_output, 371 .get_value = mxc_gpio_get_value, 372 .set_value = mxc_gpio_set_value, 373 .get_function = mxc_gpio_get_function, 374 .get_state = mxc_gpio_get_state, 375 }; 376 377 static const struct mxc_gpio_plat mxc_plat[] = { 378 { (struct gpio_regs *)GPIO1_BASE_ADDR }, 379 { (struct gpio_regs *)GPIO2_BASE_ADDR }, 380 { (struct gpio_regs *)GPIO3_BASE_ADDR }, 381 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 382 defined(CONFIG_MX53) || defined(CONFIG_MX6) 383 { (struct gpio_regs *)GPIO4_BASE_ADDR }, 384 #endif 385 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 386 { (struct gpio_regs *)GPIO5_BASE_ADDR }, 387 { (struct gpio_regs *)GPIO6_BASE_ADDR }, 388 #endif 389 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 390 { (struct gpio_regs *)GPIO7_BASE_ADDR }, 391 #endif 392 }; 393 394 static int mxc_gpio_probe(struct udevice *dev) 395 { 396 struct mxc_bank_info *bank = dev_get_priv(dev); 397 struct mxc_gpio_plat *plat = dev_get_platdata(dev); 398 struct gpio_dev_priv *uc_priv = dev->uclass_priv; 399 int banknum; 400 char name[18], *str; 401 402 banknum = plat - mxc_plat; 403 sprintf(name, "GPIO%d_", banknum + 1); 404 str = strdup(name); 405 if (!str) 406 return -ENOMEM; 407 uc_priv->bank_name = str; 408 uc_priv->gpio_count = GPIO_PER_BANK; 409 bank->regs = plat->regs; 410 411 return 0; 412 } 413 414 U_BOOT_DRIVER(gpio_mxc) = { 415 .name = "gpio_mxc", 416 .id = UCLASS_GPIO, 417 .ops = &gpio_mxc_ops, 418 .probe = mxc_gpio_probe, 419 .priv_auto_alloc_size = sizeof(struct mxc_bank_info), 420 }; 421 422 U_BOOT_DEVICES(mxc_gpios) = { 423 { "gpio_mxc", &mxc_plat[0] }, 424 { "gpio_mxc", &mxc_plat[1] }, 425 { "gpio_mxc", &mxc_plat[2] }, 426 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 427 defined(CONFIG_MX53) || defined(CONFIG_MX6) 428 { "gpio_mxc", &mxc_plat[3] }, 429 #endif 430 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 431 { "gpio_mxc", &mxc_plat[4] }, 432 { "gpio_mxc", &mxc_plat[5] }, 433 #endif 434 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 435 { "gpio_mxc", &mxc_plat[6] }, 436 #endif 437 }; 438 #endif 439