aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2007-07-12 00:32:52 -0400
committerBryan Wu <bryan.wu@analog.com>2007-07-12 00:32:52 -0400
commit5610db61cf2945a5e74667e952f2792c96ba53a1 (patch)
tree982c8cdb8267ac0a162b4de5d3d3b545adcff602 /arch/blackfin
parent520473b0775ce046d179afa686fb3222884c389d (diff)
Blackfin arch: Add Support for Peripheral PortMux and resouce allocation
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/mach-bf548/gpio.c189
1 files changed, 160 insertions, 29 deletions
diff --git a/arch/blackfin/mach-bf548/gpio.c b/arch/blackfin/mach-bf548/gpio.c
index 9b1a00aabf28..0da5f0003b8c 100644
--- a/arch/blackfin/mach-bf548/gpio.c
+++ b/arch/blackfin/mach-bf548/gpio.c
@@ -31,38 +31,64 @@
31#include <linux/err.h> 31#include <linux/err.h>
32#include <asm/blackfin.h> 32#include <asm/blackfin.h>
33#include <asm/gpio.h> 33#include <asm/gpio.h>
34#include <asm/portmux.h>
34#include <linux/irq.h> 35#include <linux/irq.h>
35 36
36static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = { 37static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
37 (struct gpio_port_t *) PORTA_FER, 38 (struct gpio_port_t *)PORTA_FER,
38 (struct gpio_port_t *) PORTB_FER, 39 (struct gpio_port_t *)PORTB_FER,
39 (struct gpio_port_t *) PORTC_FER, 40 (struct gpio_port_t *)PORTC_FER,
40 (struct gpio_port_t *) PORTD_FER, 41 (struct gpio_port_t *)PORTD_FER,
41 (struct gpio_port_t *) PORTE_FER, 42 (struct gpio_port_t *)PORTE_FER,
42 (struct gpio_port_t *) PORTF_FER, 43 (struct gpio_port_t *)PORTF_FER,
43 (struct gpio_port_t *) PORTG_FER, 44 (struct gpio_port_t *)PORTG_FER,
44 (struct gpio_port_t *) PORTH_FER, 45 (struct gpio_port_t *)PORTH_FER,
45 (struct gpio_port_t *) PORTI_FER, 46 (struct gpio_port_t *)PORTI_FER,
46 (struct gpio_port_t *) PORTJ_FER, 47 (struct gpio_port_t *)PORTJ_FER,
47}; 48};
48 49
49static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 50static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
51static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
50 52
51inline int check_gpio(unsigned short gpio) 53inline int check_gpio(unsigned short gpio)
52{ 54{
53 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 \ 55 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
54 || gpio == GPIO_PH14 || gpio == GPIO_PH15 \ 56 || gpio == GPIO_PH14 || gpio == GPIO_PH15
55 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15 \ 57 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
56 || gpio > MAX_BLACKFIN_GPIOS) 58 || gpio > MAX_BLACKFIN_GPIOS)
57 return -EINVAL; 59 return -EINVAL;
58 return 0; 60 return 0;
59} 61}
60 62
63inline void portmux_setup(unsigned short portno, unsigned short function)
64{
65 u32 pmux;
66
67 pmux = gpio_array[gpio_bank(portno)]->port_mux;
68
69 pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
70 pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
71
72 gpio_array[gpio_bank(portno)]->port_mux = pmux;
73
74}
75
76inline u16 get_portmux(unsigned short portno)
77{
78 u32 pmux;
79
80 pmux = gpio_array[gpio_bank(portno)]->port_mux;
81
82 return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
83
84}
85
61static void port_setup(unsigned short gpio, unsigned short usage) 86static void port_setup(unsigned short gpio, unsigned short usage)
62{ 87{
63 if (usage == GPIO_USAGE) { 88 if (usage == GPIO_USAGE) {
64 if (gpio_array[gpio_bank(gpio)]->port_fer & gpio_bit(gpio)) 89 if (gpio_array[gpio_bank(gpio)]->port_fer & gpio_bit(gpio))
65 printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral " 90 printk(KERN_WARNING
91 "bfin-gpio: Possible Conflict with Peripheral "
66 "usage and GPIO %d detected!\n", gpio); 92 "usage and GPIO %d detected!\n", gpio);
67 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); 93 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
68 } else 94 } else
@@ -72,18 +98,116 @@ static void port_setup(unsigned short gpio, unsigned short usage)
72 98
73static int __init bfin_gpio_init(void) 99static int __init bfin_gpio_init(void)
74{ 100{
75 int i;
76
77 printk(KERN_INFO "Blackfin GPIO Controller\n"); 101 printk(KERN_INFO "Blackfin GPIO Controller\n");
78 102
79 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE)
80 reserved_map[gpio_bank(i)] = 0;
81
82 return 0; 103 return 0;
83} 104}
84 105
85arch_initcall(bfin_gpio_init); 106arch_initcall(bfin_gpio_init);
86 107
108int peripheral_request(unsigned short per, const char *label)
109{
110 unsigned long flags;
111 unsigned short ident = P_IDENT(per);
112
113 if (!(per & P_DEFINED))
114 return -ENODEV;
115
116 if (check_gpio(ident) < 0)
117 return -EINVAL;
118
119 local_irq_save(flags);
120
121 if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
122 printk(KERN_ERR
123 "%s: Peripheral %d is already reserved as GPIO!\n",
124 __FUNCTION__, per);
125 dump_stack();
126 local_irq_restore(flags);
127 return -EBUSY;
128 }
129
130 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
131
132 u16 funct = get_portmux(ident);
133
134 if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
135 printk(KERN_ERR
136 "%s: Peripheral %d is already reserved!\n",
137 __FUNCTION__, per);
138 dump_stack();
139 local_irq_restore(flags);
140 return -EBUSY;
141 }
142 }
143
144 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
145
146 portmux_setup(ident, P_FUNCT2MUX(per));
147 port_setup(ident, PERIPHERAL_USAGE);
148
149 local_irq_restore(flags);
150
151 return 0;
152}
153EXPORT_SYMBOL(peripheral_request);
154
155int peripheral_request_list(unsigned short per[], const char *label)
156{
157
158 u16 cnt;
159 int ret;
160
161 for (cnt = 0; per[cnt] != 0; cnt++) {
162 ret = peripheral_request(per[cnt], label);
163 if (ret < 0)
164 return ret;
165 }
166
167 return 0;
168}
169EXPORT_SYMBOL(peripheral_request_list);
170
171void peripheral_free(unsigned short per)
172{
173 unsigned long flags;
174 unsigned short ident = P_IDENT(per);
175
176 if (!(per & P_DEFINED))
177 return;
178
179 if (check_gpio(ident) < 0)
180 return;
181
182 local_irq_save(flags);
183
184 if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
185 printk(KERN_ERR "bfin-gpio: Peripheral %d wasn't reserved!\n", per);
186 dump_stack();
187 local_irq_restore(flags);
188 return;
189 }
190
191 if (!(per & P_MAYSHARE)) {
192 port_setup(ident, GPIO_USAGE);
193 }
194
195 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
196
197 local_irq_restore(flags);
198}
199EXPORT_SYMBOL(peripheral_free);
200
201void peripheral_free_list(unsigned short per[])
202{
203 u16 cnt;
204
205 for (cnt = 0; per[cnt] != 0; cnt++) {
206 peripheral_free(per[cnt]);
207 }
208
209}
210EXPORT_SYMBOL(peripheral_free_list);
87 211
88/*********************************************************** 212/***********************************************************
89* 213*
@@ -109,13 +233,22 @@ int gpio_request(unsigned short gpio, const char *label)
109 233
110 local_irq_save(flags); 234 local_irq_save(flags);
111 235
112 if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) { 236 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
113 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); 237 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
114 dump_stack(); 238 dump_stack();
115 local_irq_restore(flags); 239 local_irq_restore(flags);
116 return -EBUSY; 240 return -EBUSY;
117 } 241 }
118 reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio); 242
243 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
244 printk(KERN_ERR
245 "bfin-gpio: GPIO %d is already reserved as Peripheral!\n", gpio);
246 dump_stack();
247 local_irq_restore(flags);
248 return -EBUSY;
249 }
250
251 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
119 252
120 local_irq_restore(flags); 253 local_irq_restore(flags);
121 254
@@ -125,7 +258,6 @@ int gpio_request(unsigned short gpio, const char *label)
125} 258}
126EXPORT_SYMBOL(gpio_request); 259EXPORT_SYMBOL(gpio_request);
127 260
128
129void gpio_free(unsigned short gpio) 261void gpio_free(unsigned short gpio)
130{ 262{
131 unsigned long flags; 263 unsigned long flags;
@@ -135,25 +267,24 @@ void gpio_free(unsigned short gpio)
135 267
136 local_irq_save(flags); 268 local_irq_save(flags);
137 269
138 if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { 270 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
139 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); 271 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
140 dump_stack(); 272 dump_stack();
141 local_irq_restore(flags); 273 local_irq_restore(flags);
142 return; 274 return;
143 } 275 }
144 276
145 reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); 277 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
146 278
147 local_irq_restore(flags); 279 local_irq_restore(flags);
148} 280}
149EXPORT_SYMBOL(gpio_free); 281EXPORT_SYMBOL(gpio_free);
150 282
151
152void gpio_direction_input(unsigned short gpio) 283void gpio_direction_input(unsigned short gpio)
153{ 284{
154 unsigned long flags; 285 unsigned long flags;
155 286
156 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 287 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
157 288
158 local_irq_save(flags); 289 local_irq_save(flags);
159 gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); 290 gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
@@ -166,7 +297,7 @@ void gpio_direction_output(unsigned short gpio)
166{ 297{
167 unsigned long flags; 298 unsigned long flags;
168 299
169 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 300 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
170 301
171 local_irq_save(flags); 302 local_irq_save(flags);
172 gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); 303 gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);