aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-02-19 10:22:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-20 20:11:49 -0500
commit53521d8c90d366191b6c134f88a8ebe83de60614 (patch)
tree2d4b8bed0db743927586389ab035aab816d22f36
parentc2bcbe65fc88d61f9a806367ff6eab76c9eabb3a (diff)
ssb: Make the GPIO API reentrancy safe
This fixes the GPIO API to be reentrancy safe. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/ssb/driver_chipcommon.c6
-rw-r--r--drivers/ssb/driver_extif.c5
-rw-r--r--drivers/ssb/embedded.c106
-rw-r--r--drivers/ssb/main.c3
-rw-r--r--include/linux/ssb/ssb.h5
-rw-r--r--include/linux/ssb/ssb_embedded.h8
6 files changed, 122 insertions, 11 deletions
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 7ea0c0faa9ab..e586321a473a 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -357,37 +357,31 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
357{ 357{
358 return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; 358 return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
359} 359}
360EXPORT_SYMBOL(ssb_chipco_gpio_in);
361 360
362u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) 361u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
363{ 362{
364 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); 363 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
365} 364}
366EXPORT_SYMBOL(ssb_chipco_gpio_out);
367 365
368u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) 366u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
369{ 367{
370 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); 368 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
371} 369}
372EXPORT_SYMBOL(ssb_chipco_gpio_outen);
373 370
374u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) 371u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value)
375{ 372{
376 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); 373 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
377} 374}
378EXPORT_SYMBOL(ssb_chipco_gpio_control);
379 375
380u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) 376u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
381{ 377{
382 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); 378 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value);
383} 379}
384EXPORT_SYMBOL(ssb_chipco_gpio_intmask);
385 380
386u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) 381u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value)
387{ 382{
388 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); 383 return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value);
389} 384}
390EXPORT_SYMBOL(ssb_chipco_gpio_polarity);
391 385
392#ifdef CONFIG_SSB_SERIAL 386#ifdef CONFIG_SSB_SERIAL
393int ssb_chipco_serial_init(struct ssb_chipcommon *cc, 387int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c
index 10c6b287f8bb..c3e1d3e6d610 100644
--- a/drivers/ssb/driver_extif.c
+++ b/drivers/ssb/driver_extif.c
@@ -122,30 +122,25 @@ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
122{ 122{
123 return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; 123 return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
124} 124}
125EXPORT_SYMBOL(ssb_extif_gpio_in);
126 125
127u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) 126u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
128{ 127{
129 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), 128 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
130 mask, value); 129 mask, value);
131} 130}
132EXPORT_SYMBOL(ssb_extif_gpio_out);
133 131
134u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) 132u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
135{ 133{
136 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), 134 return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
137 mask, value); 135 mask, value);
138} 136}
139EXPORT_SYMBOL(ssb_extif_gpio_outen);
140 137
141u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) 138u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value)
142{ 139{
143 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); 140 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value);
144} 141}
145EXPORT_SYMBOL(ssb_extif_gpio_polarity);
146 142
147u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) 143u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value)
148{ 144{
149 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); 145 return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value);
150} 146}
151EXPORT_SYMBOL(ssb_extif_gpio_intmask);
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index 751f58ac612c..d3ade821555c 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -11,6 +11,8 @@
11#include <linux/ssb/ssb.h> 11#include <linux/ssb/ssb.h>
12#include <linux/ssb/ssb_embedded.h> 12#include <linux/ssb/ssb_embedded.h>
13 13
14#include "ssb_private.h"
15
14 16
15int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) 17int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
16{ 18{
@@ -24,3 +26,107 @@ int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
24 } 26 }
25 return -ENODEV; 27 return -ENODEV;
26} 28}
29
30u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
31{
32 unsigned long flags;
33 u32 res = 0;
34
35 spin_lock_irqsave(&bus->gpio_lock, flags);
36 if (ssb_chipco_available(&bus->chipco))
37 res = ssb_chipco_gpio_in(&bus->chipco, mask);
38 else if (ssb_extif_available(&bus->extif))
39 res = ssb_extif_gpio_in(&bus->extif, mask);
40 else
41 SSB_WARN_ON(1);
42 spin_unlock_irqrestore(&bus->gpio_lock, flags);
43
44 return res;
45}
46EXPORT_SYMBOL(ssb_gpio_in);
47
48u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
49{
50 unsigned long flags;
51 u32 res = 0;
52
53 spin_lock_irqsave(&bus->gpio_lock, flags);
54 if (ssb_chipco_available(&bus->chipco))
55 res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
56 else if (ssb_extif_available(&bus->extif))
57 res = ssb_extif_gpio_out(&bus->extif, mask, value);
58 else
59 SSB_WARN_ON(1);
60 spin_unlock_irqrestore(&bus->gpio_lock, flags);
61
62 return res;
63}
64EXPORT_SYMBOL(ssb_gpio_out);
65
66u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
67{
68 unsigned long flags;
69 u32 res = 0;
70
71 spin_lock_irqsave(&bus->gpio_lock, flags);
72 if (ssb_chipco_available(&bus->chipco))
73 res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
74 else if (ssb_extif_available(&bus->extif))
75 res = ssb_extif_gpio_outen(&bus->extif, mask, value);
76 else
77 SSB_WARN_ON(1);
78 spin_unlock_irqrestore(&bus->gpio_lock, flags);
79
80 return res;
81}
82EXPORT_SYMBOL(ssb_gpio_outen);
83
84u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
85{
86 unsigned long flags;
87 u32 res = 0;
88
89 spin_lock_irqsave(&bus->gpio_lock, flags);
90 if (ssb_chipco_available(&bus->chipco))
91 res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
92 spin_unlock_irqrestore(&bus->gpio_lock, flags);
93
94 return res;
95}
96EXPORT_SYMBOL(ssb_gpio_control);
97
98u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
99{
100 unsigned long flags;
101 u32 res = 0;
102
103 spin_lock_irqsave(&bus->gpio_lock, flags);
104 if (ssb_chipco_available(&bus->chipco))
105 res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
106 else if (ssb_extif_available(&bus->extif))
107 res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
108 else
109 SSB_WARN_ON(1);
110 spin_unlock_irqrestore(&bus->gpio_lock, flags);
111
112 return res;
113}
114EXPORT_SYMBOL(ssb_gpio_intmask);
115
116u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
117{
118 unsigned long flags;
119 u32 res = 0;
120
121 spin_lock_irqsave(&bus->gpio_lock, flags);
122 if (ssb_chipco_available(&bus->chipco))
123 res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
124 else if (ssb_extif_available(&bus->extif))
125 res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
126 else
127 SSB_WARN_ON(1);
128 spin_unlock_irqrestore(&bus->gpio_lock, flags);
129
130 return res;
131}
132EXPORT_SYMBOL(ssb_gpio_polarity);
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 9028ed5715a1..af07ab22708f 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -569,6 +569,9 @@ static int ssb_bus_register(struct ssb_bus *bus,
569 569
570 spin_lock_init(&bus->bar_lock); 570 spin_lock_init(&bus->bar_lock);
571 INIT_LIST_HEAD(&bus->list); 571 INIT_LIST_HEAD(&bus->list);
572#ifdef CONFIG_SSB_EMBEDDED
573 spin_lock_init(&bus->gpio_lock);
574#endif
572 575
573 /* Powerup the bus */ 576 /* Powerup the bus */
574 err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); 577 err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 9d5da8b2ccf9..d14c03685717 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -283,6 +283,11 @@ struct ssb_bus {
283 /* Contents of the SPROM. */ 283 /* Contents of the SPROM. */
284 struct ssb_sprom sprom; 284 struct ssb_sprom sprom;
285 285
286#ifdef CONFIG_SSB_EMBEDDED
287 /* Lock for GPIO register access. */
288 spinlock_t gpio_lock;
289#endif /* EMBEDDED */
290
286 /* Internal-only stuff follows. Do not touch. */ 291 /* Internal-only stuff follows. Do not touch. */
287 struct list_head list; 292 struct list_head list;
288#ifdef CONFIG_SSB_DEBUG 293#ifdef CONFIG_SSB_DEBUG
diff --git a/include/linux/ssb/ssb_embedded.h b/include/linux/ssb/ssb_embedded.h
index 80bd58496450..8d8dedff059d 100644
--- a/include/linux/ssb/ssb_embedded.h
+++ b/include/linux/ssb/ssb_embedded.h
@@ -7,4 +7,12 @@
7 7
8extern int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks); 8extern int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks);
9 9
10/* Generic GPIO API */
11u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask);
12u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value);
13u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value);
14u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value);
15u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value);
16u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value);
17
10#endif /* LINUX_SSB_EMBEDDED_H_ */ 18#endif /* LINUX_SSB_EMBEDDED_H_ */