diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-29 10:27:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-29 10:27:45 -0400 |
commit | 41684f67af75b04152a1714e1a5375dfb00ee3da (patch) | |
tree | 3b0f51dd8103a4fd40ebb6cefeece7579e348cde | |
parent | ec7ae517537ae5c7b0b2cd7f562dfa3e7a05b954 (diff) | |
parent | d92ef29a6fa971d9e314e412cd9c09757906411a (diff) |
Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6
* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6:
h8300: Move gpio.h to gpio-internal.h
gpio: pl061: add DT binding support
gpio: fix build error in include/asm-generic/gpio.h
gpiolib: Ensure struct gpio is always defined
irq: Add EXPORT_SYMBOL_GPL to function of irq generic-chip
gpio-ml-ioh: Use NUMA_NO_NODE not GFP_KERNEL
gpio-pch: Use NUMA_NO_NODE not GFP_KERNEL
gpio: langwell: ensure alternate function is cleared
gpio-pch: Support interrupt function
gpio-pch: Save register value in suspend()
gpio-pch: modify gpio_nums and mask
gpio-pch: support ML7223 IOH n-Bus
gpio-pch: add spinlock in suspend/resume processing
gpio-pch: Delete invalid "restore" code in suspend()
gpio-ml-ioh: Fix suspend/resume issue
gpio-ml-ioh: Support interrupt function
gpio-ml-ioh: Delete unnecessary code
gpio/mxc: add chained_irq_enter/exit() to mx3_gpio_irq_handler()
gpio/nomadik: use genirq core to track enablement
gpio/nomadik: disable clocks when unused
-rw-r--r-- | arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | 3 | ||||
-rw-r--r-- | arch/h8300/include/asm/gpio-internal.h (renamed from arch/h8300/include/asm/gpio.h) | 0 | ||||
-rw-r--r-- | arch/h8300/platform/h8300h/irq.c | 2 | ||||
-rw-r--r-- | arch/h8300/platform/h8s/irq.c | 2 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-langwell.c | 27 | ||||
-rw-r--r-- | drivers/gpio/gpio-ml-ioh.c | 254 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpio-nomadik.c | 127 | ||||
-rw-r--r-- | drivers/gpio/gpio-pch.c | 250 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 31 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 17 | ||||
-rw-r--r-- | include/linux/amba/pl061.h | 3 | ||||
-rw-r--r-- | include/linux/gpio.h | 22 | ||||
-rw-r--r-- | kernel/irq/generic-chip.c | 4 |
15 files changed, 683 insertions, 67 deletions
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h index 3ba4d8f8073b..9605bf227df9 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h +++ b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h | |||
@@ -67,6 +67,9 @@ extern int nmk_gpio_get_mode(int gpio); | |||
67 | extern void nmk_gpio_wakeups_suspend(void); | 67 | extern void nmk_gpio_wakeups_suspend(void); |
68 | extern void nmk_gpio_wakeups_resume(void); | 68 | extern void nmk_gpio_wakeups_resume(void); |
69 | 69 | ||
70 | extern void nmk_gpio_clocks_enable(void); | ||
71 | extern void nmk_gpio_clocks_disable(void); | ||
72 | |||
70 | extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); | 73 | extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up); |
71 | 74 | ||
72 | /* | 75 | /* |
diff --git a/arch/h8300/include/asm/gpio.h b/arch/h8300/include/asm/gpio-internal.h index a714f0c0efbc..a714f0c0efbc 100644 --- a/arch/h8300/include/asm/gpio.h +++ b/arch/h8300/include/asm/gpio-internal.h | |||
diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c index e977345105d7..bc4f51bceef5 100644 --- a/arch/h8300/platform/h8300h/irq.c +++ b/arch/h8300/platform/h8300h/irq.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <asm/traps.h> | 11 | #include <asm/traps.h> |
12 | #include <asm/irq.h> | 12 | #include <asm/irq.h> |
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/gpio.h> | 14 | #include <asm/gpio-internal.h> |
15 | #include <asm/regs306x.h> | 15 | #include <asm/regs306x.h> |
16 | 16 | ||
17 | const int __initdata h8300_saved_vectors[] = { | 17 | const int __initdata h8300_saved_vectors[] = { |
diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c index 8182f041f829..7b5f29febc07 100644 --- a/arch/h8300/platform/h8s/irq.c +++ b/arch/h8300/platform/h8s/irq.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <asm/traps.h> | 14 | #include <asm/traps.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/gpio.h> | 17 | #include <asm/gpio-internal.h> |
18 | #include <asm/regs267x.h> | 18 | #include <asm/regs267x.h> |
19 | 19 | ||
20 | /* saved vector list */ | 20 | /* saved vector list */ |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 4caa3d37bbde..cb0bd078efc0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -397,6 +397,7 @@ config GPIO_LANGWELL | |||
397 | config GPIO_PCH | 397 | config GPIO_PCH |
398 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO" | 398 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO" |
399 | depends on PCI && X86 | 399 | depends on PCI && X86 |
400 | select GENERIC_IRQ_CHIP | ||
400 | help | 401 | help |
401 | This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff | 402 | This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff |
402 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 403 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
@@ -411,6 +412,7 @@ config GPIO_PCH | |||
411 | config GPIO_ML_IOH | 412 | config GPIO_ML_IOH |
412 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" | 413 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" |
413 | depends on PCI | 414 | depends on PCI |
415 | select GENERIC_IRQ_CHIP | ||
414 | help | 416 | help |
415 | ML7213 is companion chip for Intel Atom E6xx series. | 417 | ML7213 is companion chip for Intel Atom E6xx series. |
416 | This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output | 418 | This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output |
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index d2eb57c60e0e..00692e89ef87 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c | |||
@@ -59,6 +59,7 @@ enum GPIO_REG { | |||
59 | GRER, /* rising edge detect */ | 59 | GRER, /* rising edge detect */ |
60 | GFER, /* falling edge detect */ | 60 | GFER, /* falling edge detect */ |
61 | GEDR, /* edge detect result */ | 61 | GEDR, /* edge detect result */ |
62 | GAFR, /* alt function */ | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | struct lnw_gpio { | 65 | struct lnw_gpio { |
@@ -81,6 +82,31 @@ static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, | |||
81 | return ptr; | 82 | return ptr; |
82 | } | 83 | } |
83 | 84 | ||
85 | static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset, | ||
86 | enum GPIO_REG reg_type) | ||
87 | { | ||
88 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
89 | unsigned nreg = chip->ngpio / 32; | ||
90 | u8 reg = offset / 16; | ||
91 | void __iomem *ptr; | ||
92 | |||
93 | ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); | ||
94 | return ptr; | ||
95 | } | ||
96 | |||
97 | static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
98 | { | ||
99 | void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR); | ||
100 | u32 value = readl(gafr); | ||
101 | int shift = (offset % 16) << 1, af = (value >> shift) & 3; | ||
102 | |||
103 | if (af) { | ||
104 | value &= ~(3 << shift); | ||
105 | writel(value, gafr); | ||
106 | } | ||
107 | return 0; | ||
108 | } | ||
109 | |||
84 | static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) | 110 | static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) |
85 | { | 111 | { |
86 | void __iomem *gplr = gpio_reg(chip, offset, GPLR); | 112 | void __iomem *gplr = gpio_reg(chip, offset, GPLR); |
@@ -321,6 +347,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
321 | lnw->reg_base = base; | 347 | lnw->reg_base = base; |
322 | lnw->irq_base = irq_base; | 348 | lnw->irq_base = irq_base; |
323 | lnw->chip.label = dev_name(&pdev->dev); | 349 | lnw->chip.label = dev_name(&pdev->dev); |
350 | lnw->chip.request = lnw_gpio_request; | ||
324 | lnw->chip.direction_input = lnw_gpio_direction_input; | 351 | lnw->chip.direction_input = lnw_gpio_direction_input; |
325 | lnw->chip.direction_output = lnw_gpio_direction_output; | 352 | lnw->chip.direction_output = lnw_gpio_direction_output; |
326 | lnw->chip.get = lnw_gpio_get; | 353 | lnw->chip.get = lnw_gpio_get; |
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index a9016f56ed7e..3aa6beec8c1e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c | |||
@@ -18,6 +18,17 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | #define IOH_EDGE_FALLING 0 | ||
25 | #define IOH_EDGE_RISING BIT(0) | ||
26 | #define IOH_LEVEL_L BIT(1) | ||
27 | #define IOH_LEVEL_H (BIT(0) | BIT(1)) | ||
28 | #define IOH_EDGE_BOTH BIT(2) | ||
29 | #define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
30 | |||
31 | #define IOH_IRQ_BASE 0 | ||
21 | 32 | ||
22 | #define PCI_VENDOR_ID_ROHM 0x10DB | 33 | #define PCI_VENDOR_ID_ROHM 0x10DB |
23 | 34 | ||
@@ -46,12 +57,22 @@ struct ioh_regs { | |||
46 | 57 | ||
47 | /** | 58 | /** |
48 | * struct ioh_gpio_reg_data - The register store data. | 59 | * struct ioh_gpio_reg_data - The register store data. |
60 | * @ien_reg To store contents of interrupt enable register. | ||
61 | * @imask_reg: To store contents of interrupt mask regist | ||
49 | * @po_reg: To store contents of PO register. | 62 | * @po_reg: To store contents of PO register. |
50 | * @pm_reg: To store contents of PM register. | 63 | * @pm_reg: To store contents of PM register. |
64 | * @im0_reg: To store contents of interrupt mode regist0 | ||
65 | * @im1_reg: To store contents of interrupt mode regist1 | ||
66 | * @use_sel_reg: To store contents of GPIO_USE_SEL0~3 | ||
51 | */ | 67 | */ |
52 | struct ioh_gpio_reg_data { | 68 | struct ioh_gpio_reg_data { |
69 | u32 ien_reg; | ||
70 | u32 imask_reg; | ||
53 | u32 po_reg; | 71 | u32 po_reg; |
54 | u32 pm_reg; | 72 | u32 pm_reg; |
73 | u32 im0_reg; | ||
74 | u32 im1_reg; | ||
75 | u32 use_sel_reg; | ||
55 | }; | 76 | }; |
56 | 77 | ||
57 | /** | 78 | /** |
@@ -62,7 +83,11 @@ struct ioh_gpio_reg_data { | |||
62 | * @gpio: Data for GPIO infrastructure. | 83 | * @gpio: Data for GPIO infrastructure. |
63 | * @ioh_gpio_reg: Memory mapped Register data is saved here | 84 | * @ioh_gpio_reg: Memory mapped Register data is saved here |
64 | * when suspend. | 85 | * when suspend. |
86 | * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM | ||
65 | * @ch: Indicate GPIO channel | 87 | * @ch: Indicate GPIO channel |
88 | * @irq_base: Save base of IRQ number for interrupt | ||
89 | * @spinlock: Used for register access protection in | ||
90 | * interrupt context ioh_irq_type and PM; | ||
66 | */ | 91 | */ |
67 | struct ioh_gpio { | 92 | struct ioh_gpio { |
68 | void __iomem *base; | 93 | void __iomem *base; |
@@ -70,8 +95,11 @@ struct ioh_gpio { | |||
70 | struct device *dev; | 95 | struct device *dev; |
71 | struct gpio_chip gpio; | 96 | struct gpio_chip gpio; |
72 | struct ioh_gpio_reg_data ioh_gpio_reg; | 97 | struct ioh_gpio_reg_data ioh_gpio_reg; |
98 | u32 gpio_use_sel; | ||
73 | struct mutex lock; | 99 | struct mutex lock; |
74 | int ch; | 100 | int ch; |
101 | int irq_base; | ||
102 | spinlock_t spinlock; | ||
75 | }; | 103 | }; |
76 | 104 | ||
77 | static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; | 105 | static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; |
@@ -145,8 +173,25 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | |||
145 | */ | 173 | */ |
146 | static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) | 174 | static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) |
147 | { | 175 | { |
148 | chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po); | 176 | int i; |
149 | chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm); | 177 | |
178 | for (i = 0; i < 8; i ++, chip++) { | ||
179 | chip->ioh_gpio_reg.po_reg = | ||
180 | ioread32(&chip->reg->regs[chip->ch].po); | ||
181 | chip->ioh_gpio_reg.pm_reg = | ||
182 | ioread32(&chip->reg->regs[chip->ch].pm); | ||
183 | chip->ioh_gpio_reg.ien_reg = | ||
184 | ioread32(&chip->reg->regs[chip->ch].ien); | ||
185 | chip->ioh_gpio_reg.imask_reg = | ||
186 | ioread32(&chip->reg->regs[chip->ch].imask); | ||
187 | chip->ioh_gpio_reg.im0_reg = | ||
188 | ioread32(&chip->reg->regs[chip->ch].im_0); | ||
189 | chip->ioh_gpio_reg.im1_reg = | ||
190 | ioread32(&chip->reg->regs[chip->ch].im_1); | ||
191 | if (i < 4) | ||
192 | chip->ioh_gpio_reg.use_sel_reg = | ||
193 | ioread32(&chip->reg->ioh_sel_reg[i]); | ||
194 | } | ||
150 | } | 195 | } |
151 | 196 | ||
152 | /* | 197 | /* |
@@ -154,13 +199,34 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) | |||
154 | */ | 199 | */ |
155 | static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) | 200 | static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) |
156 | { | 201 | { |
157 | /* to store contents of PO register */ | 202 | int i; |
158 | iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po); | 203 | |
159 | /* to store contents of PM register */ | 204 | for (i = 0; i < 8; i ++, chip++) { |
160 | iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm); | 205 | iowrite32(chip->ioh_gpio_reg.po_reg, |
206 | &chip->reg->regs[chip->ch].po); | ||
207 | iowrite32(chip->ioh_gpio_reg.pm_reg, | ||
208 | &chip->reg->regs[chip->ch].pm); | ||
209 | iowrite32(chip->ioh_gpio_reg.ien_reg, | ||
210 | &chip->reg->regs[chip->ch].ien); | ||
211 | iowrite32(chip->ioh_gpio_reg.imask_reg, | ||
212 | &chip->reg->regs[chip->ch].imask); | ||
213 | iowrite32(chip->ioh_gpio_reg.im0_reg, | ||
214 | &chip->reg->regs[chip->ch].im_0); | ||
215 | iowrite32(chip->ioh_gpio_reg.im1_reg, | ||
216 | &chip->reg->regs[chip->ch].im_1); | ||
217 | if (i < 4) | ||
218 | iowrite32(chip->ioh_gpio_reg.use_sel_reg, | ||
219 | &chip->reg->ioh_sel_reg[i]); | ||
220 | } | ||
161 | } | 221 | } |
162 | #endif | 222 | #endif |
163 | 223 | ||
224 | static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) | ||
225 | { | ||
226 | struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); | ||
227 | return chip->irq_base + offset; | ||
228 | } | ||
229 | |||
164 | static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) | 230 | static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) |
165 | { | 231 | { |
166 | struct gpio_chip *gpio = &chip->gpio; | 232 | struct gpio_chip *gpio = &chip->gpio; |
@@ -175,16 +241,148 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) | |||
175 | gpio->base = -1; | 241 | gpio->base = -1; |
176 | gpio->ngpio = num_port; | 242 | gpio->ngpio = num_port; |
177 | gpio->can_sleep = 0; | 243 | gpio->can_sleep = 0; |
244 | gpio->to_irq = ioh_gpio_to_irq; | ||
245 | } | ||
246 | |||
247 | static int ioh_irq_type(struct irq_data *d, unsigned int type) | ||
248 | { | ||
249 | u32 im; | ||
250 | u32 *im_reg; | ||
251 | u32 ien; | ||
252 | u32 im_pos; | ||
253 | int ch; | ||
254 | unsigned long flags; | ||
255 | u32 val; | ||
256 | int irq = d->irq; | ||
257 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
258 | struct ioh_gpio *chip = gc->private; | ||
259 | |||
260 | ch = irq - chip->irq_base; | ||
261 | if (irq <= chip->irq_base + 7) { | ||
262 | im_reg = &chip->reg->regs[chip->ch].im_0; | ||
263 | im_pos = ch; | ||
264 | } else { | ||
265 | im_reg = &chip->reg->regs[chip->ch].im_1; | ||
266 | im_pos = ch - 8; | ||
267 | } | ||
268 | dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n", | ||
269 | __func__, irq, type, ch, im_pos, type); | ||
270 | |||
271 | spin_lock_irqsave(&chip->spinlock, flags); | ||
272 | |||
273 | switch (type) { | ||
274 | case IRQ_TYPE_EDGE_RISING: | ||
275 | val = IOH_EDGE_RISING; | ||
276 | break; | ||
277 | case IRQ_TYPE_EDGE_FALLING: | ||
278 | val = IOH_EDGE_FALLING; | ||
279 | break; | ||
280 | case IRQ_TYPE_EDGE_BOTH: | ||
281 | val = IOH_EDGE_BOTH; | ||
282 | break; | ||
283 | case IRQ_TYPE_LEVEL_HIGH: | ||
284 | val = IOH_LEVEL_H; | ||
285 | break; | ||
286 | case IRQ_TYPE_LEVEL_LOW: | ||
287 | val = IOH_LEVEL_L; | ||
288 | break; | ||
289 | case IRQ_TYPE_PROBE: | ||
290 | goto end; | ||
291 | default: | ||
292 | dev_warn(chip->dev, "%s: unknown type(%dd)", | ||
293 | __func__, type); | ||
294 | goto end; | ||
295 | } | ||
296 | |||
297 | /* Set interrupt mode */ | ||
298 | im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4)); | ||
299 | iowrite32(im | (val << (im_pos * 4)), im_reg); | ||
300 | |||
301 | /* iclr */ | ||
302 | iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr); | ||
303 | |||
304 | /* IMASKCLR */ | ||
305 | iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr); | ||
306 | |||
307 | /* Enable interrupt */ | ||
308 | ien = ioread32(&chip->reg->regs[chip->ch].ien); | ||
309 | iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien); | ||
310 | end: | ||
311 | spin_unlock_irqrestore(&chip->spinlock, flags); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static void ioh_irq_unmask(struct irq_data *d) | ||
317 | { | ||
318 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
319 | struct ioh_gpio *chip = gc->private; | ||
320 | |||
321 | iowrite32(1 << (d->irq - chip->irq_base), | ||
322 | &chip->reg->regs[chip->ch].imaskclr); | ||
323 | } | ||
324 | |||
325 | static void ioh_irq_mask(struct irq_data *d) | ||
326 | { | ||
327 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
328 | struct ioh_gpio *chip = gc->private; | ||
329 | |||
330 | iowrite32(1 << (d->irq - chip->irq_base), | ||
331 | &chip->reg->regs[chip->ch].imask); | ||
332 | } | ||
333 | |||
334 | static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) | ||
335 | { | ||
336 | struct ioh_gpio *chip = dev_id; | ||
337 | u32 reg_val; | ||
338 | int i, j; | ||
339 | int ret = IRQ_NONE; | ||
340 | |||
341 | for (i = 0; i < 8; i++) { | ||
342 | reg_val = ioread32(&chip->reg->regs[i].istatus); | ||
343 | for (j = 0; j < num_ports[i]; j++) { | ||
344 | if (reg_val & BIT(j)) { | ||
345 | dev_dbg(chip->dev, | ||
346 | "%s:[%d]:irq=%d status=0x%x\n", | ||
347 | __func__, j, irq, reg_val); | ||
348 | iowrite32(BIT(j), | ||
349 | &chip->reg->regs[chip->ch].iclr); | ||
350 | generic_handle_irq(chip->irq_base + j); | ||
351 | ret = IRQ_HANDLED; | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, | ||
359 | unsigned int irq_start, unsigned int num) | ||
360 | { | ||
361 | struct irq_chip_generic *gc; | ||
362 | struct irq_chip_type *ct; | ||
363 | |||
364 | gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base, | ||
365 | handle_simple_irq); | ||
366 | gc->private = chip; | ||
367 | ct = gc->chip_types; | ||
368 | |||
369 | ct->chip.irq_mask = ioh_irq_mask; | ||
370 | ct->chip.irq_unmask = ioh_irq_unmask; | ||
371 | ct->chip.irq_set_type = ioh_irq_type; | ||
372 | |||
373 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | ||
374 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
178 | } | 375 | } |
179 | 376 | ||
180 | static int __devinit ioh_gpio_probe(struct pci_dev *pdev, | 377 | static int __devinit ioh_gpio_probe(struct pci_dev *pdev, |
181 | const struct pci_device_id *id) | 378 | const struct pci_device_id *id) |
182 | { | 379 | { |
183 | int ret; | 380 | int ret; |
184 | int i; | 381 | int i, j; |
185 | struct ioh_gpio *chip; | 382 | struct ioh_gpio *chip; |
186 | void __iomem *base; | 383 | void __iomem *base; |
187 | void __iomem *chip_save; | 384 | void __iomem *chip_save; |
385 | int irq_base; | ||
188 | 386 | ||
189 | ret = pci_enable_device(pdev); | 387 | ret = pci_enable_device(pdev); |
190 | if (ret) { | 388 | if (ret) { |
@@ -228,10 +426,41 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, | |||
228 | } | 426 | } |
229 | 427 | ||
230 | chip = chip_save; | 428 | chip = chip_save; |
429 | for (j = 0; j < 8; j++, chip++) { | ||
430 | irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j], | ||
431 | NUMA_NO_NODE); | ||
432 | if (irq_base < 0) { | ||
433 | dev_warn(&pdev->dev, | ||
434 | "ml_ioh_gpio: Failed to get IRQ base num\n"); | ||
435 | chip->irq_base = -1; | ||
436 | goto err_irq_alloc_descs; | ||
437 | } | ||
438 | chip->irq_base = irq_base; | ||
439 | ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]); | ||
440 | } | ||
441 | |||
442 | chip = chip_save; | ||
443 | ret = request_irq(pdev->irq, ioh_gpio_handler, | ||
444 | IRQF_SHARED, KBUILD_MODNAME, chip); | ||
445 | if (ret != 0) { | ||
446 | dev_err(&pdev->dev, | ||
447 | "%s request_irq failed\n", __func__); | ||
448 | goto err_request_irq; | ||
449 | } | ||
450 | |||
231 | pci_set_drvdata(pdev, chip); | 451 | pci_set_drvdata(pdev, chip); |
232 | 452 | ||
233 | return 0; | 453 | return 0; |
234 | 454 | ||
455 | err_request_irq: | ||
456 | chip = chip_save; | ||
457 | err_irq_alloc_descs: | ||
458 | while (--j >= 0) { | ||
459 | chip--; | ||
460 | irq_free_descs(chip->irq_base, num_ports[j]); | ||
461 | } | ||
462 | |||
463 | chip = chip_save; | ||
235 | err_gpiochip_add: | 464 | err_gpiochip_add: |
236 | while (--i >= 0) { | 465 | while (--i >= 0) { |
237 | chip--; | 466 | chip--; |
@@ -264,7 +493,11 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev) | |||
264 | void __iomem *chip_save; | 493 | void __iomem *chip_save; |
265 | 494 | ||
266 | chip_save = chip; | 495 | chip_save = chip; |
496 | |||
497 | free_irq(pdev->irq, chip); | ||
498 | |||
267 | for (i = 0; i < 8; i++, chip++) { | 499 | for (i = 0; i < 8; i++, chip++) { |
500 | irq_free_descs(chip->irq_base, num_ports[i]); | ||
268 | err = gpiochip_remove(&chip->gpio); | 501 | err = gpiochip_remove(&chip->gpio); |
269 | if (err) | 502 | if (err) |
270 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); | 503 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); |
@@ -282,9 +515,11 @@ static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state) | |||
282 | { | 515 | { |
283 | s32 ret; | 516 | s32 ret; |
284 | struct ioh_gpio *chip = pci_get_drvdata(pdev); | 517 | struct ioh_gpio *chip = pci_get_drvdata(pdev); |
518 | unsigned long flags; | ||
285 | 519 | ||
520 | spin_lock_irqsave(&chip->spinlock, flags); | ||
286 | ioh_gpio_save_reg_conf(chip); | 521 | ioh_gpio_save_reg_conf(chip); |
287 | ioh_gpio_restore_reg_conf(chip); | 522 | spin_unlock_irqrestore(&chip->spinlock, flags); |
288 | 523 | ||
289 | ret = pci_save_state(pdev); | 524 | ret = pci_save_state(pdev); |
290 | if (ret) { | 525 | if (ret) { |
@@ -304,6 +539,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev) | |||
304 | { | 539 | { |
305 | s32 ret; | 540 | s32 ret; |
306 | struct ioh_gpio *chip = pci_get_drvdata(pdev); | 541 | struct ioh_gpio *chip = pci_get_drvdata(pdev); |
542 | unsigned long flags; | ||
307 | 543 | ||
308 | ret = pci_enable_wake(pdev, PCI_D0, 0); | 544 | ret = pci_enable_wake(pdev, PCI_D0, 0); |
309 | 545 | ||
@@ -315,9 +551,11 @@ static int ioh_gpio_resume(struct pci_dev *pdev) | |||
315 | } | 551 | } |
316 | pci_restore_state(pdev); | 552 | pci_restore_state(pdev); |
317 | 553 | ||
554 | spin_lock_irqsave(&chip->spinlock, flags); | ||
318 | iowrite32(0x01, &chip->reg->srst); | 555 | iowrite32(0x01, &chip->reg->srst); |
319 | iowrite32(0x00, &chip->reg->srst); | 556 | iowrite32(0x00, &chip->reg->srst); |
320 | ioh_gpio_restore_reg_conf(chip); | 557 | ioh_gpio_restore_reg_conf(chip); |
558 | spin_unlock_irqrestore(&chip->spinlock, flags); | ||
321 | 559 | ||
322 | return 0; | 560 | return 0; |
323 | } | 561 | } |
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 4340acae3bd3..82f7b65baf72 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <asm-generic/bug.h> | 32 | #include <asm-generic/bug.h> |
33 | #include <asm/mach/irq.h> | ||
33 | 34 | ||
34 | enum mxc_gpio_hwtype { | 35 | enum mxc_gpio_hwtype { |
35 | IMX1_GPIO, /* runs on i.mx1 */ | 36 | IMX1_GPIO, /* runs on i.mx1 */ |
@@ -232,10 +233,15 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
232 | { | 233 | { |
233 | u32 irq_stat; | 234 | u32 irq_stat; |
234 | struct mxc_gpio_port *port = irq_get_handler_data(irq); | 235 | struct mxc_gpio_port *port = irq_get_handler_data(irq); |
236 | struct irq_chip *chip = irq_get_chip(irq); | ||
237 | |||
238 | chained_irq_enter(chip, desc); | ||
235 | 239 | ||
236 | irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR); | 240 | irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR); |
237 | 241 | ||
238 | mxc_gpio_irq_handler(port, irq_stat); | 242 | mxc_gpio_irq_handler(port, irq_stat); |
243 | |||
244 | chained_irq_exit(chip, desc); | ||
239 | } | 245 | } |
240 | 246 | ||
241 | /* MX2 has one interrupt *for all* gpio ports */ | 247 | /* MX2 has one interrupt *for all* gpio ports */ |
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index 740caed2b278..1ebedfb6d46d 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c | |||
@@ -59,7 +59,6 @@ struct nmk_gpio_chip { | |||
59 | u32 rwimsc; | 59 | u32 rwimsc; |
60 | u32 fwimsc; | 60 | u32 fwimsc; |
61 | u32 slpm; | 61 | u32 slpm; |
62 | u32 enabled; | ||
63 | u32 pull_up; | 62 | u32 pull_up; |
64 | }; | 63 | }; |
65 | 64 | ||
@@ -277,6 +276,8 @@ static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) | |||
277 | if (!chip) | 276 | if (!chip) |
278 | break; | 277 | break; |
279 | 278 | ||
279 | clk_enable(chip->clk); | ||
280 | |||
280 | slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); | 281 | slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); |
281 | writel(temp, chip->addr + NMK_GPIO_SLPC); | 282 | writel(temp, chip->addr + NMK_GPIO_SLPC); |
282 | } | 283 | } |
@@ -293,6 +294,8 @@ static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) | |||
293 | break; | 294 | break; |
294 | 295 | ||
295 | writel(slpm[i], chip->addr + NMK_GPIO_SLPC); | 296 | writel(slpm[i], chip->addr + NMK_GPIO_SLPC); |
297 | |||
298 | clk_disable(chip->clk); | ||
296 | } | 299 | } |
297 | } | 300 | } |
298 | 301 | ||
@@ -337,10 +340,12 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) | |||
337 | break; | 340 | break; |
338 | } | 341 | } |
339 | 342 | ||
343 | clk_enable(nmk_chip->clk); | ||
340 | spin_lock(&nmk_chip->lock); | 344 | spin_lock(&nmk_chip->lock); |
341 | __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, | 345 | __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, |
342 | cfgs[i], sleep, glitch ? slpm : NULL); | 346 | cfgs[i], sleep, glitch ? slpm : NULL); |
343 | spin_unlock(&nmk_chip->lock); | 347 | spin_unlock(&nmk_chip->lock); |
348 | clk_disable(nmk_chip->clk); | ||
344 | } | 349 | } |
345 | 350 | ||
346 | if (glitch) | 351 | if (glitch) |
@@ -425,6 +430,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) | |||
425 | if (!nmk_chip) | 430 | if (!nmk_chip) |
426 | return -EINVAL; | 431 | return -EINVAL; |
427 | 432 | ||
433 | clk_enable(nmk_chip->clk); | ||
428 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); | 434 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
429 | spin_lock(&nmk_chip->lock); | 435 | spin_lock(&nmk_chip->lock); |
430 | 436 | ||
@@ -432,6 +438,7 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) | |||
432 | 438 | ||
433 | spin_unlock(&nmk_chip->lock); | 439 | spin_unlock(&nmk_chip->lock); |
434 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | 440 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); |
441 | clk_disable(nmk_chip->clk); | ||
435 | 442 | ||
436 | return 0; | 443 | return 0; |
437 | } | 444 | } |
@@ -458,9 +465,11 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) | |||
458 | if (!nmk_chip) | 465 | if (!nmk_chip) |
459 | return -EINVAL; | 466 | return -EINVAL; |
460 | 467 | ||
468 | clk_enable(nmk_chip->clk); | ||
461 | spin_lock_irqsave(&nmk_chip->lock, flags); | 469 | spin_lock_irqsave(&nmk_chip->lock, flags); |
462 | __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); | 470 | __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull); |
463 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 471 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
472 | clk_disable(nmk_chip->clk); | ||
464 | 473 | ||
465 | return 0; | 474 | return 0; |
466 | } | 475 | } |
@@ -484,9 +493,11 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) | |||
484 | if (!nmk_chip) | 493 | if (!nmk_chip) |
485 | return -EINVAL; | 494 | return -EINVAL; |
486 | 495 | ||
496 | clk_enable(nmk_chip->clk); | ||
487 | spin_lock_irqsave(&nmk_chip->lock, flags); | 497 | spin_lock_irqsave(&nmk_chip->lock, flags); |
488 | __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); | 498 | __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode); |
489 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 499 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
500 | clk_disable(nmk_chip->clk); | ||
490 | 501 | ||
491 | return 0; | 502 | return 0; |
492 | } | 503 | } |
@@ -503,9 +514,13 @@ int nmk_gpio_get_mode(int gpio) | |||
503 | 514 | ||
504 | bit = 1 << (gpio - nmk_chip->chip.base); | 515 | bit = 1 << (gpio - nmk_chip->chip.base); |
505 | 516 | ||
517 | clk_enable(nmk_chip->clk); | ||
518 | |||
506 | afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; | 519 | afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; |
507 | bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; | 520 | bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; |
508 | 521 | ||
522 | clk_disable(nmk_chip->clk); | ||
523 | |||
509 | return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); | 524 | return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); |
510 | } | 525 | } |
511 | EXPORT_SYMBOL(nmk_gpio_get_mode); | 526 | EXPORT_SYMBOL(nmk_gpio_get_mode); |
@@ -526,7 +541,10 @@ static void nmk_gpio_irq_ack(struct irq_data *d) | |||
526 | nmk_chip = irq_data_get_irq_chip_data(d); | 541 | nmk_chip = irq_data_get_irq_chip_data(d); |
527 | if (!nmk_chip) | 542 | if (!nmk_chip) |
528 | return; | 543 | return; |
544 | |||
545 | clk_enable(nmk_chip->clk); | ||
529 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); | 546 | writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); |
547 | clk_disable(nmk_chip->clk); | ||
530 | } | 548 | } |
531 | 549 | ||
532 | enum nmk_gpio_irq_type { | 550 | enum nmk_gpio_irq_type { |
@@ -587,11 +605,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) | |||
587 | if (!nmk_chip) | 605 | if (!nmk_chip) |
588 | return -EINVAL; | 606 | return -EINVAL; |
589 | 607 | ||
590 | if (enable) | 608 | clk_enable(nmk_chip->clk); |
591 | nmk_chip->enabled |= bitmask; | ||
592 | else | ||
593 | nmk_chip->enabled &= ~bitmask; | ||
594 | |||
595 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); | 609 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
596 | spin_lock(&nmk_chip->lock); | 610 | spin_lock(&nmk_chip->lock); |
597 | 611 | ||
@@ -602,6 +616,7 @@ static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) | |||
602 | 616 | ||
603 | spin_unlock(&nmk_chip->lock); | 617 | spin_unlock(&nmk_chip->lock); |
604 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | 618 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); |
619 | clk_disable(nmk_chip->clk); | ||
605 | 620 | ||
606 | return 0; | 621 | return 0; |
607 | } | 622 | } |
@@ -629,10 +644,11 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | |||
629 | return -EINVAL; | 644 | return -EINVAL; |
630 | bitmask = nmk_gpio_get_bitmask(gpio); | 645 | bitmask = nmk_gpio_get_bitmask(gpio); |
631 | 646 | ||
647 | clk_enable(nmk_chip->clk); | ||
632 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); | 648 | spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); |
633 | spin_lock(&nmk_chip->lock); | 649 | spin_lock(&nmk_chip->lock); |
634 | 650 | ||
635 | if (!(nmk_chip->enabled & bitmask)) | 651 | if (irqd_irq_disabled(d)) |
636 | __nmk_gpio_set_wake(nmk_chip, gpio, on); | 652 | __nmk_gpio_set_wake(nmk_chip, gpio, on); |
637 | 653 | ||
638 | if (on) | 654 | if (on) |
@@ -642,13 +658,15 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | |||
642 | 658 | ||
643 | spin_unlock(&nmk_chip->lock); | 659 | spin_unlock(&nmk_chip->lock); |
644 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); | 660 | spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); |
661 | clk_disable(nmk_chip->clk); | ||
645 | 662 | ||
646 | return 0; | 663 | return 0; |
647 | } | 664 | } |
648 | 665 | ||
649 | static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) | 666 | static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
650 | { | 667 | { |
651 | bool enabled, wake = irqd_is_wakeup_set(d); | 668 | bool enabled = !irqd_irq_disabled(d); |
669 | bool wake = irqd_is_wakeup_set(d); | ||
652 | int gpio; | 670 | int gpio; |
653 | struct nmk_gpio_chip *nmk_chip; | 671 | struct nmk_gpio_chip *nmk_chip; |
654 | unsigned long flags; | 672 | unsigned long flags; |
@@ -665,8 +683,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
665 | if (type & IRQ_TYPE_LEVEL_LOW) | 683 | if (type & IRQ_TYPE_LEVEL_LOW) |
666 | return -EINVAL; | 684 | return -EINVAL; |
667 | 685 | ||
668 | enabled = nmk_chip->enabled & bitmask; | 686 | clk_enable(nmk_chip->clk); |
669 | |||
670 | spin_lock_irqsave(&nmk_chip->lock, flags); | 687 | spin_lock_irqsave(&nmk_chip->lock, flags); |
671 | 688 | ||
672 | if (enabled) | 689 | if (enabled) |
@@ -690,10 +707,28 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
690 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); | 707 | __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); |
691 | 708 | ||
692 | spin_unlock_irqrestore(&nmk_chip->lock, flags); | 709 | spin_unlock_irqrestore(&nmk_chip->lock, flags); |
710 | clk_disable(nmk_chip->clk); | ||
693 | 711 | ||
694 | return 0; | 712 | return 0; |
695 | } | 713 | } |
696 | 714 | ||
715 | static unsigned int nmk_gpio_irq_startup(struct irq_data *d) | ||
716 | { | ||
717 | struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); | ||
718 | |||
719 | clk_enable(nmk_chip->clk); | ||
720 | nmk_gpio_irq_unmask(d); | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | static void nmk_gpio_irq_shutdown(struct irq_data *d) | ||
725 | { | ||
726 | struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); | ||
727 | |||
728 | nmk_gpio_irq_mask(d); | ||
729 | clk_disable(nmk_chip->clk); | ||
730 | } | ||
731 | |||
697 | static struct irq_chip nmk_gpio_irq_chip = { | 732 | static struct irq_chip nmk_gpio_irq_chip = { |
698 | .name = "Nomadik-GPIO", | 733 | .name = "Nomadik-GPIO", |
699 | .irq_ack = nmk_gpio_irq_ack, | 734 | .irq_ack = nmk_gpio_irq_ack, |
@@ -701,6 +736,8 @@ static struct irq_chip nmk_gpio_irq_chip = { | |||
701 | .irq_unmask = nmk_gpio_irq_unmask, | 736 | .irq_unmask = nmk_gpio_irq_unmask, |
702 | .irq_set_type = nmk_gpio_irq_set_type, | 737 | .irq_set_type = nmk_gpio_irq_set_type, |
703 | .irq_set_wake = nmk_gpio_irq_set_wake, | 738 | .irq_set_wake = nmk_gpio_irq_set_wake, |
739 | .irq_startup = nmk_gpio_irq_startup, | ||
740 | .irq_shutdown = nmk_gpio_irq_shutdown, | ||
704 | }; | 741 | }; |
705 | 742 | ||
706 | static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, | 743 | static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, |
@@ -727,7 +764,11 @@ static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, | |||
727 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 764 | static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) |
728 | { | 765 | { |
729 | struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); | 766 | struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq); |
730 | u32 status = readl(nmk_chip->addr + NMK_GPIO_IS); | 767 | u32 status; |
768 | |||
769 | clk_enable(nmk_chip->clk); | ||
770 | status = readl(nmk_chip->addr + NMK_GPIO_IS); | ||
771 | clk_disable(nmk_chip->clk); | ||
731 | 772 | ||
732 | __nmk_gpio_irq_handler(irq, desc, status); | 773 | __nmk_gpio_irq_handler(irq, desc, status); |
733 | } | 774 | } |
@@ -773,7 +814,12 @@ static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) | |||
773 | struct nmk_gpio_chip *nmk_chip = | 814 | struct nmk_gpio_chip *nmk_chip = |
774 | container_of(chip, struct nmk_gpio_chip, chip); | 815 | container_of(chip, struct nmk_gpio_chip, chip); |
775 | 816 | ||
817 | clk_enable(nmk_chip->clk); | ||
818 | |||
776 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); | 819 | writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); |
820 | |||
821 | clk_disable(nmk_chip->clk); | ||
822 | |||
777 | return 0; | 823 | return 0; |
778 | } | 824 | } |
779 | 825 | ||
@@ -782,8 +828,15 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) | |||
782 | struct nmk_gpio_chip *nmk_chip = | 828 | struct nmk_gpio_chip *nmk_chip = |
783 | container_of(chip, struct nmk_gpio_chip, chip); | 829 | container_of(chip, struct nmk_gpio_chip, chip); |
784 | u32 bit = 1 << offset; | 830 | u32 bit = 1 << offset; |
831 | int value; | ||
832 | |||
833 | clk_enable(nmk_chip->clk); | ||
785 | 834 | ||
786 | return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; | 835 | value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; |
836 | |||
837 | clk_disable(nmk_chip->clk); | ||
838 | |||
839 | return value; | ||
787 | } | 840 | } |
788 | 841 | ||
789 | static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, | 842 | static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, |
@@ -792,7 +845,11 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, | |||
792 | struct nmk_gpio_chip *nmk_chip = | 845 | struct nmk_gpio_chip *nmk_chip = |
793 | container_of(chip, struct nmk_gpio_chip, chip); | 846 | container_of(chip, struct nmk_gpio_chip, chip); |
794 | 847 | ||
848 | clk_enable(nmk_chip->clk); | ||
849 | |||
795 | __nmk_gpio_set_output(nmk_chip, offset, val); | 850 | __nmk_gpio_set_output(nmk_chip, offset, val); |
851 | |||
852 | clk_disable(nmk_chip->clk); | ||
796 | } | 853 | } |
797 | 854 | ||
798 | static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, | 855 | static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, |
@@ -801,8 +858,12 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, | |||
801 | struct nmk_gpio_chip *nmk_chip = | 858 | struct nmk_gpio_chip *nmk_chip = |
802 | container_of(chip, struct nmk_gpio_chip, chip); | 859 | container_of(chip, struct nmk_gpio_chip, chip); |
803 | 860 | ||
861 | clk_enable(nmk_chip->clk); | ||
862 | |||
804 | __nmk_gpio_make_output(nmk_chip, offset, val); | 863 | __nmk_gpio_make_output(nmk_chip, offset, val); |
805 | 864 | ||
865 | clk_disable(nmk_chip->clk); | ||
866 | |||
806 | return 0; | 867 | return 0; |
807 | } | 868 | } |
808 | 869 | ||
@@ -833,6 +894,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
833 | [NMK_GPIO_ALT_C] = "altC", | 894 | [NMK_GPIO_ALT_C] = "altC", |
834 | }; | 895 | }; |
835 | 896 | ||
897 | clk_enable(nmk_chip->clk); | ||
898 | |||
836 | for (i = 0; i < chip->ngpio; i++, gpio++) { | 899 | for (i = 0; i < chip->ngpio; i++, gpio++) { |
837 | const char *label = gpiochip_is_requested(chip, i); | 900 | const char *label = gpiochip_is_requested(chip, i); |
838 | bool pull; | 901 | bool pull; |
@@ -877,6 +940,8 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
877 | 940 | ||
878 | seq_printf(s, "\n"); | 941 | seq_printf(s, "\n"); |
879 | } | 942 | } |
943 | |||
944 | clk_disable(nmk_chip->clk); | ||
880 | } | 945 | } |
881 | 946 | ||
882 | #else | 947 | #else |
@@ -894,6 +959,34 @@ static struct gpio_chip nmk_gpio_template = { | |||
894 | .can_sleep = 0, | 959 | .can_sleep = 0, |
895 | }; | 960 | }; |
896 | 961 | ||
962 | void nmk_gpio_clocks_enable(void) | ||
963 | { | ||
964 | int i; | ||
965 | |||
966 | for (i = 0; i < NUM_BANKS; i++) { | ||
967 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
968 | |||
969 | if (!chip) | ||
970 | continue; | ||
971 | |||
972 | clk_enable(chip->clk); | ||
973 | } | ||
974 | } | ||
975 | |||
976 | void nmk_gpio_clocks_disable(void) | ||
977 | { | ||
978 | int i; | ||
979 | |||
980 | for (i = 0; i < NUM_BANKS; i++) { | ||
981 | struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; | ||
982 | |||
983 | if (!chip) | ||
984 | continue; | ||
985 | |||
986 | clk_disable(chip->clk); | ||
987 | } | ||
988 | } | ||
989 | |||
897 | /* | 990 | /* |
898 | * Called from the suspend/resume path to only keep the real wakeup interrupts | 991 | * Called from the suspend/resume path to only keep the real wakeup interrupts |
899 | * (those that have had set_irq_wake() called on them) as wakeup interrupts, | 992 | * (those that have had set_irq_wake() called on them) as wakeup interrupts, |
@@ -913,6 +1006,8 @@ void nmk_gpio_wakeups_suspend(void) | |||
913 | if (!chip) | 1006 | if (!chip) |
914 | break; | 1007 | break; |
915 | 1008 | ||
1009 | clk_enable(chip->clk); | ||
1010 | |||
916 | chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); | 1011 | chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); |
917 | chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); | 1012 | chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); |
918 | 1013 | ||
@@ -927,6 +1022,8 @@ void nmk_gpio_wakeups_suspend(void) | |||
927 | /* 0 -> wakeup enable */ | 1022 | /* 0 -> wakeup enable */ |
928 | writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); | 1023 | writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); |
929 | } | 1024 | } |
1025 | |||
1026 | clk_disable(chip->clk); | ||
930 | } | 1027 | } |
931 | } | 1028 | } |
932 | 1029 | ||
@@ -940,11 +1037,15 @@ void nmk_gpio_wakeups_resume(void) | |||
940 | if (!chip) | 1037 | if (!chip) |
941 | break; | 1038 | break; |
942 | 1039 | ||
1040 | clk_enable(chip->clk); | ||
1041 | |||
943 | writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); | 1042 | writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); |
944 | writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); | 1043 | writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); |
945 | 1044 | ||
946 | if (chip->sleepmode) | 1045 | if (chip->sleepmode) |
947 | writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); | 1046 | writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); |
1047 | |||
1048 | clk_disable(chip->clk); | ||
948 | } | 1049 | } |
949 | } | 1050 | } |
950 | 1051 | ||
@@ -1011,8 +1112,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) | |||
1011 | goto out_release; | 1112 | goto out_release; |
1012 | } | 1113 | } |
1013 | 1114 | ||
1014 | clk_enable(clk); | ||
1015 | |||
1016 | nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); | 1115 | nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); |
1017 | if (!nmk_chip) { | 1116 | if (!nmk_chip) { |
1018 | ret = -ENOMEM; | 1117 | ret = -ENOMEM; |
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 36919e77c495..1e8a4a538810 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c | |||
@@ -17,9 +17,17 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
20 | 22 | ||
21 | #define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */ | 23 | #define PCH_EDGE_FALLING 0 |
22 | #define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */ | 24 | #define PCH_EDGE_RISING BIT(0) |
25 | #define PCH_LEVEL_L BIT(1) | ||
26 | #define PCH_LEVEL_H (BIT(0) | BIT(1)) | ||
27 | #define PCH_EDGE_BOTH BIT(2) | ||
28 | #define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
29 | |||
30 | #define PCH_IRQ_BASE 24 | ||
23 | 31 | ||
24 | struct pch_regs { | 32 | struct pch_regs { |
25 | u32 ien; | 33 | u32 ien; |
@@ -33,18 +41,43 @@ struct pch_regs { | |||
33 | u32 pm; | 41 | u32 pm; |
34 | u32 im0; | 42 | u32 im0; |
35 | u32 im1; | 43 | u32 im1; |
36 | u32 reserved[4]; | 44 | u32 reserved[3]; |
45 | u32 gpio_use_sel; | ||
37 | u32 reset; | 46 | u32 reset; |
38 | }; | 47 | }; |
39 | 48 | ||
49 | enum pch_type_t { | ||
50 | INTEL_EG20T_PCH, | ||
51 | OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */ | ||
52 | OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */ | ||
53 | }; | ||
54 | |||
55 | /* Specifies number of GPIO PINS */ | ||
56 | static int gpio_pins[] = { | ||
57 | [INTEL_EG20T_PCH] = 12, | ||
58 | [OKISEMI_ML7223m_IOH] = 8, | ||
59 | [OKISEMI_ML7223n_IOH] = 8, | ||
60 | }; | ||
61 | |||
40 | /** | 62 | /** |
41 | * struct pch_gpio_reg_data - The register store data. | 63 | * struct pch_gpio_reg_data - The register store data. |
64 | * @ien_reg: To store contents of IEN register. | ||
65 | * @imask_reg: To store contents of IMASK register. | ||
42 | * @po_reg: To store contents of PO register. | 66 | * @po_reg: To store contents of PO register. |
43 | * @pm_reg: To store contents of PM register. | 67 | * @pm_reg: To store contents of PM register. |
68 | * @im0_reg: To store contents of IM0 register. | ||
69 | * @im1_reg: To store contents of IM1 register. | ||
70 | * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register. | ||
71 | * (Only ML7223 Bus-n) | ||
44 | */ | 72 | */ |
45 | struct pch_gpio_reg_data { | 73 | struct pch_gpio_reg_data { |
74 | u32 ien_reg; | ||
75 | u32 imask_reg; | ||
46 | u32 po_reg; | 76 | u32 po_reg; |
47 | u32 pm_reg; | 77 | u32 pm_reg; |
78 | u32 im0_reg; | ||
79 | u32 im1_reg; | ||
80 | u32 gpio_use_sel_reg; | ||
48 | }; | 81 | }; |
49 | 82 | ||
50 | /** | 83 | /** |
@@ -55,6 +88,12 @@ struct pch_gpio_reg_data { | |||
55 | * @gpio: Data for GPIO infrastructure. | 88 | * @gpio: Data for GPIO infrastructure. |
56 | * @pch_gpio_reg: Memory mapped Register data is saved here | 89 | * @pch_gpio_reg: Memory mapped Register data is saved here |
57 | * when suspend. | 90 | * when suspend. |
91 | * @lock: Used for register access protection | ||
92 | * @irq_base: Save base of IRQ number for interrupt | ||
93 | * @ioh: IOH ID | ||
94 | * @spinlock: Used for register access protection in | ||
95 | * interrupt context pch_irq_mask, | ||
96 | * pch_irq_unmask and pch_irq_type; | ||
58 | */ | 97 | */ |
59 | struct pch_gpio { | 98 | struct pch_gpio { |
60 | void __iomem *base; | 99 | void __iomem *base; |
@@ -63,6 +102,9 @@ struct pch_gpio { | |||
63 | struct gpio_chip gpio; | 102 | struct gpio_chip gpio; |
64 | struct pch_gpio_reg_data pch_gpio_reg; | 103 | struct pch_gpio_reg_data pch_gpio_reg; |
65 | struct mutex lock; | 104 | struct mutex lock; |
105 | int irq_base; | ||
106 | enum pch_type_t ioh; | ||
107 | spinlock_t spinlock; | ||
66 | }; | 108 | }; |
67 | 109 | ||
68 | static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) | 110 | static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) |
@@ -96,7 +138,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, | |||
96 | u32 reg_val; | 138 | u32 reg_val; |
97 | 139 | ||
98 | mutex_lock(&chip->lock); | 140 | mutex_lock(&chip->lock); |
99 | pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; | 141 | pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); |
100 | pm |= (1 << nr); | 142 | pm |= (1 << nr); |
101 | iowrite32(pm, &chip->reg->pm); | 143 | iowrite32(pm, &chip->reg->pm); |
102 | 144 | ||
@@ -118,7 +160,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | |||
118 | u32 pm; | 160 | u32 pm; |
119 | 161 | ||
120 | mutex_lock(&chip->lock); | 162 | mutex_lock(&chip->lock); |
121 | pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/ | 163 | pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); |
122 | pm &= ~(1 << nr); | 164 | pm &= ~(1 << nr); |
123 | iowrite32(pm, &chip->reg->pm); | 165 | iowrite32(pm, &chip->reg->pm); |
124 | mutex_unlock(&chip->lock); | 166 | mutex_unlock(&chip->lock); |
@@ -131,8 +173,16 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | |||
131 | */ | 173 | */ |
132 | static void pch_gpio_save_reg_conf(struct pch_gpio *chip) | 174 | static void pch_gpio_save_reg_conf(struct pch_gpio *chip) |
133 | { | 175 | { |
176 | chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien); | ||
177 | chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask); | ||
134 | chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po); | 178 | chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po); |
135 | chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm); | 179 | chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm); |
180 | chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0); | ||
181 | if (chip->ioh == INTEL_EG20T_PCH) | ||
182 | chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1); | ||
183 | if (chip->ioh == OKISEMI_ML7223n_IOH) | ||
184 | chip->pch_gpio_reg.gpio_use_sel_reg =\ | ||
185 | ioread32(&chip->reg->gpio_use_sel); | ||
136 | } | 186 | } |
137 | 187 | ||
138 | /* | 188 | /* |
@@ -140,10 +190,24 @@ static void pch_gpio_save_reg_conf(struct pch_gpio *chip) | |||
140 | */ | 190 | */ |
141 | static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) | 191 | static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) |
142 | { | 192 | { |
193 | iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien); | ||
194 | iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask); | ||
143 | /* to store contents of PO register */ | 195 | /* to store contents of PO register */ |
144 | iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po); | 196 | iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po); |
145 | /* to store contents of PM register */ | 197 | /* to store contents of PM register */ |
146 | iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm); | 198 | iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm); |
199 | iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0); | ||
200 | if (chip->ioh == INTEL_EG20T_PCH) | ||
201 | iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1); | ||
202 | if (chip->ioh == OKISEMI_ML7223n_IOH) | ||
203 | iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, | ||
204 | &chip->reg->gpio_use_sel); | ||
205 | } | ||
206 | |||
207 | static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) | ||
208 | { | ||
209 | struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); | ||
210 | return chip->irq_base + offset; | ||
147 | } | 211 | } |
148 | 212 | ||
149 | static void pch_gpio_setup(struct pch_gpio *chip) | 213 | static void pch_gpio_setup(struct pch_gpio *chip) |
@@ -158,8 +222,132 @@ static void pch_gpio_setup(struct pch_gpio *chip) | |||
158 | gpio->set = pch_gpio_set; | 222 | gpio->set = pch_gpio_set; |
159 | gpio->dbg_show = NULL; | 223 | gpio->dbg_show = NULL; |
160 | gpio->base = -1; | 224 | gpio->base = -1; |
161 | gpio->ngpio = GPIO_NUM_PINS; | 225 | gpio->ngpio = gpio_pins[chip->ioh]; |
162 | gpio->can_sleep = 0; | 226 | gpio->can_sleep = 0; |
227 | gpio->to_irq = pch_gpio_to_irq; | ||
228 | } | ||
229 | |||
230 | static int pch_irq_type(struct irq_data *d, unsigned int type) | ||
231 | { | ||
232 | u32 im; | ||
233 | u32 *im_reg; | ||
234 | u32 ien; | ||
235 | u32 im_pos; | ||
236 | int ch; | ||
237 | unsigned long flags; | ||
238 | u32 val; | ||
239 | int irq = d->irq; | ||
240 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
241 | struct pch_gpio *chip = gc->private; | ||
242 | |||
243 | ch = irq - chip->irq_base; | ||
244 | if (irq <= chip->irq_base + 7) { | ||
245 | im_reg = &chip->reg->im0; | ||
246 | im_pos = ch; | ||
247 | } else { | ||
248 | im_reg = &chip->reg->im1; | ||
249 | im_pos = ch - 8; | ||
250 | } | ||
251 | dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d\n", | ||
252 | __func__, irq, type, ch, im_pos); | ||
253 | |||
254 | spin_lock_irqsave(&chip->spinlock, flags); | ||
255 | |||
256 | switch (type) { | ||
257 | case IRQ_TYPE_EDGE_RISING: | ||
258 | val = PCH_EDGE_RISING; | ||
259 | break; | ||
260 | case IRQ_TYPE_EDGE_FALLING: | ||
261 | val = PCH_EDGE_FALLING; | ||
262 | break; | ||
263 | case IRQ_TYPE_EDGE_BOTH: | ||
264 | val = PCH_EDGE_BOTH; | ||
265 | break; | ||
266 | case IRQ_TYPE_LEVEL_HIGH: | ||
267 | val = PCH_LEVEL_H; | ||
268 | break; | ||
269 | case IRQ_TYPE_LEVEL_LOW: | ||
270 | val = PCH_LEVEL_L; | ||
271 | break; | ||
272 | case IRQ_TYPE_PROBE: | ||
273 | goto end; | ||
274 | default: | ||
275 | dev_warn(chip->dev, "%s: unknown type(%dd)", | ||
276 | __func__, type); | ||
277 | goto end; | ||
278 | } | ||
279 | |||
280 | /* Set interrupt mode */ | ||
281 | im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4)); | ||
282 | iowrite32(im | (val << (im_pos * 4)), im_reg); | ||
283 | |||
284 | /* iclr */ | ||
285 | iowrite32(BIT(ch), &chip->reg->iclr); | ||
286 | |||
287 | /* IMASKCLR */ | ||
288 | iowrite32(BIT(ch), &chip->reg->imaskclr); | ||
289 | |||
290 | /* Enable interrupt */ | ||
291 | ien = ioread32(&chip->reg->ien); | ||
292 | iowrite32(ien | BIT(ch), &chip->reg->ien); | ||
293 | end: | ||
294 | spin_unlock_irqrestore(&chip->spinlock, flags); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static void pch_irq_unmask(struct irq_data *d) | ||
300 | { | ||
301 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
302 | struct pch_gpio *chip = gc->private; | ||
303 | |||
304 | iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr); | ||
305 | } | ||
306 | |||
307 | static void pch_irq_mask(struct irq_data *d) | ||
308 | { | ||
309 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
310 | struct pch_gpio *chip = gc->private; | ||
311 | |||
312 | iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask); | ||
313 | } | ||
314 | |||
315 | static irqreturn_t pch_gpio_handler(int irq, void *dev_id) | ||
316 | { | ||
317 | struct pch_gpio *chip = dev_id; | ||
318 | u32 reg_val = ioread32(&chip->reg->istatus); | ||
319 | int i; | ||
320 | int ret = IRQ_NONE; | ||
321 | |||
322 | for (i = 0; i < gpio_pins[chip->ioh]; i++) { | ||
323 | if (reg_val & BIT(i)) { | ||
324 | dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n", | ||
325 | __func__, i, irq, reg_val); | ||
326 | iowrite32(BIT(i), &chip->reg->iclr); | ||
327 | generic_handle_irq(chip->irq_base + i); | ||
328 | ret = IRQ_HANDLED; | ||
329 | } | ||
330 | } | ||
331 | return ret; | ||
332 | } | ||
333 | |||
334 | static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip, | ||
335 | unsigned int irq_start, unsigned int num) | ||
336 | { | ||
337 | struct irq_chip_generic *gc; | ||
338 | struct irq_chip_type *ct; | ||
339 | |||
340 | gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base, | ||
341 | handle_simple_irq); | ||
342 | gc->private = chip; | ||
343 | ct = gc->chip_types; | ||
344 | |||
345 | ct->chip.irq_mask = pch_irq_mask; | ||
346 | ct->chip.irq_unmask = pch_irq_unmask; | ||
347 | ct->chip.irq_set_type = pch_irq_type; | ||
348 | |||
349 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | ||
350 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
163 | } | 351 | } |
164 | 352 | ||
165 | static int __devinit pch_gpio_probe(struct pci_dev *pdev, | 353 | static int __devinit pch_gpio_probe(struct pci_dev *pdev, |
@@ -167,6 +355,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, | |||
167 | { | 355 | { |
168 | s32 ret; | 356 | s32 ret; |
169 | struct pch_gpio *chip; | 357 | struct pch_gpio *chip; |
358 | int irq_base; | ||
170 | 359 | ||
171 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 360 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
172 | if (chip == NULL) | 361 | if (chip == NULL) |
@@ -192,6 +381,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, | |||
192 | goto err_iomap; | 381 | goto err_iomap; |
193 | } | 382 | } |
194 | 383 | ||
384 | if (pdev->device == 0x8803) | ||
385 | chip->ioh = INTEL_EG20T_PCH; | ||
386 | else if (pdev->device == 0x8014) | ||
387 | chip->ioh = OKISEMI_ML7223m_IOH; | ||
388 | else if (pdev->device == 0x8043) | ||
389 | chip->ioh = OKISEMI_ML7223n_IOH; | ||
390 | |||
195 | chip->reg = chip->base; | 391 | chip->reg = chip->base; |
196 | pci_set_drvdata(pdev, chip); | 392 | pci_set_drvdata(pdev, chip); |
197 | mutex_init(&chip->lock); | 393 | mutex_init(&chip->lock); |
@@ -202,8 +398,36 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, | |||
202 | goto err_gpiochip_add; | 398 | goto err_gpiochip_add; |
203 | } | 399 | } |
204 | 400 | ||
401 | irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE); | ||
402 | if (irq_base < 0) { | ||
403 | dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n"); | ||
404 | chip->irq_base = -1; | ||
405 | goto end; | ||
406 | } | ||
407 | chip->irq_base = irq_base; | ||
408 | |||
409 | ret = request_irq(pdev->irq, pch_gpio_handler, | ||
410 | IRQF_SHARED, KBUILD_MODNAME, chip); | ||
411 | if (ret != 0) { | ||
412 | dev_err(&pdev->dev, | ||
413 | "%s request_irq failed\n", __func__); | ||
414 | goto err_request_irq; | ||
415 | } | ||
416 | |||
417 | pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]); | ||
418 | |||
419 | /* Initialize interrupt ien register */ | ||
420 | iowrite32(0, &chip->reg->ien); | ||
421 | end: | ||
205 | return 0; | 422 | return 0; |
206 | 423 | ||
424 | err_request_irq: | ||
425 | irq_free_descs(irq_base, gpio_pins[chip->ioh]); | ||
426 | |||
427 | ret = gpiochip_remove(&chip->gpio); | ||
428 | if (ret) | ||
429 | dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); | ||
430 | |||
207 | err_gpiochip_add: | 431 | err_gpiochip_add: |
208 | pci_iounmap(pdev, chip->base); | 432 | pci_iounmap(pdev, chip->base); |
209 | 433 | ||
@@ -224,6 +448,12 @@ static void __devexit pch_gpio_remove(struct pci_dev *pdev) | |||
224 | int err; | 448 | int err; |
225 | struct pch_gpio *chip = pci_get_drvdata(pdev); | 449 | struct pch_gpio *chip = pci_get_drvdata(pdev); |
226 | 450 | ||
451 | if (chip->irq_base != -1) { | ||
452 | free_irq(pdev->irq, chip); | ||
453 | |||
454 | irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]); | ||
455 | } | ||
456 | |||
227 | err = gpiochip_remove(&chip->gpio); | 457 | err = gpiochip_remove(&chip->gpio); |
228 | if (err) | 458 | if (err) |
229 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); | 459 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); |
@@ -239,9 +469,11 @@ static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state) | |||
239 | { | 469 | { |
240 | s32 ret; | 470 | s32 ret; |
241 | struct pch_gpio *chip = pci_get_drvdata(pdev); | 471 | struct pch_gpio *chip = pci_get_drvdata(pdev); |
472 | unsigned long flags; | ||
242 | 473 | ||
474 | spin_lock_irqsave(&chip->spinlock, flags); | ||
243 | pch_gpio_save_reg_conf(chip); | 475 | pch_gpio_save_reg_conf(chip); |
244 | pch_gpio_restore_reg_conf(chip); | 476 | spin_unlock_irqrestore(&chip->spinlock, flags); |
245 | 477 | ||
246 | ret = pci_save_state(pdev); | 478 | ret = pci_save_state(pdev); |
247 | if (ret) { | 479 | if (ret) { |
@@ -261,6 +493,7 @@ static int pch_gpio_resume(struct pci_dev *pdev) | |||
261 | { | 493 | { |
262 | s32 ret; | 494 | s32 ret; |
263 | struct pch_gpio *chip = pci_get_drvdata(pdev); | 495 | struct pch_gpio *chip = pci_get_drvdata(pdev); |
496 | unsigned long flags; | ||
264 | 497 | ||
265 | ret = pci_enable_wake(pdev, PCI_D0, 0); | 498 | ret = pci_enable_wake(pdev, PCI_D0, 0); |
266 | 499 | ||
@@ -272,9 +505,11 @@ static int pch_gpio_resume(struct pci_dev *pdev) | |||
272 | } | 505 | } |
273 | pci_restore_state(pdev); | 506 | pci_restore_state(pdev); |
274 | 507 | ||
508 | spin_lock_irqsave(&chip->spinlock, flags); | ||
275 | iowrite32(0x01, &chip->reg->reset); | 509 | iowrite32(0x01, &chip->reg->reset); |
276 | iowrite32(0x00, &chip->reg->reset); | 510 | iowrite32(0x00, &chip->reg->reset); |
277 | pch_gpio_restore_reg_conf(chip); | 511 | pch_gpio_restore_reg_conf(chip); |
512 | spin_unlock_irqrestore(&chip->spinlock, flags); | ||
278 | 513 | ||
279 | return 0; | 514 | return 0; |
280 | } | 515 | } |
@@ -287,6 +522,7 @@ static int pch_gpio_resume(struct pci_dev *pdev) | |||
287 | static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { | 522 | static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { |
288 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, | 523 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, |
289 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, | 524 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) }, |
525 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, | ||
290 | { 0, } | 526 | { 0, } |
291 | }; | 527 | }; |
292 | MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); | 528 | MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); |
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 2c5a18f32bf3..093c90bd3c1d 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -118,7 +118,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | |||
118 | { | 118 | { |
119 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | 119 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); |
120 | 120 | ||
121 | if (chip->irq_base == (unsigned) -1) | 121 | if (chip->irq_base == NO_IRQ) |
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | 123 | ||
124 | return chip->irq_base + offset; | 124 | return chip->irq_base + offset; |
@@ -246,6 +246,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
246 | if (chip == NULL) | 246 | if (chip == NULL) |
247 | return -ENOMEM; | 247 | return -ENOMEM; |
248 | 248 | ||
249 | pdata = dev->dev.platform_data; | ||
250 | if (pdata) { | ||
251 | chip->gc.base = pdata->gpio_base; | ||
252 | chip->irq_base = pdata->irq_base; | ||
253 | } else if (dev->dev.of_node) { | ||
254 | chip->gc.base = -1; | ||
255 | chip->irq_base = NO_IRQ; | ||
256 | } else { | ||
257 | ret = -ENODEV; | ||
258 | goto free_mem; | ||
259 | } | ||
260 | |||
249 | if (!request_mem_region(dev->res.start, | 261 | if (!request_mem_region(dev->res.start, |
250 | resource_size(&dev->res), "pl061")) { | 262 | resource_size(&dev->res), "pl061")) { |
251 | ret = -EBUSY; | 263 | ret = -EBUSY; |
@@ -267,14 +279,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
267 | chip->gc.get = pl061_get_value; | 279 | chip->gc.get = pl061_get_value; |
268 | chip->gc.set = pl061_set_value; | 280 | chip->gc.set = pl061_set_value; |
269 | chip->gc.to_irq = pl061_to_irq; | 281 | chip->gc.to_irq = pl061_to_irq; |
270 | chip->gc.base = pdata->gpio_base; | ||
271 | chip->gc.ngpio = PL061_GPIO_NR; | 282 | chip->gc.ngpio = PL061_GPIO_NR; |
272 | chip->gc.label = dev_name(&dev->dev); | 283 | chip->gc.label = dev_name(&dev->dev); |
273 | chip->gc.dev = &dev->dev; | 284 | chip->gc.dev = &dev->dev; |
274 | chip->gc.owner = THIS_MODULE; | 285 | chip->gc.owner = THIS_MODULE; |
275 | 286 | ||
276 | chip->irq_base = pdata->irq_base; | ||
277 | |||
278 | ret = gpiochip_add(&chip->gc); | 287 | ret = gpiochip_add(&chip->gc); |
279 | if (ret) | 288 | if (ret) |
280 | goto iounmap; | 289 | goto iounmap; |
@@ -283,7 +292,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
283 | * irq_chip support | 292 | * irq_chip support |
284 | */ | 293 | */ |
285 | 294 | ||
286 | if (chip->irq_base == (unsigned) -1) | 295 | if (chip->irq_base == NO_IRQ) |
287 | return 0; | 296 | return 0; |
288 | 297 | ||
289 | writeb(0, chip->base + GPIOIE); /* disable irqs */ | 298 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
@@ -307,11 +316,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) | |||
307 | list_add(&chip->list, chip_list); | 316 | list_add(&chip->list, chip_list); |
308 | 317 | ||
309 | for (i = 0; i < PL061_GPIO_NR; i++) { | 318 | for (i = 0; i < PL061_GPIO_NR; i++) { |
310 | if (pdata->directions & (1 << i)) | 319 | if (pdata) { |
311 | pl061_direction_output(&chip->gc, i, | 320 | if (pdata->directions & (1 << i)) |
312 | pdata->values & (1 << i)); | 321 | pl061_direction_output(&chip->gc, i, |
313 | else | 322 | pdata->values & (1 << i)); |
314 | pl061_direction_input(&chip->gc, i); | 323 | else |
324 | pl061_direction_input(&chip->gc, i); | ||
325 | } | ||
315 | 326 | ||
316 | irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, | 327 | irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, |
317 | handle_simple_irq); | 328 | handle_simple_irq); |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index d494001b1226..8c8621097fa0 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -41,6 +41,7 @@ static inline bool gpio_is_valid(int number) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | struct device; | 43 | struct device; |
44 | struct gpio; | ||
44 | struct seq_file; | 45 | struct seq_file; |
45 | struct module; | 46 | struct module; |
46 | struct device_node; | 47 | struct device_node; |
@@ -170,18 +171,6 @@ extern int __gpio_cansleep(unsigned gpio); | |||
170 | 171 | ||
171 | extern int __gpio_to_irq(unsigned gpio); | 172 | extern int __gpio_to_irq(unsigned gpio); |
172 | 173 | ||
173 | /** | ||
174 | * struct gpio - a structure describing a GPIO with configuration | ||
175 | * @gpio: the GPIO number | ||
176 | * @flags: GPIO configuration as specified by GPIOF_* | ||
177 | * @label: a literal description string of this GPIO | ||
178 | */ | ||
179 | struct gpio { | ||
180 | unsigned gpio; | ||
181 | unsigned long flags; | ||
182 | const char *label; | ||
183 | }; | ||
184 | |||
185 | extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); | 174 | extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); |
186 | extern int gpio_request_array(const struct gpio *array, size_t num); | 175 | extern int gpio_request_array(const struct gpio *array, size_t num); |
187 | extern void gpio_free_array(const struct gpio *array, size_t num); | 176 | extern void gpio_free_array(const struct gpio *array, size_t num); |
@@ -220,13 +209,13 @@ static inline int gpio_cansleep(unsigned gpio) | |||
220 | static inline int gpio_get_value_cansleep(unsigned gpio) | 209 | static inline int gpio_get_value_cansleep(unsigned gpio) |
221 | { | 210 | { |
222 | might_sleep(); | 211 | might_sleep(); |
223 | return gpio_get_value(gpio); | 212 | return __gpio_get_value(gpio); |
224 | } | 213 | } |
225 | 214 | ||
226 | static inline void gpio_set_value_cansleep(unsigned gpio, int value) | 215 | static inline void gpio_set_value_cansleep(unsigned gpio, int value) |
227 | { | 216 | { |
228 | might_sleep(); | 217 | might_sleep(); |
229 | gpio_set_value(gpio, value); | 218 | __gpio_set_value(gpio, value); |
230 | } | 219 | } |
231 | 220 | ||
232 | #endif /* !CONFIG_GPIOLIB */ | 221 | #endif /* !CONFIG_GPIOLIB */ |
diff --git a/include/linux/amba/pl061.h b/include/linux/amba/pl061.h index 5ddd9ad4b19c..2412af944f1f 100644 --- a/include/linux/amba/pl061.h +++ b/include/linux/amba/pl061.h | |||
@@ -7,8 +7,7 @@ struct pl061_platform_data { | |||
7 | unsigned gpio_base; | 7 | unsigned gpio_base; |
8 | 8 | ||
9 | /* number of the first IRQ. | 9 | /* number of the first IRQ. |
10 | * If the IRQ functionality in not desired this must be set to | 10 | * If the IRQ functionality in not desired this must be set to NO_IRQ. |
11 | * (unsigned) -1. | ||
12 | */ | 11 | */ |
13 | unsigned irq_base; | 12 | unsigned irq_base; |
14 | 13 | ||
diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 17b5a0d80e42..38ac48b7d3a8 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h | |||
@@ -14,6 +14,18 @@ | |||
14 | #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) | 14 | #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) |
15 | #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) | 15 | #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) |
16 | 16 | ||
17 | /** | ||
18 | * struct gpio - a structure describing a GPIO with configuration | ||
19 | * @gpio: the GPIO number | ||
20 | * @flags: GPIO configuration as specified by GPIOF_* | ||
21 | * @label: a literal description string of this GPIO | ||
22 | */ | ||
23 | struct gpio { | ||
24 | unsigned gpio; | ||
25 | unsigned long flags; | ||
26 | const char *label; | ||
27 | }; | ||
28 | |||
17 | #ifdef CONFIG_GENERIC_GPIO | 29 | #ifdef CONFIG_GENERIC_GPIO |
18 | #include <asm/gpio.h> | 30 | #include <asm/gpio.h> |
19 | 31 | ||
@@ -24,18 +36,8 @@ | |||
24 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
25 | 37 | ||
26 | struct device; | 38 | struct device; |
27 | struct gpio; | ||
28 | struct gpio_chip; | 39 | struct gpio_chip; |
29 | 40 | ||
30 | /* | ||
31 | * Some platforms don't support the GPIO programming interface. | ||
32 | * | ||
33 | * In case some driver uses it anyway (it should normally have | ||
34 | * depended on GENERIC_GPIO), these routines help the compiler | ||
35 | * optimize out much GPIO-related code ... or trigger a runtime | ||
36 | * warning when something is wrongly called. | ||
37 | */ | ||
38 | |||
39 | static inline bool gpio_is_valid(int number) | 41 | static inline bool gpio_is_valid(int number) |
40 | { | 42 | { |
41 | return false; | 43 | return false; |
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index e38544dddb18..6cb7613e4bf4 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c | |||
@@ -211,6 +211,7 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, | |||
211 | } | 211 | } |
212 | return gc; | 212 | return gc; |
213 | } | 213 | } |
214 | EXPORT_SYMBOL_GPL(irq_alloc_generic_chip); | ||
214 | 215 | ||
215 | /* | 216 | /* |
216 | * Separate lockdep class for interrupt chip which can nest irq_desc | 217 | * Separate lockdep class for interrupt chip which can nest irq_desc |
@@ -258,6 +259,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
258 | } | 259 | } |
259 | gc->irq_cnt = i - gc->irq_base; | 260 | gc->irq_cnt = i - gc->irq_base; |
260 | } | 261 | } |
262 | EXPORT_SYMBOL_GPL(irq_setup_generic_chip); | ||
261 | 263 | ||
262 | /** | 264 | /** |
263 | * irq_setup_alt_chip - Switch to alternative chip | 265 | * irq_setup_alt_chip - Switch to alternative chip |
@@ -281,6 +283,7 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type) | |||
281 | } | 283 | } |
282 | return -EINVAL; | 284 | return -EINVAL; |
283 | } | 285 | } |
286 | EXPORT_SYMBOL_GPL(irq_setup_alt_chip); | ||
284 | 287 | ||
285 | /** | 288 | /** |
286 | * irq_remove_generic_chip - Remove a chip | 289 | * irq_remove_generic_chip - Remove a chip |
@@ -311,6 +314,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
311 | irq_modify_status(i, clr, set); | 314 | irq_modify_status(i, clr, set); |
312 | } | 315 | } |
313 | } | 316 | } |
317 | EXPORT_SYMBOL_GPL(irq_remove_generic_chip); | ||
314 | 318 | ||
315 | #ifdef CONFIG_PM | 319 | #ifdef CONFIG_PM |
316 | static int irq_gc_suspend(void) | 320 | static int irq_gc_suspend(void) |