diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/sodaville.txt | 48 | ||||
-rw-r--r-- | arch/x86/platform/ce4100/falconfalls.dts | 7 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 14 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mc9s08dz60.c | 161 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-sodaville.c | 302 | ||||
-rw-r--r-- | drivers/gpio/gpio-tps65910.c | 20 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 8 | ||||
-rw-r--r-- | drivers/of/gpio.c | 9 | ||||
-rw-r--r-- | include/linux/mfd/tps65910.h | 8 | ||||
-rw-r--r-- | include/linux/of_gpio.h | 27 |
12 files changed, 599 insertions, 14 deletions
diff --git a/Documentation/devicetree/bindings/gpio/sodaville.txt b/Documentation/devicetree/bindings/gpio/sodaville.txt new file mode 100644 index 000000000000..563eff22b975 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/sodaville.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | GPIO controller on CE4100 / Sodaville SoCs | ||
2 | ========================================== | ||
3 | |||
4 | The bindings for CE4100's GPIO controller match the generic description | ||
5 | which is covered by the gpio.txt file in this folder. | ||
6 | |||
7 | The only additional property is the intel,muxctl property which holds the | ||
8 | value which is written into the MUXCNTL register. | ||
9 | |||
10 | There is no compatible property for now because the driver is probed via | ||
11 | PCI id (vendor 0x8086 device 0x2e67). | ||
12 | |||
13 | The interrupt specifier consists of two cells encoded as follows: | ||
14 | - <1st cell>: The interrupt-number that identifies the interrupt source. | ||
15 | - <2nd cell>: The level-sense information, encoded as follows: | ||
16 | 4 - active high level-sensitive | ||
17 | 8 - active low level-sensitive | ||
18 | |||
19 | Example of the GPIO device and one user: | ||
20 | |||
21 | pcigpio: gpio@b,1 { | ||
22 | /* two cells for GPIO and interrupt */ | ||
23 | #gpio-cells = <2>; | ||
24 | #interrupt-cells = <2>; | ||
25 | compatible = "pci8086,2e67.2", | ||
26 | "pci8086,2e67", | ||
27 | "pciclassff0000", | ||
28 | "pciclassff00"; | ||
29 | |||
30 | reg = <0x15900 0x0 0x0 0x0 0x0>; | ||
31 | /* Interrupt line of the gpio device */ | ||
32 | interrupts = <15 1>; | ||
33 | /* It is an interrupt and GPIO controller itself */ | ||
34 | interrupt-controller; | ||
35 | gpio-controller; | ||
36 | intel,muxctl = <0>; | ||
37 | }; | ||
38 | |||
39 | testuser@20 { | ||
40 | compatible = "example,testuser"; | ||
41 | /* User the 11th GPIO line as an active high triggered | ||
42 | * level interrupt | ||
43 | */ | ||
44 | interrupts = <11 8>; | ||
45 | interrupt-parent = <&pcigpio>; | ||
46 | /* Use this GPIO also with the gpio functions */ | ||
47 | gpios = <&pcigpio 11 0>; | ||
48 | }; | ||
diff --git a/arch/x86/platform/ce4100/falconfalls.dts b/arch/x86/platform/ce4100/falconfalls.dts index e70be38ce039..ce874f872cc6 100644 --- a/arch/x86/platform/ce4100/falconfalls.dts +++ b/arch/x86/platform/ce4100/falconfalls.dts | |||
@@ -208,16 +208,19 @@ | |||
208 | interrupts = <14 1>; | 208 | interrupts = <14 1>; |
209 | }; | 209 | }; |
210 | 210 | ||
211 | gpio@b,1 { | 211 | pcigpio: gpio@b,1 { |
212 | #gpio-cells = <2>; | ||
213 | #interrupt-cells = <2>; | ||
212 | compatible = "pci8086,2e67.2", | 214 | compatible = "pci8086,2e67.2", |
213 | "pci8086,2e67", | 215 | "pci8086,2e67", |
214 | "pciclassff0000", | 216 | "pciclassff0000", |
215 | "pciclassff00"; | 217 | "pciclassff00"; |
216 | 218 | ||
217 | #gpio-cells = <2>; | ||
218 | reg = <0x15900 0x0 0x0 0x0 0x0>; | 219 | reg = <0x15900 0x0 0x0 0x0 0x0>; |
219 | interrupts = <15 1>; | 220 | interrupts = <15 1>; |
221 | interrupt-controller; | ||
220 | gpio-controller; | 222 | gpio-controller; |
223 | intel,muxctl = <0>; | ||
221 | }; | 224 | }; |
222 | 225 | ||
223 | i2c-controller@b,2 { | 226 | i2c-controller@b,2 { |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d0c41188d4e5..dbb1909ca0a2 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -225,6 +225,12 @@ config GPIO_MAX732X_IRQ | |||
225 | Say yes here to enable the max732x to be used as an interrupt | 225 | Say yes here to enable the max732x to be used as an interrupt |
226 | controller. It requires the driver to be built in the kernel. | 226 | controller. It requires the driver to be built in the kernel. |
227 | 227 | ||
228 | config GPIO_MC9S08DZ60 | ||
229 | bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions" | ||
230 | depends on I2C && MACH_MX35_3DS | ||
231 | help | ||
232 | Select this to enable the MC9S08DZ60 GPIO driver | ||
233 | |||
228 | config GPIO_PCA953X | 234 | config GPIO_PCA953X |
229 | tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" | 235 | tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" |
230 | depends on I2C | 236 | depends on I2C |
@@ -411,6 +417,14 @@ config GPIO_ML_IOH | |||
411 | Hub) which is for IVI(In-Vehicle Infotainment) use. | 417 | Hub) which is for IVI(In-Vehicle Infotainment) use. |
412 | This driver can access the IOH's GPIO device. | 418 | This driver can access the IOH's GPIO device. |
413 | 419 | ||
420 | config GPIO_SODAVILLE | ||
421 | bool "Intel Sodaville GPIO support" | ||
422 | depends on X86 && PCI && OF | ||
423 | select GPIO_GENERIC | ||
424 | select GENERIC_IRQ_CHIP | ||
425 | help | ||
426 | Say Y here to support Intel Sodaville GPIO. | ||
427 | |||
414 | config GPIO_TIMBERDALE | 428 | config GPIO_TIMBERDALE |
415 | bool "Support for timberdale GPIO IP" | 429 | bool "Support for timberdale GPIO IP" |
416 | depends on MFD_TIMBERDALE && HAS_IOMEM | 430 | depends on MFD_TIMBERDALE && HAS_IOMEM |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fa10df604c01..593bdcd1976e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o | |||
26 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o | 26 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o |
27 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o | 27 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o |
28 | obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o | 28 | obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o |
29 | obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o | ||
29 | obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o | 30 | obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o |
30 | obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o | 31 | obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o |
31 | obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o | 32 | obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o |
@@ -45,6 +46,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o | |||
45 | obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o | 46 | obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o |
46 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o | 47 | obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o |
47 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o | 48 | obj-$(CONFIG_GPIO_SCH) += gpio-sch.o |
49 | obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o | ||
48 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o | 50 | obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o |
49 | obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o | 51 | obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o |
50 | obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o | 52 | obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o |
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c new file mode 100644 index 000000000000..2738cc44d636 --- /dev/null +++ b/drivers/gpio/gpio-mc9s08dz60.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * Author: Wu Guoxing <b39297@freescale.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/gpio.h> | ||
22 | |||
23 | #define GPIO_GROUP_NUM 2 | ||
24 | #define GPIO_NUM_PER_GROUP 8 | ||
25 | #define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP) | ||
26 | |||
27 | struct mc9s08dz60 { | ||
28 | struct i2c_client *client; | ||
29 | struct gpio_chip chip; | ||
30 | }; | ||
31 | |||
32 | static inline struct mc9s08dz60 *to_mc9s08dz60(struct gpio_chip *gc) | ||
33 | { | ||
34 | return container_of(gc, struct mc9s08dz60, chip); | ||
35 | } | ||
36 | |||
37 | |||
38 | static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit) | ||
39 | { | ||
40 | *reg = 0x20 + offset / GPIO_NUM_PER_GROUP; | ||
41 | *bit = offset % GPIO_NUM_PER_GROUP; | ||
42 | } | ||
43 | |||
44 | static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset) | ||
45 | { | ||
46 | u8 reg, bit; | ||
47 | s32 value; | ||
48 | struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); | ||
49 | |||
50 | mc9s_gpio_to_reg_and_bit(offset, ®, &bit); | ||
51 | value = i2c_smbus_read_byte_data(mc9s->client, reg); | ||
52 | |||
53 | return (value >= 0) ? (value >> bit) & 0x1 : 0; | ||
54 | } | ||
55 | |||
56 | static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val) | ||
57 | { | ||
58 | u8 reg, bit; | ||
59 | s32 value; | ||
60 | |||
61 | mc9s_gpio_to_reg_and_bit(offset, ®, &bit); | ||
62 | value = i2c_smbus_read_byte_data(mc9s->client, reg); | ||
63 | if (value >= 0) { | ||
64 | if (val) | ||
65 | value |= 1 << bit; | ||
66 | else | ||
67 | value &= ~(1 << bit); | ||
68 | |||
69 | return i2c_smbus_write_byte_data(mc9s->client, reg, value); | ||
70 | } else | ||
71 | return value; | ||
72 | |||
73 | } | ||
74 | |||
75 | |||
76 | static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val) | ||
77 | { | ||
78 | struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); | ||
79 | |||
80 | mc9s08dz60_set(mc9s, offset, val); | ||
81 | } | ||
82 | |||
83 | static int mc9s08dz60_direction_output(struct gpio_chip *gc, | ||
84 | unsigned offset, int val) | ||
85 | { | ||
86 | struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc); | ||
87 | |||
88 | return mc9s08dz60_set(mc9s, offset, val); | ||
89 | } | ||
90 | |||
91 | static int mc9s08dz60_probe(struct i2c_client *client, | ||
92 | const struct i2c_device_id *id) | ||
93 | { | ||
94 | int ret = 0; | ||
95 | struct mc9s08dz60 *mc9s; | ||
96 | |||
97 | mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL); | ||
98 | if (!mc9s) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | mc9s->chip.label = client->name; | ||
102 | mc9s->chip.base = -1; | ||
103 | mc9s->chip.dev = &client->dev; | ||
104 | mc9s->chip.owner = THIS_MODULE; | ||
105 | mc9s->chip.ngpio = GPIO_NUM; | ||
106 | mc9s->chip.can_sleep = 1; | ||
107 | mc9s->chip.get = mc9s08dz60_get_value; | ||
108 | mc9s->chip.set = mc9s08dz60_set_value; | ||
109 | mc9s->chip.direction_output = mc9s08dz60_direction_output; | ||
110 | mc9s->client = client; | ||
111 | i2c_set_clientdata(client, mc9s); | ||
112 | |||
113 | ret = gpiochip_add(&mc9s->chip); | ||
114 | if (ret) | ||
115 | goto error; | ||
116 | |||
117 | return 0; | ||
118 | |||
119 | error: | ||
120 | kfree(mc9s); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int mc9s08dz60_remove(struct i2c_client *client) | ||
125 | { | ||
126 | struct mc9s08dz60 *mc9s; | ||
127 | int ret; | ||
128 | |||
129 | mc9s = i2c_get_clientdata(client); | ||
130 | |||
131 | ret = gpiochip_remove(&mc9s->chip); | ||
132 | if (!ret) | ||
133 | kfree(mc9s); | ||
134 | |||
135 | return ret; | ||
136 | |||
137 | } | ||
138 | |||
139 | static const struct i2c_device_id mc9s08dz60_id[] = { | ||
140 | {"mc9s08dz60", 0}, | ||
141 | {}, | ||
142 | }; | ||
143 | |||
144 | MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id); | ||
145 | |||
146 | static struct i2c_driver mc9s08dz60_i2c_driver = { | ||
147 | .driver = { | ||
148 | .owner = THIS_MODULE, | ||
149 | .name = "mc9s08dz60", | ||
150 | }, | ||
151 | .probe = mc9s08dz60_probe, | ||
152 | .remove = mc9s08dz60_remove, | ||
153 | .id_table = mc9s08dz60_id, | ||
154 | }; | ||
155 | |||
156 | module_i2c_driver(mc9s08dz60_i2c_driver); | ||
157 | |||
158 | MODULE_AUTHOR("Freescale Semiconductor, Inc. " | ||
159 | "Wu Guoxing <b39297@freescale.com>"); | ||
160 | MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board"); | ||
161 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 77c9cc70fa77..b4b5da4fd2cc 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -352,7 +352,12 @@ static int pl061_resume(struct device *dev) | |||
352 | return 0; | 352 | return 0; |
353 | } | 353 | } |
354 | 354 | ||
355 | static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume); | 355 | static const struct dev_pm_ops pl061_dev_pm_ops = { |
356 | .suspend = pl061_suspend, | ||
357 | .resume = pl061_resume, | ||
358 | .freeze = pl061_suspend, | ||
359 | .restore = pl061_resume, | ||
360 | }; | ||
356 | #endif | 361 | #endif |
357 | 362 | ||
358 | static struct amba_id pl061_ids[] = { | 363 | static struct amba_id pl061_ids[] = { |
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c new file mode 100644 index 000000000000..9ba15d31d242 --- /dev/null +++ b/drivers/gpio/gpio-sodaville.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * GPIO interface for Intel Sodaville SoCs. | ||
3 | * | ||
4 | * Copyright (c) 2010, 2011 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License 2 as published | ||
8 | * by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/errno.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/basic_mmio_gpio.h> | ||
24 | |||
25 | #define DRV_NAME "sdv_gpio" | ||
26 | #define SDV_NUM_PUB_GPIOS 12 | ||
27 | #define PCI_DEVICE_ID_SDV_GPIO 0x2e67 | ||
28 | #define GPIO_BAR 0 | ||
29 | |||
30 | #define GPOUTR 0x00 | ||
31 | #define GPOER 0x04 | ||
32 | #define GPINR 0x08 | ||
33 | |||
34 | #define GPSTR 0x0c | ||
35 | #define GPIT1R0 0x10 | ||
36 | #define GPIO_INT 0x14 | ||
37 | #define GPIT1R1 0x18 | ||
38 | |||
39 | #define GPMUXCTL 0x1c | ||
40 | |||
41 | struct sdv_gpio_chip_data { | ||
42 | int irq_base; | ||
43 | void __iomem *gpio_pub_base; | ||
44 | struct irq_domain id; | ||
45 | struct irq_chip_generic *gc; | ||
46 | struct bgpio_chip bgpio; | ||
47 | }; | ||
48 | |||
49 | static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type) | ||
50 | { | ||
51 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
52 | struct sdv_gpio_chip_data *sd = gc->private; | ||
53 | void __iomem *type_reg; | ||
54 | u32 irq_offs = d->irq - sd->irq_base; | ||
55 | u32 reg; | ||
56 | |||
57 | if (irq_offs < 8) | ||
58 | type_reg = sd->gpio_pub_base + GPIT1R0; | ||
59 | else | ||
60 | type_reg = sd->gpio_pub_base + GPIT1R1; | ||
61 | |||
62 | reg = readl(type_reg); | ||
63 | |||
64 | switch (type) { | ||
65 | case IRQ_TYPE_LEVEL_HIGH: | ||
66 | reg &= ~BIT(4 * (irq_offs % 8)); | ||
67 | break; | ||
68 | |||
69 | case IRQ_TYPE_LEVEL_LOW: | ||
70 | reg |= BIT(4 * (irq_offs % 8)); | ||
71 | break; | ||
72 | |||
73 | default: | ||
74 | return -EINVAL; | ||
75 | } | ||
76 | |||
77 | writel(reg, type_reg); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data) | ||
82 | { | ||
83 | struct sdv_gpio_chip_data *sd = data; | ||
84 | u32 irq_stat = readl(sd->gpio_pub_base + GPSTR); | ||
85 | |||
86 | irq_stat &= readl(sd->gpio_pub_base + GPIO_INT); | ||
87 | if (!irq_stat) | ||
88 | return IRQ_NONE; | ||
89 | |||
90 | while (irq_stat) { | ||
91 | u32 irq_bit = __fls(irq_stat); | ||
92 | |||
93 | irq_stat &= ~BIT(irq_bit); | ||
94 | generic_handle_irq(sd->irq_base + irq_bit); | ||
95 | } | ||
96 | |||
97 | return IRQ_HANDLED; | ||
98 | } | ||
99 | |||
100 | static int sdv_xlate(struct irq_domain *h, struct device_node *node, | ||
101 | const u32 *intspec, u32 intsize, irq_hw_number_t *out_hwirq, | ||
102 | u32 *out_type) | ||
103 | { | ||
104 | u32 line, type; | ||
105 | |||
106 | if (node != h->of_node) | ||
107 | return -EINVAL; | ||
108 | |||
109 | if (intsize < 2) | ||
110 | return -EINVAL; | ||
111 | |||
112 | line = *intspec; | ||
113 | *out_hwirq = line; | ||
114 | |||
115 | intspec++; | ||
116 | type = *intspec; | ||
117 | |||
118 | switch (type) { | ||
119 | case IRQ_TYPE_LEVEL_LOW: | ||
120 | case IRQ_TYPE_LEVEL_HIGH: | ||
121 | *out_type = type; | ||
122 | break; | ||
123 | default: | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static struct irq_domain_ops irq_domain_sdv_ops = { | ||
130 | .dt_translate = sdv_xlate, | ||
131 | }; | ||
132 | |||
133 | static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, | ||
134 | struct pci_dev *pdev) | ||
135 | { | ||
136 | struct irq_chip_type *ct; | ||
137 | int ret; | ||
138 | |||
139 | sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1); | ||
140 | if (sd->irq_base < 0) | ||
141 | return sd->irq_base; | ||
142 | |||
143 | /* mask + ACK all interrupt sources */ | ||
144 | writel(0, sd->gpio_pub_base + GPIO_INT); | ||
145 | writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR); | ||
146 | |||
147 | ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED, | ||
148 | "sdv_gpio", sd); | ||
149 | if (ret) | ||
150 | goto out_free_desc; | ||
151 | |||
152 | sd->id.irq_base = sd->irq_base; | ||
153 | sd->id.of_node = of_node_get(pdev->dev.of_node); | ||
154 | sd->id.ops = &irq_domain_sdv_ops; | ||
155 | |||
156 | /* | ||
157 | * This gpio irq controller latches level irqs. Testing shows that if | ||
158 | * we unmask & ACK the IRQ before the source of the interrupt is gone | ||
159 | * then the interrupt is active again. | ||
160 | */ | ||
161 | sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base, | ||
162 | sd->gpio_pub_base, handle_fasteoi_irq); | ||
163 | if (!sd->gc) { | ||
164 | ret = -ENOMEM; | ||
165 | goto out_free_irq; | ||
166 | } | ||
167 | |||
168 | sd->gc->private = sd; | ||
169 | ct = sd->gc->chip_types; | ||
170 | ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; | ||
171 | ct->regs.eoi = GPSTR; | ||
172 | ct->regs.mask = GPIO_INT; | ||
173 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
174 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
175 | ct->chip.irq_eoi = irq_gc_eoi; | ||
176 | ct->chip.irq_set_type = sdv_gpio_pub_set_type; | ||
177 | |||
178 | irq_setup_generic_chip(sd->gc, IRQ_MSK(SDV_NUM_PUB_GPIOS), | ||
179 | IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, | ||
180 | IRQ_LEVEL | IRQ_NOPROBE); | ||
181 | |||
182 | irq_domain_add(&sd->id); | ||
183 | return 0; | ||
184 | out_free_irq: | ||
185 | free_irq(pdev->irq, sd); | ||
186 | out_free_desc: | ||
187 | irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int __devinit sdv_gpio_probe(struct pci_dev *pdev, | ||
192 | const struct pci_device_id *pci_id) | ||
193 | { | ||
194 | struct sdv_gpio_chip_data *sd; | ||
195 | unsigned long addr; | ||
196 | const void *prop; | ||
197 | int len; | ||
198 | int ret; | ||
199 | u32 mux_val; | ||
200 | |||
201 | sd = kzalloc(sizeof(struct sdv_gpio_chip_data), GFP_KERNEL); | ||
202 | if (!sd) | ||
203 | return -ENOMEM; | ||
204 | ret = pci_enable_device(pdev); | ||
205 | if (ret) { | ||
206 | dev_err(&pdev->dev, "can't enable device.\n"); | ||
207 | goto done; | ||
208 | } | ||
209 | |||
210 | ret = pci_request_region(pdev, GPIO_BAR, DRV_NAME); | ||
211 | if (ret) { | ||
212 | dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR); | ||
213 | goto disable_pci; | ||
214 | } | ||
215 | |||
216 | addr = pci_resource_start(pdev, GPIO_BAR); | ||
217 | if (!addr) | ||
218 | goto release_reg; | ||
219 | sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR)); | ||
220 | |||
221 | prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len); | ||
222 | if (prop && len == 4) { | ||
223 | mux_val = of_read_number(prop, 1); | ||
224 | writel(mux_val, sd->gpio_pub_base + GPMUXCTL); | ||
225 | } | ||
226 | |||
227 | ret = bgpio_init(&sd->bgpio, &pdev->dev, 4, | ||
228 | sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR, | ||
229 | NULL, sd->gpio_pub_base + GPOER, NULL, false); | ||
230 | if (ret) | ||
231 | goto unmap; | ||
232 | sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS; | ||
233 | |||
234 | ret = gpiochip_add(&sd->bgpio.gc); | ||
235 | if (ret < 0) { | ||
236 | dev_err(&pdev->dev, "gpiochip_add() failed.\n"); | ||
237 | goto unmap; | ||
238 | } | ||
239 | |||
240 | ret = sdv_register_irqsupport(sd, pdev); | ||
241 | if (ret) | ||
242 | goto unmap; | ||
243 | |||
244 | pci_set_drvdata(pdev, sd); | ||
245 | dev_info(&pdev->dev, "Sodaville GPIO driver registered.\n"); | ||
246 | return 0; | ||
247 | |||
248 | unmap: | ||
249 | iounmap(sd->gpio_pub_base); | ||
250 | release_reg: | ||
251 | pci_release_region(pdev, GPIO_BAR); | ||
252 | disable_pci: | ||
253 | pci_disable_device(pdev); | ||
254 | done: | ||
255 | kfree(sd); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static void sdv_gpio_remove(struct pci_dev *pdev) | ||
260 | { | ||
261 | struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev); | ||
262 | |||
263 | irq_domain_del(&sd->id); | ||
264 | free_irq(pdev->irq, sd); | ||
265 | irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); | ||
266 | |||
267 | if (gpiochip_remove(&sd->bgpio.gc)) | ||
268 | dev_err(&pdev->dev, "gpiochip_remove() failed.\n"); | ||
269 | |||
270 | pci_release_region(pdev, GPIO_BAR); | ||
271 | iounmap(sd->gpio_pub_base); | ||
272 | pci_disable_device(pdev); | ||
273 | kfree(sd); | ||
274 | } | ||
275 | |||
276 | static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = { | ||
277 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) }, | ||
278 | { 0, }, | ||
279 | }; | ||
280 | |||
281 | static struct pci_driver sdv_gpio_driver = { | ||
282 | .name = DRV_NAME, | ||
283 | .id_table = sdv_gpio_pci_ids, | ||
284 | .probe = sdv_gpio_probe, | ||
285 | .remove = sdv_gpio_remove, | ||
286 | }; | ||
287 | |||
288 | static int __init sdv_gpio_init(void) | ||
289 | { | ||
290 | return pci_register_driver(&sdv_gpio_driver); | ||
291 | } | ||
292 | module_init(sdv_gpio_init); | ||
293 | |||
294 | static void __exit sdv_gpio_exit(void) | ||
295 | { | ||
296 | pci_unregister_driver(&sdv_gpio_driver); | ||
297 | } | ||
298 | module_exit(sdv_gpio_exit); | ||
299 | |||
300 | MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>"); | ||
301 | MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs"); | ||
302 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 91f45b965d1e..7eef648a3351 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c | |||
@@ -69,6 +69,7 @@ static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset) | |||
69 | void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) | 69 | void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) |
70 | { | 70 | { |
71 | int ret; | 71 | int ret; |
72 | struct tps65910_board *board_data; | ||
72 | 73 | ||
73 | if (!gpio_base) | 74 | if (!gpio_base) |
74 | return; | 75 | return; |
@@ -80,10 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) | |||
80 | 81 | ||
81 | switch(tps65910_chip_id(tps65910)) { | 82 | switch(tps65910_chip_id(tps65910)) { |
82 | case TPS65910: | 83 | case TPS65910: |
83 | tps65910->gpio.ngpio = 6; | 84 | tps65910->gpio.ngpio = TPS65910_NUM_GPIO; |
84 | break; | 85 | break; |
85 | case TPS65911: | 86 | case TPS65911: |
86 | tps65910->gpio.ngpio = 9; | 87 | tps65910->gpio.ngpio = TPS65911_NUM_GPIO; |
87 | break; | 88 | break; |
88 | default: | 89 | default: |
89 | return; | 90 | return; |
@@ -95,6 +96,21 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base) | |||
95 | tps65910->gpio.set = tps65910_gpio_set; | 96 | tps65910->gpio.set = tps65910_gpio_set; |
96 | tps65910->gpio.get = tps65910_gpio_get; | 97 | tps65910->gpio.get = tps65910_gpio_get; |
97 | 98 | ||
99 | /* Configure sleep control for gpios */ | ||
100 | board_data = dev_get_platdata(tps65910->dev); | ||
101 | if (board_data) { | ||
102 | int i; | ||
103 | for (i = 0; i < tps65910->gpio.ngpio; ++i) { | ||
104 | if (board_data->en_gpio_sleep[i]) { | ||
105 | ret = tps65910_set_bits(tps65910, | ||
106 | TPS65910_GPIO0 + i, GPIO_SLEEP_MASK); | ||
107 | if (ret < 0) | ||
108 | dev_warn(tps65910->dev, | ||
109 | "GPIO Sleep setting failed\n"); | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
98 | ret = gpiochip_add(&tps65910->gpio); | 114 | ret = gpiochip_add(&tps65910->gpio); |
99 | 115 | ||
100 | if (ret) | 116 | if (ret) |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 17fdf4b6af93..d77354068b90 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -873,6 +873,7 @@ void gpio_unexport(unsigned gpio) | |||
873 | { | 873 | { |
874 | struct gpio_desc *desc; | 874 | struct gpio_desc *desc; |
875 | int status = 0; | 875 | int status = 0; |
876 | struct device *dev = NULL; | ||
876 | 877 | ||
877 | if (!gpio_is_valid(gpio)) { | 878 | if (!gpio_is_valid(gpio)) { |
878 | status = -EINVAL; | 879 | status = -EINVAL; |
@@ -884,19 +885,20 @@ void gpio_unexport(unsigned gpio) | |||
884 | desc = &gpio_desc[gpio]; | 885 | desc = &gpio_desc[gpio]; |
885 | 886 | ||
886 | if (test_bit(FLAG_EXPORT, &desc->flags)) { | 887 | if (test_bit(FLAG_EXPORT, &desc->flags)) { |
887 | struct device *dev = NULL; | ||
888 | 888 | ||
889 | dev = class_find_device(&gpio_class, NULL, desc, match_export); | 889 | dev = class_find_device(&gpio_class, NULL, desc, match_export); |
890 | if (dev) { | 890 | if (dev) { |
891 | gpio_setup_irq(desc, dev, 0); | 891 | gpio_setup_irq(desc, dev, 0); |
892 | clear_bit(FLAG_EXPORT, &desc->flags); | 892 | clear_bit(FLAG_EXPORT, &desc->flags); |
893 | put_device(dev); | ||
894 | device_unregister(dev); | ||
895 | } else | 893 | } else |
896 | status = -ENODEV; | 894 | status = -ENODEV; |
897 | } | 895 | } |
898 | 896 | ||
899 | mutex_unlock(&sysfs_lock); | 897 | mutex_unlock(&sysfs_lock); |
898 | if (dev) { | ||
899 | device_unregister(dev); | ||
900 | put_device(dev); | ||
901 | } | ||
900 | done: | 902 | done: |
901 | if (status) | 903 | if (status) |
902 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); | 904 | pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); |
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index 7e62d15d60f6..e034b38590a8 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c | |||
@@ -78,8 +78,9 @@ err0: | |||
78 | EXPORT_SYMBOL(of_get_named_gpio_flags); | 78 | EXPORT_SYMBOL(of_get_named_gpio_flags); |
79 | 79 | ||
80 | /** | 80 | /** |
81 | * of_gpio_count - Count GPIOs for a device | 81 | * of_gpio_named_count - Count GPIOs for a device |
82 | * @np: device node to count GPIOs for | 82 | * @np: device node to count GPIOs for |
83 | * @propname: property name containing gpio specifier(s) | ||
83 | * | 84 | * |
84 | * The function returns the count of GPIOs specified for a node. | 85 | * The function returns the count of GPIOs specified for a node. |
85 | * | 86 | * |
@@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags); | |||
93 | * defines four GPIOs (so this function will return 4), two of which | 94 | * defines four GPIOs (so this function will return 4), two of which |
94 | * are not specified. | 95 | * are not specified. |
95 | */ | 96 | */ |
96 | unsigned int of_gpio_count(struct device_node *np) | 97 | unsigned int of_gpio_named_count(struct device_node *np, const char* propname) |
97 | { | 98 | { |
98 | unsigned int cnt = 0; | 99 | unsigned int cnt = 0; |
99 | 100 | ||
100 | do { | 101 | do { |
101 | int ret; | 102 | int ret; |
102 | 103 | ||
103 | ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells", | 104 | ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", |
104 | cnt, NULL); | 105 | cnt, NULL); |
105 | /* A hole in the gpios = <> counts anyway. */ | 106 | /* A hole in the gpios = <> counts anyway. */ |
106 | if (ret < 0 && ret != -EEXIST) | 107 | if (ret < 0 && ret != -EEXIST) |
@@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np) | |||
109 | 110 | ||
110 | return cnt; | 111 | return cnt; |
111 | } | 112 | } |
112 | EXPORT_SYMBOL(of_gpio_count); | 113 | EXPORT_SYMBOL(of_gpio_named_count); |
113 | 114 | ||
114 | /** | 115 | /** |
115 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags | 116 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags |
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index d0cb12eba402..9071902bd222 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h | |||
@@ -657,6 +657,8 @@ | |||
657 | 657 | ||
658 | 658 | ||
659 | /*Register GPIO (0x80) register.RegisterDescription */ | 659 | /*Register GPIO (0x80) register.RegisterDescription */ |
660 | #define GPIO_SLEEP_MASK 0x80 | ||
661 | #define GPIO_SLEEP_SHIFT 7 | ||
660 | #define GPIO_DEB_MASK 0x10 | 662 | #define GPIO_DEB_MASK 0x10 |
661 | #define GPIO_DEB_SHIFT 4 | 663 | #define GPIO_DEB_SHIFT 4 |
662 | #define GPIO_PUEN_MASK 0x08 | 664 | #define GPIO_PUEN_MASK 0x08 |
@@ -740,6 +742,11 @@ | |||
740 | #define TPS65910_GPIO_STS BIT(1) | 742 | #define TPS65910_GPIO_STS BIT(1) |
741 | #define TPS65910_GPIO_SET BIT(0) | 743 | #define TPS65910_GPIO_SET BIT(0) |
742 | 744 | ||
745 | /* Max number of TPS65910/11 GPIOs */ | ||
746 | #define TPS65910_NUM_GPIO 6 | ||
747 | #define TPS65911_NUM_GPIO 9 | ||
748 | #define TPS6591X_MAX_NUM_GPIO 9 | ||
749 | |||
743 | /* Regulator Index Definitions */ | 750 | /* Regulator Index Definitions */ |
744 | #define TPS65910_REG_VRTC 0 | 751 | #define TPS65910_REG_VRTC 0 |
745 | #define TPS65910_REG_VIO 1 | 752 | #define TPS65910_REG_VIO 1 |
@@ -779,6 +786,7 @@ struct tps65910_board { | |||
779 | int irq_base; | 786 | int irq_base; |
780 | int vmbch_threshold; | 787 | int vmbch_threshold; |
781 | int vmbch2_threshold; | 788 | int vmbch2_threshold; |
789 | bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; | ||
782 | struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; | 790 | struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; |
783 | }; | 791 | }; |
784 | 792 | ||
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index b254052a49d7..81733d12cbea 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h | |||
@@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) | |||
50 | extern int of_get_named_gpio_flags(struct device_node *np, | 50 | extern int of_get_named_gpio_flags(struct device_node *np, |
51 | const char *list_name, int index, enum of_gpio_flags *flags); | 51 | const char *list_name, int index, enum of_gpio_flags *flags); |
52 | 52 | ||
53 | extern unsigned int of_gpio_count(struct device_node *np); | 53 | extern unsigned int of_gpio_named_count(struct device_node *np, |
54 | const char* propname); | ||
54 | 55 | ||
55 | extern int of_mm_gpiochip_add(struct device_node *np, | 56 | extern int of_mm_gpiochip_add(struct device_node *np, |
56 | struct of_mm_gpio_chip *mm_gc); | 57 | struct of_mm_gpio_chip *mm_gc); |
@@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np, | |||
71 | return -ENOSYS; | 72 | return -ENOSYS; |
72 | } | 73 | } |
73 | 74 | ||
74 | static inline unsigned int of_gpio_count(struct device_node *np) | 75 | static inline unsigned int of_gpio_named_count(struct device_node *np, |
76 | const char* propname) | ||
75 | { | 77 | { |
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
@@ -89,6 +91,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { } | |||
89 | #endif /* CONFIG_OF_GPIO */ | 91 | #endif /* CONFIG_OF_GPIO */ |
90 | 92 | ||
91 | /** | 93 | /** |
94 | * of_gpio_count - Count GPIOs for a device | ||
95 | * @np: device node to count GPIOs for | ||
96 | * | ||
97 | * The function returns the count of GPIOs specified for a node. | ||
98 | * | ||
99 | * Note that the empty GPIO specifiers counts too. For example, | ||
100 | * | ||
101 | * gpios = <0 | ||
102 | * &pio1 1 2 | ||
103 | * 0 | ||
104 | * &pio2 3 4>; | ||
105 | * | ||
106 | * defines four GPIOs (so this function will return 4), two of which | ||
107 | * are not specified. | ||
108 | */ | ||
109 | static inline unsigned int of_gpio_count(struct device_node *np) | ||
110 | { | ||
111 | return of_gpio_named_count(np, "gpios"); | ||
112 | } | ||
113 | |||
114 | /** | ||
92 | * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API | 115 | * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API |
93 | * @np: device node to get GPIO from | 116 | * @np: device node to get GPIO from |
94 | * @index: index of the GPIO | 117 | * @index: index of the GPIO |