Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pinmux.c
Go to the documentation of this file.
1 /*
2  * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
3  * Unassigned pins and GPIO pins can be allocated to a fixed interface
4  * or the I/O processor instead.
5  *
6  * Copyright (c) 2004-2007 Axis Communications AB.
7  */
8 
9 #include <linux/init.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/spinlock.h>
14 #include <hwregs/reg_map.h>
15 #include <hwregs/reg_rdwr.h>
16 #include <pinmux.h>
17 #include <hwregs/pinmux_defs.h>
18 
19 #undef DEBUG
20 
21 #define PORT_PINS 18
22 #define PORTS 4
23 
24 static char pins[PORTS][PORT_PINS];
25 static DEFINE_SPINLOCK(pinmux_lock);
26 
27 static void crisv32_pinmux_set(int port);
28 
30 {
31  static int initialized;
32 
33  if (!initialized) {
34  reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
35  initialized = 1;
36  REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
37  pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
38  pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
39  REG_WR(pinmux, regi_pinmux, rw_pa, pa);
44  }
45 
46  return 0;
47 }
48 
49 int
50 crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
51 {
52  int i;
53  unsigned long flags;
54 
56 
57  if (port > PORTS || port < 0)
58  return -EINVAL;
59 
60  spin_lock_irqsave(&pinmux_lock, flags);
61 
62  for (i = first_pin; i <= last_pin; i++) {
63  if ((pins[port][i] != pinmux_none)
64  && (pins[port][i] != pinmux_gpio)
65  && (pins[port][i] != mode)) {
66  spin_unlock_irqrestore(&pinmux_lock, flags);
67 #ifdef DEBUG
68  panic("Pinmux alloc failed!\n");
69 #endif
70  return -EPERM;
71  }
72  }
73 
74  for (i = first_pin; i <= last_pin; i++)
75  pins[port][i] = mode;
76 
77  crisv32_pinmux_set(port);
78 
79  spin_unlock_irqrestore(&pinmux_lock, flags);
80 
81  return 0;
82 }
83 
85 {
86  int ret = -EINVAL;
87  char saved[sizeof pins];
88  unsigned long flags;
89 
90  spin_lock_irqsave(&pinmux_lock, flags);
91 
92  /* Save internal data for recovery */
93  memcpy(saved, pins, sizeof pins);
94 
95  crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
96 
97  reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
98 
99  switch (function) {
100  case pinmux_ser1:
102  hwprot.ser1 = regk_pinmux_yes;
103  break;
104  case pinmux_ser2:
106  hwprot.ser2 = regk_pinmux_yes;
107  break;
108  case pinmux_ser3:
109  ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
110  hwprot.ser3 = regk_pinmux_yes;
111  break;
112  case pinmux_sser0:
114  ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
115  hwprot.sser0 = regk_pinmux_yes;
116  break;
117  case pinmux_sser1:
119  hwprot.sser1 = regk_pinmux_yes;
120  break;
121  case pinmux_ata0:
123  ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
124  hwprot.ata0 = regk_pinmux_yes;
125  break;
126  case pinmux_ata1:
128  ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
129  hwprot.ata1 = regk_pinmux_yes;
130  break;
131  case pinmux_ata2:
132  ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
134  hwprot.ata2 = regk_pinmux_yes;
135  break;
136  case pinmux_ata3:
139  hwprot.ata2 = regk_pinmux_yes;
140  break;
141  case pinmux_ata:
143  ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
144  hwprot.ata = regk_pinmux_yes;
145  break;
146  case pinmux_eth1:
148  hwprot.eth1 = regk_pinmux_yes;
149  hwprot.eth1_mgm = regk_pinmux_yes;
150  break;
151  case pinmux_timer:
152  ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
153  hwprot.timer = regk_pinmux_yes;
154  spin_unlock_irqrestore(&pinmux_lock, flags);
155  return ret;
156  }
157 
158  if (!ret)
159  REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
160  else
161  memcpy(pins, saved, sizeof pins);
162 
163  spin_unlock_irqrestore(&pinmux_lock, flags);
164 
165  return ret;
166 }
167 
168 void crisv32_pinmux_set(int port)
169 {
170  int i;
171  int gpio_val = 0;
172  int iop_val = 0;
173 
174  for (i = 0; i < PORT_PINS; i++) {
175  if (pins[port][i] == pinmux_gpio)
176  gpio_val |= (1 << i);
177  else if (pins[port][i] == pinmux_iop)
178  iop_val |= (1 << i);
179  }
180 
182  gpio_val);
184  iop_val);
185 
186 #ifdef DEBUG
188 #endif
189 }
190 
191 int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
192 {
193  int i;
194  unsigned long flags;
195 
197 
198  if (port > PORTS || port < 0)
199  return -EINVAL;
200 
201  spin_lock_irqsave(&pinmux_lock, flags);
202 
203  for (i = first_pin; i <= last_pin; i++)
204  pins[port][i] = pinmux_none;
205 
206  crisv32_pinmux_set(port);
207  spin_unlock_irqrestore(&pinmux_lock, flags);
208 
209  return 0;
210 }
211 
213 {
214  int ret = -EINVAL;
215  char saved[sizeof pins];
216  unsigned long flags;
217 
218  spin_lock_irqsave(&pinmux_lock, flags);
219 
220  /* Save internal data for recovery */
221  memcpy(saved, pins, sizeof pins);
222 
223  crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
224 
225  reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
226 
227  switch (function) {
228  case pinmux_ser1:
229  ret = crisv32_pinmux_dealloc(PORT_C, 4, 7);
230  hwprot.ser1 = regk_pinmux_no;
231  break;
232  case pinmux_ser2:
233  ret = crisv32_pinmux_dealloc(PORT_C, 8, 11);
234  hwprot.ser2 = regk_pinmux_no;
235  break;
236  case pinmux_ser3:
237  ret = crisv32_pinmux_dealloc(PORT_C, 12, 15);
238  hwprot.ser3 = regk_pinmux_no;
239  break;
240  case pinmux_sser0:
241  ret = crisv32_pinmux_dealloc(PORT_C, 0, 3);
242  ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16);
243  hwprot.sser0 = regk_pinmux_no;
244  break;
245  case pinmux_sser1:
246  ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
247  hwprot.sser1 = regk_pinmux_no;
248  break;
249  case pinmux_ata0:
250  ret = crisv32_pinmux_dealloc(PORT_D, 5, 7);
251  ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17);
252  hwprot.ata0 = regk_pinmux_no;
253  break;
254  case pinmux_ata1:
255  ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
256  ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17);
257  hwprot.ata1 = regk_pinmux_no;
258  break;
259  case pinmux_ata2:
260  ret = crisv32_pinmux_dealloc(PORT_C, 11, 15);
261  ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3);
262  hwprot.ata2 = regk_pinmux_no;
263  break;
264  case pinmux_ata3:
265  ret = crisv32_pinmux_dealloc(PORT_C, 8, 10);
266  ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2);
267  hwprot.ata2 = regk_pinmux_no;
268  break;
269  case pinmux_ata:
270  ret = crisv32_pinmux_dealloc(PORT_B, 0, 15);
271  ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15);
272  hwprot.ata = regk_pinmux_no;
273  break;
274  case pinmux_eth1:
275  ret = crisv32_pinmux_dealloc(PORT_E, 0, 17);
276  hwprot.eth1 = regk_pinmux_no;
277  hwprot.eth1_mgm = regk_pinmux_no;
278  break;
279  case pinmux_timer:
280  ret = crisv32_pinmux_dealloc(PORT_C, 16, 16);
281  hwprot.timer = regk_pinmux_no;
282  spin_unlock_irqrestore(&pinmux_lock, flags);
283  return ret;
284  }
285 
286  if (!ret)
287  REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
288  else
289  memcpy(pins, saved, sizeof pins);
290 
291  spin_unlock_irqrestore(&pinmux_lock, flags);
292 
293  return ret;
294 }
295 
297 {
298  int i, j;
299 
301 
302  for (i = 0; i < PORTS; i++) {
303  printk(KERN_DEBUG "Port %c\n", 'B' + i);
304  for (j = 0; j < PORT_PINS; j++)
305  printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
306  }
307 }
308