diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2012-12-15 17:50:46 -0500 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2013-01-24 19:24:21 -0500 |
commit | 6f6a4a683be97837f3baae443aacd2b0e6162b10 (patch) | |
tree | f1a3970e00dfd46df21769c11c7d795ebd192c25 /drivers/sh | |
parent | f9492fda70c87b410e61675095212dc806bdf615 (diff) |
sh-pfc: Merge PFC core and gpio
The PFC core calls the gpio module gpiochip registration in its
register_sh_pfc() function, itself called at arch initialization time.
If the gpio module isn't present then the gpiochip will never be
registered.
As the gpio module can only be present at arch initialization time if
it's builtin, there's no point in allowing to build it as a module. Make
it a boolean option, and initialize it synchronously with the core if
selected.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/pfc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/sh/pfc/Makefile | 4 | ||||
-rw-r--r-- | drivers/sh/pfc/core.c | 23 | ||||
-rw-r--r-- | drivers/sh/pfc/core.h | 4 | ||||
-rw-r--r-- | drivers/sh/pfc/gpio.c | 79 |
5 files changed, 25 insertions, 87 deletions
diff --git a/drivers/sh/pfc/Kconfig b/drivers/sh/pfc/Kconfig index f33d82a38b4b..eaeabc58bb06 100644 --- a/drivers/sh/pfc/Kconfig +++ b/drivers/sh/pfc/Kconfig | |||
@@ -11,7 +11,7 @@ config SH_PFC | |||
11 | def_bool y | 11 | def_bool y |
12 | 12 | ||
13 | config GPIO_SH_PFC | 13 | config GPIO_SH_PFC |
14 | tristate "SuperH PFC GPIO support" | 14 | bool "SuperH PFC GPIO support" |
15 | depends on SH_PFC && GPIOLIB | 15 | depends on SH_PFC && GPIOLIB |
16 | help | 16 | help |
17 | This enables support for GPIOs within the SoC's pin function | 17 | This enables support for GPIOs within the SoC's pin function |
diff --git a/drivers/sh/pfc/Makefile b/drivers/sh/pfc/Makefile index ce6fae353844..6315cf35b34d 100644 --- a/drivers/sh/pfc/Makefile +++ b/drivers/sh/pfc/Makefile | |||
@@ -1,3 +1,5 @@ | |||
1 | sh-pfc-objs = core.o pinctrl.o | 1 | sh-pfc-objs = core.o pinctrl.o |
2 | ifeq ($(CONFIG_GPIO_SH_PFC),y) | ||
3 | sh-pfc-objs += gpio.o | ||
4 | endif | ||
2 | obj-y += sh-pfc.o | 5 | obj-y += sh-pfc.o |
3 | obj-$(CONFIG_GPIO_SH_PFC) += gpio.o | ||
diff --git a/drivers/sh/pfc/core.c b/drivers/sh/pfc/core.c index 30e33db7a2dc..541099613a21 100644 --- a/drivers/sh/pfc/core.c +++ b/drivers/sh/pfc/core.c | |||
@@ -149,7 +149,6 @@ int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos) | |||
149 | 149 | ||
150 | return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1; | 150 | return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1; |
151 | } | 151 | } |
152 | EXPORT_SYMBOL_GPL(sh_pfc_read_bit); | ||
153 | 152 | ||
154 | void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, | 153 | void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, |
155 | unsigned long value) | 154 | unsigned long value) |
@@ -169,7 +168,6 @@ void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, | |||
169 | 168 | ||
170 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); | 169 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); |
171 | } | 170 | } |
172 | EXPORT_SYMBOL_GPL(sh_pfc_write_bit); | ||
173 | 171 | ||
174 | static void config_reg_helper(struct sh_pfc *pfc, | 172 | static void config_reg_helper(struct sh_pfc *pfc, |
175 | struct pinmux_cfg_reg *crp, | 173 | struct pinmux_cfg_reg *crp, |
@@ -307,7 +305,6 @@ int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio, | |||
307 | *bitp = n; | 305 | *bitp = n; |
308 | return 0; | 306 | return 0; |
309 | } | 307 | } |
310 | EXPORT_SYMBOL_GPL(sh_pfc_get_data_reg); | ||
311 | 308 | ||
312 | static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id, | 309 | static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id, |
313 | struct pinmux_cfg_reg **crp, | 310 | struct pinmux_cfg_reg **crp, |
@@ -384,7 +381,6 @@ int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos, | |||
384 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); | 381 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); |
385 | return -1; | 382 | return -1; |
386 | } | 383 | } |
387 | EXPORT_SYMBOL_GPL(sh_pfc_gpio_to_enum); | ||
388 | 384 | ||
389 | int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, | 385 | int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, |
390 | int cfg_mode) | 386 | int cfg_mode) |
@@ -500,7 +496,6 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, | |||
500 | 496 | ||
501 | int register_sh_pfc(struct sh_pfc_platform_data *pdata) | 497 | int register_sh_pfc(struct sh_pfc_platform_data *pdata) |
502 | { | 498 | { |
503 | int (*initroutine)(struct sh_pfc *) = NULL; | ||
504 | int ret; | 499 | int ret; |
505 | 500 | ||
506 | /* | 501 | /* |
@@ -531,24 +526,20 @@ int register_sh_pfc(struct sh_pfc_platform_data *pdata) | |||
531 | if (unlikely(ret != 0)) | 526 | if (unlikely(ret != 0)) |
532 | goto err; | 527 | goto err; |
533 | 528 | ||
529 | #ifdef CONFIG_GPIO_SH_PFC | ||
534 | /* | 530 | /* |
535 | * Then the GPIO chip | 531 | * Then the GPIO chip |
536 | */ | 532 | */ |
537 | initroutine = symbol_request(sh_pfc_register_gpiochip); | 533 | ret = sh_pfc_register_gpiochip(&sh_pfc); |
538 | if (initroutine) { | 534 | if (unlikely(ret != 0)) { |
539 | ret = (*initroutine)(&sh_pfc); | ||
540 | symbol_put_addr(initroutine); | ||
541 | |||
542 | /* | 535 | /* |
543 | * If the GPIO chip fails to come up we still leave the | 536 | * If the GPIO chip fails to come up we still leave the |
544 | * PFC state as it is, given that there are already | 537 | * PFC state as it is, given that there are already |
545 | * extant users of it that have succeeded by this point. | 538 | * extant users of it that have succeeded by this point. |
546 | */ | 539 | */ |
547 | if (unlikely(ret != 0)) { | 540 | pr_notice("failed to init GPIO chip, ignoring...\n"); |
548 | pr_notice("failed to init GPIO chip, ignoring...\n"); | ||
549 | ret = 0; | ||
550 | } | ||
551 | } | 541 | } |
542 | #endif | ||
552 | 543 | ||
553 | pr_info("%s support registered\n", sh_pfc.pdata->name); | 544 | pr_info("%s support registered\n", sh_pfc.pdata->name); |
554 | 545 | ||
@@ -560,3 +551,7 @@ err: | |||
560 | 551 | ||
561 | return ret; | 552 | return ret; |
562 | } | 553 | } |
554 | |||
555 | MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart"); | ||
556 | MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller"); | ||
557 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/sh/pfc/core.h b/drivers/sh/pfc/core.h index b07ae259c0eb..f3032b232fb0 100644 --- a/drivers/sh/pfc/core.h +++ b/drivers/sh/pfc/core.h | |||
@@ -20,14 +20,18 @@ struct pfc_window { | |||
20 | unsigned long size; | 20 | unsigned long size; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | struct sh_pfc_chip; | ||
24 | |||
23 | struct sh_pfc { | 25 | struct sh_pfc { |
24 | struct sh_pfc_platform_data *pdata; | 26 | struct sh_pfc_platform_data *pdata; |
25 | spinlock_t lock; | 27 | spinlock_t lock; |
26 | 28 | ||
27 | struct pfc_window *window; | 29 | struct pfc_window *window; |
30 | struct sh_pfc_chip *gpio; | ||
28 | }; | 31 | }; |
29 | 32 | ||
30 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc); | 33 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc); |
34 | int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc); | ||
31 | 35 | ||
32 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc); | 36 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc); |
33 | 37 | ||
diff --git a/drivers/sh/pfc/gpio.c b/drivers/sh/pfc/gpio.c index 565b366c909f..d8b0c74a950d 100644 --- a/drivers/sh/pfc/gpio.c +++ b/drivers/sh/pfc/gpio.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/pinctrl/consumer.h> | 18 | #include <linux/pinctrl/consumer.h> |
20 | #include <linux/sh_pfc.h> | 19 | #include <linux/sh_pfc.h> |
21 | 20 | ||
@@ -152,44 +151,23 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) | |||
152 | sh_pfc_gpio_setup(chip); | 151 | sh_pfc_gpio_setup(chip); |
153 | 152 | ||
154 | ret = gpiochip_add(&chip->gpio_chip); | 153 | ret = gpiochip_add(&chip->gpio_chip); |
155 | if (unlikely(ret < 0)) | 154 | if (unlikely(ret < 0)) { |
156 | kfree(chip); | 155 | kfree(chip); |
156 | return ret; | ||
157 | } | ||
158 | |||
159 | pfc->gpio = chip; | ||
157 | 160 | ||
158 | pr_info("%s handling gpio %d -> %d\n", | 161 | pr_info("%s handling gpio %d -> %d\n", |
159 | pfc->pdata->name, pfc->pdata->first_gpio, | 162 | pfc->pdata->name, pfc->pdata->first_gpio, |
160 | pfc->pdata->last_gpio); | 163 | pfc->pdata->last_gpio); |
161 | 164 | ||
162 | return ret; | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(sh_pfc_register_gpiochip); | ||
165 | |||
166 | static int sh_pfc_gpio_match(struct gpio_chip *gc, void *data) | ||
167 | { | ||
168 | return !!strstr(gc->label, data); | ||
169 | } | ||
170 | |||
171 | static int sh_pfc_gpio_probe(struct platform_device *pdev) | ||
172 | { | ||
173 | struct sh_pfc_chip *chip; | ||
174 | struct gpio_chip *gc; | ||
175 | |||
176 | gc = gpiochip_find("_pfc", sh_pfc_gpio_match); | ||
177 | if (unlikely(!gc)) { | ||
178 | pr_err("Cant find gpio chip\n"); | ||
179 | return -ENODEV; | ||
180 | } | ||
181 | |||
182 | chip = gpio_to_pfc_chip(gc); | ||
183 | platform_set_drvdata(pdev, chip); | ||
184 | |||
185 | pr_info("attaching to GPIO chip %s\n", chip->pfc->pdata->name); | ||
186 | |||
187 | return 0; | 165 | return 0; |
188 | } | 166 | } |
189 | 167 | ||
190 | static int sh_pfc_gpio_remove(struct platform_device *pdev) | 168 | int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc) |
191 | { | 169 | { |
192 | struct sh_pfc_chip *chip = platform_get_drvdata(pdev); | 170 | struct sh_pfc_chip *chip = pfc->gpio; |
193 | int ret; | 171 | int ret; |
194 | 172 | ||
195 | ret = gpiochip_remove(&chip->gpio_chip); | 173 | ret = gpiochip_remove(&chip->gpio_chip); |
@@ -197,47 +175,6 @@ static int sh_pfc_gpio_remove(struct platform_device *pdev) | |||
197 | return ret; | 175 | return ret; |
198 | 176 | ||
199 | kfree(chip); | 177 | kfree(chip); |
178 | pfc->gpio = NULL; | ||
200 | return 0; | 179 | return 0; |
201 | } | 180 | } |
202 | |||
203 | static struct platform_driver sh_pfc_gpio_driver = { | ||
204 | .probe = sh_pfc_gpio_probe, | ||
205 | .remove = sh_pfc_gpio_remove, | ||
206 | .driver = { | ||
207 | .name = KBUILD_MODNAME, | ||
208 | .owner = THIS_MODULE, | ||
209 | }, | ||
210 | }; | ||
211 | |||
212 | static struct platform_device sh_pfc_gpio_device = { | ||
213 | .name = KBUILD_MODNAME, | ||
214 | .id = -1, | ||
215 | }; | ||
216 | |||
217 | static int __init sh_pfc_gpio_init(void) | ||
218 | { | ||
219 | int rc; | ||
220 | |||
221 | rc = platform_driver_register(&sh_pfc_gpio_driver); | ||
222 | if (likely(!rc)) { | ||
223 | rc = platform_device_register(&sh_pfc_gpio_device); | ||
224 | if (unlikely(rc)) | ||
225 | platform_driver_unregister(&sh_pfc_gpio_driver); | ||
226 | } | ||
227 | |||
228 | return rc; | ||
229 | } | ||
230 | |||
231 | static void __exit sh_pfc_gpio_exit(void) | ||
232 | { | ||
233 | platform_device_unregister(&sh_pfc_gpio_device); | ||
234 | platform_driver_unregister(&sh_pfc_gpio_driver); | ||
235 | } | ||
236 | |||
237 | module_init(sh_pfc_gpio_init); | ||
238 | module_exit(sh_pfc_gpio_exit); | ||
239 | |||
240 | MODULE_AUTHOR("Magnus Damm, Paul Mundt"); | ||
241 | MODULE_DESCRIPTION("GPIO driver for SuperH pin function controller"); | ||
242 | MODULE_LICENSE("GPL v2"); | ||
243 | MODULE_ALIAS("platform:pfc-gpio"); | ||