aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/Kconfig9
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/bcma_private.h10
-rw-r--r--drivers/bcma/driver_chipcommon.c81
-rw-r--r--drivers/bcma/driver_gpio.c98
-rw-r--r--drivers/bcma/main.c5
6 files changed, 199 insertions, 5 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index a533af218368..d7b56a88c9f4 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -65,6 +65,15 @@ config BCMA_DRIVER_GMAC_CMN
65 65
66 If unsure, say N 66 If unsure, say N
67 67
68config BCMA_DRIVER_GPIO
69 bool "BCMA GPIO driver"
70 depends on BCMA
71 select GPIOLIB
72 help
73 Driver to provide access to the GPIO pins of the bcma bus.
74
75 If unsure, say N
76
68config BCMA_DEBUG 77config BCMA_DEBUG
69 bool "BCMA debugging" 78 bool "BCMA debugging"
70 depends on BCMA 79 depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 8ad42d41b2f2..734b32f09c0a 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -6,6 +6,7 @@ bcma-y += driver_pci.o
6bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 6bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
7bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o 7bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
8bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o 8bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
9bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o
9bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 10bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
10bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o 11bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
11obj-$(CONFIG_BCMA) += bcma.o 12obj-$(CONFIG_BCMA) += bcma.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 537ae53231cd..4a2d72ec6d43 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -91,4 +91,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
91void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); 91void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
92#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ 92#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
93 93
94#ifdef CONFIG_BCMA_DRIVER_GPIO
95/* driver_gpio.c */
96int bcma_gpio_init(struct bcma_drv_cc *cc);
97#else
98static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
99{
100 return -ENOTSUPP;
101}
102#endif /* CONFIG_BCMA_DRIVER_GPIO */
103
94#endif 104#endif
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index dc96dd8ebff2..e461ad25fda4 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -114,6 +114,8 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
114 if (cc->early_setup_done) 114 if (cc->early_setup_done)
115 return; 115 return;
116 116
117 spin_lock_init(&cc->gpio_lock);
118
117 if (cc->core->id.rev >= 11) 119 if (cc->core->id.rev >= 11)
118 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 120 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
119 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); 121 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -202,28 +204,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
202 204
203u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) 205u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
204{ 206{
205 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); 207 unsigned long flags;
208 u32 res;
209
210 spin_lock_irqsave(&cc->gpio_lock, flags);
211 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
212 spin_unlock_irqrestore(&cc->gpio_lock, flags);
213
214 return res;
206} 215}
207 216
208u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) 217u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
209{ 218{
210 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); 219 unsigned long flags;
220 u32 res;
221
222 spin_lock_irqsave(&cc->gpio_lock, flags);
223 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
224 spin_unlock_irqrestore(&cc->gpio_lock, flags);
225
226 return res;
211} 227}
212 228
229/*
230 * If the bit is set to 0, chipcommon controlls this GPIO,
231 * if the bit is set to 1, it is used by some part of the chip and not our code.
232 */
213u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) 233u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
214{ 234{
215 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); 235 unsigned long flags;
236 u32 res;
237
238 spin_lock_irqsave(&cc->gpio_lock, flags);
239 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
240 spin_unlock_irqrestore(&cc->gpio_lock, flags);
241
242 return res;
216} 243}
217EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); 244EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
218 245
219u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) 246u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
220{ 247{
221 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); 248 unsigned long flags;
249 u32 res;
250
251 spin_lock_irqsave(&cc->gpio_lock, flags);
252 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
253 spin_unlock_irqrestore(&cc->gpio_lock, flags);
254
255 return res;
222} 256}
223 257
224u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) 258u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
225{ 259{
226 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); 260 unsigned long flags;
261 u32 res;
262
263 spin_lock_irqsave(&cc->gpio_lock, flags);
264 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
265 spin_unlock_irqrestore(&cc->gpio_lock, flags);
266
267 return res;
268}
269
270u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
271{
272 unsigned long flags;
273 u32 res;
274
275 if (cc->core->id.rev < 20)
276 return 0;
277
278 spin_lock_irqsave(&cc->gpio_lock, flags);
279 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
280 spin_unlock_irqrestore(&cc->gpio_lock, flags);
281
282 return res;
283}
284
285u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
286{
287 unsigned long flags;
288 u32 res;
289
290 if (cc->core->id.rev < 20)
291 return 0;
292
293 spin_lock_irqsave(&cc->gpio_lock, flags);
294 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
295 spin_unlock_irqrestore(&cc->gpio_lock, flags);
296
297 return res;
227} 298}
228 299
229#ifdef CONFIG_BCMA_DRIVER_MIPS 300#ifdef CONFIG_BCMA_DRIVER_MIPS
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
new file mode 100644
index 000000000000..9a6f585da2d9
--- /dev/null
+++ b/drivers/bcma/driver_gpio.c
@@ -0,0 +1,98 @@
1/*
2 * Broadcom specific AMBA
3 * GPIO driver
4 *
5 * Copyright 2011, Broadcom Corporation
6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 *
8 * Licensed under the GNU/GPL. See COPYING for details.
9 */
10
11#include <linux/gpio.h>
12#include <linux/export.h>
13#include <linux/bcma/bcma.h>
14
15#include "bcma_private.h"
16
17static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
18{
19 return container_of(chip, struct bcma_drv_cc, gpio);
20}
21
22static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
23{
24 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
25
26 return !!bcma_chipco_gpio_in(cc, 1 << gpio);
27}
28
29static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
30 int value)
31{
32 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
33
34 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
35}
36
37static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
38{
39 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
40
41 bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
42 return 0;
43}
44
45static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
46 int value)
47{
48 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
49
50 bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
51 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
52 return 0;
53}
54
55static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
56{
57 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
58
59 bcma_chipco_gpio_control(cc, 1 << gpio, 0);
60 /* clear pulldown */
61 bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
62 /* Set pullup */
63 bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
64
65 return 0;
66}
67
68static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
69{
70 struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
71
72 /* clear pullup */
73 bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
74}
75
76int bcma_gpio_init(struct bcma_drv_cc *cc)
77{
78 struct gpio_chip *chip = &cc->gpio;
79
80 chip->label = "bcma_gpio";
81 chip->owner = THIS_MODULE;
82 chip->request = bcma_gpio_request;
83 chip->free = bcma_gpio_free;
84 chip->get = bcma_gpio_get_value;
85 chip->set = bcma_gpio_set_value;
86 chip->direction_input = bcma_gpio_direction_input;
87 chip->direction_output = bcma_gpio_direction_output;
88 chip->ngpio = 16;
89 /* There is just one SoC in one device and its GPIO addresses should be
90 * deterministic to address them more easily. The other buses could get
91 * a random base number. */
92 if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
93 chip->base = 0;
94 else
95 chip->base = -1;
96
97 return gpiochip_add(chip);
98}
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index debd4f142f93..53ba20ca17e0 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -164,6 +164,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
164 bcma_err(bus, "Error registering NAND flash\n"); 164 bcma_err(bus, "Error registering NAND flash\n");
165 } 165 }
166#endif 166#endif
167 err = bcma_gpio_init(&bus->drv_cc);
168 if (err == -ENOTSUPP)
169 bcma_debug(bus, "GPIO driver not activated\n");
170 else if (err)
171 bcma_err(bus, "Error registering GPIO driver: %i\n", err);
167 172
168 if (bus->hosttype == BCMA_HOSTTYPE_SOC) { 173 if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
169 err = bcma_chipco_watchdog_register(&bus->drv_cc); 174 err = bcma_chipco_watchdog_register(&bus->drv_cc);