]>
Commit | Line | Data |
---|---|---|
cbff0c4d SG |
1 | /* |
2 | * Copyright (C) 2017 Sanechips Technology Co., Ltd. | |
3 | * Copyright 2017 Linaro Ltd. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | */ | |
9 | ||
10 | #include <linux/io.h> | |
11 | #include <linux/of.h> | |
12 | #include <linux/of_address.h> | |
13 | #include <linux/of_device.h> | |
14 | #include <linux/pinctrl/pinctrl.h> | |
15 | #include <linux/pinctrl/pinconf-generic.h> | |
16 | #include <linux/pinctrl/pinmux.h> | |
17 | #include <linux/platform_device.h> | |
18 | #include <linux/slab.h> | |
19 | ||
20 | #include "../core.h" | |
21 | #include "../pinctrl-utils.h" | |
22 | #include "../pinmux.h" | |
23 | #include "pinctrl-zx.h" | |
24 | ||
25 | #define ZX_PULL_DOWN BIT(0) | |
26 | #define ZX_PULL_UP BIT(1) | |
27 | #define ZX_INPUT_ENABLE BIT(3) | |
28 | #define ZX_DS_SHIFT 4 | |
29 | #define ZX_DS_MASK (0x7 << ZX_DS_SHIFT) | |
30 | #define ZX_DS_VALUE(x) (((x) << ZX_DS_SHIFT) & ZX_DS_MASK) | |
31 | #define ZX_SLEW BIT(8) | |
32 | ||
33 | struct zx_pinctrl { | |
34 | struct pinctrl_dev *pctldev; | |
35 | struct device *dev; | |
36 | void __iomem *base; | |
37 | void __iomem *aux_base; | |
38 | spinlock_t lock; | |
39 | struct zx_pinctrl_soc_info *info; | |
40 | }; | |
41 | ||
42 | static int zx_dt_node_to_map(struct pinctrl_dev *pctldev, | |
43 | struct device_node *np_config, | |
44 | struct pinctrl_map **map, u32 *num_maps) | |
45 | { | |
46 | return pinconf_generic_dt_node_to_map(pctldev, np_config, map, | |
47 | num_maps, PIN_MAP_TYPE_INVALID); | |
48 | } | |
49 | ||
50 | static const struct pinctrl_ops zx_pinctrl_ops = { | |
51 | .dt_node_to_map = zx_dt_node_to_map, | |
52 | .dt_free_map = pinctrl_utils_free_map, | |
53 | .get_groups_count = pinctrl_generic_get_group_count, | |
54 | .get_group_name = pinctrl_generic_get_group_name, | |
55 | .get_group_pins = pinctrl_generic_get_group_pins, | |
56 | }; | |
57 | ||
58 | #define NONAON_MVAL 2 | |
59 | ||
60 | static int zx_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, | |
61 | unsigned int group_selector) | |
62 | { | |
63 | struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev); | |
64 | struct zx_pinctrl_soc_info *info = zpctl->info; | |
65 | const struct pinctrl_pin_desc *pindesc = info->pins + group_selector; | |
66 | struct zx_pin_data *data = pindesc->drv_data; | |
b962e2cd SG |
67 | struct zx_mux_desc *mux; |
68 | u32 mask, offset, bitpos; | |
cbff0c4d SG |
69 | struct function_desc *func; |
70 | unsigned long flags; | |
71 | u32 val, mval; | |
72 | ||
73 | /* Skip reserved pin */ | |
74 | if (!data) | |
75 | return -EINVAL; | |
76 | ||
b962e2cd SG |
77 | mux = data->muxes; |
78 | mask = (1 << data->width) - 1; | |
79 | offset = data->offset; | |
80 | bitpos = data->bitpos; | |
81 | ||
cbff0c4d SG |
82 | func = pinmux_generic_get_function(pctldev, func_selector); |
83 | if (!func) | |
84 | return -EINVAL; | |
85 | ||
86 | while (mux->name) { | |
87 | if (strcmp(mux->name, func->name) == 0) | |
88 | break; | |
89 | mux++; | |
90 | } | |
91 | ||
92 | /* Found mux value to be written */ | |
93 | mval = mux->muxval; | |
94 | ||
95 | spin_lock_irqsave(&zpctl->lock, flags); | |
96 | ||
97 | if (data->aon_pin) { | |
98 | /* | |
99 | * It's an AON pin, whose mux register offset and bit position | |
100 | * can be caluculated from pin number. Each register covers 16 | |
101 | * pins, and each pin occupies 2 bits. | |
102 | */ | |
103 | u16 aoffset = pindesc->number / 16 * 4; | |
104 | u16 abitpos = (pindesc->number % 16) * 2; | |
105 | ||
106 | if (mval & AON_MUX_FLAG) { | |
107 | /* | |
108 | * This is a mux value that needs to be written into | |
109 | * AON pinmux register. Write it and then we're done. | |
110 | */ | |
111 | val = readl(zpctl->aux_base + aoffset); | |
112 | val &= ~(0x3 << abitpos); | |
113 | val |= (mval & 0x3) << abitpos; | |
114 | writel(val, zpctl->aux_base + aoffset); | |
115 | } else { | |
116 | /* | |
117 | * It's a mux value that needs to be written into TOP | |
118 | * pinmux register. | |
119 | */ | |
120 | val = readl(zpctl->base + offset); | |
121 | val &= ~(mask << bitpos); | |
122 | val |= (mval & mask) << bitpos; | |
123 | writel(val, zpctl->base + offset); | |
124 | ||
125 | /* | |
126 | * In this case, the AON pinmux register needs to be | |
127 | * set up to select non-AON function. | |
128 | */ | |
129 | val = readl(zpctl->aux_base + aoffset); | |
130 | val &= ~(0x3 << abitpos); | |
131 | val |= NONAON_MVAL << abitpos; | |
132 | writel(val, zpctl->aux_base + aoffset); | |
133 | } | |
134 | ||
135 | } else { | |
136 | /* | |
137 | * This is a TOP pin, and we only need to set up TOP pinmux | |
138 | * register and then we're done with it. | |
139 | */ | |
140 | val = readl(zpctl->base + offset); | |
141 | val &= ~(mask << bitpos); | |
142 | val |= (mval & mask) << bitpos; | |
143 | writel(val, zpctl->base + offset); | |
144 | } | |
145 | ||
146 | spin_unlock_irqrestore(&zpctl->lock, flags); | |
147 | ||
148 | return 0; | |
149 | } | |
150 | ||
151 | static const struct pinmux_ops zx_pinmux_ops = { | |
152 | .get_functions_count = pinmux_generic_get_function_count, | |
153 | .get_function_name = pinmux_generic_get_function_name, | |
154 | .get_function_groups = pinmux_generic_get_function_groups, | |
155 | .set_mux = zx_set_mux, | |
156 | }; | |
157 | ||
158 | static int zx_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin, | |
159 | unsigned long *config) | |
160 | { | |
161 | struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev); | |
162 | struct zx_pinctrl_soc_info *info = zpctl->info; | |
163 | const struct pinctrl_pin_desc *pindesc = info->pins + pin; | |
164 | struct zx_pin_data *data = pindesc->drv_data; | |
165 | enum pin_config_param param = pinconf_to_config_param(*config); | |
166 | u32 val; | |
167 | ||
168 | /* Skip reserved pin */ | |
169 | if (!data) | |
170 | return -EINVAL; | |
171 | ||
172 | val = readl(zpctl->aux_base + data->coffset); | |
173 | val = val >> data->cbitpos; | |
174 | ||
175 | switch (param) { | |
176 | case PIN_CONFIG_BIAS_PULL_DOWN: | |
177 | val &= ZX_PULL_DOWN; | |
178 | val = !!val; | |
179 | if (val == 0) | |
180 | return -EINVAL; | |
181 | break; | |
182 | case PIN_CONFIG_BIAS_PULL_UP: | |
183 | val &= ZX_PULL_UP; | |
184 | val = !!val; | |
185 | if (val == 0) | |
186 | return -EINVAL; | |
187 | break; | |
188 | case PIN_CONFIG_INPUT_ENABLE: | |
189 | val &= ZX_INPUT_ENABLE; | |
190 | val = !!val; | |
191 | if (val == 0) | |
192 | return -EINVAL; | |
193 | break; | |
194 | case PIN_CONFIG_DRIVE_STRENGTH: | |
195 | val &= ZX_DS_MASK; | |
196 | val = val >> ZX_DS_SHIFT; | |
197 | break; | |
198 | case PIN_CONFIG_SLEW_RATE: | |
199 | val &= ZX_SLEW; | |
200 | val = !!val; | |
201 | break; | |
202 | default: | |
203 | return -ENOTSUPP; | |
204 | } | |
205 | ||
206 | *config = pinconf_to_config_packed(param, val); | |
207 | ||
208 | return 0; | |
209 | } | |
210 | ||
211 | static int zx_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, | |
212 | unsigned long *configs, unsigned int num_configs) | |
213 | { | |
214 | struct zx_pinctrl *zpctl = pinctrl_dev_get_drvdata(pctldev); | |
215 | struct zx_pinctrl_soc_info *info = zpctl->info; | |
216 | const struct pinctrl_pin_desc *pindesc = info->pins + pin; | |
217 | struct zx_pin_data *data = pindesc->drv_data; | |
218 | enum pin_config_param param; | |
219 | u32 val, arg; | |
220 | int i; | |
221 | ||
222 | /* Skip reserved pin */ | |
223 | if (!data) | |
224 | return -EINVAL; | |
225 | ||
226 | val = readl(zpctl->aux_base + data->coffset); | |
227 | ||
228 | for (i = 0; i < num_configs; i++) { | |
229 | param = pinconf_to_config_param(configs[i]); | |
230 | arg = pinconf_to_config_argument(configs[i]); | |
231 | ||
232 | switch (param) { | |
233 | case PIN_CONFIG_BIAS_PULL_DOWN: | |
234 | val |= ZX_PULL_DOWN << data->cbitpos; | |
235 | break; | |
236 | case PIN_CONFIG_BIAS_PULL_UP: | |
237 | val |= ZX_PULL_UP << data->cbitpos; | |
238 | break; | |
239 | case PIN_CONFIG_INPUT_ENABLE: | |
240 | val |= ZX_INPUT_ENABLE << data->cbitpos; | |
241 | break; | |
242 | case PIN_CONFIG_DRIVE_STRENGTH: | |
243 | val &= ~(ZX_DS_MASK << data->cbitpos); | |
244 | val |= ZX_DS_VALUE(arg) << data->cbitpos; | |
245 | break; | |
246 | case PIN_CONFIG_SLEW_RATE: | |
247 | if (arg) | |
248 | val |= ZX_SLEW << data->cbitpos; | |
249 | else | |
250 | val &= ~ZX_SLEW << data->cbitpos; | |
251 | break; | |
252 | default: | |
253 | return -ENOTSUPP; | |
254 | } | |
255 | } | |
256 | ||
257 | writel(val, zpctl->aux_base + data->coffset); | |
258 | return 0; | |
259 | } | |
260 | ||
261 | static const struct pinconf_ops zx_pinconf_ops = { | |
262 | .pin_config_set = zx_pin_config_set, | |
263 | .pin_config_get = zx_pin_config_get, | |
264 | .is_generic = true, | |
265 | }; | |
266 | ||
267 | static int zx_pinctrl_build_state(struct platform_device *pdev) | |
268 | { | |
269 | struct zx_pinctrl *zpctl = platform_get_drvdata(pdev); | |
270 | struct zx_pinctrl_soc_info *info = zpctl->info; | |
271 | struct pinctrl_dev *pctldev = zpctl->pctldev; | |
272 | struct function_desc *functions; | |
273 | int nfunctions; | |
274 | struct group_desc *groups; | |
275 | int ngroups; | |
276 | int i; | |
277 | ||
278 | /* Every single pin composes a group */ | |
279 | ngroups = info->npins; | |
280 | groups = devm_kzalloc(&pdev->dev, ngroups * sizeof(*groups), | |
281 | GFP_KERNEL); | |
282 | if (!groups) | |
283 | return -ENOMEM; | |
284 | ||
285 | for (i = 0; i < ngroups; i++) { | |
286 | const struct pinctrl_pin_desc *pindesc = info->pins + i; | |
287 | struct group_desc *group = groups + i; | |
cbff0c4d SG |
288 | |
289 | group->name = pindesc->name; | |
80fbc2d9 SG |
290 | group->pins = (int *) &pindesc->number; |
291 | group->num_pins = 1; | |
cbff0c4d SG |
292 | radix_tree_insert(&pctldev->pin_group_tree, i, group); |
293 | } | |
294 | ||
295 | pctldev->num_groups = ngroups; | |
296 | ||
297 | /* Build function list from pin mux functions */ | |
298 | functions = devm_kzalloc(&pdev->dev, info->npins * sizeof(*functions), | |
299 | GFP_KERNEL); | |
300 | if (!functions) | |
301 | return -ENOMEM; | |
302 | ||
303 | nfunctions = 0; | |
304 | for (i = 0; i < info->npins; i++) { | |
305 | const struct pinctrl_pin_desc *pindesc = info->pins + i; | |
306 | struct zx_pin_data *data = pindesc->drv_data; | |
307 | struct zx_mux_desc *mux; | |
308 | ||
309 | /* Reserved pins do not have a drv_data at all */ | |
310 | if (!data) | |
311 | continue; | |
312 | ||
313 | /* Loop over all muxes for the pin */ | |
314 | mux = data->muxes; | |
315 | while (mux->name) { | |
316 | struct function_desc *func = functions; | |
317 | ||
318 | /* Search function list for given mux */ | |
319 | while (func->name) { | |
320 | if (strcmp(mux->name, func->name) == 0) { | |
321 | /* Function exists */ | |
322 | func->num_group_names++; | |
323 | break; | |
324 | } | |
325 | func++; | |
326 | } | |
327 | ||
328 | if (!func->name) { | |
329 | /* New function */ | |
330 | func->name = mux->name; | |
331 | func->num_group_names = 1; | |
332 | radix_tree_insert(&pctldev->pin_function_tree, | |
333 | nfunctions++, func); | |
334 | } | |
335 | ||
336 | mux++; | |
337 | } | |
338 | } | |
339 | ||
340 | pctldev->num_functions = nfunctions; | |
341 | functions = krealloc(functions, nfunctions * sizeof(*functions), | |
342 | GFP_KERNEL); | |
343 | ||
344 | /* Find pin groups for every single function */ | |
345 | for (i = 0; i < info->npins; i++) { | |
346 | const struct pinctrl_pin_desc *pindesc = info->pins + i; | |
347 | struct zx_pin_data *data = pindesc->drv_data; | |
348 | struct zx_mux_desc *mux; | |
349 | ||
350 | if (!data) | |
351 | continue; | |
352 | ||
353 | mux = data->muxes; | |
354 | while (mux->name) { | |
355 | struct function_desc *func; | |
356 | const char **group; | |
357 | int j; | |
358 | ||
359 | /* Find function for given mux */ | |
360 | for (j = 0; j < nfunctions; j++) | |
361 | if (strcmp(functions[j].name, mux->name) == 0) | |
362 | break; | |
363 | ||
364 | func = functions + j; | |
365 | if (!func->group_names) { | |
366 | func->group_names = devm_kzalloc(&pdev->dev, | |
367 | func->num_group_names * | |
368 | sizeof(*func->group_names), | |
369 | GFP_KERNEL); | |
370 | if (!func->group_names) | |
371 | return -ENOMEM; | |
372 | } | |
373 | ||
374 | group = func->group_names; | |
375 | while (*group) | |
376 | group++; | |
377 | *group = pindesc->name; | |
378 | ||
379 | mux++; | |
380 | } | |
381 | } | |
382 | ||
383 | return 0; | |
384 | } | |
385 | ||
386 | int zx_pinctrl_init(struct platform_device *pdev, | |
387 | struct zx_pinctrl_soc_info *info) | |
388 | { | |
389 | struct pinctrl_desc *pctldesc; | |
390 | struct zx_pinctrl *zpctl; | |
391 | struct device_node *np; | |
392 | struct resource *res; | |
393 | int ret; | |
394 | ||
395 | zpctl = devm_kzalloc(&pdev->dev, sizeof(*zpctl), GFP_KERNEL); | |
396 | if (!zpctl) | |
397 | return -ENOMEM; | |
398 | ||
399 | spin_lock_init(&zpctl->lock); | |
400 | ||
401 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
402 | zpctl->base = devm_ioremap_resource(&pdev->dev, res); | |
403 | if (IS_ERR(zpctl->base)) | |
404 | return PTR_ERR(zpctl->base); | |
405 | ||
406 | np = of_parse_phandle(pdev->dev.of_node, "zte,auxiliary-controller", 0); | |
407 | if (!np) { | |
408 | dev_err(&pdev->dev, "failed to find auxiliary controller\n"); | |
409 | return -ENODEV; | |
410 | } | |
411 | ||
412 | zpctl->aux_base = of_iomap(np, 0); | |
413 | if (!zpctl->aux_base) | |
414 | return -ENOMEM; | |
415 | ||
416 | zpctl->dev = &pdev->dev; | |
417 | zpctl->info = info; | |
418 | ||
419 | pctldesc = devm_kzalloc(&pdev->dev, sizeof(*pctldesc), GFP_KERNEL); | |
420 | if (!pctldesc) | |
421 | return -ENOMEM; | |
422 | ||
423 | pctldesc->name = dev_name(&pdev->dev); | |
424 | pctldesc->owner = THIS_MODULE; | |
425 | pctldesc->pins = info->pins; | |
426 | pctldesc->npins = info->npins; | |
427 | pctldesc->pctlops = &zx_pinctrl_ops; | |
428 | pctldesc->pmxops = &zx_pinmux_ops; | |
429 | pctldesc->confops = &zx_pinconf_ops; | |
430 | ||
431 | zpctl->pctldev = devm_pinctrl_register(&pdev->dev, pctldesc, zpctl); | |
432 | if (IS_ERR(zpctl->pctldev)) { | |
433 | ret = PTR_ERR(zpctl->pctldev); | |
434 | dev_err(&pdev->dev, "failed to register pinctrl: %d\n", ret); | |
435 | return ret; | |
436 | } | |
437 | ||
438 | platform_set_drvdata(pdev, zpctl); | |
439 | ||
440 | ret = zx_pinctrl_build_state(pdev); | |
441 | if (ret) { | |
442 | dev_err(&pdev->dev, "failed to build state: %d\n", ret); | |
443 | return ret; | |
444 | } | |
445 | ||
446 | dev_info(&pdev->dev, "initialized pinctrl driver\n"); | |
447 | return 0; | |
448 | } |