diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/cs5535-gpio.c | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 56138893819a..0fdbe94f24a3 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
@@ -19,6 +19,29 @@ | |||
19 | #define DRV_NAME "cs5535-gpio" | 19 | #define DRV_NAME "cs5535-gpio" |
20 | #define GPIO_BAR 1 | 20 | #define GPIO_BAR 1 |
21 | 21 | ||
22 | /* | ||
23 | * Some GPIO pins | ||
24 | * 31-29,23 : reserved (always mask out) | ||
25 | * 28 : Power Button | ||
26 | * 26 : PME# | ||
27 | * 22-16 : LPC | ||
28 | * 14,15 : SMBus | ||
29 | * 9,8 : UART1 | ||
30 | * 7 : PCI INTB | ||
31 | * 3,4 : UART2/DDC | ||
32 | * 2 : IDE_IRQ0 | ||
33 | * 1 : AC_BEEP | ||
34 | * 0 : PCI INTA | ||
35 | * | ||
36 | * If a mask was not specified, allow all except | ||
37 | * reserved and Power Button | ||
38 | */ | ||
39 | #define GPIO_DEFAULT_MASK 0x0F7FFFFF | ||
40 | |||
41 | static ulong mask = GPIO_DEFAULT_MASK; | ||
42 | module_param_named(mask, mask, ulong, 0444); | ||
43 | MODULE_PARM_DESC(mask, "GPIO channel mask."); | ||
44 | |||
22 | static struct cs5535_gpio_chip { | 45 | static struct cs5535_gpio_chip { |
23 | struct gpio_chip chip; | 46 | struct gpio_chip chip; |
24 | resource_size_t base; | 47 | resource_size_t base; |
@@ -102,6 +125,33 @@ EXPORT_SYMBOL_GPL(cs5535_gpio_isset); | |||
102 | * Generic gpio_chip API support. | 125 | * Generic gpio_chip API support. |
103 | */ | 126 | */ |
104 | 127 | ||
128 | static int chip_gpio_request(struct gpio_chip *c, unsigned offset) | ||
129 | { | ||
130 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | ||
131 | unsigned long flags; | ||
132 | |||
133 | spin_lock_irqsave(&chip->lock, flags); | ||
134 | |||
135 | /* check if this pin is available */ | ||
136 | if ((mask & (1 << offset)) == 0) { | ||
137 | dev_info(&chip->pdev->dev, | ||
138 | "pin %u is not available (check mask)\n", offset); | ||
139 | spin_unlock_irqrestore(&chip->lock, flags); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | /* disable output aux 1 & 2 on this pin */ | ||
144 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1); | ||
145 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2); | ||
146 | |||
147 | /* disable input aux 1 on this pin */ | ||
148 | __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1); | ||
149 | |||
150 | spin_unlock_irqrestore(&chip->lock, flags); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
105 | static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) | 155 | static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) |
106 | { | 156 | { |
107 | return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL); | 157 | return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL); |
@@ -145,13 +195,26 @@ static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) | |||
145 | return 0; | 195 | return 0; |
146 | } | 196 | } |
147 | 197 | ||
198 | static char *cs5535_gpio_names[] = { | ||
199 | "GPIO0", "GPIO1", "GPIO2", "GPIO3", | ||
200 | "GPIO4", "GPIO5", "GPIO6", "GPIO7", | ||
201 | "GPIO8", "GPIO9", "GPIO10", "GPIO11", | ||
202 | "GPIO12", "GPIO13", "GPIO14", "GPIO15", | ||
203 | "GPIO16", "GPIO17", "GPIO18", "GPIO19", | ||
204 | "GPIO20", "GPIO21", "GPIO22", NULL, | ||
205 | "GPIO24", "GPIO25", "GPIO26", "GPIO27", | ||
206 | "GPIO28", NULL, NULL, NULL, | ||
207 | }; | ||
208 | |||
148 | static struct cs5535_gpio_chip cs5535_gpio_chip = { | 209 | static struct cs5535_gpio_chip cs5535_gpio_chip = { |
149 | .chip = { | 210 | .chip = { |
150 | .owner = THIS_MODULE, | 211 | .owner = THIS_MODULE, |
151 | .label = DRV_NAME, | 212 | .label = DRV_NAME, |
152 | 213 | ||
153 | .base = 0, | 214 | .base = 0, |
154 | .ngpio = 28, | 215 | .ngpio = 32, |
216 | .names = cs5535_gpio_names, | ||
217 | .request = chip_gpio_request, | ||
155 | 218 | ||
156 | .get = chip_gpio_get, | 219 | .get = chip_gpio_get, |
157 | .set = chip_gpio_set, | 220 | .set = chip_gpio_set, |
@@ -165,6 +228,7 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, | |||
165 | const struct pci_device_id *pci_id) | 228 | const struct pci_device_id *pci_id) |
166 | { | 229 | { |
167 | int err; | 230 | int err; |
231 | ulong mask_orig = mask; | ||
168 | 232 | ||
169 | /* There are two ways to get the GPIO base address; one is by | 233 | /* There are two ways to get the GPIO base address; one is by |
170 | * fetching it from MSR_LBAR_GPIO, the other is by reading the | 234 | * fetching it from MSR_LBAR_GPIO, the other is by reading the |
@@ -193,14 +257,23 @@ static int __init cs5535_gpio_probe(struct pci_dev *pdev, | |||
193 | dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR, | 257 | dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR, |
194 | (unsigned long long) cs5535_gpio_chip.base); | 258 | (unsigned long long) cs5535_gpio_chip.base); |
195 | 259 | ||
260 | /* mask out reserved pins */ | ||
261 | mask &= 0x1F7FFFFF; | ||
262 | |||
263 | /* do not allow pin 28, Power Button, as there's special handling | ||
264 | * in the PMC needed. (note 12, p. 48) */ | ||
265 | mask &= ~(1 << 28); | ||
266 | |||
267 | if (mask_orig != mask) | ||
268 | dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n", | ||
269 | mask_orig, mask); | ||
270 | |||
196 | /* finally, register with the generic GPIO API */ | 271 | /* finally, register with the generic GPIO API */ |
197 | err = gpiochip_add(&cs5535_gpio_chip.chip); | 272 | err = gpiochip_add(&cs5535_gpio_chip.chip); |
198 | if (err) { | 273 | if (err) |
199 | dev_err(&pdev->dev, "failed to register gpio chip\n"); | ||
200 | goto release_region; | 274 | goto release_region; |
201 | } | ||
202 | 275 | ||
203 | printk(KERN_INFO DRV_NAME ": GPIO support successfully loaded.\n"); | 276 | dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n"); |
204 | return 0; | 277 | return 0; |
205 | 278 | ||
206 | release_region: | 279 | release_region: |