diff options
-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"); | ||