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