aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mxs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-26 15:57:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-26 15:57:47 -0400
commit84a442b9a16ee69243ce7fce5d6f6f9c3fbdee68 (patch)
tree332a0c901d8ab2ffb19b8ce14b4b094bf5b08657 /drivers/gpio/gpio-mxs.c
parent39b6cc668c5ecc66f6f9c9293ffab681cb6f7065 (diff)
parentdeb88cc3c69975cbd9875ed9fac259b351f6b64d (diff)
Merge tag 'dt2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc device tree conversions (part 2) from Olof Johansson: "These continue the device tree work from part 1, this set is for the tegra, mxs and imx platforms, all of which have dependencies on clock or pinctrl changes submitted earlier." Fix up trivial conflicts due to nearby changes in drivers/{gpio/gpio,i2c/busses/i2c}-mxs.c * tag 'dt2' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (73 commits) ARM: dt: tegra: invert status=disable vs status=okay ARM: dt: tegra: consistent basic property ordering ARM: dt: tegra: sort nodes based on bus order ARM: dt: tegra: remove duplicate device_type property ARM: dt: tegra: consistenly use lower-case for hex constants ARM: dt: tegra: format regs properties consistently ARM: dt: tegra: gpio comment cleanup ARM: dt: tegra: remove unnecessary unit addresses ARM: dt: tegra: whitespace cleanup ARM: dt: tegra cardhu: fix typo in SDHCI node name ARM: dt: tegra: cardhu: register core regulator tps62361 ARM: dt: tegra30.dtsi: Add SMMU node ARM: dt: tegra20.dtsi: Add GART node ARM: dt: tegra30.dtsi: Add Memory Controller(MC) nodes ARM: dt: tegra20.dtsi: Add Memory Controller(MC) nodes ARM: dt: tegra: Add device tree support for AHB ARM: dts: enable audio support for imx28-evk ARM: dts: enable i2c device for imx28-evk i2c: mxs: add device tree probe support ARM: dts: enable mmc for imx28-evk ...
Diffstat (limited to 'drivers/gpio/gpio-mxs.c')
-rw-r--r--drivers/gpio/gpio-mxs.c156
1 files changed, 94 insertions, 62 deletions
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index b4136501abd8..39e495669961 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -25,23 +25,25 @@
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/irq.h> 26#include <linux/irq.h>
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_device.h>
28#include <linux/platform_device.h> 31#include <linux/platform_device.h>
29#include <linux/slab.h> 32#include <linux/slab.h>
30#include <linux/basic_mmio_gpio.h> 33#include <linux/basic_mmio_gpio.h>
31#include <linux/module.h> 34#include <linux/module.h>
32#include <mach/mxs.h>
33 35
34#define MXS_SET 0x4 36#define MXS_SET 0x4
35#define MXS_CLR 0x8 37#define MXS_CLR 0x8
36 38
37#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) 39#define PINCTRL_DOUT(p) ((is_imx23_gpio(p) ? 0x0500 : 0x0700) + (p->id) * 0x10)
38#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) 40#define PINCTRL_DIN(p) ((is_imx23_gpio(p) ? 0x0600 : 0x0900) + (p->id) * 0x10)
39#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10) 41#define PINCTRL_DOE(p) ((is_imx23_gpio(p) ? 0x0700 : 0x0b00) + (p->id) * 0x10)
40#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10) 42#define PINCTRL_PIN2IRQ(p) ((is_imx23_gpio(p) ? 0x0800 : 0x1000) + (p->id) * 0x10)
41#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10) 43#define PINCTRL_IRQEN(p) ((is_imx23_gpio(p) ? 0x0900 : 0x1100) + (p->id) * 0x10)
42#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10) 44#define PINCTRL_IRQLEV(p) ((is_imx23_gpio(p) ? 0x0a00 : 0x1200) + (p->id) * 0x10)
43#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10) 45#define PINCTRL_IRQPOL(p) ((is_imx23_gpio(p) ? 0x0b00 : 0x1300) + (p->id) * 0x10)
44#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10) 46#define PINCTRL_IRQSTAT(p) ((is_imx23_gpio(p) ? 0x0c00 : 0x1400) + (p->id) * 0x10)
45 47
46#define GPIO_INT_FALL_EDGE 0x0 48#define GPIO_INT_FALL_EDGE 0x0
47#define GPIO_INT_LOW_LEV 0x1 49#define GPIO_INT_LOW_LEV 0x1
@@ -52,14 +54,30 @@
52 54
53#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) 55#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START)
54 56
57enum mxs_gpio_id {
58 IMX23_GPIO,
59 IMX28_GPIO,
60};
61
55struct mxs_gpio_port { 62struct mxs_gpio_port {
56 void __iomem *base; 63 void __iomem *base;
57 int id; 64 int id;
58 int irq; 65 int irq;
59 int virtual_irq_start; 66 int virtual_irq_start;
60 struct bgpio_chip bgc; 67 struct bgpio_chip bgc;
68 enum mxs_gpio_id devid;
61}; 69};
62 70
71static inline int is_imx23_gpio(struct mxs_gpio_port *port)
72{
73 return port->devid == IMX23_GPIO;
74}
75
76static inline int is_imx28_gpio(struct mxs_gpio_port *port)
77{
78 return port->devid == IMX28_GPIO;
79}
80
63/* Note: This driver assumes 32 GPIOs are handled in one register */ 81/* Note: This driver assumes 32 GPIOs are handled in one register */
64 82
65static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) 83static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
@@ -89,21 +107,21 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
89 } 107 }
90 108
91 /* set level or edge */ 109 /* set level or edge */
92 pin_addr = port->base + PINCTRL_IRQLEV(port->id); 110 pin_addr = port->base + PINCTRL_IRQLEV(port);
93 if (edge & GPIO_INT_LEV_MASK) 111 if (edge & GPIO_INT_LEV_MASK)
94 writel(pin_mask, pin_addr + MXS_SET); 112 writel(pin_mask, pin_addr + MXS_SET);
95 else 113 else
96 writel(pin_mask, pin_addr + MXS_CLR); 114 writel(pin_mask, pin_addr + MXS_CLR);
97 115
98 /* set polarity */ 116 /* set polarity */
99 pin_addr = port->base + PINCTRL_IRQPOL(port->id); 117 pin_addr = port->base + PINCTRL_IRQPOL(port);
100 if (edge & GPIO_INT_POL_MASK) 118 if (edge & GPIO_INT_POL_MASK)
101 writel(pin_mask, pin_addr + MXS_SET); 119 writel(pin_mask, pin_addr + MXS_SET);
102 else 120 else
103 writel(pin_mask, pin_addr + MXS_CLR); 121 writel(pin_mask, pin_addr + MXS_CLR);
104 122
105 writel(1 << (gpio & 0x1f), 123 writel(1 << (gpio & 0x1f),
106 port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); 124 port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
107 125
108 return 0; 126 return 0;
109} 127}
@@ -117,8 +135,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
117 135
118 desc->irq_data.chip->irq_ack(&desc->irq_data); 136 desc->irq_data.chip->irq_ack(&desc->irq_data);
119 137
120 irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & 138 irq_stat = readl(port->base + PINCTRL_IRQSTAT(port)) &
121 readl(port->base + PINCTRL_IRQEN(port->id)); 139 readl(port->base + PINCTRL_IRQEN(port));
122 140
123 while (irq_stat != 0) { 141 while (irq_stat != 0) {
124 int irqoffset = fls(irq_stat) - 1; 142 int irqoffset = fls(irq_stat) - 1;
@@ -164,8 +182,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
164 ct->chip.irq_unmask = irq_gc_mask_set_bit; 182 ct->chip.irq_unmask = irq_gc_mask_set_bit;
165 ct->chip.irq_set_type = mxs_gpio_set_irq_type; 183 ct->chip.irq_set_type = mxs_gpio_set_irq_type;
166 ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; 184 ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
167 ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; 185 ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
168 ct->regs.mask = PINCTRL_IRQEN(port->id); 186 ct->regs.mask = PINCTRL_IRQEN(port);
169 187
170 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); 188 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
171} 189}
@@ -179,60 +197,83 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
179 return port->virtual_irq_start + offset; 197 return port->virtual_irq_start + offset;
180} 198}
181 199
200static struct platform_device_id mxs_gpio_ids[] = {
201 {
202 .name = "imx23-gpio",
203 .driver_data = IMX23_GPIO,
204 }, {
205 .name = "imx28-gpio",
206 .driver_data = IMX28_GPIO,
207 }, {
208 /* sentinel */
209 }
210};
211MODULE_DEVICE_TABLE(platform, mxs_gpio_ids);
212
213static const struct of_device_id mxs_gpio_dt_ids[] = {
214 { .compatible = "fsl,imx23-gpio", .data = (void *) IMX23_GPIO, },
215 { .compatible = "fsl,imx28-gpio", .data = (void *) IMX28_GPIO, },
216 { /* sentinel */ }
217};
218MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
219
182static int __devinit mxs_gpio_probe(struct platform_device *pdev) 220static int __devinit mxs_gpio_probe(struct platform_device *pdev)
183{ 221{
222 const struct of_device_id *of_id =
223 of_match_device(mxs_gpio_dt_ids, &pdev->dev);
224 struct device_node *np = pdev->dev.of_node;
225 struct device_node *parent;
184 static void __iomem *base; 226 static void __iomem *base;
185 struct mxs_gpio_port *port; 227 struct mxs_gpio_port *port;
186 struct resource *iores = NULL; 228 struct resource *iores = NULL;
187 int err; 229 int err;
188 230
189 port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); 231 port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
190 if (!port) 232 if (!port)
191 return -ENOMEM; 233 return -ENOMEM;
192 234
193 port->id = pdev->id; 235 if (np) {
236 port->id = of_alias_get_id(np, "gpio");
237 if (port->id < 0)
238 return port->id;
239 port->devid = (enum mxs_gpio_id) of_id->data;
240 } else {
241 port->id = pdev->id;
242 port->devid = pdev->id_entry->driver_data;
243 }
194 port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; 244 port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
195 245
246 port->irq = platform_get_irq(pdev, 0);
247 if (port->irq < 0)
248 return port->irq;
249
196 /* 250 /*
197 * map memory region only once, as all the gpio ports 251 * map memory region only once, as all the gpio ports
198 * share the same one 252 * share the same one
199 */ 253 */
200 if (!base) { 254 if (!base) {
201 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 255 if (np) {
202 if (!iores) { 256 parent = of_get_parent(np);
203 err = -ENODEV; 257 base = of_iomap(parent, 0);
204 goto out_kfree; 258 of_node_put(parent);
205 } 259 } else {
206 260 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
207 if (!request_mem_region(iores->start, resource_size(iores), 261 base = devm_request_and_ioremap(&pdev->dev, iores);
208 pdev->name)) {
209 err = -EBUSY;
210 goto out_kfree;
211 }
212
213 base = ioremap(iores->start, resource_size(iores));
214 if (!base) {
215 err = -ENOMEM;
216 goto out_release_mem;
217 } 262 }
263 if (!base)
264 return -EADDRNOTAVAIL;
218 } 265 }
219 port->base = base; 266 port->base = base;
220 267
221 port->irq = platform_get_irq(pdev, 0);
222 if (port->irq < 0) {
223 err = -EINVAL;
224 goto out_iounmap;
225 }
226
227 /* 268 /*
228 * select the pin interrupt functionality but initially 269 * select the pin interrupt functionality but initially
229 * disable the interrupts 270 * disable the interrupts
230 */ 271 */
231 writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id)); 272 writel(~0U, port->base + PINCTRL_PIN2IRQ(port));
232 writel(0, port->base + PINCTRL_IRQEN(port->id)); 273 writel(0, port->base + PINCTRL_IRQEN(port));
233 274
234 /* clear address has to be used to clear IRQSTAT bits */ 275 /* clear address has to be used to clear IRQSTAT bits */
235 writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); 276 writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
236 277
237 /* gpio-mxs can be a generic irq chip */ 278 /* gpio-mxs can be a generic irq chip */
238 mxs_gpio_init_gc(port); 279 mxs_gpio_init_gc(port);
@@ -242,41 +283,32 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
242 irq_set_handler_data(port->irq, port); 283 irq_set_handler_data(port->irq, port);
243 284
244 err = bgpio_init(&port->bgc, &pdev->dev, 4, 285 err = bgpio_init(&port->bgc, &pdev->dev, 4,
245 port->base + PINCTRL_DIN(port->id), 286 port->base + PINCTRL_DIN(port),
246 port->base + PINCTRL_DOUT(port->id), NULL, 287 port->base + PINCTRL_DOUT(port), NULL,
247 port->base + PINCTRL_DOE(port->id), NULL, 0); 288 port->base + PINCTRL_DOE(port), NULL, 0);
248 if (err) 289 if (err)
249 goto out_iounmap; 290 return err;
250 291
251 port->bgc.gc.to_irq = mxs_gpio_to_irq; 292 port->bgc.gc.to_irq = mxs_gpio_to_irq;
252 port->bgc.gc.base = port->id * 32; 293 port->bgc.gc.base = port->id * 32;
253 294
254 err = gpiochip_add(&port->bgc.gc); 295 err = gpiochip_add(&port->bgc.gc);
255 if (err) 296 if (err) {
256 goto out_bgpio_remove; 297 bgpio_remove(&port->bgc);
298 return err;
299 }
257 300
258 return 0; 301 return 0;
259
260out_bgpio_remove:
261 bgpio_remove(&port->bgc);
262out_iounmap:
263 if (iores)
264 iounmap(port->base);
265out_release_mem:
266 if (iores)
267 release_mem_region(iores->start, resource_size(iores));
268out_kfree:
269 kfree(port);
270 dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
271 return err;
272} 302}
273 303
274static struct platform_driver mxs_gpio_driver = { 304static struct platform_driver mxs_gpio_driver = {
275 .driver = { 305 .driver = {
276 .name = "gpio-mxs", 306 .name = "gpio-mxs",
277 .owner = THIS_MODULE, 307 .owner = THIS_MODULE,
308 .of_match_table = mxs_gpio_dt_ids,
278 }, 309 },
279 .probe = mxs_gpio_probe, 310 .probe = mxs_gpio_probe,
311 .id_table = mxs_gpio_ids,
280}; 312};
281 313
282static int __init mxs_gpio_init(void) 314static int __init mxs_gpio_init(void)