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 169fc58427d3..8cd80bff8e91 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -89,4 +89,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
89void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); 89void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
90#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ 90#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
91 91
92#ifdef CONFIG_BCMA_DRIVER_GPIO
93/* driver_gpio.c */
94int bcma_gpio_init(struct bcma_drv_cc *cc);
95#else
96static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
97{
98 return -ENOTSUPP;
99}
100#endif /* CONFIG_BCMA_DRIVER_GPIO */
101
92#endif 102#endif
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index a4c3ebcc4c86..994fce65f77d 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -30,6 +30,8 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
30 if (cc->setup_done) 30 if (cc->setup_done)
31 return; 31 return;
32 32
33 spin_lock_init(&cc->gpio_lock);
34
33 if (cc->core->id.rev >= 11) 35 if (cc->core->id.rev >= 11)
34 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 36 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
35 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); 37 cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
@@ -84,28 +86,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
84 86
85u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) 87u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
86{ 88{
87 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); 89 unsigned long flags;
90 u32 res;
91
92 spin_lock_irqsave(&cc->gpio_lock, flags);
93 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
94 spin_unlock_irqrestore(&cc->gpio_lock, flags);
95
96 return res;
88} 97}
89 98
90u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) 99u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
91{ 100{
92 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); 101 unsigned long flags;
102 u32 res;
103
104 spin_lock_irqsave(&cc->gpio_lock, flags);
105 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
106 spin_unlock_irqrestore(&cc->gpio_lock, flags);
107
108 return res;
93} 109}
94 110
111/*
112 * If the bit is set to 0, chipcommon controlls this GPIO,
113 * if the bit is set to 1, it is used by some part of the chip and not our code.
114 */
95u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) 115u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
96{ 116{
97 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); 117 unsigned long flags;
118 u32 res;
119
120 spin_lock_irqsave(&cc->gpio_lock, flags);
121 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
122 spin_unlock_irqrestore(&cc->gpio_lock, flags);
123
124 return res;
98} 125}
99EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); 126EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
100 127
101u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) 128u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
102{ 129{
103 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); 130 unsigned long flags;
131 u32 res;
132
133 spin_lock_irqsave(&cc->gpio_lock, flags);
134 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
135 spin_unlock_irqrestore(&cc->gpio_lock, flags);
136
137 return res;
104} 138}
105 139
106u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) 140u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
107{ 141{
108 return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); 142 unsigned long flags;
143 u32 res;
144
145 spin_lock_irqsave(&cc->gpio_lock, flags);
146 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
147 spin_unlock_irqrestore(&cc->gpio_lock, flags);
148
149 return res;
150}
151
152u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value)
153{
154 unsigned long flags;
155 u32 res;
156
157 if (cc->core->id.rev < 20)
158 return 0;
159
160 spin_lock_irqsave(&cc->gpio_lock, flags);
161 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value);
162 spin_unlock_irqrestore(&cc->gpio_lock, flags);
163
164 return res;
165}
166
167u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
168{
169 unsigned long flags;
170 u32 res;
171
172 if (cc->core->id.rev < 20)
173 return 0;
174
175 spin_lock_irqsave(&cc->gpio_lock, flags);
176 res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value);
177 spin_unlock_irqrestore(&cc->gpio_lock, flags);
178
179 return res;
109} 180}
110 181
111#ifdef CONFIG_BCMA_DRIVER_MIPS 182#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 d865470bc951..478ba01ca0c2 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -152,6 +152,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
152 bcma_err(bus, "Error registering NAND flash\n"); 152 bcma_err(bus, "Error registering NAND flash\n");
153 } 153 }
154#endif 154#endif
155 err = bcma_gpio_init(&bus->drv_cc);
156 if (err == -ENOTSUPP)
157 bcma_debug(bus, "GPIO driver not activated\n");
158 else if (err)
159 bcma_err(bus, "Error registering GPIO driver: %i\n", err);
155 160
156 return 0; 161 return 0;
157} 162}