diff options
Diffstat (limited to 'drivers/pinctrl/sh-pfc/pinctrl.c')
-rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 491 |
1 files changed, 251 insertions, 240 deletions
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index 11e0e1374d65..3492ec9a33b7 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c | |||
@@ -9,7 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define DRV_NAME "sh-pfc" | 11 | #define DRV_NAME "sh-pfc" |
12 | #define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt | ||
13 | 12 | ||
14 | #include <linux/device.h> | 13 | #include <linux/device.h> |
15 | #include <linux/err.h> | 14 | #include <linux/err.h> |
@@ -24,25 +23,28 @@ | |||
24 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
25 | 24 | ||
26 | #include "core.h" | 25 | #include "core.h" |
26 | #include "../core.h" | ||
27 | #include "../pinconf.h" | ||
28 | |||
29 | struct sh_pfc_pin_config { | ||
30 | u32 type; | ||
31 | }; | ||
27 | 32 | ||
28 | struct sh_pfc_pinctrl { | 33 | struct sh_pfc_pinctrl { |
29 | struct pinctrl_dev *pctl; | 34 | struct pinctrl_dev *pctl; |
30 | struct sh_pfc *pfc; | 35 | struct pinctrl_desc pctl_desc; |
31 | |||
32 | struct pinmux_gpio **functions; | ||
33 | unsigned int nr_functions; | ||
34 | 36 | ||
35 | struct pinctrl_pin_desc *pads; | 37 | struct sh_pfc *pfc; |
36 | unsigned int nr_pads; | ||
37 | 38 | ||
38 | spinlock_t lock; | 39 | struct pinctrl_pin_desc *pins; |
40 | struct sh_pfc_pin_config *configs; | ||
39 | }; | 41 | }; |
40 | 42 | ||
41 | static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) | 43 | static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) |
42 | { | 44 | { |
43 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 45 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
44 | 46 | ||
45 | return pmx->nr_pads; | 47 | return pmx->pfc->info->nr_groups; |
46 | } | 48 | } |
47 | 49 | ||
48 | static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, | 50 | static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, |
@@ -50,16 +52,16 @@ static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, | |||
50 | { | 52 | { |
51 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 53 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
52 | 54 | ||
53 | return pmx->pads[selector].name; | 55 | return pmx->pfc->info->groups[selector].name; |
54 | } | 56 | } |
55 | 57 | ||
56 | static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group, | 58 | static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, |
57 | const unsigned **pins, unsigned *num_pins) | 59 | const unsigned **pins, unsigned *num_pins) |
58 | { | 60 | { |
59 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 61 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
60 | 62 | ||
61 | *pins = &pmx->pads[group].number; | 63 | *pins = pmx->pfc->info->groups[selector].pins; |
62 | *num_pins = 1; | 64 | *num_pins = pmx->pfc->info->groups[selector].nr_pins; |
63 | 65 | ||
64 | return 0; | 66 | return 0; |
65 | } | 67 | } |
@@ -70,7 +72,7 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, | |||
70 | seq_printf(s, "%s", DRV_NAME); | 72 | seq_printf(s, "%s", DRV_NAME); |
71 | } | 73 | } |
72 | 74 | ||
73 | static struct pinctrl_ops sh_pfc_pinctrl_ops = { | 75 | static const struct pinctrl_ops sh_pfc_pinctrl_ops = { |
74 | .get_groups_count = sh_pfc_get_groups_count, | 76 | .get_groups_count = sh_pfc_get_groups_count, |
75 | .get_group_name = sh_pfc_get_group_name, | 77 | .get_group_name = sh_pfc_get_group_name, |
76 | .get_group_pins = sh_pfc_get_group_pins, | 78 | .get_group_pins = sh_pfc_get_group_pins, |
@@ -81,7 +83,7 @@ static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev) | |||
81 | { | 83 | { |
82 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 84 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
83 | 85 | ||
84 | return pmx->nr_functions; | 86 | return pmx->pfc->info->nr_functions; |
85 | } | 87 | } |
86 | 88 | ||
87 | static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, | 89 | static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, |
@@ -89,136 +91,113 @@ static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, | |||
89 | { | 91 | { |
90 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 92 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
91 | 93 | ||
92 | return pmx->functions[selector]->name; | 94 | return pmx->pfc->info->functions[selector].name; |
93 | } | 95 | } |
94 | 96 | ||
95 | static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func, | 97 | static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, |
98 | unsigned selector, | ||
96 | const char * const **groups, | 99 | const char * const **groups, |
97 | unsigned * const num_groups) | 100 | unsigned * const num_groups) |
98 | { | 101 | { |
99 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 102 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
100 | 103 | ||
101 | *groups = &pmx->functions[func]->name; | 104 | *groups = pmx->pfc->info->functions[selector].groups; |
102 | *num_groups = 1; | 105 | *num_groups = pmx->pfc->info->functions[selector].nr_groups; |
103 | 106 | ||
104 | return 0; | 107 | return 0; |
105 | } | 108 | } |
106 | 109 | ||
107 | static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func, | 110 | static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector, |
108 | unsigned group) | 111 | unsigned group) |
109 | { | 112 | { |
110 | return 0; | 113 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
111 | } | 114 | struct sh_pfc *pfc = pmx->pfc; |
115 | const struct sh_pfc_pin_group *grp = &pfc->info->groups[group]; | ||
116 | unsigned long flags; | ||
117 | unsigned int i; | ||
118 | int ret = 0; | ||
112 | 119 | ||
113 | static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func, | 120 | spin_lock_irqsave(&pfc->lock, flags); |
114 | unsigned group) | ||
115 | { | ||
116 | } | ||
117 | 121 | ||
118 | static int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset) | 122 | for (i = 0; i < grp->nr_pins; ++i) { |
119 | { | 123 | int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]); |
120 | if (sh_pfc_config_gpio(pfc, offset, | 124 | struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; |
121 | PINMUX_TYPE_FUNCTION, | ||
122 | GPIO_CFG_DRYRUN) != 0) | ||
123 | return -EINVAL; | ||
124 | 125 | ||
125 | if (sh_pfc_config_gpio(pfc, offset, | 126 | if (cfg->type != PINMUX_TYPE_NONE) { |
126 | PINMUX_TYPE_FUNCTION, | 127 | ret = -EBUSY; |
127 | GPIO_CFG_REQ) != 0) | 128 | goto done; |
128 | return -EINVAL; | 129 | } |
130 | } | ||
129 | 131 | ||
130 | return 0; | 132 | for (i = 0; i < grp->nr_pins; ++i) { |
133 | ret = sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION); | ||
134 | if (ret < 0) | ||
135 | break; | ||
136 | } | ||
137 | |||
138 | done: | ||
139 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
140 | return ret; | ||
131 | } | 141 | } |
132 | 142 | ||
133 | static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset, | 143 | static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector, |
134 | int new_type) | 144 | unsigned group) |
135 | { | 145 | { |
146 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
147 | struct sh_pfc *pfc = pmx->pfc; | ||
148 | const struct sh_pfc_pin_group *grp = &pfc->info->groups[group]; | ||
136 | unsigned long flags; | 149 | unsigned long flags; |
137 | int pinmux_type; | 150 | unsigned int i; |
138 | int ret = -EINVAL; | ||
139 | 151 | ||
140 | spin_lock_irqsave(&pfc->lock, flags); | 152 | spin_lock_irqsave(&pfc->lock, flags); |
141 | 153 | ||
142 | pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE; | 154 | for (i = 0; i < grp->nr_pins; ++i) { |
155 | int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]); | ||
156 | struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; | ||
143 | 157 | ||
144 | /* | 158 | cfg->type = PINMUX_TYPE_NONE; |
145 | * See if the present config needs to first be de-configured. | ||
146 | */ | ||
147 | switch (pinmux_type) { | ||
148 | case PINMUX_TYPE_GPIO: | ||
149 | break; | ||
150 | case PINMUX_TYPE_OUTPUT: | ||
151 | case PINMUX_TYPE_INPUT: | ||
152 | case PINMUX_TYPE_INPUT_PULLUP: | ||
153 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
154 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
155 | break; | ||
156 | default: | ||
157 | goto err; | ||
158 | } | 159 | } |
159 | 160 | ||
160 | /* | ||
161 | * Dry run | ||
162 | */ | ||
163 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
164 | GPIO_CFG_DRYRUN) != 0) | ||
165 | goto err; | ||
166 | |||
167 | /* | ||
168 | * Request | ||
169 | */ | ||
170 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
171 | GPIO_CFG_REQ) != 0) | ||
172 | goto err; | ||
173 | |||
174 | pfc->info->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
175 | pfc->info->gpios[offset].flags |= new_type; | ||
176 | |||
177 | ret = 0; | ||
178 | |||
179 | err: | ||
180 | spin_unlock_irqrestore(&pfc->lock, flags); | 161 | spin_unlock_irqrestore(&pfc->lock, flags); |
181 | |||
182 | return ret; | ||
183 | } | 162 | } |
184 | 163 | ||
185 | |||
186 | static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, | 164 | static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, |
187 | struct pinctrl_gpio_range *range, | 165 | struct pinctrl_gpio_range *range, |
188 | unsigned offset) | 166 | unsigned offset) |
189 | { | 167 | { |
190 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 168 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
191 | struct sh_pfc *pfc = pmx->pfc; | 169 | struct sh_pfc *pfc = pmx->pfc; |
170 | int idx = sh_pfc_get_pin_index(pfc, offset); | ||
171 | struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; | ||
192 | unsigned long flags; | 172 | unsigned long flags; |
193 | int ret, pinmux_type; | 173 | int ret; |
194 | 174 | ||
195 | spin_lock_irqsave(&pfc->lock, flags); | 175 | spin_lock_irqsave(&pfc->lock, flags); |
196 | 176 | ||
197 | pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE; | 177 | if (cfg->type != PINMUX_TYPE_NONE) { |
178 | dev_err(pfc->dev, | ||
179 | "Pin %u is busy, can't configure it as GPIO.\n", | ||
180 | offset); | ||
181 | ret = -EBUSY; | ||
182 | goto done; | ||
183 | } | ||
198 | 184 | ||
199 | switch (pinmux_type) { | 185 | if (!pfc->gpio) { |
200 | case PINMUX_TYPE_FUNCTION: | 186 | /* If GPIOs are handled externally the pin mux type need to be |
201 | pr_notice_once("Use of GPIO API for function requests is " | 187 | * set to GPIO here. |
202 | "deprecated, convert to pinctrl\n"); | 188 | */ |
203 | /* handle for now */ | 189 | const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; |
204 | ret = sh_pfc_config_function(pfc, offset); | ||
205 | if (unlikely(ret < 0)) | ||
206 | goto err; | ||
207 | 190 | ||
208 | break; | 191 | ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO); |
209 | case PINMUX_TYPE_GPIO: | 192 | if (ret < 0) |
210 | case PINMUX_TYPE_INPUT: | 193 | goto done; |
211 | case PINMUX_TYPE_OUTPUT: | ||
212 | break; | ||
213 | default: | ||
214 | pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); | ||
215 | ret = -ENOTSUPP; | ||
216 | goto err; | ||
217 | } | 194 | } |
218 | 195 | ||
196 | cfg->type = PINMUX_TYPE_GPIO; | ||
197 | |||
219 | ret = 0; | 198 | ret = 0; |
220 | 199 | ||
221 | err: | 200 | done: |
222 | spin_unlock_irqrestore(&pfc->lock, flags); | 201 | spin_unlock_irqrestore(&pfc->lock, flags); |
223 | 202 | ||
224 | return ret; | 203 | return ret; |
@@ -230,15 +209,12 @@ static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev, | |||
230 | { | 209 | { |
231 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 210 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
232 | struct sh_pfc *pfc = pmx->pfc; | 211 | struct sh_pfc *pfc = pmx->pfc; |
212 | int idx = sh_pfc_get_pin_index(pfc, offset); | ||
213 | struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; | ||
233 | unsigned long flags; | 214 | unsigned long flags; |
234 | int pinmux_type; | ||
235 | 215 | ||
236 | spin_lock_irqsave(&pfc->lock, flags); | 216 | spin_lock_irqsave(&pfc->lock, flags); |
237 | 217 | cfg->type = PINMUX_TYPE_NONE; | |
238 | pinmux_type = pfc->info->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
239 | |||
240 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
241 | |||
242 | spin_unlock_irqrestore(&pfc->lock, flags); | 218 | spin_unlock_irqrestore(&pfc->lock, flags); |
243 | } | 219 | } |
244 | 220 | ||
@@ -247,207 +223,242 @@ static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, | |||
247 | unsigned offset, bool input) | 223 | unsigned offset, bool input) |
248 | { | 224 | { |
249 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 225 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
250 | int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT; | 226 | struct sh_pfc *pfc = pmx->pfc; |
227 | int new_type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT; | ||
228 | int idx = sh_pfc_get_pin_index(pfc, offset); | ||
229 | const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; | ||
230 | struct sh_pfc_pin_config *cfg = &pmx->configs[idx]; | ||
231 | unsigned long flags; | ||
232 | unsigned int dir; | ||
233 | int ret; | ||
234 | |||
235 | /* Check if the requested direction is supported by the pin. Not all SoC | ||
236 | * provide pin config data, so perform the check conditionally. | ||
237 | */ | ||
238 | if (pin->configs) { | ||
239 | dir = input ? SH_PFC_PIN_CFG_INPUT : SH_PFC_PIN_CFG_OUTPUT; | ||
240 | if (!(pin->configs & dir)) | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | |||
244 | spin_lock_irqsave(&pfc->lock, flags); | ||
245 | |||
246 | ret = sh_pfc_config_mux(pfc, pin->enum_id, new_type); | ||
247 | if (ret < 0) | ||
248 | goto done; | ||
249 | |||
250 | cfg->type = new_type; | ||
251 | 251 | ||
252 | return sh_pfc_reconfig_pin(pmx->pfc, offset, type); | 252 | done: |
253 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
254 | return ret; | ||
253 | } | 255 | } |
254 | 256 | ||
255 | static struct pinmux_ops sh_pfc_pinmux_ops = { | 257 | static const struct pinmux_ops sh_pfc_pinmux_ops = { |
256 | .get_functions_count = sh_pfc_get_functions_count, | 258 | .get_functions_count = sh_pfc_get_functions_count, |
257 | .get_function_name = sh_pfc_get_function_name, | 259 | .get_function_name = sh_pfc_get_function_name, |
258 | .get_function_groups = sh_pfc_get_function_groups, | 260 | .get_function_groups = sh_pfc_get_function_groups, |
259 | .enable = sh_pfc_noop_enable, | 261 | .enable = sh_pfc_func_enable, |
260 | .disable = sh_pfc_noop_disable, | 262 | .disable = sh_pfc_func_disable, |
261 | .gpio_request_enable = sh_pfc_gpio_request_enable, | 263 | .gpio_request_enable = sh_pfc_gpio_request_enable, |
262 | .gpio_disable_free = sh_pfc_gpio_disable_free, | 264 | .gpio_disable_free = sh_pfc_gpio_disable_free, |
263 | .gpio_set_direction = sh_pfc_gpio_set_direction, | 265 | .gpio_set_direction = sh_pfc_gpio_set_direction, |
264 | }; | 266 | }; |
265 | 267 | ||
266 | static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, | 268 | /* Check whether the requested parameter is supported for a pin. */ |
267 | unsigned long *config) | 269 | static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, |
270 | enum pin_config_param param) | ||
268 | { | 271 | { |
269 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | 272 | int idx = sh_pfc_get_pin_index(pfc, _pin); |
270 | struct sh_pfc *pfc = pmx->pfc; | 273 | const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; |
271 | 274 | ||
272 | *config = pfc->info->gpios[pin].flags & PINMUX_FLAG_TYPE; | 275 | switch (param) { |
276 | case PIN_CONFIG_BIAS_DISABLE: | ||
277 | return true; | ||
273 | 278 | ||
274 | return 0; | 279 | case PIN_CONFIG_BIAS_PULL_UP: |
275 | } | 280 | return pin->configs & SH_PFC_PIN_CFG_PULL_UP; |
276 | 281 | ||
277 | static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, | 282 | case PIN_CONFIG_BIAS_PULL_DOWN: |
278 | unsigned long config) | 283 | return pin->configs & SH_PFC_PIN_CFG_PULL_DOWN; |
279 | { | ||
280 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
281 | |||
282 | /* Validate the new type */ | ||
283 | if (config >= PINMUX_FLAG_TYPE) | ||
284 | return -EINVAL; | ||
285 | 284 | ||
286 | return sh_pfc_reconfig_pin(pmx->pfc, pin, config); | 285 | default: |
286 | return false; | ||
287 | } | ||
287 | } | 288 | } |
288 | 289 | ||
289 | static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev, | 290 | static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned _pin, |
290 | struct seq_file *s, unsigned pin) | 291 | unsigned long *config) |
291 | { | 292 | { |
292 | const char *pinmux_type_str[] = { | 293 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); |
293 | [PINMUX_TYPE_NONE] = "none", | 294 | struct sh_pfc *pfc = pmx->pfc; |
294 | [PINMUX_TYPE_FUNCTION] = "function", | 295 | enum pin_config_param param = pinconf_to_config_param(*config); |
295 | [PINMUX_TYPE_GPIO] = "gpio", | 296 | unsigned long flags; |
296 | [PINMUX_TYPE_OUTPUT] = "output", | 297 | unsigned int bias; |
297 | [PINMUX_TYPE_INPUT] = "input", | ||
298 | [PINMUX_TYPE_INPUT_PULLUP] = "input bias pull up", | ||
299 | [PINMUX_TYPE_INPUT_PULLDOWN] = "input bias pull down", | ||
300 | }; | ||
301 | unsigned long config; | ||
302 | int rc; | ||
303 | |||
304 | rc = sh_pfc_pinconf_get(pctldev, pin, &config); | ||
305 | if (unlikely(rc != 0)) | ||
306 | return; | ||
307 | |||
308 | seq_printf(s, " %s", pinmux_type_str[config]); | ||
309 | } | ||
310 | 298 | ||
311 | static struct pinconf_ops sh_pfc_pinconf_ops = { | 299 | if (!sh_pfc_pinconf_validate(pfc, _pin, param)) |
312 | .pin_config_get = sh_pfc_pinconf_get, | 300 | return -ENOTSUPP; |
313 | .pin_config_set = sh_pfc_pinconf_set, | ||
314 | .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, | ||
315 | }; | ||
316 | 301 | ||
317 | static struct pinctrl_gpio_range sh_pfc_gpio_range = { | 302 | switch (param) { |
318 | .name = DRV_NAME, | 303 | case PIN_CONFIG_BIAS_DISABLE: |
319 | .id = 0, | 304 | case PIN_CONFIG_BIAS_PULL_UP: |
320 | }; | 305 | case PIN_CONFIG_BIAS_PULL_DOWN: |
306 | if (!pfc->info->ops || !pfc->info->ops->get_bias) | ||
307 | return -ENOTSUPP; | ||
321 | 308 | ||
322 | static struct pinctrl_desc sh_pfc_pinctrl_desc = { | 309 | spin_lock_irqsave(&pfc->lock, flags); |
323 | .name = DRV_NAME, | 310 | bias = pfc->info->ops->get_bias(pfc, _pin); |
324 | .owner = THIS_MODULE, | 311 | spin_unlock_irqrestore(&pfc->lock, flags); |
325 | .pctlops = &sh_pfc_pinctrl_ops, | ||
326 | .pmxops = &sh_pfc_pinmux_ops, | ||
327 | .confops = &sh_pfc_pinconf_ops, | ||
328 | }; | ||
329 | 312 | ||
330 | static void sh_pfc_map_one_gpio(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx, | 313 | if (bias != param) |
331 | struct pinmux_gpio *gpio, unsigned offset) | 314 | return -EINVAL; |
332 | { | ||
333 | struct pinmux_data_reg *dummy; | ||
334 | unsigned long flags; | ||
335 | int bit; | ||
336 | |||
337 | gpio->flags &= ~PINMUX_FLAG_TYPE; | ||
338 | 315 | ||
339 | if (sh_pfc_get_data_reg(pfc, offset, &dummy, &bit) == 0) | 316 | *config = 0; |
340 | gpio->flags |= PINMUX_TYPE_GPIO; | 317 | break; |
341 | else { | ||
342 | gpio->flags |= PINMUX_TYPE_FUNCTION; | ||
343 | 318 | ||
344 | spin_lock_irqsave(&pmx->lock, flags); | 319 | default: |
345 | pmx->nr_functions++; | 320 | return -ENOTSUPP; |
346 | spin_unlock_irqrestore(&pmx->lock, flags); | ||
347 | } | 321 | } |
322 | |||
323 | return 0; | ||
348 | } | 324 | } |
349 | 325 | ||
350 | /* pinmux ranges -> pinctrl pin descs */ | 326 | static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned _pin, |
351 | static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | 327 | unsigned long config) |
352 | { | 328 | { |
329 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
330 | struct sh_pfc *pfc = pmx->pfc; | ||
331 | enum pin_config_param param = pinconf_to_config_param(config); | ||
353 | unsigned long flags; | 332 | unsigned long flags; |
354 | int i; | ||
355 | 333 | ||
356 | pmx->nr_pads = pfc->info->last_gpio - pfc->info->first_gpio + 1; | 334 | if (!sh_pfc_pinconf_validate(pfc, _pin, param)) |
335 | return -ENOTSUPP; | ||
357 | 336 | ||
358 | pmx->pads = devm_kzalloc(pfc->dev, sizeof(*pmx->pads) * pmx->nr_pads, | 337 | switch (param) { |
359 | GFP_KERNEL); | 338 | case PIN_CONFIG_BIAS_PULL_UP: |
360 | if (unlikely(!pmx->pads)) { | 339 | case PIN_CONFIG_BIAS_PULL_DOWN: |
361 | pmx->nr_pads = 0; | 340 | case PIN_CONFIG_BIAS_DISABLE: |
362 | return -ENOMEM; | 341 | if (!pfc->info->ops || !pfc->info->ops->set_bias) |
363 | } | 342 | return -ENOTSUPP; |
364 | 343 | ||
365 | spin_lock_irqsave(&pfc->lock, flags); | 344 | spin_lock_irqsave(&pfc->lock, flags); |
345 | pfc->info->ops->set_bias(pfc, _pin, param); | ||
346 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
366 | 347 | ||
367 | /* | 348 | break; |
368 | * We don't necessarily have a 1:1 mapping between pin and linux | ||
369 | * GPIO number, as the latter maps to the associated enum_id. | ||
370 | * Care needs to be taken to translate back to pin space when | ||
371 | * dealing with any pin configurations. | ||
372 | */ | ||
373 | for (i = 0; i < pmx->nr_pads; i++) { | ||
374 | struct pinctrl_pin_desc *pin = pmx->pads + i; | ||
375 | struct pinmux_gpio *gpio = pfc->info->gpios + i; | ||
376 | 349 | ||
377 | pin->number = pfc->info->first_gpio + i; | 350 | default: |
378 | pin->name = gpio->name; | 351 | return -ENOTSUPP; |
352 | } | ||
379 | 353 | ||
380 | /* XXX */ | 354 | return 0; |
381 | if (unlikely(!gpio->enum_id)) | 355 | } |
382 | continue; | ||
383 | 356 | ||
384 | sh_pfc_map_one_gpio(pfc, pmx, gpio, i); | 357 | static int sh_pfc_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned group, |
385 | } | 358 | unsigned long config) |
359 | { | ||
360 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
361 | const unsigned int *pins; | ||
362 | unsigned int num_pins; | ||
363 | unsigned int i; | ||
386 | 364 | ||
387 | spin_unlock_irqrestore(&pfc->lock, flags); | 365 | pins = pmx->pfc->info->groups[group].pins; |
366 | num_pins = pmx->pfc->info->groups[group].nr_pins; | ||
388 | 367 | ||
389 | sh_pfc_pinctrl_desc.pins = pmx->pads; | 368 | for (i = 0; i < num_pins; ++i) |
390 | sh_pfc_pinctrl_desc.npins = pmx->nr_pads; | 369 | sh_pfc_pinconf_set(pctldev, pins[i], config); |
391 | 370 | ||
392 | return 0; | 371 | return 0; |
393 | } | 372 | } |
394 | 373 | ||
395 | static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | 374 | static const struct pinconf_ops sh_pfc_pinconf_ops = { |
375 | .is_generic = true, | ||
376 | .pin_config_get = sh_pfc_pinconf_get, | ||
377 | .pin_config_set = sh_pfc_pinconf_set, | ||
378 | .pin_config_group_set = sh_pfc_pinconf_group_set, | ||
379 | .pin_config_config_dbg_show = pinconf_generic_dump_config, | ||
380 | }; | ||
381 | |||
382 | /* PFC ranges -> pinctrl pin descs */ | ||
383 | static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | ||
396 | { | 384 | { |
397 | unsigned long flags; | 385 | const struct pinmux_range *ranges; |
398 | int i, fn; | 386 | struct pinmux_range def_range; |
387 | unsigned int nr_ranges; | ||
388 | unsigned int nr_pins; | ||
389 | unsigned int i; | ||
390 | |||
391 | if (pfc->info->ranges == NULL) { | ||
392 | def_range.begin = 0; | ||
393 | def_range.end = pfc->info->nr_pins - 1; | ||
394 | ranges = &def_range; | ||
395 | nr_ranges = 1; | ||
396 | } else { | ||
397 | ranges = pfc->info->ranges; | ||
398 | nr_ranges = pfc->info->nr_ranges; | ||
399 | } | ||
399 | 400 | ||
400 | pmx->functions = devm_kzalloc(pfc->dev, pmx->nr_functions * | 401 | pmx->pins = devm_kzalloc(pfc->dev, |
401 | sizeof(*pmx->functions), GFP_KERNEL); | 402 | sizeof(*pmx->pins) * pfc->info->nr_pins, |
402 | if (unlikely(!pmx->functions)) | 403 | GFP_KERNEL); |
404 | if (unlikely(!pmx->pins)) | ||
403 | return -ENOMEM; | 405 | return -ENOMEM; |
404 | 406 | ||
405 | spin_lock_irqsave(&pmx->lock, flags); | 407 | pmx->configs = devm_kzalloc(pfc->dev, |
406 | 408 | sizeof(*pmx->configs) * pfc->info->nr_pins, | |
407 | for (i = fn = 0; i < pmx->nr_pads; i++) { | 409 | GFP_KERNEL); |
408 | struct pinmux_gpio *gpio = pfc->info->gpios + i; | 410 | if (unlikely(!pmx->configs)) |
411 | return -ENOMEM; | ||
409 | 412 | ||
410 | if ((gpio->flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_FUNCTION) | 413 | for (i = 0, nr_pins = 0; i < nr_ranges; ++i) { |
411 | pmx->functions[fn++] = gpio; | 414 | const struct pinmux_range *range = &ranges[i]; |
415 | unsigned int number; | ||
416 | |||
417 | for (number = range->begin; number <= range->end; | ||
418 | number++, nr_pins++) { | ||
419 | struct sh_pfc_pin_config *cfg = &pmx->configs[nr_pins]; | ||
420 | struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins]; | ||
421 | const struct sh_pfc_pin *info = | ||
422 | &pfc->info->pins[nr_pins]; | ||
423 | |||
424 | pin->number = number; | ||
425 | pin->name = info->name; | ||
426 | cfg->type = PINMUX_TYPE_NONE; | ||
427 | } | ||
412 | } | 428 | } |
413 | 429 | ||
414 | spin_unlock_irqrestore(&pmx->lock, flags); | 430 | pfc->nr_pins = ranges[nr_ranges-1].end + 1; |
415 | 431 | ||
416 | return 0; | 432 | return nr_ranges; |
417 | } | 433 | } |
418 | 434 | ||
419 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | 435 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) |
420 | { | 436 | { |
421 | struct sh_pfc_pinctrl *pmx; | 437 | struct sh_pfc_pinctrl *pmx; |
422 | int ret; | 438 | int nr_ranges; |
423 | 439 | ||
424 | pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); | 440 | pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); |
425 | if (unlikely(!pmx)) | 441 | if (unlikely(!pmx)) |
426 | return -ENOMEM; | 442 | return -ENOMEM; |
427 | 443 | ||
428 | spin_lock_init(&pmx->lock); | ||
429 | |||
430 | pmx->pfc = pfc; | 444 | pmx->pfc = pfc; |
431 | pfc->pinctrl = pmx; | 445 | pfc->pinctrl = pmx; |
432 | 446 | ||
433 | ret = sh_pfc_map_gpios(pfc, pmx); | 447 | nr_ranges = sh_pfc_map_pins(pfc, pmx); |
434 | if (unlikely(ret != 0)) | 448 | if (unlikely(nr_ranges < 0)) |
435 | return ret; | 449 | return nr_ranges; |
436 | 450 | ||
437 | ret = sh_pfc_map_functions(pfc, pmx); | 451 | pmx->pctl_desc.name = DRV_NAME; |
438 | if (unlikely(ret != 0)) | 452 | pmx->pctl_desc.owner = THIS_MODULE; |
439 | return ret; | 453 | pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops; |
454 | pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops; | ||
455 | pmx->pctl_desc.confops = &sh_pfc_pinconf_ops; | ||
456 | pmx->pctl_desc.pins = pmx->pins; | ||
457 | pmx->pctl_desc.npins = pfc->info->nr_pins; | ||
440 | 458 | ||
441 | pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, pfc->dev, pmx); | 459 | pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx); |
442 | if (IS_ERR(pmx->pctl)) | 460 | if (pmx->pctl == NULL) |
443 | return PTR_ERR(pmx->pctl); | 461 | return -EINVAL; |
444 | |||
445 | sh_pfc_gpio_range.npins = pfc->info->last_gpio | ||
446 | - pfc->info->first_gpio + 1; | ||
447 | sh_pfc_gpio_range.base = pfc->info->first_gpio; | ||
448 | sh_pfc_gpio_range.pin_base = pfc->info->first_gpio; | ||
449 | |||
450 | pinctrl_add_gpio_range(pmx->pctl, &sh_pfc_gpio_range); | ||
451 | 462 | ||
452 | return 0; | 463 | return 0; |
453 | } | 464 | } |