2 * gpiolib support for Wolfson Arizona class devices
4 * Copyright 2012 Wolfson Microelectronics PLC.
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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.
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
18 #include <linux/gpio.h>
19 #include <linux/platform_device.h>
20 #include <linux/seq_file.h>
22 #include <linux/mfd/arizona/core.h>
23 #include <linux/mfd/arizona/pdata.h>
24 #include <linux/mfd/arizona/registers.h>
27 struct arizona
*arizona
;
28 struct gpio_chip gpio_chip
;
31 static inline struct arizona_gpio
*to_arizona_gpio(struct gpio_chip
*chip
)
33 return container_of(chip
, struct arizona_gpio
, gpio_chip
);
36 static int arizona_gpio_direction_in(struct gpio_chip
*chip
, unsigned offset
)
38 struct arizona_gpio
*arizona_gpio
= to_arizona_gpio(chip
);
39 struct arizona
*arizona
= arizona_gpio
->arizona
;
41 return regmap_update_bits(arizona
->regmap
, ARIZONA_GPIO1_CTRL
+ offset
,
42 ARIZONA_GPN_DIR
, ARIZONA_GPN_DIR
);
45 static int arizona_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
47 struct arizona_gpio
*arizona_gpio
= to_arizona_gpio(chip
);
48 struct arizona
*arizona
= arizona_gpio
->arizona
;
52 ret
= regmap_read(arizona
->regmap
, ARIZONA_GPIO1_CTRL
+ offset
, &val
);
56 if (val
& ARIZONA_GPN_LVL
)
62 static int arizona_gpio_direction_out(struct gpio_chip
*chip
,
63 unsigned offset
, int value
)
65 struct arizona_gpio
*arizona_gpio
= to_arizona_gpio(chip
);
66 struct arizona
*arizona
= arizona_gpio
->arizona
;
69 value
= ARIZONA_GPN_LVL
;
71 return regmap_update_bits(arizona
->regmap
, ARIZONA_GPIO1_CTRL
+ offset
,
72 ARIZONA_GPN_DIR
| ARIZONA_GPN_LVL
, value
);
75 static void arizona_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
77 struct arizona_gpio
*arizona_gpio
= to_arizona_gpio(chip
);
78 struct arizona
*arizona
= arizona_gpio
->arizona
;
81 value
= ARIZONA_GPN_LVL
;
83 regmap_update_bits(arizona
->regmap
, ARIZONA_GPIO1_CTRL
+ offset
,
84 ARIZONA_GPN_LVL
, value
);
87 static struct gpio_chip template_chip
= {
90 .direction_input
= arizona_gpio_direction_in
,
91 .get
= arizona_gpio_get
,
92 .direction_output
= arizona_gpio_direction_out
,
93 .set
= arizona_gpio_set
,
97 static int arizona_gpio_probe(struct platform_device
*pdev
)
99 struct arizona
*arizona
= dev_get_drvdata(pdev
->dev
.parent
);
100 struct arizona_pdata
*pdata
= dev_get_platdata(arizona
->dev
);
101 struct arizona_gpio
*arizona_gpio
;
104 arizona_gpio
= devm_kzalloc(&pdev
->dev
, sizeof(*arizona_gpio
),
106 if (arizona_gpio
== NULL
)
109 arizona_gpio
->arizona
= arizona
;
110 arizona_gpio
->gpio_chip
= template_chip
;
111 arizona_gpio
->gpio_chip
.dev
= &pdev
->dev
;
112 #ifdef CONFIG_OF_GPIO
113 arizona_gpio
->gpio_chip
.of_node
= arizona
->dev
->of_node
;
116 switch (arizona
->type
) {
120 arizona_gpio
->gpio_chip
.ngpio
= 5;
123 dev_err(&pdev
->dev
, "Unknown chip variant %d\n",
128 if (pdata
&& pdata
->gpio_base
)
129 arizona_gpio
->gpio_chip
.base
= pdata
->gpio_base
;
131 arizona_gpio
->gpio_chip
.base
= -1;
133 ret
= gpiochip_add(&arizona_gpio
->gpio_chip
);
135 dev_err(&pdev
->dev
, "Could not register gpiochip, %d\n",
140 platform_set_drvdata(pdev
, arizona_gpio
);
148 static int arizona_gpio_remove(struct platform_device
*pdev
)
150 struct arizona_gpio
*arizona_gpio
= platform_get_drvdata(pdev
);
152 return gpiochip_remove(&arizona_gpio
->gpio_chip
);
155 static struct platform_driver arizona_gpio_driver
= {
156 .driver
.name
= "arizona-gpio",
157 .driver
.owner
= THIS_MODULE
,
158 .probe
= arizona_gpio_probe
,
159 .remove
= arizona_gpio_remove
,
162 module_platform_driver(arizona_gpio_driver
);
164 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
165 MODULE_DESCRIPTION("GPIO interface for Arizona devices");
166 MODULE_LICENSE("GPL");
167 MODULE_ALIAS("platform:arizona-gpio");