aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/driver_gpio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-14 17:27:45 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-14 17:27:45 -0500
commitcebfa85eb86d92bf85d3b041c6b044184517a988 (patch)
treebe0a374556fe335ce96dfdb296c89537750d5868 /drivers/ssb/driver_gpio.c
parentd42b3a2906a10b732ea7d7f849d49be79d242ef0 (diff)
parent241738bd51cb0efe58e6c570223153e970afe3ae (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: "The MIPS bits for 3.8. This also includes a bunch fixes that were sitting in the linux-mips.org git tree for a long time. This pull request contains updates to several OCTEON drivers and the board support code for BCM47XX, BCM63XX, XLP, XLR, XLS, lantiq, Loongson1B, updates to the SSB bus support, MIPS kexec code and adds support for kdump. When pulling this, there are two expected merge conflicts in include/linux/bcma/bcma_driver_chipcommon.h which are trivial to resolve, just remove the conflict markers and keep both alternatives." * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (90 commits) MIPS: PMC-Sierra Yosemite: Remove support. VIDEO: Newport Fix console crashes MIPS: wrppmc: Fix build of PCI code. MIPS: IP22/IP28: Fix build of EISA code. MIPS: RB532: Fix build of prom code. MIPS: PowerTV: Fix build. MIPS: IP27: Correct fucked grammar in ops-bridge.c MIPS: Highmem: Fix build error if CONFIG_DEBUG_HIGHMEM is disabled MIPS: Fix potencial corruption MIPS: Fix for warning from FPU emulation code MIPS: Handle COP3 Unusable exception as COP1X for FP emulation MIPS: Fix poweroff failure when HOTPLUG_CPU configured. MIPS: MT: Fix build with CONFIG_UIDGID_STRICT_TYPE_CHECKS=y MIPS: Remove unused smvp.h MIPS/EDAC: Improve OCTEON EDAC support. MIPS: OCTEON: Add definitions for OCTEON memory contoller registers. MIPS: OCTEON: Add OCTEON family definitions to octeon-model.h ata: pata_octeon_cf: Use correct byte order for DMA in when built little-endian. MIPS/OCTEON/ata: Convert pata_octeon_cf.c to use device tree. MIPS: Remove usage of CEVT_R4K_LIB config option. ...
Diffstat (limited to 'drivers/ssb/driver_gpio.c')
-rw-r--r--drivers/ssb/driver_gpio.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
new file mode 100644
index 00000000000..97ac0a38e3d
--- /dev/null
+++ b/drivers/ssb/driver_gpio.c
@@ -0,0 +1,176 @@
1/*
2 * Sonics Silicon Backplane
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/ssb/ssb.h>
14
15#include "ssb_private.h"
16
17static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
18{
19 return container_of(chip, struct ssb_bus, gpio);
20}
21
22static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
23{
24 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
25
26 return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
27}
28
29static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
30 int value)
31{
32 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
33
34 ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
35}
36
37static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
38 unsigned gpio)
39{
40 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
41
42 ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
43 return 0;
44}
45
46static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
47 unsigned gpio, int value)
48{
49 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
50
51 ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
52 ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
53 return 0;
54}
55
56static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
57{
58 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
59
60 ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
61 /* clear pulldown */
62 ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
63 /* Set pullup */
64 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
65
66 return 0;
67}
68
69static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
70{
71 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
72
73 /* clear pullup */
74 ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
75}
76
77static int ssb_gpio_chipco_init(struct ssb_bus *bus)
78{
79 struct gpio_chip *chip = &bus->gpio;
80
81 chip->label = "ssb_chipco_gpio";
82 chip->owner = THIS_MODULE;
83 chip->request = ssb_gpio_chipco_request;
84 chip->free = ssb_gpio_chipco_free;
85 chip->get = ssb_gpio_chipco_get_value;
86 chip->set = ssb_gpio_chipco_set_value;
87 chip->direction_input = ssb_gpio_chipco_direction_input;
88 chip->direction_output = ssb_gpio_chipco_direction_output;
89 chip->ngpio = 16;
90 /* There is just one SoC in one device and its GPIO addresses should be
91 * deterministic to address them more easily. The other buses could get
92 * a random base number. */
93 if (bus->bustype == SSB_BUSTYPE_SSB)
94 chip->base = 0;
95 else
96 chip->base = -1;
97
98 return gpiochip_add(chip);
99}
100
101#ifdef CONFIG_SSB_DRIVER_EXTIF
102
103static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
104{
105 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
106
107 return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
108}
109
110static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
111 int value)
112{
113 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
114
115 ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
116}
117
118static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
119 unsigned gpio)
120{
121 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
122
123 ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
124 return 0;
125}
126
127static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
128 unsigned gpio, int value)
129{
130 struct ssb_bus *bus = ssb_gpio_get_bus(chip);
131
132 ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
133 ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
134 return 0;
135}
136
137static int ssb_gpio_extif_init(struct ssb_bus *bus)
138{
139 struct gpio_chip *chip = &bus->gpio;
140
141 chip->label = "ssb_extif_gpio";
142 chip->owner = THIS_MODULE;
143 chip->get = ssb_gpio_extif_get_value;
144 chip->set = ssb_gpio_extif_set_value;
145 chip->direction_input = ssb_gpio_extif_direction_input;
146 chip->direction_output = ssb_gpio_extif_direction_output;
147 chip->ngpio = 5;
148 /* There is just one SoC in one device and its GPIO addresses should be
149 * deterministic to address them more easily. The other buses could get
150 * a random base number. */
151 if (bus->bustype == SSB_BUSTYPE_SSB)
152 chip->base = 0;
153 else
154 chip->base = -1;
155
156 return gpiochip_add(chip);
157}
158
159#else
160static int ssb_gpio_extif_init(struct ssb_bus *bus)
161{
162 return -ENOTSUPP;
163}
164#endif
165
166int ssb_gpio_init(struct ssb_bus *bus)
167{
168 if (ssb_chipco_available(&bus->chipco))
169 return ssb_gpio_chipco_init(bus);
170 else if (ssb_extif_available(&bus->extif))
171 return ssb_gpio_extif_init(bus);
172 else
173 SSB_WARN_ON(1);
174
175 return -1;
176}