diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-07-20 03:42:59 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-07-20 03:42:59 -0400 |
commit | 9ff561fdf73493d757bbc74aa58627e1381650fb (patch) | |
tree | 4484d230662126b1ac94ea545ca5429c91e0a68b /drivers/sh | |
parent | 7b98cf0cf4e8798b9e7435f966ed0d90a2a925de (diff) | |
parent | fdd85ec3eb8cc1b663678a3efa16ee59a32e0277 (diff) |
Merge branch 'common/pinctrl' into sh-latest
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/Kconfig | 16 | ||||
-rw-r--r-- | drivers/sh/Makefile | 4 | ||||
-rw-r--r-- | drivers/sh/pfc/Kconfig | 26 | ||||
-rw-r--r-- | drivers/sh/pfc/Makefile | 3 | ||||
-rw-r--r-- | drivers/sh/pfc/core.c (renamed from drivers/sh/pfc.c) | 86 | ||||
-rw-r--r-- | drivers/sh/pfc/gpio.c (renamed from drivers/sh/pfc-gpio.c) | 104 | ||||
-rw-r--r-- | drivers/sh/pfc/pinctrl.c | 530 |
7 files changed, 619 insertions, 150 deletions
diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig index d7dbfee1bc70..d860ef743568 100644 --- a/drivers/sh/Kconfig +++ b/drivers/sh/Kconfig | |||
@@ -1,20 +1,6 @@ | |||
1 | menu "SuperH / SH-Mobile Driver Options" | 1 | menu "SuperH / SH-Mobile Driver Options" |
2 | 2 | ||
3 | source "drivers/sh/intc/Kconfig" | 3 | source "drivers/sh/intc/Kconfig" |
4 | 4 | source "drivers/sh/pfc/Kconfig" | |
5 | comment "Pin function controller options" | ||
6 | |||
7 | config SH_PFC | ||
8 | # XXX move off the gpio dependency | ||
9 | depends on GENERIC_GPIO | ||
10 | select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB | ||
11 | def_bool y | ||
12 | |||
13 | config GPIO_SH_PFC | ||
14 | tristate "SuperH PFC GPIO support" | ||
15 | depends on SH_PFC && GPIOLIB | ||
16 | help | ||
17 | This enables support for GPIOs within the SoC's pin function | ||
18 | controller. | ||
19 | 5 | ||
20 | endmenu | 6 | endmenu |
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index f5d93e8de090..e57895b1a425 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
@@ -5,7 +5,7 @@ obj-y := intc/ | |||
5 | 5 | ||
6 | obj-$(CONFIG_HAVE_CLK) += clk/ | 6 | obj-$(CONFIG_HAVE_CLK) += clk/ |
7 | obj-$(CONFIG_MAPLE) += maple/ | 7 | obj-$(CONFIG_MAPLE) += maple/ |
8 | obj-$(CONFIG_SH_PFC) += pfc/ | ||
8 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 9 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
9 | obj-$(CONFIG_SH_PFC) += pfc.o | 10 | |
10 | obj-$(CONFIG_GPIO_SH_PFC) += pfc-gpio.o | ||
11 | obj-y += pm_runtime.o | 11 | obj-y += pm_runtime.o |
diff --git a/drivers/sh/pfc/Kconfig b/drivers/sh/pfc/Kconfig new file mode 100644 index 000000000000..804f9ad1bf4a --- /dev/null +++ b/drivers/sh/pfc/Kconfig | |||
@@ -0,0 +1,26 @@ | |||
1 | comment "Pin function controller options" | ||
2 | |||
3 | config SH_PFC | ||
4 | # XXX move off the gpio dependency | ||
5 | depends on GENERIC_GPIO | ||
6 | select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB | ||
7 | select PINCTRL_SH_PFC | ||
8 | def_bool y | ||
9 | |||
10 | # | ||
11 | # Placeholder for now, rehome to drivers/pinctrl once the PFC APIs | ||
12 | # have settled. | ||
13 | # | ||
14 | config PINCTRL_SH_PFC | ||
15 | tristate "SuperH PFC pin controller driver" | ||
16 | depends on SH_PFC | ||
17 | select PINCTRL | ||
18 | select PINMUX | ||
19 | select PINCONF | ||
20 | |||
21 | config GPIO_SH_PFC | ||
22 | tristate "SuperH PFC GPIO support" | ||
23 | depends on SH_PFC && GPIOLIB | ||
24 | help | ||
25 | This enables support for GPIOs within the SoC's pin function | ||
26 | controller. | ||
diff --git a/drivers/sh/pfc/Makefile b/drivers/sh/pfc/Makefile new file mode 100644 index 000000000000..7916027cce37 --- /dev/null +++ b/drivers/sh/pfc/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-y += core.o | ||
2 | obj-$(CONFIG_PINCTRL_SH_PFC) += pinctrl.o | ||
3 | obj-$(CONFIG_GPIO_SH_PFC) += gpio.o | ||
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc/core.c index ce4579ebd602..68169373c98b 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc/core.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
9 | * for more details. | 9 | * for more details. |
10 | */ | 10 | */ |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 11 | #define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt |
12 | 12 | ||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/pinctrl/machine.h> | ||
22 | 23 | ||
23 | static struct sh_pfc *sh_pfc __read_mostly; | 24 | static struct sh_pfc *sh_pfc __read_mostly; |
24 | 25 | ||
@@ -501,49 +502,6 @@ int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, | |||
501 | } | 502 | } |
502 | EXPORT_SYMBOL_GPL(sh_pfc_config_gpio); | 503 | EXPORT_SYMBOL_GPL(sh_pfc_config_gpio); |
503 | 504 | ||
504 | int sh_pfc_set_direction(struct sh_pfc *pfc, unsigned gpio, | ||
505 | int new_pinmux_type) | ||
506 | { | ||
507 | int pinmux_type; | ||
508 | int ret = -EINVAL; | ||
509 | |||
510 | if (!pfc) | ||
511 | goto err_out; | ||
512 | |||
513 | pinmux_type = pfc->gpios[gpio].flags & PINMUX_FLAG_TYPE; | ||
514 | |||
515 | switch (pinmux_type) { | ||
516 | case PINMUX_TYPE_GPIO: | ||
517 | break; | ||
518 | case PINMUX_TYPE_OUTPUT: | ||
519 | case PINMUX_TYPE_INPUT: | ||
520 | case PINMUX_TYPE_INPUT_PULLUP: | ||
521 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
522 | sh_pfc_config_gpio(pfc, gpio, pinmux_type, GPIO_CFG_FREE); | ||
523 | break; | ||
524 | default: | ||
525 | goto err_out; | ||
526 | } | ||
527 | |||
528 | if (sh_pfc_config_gpio(pfc, gpio, | ||
529 | new_pinmux_type, | ||
530 | GPIO_CFG_DRYRUN) != 0) | ||
531 | goto err_out; | ||
532 | |||
533 | if (sh_pfc_config_gpio(pfc, gpio, | ||
534 | new_pinmux_type, | ||
535 | GPIO_CFG_REQ) != 0) | ||
536 | BUG(); | ||
537 | |||
538 | pfc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; | ||
539 | pfc->gpios[gpio].flags |= new_pinmux_type; | ||
540 | |||
541 | ret = 0; | ||
542 | err_out: | ||
543 | return ret; | ||
544 | } | ||
545 | EXPORT_SYMBOL_GPL(sh_pfc_set_direction); | ||
546 | |||
547 | int register_sh_pfc(struct sh_pfc *pfc) | 505 | int register_sh_pfc(struct sh_pfc *pfc) |
548 | { | 506 | { |
549 | int (*initroutine)(struct sh_pfc *) = NULL; | 507 | int (*initroutine)(struct sh_pfc *) = NULL; |
@@ -563,16 +521,52 @@ int register_sh_pfc(struct sh_pfc *pfc) | |||
563 | 521 | ||
564 | spin_lock_init(&pfc->lock); | 522 | spin_lock_init(&pfc->lock); |
565 | 523 | ||
524 | pinctrl_provide_dummies(); | ||
566 | setup_data_regs(pfc); | 525 | setup_data_regs(pfc); |
567 | 526 | ||
568 | sh_pfc = pfc; | 527 | sh_pfc = pfc; |
569 | pr_info("%s support registered\n", pfc->name); | ||
570 | 528 | ||
529 | /* | ||
530 | * Initialize pinctrl bindings first | ||
531 | */ | ||
532 | initroutine = symbol_request(sh_pfc_register_pinctrl); | ||
533 | if (initroutine) { | ||
534 | ret = (*initroutine)(pfc); | ||
535 | symbol_put_addr(initroutine); | ||
536 | |||
537 | if (unlikely(ret != 0)) | ||
538 | goto err; | ||
539 | } else { | ||
540 | pr_err("failed to initialize pinctrl bindings\n"); | ||
541 | goto err; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * Then the GPIO chip | ||
546 | */ | ||
571 | initroutine = symbol_request(sh_pfc_register_gpiochip); | 547 | initroutine = symbol_request(sh_pfc_register_gpiochip); |
572 | if (initroutine) { | 548 | if (initroutine) { |
573 | (*initroutine)(pfc); | 549 | ret = (*initroutine)(pfc); |
574 | symbol_put_addr(initroutine); | 550 | symbol_put_addr(initroutine); |
551 | |||
552 | /* | ||
553 | * If the GPIO chip fails to come up we still leave the | ||
554 | * PFC state as it is, given that there are already | ||
555 | * extant users of it that have succeeded by this point. | ||
556 | */ | ||
557 | if (unlikely(ret != 0)) { | ||
558 | pr_notice("failed to init GPIO chip, ignoring...\n"); | ||
559 | ret = 0; | ||
560 | } | ||
575 | } | 561 | } |
576 | 562 | ||
563 | pr_info("%s support registered\n", pfc->name); | ||
564 | |||
577 | return 0; | 565 | return 0; |
566 | |||
567 | err: | ||
568 | pfc_iounmap(pfc); | ||
569 | sh_pfc = NULL; | ||
570 | |||
571 | return ret; | ||
578 | } | 572 | } |
diff --git a/drivers/sh/pfc-gpio.c b/drivers/sh/pfc/gpio.c index d74e5a96024b..62bca98474a9 100644 --- a/drivers/sh/pfc-gpio.c +++ b/drivers/sh/pfc/gpio.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
9 | * for more details. | 9 | * for more details. |
10 | */ | 10 | */ |
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 11 | #define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
@@ -16,6 +16,7 @@ | |||
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> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/pinctrl/consumer.h> | ||
19 | 20 | ||
20 | struct sh_pfc_chip { | 21 | struct sh_pfc_chip { |
21 | struct sh_pfc *pfc; | 22 | struct sh_pfc *pfc; |
@@ -34,80 +35,12 @@ static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc) | |||
34 | 35 | ||
35 | static int sh_gpio_request(struct gpio_chip *gc, unsigned offset) | 36 | static int sh_gpio_request(struct gpio_chip *gc, unsigned offset) |
36 | { | 37 | { |
37 | struct sh_pfc *pfc = gpio_to_pfc(gc); | 38 | return pinctrl_request_gpio(offset); |
38 | struct pinmux_data_reg *dummy; | ||
39 | unsigned long flags; | ||
40 | int i, ret, pinmux_type; | ||
41 | |||
42 | ret = -EINVAL; | ||
43 | |||
44 | if (!pfc) | ||
45 | goto err_out; | ||
46 | |||
47 | spin_lock_irqsave(&pfc->lock, flags); | ||
48 | |||
49 | if ((pfc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) | ||
50 | goto err_unlock; | ||
51 | |||
52 | /* setup pin function here if no data is associated with pin */ | ||
53 | |||
54 | if (sh_pfc_get_data_reg(pfc, offset, &dummy, &i) != 0) | ||
55 | pinmux_type = PINMUX_TYPE_FUNCTION; | ||
56 | else | ||
57 | pinmux_type = PINMUX_TYPE_GPIO; | ||
58 | |||
59 | if (pinmux_type == PINMUX_TYPE_FUNCTION) { | ||
60 | if (sh_pfc_config_gpio(pfc, offset, | ||
61 | pinmux_type, | ||
62 | GPIO_CFG_DRYRUN) != 0) | ||
63 | goto err_unlock; | ||
64 | |||
65 | if (sh_pfc_config_gpio(pfc, offset, | ||
66 | pinmux_type, | ||
67 | GPIO_CFG_REQ) != 0) | ||
68 | BUG(); | ||
69 | } | ||
70 | |||
71 | pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
72 | pfc->gpios[offset].flags |= pinmux_type; | ||
73 | |||
74 | ret = 0; | ||
75 | err_unlock: | ||
76 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
77 | err_out: | ||
78 | return ret; | ||
79 | } | 39 | } |
80 | 40 | ||
81 | static void sh_gpio_free(struct gpio_chip *gc, unsigned offset) | 41 | static void sh_gpio_free(struct gpio_chip *gc, unsigned offset) |
82 | { | 42 | { |
83 | struct sh_pfc *pfc = gpio_to_pfc(gc); | 43 | pinctrl_free_gpio(offset); |
84 | unsigned long flags; | ||
85 | int pinmux_type; | ||
86 | |||
87 | if (!pfc) | ||
88 | return; | ||
89 | |||
90 | spin_lock_irqsave(&pfc->lock, flags); | ||
91 | |||
92 | pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
93 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
94 | pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
95 | pfc->gpios[offset].flags |= PINMUX_TYPE_NONE; | ||
96 | |||
97 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
98 | } | ||
99 | |||
100 | static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
101 | { | ||
102 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
103 | unsigned long flags; | ||
104 | int ret; | ||
105 | |||
106 | spin_lock_irqsave(&pfc->lock, flags); | ||
107 | ret = sh_pfc_set_direction(pfc, offset, PINMUX_TYPE_INPUT); | ||
108 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
109 | |||
110 | return ret; | ||
111 | } | 44 | } |
112 | 45 | ||
113 | static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value) | 46 | static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value) |
@@ -121,22 +54,6 @@ static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value) | |||
121 | sh_pfc_write_bit(dr, bit, value); | 54 | sh_pfc_write_bit(dr, bit, value); |
122 | } | 55 | } |
123 | 56 | ||
124 | static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | ||
125 | int value) | ||
126 | { | ||
127 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
128 | unsigned long flags; | ||
129 | int ret; | ||
130 | |||
131 | sh_gpio_set_value(pfc, offset, value); | ||
132 | |||
133 | spin_lock_irqsave(&pfc->lock, flags); | ||
134 | ret = sh_pfc_set_direction(pfc, offset, PINMUX_TYPE_OUTPUT); | ||
135 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio) | 57 | static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio) |
141 | { | 58 | { |
142 | struct pinmux_data_reg *dr = NULL; | 59 | struct pinmux_data_reg *dr = NULL; |
@@ -148,6 +65,19 @@ static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio) | |||
148 | return sh_pfc_read_bit(dr, bit); | 65 | return sh_pfc_read_bit(dr, bit); |
149 | } | 66 | } |
150 | 67 | ||
68 | static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
69 | { | ||
70 | return pinctrl_gpio_direction_input(offset); | ||
71 | } | ||
72 | |||
73 | static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | ||
74 | int value) | ||
75 | { | ||
76 | sh_gpio_set_value(gpio_to_pfc(gc), offset, value); | ||
77 | |||
78 | return pinctrl_gpio_direction_output(offset); | ||
79 | } | ||
80 | |||
151 | static int sh_gpio_get(struct gpio_chip *gc, unsigned offset) | 81 | static int sh_gpio_get(struct gpio_chip *gc, unsigned offset) |
152 | { | 82 | { |
153 | return sh_gpio_get_value(gpio_to_pfc(gc), offset); | 83 | return sh_gpio_get_value(gpio_to_pfc(gc), offset); |
diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c new file mode 100644 index 000000000000..0802b6c0d653 --- /dev/null +++ b/drivers/sh/pfc/pinctrl.c | |||
@@ -0,0 +1,530 @@ | |||
1 | /* | ||
2 | * SuperH Pin Function Controller pinmux support. | ||
3 | * | ||
4 | * Copyright (C) 2012 Paul Mundt | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | #define DRV_NAME "pinctrl-sh_pfc" | ||
11 | |||
12 | #define pr_fmt(fmt) DRV_NAME " " KBUILD_MODNAME ": " fmt | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/sh_pfc.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pinctrl/consumer.h> | ||
22 | #include <linux/pinctrl/pinctrl.h> | ||
23 | #include <linux/pinctrl/pinconf.h> | ||
24 | #include <linux/pinctrl/pinmux.h> | ||
25 | #include <linux/pinctrl/pinconf-generic.h> | ||
26 | |||
27 | struct sh_pfc_pinctrl { | ||
28 | struct pinctrl_dev *pctl; | ||
29 | struct sh_pfc *pfc; | ||
30 | |||
31 | struct pinmux_gpio **functions; | ||
32 | unsigned int nr_functions; | ||
33 | |||
34 | struct pinctrl_pin_desc *pads; | ||
35 | unsigned int nr_pads; | ||
36 | |||
37 | spinlock_t lock; | ||
38 | }; | ||
39 | |||
40 | static struct sh_pfc_pinctrl *sh_pfc_pmx; | ||
41 | |||
42 | static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) | ||
43 | { | ||
44 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
45 | |||
46 | return pmx->nr_pads; | ||
47 | } | ||
48 | |||
49 | static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, | ||
50 | unsigned selector) | ||
51 | { | ||
52 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
53 | |||
54 | return pmx->pads[selector].name; | ||
55 | } | ||
56 | |||
57 | static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group, | ||
58 | const unsigned **pins, unsigned *num_pins) | ||
59 | { | ||
60 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
61 | |||
62 | *pins = &pmx->pads[group].number; | ||
63 | *num_pins = 1; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, | ||
69 | unsigned offset) | ||
70 | { | ||
71 | seq_printf(s, "%s", DRV_NAME); | ||
72 | } | ||
73 | |||
74 | static struct pinctrl_ops sh_pfc_pinctrl_ops = { | ||
75 | .get_groups_count = sh_pfc_get_groups_count, | ||
76 | .get_group_name = sh_pfc_get_group_name, | ||
77 | .get_group_pins = sh_pfc_get_group_pins, | ||
78 | .pin_dbg_show = sh_pfc_pin_dbg_show, | ||
79 | }; | ||
80 | |||
81 | static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev) | ||
82 | { | ||
83 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
84 | |||
85 | return pmx->nr_functions; | ||
86 | } | ||
87 | |||
88 | static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, | ||
89 | unsigned selector) | ||
90 | { | ||
91 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
92 | |||
93 | return pmx->functions[selector]->name; | ||
94 | } | ||
95 | |||
96 | static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func, | ||
97 | const char * const **groups, | ||
98 | unsigned * const num_groups) | ||
99 | { | ||
100 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
101 | |||
102 | *groups = &pmx->functions[func]->name; | ||
103 | *num_groups = 1; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func, | ||
109 | unsigned group) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func, | ||
115 | unsigned group) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | static inline int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset) | ||
120 | { | ||
121 | if (sh_pfc_config_gpio(pfc, offset, | ||
122 | PINMUX_TYPE_FUNCTION, | ||
123 | GPIO_CFG_DRYRUN) != 0) | ||
124 | return -EINVAL; | ||
125 | |||
126 | if (sh_pfc_config_gpio(pfc, offset, | ||
127 | PINMUX_TYPE_FUNCTION, | ||
128 | GPIO_CFG_REQ) != 0) | ||
129 | return -EINVAL; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset, | ||
135 | int new_type) | ||
136 | { | ||
137 | unsigned long flags; | ||
138 | int pinmux_type; | ||
139 | int ret = -EINVAL; | ||
140 | |||
141 | spin_lock_irqsave(&pfc->lock, flags); | ||
142 | |||
143 | pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
144 | |||
145 | /* | ||
146 | * See if the present config needs to first be de-configured. | ||
147 | */ | ||
148 | switch (pinmux_type) { | ||
149 | case PINMUX_TYPE_GPIO: | ||
150 | break; | ||
151 | case PINMUX_TYPE_OUTPUT: | ||
152 | case PINMUX_TYPE_INPUT: | ||
153 | case PINMUX_TYPE_INPUT_PULLUP: | ||
154 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
155 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
156 | break; | ||
157 | default: | ||
158 | goto err; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Dry run | ||
163 | */ | ||
164 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
165 | GPIO_CFG_DRYRUN) != 0) | ||
166 | goto err; | ||
167 | |||
168 | /* | ||
169 | * Request | ||
170 | */ | ||
171 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
172 | GPIO_CFG_REQ) != 0) | ||
173 | goto err; | ||
174 | |||
175 | pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
176 | pfc->gpios[offset].flags |= new_type; | ||
177 | |||
178 | ret = 0; | ||
179 | |||
180 | err: | ||
181 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
182 | |||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | |||
187 | static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, | ||
188 | struct pinctrl_gpio_range *range, | ||
189 | unsigned offset) | ||
190 | { | ||
191 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
192 | struct sh_pfc *pfc = pmx->pfc; | ||
193 | unsigned long flags; | ||
194 | int ret, pinmux_type; | ||
195 | |||
196 | spin_lock_irqsave(&pfc->lock, flags); | ||
197 | |||
198 | pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
199 | |||
200 | switch (pinmux_type) { | ||
201 | case PINMUX_TYPE_FUNCTION: | ||
202 | pr_notice_once("Use of GPIO API for function requests is " | ||
203 | "deprecated, convert to pinctrl\n"); | ||
204 | /* handle for now */ | ||
205 | ret = sh_pfc_config_function(pfc, offset); | ||
206 | if (unlikely(ret < 0)) | ||
207 | goto err; | ||
208 | |||
209 | break; | ||
210 | case PINMUX_TYPE_GPIO: | ||
211 | break; | ||
212 | default: | ||
213 | pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); | ||
214 | return -ENOTSUPP; | ||
215 | } | ||
216 | |||
217 | ret = 0; | ||
218 | |||
219 | err: | ||
220 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
221 | |||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev, | ||
226 | struct pinctrl_gpio_range *range, | ||
227 | unsigned offset) | ||
228 | { | ||
229 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
230 | struct sh_pfc *pfc = pmx->pfc; | ||
231 | unsigned long flags; | ||
232 | int pinmux_type; | ||
233 | |||
234 | spin_lock_irqsave(&pfc->lock, flags); | ||
235 | |||
236 | pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
237 | |||
238 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
239 | |||
240 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
241 | } | ||
242 | |||
243 | static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
244 | struct pinctrl_gpio_range *range, | ||
245 | unsigned offset, bool input) | ||
246 | { | ||
247 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
248 | int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT; | ||
249 | |||
250 | return sh_pfc_reconfig_pin(pmx->pfc, offset, type); | ||
251 | } | ||
252 | |||
253 | static struct pinmux_ops sh_pfc_pinmux_ops = { | ||
254 | .get_functions_count = sh_pfc_get_functions_count, | ||
255 | .get_function_name = sh_pfc_get_function_name, | ||
256 | .get_function_groups = sh_pfc_get_function_groups, | ||
257 | .enable = sh_pfc_noop_enable, | ||
258 | .disable = sh_pfc_noop_disable, | ||
259 | .gpio_request_enable = sh_pfc_gpio_request_enable, | ||
260 | .gpio_disable_free = sh_pfc_gpio_disable_free, | ||
261 | .gpio_set_direction = sh_pfc_gpio_set_direction, | ||
262 | }; | ||
263 | |||
264 | static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, | ||
265 | unsigned long *config) | ||
266 | { | ||
267 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
268 | struct sh_pfc *pfc = pmx->pfc; | ||
269 | |||
270 | *config = pfc->gpios[pin].flags & PINMUX_FLAG_TYPE; | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, | ||
276 | unsigned long config) | ||
277 | { | ||
278 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
279 | struct sh_pfc *pfc = pmx->pfc; | ||
280 | |||
281 | /* Validate the new type */ | ||
282 | if (config >= PINMUX_FLAG_TYPE) | ||
283 | return -EINVAL; | ||
284 | |||
285 | return sh_pfc_reconfig_pin(pmx->pfc, pin, config); | ||
286 | } | ||
287 | |||
288 | static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev, | ||
289 | struct seq_file *s, unsigned pin) | ||
290 | { | ||
291 | const char *pinmux_type_str[] = { | ||
292 | [PINMUX_TYPE_NONE] = "none", | ||
293 | [PINMUX_TYPE_FUNCTION] = "function", | ||
294 | [PINMUX_TYPE_GPIO] = "gpio", | ||
295 | [PINMUX_TYPE_OUTPUT] = "output", | ||
296 | [PINMUX_TYPE_INPUT] = "input", | ||
297 | [PINMUX_TYPE_INPUT_PULLUP] = "input bias pull up", | ||
298 | [PINMUX_TYPE_INPUT_PULLDOWN] = "input bias pull down", | ||
299 | }; | ||
300 | unsigned long config; | ||
301 | int rc; | ||
302 | |||
303 | rc = sh_pfc_pinconf_get(pctldev, pin, &config); | ||
304 | if (unlikely(rc != 0)) | ||
305 | return; | ||
306 | |||
307 | seq_printf(s, " %s", pinmux_type_str[config]); | ||
308 | } | ||
309 | |||
310 | static struct pinconf_ops sh_pfc_pinconf_ops = { | ||
311 | .pin_config_get = sh_pfc_pinconf_get, | ||
312 | .pin_config_set = sh_pfc_pinconf_set, | ||
313 | .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, | ||
314 | }; | ||
315 | |||
316 | static struct pinctrl_gpio_range sh_pfc_gpio_range = { | ||
317 | .name = DRV_NAME, | ||
318 | .id = 0, | ||
319 | }; | ||
320 | |||
321 | static struct pinctrl_desc sh_pfc_pinctrl_desc = { | ||
322 | .name = DRV_NAME, | ||
323 | .owner = THIS_MODULE, | ||
324 | .pctlops = &sh_pfc_pinctrl_ops, | ||
325 | .pmxops = &sh_pfc_pinmux_ops, | ||
326 | .confops = &sh_pfc_pinconf_ops, | ||
327 | }; | ||
328 | |||
329 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | ||
330 | { | ||
331 | sh_pfc_pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL); | ||
332 | if (unlikely(!sh_pfc_pmx)) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | spin_lock_init(&sh_pfc_pmx->lock); | ||
336 | |||
337 | sh_pfc_pmx->pfc = pfc; | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | EXPORT_SYMBOL_GPL(sh_pfc_register_pinctrl); | ||
342 | |||
343 | static inline void __devinit sh_pfc_map_one_gpio(struct sh_pfc *pfc, | ||
344 | struct sh_pfc_pinctrl *pmx, | ||
345 | struct pinmux_gpio *gpio, | ||
346 | unsigned offset) | ||
347 | { | ||
348 | struct pinmux_data_reg *dummy; | ||
349 | unsigned long flags; | ||
350 | int bit; | ||
351 | |||
352 | gpio->flags &= ~PINMUX_FLAG_TYPE; | ||
353 | |||
354 | if (sh_pfc_get_data_reg(pfc, offset, &dummy, &bit) == 0) | ||
355 | gpio->flags |= PINMUX_TYPE_GPIO; | ||
356 | else { | ||
357 | gpio->flags |= PINMUX_TYPE_FUNCTION; | ||
358 | |||
359 | spin_lock_irqsave(&pmx->lock, flags); | ||
360 | pmx->nr_functions++; | ||
361 | spin_unlock_irqrestore(&pmx->lock, flags); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* pinmux ranges -> pinctrl pin descs */ | ||
366 | static int __devinit sh_pfc_map_gpios(struct sh_pfc *pfc, | ||
367 | struct sh_pfc_pinctrl *pmx) | ||
368 | { | ||
369 | unsigned long flags; | ||
370 | int i; | ||
371 | |||
372 | pmx->nr_pads = pfc->last_gpio - pfc->first_gpio + 1; | ||
373 | |||
374 | pmx->pads = kmalloc(sizeof(struct pinctrl_pin_desc) * pmx->nr_pads, | ||
375 | GFP_KERNEL); | ||
376 | if (unlikely(!pmx->pads)) { | ||
377 | pmx->nr_pads = 0; | ||
378 | return -ENOMEM; | ||
379 | } | ||
380 | |||
381 | spin_lock_irqsave(&pfc->lock, flags); | ||
382 | |||
383 | /* | ||
384 | * We don't necessarily have a 1:1 mapping between pin and linux | ||
385 | * GPIO number, as the latter maps to the associated enum_id. | ||
386 | * Care needs to be taken to translate back to pin space when | ||
387 | * dealing with any pin configurations. | ||
388 | */ | ||
389 | for (i = 0; i < pmx->nr_pads; i++) { | ||
390 | struct pinctrl_pin_desc *pin = pmx->pads + i; | ||
391 | struct pinmux_gpio *gpio = pfc->gpios + i; | ||
392 | |||
393 | pin->number = pfc->first_gpio + i; | ||
394 | pin->name = gpio->name; | ||
395 | |||
396 | /* XXX */ | ||
397 | if (unlikely(!gpio->enum_id)) | ||
398 | continue; | ||
399 | |||
400 | sh_pfc_map_one_gpio(pfc, pmx, gpio, i); | ||
401 | } | ||
402 | |||
403 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
404 | |||
405 | sh_pfc_pinctrl_desc.pins = pmx->pads; | ||
406 | sh_pfc_pinctrl_desc.npins = pmx->nr_pads; | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int __devinit sh_pfc_map_functions(struct sh_pfc *pfc, | ||
412 | struct sh_pfc_pinctrl *pmx) | ||
413 | { | ||
414 | unsigned long flags; | ||
415 | int i, fn; | ||
416 | |||
417 | pmx->functions = kzalloc(pmx->nr_functions * sizeof(void *), | ||
418 | GFP_KERNEL); | ||
419 | if (unlikely(!pmx->functions)) | ||
420 | return -ENOMEM; | ||
421 | |||
422 | spin_lock_irqsave(&pmx->lock, flags); | ||
423 | |||
424 | for (i = fn = 0; i < pmx->nr_pads; i++) { | ||
425 | struct pinmux_gpio *gpio = pfc->gpios + i; | ||
426 | |||
427 | if ((gpio->flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_FUNCTION) | ||
428 | pmx->functions[fn++] = gpio; | ||
429 | } | ||
430 | |||
431 | spin_unlock_irqrestore(&pmx->lock, flags); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int __devinit sh_pfc_pinctrl_probe(struct platform_device *pdev) | ||
437 | { | ||
438 | struct sh_pfc *pfc; | ||
439 | int ret; | ||
440 | |||
441 | if (unlikely(!sh_pfc_pmx)) | ||
442 | return -ENODEV; | ||
443 | |||
444 | pfc = sh_pfc_pmx->pfc; | ||
445 | |||
446 | ret = sh_pfc_map_gpios(pfc, sh_pfc_pmx); | ||
447 | if (unlikely(ret != 0)) | ||
448 | return ret; | ||
449 | |||
450 | ret = sh_pfc_map_functions(pfc, sh_pfc_pmx); | ||
451 | if (unlikely(ret != 0)) | ||
452 | goto free_pads; | ||
453 | |||
454 | sh_pfc_pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, &pdev->dev, | ||
455 | sh_pfc_pmx); | ||
456 | if (IS_ERR(sh_pfc_pmx->pctl)) { | ||
457 | ret = PTR_ERR(sh_pfc_pmx->pctl); | ||
458 | goto free_functions; | ||
459 | } | ||
460 | |||
461 | sh_pfc_gpio_range.npins = pfc->last_gpio - pfc->first_gpio + 1; | ||
462 | sh_pfc_gpio_range.base = pfc->first_gpio; | ||
463 | sh_pfc_gpio_range.pin_base = pfc->first_gpio; | ||
464 | |||
465 | pinctrl_add_gpio_range(sh_pfc_pmx->pctl, &sh_pfc_gpio_range); | ||
466 | |||
467 | platform_set_drvdata(pdev, sh_pfc_pmx); | ||
468 | |||
469 | return 0; | ||
470 | |||
471 | free_functions: | ||
472 | kfree(sh_pfc_pmx->functions); | ||
473 | free_pads: | ||
474 | kfree(sh_pfc_pmx->pads); | ||
475 | kfree(sh_pfc_pmx); | ||
476 | |||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | static int __devexit sh_pfc_pinctrl_remove(struct platform_device *pdev) | ||
481 | { | ||
482 | struct sh_pfc_pinctrl *pmx = platform_get_drvdata(pdev); | ||
483 | |||
484 | pinctrl_remove_gpio_range(pmx->pctl, &sh_pfc_gpio_range); | ||
485 | pinctrl_unregister(pmx->pctl); | ||
486 | |||
487 | platform_set_drvdata(pdev, NULL); | ||
488 | |||
489 | kfree(sh_pfc_pmx->functions); | ||
490 | kfree(sh_pfc_pmx->pads); | ||
491 | kfree(sh_pfc_pmx); | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static struct platform_driver sh_pfc_pinctrl_driver = { | ||
497 | .probe = sh_pfc_pinctrl_probe, | ||
498 | .remove = __devexit_p(sh_pfc_pinctrl_remove), | ||
499 | .driver = { | ||
500 | .name = DRV_NAME, | ||
501 | .owner = THIS_MODULE, | ||
502 | }, | ||
503 | }; | ||
504 | |||
505 | static struct platform_device sh_pfc_pinctrl_device = { | ||
506 | .name = DRV_NAME, | ||
507 | .id = -1, | ||
508 | }; | ||
509 | |||
510 | static int __init sh_pfc_pinctrl_init(void) | ||
511 | { | ||
512 | int rc; | ||
513 | |||
514 | rc = platform_driver_register(&sh_pfc_pinctrl_driver); | ||
515 | if (likely(!rc)) { | ||
516 | rc = platform_device_register(&sh_pfc_pinctrl_device); | ||
517 | if (unlikely(rc)) | ||
518 | platform_driver_unregister(&sh_pfc_pinctrl_driver); | ||
519 | } | ||
520 | |||
521 | return rc; | ||
522 | } | ||
523 | |||
524 | static void __exit sh_pfc_pinctrl_exit(void) | ||
525 | { | ||
526 | platform_driver_unregister(&sh_pfc_pinctrl_driver); | ||
527 | } | ||
528 | |||
529 | subsys_initcall(sh_pfc_pinctrl_init); | ||
530 | module_exit(sh_pfc_pinctrl_exit); | ||