diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-06-21 00:44:42 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-06-21 00:44:42 -0400 |
commit | 7b98cf0cf4e8798b9e7435f966ed0d90a2a925de (patch) | |
tree | a5d2a80f121a5c854773ddc85b1d9cbd6b840861 /drivers/sh | |
parent | e1eaf354528ceb002c8e2840a55c44cd76aaaed8 (diff) | |
parent | 06d5631f56460917af3d9417ef63811cf0cad9ce (diff) |
Merge branch 'common/pfc' into sh-latest
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/Kconfig | 15 | ||||
-rw-r--r-- | drivers/sh/Makefile | 3 | ||||
-rw-r--r-- | drivers/sh/pfc-gpio.c | 309 | ||||
-rw-r--r-- | drivers/sh/pfc.c | 379 |
4 files changed, 435 insertions, 271 deletions
diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig index f168a6159961..d7dbfee1bc70 100644 --- a/drivers/sh/Kconfig +++ b/drivers/sh/Kconfig | |||
@@ -2,4 +2,19 @@ menu "SuperH / SH-Mobile Driver Options" | |||
2 | 2 | ||
3 | source "drivers/sh/intc/Kconfig" | 3 | source "drivers/sh/intc/Kconfig" |
4 | 4 | ||
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 | endmenu | 20 | endmenu |
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 7139ad2f2086..f5d93e8de090 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
@@ -6,5 +6,6 @@ obj-y := intc/ | |||
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_SUPERHYWAY) += superhyway/ | 8 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
9 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 9 | obj-$(CONFIG_SH_PFC) += pfc.o |
10 | obj-$(CONFIG_GPIO_SH_PFC) += pfc-gpio.o | ||
10 | obj-y += pm_runtime.o | 11 | obj-y += pm_runtime.o |
diff --git a/drivers/sh/pfc-gpio.c b/drivers/sh/pfc-gpio.c new file mode 100644 index 000000000000..d74e5a96024b --- /dev/null +++ b/drivers/sh/pfc-gpio.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * SuperH Pin Function Controller GPIO driver. | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * Copyright (C) 2009 - 2012 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | struct sh_pfc_chip { | ||
21 | struct sh_pfc *pfc; | ||
22 | struct gpio_chip gpio_chip; | ||
23 | }; | ||
24 | |||
25 | static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc) | ||
26 | { | ||
27 | return container_of(gc, struct sh_pfc_chip, gpio_chip); | ||
28 | } | ||
29 | |||
30 | static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc) | ||
31 | { | ||
32 | return gpio_to_pfc_chip(gc)->pfc; | ||
33 | } | ||
34 | |||
35 | static int sh_gpio_request(struct gpio_chip *gc, unsigned offset) | ||
36 | { | ||
37 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
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 | } | ||
80 | |||
81 | static void sh_gpio_free(struct gpio_chip *gc, unsigned offset) | ||
82 | { | ||
83 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
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 | } | ||
112 | |||
113 | static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value) | ||
114 | { | ||
115 | struct pinmux_data_reg *dr = NULL; | ||
116 | int bit = 0; | ||
117 | |||
118 | if (!pfc || sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0) | ||
119 | BUG(); | ||
120 | else | ||
121 | sh_pfc_write_bit(dr, bit, value); | ||
122 | } | ||
123 | |||
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) | ||
141 | { | ||
142 | struct pinmux_data_reg *dr = NULL; | ||
143 | int bit = 0; | ||
144 | |||
145 | if (!pfc || sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0) | ||
146 | return -EINVAL; | ||
147 | |||
148 | return sh_pfc_read_bit(dr, bit); | ||
149 | } | ||
150 | |||
151 | static int sh_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
152 | { | ||
153 | return sh_gpio_get_value(gpio_to_pfc(gc), offset); | ||
154 | } | ||
155 | |||
156 | static void sh_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | ||
157 | { | ||
158 | sh_gpio_set_value(gpio_to_pfc(gc), offset, value); | ||
159 | } | ||
160 | |||
161 | static int sh_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
162 | { | ||
163 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
164 | pinmux_enum_t enum_id; | ||
165 | pinmux_enum_t *enum_ids; | ||
166 | int i, k, pos; | ||
167 | |||
168 | pos = 0; | ||
169 | enum_id = 0; | ||
170 | while (1) { | ||
171 | pos = sh_pfc_gpio_to_enum(pfc, offset, pos, &enum_id); | ||
172 | if (pos <= 0 || !enum_id) | ||
173 | break; | ||
174 | |||
175 | for (i = 0; i < pfc->gpio_irq_size; i++) { | ||
176 | enum_ids = pfc->gpio_irq[i].enum_ids; | ||
177 | for (k = 0; enum_ids[k]; k++) { | ||
178 | if (enum_ids[k] == enum_id) | ||
179 | return pfc->gpio_irq[i].irq; | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | return -ENOSYS; | ||
185 | } | ||
186 | |||
187 | static void sh_pfc_gpio_setup(struct sh_pfc_chip *chip) | ||
188 | { | ||
189 | struct sh_pfc *pfc = chip->pfc; | ||
190 | struct gpio_chip *gc = &chip->gpio_chip; | ||
191 | |||
192 | gc->request = sh_gpio_request; | ||
193 | gc->free = sh_gpio_free; | ||
194 | gc->direction_input = sh_gpio_direction_input; | ||
195 | gc->get = sh_gpio_get; | ||
196 | gc->direction_output = sh_gpio_direction_output; | ||
197 | gc->set = sh_gpio_set; | ||
198 | gc->to_irq = sh_gpio_to_irq; | ||
199 | |||
200 | WARN_ON(pfc->first_gpio != 0); /* needs testing */ | ||
201 | |||
202 | gc->label = pfc->name; | ||
203 | gc->owner = THIS_MODULE; | ||
204 | gc->base = pfc->first_gpio; | ||
205 | gc->ngpio = (pfc->last_gpio - pfc->first_gpio) + 1; | ||
206 | } | ||
207 | |||
208 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc) | ||
209 | { | ||
210 | struct sh_pfc_chip *chip; | ||
211 | int ret; | ||
212 | |||
213 | chip = kzalloc(sizeof(struct sh_pfc_chip), GFP_KERNEL); | ||
214 | if (unlikely(!chip)) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | chip->pfc = pfc; | ||
218 | |||
219 | sh_pfc_gpio_setup(chip); | ||
220 | |||
221 | ret = gpiochip_add(&chip->gpio_chip); | ||
222 | if (unlikely(ret < 0)) | ||
223 | kfree(chip); | ||
224 | |||
225 | pr_info("%s handling gpio %d -> %d\n", | ||
226 | pfc->name, pfc->first_gpio, pfc->last_gpio); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | EXPORT_SYMBOL_GPL(sh_pfc_register_gpiochip); | ||
231 | |||
232 | static int sh_pfc_gpio_match(struct gpio_chip *gc, void *data) | ||
233 | { | ||
234 | return !!strstr(gc->label, data); | ||
235 | } | ||
236 | |||
237 | static int __devinit sh_pfc_gpio_probe(struct platform_device *pdev) | ||
238 | { | ||
239 | struct sh_pfc_chip *chip; | ||
240 | struct gpio_chip *gc; | ||
241 | |||
242 | gc = gpiochip_find("_pfc", sh_pfc_gpio_match); | ||
243 | if (unlikely(!gc)) { | ||
244 | pr_err("Cant find gpio chip\n"); | ||
245 | return -ENODEV; | ||
246 | } | ||
247 | |||
248 | chip = gpio_to_pfc_chip(gc); | ||
249 | platform_set_drvdata(pdev, chip); | ||
250 | |||
251 | pr_info("attaching to GPIO chip %s\n", chip->pfc->name); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static int __devexit sh_pfc_gpio_remove(struct platform_device *pdev) | ||
257 | { | ||
258 | struct sh_pfc_chip *chip = platform_get_drvdata(pdev); | ||
259 | int ret; | ||
260 | |||
261 | ret = gpiochip_remove(&chip->gpio_chip); | ||
262 | if (unlikely(ret < 0)) | ||
263 | return ret; | ||
264 | |||
265 | kfree(chip); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct platform_driver sh_pfc_gpio_driver = { | ||
270 | .probe = sh_pfc_gpio_probe, | ||
271 | .remove = __devexit_p(sh_pfc_gpio_remove), | ||
272 | .driver = { | ||
273 | .name = KBUILD_MODNAME, | ||
274 | .owner = THIS_MODULE, | ||
275 | }, | ||
276 | }; | ||
277 | |||
278 | static struct platform_device sh_pfc_gpio_device = { | ||
279 | .name = KBUILD_MODNAME, | ||
280 | .id = -1, | ||
281 | }; | ||
282 | |||
283 | static int __init sh_pfc_gpio_init(void) | ||
284 | { | ||
285 | int rc; | ||
286 | |||
287 | rc = platform_driver_register(&sh_pfc_gpio_driver); | ||
288 | if (likely(!rc)) { | ||
289 | rc = platform_device_register(&sh_pfc_gpio_device); | ||
290 | if (unlikely(rc)) | ||
291 | platform_driver_unregister(&sh_pfc_gpio_driver); | ||
292 | } | ||
293 | |||
294 | return rc; | ||
295 | } | ||
296 | |||
297 | static void __exit sh_pfc_gpio_exit(void) | ||
298 | { | ||
299 | platform_device_unregister(&sh_pfc_gpio_device); | ||
300 | platform_driver_unregister(&sh_pfc_gpio_driver); | ||
301 | } | ||
302 | |||
303 | module_init(sh_pfc_gpio_init); | ||
304 | module_exit(sh_pfc_gpio_exit); | ||
305 | |||
306 | MODULE_AUTHOR("Magnus Damm, Paul Mundt"); | ||
307 | MODULE_DESCRIPTION("GPIO driver for SuperH pin function controller"); | ||
308 | MODULE_LICENSE("GPL v2"); | ||
309 | MODULE_ALIAS("platform:pfc-gpio"); | ||
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c index 522c6c46d1be..ce4579ebd602 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Pinmuxed GPIO support for SuperH. | 2 | * SuperH Pin Function Controller support. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Magnus Damm | 4 | * Copyright (C) 2008 Magnus Damm |
5 | * Copyright (C) 2009 - 2012 Paul Mundt | ||
5 | * | 6 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * 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 | * License. See the file "COPYING" in the main directory of this archive |
@@ -11,70 +12,74 @@ | |||
11 | 12 | ||
12 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/list.h> | 15 | #include <linux/sh_pfc.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/clk.h> | ||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/irq.h> | ||
20 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
21 | #include <linux/gpio.h> | ||
22 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
23 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
24 | 22 | ||
25 | static void pfc_iounmap(struct pinmux_info *pip) | 23 | static struct sh_pfc *sh_pfc __read_mostly; |
24 | |||
25 | static inline bool sh_pfc_initialized(void) | ||
26 | { | ||
27 | return !!sh_pfc; | ||
28 | } | ||
29 | |||
30 | static void pfc_iounmap(struct sh_pfc *pfc) | ||
26 | { | 31 | { |
27 | int k; | 32 | int k; |
28 | 33 | ||
29 | for (k = 0; k < pip->num_resources; k++) | 34 | for (k = 0; k < pfc->num_resources; k++) |
30 | if (pip->window[k].virt) | 35 | if (pfc->window[k].virt) |
31 | iounmap(pip->window[k].virt); | 36 | iounmap(pfc->window[k].virt); |
32 | 37 | ||
33 | kfree(pip->window); | 38 | kfree(pfc->window); |
34 | pip->window = NULL; | 39 | pfc->window = NULL; |
35 | } | 40 | } |
36 | 41 | ||
37 | static int pfc_ioremap(struct pinmux_info *pip) | 42 | static int pfc_ioremap(struct sh_pfc *pfc) |
38 | { | 43 | { |
39 | struct resource *res; | 44 | struct resource *res; |
40 | int k; | 45 | int k; |
41 | 46 | ||
42 | if (!pip->num_resources) | 47 | if (!pfc->num_resources) |
43 | return 0; | 48 | return 0; |
44 | 49 | ||
45 | pip->window = kzalloc(pip->num_resources * sizeof(*pip->window), | 50 | pfc->window = kzalloc(pfc->num_resources * sizeof(*pfc->window), |
46 | GFP_NOWAIT); | 51 | GFP_NOWAIT); |
47 | if (!pip->window) | 52 | if (!pfc->window) |
48 | goto err1; | 53 | goto err1; |
49 | 54 | ||
50 | for (k = 0; k < pip->num_resources; k++) { | 55 | for (k = 0; k < pfc->num_resources; k++) { |
51 | res = pip->resource + k; | 56 | res = pfc->resource + k; |
52 | WARN_ON(resource_type(res) != IORESOURCE_MEM); | 57 | WARN_ON(resource_type(res) != IORESOURCE_MEM); |
53 | pip->window[k].phys = res->start; | 58 | pfc->window[k].phys = res->start; |
54 | pip->window[k].size = resource_size(res); | 59 | pfc->window[k].size = resource_size(res); |
55 | pip->window[k].virt = ioremap_nocache(res->start, | 60 | pfc->window[k].virt = ioremap_nocache(res->start, |
56 | resource_size(res)); | 61 | resource_size(res)); |
57 | if (!pip->window[k].virt) | 62 | if (!pfc->window[k].virt) |
58 | goto err2; | 63 | goto err2; |
59 | } | 64 | } |
60 | 65 | ||
61 | return 0; | 66 | return 0; |
62 | 67 | ||
63 | err2: | 68 | err2: |
64 | pfc_iounmap(pip); | 69 | pfc_iounmap(pfc); |
65 | err1: | 70 | err1: |
66 | return -1; | 71 | return -1; |
67 | } | 72 | } |
68 | 73 | ||
69 | static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip, | 74 | static void __iomem *pfc_phys_to_virt(struct sh_pfc *pfc, |
70 | unsigned long address) | 75 | unsigned long address) |
71 | { | 76 | { |
72 | struct pfc_window *window; | 77 | struct pfc_window *window; |
73 | int k; | 78 | int k; |
74 | 79 | ||
75 | /* scan through physical windows and convert address */ | 80 | /* scan through physical windows and convert address */ |
76 | for (k = 0; k < pip->num_resources; k++) { | 81 | for (k = 0; k < pfc->num_resources; k++) { |
77 | window = pip->window + k; | 82 | window = pfc->window + k; |
78 | 83 | ||
79 | if (address < window->phys) | 84 | if (address < window->phys) |
80 | continue; | 85 | continue; |
@@ -135,8 +140,7 @@ static void gpio_write_raw_reg(void __iomem *mapped_reg, | |||
135 | BUG(); | 140 | BUG(); |
136 | } | 141 | } |
137 | 142 | ||
138 | static int gpio_read_bit(struct pinmux_data_reg *dr, | 143 | int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos) |
139 | unsigned long in_pos) | ||
140 | { | 144 | { |
141 | unsigned long pos; | 145 | unsigned long pos; |
142 | 146 | ||
@@ -147,9 +151,10 @@ static int gpio_read_bit(struct pinmux_data_reg *dr, | |||
147 | 151 | ||
148 | return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1; | 152 | return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1; |
149 | } | 153 | } |
154 | EXPORT_SYMBOL_GPL(sh_pfc_read_bit); | ||
150 | 155 | ||
151 | static void gpio_write_bit(struct pinmux_data_reg *dr, | 156 | void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, |
152 | unsigned long in_pos, unsigned long value) | 157 | unsigned long value) |
153 | { | 158 | { |
154 | unsigned long pos; | 159 | unsigned long pos; |
155 | 160 | ||
@@ -166,8 +171,9 @@ static void gpio_write_bit(struct pinmux_data_reg *dr, | |||
166 | 171 | ||
167 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); | 172 | gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); |
168 | } | 173 | } |
174 | EXPORT_SYMBOL_GPL(sh_pfc_write_bit); | ||
169 | 175 | ||
170 | static void config_reg_helper(struct pinmux_info *gpioc, | 176 | static void config_reg_helper(struct sh_pfc *pfc, |
171 | struct pinmux_cfg_reg *crp, | 177 | struct pinmux_cfg_reg *crp, |
172 | unsigned long in_pos, | 178 | unsigned long in_pos, |
173 | void __iomem **mapped_regp, | 179 | void __iomem **mapped_regp, |
@@ -176,7 +182,7 @@ static void config_reg_helper(struct pinmux_info *gpioc, | |||
176 | { | 182 | { |
177 | int k; | 183 | int k; |
178 | 184 | ||
179 | *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg); | 185 | *mapped_regp = pfc_phys_to_virt(pfc, crp->reg); |
180 | 186 | ||
181 | if (crp->field_width) { | 187 | if (crp->field_width) { |
182 | *maskp = (1 << crp->field_width) - 1; | 188 | *maskp = (1 << crp->field_width) - 1; |
@@ -189,14 +195,14 @@ static void config_reg_helper(struct pinmux_info *gpioc, | |||
189 | } | 195 | } |
190 | } | 196 | } |
191 | 197 | ||
192 | static int read_config_reg(struct pinmux_info *gpioc, | 198 | static int read_config_reg(struct sh_pfc *pfc, |
193 | struct pinmux_cfg_reg *crp, | 199 | struct pinmux_cfg_reg *crp, |
194 | unsigned long field) | 200 | unsigned long field) |
195 | { | 201 | { |
196 | void __iomem *mapped_reg; | 202 | void __iomem *mapped_reg; |
197 | unsigned long mask, pos; | 203 | unsigned long mask, pos; |
198 | 204 | ||
199 | config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos); | 205 | config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos); |
200 | 206 | ||
201 | pr_debug("read_reg: addr = %lx, field = %ld, " | 207 | pr_debug("read_reg: addr = %lx, field = %ld, " |
202 | "r_width = %ld, f_width = %ld\n", | 208 | "r_width = %ld, f_width = %ld\n", |
@@ -205,14 +211,14 @@ static int read_config_reg(struct pinmux_info *gpioc, | |||
205 | return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask; | 211 | return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask; |
206 | } | 212 | } |
207 | 213 | ||
208 | static void write_config_reg(struct pinmux_info *gpioc, | 214 | static void write_config_reg(struct sh_pfc *pfc, |
209 | struct pinmux_cfg_reg *crp, | 215 | struct pinmux_cfg_reg *crp, |
210 | unsigned long field, unsigned long value) | 216 | unsigned long field, unsigned long value) |
211 | { | 217 | { |
212 | void __iomem *mapped_reg; | 218 | void __iomem *mapped_reg; |
213 | unsigned long mask, pos, data; | 219 | unsigned long mask, pos, data; |
214 | 220 | ||
215 | config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos); | 221 | config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos); |
216 | 222 | ||
217 | pr_debug("write_reg addr = %lx, value = %ld, field = %ld, " | 223 | pr_debug("write_reg addr = %lx, value = %ld, field = %ld, " |
218 | "r_width = %ld, f_width = %ld\n", | 224 | "r_width = %ld, f_width = %ld\n", |
@@ -225,30 +231,30 @@ static void write_config_reg(struct pinmux_info *gpioc, | |||
225 | data &= mask; | 231 | data &= mask; |
226 | data |= value; | 232 | data |= value; |
227 | 233 | ||
228 | if (gpioc->unlock_reg) | 234 | if (pfc->unlock_reg) |
229 | gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg), | 235 | gpio_write_raw_reg(pfc_phys_to_virt(pfc, pfc->unlock_reg), |
230 | 32, ~data); | 236 | 32, ~data); |
231 | 237 | ||
232 | gpio_write_raw_reg(mapped_reg, crp->reg_width, data); | 238 | gpio_write_raw_reg(mapped_reg, crp->reg_width, data); |
233 | } | 239 | } |
234 | 240 | ||
235 | static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) | 241 | static int setup_data_reg(struct sh_pfc *pfc, unsigned gpio) |
236 | { | 242 | { |
237 | struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; | 243 | struct pinmux_gpio *gpiop = &pfc->gpios[gpio]; |
238 | struct pinmux_data_reg *data_reg; | 244 | struct pinmux_data_reg *data_reg; |
239 | int k, n; | 245 | int k, n; |
240 | 246 | ||
241 | if (!enum_in_range(gpiop->enum_id, &gpioc->data)) | 247 | if (!enum_in_range(gpiop->enum_id, &pfc->data)) |
242 | return -1; | 248 | return -1; |
243 | 249 | ||
244 | k = 0; | 250 | k = 0; |
245 | while (1) { | 251 | while (1) { |
246 | data_reg = gpioc->data_regs + k; | 252 | data_reg = pfc->data_regs + k; |
247 | 253 | ||
248 | if (!data_reg->reg_width) | 254 | if (!data_reg->reg_width) |
249 | break; | 255 | break; |
250 | 256 | ||
251 | data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg); | 257 | data_reg->mapped_reg = pfc_phys_to_virt(pfc, data_reg->reg); |
252 | 258 | ||
253 | for (n = 0; n < data_reg->reg_width; n++) { | 259 | for (n = 0; n < data_reg->reg_width; n++) { |
254 | if (data_reg->enum_ids[n] == gpiop->enum_id) { | 260 | if (data_reg->enum_ids[n] == gpiop->enum_id) { |
@@ -267,17 +273,17 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) | |||
267 | return -1; | 273 | return -1; |
268 | } | 274 | } |
269 | 275 | ||
270 | static void setup_data_regs(struct pinmux_info *gpioc) | 276 | static void setup_data_regs(struct sh_pfc *pfc) |
271 | { | 277 | { |
272 | struct pinmux_data_reg *drp; | 278 | struct pinmux_data_reg *drp; |
273 | int k; | 279 | int k; |
274 | 280 | ||
275 | for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++) | 281 | for (k = pfc->first_gpio; k <= pfc->last_gpio; k++) |
276 | setup_data_reg(gpioc, k); | 282 | setup_data_reg(pfc, k); |
277 | 283 | ||
278 | k = 0; | 284 | k = 0; |
279 | while (1) { | 285 | while (1) { |
280 | drp = gpioc->data_regs + k; | 286 | drp = pfc->data_regs + k; |
281 | 287 | ||
282 | if (!drp->reg_width) | 288 | if (!drp->reg_width) |
283 | break; | 289 | break; |
@@ -288,23 +294,24 @@ static void setup_data_regs(struct pinmux_info *gpioc) | |||
288 | } | 294 | } |
289 | } | 295 | } |
290 | 296 | ||
291 | static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, | 297 | int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio, |
292 | struct pinmux_data_reg **drp, int *bitp) | 298 | struct pinmux_data_reg **drp, int *bitp) |
293 | { | 299 | { |
294 | struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; | 300 | struct pinmux_gpio *gpiop = &pfc->gpios[gpio]; |
295 | int k, n; | 301 | int k, n; |
296 | 302 | ||
297 | if (!enum_in_range(gpiop->enum_id, &gpioc->data)) | 303 | if (!enum_in_range(gpiop->enum_id, &pfc->data)) |
298 | return -1; | 304 | return -1; |
299 | 305 | ||
300 | k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; | 306 | k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; |
301 | n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; | 307 | n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; |
302 | *drp = gpioc->data_regs + k; | 308 | *drp = pfc->data_regs + k; |
303 | *bitp = n; | 309 | *bitp = n; |
304 | return 0; | 310 | return 0; |
305 | } | 311 | } |
312 | EXPORT_SYMBOL_GPL(sh_pfc_get_data_reg); | ||
306 | 313 | ||
307 | static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, | 314 | static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id, |
308 | struct pinmux_cfg_reg **crp, | 315 | struct pinmux_cfg_reg **crp, |
309 | int *fieldp, int *valuep, | 316 | int *fieldp, int *valuep, |
310 | unsigned long **cntp) | 317 | unsigned long **cntp) |
@@ -315,7 +322,7 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, | |||
315 | 322 | ||
316 | k = 0; | 323 | k = 0; |
317 | while (1) { | 324 | while (1) { |
318 | config_reg = gpioc->cfg_regs + k; | 325 | config_reg = pfc->cfg_regs + k; |
319 | 326 | ||
320 | r_width = config_reg->reg_width; | 327 | r_width = config_reg->reg_width; |
321 | f_width = config_reg->field_width; | 328 | f_width = config_reg->field_width; |
@@ -350,15 +357,15 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, | |||
350 | return -1; | 357 | return -1; |
351 | } | 358 | } |
352 | 359 | ||
353 | static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, | 360 | int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos, |
354 | int pos, pinmux_enum_t *enum_idp) | 361 | pinmux_enum_t *enum_idp) |
355 | { | 362 | { |
356 | pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; | 363 | pinmux_enum_t enum_id = pfc->gpios[gpio].enum_id; |
357 | pinmux_enum_t *data = gpioc->gpio_data; | 364 | pinmux_enum_t *data = pfc->gpio_data; |
358 | int k; | 365 | int k; |
359 | 366 | ||
360 | if (!enum_in_range(enum_id, &gpioc->data)) { | 367 | if (!enum_in_range(enum_id, &pfc->data)) { |
361 | if (!enum_in_range(enum_id, &gpioc->mark)) { | 368 | if (!enum_in_range(enum_id, &pfc->mark)) { |
362 | pr_err("non data/mark enum_id for gpio %d\n", gpio); | 369 | pr_err("non data/mark enum_id for gpio %d\n", gpio); |
363 | return -1; | 370 | return -1; |
364 | } | 371 | } |
@@ -369,7 +376,7 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, | |||
369 | return pos + 1; | 376 | return pos + 1; |
370 | } | 377 | } |
371 | 378 | ||
372 | for (k = 0; k < gpioc->gpio_data_size; k++) { | 379 | for (k = 0; k < pfc->gpio_data_size; k++) { |
373 | if (data[k] == enum_id) { | 380 | if (data[k] == enum_id) { |
374 | *enum_idp = data[k + 1]; | 381 | *enum_idp = data[k + 1]; |
375 | return k + 1; | 382 | return k + 1; |
@@ -379,11 +386,10 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, | |||
379 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); | 386 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); |
380 | return -1; | 387 | return -1; |
381 | } | 388 | } |
389 | EXPORT_SYMBOL_GPL(sh_pfc_gpio_to_enum); | ||
382 | 390 | ||
383 | enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; | 391 | int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, |
384 | 392 | int cfg_mode) | |
385 | static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | ||
386 | int pinmux_type, int cfg_mode) | ||
387 | { | 393 | { |
388 | struct pinmux_cfg_reg *cr = NULL; | 394 | struct pinmux_cfg_reg *cr = NULL; |
389 | pinmux_enum_t enum_id; | 395 | pinmux_enum_t enum_id; |
@@ -398,19 +404,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
398 | break; | 404 | break; |
399 | 405 | ||
400 | case PINMUX_TYPE_OUTPUT: | 406 | case PINMUX_TYPE_OUTPUT: |
401 | range = &gpioc->output; | 407 | range = &pfc->output; |
402 | break; | 408 | break; |
403 | 409 | ||
404 | case PINMUX_TYPE_INPUT: | 410 | case PINMUX_TYPE_INPUT: |
405 | range = &gpioc->input; | 411 | range = &pfc->input; |
406 | break; | 412 | break; |
407 | 413 | ||
408 | case PINMUX_TYPE_INPUT_PULLUP: | 414 | case PINMUX_TYPE_INPUT_PULLUP: |
409 | range = &gpioc->input_pu; | 415 | range = &pfc->input_pu; |
410 | break; | 416 | break; |
411 | 417 | ||
412 | case PINMUX_TYPE_INPUT_PULLDOWN: | 418 | case PINMUX_TYPE_INPUT_PULLDOWN: |
413 | range = &gpioc->input_pd; | 419 | range = &pfc->input_pd; |
414 | break; | 420 | break; |
415 | 421 | ||
416 | default: | 422 | default: |
@@ -422,7 +428,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
422 | field = 0; | 428 | field = 0; |
423 | value = 0; | 429 | value = 0; |
424 | while (1) { | 430 | while (1) { |
425 | pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); | 431 | pos = sh_pfc_gpio_to_enum(pfc, gpio, pos, &enum_id); |
426 | if (pos <= 0) | 432 | if (pos <= 0) |
427 | goto out_err; | 433 | goto out_err; |
428 | 434 | ||
@@ -430,7 +436,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
430 | break; | 436 | break; |
431 | 437 | ||
432 | /* first check if this is a function enum */ | 438 | /* first check if this is a function enum */ |
433 | in_range = enum_in_range(enum_id, &gpioc->function); | 439 | in_range = enum_in_range(enum_id, &pfc->function); |
434 | if (!in_range) { | 440 | if (!in_range) { |
435 | /* not a function enum */ | 441 | /* not a function enum */ |
436 | if (range) { | 442 | if (range) { |
@@ -467,19 +473,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
467 | if (!in_range) | 473 | if (!in_range) |
468 | continue; | 474 | continue; |
469 | 475 | ||
470 | if (get_config_reg(gpioc, enum_id, &cr, | 476 | if (get_config_reg(pfc, enum_id, &cr, |
471 | &field, &value, &cntp) != 0) | 477 | &field, &value, &cntp) != 0) |
472 | goto out_err; | 478 | goto out_err; |
473 | 479 | ||
474 | switch (cfg_mode) { | 480 | switch (cfg_mode) { |
475 | case GPIO_CFG_DRYRUN: | 481 | case GPIO_CFG_DRYRUN: |
476 | if (!*cntp || | 482 | if (!*cntp || |
477 | (read_config_reg(gpioc, cr, field) != value)) | 483 | (read_config_reg(pfc, cr, field) != value)) |
478 | continue; | 484 | continue; |
479 | break; | 485 | break; |
480 | 486 | ||
481 | case GPIO_CFG_REQ: | 487 | case GPIO_CFG_REQ: |
482 | write_config_reg(gpioc, cr, field, value); | 488 | write_config_reg(pfc, cr, field, value); |
483 | *cntp = *cntp + 1; | 489 | *cntp = *cntp + 1; |
484 | break; | 490 | break; |
485 | 491 | ||
@@ -493,89 +499,18 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, | |||
493 | out_err: | 499 | out_err: |
494 | return -1; | 500 | return -1; |
495 | } | 501 | } |
502 | EXPORT_SYMBOL_GPL(sh_pfc_config_gpio); | ||
496 | 503 | ||
497 | static DEFINE_SPINLOCK(gpio_lock); | 504 | int sh_pfc_set_direction(struct sh_pfc *pfc, unsigned gpio, |
498 | 505 | int new_pinmux_type) | |
499 | static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip) | ||
500 | { | ||
501 | return container_of(chip, struct pinmux_info, chip); | ||
502 | } | ||
503 | |||
504 | static int sh_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
505 | { | ||
506 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
507 | struct pinmux_data_reg *dummy; | ||
508 | unsigned long flags; | ||
509 | int i, ret, pinmux_type; | ||
510 | |||
511 | ret = -EINVAL; | ||
512 | |||
513 | if (!gpioc) | ||
514 | goto err_out; | ||
515 | |||
516 | spin_lock_irqsave(&gpio_lock, flags); | ||
517 | |||
518 | if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) | ||
519 | goto err_unlock; | ||
520 | |||
521 | /* setup pin function here if no data is associated with pin */ | ||
522 | |||
523 | if (get_data_reg(gpioc, offset, &dummy, &i) != 0) | ||
524 | pinmux_type = PINMUX_TYPE_FUNCTION; | ||
525 | else | ||
526 | pinmux_type = PINMUX_TYPE_GPIO; | ||
527 | |||
528 | if (pinmux_type == PINMUX_TYPE_FUNCTION) { | ||
529 | if (pinmux_config_gpio(gpioc, offset, | ||
530 | pinmux_type, | ||
531 | GPIO_CFG_DRYRUN) != 0) | ||
532 | goto err_unlock; | ||
533 | |||
534 | if (pinmux_config_gpio(gpioc, offset, | ||
535 | pinmux_type, | ||
536 | GPIO_CFG_REQ) != 0) | ||
537 | BUG(); | ||
538 | } | ||
539 | |||
540 | gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
541 | gpioc->gpios[offset].flags |= pinmux_type; | ||
542 | |||
543 | ret = 0; | ||
544 | err_unlock: | ||
545 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
546 | err_out: | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | static void sh_gpio_free(struct gpio_chip *chip, unsigned offset) | ||
551 | { | ||
552 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
553 | unsigned long flags; | ||
554 | int pinmux_type; | ||
555 | |||
556 | if (!gpioc) | ||
557 | return; | ||
558 | |||
559 | spin_lock_irqsave(&gpio_lock, flags); | ||
560 | |||
561 | pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
562 | pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE); | ||
563 | gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
564 | gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE; | ||
565 | |||
566 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
567 | } | ||
568 | |||
569 | static int pinmux_direction(struct pinmux_info *gpioc, | ||
570 | unsigned gpio, int new_pinmux_type) | ||
571 | { | 506 | { |
572 | int pinmux_type; | 507 | int pinmux_type; |
573 | int ret = -EINVAL; | 508 | int ret = -EINVAL; |
574 | 509 | ||
575 | if (!gpioc) | 510 | if (!pfc) |
576 | goto err_out; | 511 | goto err_out; |
577 | 512 | ||
578 | pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; | 513 | pinmux_type = pfc->gpios[gpio].flags & PINMUX_FLAG_TYPE; |
579 | 514 | ||
580 | switch (pinmux_type) { | 515 | switch (pinmux_type) { |
581 | case PINMUX_TYPE_GPIO: | 516 | case PINMUX_TYPE_GPIO: |
@@ -584,156 +519,60 @@ static int pinmux_direction(struct pinmux_info *gpioc, | |||
584 | case PINMUX_TYPE_INPUT: | 519 | case PINMUX_TYPE_INPUT: |
585 | case PINMUX_TYPE_INPUT_PULLUP: | 520 | case PINMUX_TYPE_INPUT_PULLUP: |
586 | case PINMUX_TYPE_INPUT_PULLDOWN: | 521 | case PINMUX_TYPE_INPUT_PULLDOWN: |
587 | pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); | 522 | sh_pfc_config_gpio(pfc, gpio, pinmux_type, GPIO_CFG_FREE); |
588 | break; | 523 | break; |
589 | default: | 524 | default: |
590 | goto err_out; | 525 | goto err_out; |
591 | } | 526 | } |
592 | 527 | ||
593 | if (pinmux_config_gpio(gpioc, gpio, | 528 | if (sh_pfc_config_gpio(pfc, gpio, |
594 | new_pinmux_type, | 529 | new_pinmux_type, |
595 | GPIO_CFG_DRYRUN) != 0) | 530 | GPIO_CFG_DRYRUN) != 0) |
596 | goto err_out; | 531 | goto err_out; |
597 | 532 | ||
598 | if (pinmux_config_gpio(gpioc, gpio, | 533 | if (sh_pfc_config_gpio(pfc, gpio, |
599 | new_pinmux_type, | 534 | new_pinmux_type, |
600 | GPIO_CFG_REQ) != 0) | 535 | GPIO_CFG_REQ) != 0) |
601 | BUG(); | 536 | BUG(); |
602 | 537 | ||
603 | gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; | 538 | pfc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; |
604 | gpioc->gpios[gpio].flags |= new_pinmux_type; | 539 | pfc->gpios[gpio].flags |= new_pinmux_type; |
605 | 540 | ||
606 | ret = 0; | 541 | ret = 0; |
607 | err_out: | 542 | err_out: |
608 | return ret; | 543 | return ret; |
609 | } | 544 | } |
545 | EXPORT_SYMBOL_GPL(sh_pfc_set_direction); | ||
610 | 546 | ||
611 | static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 547 | int register_sh_pfc(struct sh_pfc *pfc) |
612 | { | ||
613 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
614 | unsigned long flags; | ||
615 | int ret; | ||
616 | |||
617 | spin_lock_irqsave(&gpio_lock, flags); | ||
618 | ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT); | ||
619 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | static void sh_gpio_set_value(struct pinmux_info *gpioc, | ||
625 | unsigned gpio, int value) | ||
626 | { | ||
627 | struct pinmux_data_reg *dr = NULL; | ||
628 | int bit = 0; | ||
629 | |||
630 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) | ||
631 | BUG(); | ||
632 | else | ||
633 | gpio_write_bit(dr, bit, value); | ||
634 | } | ||
635 | |||
636 | static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
637 | int value) | ||
638 | { | 548 | { |
639 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | 549 | int (*initroutine)(struct sh_pfc *) = NULL; |
640 | unsigned long flags; | ||
641 | int ret; | 550 | int ret; |
642 | 551 | ||
643 | sh_gpio_set_value(gpioc, offset, value); | 552 | /* |
644 | spin_lock_irqsave(&gpio_lock, flags); | 553 | * Ensure that the type encoding fits |
645 | ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT); | 554 | */ |
646 | spin_unlock_irqrestore(&gpio_lock, flags); | 555 | BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1)); |
647 | |||
648 | return ret; | ||
649 | } | ||
650 | |||
651 | static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) | ||
652 | { | ||
653 | struct pinmux_data_reg *dr = NULL; | ||
654 | int bit = 0; | ||
655 | |||
656 | if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) | ||
657 | return -EINVAL; | ||
658 | 556 | ||
659 | return gpio_read_bit(dr, bit); | 557 | if (sh_pfc) |
660 | } | 558 | return -EBUSY; |
661 | |||
662 | static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
663 | { | ||
664 | return sh_gpio_get_value(chip_to_pinmux(chip), offset); | ||
665 | } | ||
666 | 559 | ||
667 | static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 560 | ret = pfc_ioremap(pfc); |
668 | { | 561 | if (unlikely(ret < 0)) |
669 | sh_gpio_set_value(chip_to_pinmux(chip), offset, value); | ||
670 | } | ||
671 | |||
672 | static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
673 | { | ||
674 | struct pinmux_info *gpioc = chip_to_pinmux(chip); | ||
675 | pinmux_enum_t enum_id; | ||
676 | pinmux_enum_t *enum_ids; | ||
677 | int i, k, pos; | ||
678 | |||
679 | pos = 0; | ||
680 | enum_id = 0; | ||
681 | while (1) { | ||
682 | pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id); | ||
683 | if (pos <= 0 || !enum_id) | ||
684 | break; | ||
685 | |||
686 | for (i = 0; i < gpioc->gpio_irq_size; i++) { | ||
687 | enum_ids = gpioc->gpio_irq[i].enum_ids; | ||
688 | for (k = 0; enum_ids[k]; k++) { | ||
689 | if (enum_ids[k] == enum_id) | ||
690 | return gpioc->gpio_irq[i].irq; | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | |||
695 | return -ENOSYS; | ||
696 | } | ||
697 | |||
698 | int register_pinmux(struct pinmux_info *pip) | ||
699 | { | ||
700 | struct gpio_chip *chip = &pip->chip; | ||
701 | int ret; | ||
702 | |||
703 | pr_info("%s handling gpio %d -> %d\n", | ||
704 | pip->name, pip->first_gpio, pip->last_gpio); | ||
705 | |||
706 | ret = pfc_ioremap(pip); | ||
707 | if (ret < 0) | ||
708 | return ret; | 562 | return ret; |
709 | 563 | ||
710 | setup_data_regs(pip); | 564 | spin_lock_init(&pfc->lock); |
711 | |||
712 | chip->request = sh_gpio_request; | ||
713 | chip->free = sh_gpio_free; | ||
714 | chip->direction_input = sh_gpio_direction_input; | ||
715 | chip->get = sh_gpio_get; | ||
716 | chip->direction_output = sh_gpio_direction_output; | ||
717 | chip->set = sh_gpio_set; | ||
718 | chip->to_irq = sh_gpio_to_irq; | ||
719 | |||
720 | WARN_ON(pip->first_gpio != 0); /* needs testing */ | ||
721 | 565 | ||
722 | chip->label = pip->name; | 566 | setup_data_regs(pfc); |
723 | chip->owner = THIS_MODULE; | ||
724 | chip->base = pip->first_gpio; | ||
725 | chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; | ||
726 | 567 | ||
727 | ret = gpiochip_add(chip); | 568 | sh_pfc = pfc; |
728 | if (ret < 0) | 569 | pr_info("%s support registered\n", pfc->name); |
729 | pfc_iounmap(pip); | ||
730 | 570 | ||
731 | return ret; | 571 | initroutine = symbol_request(sh_pfc_register_gpiochip); |
732 | } | 572 | if (initroutine) { |
573 | (*initroutine)(pfc); | ||
574 | symbol_put_addr(initroutine); | ||
575 | } | ||
733 | 576 | ||
734 | int unregister_pinmux(struct pinmux_info *pip) | 577 | return 0; |
735 | { | ||
736 | pr_info("%s deregistering\n", pip->name); | ||
737 | pfc_iounmap(pip); | ||
738 | return gpiochip_remove(&pip->chip); | ||
739 | } | 578 | } |