1c4ea1424SStefano Babic /* 2c4ea1424SStefano Babic * Copyright (C) 2009 3c4ea1424SStefano Babic * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4c4ea1424SStefano Babic * 5d8e0ca85SStefano Babic * Copyright (C) 2011 6d8e0ca85SStefano Babic * Stefano Babic, DENX Software Engineering, <sbabic@denx.de> 7d8e0ca85SStefano Babic * 8c4ea1424SStefano Babic * See file CREDITS for list of people who contributed to this 9c4ea1424SStefano Babic * project. 10c4ea1424SStefano Babic * 11c4ea1424SStefano Babic * This program is free software; you can redistribute it and/or 12c4ea1424SStefano Babic * modify it under the terms of the GNU General Public License as 13c4ea1424SStefano Babic * published by the Free Software Foundation; either version 2 of 14c4ea1424SStefano Babic * the License, or (at your option) any later version. 15c4ea1424SStefano Babic * 16c4ea1424SStefano Babic * This program is distributed in the hope that it will be useful, 17c4ea1424SStefano Babic * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c4ea1424SStefano Babic * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c4ea1424SStefano Babic * GNU General Public License for more details. 20c4ea1424SStefano Babic * 21c4ea1424SStefano Babic * You should have received a copy of the GNU General Public License 22c4ea1424SStefano Babic * along with this program; if not, write to the Free Software 23c4ea1424SStefano Babic * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24c4ea1424SStefano Babic * MA 02111-1307 USA 25c4ea1424SStefano Babic */ 26c4ea1424SStefano Babic #include <common.h> 27c4ea1424SStefano Babic #include <asm/arch/imx-regs.h> 28d8e0ca85SStefano Babic #include <asm/gpio.h> 29c4ea1424SStefano Babic #include <asm/io.h> 30e53bcd94SFabio Estevam #include <errno.h> 31c4ea1424SStefano Babic 32d8e0ca85SStefano Babic enum mxc_gpio_direction { 33d8e0ca85SStefano Babic MXC_GPIO_DIRECTION_IN, 34d8e0ca85SStefano Babic MXC_GPIO_DIRECTION_OUT, 35d8e0ca85SStefano Babic }; 36d8e0ca85SStefano Babic 378d28c211SVikram Narayanan #define GPIO_TO_PORT(n) (n / 32) 38d8e0ca85SStefano Babic 39c4ea1424SStefano Babic /* GPIO port description */ 40c4ea1424SStefano Babic static unsigned long gpio_ports[] = { 41c4ea1424SStefano Babic [0] = GPIO1_BASE_ADDR, 42c4ea1424SStefano Babic [1] = GPIO2_BASE_ADDR, 43c4ea1424SStefano Babic [2] = GPIO3_BASE_ADDR, 44*e71c39deStrem #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 45*e71c39deStrem defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 46c4ea1424SStefano Babic [3] = GPIO4_BASE_ADDR, 47c4ea1424SStefano Babic #endif 48*e71c39deStrem #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 4901643ec1SLiu Hui-R64343 [4] = GPIO5_BASE_ADDR, 5001643ec1SLiu Hui-R64343 [5] = GPIO6_BASE_ADDR, 51*e71c39deStrem #endif 52*e71c39deStrem #if defined(CONFIG_MX53) || defined(CONFIG_MX6Q) 5301643ec1SLiu Hui-R64343 [6] = GPIO7_BASE_ADDR, 5401643ec1SLiu Hui-R64343 #endif 55c4ea1424SStefano Babic }; 56c4ea1424SStefano Babic 57d8e0ca85SStefano Babic static int mxc_gpio_direction(unsigned int gpio, 58d8e0ca85SStefano Babic enum mxc_gpio_direction direction) 59c4ea1424SStefano Babic { 60be282554SVikram Narayanan unsigned int port = GPIO_TO_PORT(gpio); 61c4ea1424SStefano Babic struct gpio_regs *regs; 62c4ea1424SStefano Babic u32 l; 63c4ea1424SStefano Babic 64c4ea1424SStefano Babic if (port >= ARRAY_SIZE(gpio_ports)) 65365d6070SJoe Hershberger return -1; 66c4ea1424SStefano Babic 67c4ea1424SStefano Babic gpio &= 0x1f; 68c4ea1424SStefano Babic 69c4ea1424SStefano Babic regs = (struct gpio_regs *)gpio_ports[port]; 70c4ea1424SStefano Babic 71c4ea1424SStefano Babic l = readl(®s->gpio_dir); 72c4ea1424SStefano Babic 73c4ea1424SStefano Babic switch (direction) { 74c4ea1424SStefano Babic case MXC_GPIO_DIRECTION_OUT: 75c4ea1424SStefano Babic l |= 1 << gpio; 76c4ea1424SStefano Babic break; 77c4ea1424SStefano Babic case MXC_GPIO_DIRECTION_IN: 78c4ea1424SStefano Babic l &= ~(1 << gpio); 79c4ea1424SStefano Babic } 80c4ea1424SStefano Babic writel(l, ®s->gpio_dir); 81c4ea1424SStefano Babic 82c4ea1424SStefano Babic return 0; 83c4ea1424SStefano Babic } 84c4ea1424SStefano Babic 85365d6070SJoe Hershberger int gpio_set_value(unsigned gpio, int value) 86c4ea1424SStefano Babic { 87be282554SVikram Narayanan unsigned int port = GPIO_TO_PORT(gpio); 88c4ea1424SStefano Babic struct gpio_regs *regs; 89c4ea1424SStefano Babic u32 l; 90c4ea1424SStefano Babic 91c4ea1424SStefano Babic if (port >= ARRAY_SIZE(gpio_ports)) 92365d6070SJoe Hershberger return -1; 93c4ea1424SStefano Babic 94c4ea1424SStefano Babic gpio &= 0x1f; 95c4ea1424SStefano Babic 96c4ea1424SStefano Babic regs = (struct gpio_regs *)gpio_ports[port]; 97c4ea1424SStefano Babic 98c4ea1424SStefano Babic l = readl(®s->gpio_dr); 99c4ea1424SStefano Babic if (value) 100c4ea1424SStefano Babic l |= 1 << gpio; 101c4ea1424SStefano Babic else 102c4ea1424SStefano Babic l &= ~(1 << gpio); 103c4ea1424SStefano Babic writel(l, ®s->gpio_dr); 104365d6070SJoe Hershberger 105365d6070SJoe Hershberger return 0; 106c4ea1424SStefano Babic } 107c4ea1424SStefano Babic 108365d6070SJoe Hershberger int gpio_get_value(unsigned gpio) 109c4ea1424SStefano Babic { 110be282554SVikram Narayanan unsigned int port = GPIO_TO_PORT(gpio); 111c4ea1424SStefano Babic struct gpio_regs *regs; 112365d6070SJoe Hershberger u32 val; 113c4ea1424SStefano Babic 114c4ea1424SStefano Babic if (port >= ARRAY_SIZE(gpio_ports)) 115365d6070SJoe Hershberger return -1; 116c4ea1424SStefano Babic 117c4ea1424SStefano Babic gpio &= 0x1f; 118c4ea1424SStefano Babic 119c4ea1424SStefano Babic regs = (struct gpio_regs *)gpio_ports[port]; 120c4ea1424SStefano Babic 1215dafa454SBenoît Thébaudeau val = (readl(®s->gpio_psr) >> gpio) & 0x01; 122c4ea1424SStefano Babic 123365d6070SJoe Hershberger return val; 124c4ea1424SStefano Babic } 125d8e0ca85SStefano Babic 126365d6070SJoe Hershberger int gpio_request(unsigned gpio, const char *label) 127d8e0ca85SStefano Babic { 128be282554SVikram Narayanan unsigned int port = GPIO_TO_PORT(gpio); 129d8e0ca85SStefano Babic if (port >= ARRAY_SIZE(gpio_ports)) 130365d6070SJoe Hershberger return -1; 131d8e0ca85SStefano Babic return 0; 132d8e0ca85SStefano Babic } 133d8e0ca85SStefano Babic 134365d6070SJoe Hershberger int gpio_free(unsigned gpio) 135d8e0ca85SStefano Babic { 136365d6070SJoe Hershberger return 0; 137d8e0ca85SStefano Babic } 138d8e0ca85SStefano Babic 139365d6070SJoe Hershberger int gpio_direction_input(unsigned gpio) 140d8e0ca85SStefano Babic { 141365d6070SJoe Hershberger return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); 142d8e0ca85SStefano Babic } 143d8e0ca85SStefano Babic 144365d6070SJoe Hershberger int gpio_direction_output(unsigned gpio, int value) 145d8e0ca85SStefano Babic { 146365d6070SJoe Hershberger int ret = mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); 147d8e0ca85SStefano Babic 148d8e0ca85SStefano Babic if (ret < 0) 149d8e0ca85SStefano Babic return ret; 150d8e0ca85SStefano Babic 151d71c9c9fSVikram Narayanan return gpio_set_value(gpio, value); 152d8e0ca85SStefano Babic } 153