xref: /openbmc/linux/arch/m68k/coldfire/gpio.c (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
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  
__mcfgpio_get_value(unsigned gpio)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  
__mcfgpio_set_value(unsigned gpio,int value)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  
__mcfgpio_direction_input(unsigned gpio)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  
__mcfgpio_direction_output(unsigned gpio,int value)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  
__mcfgpio_request(unsigned gpio)96  int __mcfgpio_request(unsigned gpio)
97  {
98  	return 0;
99  }
100  EXPORT_SYMBOL(__mcfgpio_request);
101  
__mcfgpio_free(unsigned gpio)102  void __mcfgpio_free(unsigned gpio)
103  {
104  	__mcfgpio_direction_input(gpio);
105  }
106  EXPORT_SYMBOL(__mcfgpio_free);
107  
108  #ifdef CONFIG_GPIOLIB
109  
mcfgpio_direction_input(struct gpio_chip * chip,unsigned offset)110  static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
111  {
112  	return __mcfgpio_direction_input(offset);
113  }
114  
mcfgpio_get_value(struct gpio_chip * chip,unsigned offset)115  static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
116  {
117  	return !!__mcfgpio_get_value(offset);
118  }
119  
mcfgpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)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  
mcfgpio_set_value(struct gpio_chip * chip,unsigned offset,int value)126  static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
127  			      int value)
128  {
129  	__mcfgpio_set_value(offset, value);
130  }
131  
mcfgpio_request(struct gpio_chip * chip,unsigned offset)132  static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
133  {
134  	return __mcfgpio_request(offset);
135  }
136  
mcfgpio_free(struct gpio_chip * chip,unsigned offset)137  static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
138  {
139  	__mcfgpio_free(offset);
140  }
141  
mcfgpio_to_irq(struct gpio_chip * chip,unsigned offset)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  
mcfgpio_sysinit(void)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