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 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 #include <common.h> 27 #include <asm/arch/imx-regs.h> 28 #include <asm/gpio.h> 29 #include <asm/io.h> 30 #include <errno.h> 31 32 enum mxc_gpio_direction { 33 MXC_GPIO_DIRECTION_IN, 34 MXC_GPIO_DIRECTION_OUT, 35 }; 36 37 #define GPIO_TO_PORT(n) (n / 32) 38 39 /* GPIO port description */ 40 static unsigned long gpio_ports[] = { 41 [0] = GPIO1_BASE_ADDR, 42 [1] = GPIO2_BASE_ADDR, 43 [2] = GPIO3_BASE_ADDR, 44 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 45 defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 46 [3] = GPIO4_BASE_ADDR, 47 #endif 48 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 49 [4] = GPIO5_BASE_ADDR, 50 [5] = GPIO6_BASE_ADDR, 51 #endif 52 #if defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 53 [6] = GPIO7_BASE_ADDR, 54 #endif 55 }; 56 57 static int mxc_gpio_direction(unsigned int gpio, 58 enum mxc_gpio_direction direction) 59 { 60 unsigned int port = GPIO_TO_PORT(gpio); 61 struct gpio_regs *regs; 62 u32 l; 63 64 if (port >= ARRAY_SIZE(gpio_ports)) 65 return -1; 66 67 gpio &= 0x1f; 68 69 regs = (struct gpio_regs *)gpio_ports[port]; 70 71 l = readl(®s->gpio_dir); 72 73 switch (direction) { 74 case MXC_GPIO_DIRECTION_OUT: 75 l |= 1 << gpio; 76 break; 77 case MXC_GPIO_DIRECTION_IN: 78 l &= ~(1 << gpio); 79 } 80 writel(l, ®s->gpio_dir); 81 82 return 0; 83 } 84 85 int gpio_set_value(unsigned gpio, int value) 86 { 87 unsigned int port = GPIO_TO_PORT(gpio); 88 struct gpio_regs *regs; 89 u32 l; 90 91 if (port >= ARRAY_SIZE(gpio_ports)) 92 return -1; 93 94 gpio &= 0x1f; 95 96 regs = (struct gpio_regs *)gpio_ports[port]; 97 98 l = readl(®s->gpio_dr); 99 if (value) 100 l |= 1 << gpio; 101 else 102 l &= ~(1 << gpio); 103 writel(l, ®s->gpio_dr); 104 105 return 0; 106 } 107 108 int gpio_get_value(unsigned gpio) 109 { 110 unsigned int port = GPIO_TO_PORT(gpio); 111 struct gpio_regs *regs; 112 u32 val; 113 114 if (port >= ARRAY_SIZE(gpio_ports)) 115 return -1; 116 117 gpio &= 0x1f; 118 119 regs = (struct gpio_regs *)gpio_ports[port]; 120 121 val = (readl(®s->gpio_psr) >> gpio) & 0x01; 122 123 return val; 124 } 125 126 int gpio_request(unsigned gpio, const char *label) 127 { 128 unsigned int port = GPIO_TO_PORT(gpio); 129 if (port >= ARRAY_SIZE(gpio_ports)) 130 return -1; 131 return 0; 132 } 133 134 int gpio_free(unsigned gpio) 135 { 136 return 0; 137 } 138 139 int gpio_direction_input(unsigned gpio) 140 { 141 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); 142 } 143 144 int gpio_direction_output(unsigned gpio, int value) 145 { 146 int ret = mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); 147 148 if (ret < 0) 149 return ret; 150 151 return gpio_set_value(gpio, value); 152 } 153