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