Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2/*
3 * Copyright (C) 2024 Canaan Bright Sight Co. Ltd
4 * Copyright (C) 2024 Ze Huang <18771902331@163.com>
5 */
6#include <linux/module.h>
7#include <linux/device.h>
8#include <linux/of.h>
9#include <linux/of_address.h>
10#include <linux/of_device.h>
11#include <linux/platform_device.h>
12#include <linux/pinctrl/pinctrl.h>
13#include <linux/pinctrl/pinmux.h>
14#include <linux/pinctrl/pinconf.h>
15#include <linux/pinctrl/pinconf-generic.h>
16#include <linux/regmap.h>
17#include <linux/seq_file.h>
18
19#include "core.h"
20#include "pinconf.h"
21
22#define K230_NPINS 64
23
24#define K230_SHIFT_ST (0)
25#define K230_SHIFT_DS (1)
26#define K230_SHIFT_BIAS (5)
27#define K230_SHIFT_PD (5)
28#define K230_SHIFT_PU (6)
29#define K230_SHIFT_OE (7)
30#define K230_SHIFT_IE (8)
31#define K230_SHIFT_MSC (9)
32#define K230_SHIFT_SL (10)
33#define K230_SHIFT_SEL (11)
34
35#define K230_PC_ST BIT(0)
36#define K230_PC_DS GENMASK(4, 1)
37#define K230_PC_PD BIT(5)
38#define K230_PC_PU BIT(6)
39#define K230_PC_BIAS GENMASK(6, 5)
40#define K230_PC_OE BIT(7)
41#define K230_PC_IE BIT(8)
42#define K230_PC_MSC BIT(9)
43#define K230_PC_SL BIT(10)
44#define K230_PC_SEL GENMASK(13, 11)
45
46struct k230_pin_conf {
47 unsigned int func;
48 unsigned long *configs;
49 unsigned int nconfigs;
50};
51
52struct k230_pin_group {
53 const char *name;
54 unsigned int *pins;
55 unsigned int num_pins;
56
57 struct k230_pin_conf *data;
58};
59
60struct k230_pmx_func {
61 const char *name;
62 const char **groups;
63 unsigned int *group_idx;
64 unsigned int ngroups;
65};
66
67struct k230_pinctrl {
68 struct pinctrl_desc pctl;
69 struct pinctrl_dev *pctl_dev;
70 struct regmap *regmap_base;
71 void __iomem *base;
72 struct k230_pin_group *groups;
73 unsigned int ngroups;
74 struct k230_pmx_func *functions;
75 unsigned int nfunctions;
76};
77
78static const struct regmap_config k230_regmap_config = {
79 .name = "canaan,pinctrl",
80 .reg_bits = 32,
81 .val_bits = 32,
82 .max_register = 0x100,
83 .reg_stride = 4,
84};
85
86static int k230_get_groups_count(struct pinctrl_dev *pctldev)
87{
88 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
89
90 return info->ngroups;
91}
92
93static const char *k230_get_group_name(struct pinctrl_dev *pctldev,
94 unsigned int selector)
95{
96 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
97
98 return info->groups[selector].name;
99}
100
101static int k230_get_group_pins(struct pinctrl_dev *pctldev,
102 unsigned int selector,
103 const unsigned int **pins,
104 unsigned int *num_pins)
105{
106 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
107
108 if (selector >= info->ngroups)
109 return -EINVAL;
110
111 *pins = info->groups[selector].pins;
112 *num_pins = info->groups[selector].num_pins;
113
114 return 0;
115}
116
117static inline const struct k230_pmx_func *k230_name_to_funtion(
118 const struct k230_pinctrl *info, const char *name)
119{
120 unsigned int i;
121
122 for (i = 0; i < info->nfunctions; i++) {
123 if (!strcmp(info->functions[i].name, name))
124 return &info->functions[i];
125 }
126
127 return NULL;
128}
129
130static struct pinctrl_pin_desc k230_pins[] = {
131 PINCTRL_PIN(0, "IO0"), PINCTRL_PIN(1, "IO1"), PINCTRL_PIN(2, "IO2"),
132 PINCTRL_PIN(3, "IO3"), PINCTRL_PIN(4, "IO4"), PINCTRL_PIN(5, "IO5"),
133 PINCTRL_PIN(6, "IO6"), PINCTRL_PIN(7, "IO7"), PINCTRL_PIN(8, "IO8"),
134 PINCTRL_PIN(9, "IO9"), PINCTRL_PIN(10, "IO10"), PINCTRL_PIN(11, "IO11"),
135 PINCTRL_PIN(12, "IO12"), PINCTRL_PIN(13, "IO13"), PINCTRL_PIN(14, "IO14"),
136 PINCTRL_PIN(15, "IO15"), PINCTRL_PIN(16, "IO16"), PINCTRL_PIN(17, "IO17"),
137 PINCTRL_PIN(18, "IO18"), PINCTRL_PIN(19, "IO19"), PINCTRL_PIN(20, "IO20"),
138 PINCTRL_PIN(21, "IO21"), PINCTRL_PIN(22, "IO22"), PINCTRL_PIN(23, "IO23"),
139 PINCTRL_PIN(24, "IO24"), PINCTRL_PIN(25, "IO25"), PINCTRL_PIN(26, "IO26"),
140 PINCTRL_PIN(27, "IO27"), PINCTRL_PIN(28, "IO28"), PINCTRL_PIN(29, "IO29"),
141 PINCTRL_PIN(30, "IO30"), PINCTRL_PIN(31, "IO31"), PINCTRL_PIN(32, "IO32"),
142 PINCTRL_PIN(33, "IO33"), PINCTRL_PIN(34, "IO34"), PINCTRL_PIN(35, "IO35"),
143 PINCTRL_PIN(36, "IO36"), PINCTRL_PIN(37, "IO37"), PINCTRL_PIN(38, "IO38"),
144 PINCTRL_PIN(39, "IO39"), PINCTRL_PIN(40, "IO40"), PINCTRL_PIN(41, "IO41"),
145 PINCTRL_PIN(42, "IO42"), PINCTRL_PIN(43, "IO43"), PINCTRL_PIN(44, "IO44"),
146 PINCTRL_PIN(45, "IO45"), PINCTRL_PIN(46, "IO46"), PINCTRL_PIN(47, "IO47"),
147 PINCTRL_PIN(48, "IO48"), PINCTRL_PIN(49, "IO49"), PINCTRL_PIN(50, "IO50"),
148 PINCTRL_PIN(51, "IO51"), PINCTRL_PIN(52, "IO52"), PINCTRL_PIN(53, "IO53"),
149 PINCTRL_PIN(54, "IO54"), PINCTRL_PIN(55, "IO55"), PINCTRL_PIN(56, "IO56"),
150 PINCTRL_PIN(57, "IO57"), PINCTRL_PIN(58, "IO58"), PINCTRL_PIN(59, "IO59"),
151 PINCTRL_PIN(60, "IO60"), PINCTRL_PIN(61, "IO61"), PINCTRL_PIN(62, "IO62"),
152 PINCTRL_PIN(63, "IO63")
153};
154
155static void k230_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
156 struct seq_file *s, unsigned int offset)
157{
158 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
159 u32 val, bias, drive, input, slew, schmitt, power;
160 struct k230_pin_group *grp = k230_pins[offset].drv_data;
161 static const char * const biasing[] = {
162 "pull none", "pull down", "pull up", "" };
163 static const char * const enable[] = {
164 "disable", "enable" };
165 static const char * const power_source[] = {
166 "3V3", "1V8" };
167
168 regmap_read(info->regmap_base, offset * 4, &val);
169
170 drive = (val & K230_PC_DS) >> K230_SHIFT_DS;
171 bias = (val & K230_PC_BIAS) >> K230_SHIFT_BIAS;
172 input = (val & K230_PC_IE) >> K230_SHIFT_IE;
173 slew = (val & K230_PC_SL) >> K230_SHIFT_SL;
174 schmitt = (val & K230_PC_ST) >> K230_SHIFT_ST;
175 power = (val & K230_PC_MSC) >> K230_SHIFT_MSC;
176
177 seq_printf(s, "%s - strength %d - %s - %s - slewrate %s - schmitt %s - %s",
178 grp ? grp->name : "unknown",
179 drive,
180 biasing[bias],
181 input ? "input" : "output",
182 enable[slew],
183 enable[schmitt],
184 power_source[power]);
185}
186
187static int k230_dt_node_to_map(struct pinctrl_dev *pctldev,
188 struct device_node *np_config,
189 struct pinctrl_map **map,
190 unsigned int *num_maps)
191{
192 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
193 struct device *dev = info->pctl_dev->dev;
194 const struct k230_pmx_func *func;
195 const struct k230_pin_group *grp;
196 struct pinctrl_map *new_map;
197 int map_num, i, j, idx;
198 unsigned int grp_id;
199
200 func = k230_name_to_funtion(info, np_config->name);
201 if (!func) {
202 dev_err(dev, "function %s not found\n", np_config->name);
203 return -EINVAL;
204 }
205
206 map_num = 0;
207 for (i = 0; i < func->ngroups; ++i) {
208 grp_id = func->group_idx[i];
209 /* npins of config map plus a mux map */
210 map_num += info->groups[grp_id].num_pins + 1;
211 }
212
213 new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);
214 if (!new_map)
215 return -ENOMEM;
216 *map = new_map;
217 *num_maps = map_num;
218
219 idx = 0;
220 for (i = 0; i < func->ngroups; ++i) {
221 grp_id = func->group_idx[i];
222 grp = &info->groups[grp_id];
223 new_map[idx].type = PIN_MAP_TYPE_MUX_GROUP;
224 new_map[idx].data.mux.group = grp->name;
225 new_map[idx].data.mux.function = np_config->name;
226 idx++;
227
228 for (j = 0; j < grp->num_pins; ++j) {
229 new_map[idx].type = PIN_MAP_TYPE_CONFIGS_PIN;
230 new_map[idx].data.configs.group_or_pin =
231 pin_get_name(pctldev, grp->pins[j]);
232 new_map[idx].data.configs.configs =
233 grp->data[j].configs;
234 new_map[idx].data.configs.num_configs =
235 grp->data[j].nconfigs;
236 idx++;
237 }
238 }
239
240 return 0;
241}
242
243static void k230_dt_free_map(struct pinctrl_dev *pctldev,
244 struct pinctrl_map *map, unsigned int num_maps)
245{
246 kfree(map);
247}
248
249static const struct pinctrl_ops k230_pctrl_ops = {
250 .get_groups_count = k230_get_groups_count,
251 .get_group_name = k230_get_group_name,
252 .get_group_pins = k230_get_group_pins,
253 .pin_dbg_show = k230_pinctrl_pin_dbg_show,
254 .dt_node_to_map = k230_dt_node_to_map,
255 .dt_free_map = k230_dt_free_map,
256};
257
258static int k230_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
259 unsigned long *config)
260{
261 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
262 enum pin_config_param param = pinconf_to_config_param(*config);
263 unsigned int val, arg;
264
265 regmap_read(info->regmap_base, pin * 4, &val);
266
267 switch (param) {
268 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
269 arg = (val & K230_PC_ST) ? 1 : 0;
270 break;
271 case PIN_CONFIG_DRIVE_STRENGTH:
272 arg = (val & K230_PC_DS) >> K230_SHIFT_DS;
273 break;
274 case PIN_CONFIG_BIAS_DISABLE:
275 arg = (val & K230_PC_BIAS) ? 0 : 1;
276 break;
277 case PIN_CONFIG_BIAS_PULL_DOWN:
278 arg = (val & K230_PC_PD) ? 1 : 0;
279 break;
280 case PIN_CONFIG_BIAS_PULL_UP:
281 arg = (val & K230_PC_PU) ? 1 : 0;
282 break;
283 case PIN_CONFIG_OUTPUT_ENABLE:
284 arg = (val & K230_PC_OE) ? 1 : 0;
285 break;
286 case PIN_CONFIG_INPUT_ENABLE:
287 arg = (val & K230_PC_IE) ? 1 : 0;
288 break;
289 case PIN_CONFIG_POWER_SOURCE:
290 arg = (val & K230_PC_MSC) ? 1 : 0;
291 break;
292 case PIN_CONFIG_SLEW_RATE:
293 arg = (val & K230_PC_SL) ? 1 : 0;
294 break;
295 default:
296 return -EINVAL;
297 }
298
299 *config = pinconf_to_config_packed(param, arg);
300
301 return 0;
302}
303
304static int k230_pinconf_set_param(struct pinctrl_dev *pctldev, unsigned int pin,
305 enum pin_config_param param, unsigned int arg)
306{
307 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
308 unsigned int val;
309
310 regmap_read(info->regmap_base, pin * 4, &val);
311
312 switch (param) {
313 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
314 if (arg)
315 val |= K230_PC_ST;
316 else
317 val &= ~K230_PC_ST;
318 break;
319 case PIN_CONFIG_DRIVE_STRENGTH:
320 val &= ~K230_PC_DS;
321 val |= (arg << K230_SHIFT_DS) & K230_PC_DS;
322 break;
323 case PIN_CONFIG_BIAS_DISABLE:
324 val &= ~K230_PC_BIAS;
325 break;
326 case PIN_CONFIG_BIAS_PULL_DOWN:
327 if (!arg)
328 return -EINVAL;
329 val |= K230_PC_PD;
330 break;
331 case PIN_CONFIG_BIAS_PULL_UP:
332 if (!arg)
333 return -EINVAL;
334 val |= K230_PC_PU;
335 break;
336 case PIN_CONFIG_OUTPUT_ENABLE:
337 if (!arg)
338 return -EINVAL;
339 val |= K230_PC_OE;
340 break;
341 case PIN_CONFIG_INPUT_ENABLE:
342 if (!arg)
343 return -EINVAL;
344 val |= K230_PC_IE;
345 break;
346 case PIN_CONFIG_POWER_SOURCE:
347 if (arg)
348 val |= K230_PC_MSC;
349 else
350 val &= ~K230_PC_MSC;
351 break;
352 case PIN_CONFIG_SLEW_RATE:
353 if (arg)
354 val |= K230_PC_SL;
355 else
356 val &= ~K230_PC_SL;
357 break;
358 default:
359 return -EINVAL;
360 }
361
362 regmap_write(info->regmap_base, pin * 4, val);
363
364 return 0;
365}
366
367static int k230_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
368 unsigned long *configs, unsigned int num_configs)
369{
370 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
371 struct device *dev = info->pctl_dev->dev;
372 enum pin_config_param param;
373 unsigned int arg, i;
374 int ret;
375
376 if (pin >= K230_NPINS) {
377 dev_err(dev, "pin number out of range\n");
378 return -EINVAL;
379 }
380
381 for (i = 0; i < num_configs; i++) {
382 param = pinconf_to_config_param(configs[i]);
383 arg = pinconf_to_config_argument(configs[i]);
384 ret = k230_pinconf_set_param(pctldev, pin, param, arg);
385 if (ret)
386 return ret;
387 }
388
389 return 0;
390}
391
392static void k230_pconf_dbg_show(struct pinctrl_dev *pctldev,
393 struct seq_file *s, unsigned int pin)
394{
395 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
396 unsigned int val;
397
398 regmap_read(info->regmap_base, pin * 4, &val);
399
400 seq_printf(s, " 0x%08x", val);
401}
402
403static const struct pinconf_ops k230_pinconf_ops = {
404 .is_generic = true,
405 .pin_config_get = k230_pinconf_get,
406 .pin_config_set = k230_pinconf_set,
407 .pin_config_dbg_show = k230_pconf_dbg_show,
408};
409
410static int k230_get_functions_count(struct pinctrl_dev *pctldev)
411{
412 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
413
414 return info->nfunctions;
415}
416
417static const char *k230_get_fname(struct pinctrl_dev *pctldev,
418 unsigned int selector)
419{
420 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
421
422 return info->functions[selector].name;
423}
424
425static int k230_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
426 const char * const **groups, unsigned int *num_groups)
427{
428 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
429
430 *groups = info->functions[selector].groups;
431 *num_groups = info->functions[selector].ngroups;
432
433 return 0;
434}
435
436static int k230_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
437 unsigned int group)
438{
439 struct k230_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
440 const struct k230_pin_conf *data = info->groups[group].data;
441 struct k230_pin_group *grp = &info->groups[group];
442 const unsigned int *pins = grp->pins;
443 struct regmap *regmap;
444 unsigned int value, mask;
445 int cnt, reg;
446
447 regmap = info->regmap_base;
448
449 for (cnt = 0; cnt < grp->num_pins; cnt++) {
450 reg = pins[cnt] * 4;
451 value = data[cnt].func << K230_SHIFT_SEL;
452 mask = K230_PC_SEL;
453 regmap_update_bits(regmap, reg, mask, value);
454 k230_pins[pins[cnt]].drv_data = grp;
455 }
456
457 return 0;
458}
459
460static const struct pinmux_ops k230_pmxops = {
461 .get_functions_count = k230_get_functions_count,
462 .get_function_name = k230_get_fname,
463 .get_function_groups = k230_get_groups,
464 .set_mux = k230_set_mux,
465 .strict = true,
466};
467
468static int k230_pinctrl_parse_groups(struct device_node *np,
469 struct k230_pin_group *grp,
470 struct k230_pinctrl *info,
471 unsigned int index)
472{
473 struct device *dev = info->pctl_dev->dev;
474 const __be32 *list;
475 int size, i, ret;
476
477 grp->name = np->name;
478
479 list = of_get_property(np, "pinmux", &size);
480 if (!list) {
481 dev_err(dev, "failed to get pinmux property\n");
482 return -EINVAL;
483 }
484 size /= sizeof(*list);
485
486 grp->num_pins = size;
487 grp->pins = devm_kcalloc(dev, grp->num_pins, sizeof(*grp->pins),
488 GFP_KERNEL);
489 grp->data = devm_kcalloc(dev, grp->num_pins, sizeof(*grp->data),
490 GFP_KERNEL);
491 if (!grp->pins || !grp->data)
492 return -ENOMEM;
493
494 for (i = 0; i < size; i++) {
495 unsigned int mux_data = be32_to_cpu(*list++);
496
497 grp->pins[i] = (mux_data >> 8);
498 grp->data[i].func = (mux_data & 0xff);
499
500 ret = pinconf_generic_parse_dt_config(np, NULL,
501 &grp->data[i].configs,
502 &grp->data[i].nconfigs);
503 if (ret)
504 return ret;
505 }
506
507 return 0;
508}
509
510static int k230_pinctrl_parse_functions(struct device_node *np,
511 struct k230_pinctrl *info,
512 unsigned int index)
513{
514 struct device *dev = info->pctl_dev->dev;
515 struct k230_pmx_func *func;
516 struct k230_pin_group *grp;
517 static unsigned int idx, i;
518 int ret;
519
520 func = &info->functions[index];
521
522 func->name = np->name;
523 func->ngroups = of_get_child_count(np);
524 if (func->ngroups <= 0)
525 return 0;
526
527 func->groups = devm_kcalloc(dev, func->ngroups,
528 sizeof(*func->groups), GFP_KERNEL);
529 func->group_idx = devm_kcalloc(dev, func->ngroups,
530 sizeof(*func->group_idx), GFP_KERNEL);
531 if (!func->groups || !func->group_idx)
532 return -ENOMEM;
533
534 i = 0;
535
536 for_each_child_of_node_scoped(np, child) {
537 func->groups[i] = child->name;
538 func->group_idx[i] = idx;
539 grp = &info->groups[idx];
540 idx++;
541 ret = k230_pinctrl_parse_groups(child, grp, info, i++);
542 if (ret)
543 return ret;
544 }
545
546 return 0;
547}
548
549static void k230_pinctrl_child_count(struct k230_pinctrl *info,
550 struct device_node *np)
551{
552 for_each_child_of_node_scoped(np, child) {
553 info->nfunctions++;
554 info->ngroups += of_get_child_count(child);
555 }
556}
557
558static int k230_pinctrl_parse_dt(struct platform_device *pdev,
559 struct k230_pinctrl *info)
560{
561 struct device *dev = &pdev->dev;
562 struct device_node *np = dev->of_node;
563 unsigned int i;
564 int ret;
565
566 k230_pinctrl_child_count(info, np);
567
568 info->functions = devm_kcalloc(dev, info->nfunctions,
569 sizeof(*info->functions), GFP_KERNEL);
570 info->groups = devm_kcalloc(dev, info->ngroups,
571 sizeof(*info->groups), GFP_KERNEL);
572 if (!info->functions || !info->groups)
573 return -ENOMEM;
574
575 i = 0;
576
577 for_each_child_of_node_scoped(np, child) {
578 ret = k230_pinctrl_parse_functions(child, info, i++);
579 if (ret) {
580 dev_err(dev, "failed to parse function\n");
581 return ret;
582 }
583 }
584
585 return 0;
586}
587
588static int k230_pinctrl_probe(struct platform_device *pdev)
589{
590 struct device *dev = &pdev->dev;
591 struct k230_pinctrl *info;
592 struct pinctrl_desc *pctl;
593 int ret;
594
595 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
596 if (!info)
597 return -ENOMEM;
598
599 pctl = &info->pctl;
600
601 pctl->name = "k230-pinctrl";
602 pctl->owner = THIS_MODULE;
603 pctl->pins = k230_pins;
604 pctl->npins = ARRAY_SIZE(k230_pins);
605 pctl->pctlops = &k230_pctrl_ops;
606 pctl->pmxops = &k230_pmxops;
607 pctl->confops = &k230_pinconf_ops;
608
609 info->base = devm_platform_ioremap_resource(pdev, 0);
610 if (IS_ERR(info->base))
611 return PTR_ERR(info->base);
612
613 info->regmap_base = devm_regmap_init_mmio(dev, info->base,
614 &k230_regmap_config);
615 if (IS_ERR(info->regmap_base))
616 return dev_err_probe(dev, PTR_ERR(info->regmap_base),
617 "failed to init regmap\n");
618
619 ret = k230_pinctrl_parse_dt(pdev, info);
620 if (ret)
621 return ret;
622
623 info->pctl_dev = devm_pinctrl_register(dev, pctl, info);
624 if (IS_ERR(info->pctl_dev))
625 return dev_err_probe(dev, PTR_ERR(info->pctl_dev),
626 "devm_pinctrl_register failed\n");
627
628 return 0;
629}
630
631static const struct of_device_id k230_dt_ids[] = {
632 { .compatible = "canaan,k230-pinctrl", },
633 { /* sentinel */ }
634};
635MODULE_DEVICE_TABLE(of, k230_dt_ids);
636
637static struct platform_driver k230_pinctrl_driver = {
638 .probe = k230_pinctrl_probe,
639 .driver = {
640 .name = "k230-pinctrl",
641 .of_match_table = k230_dt_ids,
642 },
643};
644module_platform_driver(k230_pinctrl_driver);
645
646MODULE_LICENSE("GPL");
647MODULE_AUTHOR("Ze Huang <18771902331@163.com>");
648MODULE_DESCRIPTION("Canaan K230 pinctrl driver");