1 /* 2 * arch/arm/plat-orion/gpio.c 3 * 4 * Marvell Orion SoC GPIO handling. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 /* 10 * Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver. 11 * Removed orion_gpiochip struct and kernel level irq handling. 12 * 13 * Dieter Kiermaier dk-arm-linux@gmx.de 14 */ 15 16 #include <common.h> 17 #include <linux/bitops.h> 18 #include <asm/io.h> 19 #include <asm/arch/soc.h> 20 #include <asm/arch/gpio.h> 21 22 static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; 23 static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; 24 25 void __set_direction(unsigned pin, int input) 26 { 27 u32 u; 28 29 u = readl(GPIO_IO_CONF(pin)); 30 if (input) 31 u |= 1 << (pin & 31); 32 else 33 u &= ~(1 << (pin & 31)); 34 writel(u, GPIO_IO_CONF(pin)); 35 36 u = readl(GPIO_IO_CONF(pin)); 37 } 38 39 static void __set_level(unsigned pin, int high) 40 { 41 u32 u; 42 43 u = readl(GPIO_OUT(pin)); 44 if (high) 45 u |= 1 << (pin & 31); 46 else 47 u &= ~(1 << (pin & 31)); 48 writel(u, GPIO_OUT(pin)); 49 } 50 51 static void __set_blinking(unsigned pin, int blink) 52 { 53 u32 u; 54 55 u = readl(GPIO_BLINK_EN(pin)); 56 if (blink) 57 u |= 1 << (pin & 31); 58 else 59 u &= ~(1 << (pin & 31)); 60 writel(u, GPIO_BLINK_EN(pin)); 61 } 62 63 int kw_gpio_is_valid(unsigned pin, int mode) 64 { 65 if (pin < GPIO_MAX) { 66 if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input)) 67 goto err_out; 68 69 if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output)) 70 goto err_out; 71 return 0; 72 } 73 74 err_out: 75 printf("%s: invalid GPIO %d\n", __func__, pin); 76 return 1; 77 } 78 79 void kw_gpio_set_valid(unsigned pin, int mode) 80 { 81 if (mode == 1) 82 mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK; 83 if (mode & GPIO_INPUT_OK) 84 __set_bit(pin, gpio_valid_input); 85 else 86 __clear_bit(pin, gpio_valid_input); 87 if (mode & GPIO_OUTPUT_OK) 88 __set_bit(pin, gpio_valid_output); 89 else 90 __clear_bit(pin, gpio_valid_output); 91 } 92 /* 93 * GENERIC_GPIO primitives. 94 */ 95 int kw_gpio_direction_input(unsigned pin) 96 { 97 if (kw_gpio_is_valid(pin, GPIO_INPUT_OK) != 0) 98 return 1; 99 100 /* Configure GPIO direction. */ 101 __set_direction(pin, 1); 102 103 return 0; 104 } 105 106 int kw_gpio_direction_output(unsigned pin, int value) 107 { 108 if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0) 109 { 110 printf("%s: invalid GPIO %d\n", __func__, pin); 111 return 1; 112 } 113 114 __set_blinking(pin, 0); 115 116 /* Configure GPIO output value. */ 117 __set_level(pin, value); 118 119 /* Configure GPIO direction. */ 120 __set_direction(pin, 0); 121 122 return 0; 123 } 124 125 int kw_gpio_get_value(unsigned pin) 126 { 127 int val; 128 129 if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) 130 val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); 131 else 132 val = readl(GPIO_OUT(pin)); 133 134 return (val >> (pin & 31)) & 1; 135 } 136 137 void kw_gpio_set_value(unsigned pin, int value) 138 { 139 /* Configure GPIO output value. */ 140 __set_level(pin, value); 141 } 142 143 void kw_gpio_set_blink(unsigned pin, int blink) 144 { 145 /* Set output value to zero. */ 146 __set_level(pin, 0); 147 148 /* Set blinking. */ 149 __set_blinking(pin, blink); 150 } 151