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 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_MX51) || defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 44 [3] = GPIO4_BASE_ADDR, 45 #endif 46 #if defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 47 [4] = GPIO5_BASE_ADDR, 48 [5] = GPIO6_BASE_ADDR, 49 [6] = GPIO7_BASE_ADDR, 50 #endif 51 }; 52 53 static int mxc_gpio_direction(unsigned int gpio, 54 enum mxc_gpio_direction direction) 55 { 56 unsigned int port = gpio >> 5; 57 struct gpio_regs *regs; 58 u32 l; 59 60 if (port >= ARRAY_SIZE(gpio_ports)) 61 return -EINVAL; 62 63 gpio &= 0x1f; 64 65 regs = (struct gpio_regs *)gpio_ports[port]; 66 67 l = readl(®s->gpio_dir); 68 69 switch (direction) { 70 case MXC_GPIO_DIRECTION_OUT: 71 l |= 1 << gpio; 72 break; 73 case MXC_GPIO_DIRECTION_IN: 74 l &= ~(1 << gpio); 75 } 76 writel(l, ®s->gpio_dir); 77 78 return 0; 79 } 80 81 void gpio_set_value(int gpio, int value) 82 { 83 unsigned int port = gpio >> 5; 84 struct gpio_regs *regs; 85 u32 l; 86 87 if (port >= ARRAY_SIZE(gpio_ports)) 88 return; 89 90 gpio &= 0x1f; 91 92 regs = (struct gpio_regs *)gpio_ports[port]; 93 94 l = readl(®s->gpio_dr); 95 if (value) 96 l |= 1 << gpio; 97 else 98 l &= ~(1 << gpio); 99 writel(l, ®s->gpio_dr); 100 } 101 102 int gpio_get_value(int gpio) 103 { 104 unsigned int port = gpio >> 5; 105 struct gpio_regs *regs; 106 u32 l; 107 108 if (port >= ARRAY_SIZE(gpio_ports)) 109 return -EINVAL; 110 111 gpio &= 0x1f; 112 113 regs = (struct gpio_regs *)gpio_ports[port]; 114 115 l = (readl(®s->gpio_dr) >> gpio) & 0x01; 116 117 return l; 118 } 119 120 int gpio_request(int gp, const char *label) 121 { 122 unsigned int port = gp >> 5; 123 if (port >= ARRAY_SIZE(gpio_ports)) 124 return -EINVAL; 125 return 0; 126 } 127 128 void gpio_free(int gp) 129 { 130 } 131 132 void gpio_toggle_value(int gp) 133 { 134 gpio_set_value(gp, !gpio_get_value(gp)); 135 } 136 137 int gpio_direction_input(int gp) 138 { 139 return mxc_gpio_direction(gp, MXC_GPIO_DIRECTION_IN); 140 } 141 142 int gpio_direction_output(int gp, int value) 143 { 144 int ret = mxc_gpio_direction(gp, MXC_GPIO_DIRECTION_OUT); 145 146 if (ret < 0) 147 return ret; 148 149 gpio_set_value(gp, value); 150 return 0; 151 } 152