xref: /linux/arch/m68k/coldfire/gpio.c (revision 44f57d78)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Coldfire generic GPIO support.
4  *
5  * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/device.h>
12 
13 #include <linux/io.h>
14 #include <asm/coldfire.h>
15 #include <asm/mcfsim.h>
16 #include <asm/mcfgpio.h>
17 
18 int __mcfgpio_get_value(unsigned gpio)
19 {
20 	return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
21 }
22 EXPORT_SYMBOL(__mcfgpio_get_value);
23 
24 void __mcfgpio_set_value(unsigned gpio, int value)
25 {
26 	if (gpio < MCFGPIO_SCR_START) {
27 		unsigned long flags;
28 		MCFGPIO_PORTTYPE data;
29 
30 		local_irq_save(flags);
31 		data = mcfgpio_read(__mcfgpio_podr(gpio));
32 		if (value)
33 			data |= mcfgpio_bit(gpio);
34 		else
35 			data &= ~mcfgpio_bit(gpio);
36 		mcfgpio_write(data, __mcfgpio_podr(gpio));
37 		local_irq_restore(flags);
38 	} else {
39 		if (value)
40 			mcfgpio_write(mcfgpio_bit(gpio),
41 					MCFGPIO_SETR_PORT(gpio));
42 		else
43 			mcfgpio_write(~mcfgpio_bit(gpio),
44 					MCFGPIO_CLRR_PORT(gpio));
45 	}
46 }
47 EXPORT_SYMBOL(__mcfgpio_set_value);
48 
49 int __mcfgpio_direction_input(unsigned gpio)
50 {
51 	unsigned long flags;
52 	MCFGPIO_PORTTYPE dir;
53 
54 	local_irq_save(flags);
55 	dir = mcfgpio_read(__mcfgpio_pddr(gpio));
56 	dir &= ~mcfgpio_bit(gpio);
57 	mcfgpio_write(dir, __mcfgpio_pddr(gpio));
58 	local_irq_restore(flags);
59 
60 	return 0;
61 }
62 EXPORT_SYMBOL(__mcfgpio_direction_input);
63 
64 int __mcfgpio_direction_output(unsigned gpio, int value)
65 {
66 	unsigned long flags;
67 	MCFGPIO_PORTTYPE data;
68 
69 	local_irq_save(flags);
70 	data = mcfgpio_read(__mcfgpio_pddr(gpio));
71 	data |= mcfgpio_bit(gpio);
72 	mcfgpio_write(data, __mcfgpio_pddr(gpio));
73 
74 	/* now set the data to output */
75 	if (gpio < MCFGPIO_SCR_START) {
76 		data = mcfgpio_read(__mcfgpio_podr(gpio));
77 		if (value)
78 			data |= mcfgpio_bit(gpio);
79 		else
80 			data &= ~mcfgpio_bit(gpio);
81 		mcfgpio_write(data, __mcfgpio_podr(gpio));
82 	} else {
83 		 if (value)
84 			mcfgpio_write(mcfgpio_bit(gpio),
85 					MCFGPIO_SETR_PORT(gpio));
86 		 else
87 			 mcfgpio_write(~mcfgpio_bit(gpio),
88 					 MCFGPIO_CLRR_PORT(gpio));
89 	}
90 	local_irq_restore(flags);
91 	return 0;
92 }
93 EXPORT_SYMBOL(__mcfgpio_direction_output);
94 
95 int __mcfgpio_request(unsigned gpio)
96 {
97 	return 0;
98 }
99 EXPORT_SYMBOL(__mcfgpio_request);
100 
101 void __mcfgpio_free(unsigned gpio)
102 {
103 	__mcfgpio_direction_input(gpio);
104 }
105 EXPORT_SYMBOL(__mcfgpio_free);
106 
107 #ifdef CONFIG_GPIOLIB
108 
109 static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
110 {
111 	return __mcfgpio_direction_input(offset);
112 }
113 
114 static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
115 {
116 	return !!__mcfgpio_get_value(offset);
117 }
118 
119 static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
120 				    int value)
121 {
122 	return __mcfgpio_direction_output(offset, value);
123 }
124 
125 static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
126 			      int value)
127 {
128 	__mcfgpio_set_value(offset, value);
129 }
130 
131 static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
132 {
133 	return __mcfgpio_request(offset);
134 }
135 
136 static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
137 {
138 	__mcfgpio_free(offset);
139 }
140 
141 static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
142 {
143 #if defined(MCFGPIO_IRQ_MIN)
144 	if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
145 #else
146 	if (offset < MCFGPIO_IRQ_MAX)
147 #endif
148 		return MCFGPIO_IRQ_VECBASE + offset;
149 	else
150 		return -EINVAL;
151 }
152 
153 static struct gpio_chip mcfgpio_chip = {
154 	.label			= "mcfgpio",
155 	.request		= mcfgpio_request,
156 	.free			= mcfgpio_free,
157 	.direction_input	= mcfgpio_direction_input,
158 	.direction_output	= mcfgpio_direction_output,
159 	.get			= mcfgpio_get_value,
160 	.set			= mcfgpio_set_value,
161 	.to_irq			= mcfgpio_to_irq,
162 	.base			= 0,
163 	.ngpio			= MCFGPIO_PIN_MAX,
164 };
165 
166 static int __init mcfgpio_sysinit(void)
167 {
168 	return gpiochip_add_data(&mcfgpio_chip, NULL);
169 }
170 
171 core_initcall(mcfgpio_sysinit);
172 #endif
173