]>
Commit | Line | Data |
---|---|---|
af39bb8b | 1 | /* |
2 | * Coldfire generic GPIO support. | |
3 | * | |
4 | * (C) Copyright 2009, Steven King <[email protected]> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; version 2 of the License. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | */ | |
15 | ||
16 | #include <linux/kernel.h> | |
eac57949 | 17 | #include <linux/module.h> |
af39bb8b | 18 | #include <linux/init.h> |
a6ec0c03 | 19 | #include <linux/device.h> |
af39bb8b | 20 | |
eac57949 SK |
21 | #include <linux/io.h> |
22 | #include <asm/coldfire.h> | |
23 | #include <asm/mcfsim.h> | |
af39bb8b | 24 | #include <asm/mcfgpio.h> |
25 | ||
eac57949 SK |
26 | int __mcfgpio_get_value(unsigned gpio) |
27 | { | |
28 | return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio); | |
29 | } | |
30 | EXPORT_SYMBOL(__mcfgpio_get_value); | |
31 | ||
32 | void __mcfgpio_set_value(unsigned gpio, int value) | |
33 | { | |
34 | if (gpio < MCFGPIO_SCR_START) { | |
35 | unsigned long flags; | |
36 | MCFGPIO_PORTTYPE data; | |
37 | ||
38 | local_irq_save(flags); | |
39 | data = mcfgpio_read(__mcfgpio_podr(gpio)); | |
40 | if (value) | |
41 | data |= mcfgpio_bit(gpio); | |
42 | else | |
43 | data &= ~mcfgpio_bit(gpio); | |
44 | mcfgpio_write(data, __mcfgpio_podr(gpio)); | |
45 | local_irq_restore(flags); | |
46 | } else { | |
47 | if (value) | |
48 | mcfgpio_write(mcfgpio_bit(gpio), | |
49 | MCFGPIO_SETR_PORT(gpio)); | |
50 | else | |
51 | mcfgpio_write(~mcfgpio_bit(gpio), | |
52 | MCFGPIO_CLRR_PORT(gpio)); | |
53 | } | |
54 | } | |
55 | EXPORT_SYMBOL(__mcfgpio_set_value); | |
af39bb8b | 56 | |
eac57949 | 57 | int __mcfgpio_direction_input(unsigned gpio) |
af39bb8b | 58 | { |
59 | unsigned long flags; | |
60 | MCFGPIO_PORTTYPE dir; | |
af39bb8b | 61 | |
62 | local_irq_save(flags); | |
eac57949 SK |
63 | dir = mcfgpio_read(__mcfgpio_pddr(gpio)); |
64 | dir &= ~mcfgpio_bit(gpio); | |
65 | mcfgpio_write(dir, __mcfgpio_pddr(gpio)); | |
af39bb8b | 66 | local_irq_restore(flags); |
67 | ||
68 | return 0; | |
69 | } | |
eac57949 | 70 | EXPORT_SYMBOL(__mcfgpio_direction_input); |
af39bb8b | 71 | |
eac57949 | 72 | int __mcfgpio_direction_output(unsigned gpio, int value) |
af39bb8b | 73 | { |
74 | unsigned long flags; | |
75 | MCFGPIO_PORTTYPE data; | |
af39bb8b | 76 | |
77 | local_irq_save(flags); | |
eac57949 | 78 | data = mcfgpio_read(__mcfgpio_pddr(gpio)); |
ffca5af9 | 79 | data |= mcfgpio_bit(gpio); |
eac57949 SK |
80 | mcfgpio_write(data, __mcfgpio_pddr(gpio)); |
81 | ||
82 | /* now set the data to output */ | |
83 | if (gpio < MCFGPIO_SCR_START) { | |
84 | data = mcfgpio_read(__mcfgpio_podr(gpio)); | |
85 | if (value) | |
86 | data |= mcfgpio_bit(gpio); | |
87 | else | |
88 | data &= ~mcfgpio_bit(gpio); | |
89 | mcfgpio_write(data, __mcfgpio_podr(gpio)); | |
90 | } else { | |
91 | if (value) | |
92 | mcfgpio_write(mcfgpio_bit(gpio), | |
93 | MCFGPIO_SETR_PORT(gpio)); | |
94 | else | |
95 | mcfgpio_write(~mcfgpio_bit(gpio), | |
96 | MCFGPIO_CLRR_PORT(gpio)); | |
97 | } | |
af39bb8b | 98 | local_irq_restore(flags); |
eac57949 SK |
99 | return 0; |
100 | } | |
101 | EXPORT_SYMBOL(__mcfgpio_direction_output); | |
af39bb8b | 102 | |
eac57949 SK |
103 | int __mcfgpio_request(unsigned gpio) |
104 | { | |
af39bb8b | 105 | return 0; |
106 | } | |
eac57949 | 107 | EXPORT_SYMBOL(__mcfgpio_request); |
af39bb8b | 108 | |
eac57949 | 109 | void __mcfgpio_free(unsigned gpio) |
af39bb8b | 110 | { |
eac57949 SK |
111 | __mcfgpio_direction_input(gpio); |
112 | } | |
113 | EXPORT_SYMBOL(__mcfgpio_free); | |
af39bb8b | 114 | |
eac57949 | 115 | #ifdef CONFIG_GPIOLIB |
af39bb8b | 116 | |
ec9f8483 | 117 | static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset) |
eac57949 SK |
118 | { |
119 | return __mcfgpio_direction_input(offset); | |
af39bb8b | 120 | } |
121 | ||
ec9f8483 | 122 | static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset) |
af39bb8b | 123 | { |
eac57949 | 124 | return __mcfgpio_get_value(offset); |
af39bb8b | 125 | } |
126 | ||
ec9f8483 SK |
127 | static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset, |
128 | int value) | |
af39bb8b | 129 | { |
eac57949 | 130 | return __mcfgpio_direction_output(offset, value); |
af39bb8b | 131 | } |
132 | ||
ec9f8483 SK |
133 | static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset, |
134 | int value) | |
af39bb8b | 135 | { |
eac57949 SK |
136 | __mcfgpio_set_value(offset, value); |
137 | } | |
af39bb8b | 138 | |
ec9f8483 | 139 | static int mcfgpio_request(struct gpio_chip *chip, unsigned offset) |
eac57949 SK |
140 | { |
141 | return __mcfgpio_request(offset); | |
142 | } | |
af39bb8b | 143 | |
ec9f8483 | 144 | static void mcfgpio_free(struct gpio_chip *chip, unsigned offset) |
eac57949 SK |
145 | { |
146 | __mcfgpio_free(offset); | |
af39bb8b | 147 | } |
148 | ||
ec9f8483 | 149 | static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset) |
60fc65fd SK |
150 | { |
151 | #if defined(MCFGPIO_IRQ_MIN) | |
152 | if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX)) | |
153 | #else | |
154 | if (offset < MCFGPIO_IRQ_MAX) | |
155 | #endif | |
156 | return MCFGPIO_IRQ_VECBASE + offset; | |
157 | else | |
158 | return -EINVAL; | |
159 | } | |
160 | ||
ec9f8483 | 161 | static struct bus_type mcfgpio_subsys = { |
a6ec0c03 KS |
162 | .name = "gpio", |
163 | .dev_name = "gpio", | |
af39bb8b | 164 | }; |
165 | ||
eac57949 SK |
166 | static struct gpio_chip mcfgpio_chip = { |
167 | .label = "mcfgpio", | |
168 | .request = mcfgpio_request, | |
169 | .free = mcfgpio_free, | |
170 | .direction_input = mcfgpio_direction_input, | |
171 | .direction_output = mcfgpio_direction_output, | |
172 | .get = mcfgpio_get_value, | |
173 | .set = mcfgpio_set_value, | |
60fc65fd | 174 | .to_irq = mcfgpio_to_irq, |
eac57949 SK |
175 | .base = 0, |
176 | .ngpio = MCFGPIO_PIN_MAX, | |
177 | }; | |
f23c144d | 178 | |
eac57949 SK |
179 | static int __init mcfgpio_sysinit(void) |
180 | { | |
181 | gpiochip_add(&mcfgpio_chip); | |
182 | return subsys_system_register(&mcfgpio_subsys, NULL); | |
af39bb8b | 183 | } |
184 | ||
eac57949 SK |
185 | core_initcall(mcfgpio_sysinit); |
186 | #endif |