aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/powerpc/booting-without-of.txt27
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig9
-rw-r--r--arch/powerpc/sysdev/qe_lib/Makefile1
-rw-r--r--arch/powerpc/sysdev/qe_lib/gpio.c146
-rw-r--r--include/asm-powerpc/qe.h3
5 files changed, 186 insertions, 0 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 8675ebca2cfd..b68684d39f96 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1736,6 +1736,33 @@ platforms are moved over to use the flattened-device-tree model.
1736 ...... 1736 ......
1737 }; 1737 };
1738 1738
1739 Note that "par_io" nodes are obsolete, and should not be used for
1740 the new device trees. Instead, each Par I/O bank should be represented
1741 via its own gpio-controller node:
1742
1743 Required properties:
1744 - #gpio-cells : should be "2".
1745 - compatible : should be "fsl,<chip>-qe-pario-bank",
1746 "fsl,mpc8323-qe-pario-bank".
1747 - reg : offset to the register set and its length.
1748 - gpio-controller : node to identify gpio controllers.
1749
1750 Example:
1751 qe_pio_a: gpio-controller@1400 {
1752 #gpio-cells = <2>;
1753 compatible = "fsl,mpc8360-qe-pario-bank",
1754 "fsl,mpc8323-qe-pario-bank";
1755 reg = <0x1400 0x18>;
1756 gpio-controller;
1757 };
1758
1759 qe_pio_e: gpio-controller@1460 {
1760 #gpio-cells = <2>;
1761 compatible = "fsl,mpc8360-qe-pario-bank",
1762 "fsl,mpc8323-qe-pario-bank";
1763 reg = <0x1460 0x18>;
1764 gpio-controller;
1765 };
1739 1766
1740 vi) Pin configuration nodes 1767 vi) Pin configuration nodes
1741 1768
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 76ffbc48d4b9..4bb18f57901e 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -24,3 +24,12 @@ config QE_USB
24 bool 24 bool
25 help 25 help
26 QE USB Host Controller support 26 QE USB Host Controller support
27
28config QE_GPIO
29 bool "QE GPIO support"
30 depends on QUICC_ENGINE
31 select GENERIC_GPIO
32 select HAVE_GPIO_LIB
33 help
34 Say Y here if you're going to use hardware that connects to the
35 QE GPIOs.
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
index e9ff8884f74a..f1855c185291 100644
--- a/arch/powerpc/sysdev/qe_lib/Makefile
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_UCC) += ucc.o
7obj-$(CONFIG_UCC_SLOW) += ucc_slow.o 7obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
8obj-$(CONFIG_UCC_FAST) += ucc_fast.o 8obj-$(CONFIG_UCC_FAST) += ucc_fast.o
9obj-$(CONFIG_QE_USB) += usb.o 9obj-$(CONFIG_QE_USB) += usb.o
10obj-$(CONFIG_QE_GPIO) += gpio.o
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
new file mode 100644
index 000000000000..c712e245dc4c
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -0,0 +1,146 @@
1/*
2 * QUICC Engine GPIOs
3 *
4 * Copyright (c) MontaVista Software, Inc. 2008.
5 *
6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/spinlock.h>
16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/of_gpio.h>
19#include <linux/gpio.h>
20#include <asm/qe.h>
21
22struct qe_gpio_chip {
23 struct of_mm_gpio_chip mm_gc;
24 spinlock_t lock;
25
26 /* shadowed data register to clear/set bits safely */
27 u32 cpdata;
28};
29
30static inline struct qe_gpio_chip *
31to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc)
32{
33 return container_of(mm_gc, struct qe_gpio_chip, mm_gc);
34}
35
36static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
37{
38 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
39 struct qe_pio_regs __iomem *regs = mm_gc->regs;
40
41 qe_gc->cpdata = in_be32(&regs->cpdata);
42}
43
44static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
45{
46 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
47 struct qe_pio_regs __iomem *regs = mm_gc->regs;
48 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
49
50 return in_be32(&regs->cpdata) & pin_mask;
51}
52
53static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
54{
55 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
56 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
57 struct qe_pio_regs __iomem *regs = mm_gc->regs;
58 unsigned long flags;
59 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
60
61 spin_lock_irqsave(&qe_gc->lock, flags);
62
63 if (val)
64 qe_gc->cpdata |= pin_mask;
65 else
66 qe_gc->cpdata &= ~pin_mask;
67
68 out_be32(&regs->cpdata, qe_gc->cpdata);
69
70 spin_unlock_irqrestore(&qe_gc->lock, flags);
71}
72
73static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
74{
75 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
76 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
77 unsigned long flags;
78
79 spin_lock_irqsave(&qe_gc->lock, flags);
80
81 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0);
82
83 spin_unlock_irqrestore(&qe_gc->lock, flags);
84
85 return 0;
86}
87
88static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
89{
90 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
91 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
92 unsigned long flags;
93
94 spin_lock_irqsave(&qe_gc->lock, flags);
95
96 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
97
98 spin_unlock_irqrestore(&qe_gc->lock, flags);
99
100 qe_gpio_set(gc, gpio, val);
101
102 return 0;
103}
104
105void __init qe_add_gpiochips(void)
106{
107 struct device_node *np;
108
109 for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
110 int ret;
111 struct qe_gpio_chip *qe_gc;
112 struct of_mm_gpio_chip *mm_gc;
113 struct of_gpio_chip *of_gc;
114 struct gpio_chip *gc;
115
116 qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
117 if (!qe_gc) {
118 ret = -ENOMEM;
119 goto err;
120 }
121
122 spin_lock_init(&qe_gc->lock);
123
124 mm_gc = &qe_gc->mm_gc;
125 of_gc = &mm_gc->of_gc;
126 gc = &of_gc->gc;
127
128 mm_gc->save_regs = qe_gpio_save_regs;
129 of_gc->gpio_cells = 2;
130 gc->ngpio = QE_PIO_PINS;
131 gc->direction_input = qe_gpio_dir_in;
132 gc->direction_output = qe_gpio_dir_out;
133 gc->get = qe_gpio_get;
134 gc->set = qe_gpio_set;
135
136 ret = of_mm_gpiochip_add(np, mm_gc);
137 if (ret)
138 goto err;
139 continue;
140err:
141 pr_err("%s: registration failed with status %d\n",
142 np->full_name, ret);
143 kfree(qe_gc);
144 /* try others anyway */
145 }
146}
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index c4523acad48b..01e3c70b93ab 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -100,8 +100,11 @@ struct qe_pio_regs {
100#endif 100#endif
101}; 101};
102 102
103extern void __init qe_add_gpiochips(void);
103extern int par_io_init(struct device_node *np); 104extern int par_io_init(struct device_node *np);
104extern int par_io_of_config(struct device_node *np); 105extern int par_io_of_config(struct device_node *np);
106#define QE_PIO_DIR_IN 2
107#define QE_PIO_DIR_OUT 1
105extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, 108extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
106 int dir, int open_drain, int assignment, 109 int dir, int open_drain, int assignment,
107 int has_irq); 110 int has_irq);