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