1 /* 2 * arch/arm/plat-orion/gpio.c 3 * 4 * Marvell Orion SoC GPIO handling. 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 22 * MA 02110-1301 USA 23 */ 24 25 /* 26 * Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver. 27 * Removed orion_gpiochip struct and kernel level irq handling. 28 * 29 * Dieter Kiermaier dk-arm-linux@gmx.de 30 */ 31 32 #include <common.h> 33 #include <asm/bitops.h> 34 #include <asm/arch/kirkwood.h> 35 #include <asm/arch/gpio.h> 36 37 static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; 38 static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; 39 40 void __set_direction(unsigned pin, int input) 41 { 42 u32 u; 43 44 u = readl(GPIO_IO_CONF(pin)); 45 if (input) 46 u |= 1 << (pin & 31); 47 else 48 u &= ~(1 << (pin & 31)); 49 writel(u, GPIO_IO_CONF(pin)); 50 51 u = readl(GPIO_IO_CONF(pin)); 52 } 53 54 void __set_level(unsigned pin, int high) 55 { 56 u32 u; 57 58 u = readl(GPIO_OUT(pin)); 59 if (high) 60 u |= 1 << (pin & 31); 61 else 62 u &= ~(1 << (pin & 31)); 63 writel(u, GPIO_OUT(pin)); 64 } 65 66 void __set_blinking(unsigned pin, int blink) 67 { 68 u32 u; 69 70 u = readl(GPIO_BLINK_EN(pin)); 71 if (blink) 72 u |= 1 << (pin & 31); 73 else 74 u &= ~(1 << (pin & 31)); 75 writel(u, GPIO_BLINK_EN(pin)); 76 } 77 78 int kw_gpio_is_valid(unsigned pin, int mode) 79 { 80 if (pin < GPIO_MAX) { 81 if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input)) 82 goto err_out; 83 84 if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output)) 85 goto err_out; 86 return 0; 87 } 88 89 err_out: 90 printf("%s: invalid GPIO %d\n", __func__, pin); 91 return 1; 92 } 93 94 void kw_gpio_set_valid(unsigned pin, int mode) 95 { 96 if (mode == 1) 97 mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; 98 if (mode & GPIO_INPUT_OK) 99 __set_bit(pin, gpio_valid_input); 100 else 101 __clear_bit(pin, gpio_valid_input); 102 if (mode & GPIO_OUTPUT_OK) 103 __set_bit(pin, gpio_valid_output); 104 else 105 __clear_bit(pin, gpio_valid_output); 106 } 107 /* 108 * GENERIC_GPIO primitives. 109 */ 110 int kw_gpio_direction_input(unsigned pin) 111 { 112 if (!kw_gpio_is_valid(pin, GPIO_INPUT_OK)) 113 return 1; 114 115 /* Configure GPIO direction. */ 116 __set_direction(pin, 1); 117 118 return 0; 119 } 120 121 int kw_gpio_direction_output(unsigned pin, int value) 122 { 123 if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0) 124 { 125 printf("%s: invalid GPIO %d\n", __func__, pin); 126 return 1; 127 } 128 129 __set_blinking(pin, 0); 130 131 /* Configure GPIO output value. */ 132 __set_level(pin, value); 133 134 /* Configure GPIO direction. */ 135 __set_direction(pin, 0); 136 137 return 0; 138 } 139 140 int kw_gpio_get_value(unsigned pin) 141 { 142 int val; 143 144 if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) 145 val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); 146 else 147 val = readl(GPIO_OUT(pin)); 148 149 return (val >> (pin & 31)) & 1; 150 } 151 152 void kw_gpio_set_value(unsigned pin, int value) 153 { 154 /* Configure GPIO output value. */ 155 __set_level(pin, value); 156 } 157 158 void kw_gpio_set_blink(unsigned pin, int blink) 159 { 160 /* Set output value to zero. */ 161 __set_level(pin, 0); 162 163 /* Set blinking. */ 164 __set_blinking(pin, blink); 165 } 166