aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mxc.c
diff options
context:
space:
mode:
authorBenoît Thébaudeau <benoit.thebaudeau@advansee.com>2012-06-22 15:04:06 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-07-17 15:00:16 -0400
commitaeb27748e3bc1e89ec590713e574cb6f885cc3c6 (patch)
tree79a76bb0bd3275173fdf5840db8e0c1683fd0f8b /drivers/gpio/gpio-mxc.c
parent41920d16360ebc8c482911078a17d9994fb77612 (diff)
gpio/mxc: use the edge_sel feature if available
Some mxc processors have an edge_sel feature, which allows the IRQ to be triggered by any edge. This patch makes use of this feature if available, which skips mxc_flip_edge(). Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Linus Walleij <linus.walleij@stericsson.com> Acked-by: Sascha Hauer <kernel@pengutronix.de> Cc: <linux-arm-kernel@lists.infradead.org> Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-mxc.c')
-rw-r--r--drivers/gpio/gpio-mxc.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index c337143b18f8..bb985e815533 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -38,7 +38,8 @@
38enum mxc_gpio_hwtype { 38enum mxc_gpio_hwtype {
39 IMX1_GPIO, /* runs on i.mx1 */ 39 IMX1_GPIO, /* runs on i.mx1 */
40 IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ 40 IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
41 IMX31_GPIO, /* runs on all other i.mx */ 41 IMX31_GPIO, /* runs on i.mx31 */
42 IMX35_GPIO, /* runs on all other i.mx */
42}; 43};
43 44
44/* device type dependent stuff */ 45/* device type dependent stuff */
@@ -50,6 +51,7 @@ struct mxc_gpio_hwdata {
50 unsigned icr2_reg; 51 unsigned icr2_reg;
51 unsigned imr_reg; 52 unsigned imr_reg;
52 unsigned isr_reg; 53 unsigned isr_reg;
54 int edge_sel_reg;
53 unsigned low_level; 55 unsigned low_level;
54 unsigned high_level; 56 unsigned high_level;
55 unsigned rise_edge; 57 unsigned rise_edge;
@@ -74,6 +76,7 @@ static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
74 .icr2_reg = 0x2c, 76 .icr2_reg = 0x2c,
75 .imr_reg = 0x30, 77 .imr_reg = 0x30,
76 .isr_reg = 0x34, 78 .isr_reg = 0x34,
79 .edge_sel_reg = -EINVAL,
77 .low_level = 0x03, 80 .low_level = 0x03,
78 .high_level = 0x02, 81 .high_level = 0x02,
79 .rise_edge = 0x00, 82 .rise_edge = 0x00,
@@ -88,6 +91,22 @@ static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
88 .icr2_reg = 0x10, 91 .icr2_reg = 0x10,
89 .imr_reg = 0x14, 92 .imr_reg = 0x14,
90 .isr_reg = 0x18, 93 .isr_reg = 0x18,
94 .edge_sel_reg = -EINVAL,
95 .low_level = 0x00,
96 .high_level = 0x01,
97 .rise_edge = 0x02,
98 .fall_edge = 0x03,
99};
100
101static struct mxc_gpio_hwdata imx35_gpio_hwdata = {
102 .dr_reg = 0x00,
103 .gdir_reg = 0x04,
104 .psr_reg = 0x08,
105 .icr1_reg = 0x0c,
106 .icr2_reg = 0x10,
107 .imr_reg = 0x14,
108 .isr_reg = 0x18,
109 .edge_sel_reg = 0x1c,
91 .low_level = 0x00, 110 .low_level = 0x00,
92 .high_level = 0x01, 111 .high_level = 0x01,
93 .rise_edge = 0x02, 112 .rise_edge = 0x02,
@@ -104,12 +123,13 @@ static struct mxc_gpio_hwdata *mxc_gpio_hwdata;
104#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg) 123#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg)
105#define GPIO_IMR (mxc_gpio_hwdata->imr_reg) 124#define GPIO_IMR (mxc_gpio_hwdata->imr_reg)
106#define GPIO_ISR (mxc_gpio_hwdata->isr_reg) 125#define GPIO_ISR (mxc_gpio_hwdata->isr_reg)
126#define GPIO_EDGE_SEL (mxc_gpio_hwdata->edge_sel_reg)
107 127
108#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level) 128#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level)
109#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level) 129#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level)
110#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge) 130#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge)
111#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge) 131#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge)
112#define GPIO_INT_NONE 0x4 132#define GPIO_INT_BOTH_EDGES 0x4
113 133
114static struct platform_device_id mxc_gpio_devtype[] = { 134static struct platform_device_id mxc_gpio_devtype[] = {
115 { 135 {
@@ -122,6 +142,9 @@ static struct platform_device_id mxc_gpio_devtype[] = {
122 .name = "imx31-gpio", 142 .name = "imx31-gpio",
123 .driver_data = IMX31_GPIO, 143 .driver_data = IMX31_GPIO,
124 }, { 144 }, {
145 .name = "imx35-gpio",
146 .driver_data = IMX35_GPIO,
147 }, {
125 /* sentinel */ 148 /* sentinel */
126 } 149 }
127}; 150};
@@ -130,6 +153,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
130 { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], }, 153 { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
131 { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], }, 154 { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
132 { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], }, 155 { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
156 { .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },
133 { /* sentinel */ } 157 { /* sentinel */ }
134}; 158};
135 159
@@ -160,15 +184,19 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
160 edge = GPIO_INT_FALL_EDGE; 184 edge = GPIO_INT_FALL_EDGE;
161 break; 185 break;
162 case IRQ_TYPE_EDGE_BOTH: 186 case IRQ_TYPE_EDGE_BOTH:
163 val = gpio_get_value(gpio); 187 if (GPIO_EDGE_SEL >= 0) {
164 if (val) { 188 edge = GPIO_INT_BOTH_EDGES;
165 edge = GPIO_INT_LOW_LEV;
166 pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
167 } else { 189 } else {
168 edge = GPIO_INT_HIGH_LEV; 190 val = gpio_get_value(gpio);
169 pr_debug("mxc: set GPIO %d to high trigger\n", gpio); 191 if (val) {
192 edge = GPIO_INT_LOW_LEV;
193 pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
194 } else {
195 edge = GPIO_INT_HIGH_LEV;
196 pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
197 }
198 port->both_edges |= 1 << (gpio & 31);
170 } 199 }
171 port->both_edges |= 1 << (gpio & 31);
172 break; 200 break;
173 case IRQ_TYPE_LEVEL_LOW: 201 case IRQ_TYPE_LEVEL_LOW:
174 edge = GPIO_INT_LOW_LEV; 202 edge = GPIO_INT_LOW_LEV;
@@ -180,10 +208,23 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
180 return -EINVAL; 208 return -EINVAL;
181 } 209 }
182 210
183 reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */ 211 if (GPIO_EDGE_SEL >= 0) {
184 bit = gpio & 0xf; 212 val = readl(port->base + GPIO_EDGE_SEL);
185 val = readl(reg) & ~(0x3 << (bit << 1)); 213 if (edge == GPIO_INT_BOTH_EDGES)
186 writel(val | (edge << (bit << 1)), reg); 214 writel(val | (1 << (gpio & 0x1f)),
215 port->base + GPIO_EDGE_SEL);
216 else
217 writel(val & ~(1 << (gpio & 0x1f)),
218 port->base + GPIO_EDGE_SEL);
219 }
220
221 if (edge != GPIO_INT_BOTH_EDGES) {
222 reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
223 bit = gpio & 0xf;
224 val = readl(reg) & ~(0x3 << (bit << 1));
225 writel(val | (edge << (bit << 1)), reg);
226 }
227
187 writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); 228 writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
188 229
189 return 0; 230 return 0;
@@ -338,7 +379,9 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
338 return; 379 return;
339 } 380 }
340 381
341 if (hwtype == IMX31_GPIO) 382 if (hwtype == IMX35_GPIO)
383 mxc_gpio_hwdata = &imx35_gpio_hwdata;
384 else if (hwtype == IMX31_GPIO)
342 mxc_gpio_hwdata = &imx31_gpio_hwdata; 385 mxc_gpio_hwdata = &imx31_gpio_hwdata;
343 else 386 else
344 mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata; 387 mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;