1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Google LLC
4 * Copyright (c) 2021 Aspeed Technology Inc.
5 */
6#include <linux/device.h>
7#include <linux/module.h>
8#include <linux/of.h>
9#include <linux/mfd/syscon.h>
10#include <linux/regmap.h>
11#include <linux/platform_device.h>
12
13/* register offsets */
14#define HICR9 0x98
15#define HICRA 0x9c
16
17/* attributes options */
18#define UART_ROUTING_IO1 "io1"
19#define UART_ROUTING_IO2 "io2"
20#define UART_ROUTING_IO3 "io3"
21#define UART_ROUTING_IO4 "io4"
22#define UART_ROUTING_IO5 "io5"
23#define UART_ROUTING_IO6 "io6"
24#define UART_ROUTING_IO10 "io10"
25#define UART_ROUTING_UART1 "uart1"
26#define UART_ROUTING_UART2 "uart2"
27#define UART_ROUTING_UART3 "uart3"
28#define UART_ROUTING_UART4 "uart4"
29#define UART_ROUTING_UART5 "uart5"
30#define UART_ROUTING_UART6 "uart6"
31#define UART_ROUTING_UART10 "uart10"
32#define UART_ROUTING_RES "reserved"
33
34struct aspeed_uart_routing {
35 struct regmap *map;
36 struct attribute_group const *attr_grp;
37};
38
39struct aspeed_uart_routing_selector {
40 struct device_attribute dev_attr;
41 uint8_t reg;
42 uint8_t mask;
43 uint8_t shift;
44 const char *const options[];
45};
46
47#define to_routing_selector(_dev_attr) \
48 container_of(_dev_attr, struct aspeed_uart_routing_selector, dev_attr)
49
50static ssize_t aspeed_uart_routing_show(struct device *dev,
51 struct device_attribute *attr,
52 char *buf);
53
54static ssize_t aspeed_uart_routing_store(struct device *dev,
55 struct device_attribute *attr,
56 const char *buf, size_t count);
57
58#define ROUTING_ATTR(_name) { \
59 .attr = {.name = _name, \
60 .mode = VERIFY_OCTAL_PERMISSIONS(0644) }, \
61 .show = aspeed_uart_routing_show, \
62 .store = aspeed_uart_routing_store, \
63}
64
65/* routing selector for AST25xx */
66static struct aspeed_uart_routing_selector ast2500_io6_sel = {
67 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO6),
68 .reg = HICR9,
69 .shift = 8,
70 .mask = 0xf,
71 .options = {
72 UART_ROUTING_UART1,
73 UART_ROUTING_UART2,
74 UART_ROUTING_UART3,
75 UART_ROUTING_UART4,
76 UART_ROUTING_UART5,
77 UART_ROUTING_IO1,
78 UART_ROUTING_IO2,
79 UART_ROUTING_IO3,
80 UART_ROUTING_IO4,
81 UART_ROUTING_IO5,
82 NULL,
83 },
84};
85
86static struct aspeed_uart_routing_selector ast2500_uart5_sel = {
87 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART5),
88 .reg = HICRA,
89 .shift = 28,
90 .mask = 0xf,
91 .options = {
92 UART_ROUTING_IO5,
93 UART_ROUTING_IO1,
94 UART_ROUTING_IO2,
95 UART_ROUTING_IO3,
96 UART_ROUTING_IO4,
97 UART_ROUTING_UART1,
98 UART_ROUTING_UART2,
99 UART_ROUTING_UART3,
100 UART_ROUTING_UART4,
101 UART_ROUTING_IO6,
102 NULL,
103 },
104};
105
106static struct aspeed_uart_routing_selector ast2500_uart4_sel = {
107 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART4),
108 .reg = HICRA,
109 .shift = 25,
110 .mask = 0x7,
111 .options = {
112 UART_ROUTING_IO4,
113 UART_ROUTING_IO1,
114 UART_ROUTING_IO2,
115 UART_ROUTING_IO3,
116 UART_ROUTING_UART1,
117 UART_ROUTING_UART2,
118 UART_ROUTING_UART3,
119 UART_ROUTING_IO6,
120 NULL,
121 },
122};
123
124static struct aspeed_uart_routing_selector ast2500_uart3_sel = {
125 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART3),
126 .reg = HICRA,
127 .shift = 22,
128 .mask = 0x7,
129 .options = {
130 UART_ROUTING_IO3,
131 UART_ROUTING_IO4,
132 UART_ROUTING_IO1,
133 UART_ROUTING_IO2,
134 UART_ROUTING_UART4,
135 UART_ROUTING_UART1,
136 UART_ROUTING_UART2,
137 UART_ROUTING_IO6,
138 NULL,
139 },
140};
141
142static struct aspeed_uart_routing_selector ast2500_uart2_sel = {
143 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART2),
144 .reg = HICRA,
145 .shift = 19,
146 .mask = 0x7,
147 .options = {
148 UART_ROUTING_IO2,
149 UART_ROUTING_IO3,
150 UART_ROUTING_IO4,
151 UART_ROUTING_IO1,
152 UART_ROUTING_UART3,
153 UART_ROUTING_UART4,
154 UART_ROUTING_UART1,
155 UART_ROUTING_IO6,
156 NULL,
157 },
158};
159
160static struct aspeed_uart_routing_selector ast2500_uart1_sel = {
161 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART1),
162 .reg = HICRA,
163 .shift = 16,
164 .mask = 0x7,
165 .options = {
166 UART_ROUTING_IO1,
167 UART_ROUTING_IO2,
168 UART_ROUTING_IO3,
169 UART_ROUTING_IO4,
170 UART_ROUTING_UART2,
171 UART_ROUTING_UART3,
172 UART_ROUTING_UART4,
173 UART_ROUTING_IO6,
174 NULL,
175 },
176};
177
178static struct aspeed_uart_routing_selector ast2500_io5_sel = {
179 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO5),
180 .reg = HICRA,
181 .shift = 12,
182 .mask = 0x7,
183 .options = {
184 UART_ROUTING_UART5,
185 UART_ROUTING_UART1,
186 UART_ROUTING_UART2,
187 UART_ROUTING_UART3,
188 UART_ROUTING_UART4,
189 UART_ROUTING_IO1,
190 UART_ROUTING_IO3,
191 UART_ROUTING_IO6,
192 NULL,
193 },
194};
195
196static struct aspeed_uart_routing_selector ast2500_io4_sel = {
197 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO4),
198 .reg = HICRA,
199 .shift = 9,
200 .mask = 0x7,
201 .options = {
202 UART_ROUTING_UART4,
203 UART_ROUTING_UART5,
204 UART_ROUTING_UART1,
205 UART_ROUTING_UART2,
206 UART_ROUTING_UART3,
207 UART_ROUTING_IO1,
208 UART_ROUTING_IO2,
209 UART_ROUTING_IO6,
210 NULL,
211 },
212};
213
214static struct aspeed_uart_routing_selector ast2500_io3_sel = {
215 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO3),
216 .reg = HICRA,
217 .shift = 6,
218 .mask = 0x7,
219 .options = {
220 UART_ROUTING_UART3,
221 UART_ROUTING_UART4,
222 UART_ROUTING_UART5,
223 UART_ROUTING_UART1,
224 UART_ROUTING_UART2,
225 UART_ROUTING_IO1,
226 UART_ROUTING_IO2,
227 UART_ROUTING_IO6,
228 NULL,
229 },
230};
231
232static struct aspeed_uart_routing_selector ast2500_io2_sel = {
233 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO2),
234 .reg = HICRA,
235 .shift = 3,
236 .mask = 0x7,
237 .options = {
238 UART_ROUTING_UART2,
239 UART_ROUTING_UART3,
240 UART_ROUTING_UART4,
241 UART_ROUTING_UART5,
242 UART_ROUTING_UART1,
243 UART_ROUTING_IO3,
244 UART_ROUTING_IO4,
245 UART_ROUTING_IO6,
246 NULL,
247 },
248};
249
250static struct aspeed_uart_routing_selector ast2500_io1_sel = {
251 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO1),
252 .reg = HICRA,
253 .shift = 0,
254 .mask = 0x7,
255 .options = {
256 UART_ROUTING_UART1,
257 UART_ROUTING_UART2,
258 UART_ROUTING_UART3,
259 UART_ROUTING_UART4,
260 UART_ROUTING_UART5,
261 UART_ROUTING_IO3,
262 UART_ROUTING_IO4,
263 UART_ROUTING_IO6,
264 NULL,
265 },
266};
267
268static struct attribute *ast2500_uart_routing_attrs[] = {
269 &ast2500_io6_sel.dev_attr.attr,
270 &ast2500_uart5_sel.dev_attr.attr,
271 &ast2500_uart4_sel.dev_attr.attr,
272 &ast2500_uart3_sel.dev_attr.attr,
273 &ast2500_uart2_sel.dev_attr.attr,
274 &ast2500_uart1_sel.dev_attr.attr,
275 &ast2500_io5_sel.dev_attr.attr,
276 &ast2500_io4_sel.dev_attr.attr,
277 &ast2500_io3_sel.dev_attr.attr,
278 &ast2500_io2_sel.dev_attr.attr,
279 &ast2500_io1_sel.dev_attr.attr,
280 NULL,
281};
282
283static const struct attribute_group ast2500_uart_routing_attr_group = {
284 .attrs = ast2500_uart_routing_attrs,
285};
286
287/* routing selector for AST26xx */
288static struct aspeed_uart_routing_selector ast2600_uart10_sel = {
289 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART10),
290 .reg = HICR9,
291 .shift = 12,
292 .mask = 0xf,
293 .options = {
294 UART_ROUTING_IO10,
295 UART_ROUTING_IO1,
296 UART_ROUTING_IO2,
297 UART_ROUTING_IO3,
298 UART_ROUTING_IO4,
299 UART_ROUTING_RES,
300 UART_ROUTING_UART1,
301 UART_ROUTING_UART2,
302 UART_ROUTING_UART3,
303 UART_ROUTING_UART4,
304 NULL,
305 },
306};
307
308static struct aspeed_uart_routing_selector ast2600_io10_sel = {
309 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO10),
310 .reg = HICR9,
311 .shift = 8,
312 .mask = 0xf,
313 .options = {
314 UART_ROUTING_UART1,
315 UART_ROUTING_UART2,
316 UART_ROUTING_UART3,
317 UART_ROUTING_UART4,
318 UART_ROUTING_RES,
319 UART_ROUTING_IO1,
320 UART_ROUTING_IO2,
321 UART_ROUTING_IO3,
322 UART_ROUTING_IO4,
323 UART_ROUTING_RES,
324 UART_ROUTING_UART10,
325 NULL,
326 },
327};
328
329static struct aspeed_uart_routing_selector ast2600_uart4_sel = {
330 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART4),
331 .reg = HICRA,
332 .shift = 25,
333 .mask = 0x7,
334 .options = {
335 UART_ROUTING_IO4,
336 UART_ROUTING_IO1,
337 UART_ROUTING_IO2,
338 UART_ROUTING_IO3,
339 UART_ROUTING_UART1,
340 UART_ROUTING_UART2,
341 UART_ROUTING_UART3,
342 UART_ROUTING_IO10,
343 NULL,
344 },
345};
346
347static struct aspeed_uart_routing_selector ast2600_uart3_sel = {
348 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART3),
349 .reg = HICRA,
350 .shift = 22,
351 .mask = 0x7,
352 .options = {
353 UART_ROUTING_IO3,
354 UART_ROUTING_IO4,
355 UART_ROUTING_IO1,
356 UART_ROUTING_IO2,
357 UART_ROUTING_UART4,
358 UART_ROUTING_UART1,
359 UART_ROUTING_UART2,
360 UART_ROUTING_IO10,
361 NULL,
362 },
363};
364
365static struct aspeed_uart_routing_selector ast2600_uart2_sel = {
366 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART2),
367 .reg = HICRA,
368 .shift = 19,
369 .mask = 0x7,
370 .options = {
371 UART_ROUTING_IO2,
372 UART_ROUTING_IO3,
373 UART_ROUTING_IO4,
374 UART_ROUTING_IO1,
375 UART_ROUTING_UART3,
376 UART_ROUTING_UART4,
377 UART_ROUTING_UART1,
378 UART_ROUTING_IO10,
379 NULL,
380 },
381};
382
383static struct aspeed_uart_routing_selector ast2600_uart1_sel = {
384 .dev_attr = ROUTING_ATTR(UART_ROUTING_UART1),
385 .reg = HICRA,
386 .shift = 16,
387 .mask = 0x7,
388 .options = {
389 UART_ROUTING_IO1,
390 UART_ROUTING_IO2,
391 UART_ROUTING_IO3,
392 UART_ROUTING_IO4,
393 UART_ROUTING_UART2,
394 UART_ROUTING_UART3,
395 UART_ROUTING_UART4,
396 UART_ROUTING_IO10,
397 NULL,
398 },
399};
400
401static struct aspeed_uart_routing_selector ast2600_io4_sel = {
402 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO4),
403 .reg = HICRA,
404 .shift = 9,
405 .mask = 0x7,
406 .options = {
407 UART_ROUTING_UART4,
408 UART_ROUTING_UART10,
409 UART_ROUTING_UART1,
410 UART_ROUTING_UART2,
411 UART_ROUTING_UART3,
412 UART_ROUTING_IO1,
413 UART_ROUTING_IO2,
414 UART_ROUTING_IO10,
415 NULL,
416 },
417};
418
419static struct aspeed_uart_routing_selector ast2600_io3_sel = {
420 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO3),
421 .reg = HICRA,
422 .shift = 6,
423 .mask = 0x7,
424 .options = {
425 UART_ROUTING_UART3,
426 UART_ROUTING_UART4,
427 UART_ROUTING_UART10,
428 UART_ROUTING_UART1,
429 UART_ROUTING_UART2,
430 UART_ROUTING_IO1,
431 UART_ROUTING_IO2,
432 UART_ROUTING_IO10,
433 NULL,
434 },
435};
436
437static struct aspeed_uart_routing_selector ast2600_io2_sel = {
438 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO2),
439 .reg = HICRA,
440 .shift = 3,
441 .mask = 0x7,
442 .options = {
443 UART_ROUTING_UART2,
444 UART_ROUTING_UART3,
445 UART_ROUTING_UART4,
446 UART_ROUTING_UART10,
447 UART_ROUTING_UART1,
448 UART_ROUTING_IO3,
449 UART_ROUTING_IO4,
450 UART_ROUTING_IO10,
451 NULL,
452 },
453};
454
455static struct aspeed_uart_routing_selector ast2600_io1_sel = {
456 .dev_attr = ROUTING_ATTR(UART_ROUTING_IO1),
457 .reg = HICRA,
458 .shift = 0,
459 .mask = 0x7,
460 .options = {
461 UART_ROUTING_UART1,
462 UART_ROUTING_UART2,
463 UART_ROUTING_UART3,
464 UART_ROUTING_UART4,
465 UART_ROUTING_UART10,
466 UART_ROUTING_IO3,
467 UART_ROUTING_IO4,
468 UART_ROUTING_IO10,
469 NULL,
470 },
471};
472
473static struct attribute *ast2600_uart_routing_attrs[] = {
474 &ast2600_uart10_sel.dev_attr.attr,
475 &ast2600_io10_sel.dev_attr.attr,
476 &ast2600_uart4_sel.dev_attr.attr,
477 &ast2600_uart3_sel.dev_attr.attr,
478 &ast2600_uart2_sel.dev_attr.attr,
479 &ast2600_uart1_sel.dev_attr.attr,
480 &ast2600_io4_sel.dev_attr.attr,
481 &ast2600_io3_sel.dev_attr.attr,
482 &ast2600_io2_sel.dev_attr.attr,
483 &ast2600_io1_sel.dev_attr.attr,
484 NULL,
485};
486
487static const struct attribute_group ast2600_uart_routing_attr_group = {
488 .attrs = ast2600_uart_routing_attrs,
489};
490
491static ssize_t aspeed_uart_routing_show(struct device *dev,
492 struct device_attribute *attr,
493 char *buf)
494{
495 struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
496 struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
497 int val, pos, len;
498
499 regmap_read(map: uart_routing->map, reg: sel->reg, val: &val);
500 val = (val >> sel->shift) & sel->mask;
501
502 len = 0;
503 for (pos = 0; sel->options[pos] != NULL; ++pos) {
504 if (pos == val)
505 len += sysfs_emit_at(buf, at: len, fmt: "[%s] ", sel->options[pos]);
506 else
507 len += sysfs_emit_at(buf, at: len, fmt: "%s ", sel->options[pos]);
508 }
509
510 if (val >= pos)
511 len += sysfs_emit_at(buf, at: len, fmt: "[unknown(%d)]", val);
512
513 len += sysfs_emit_at(buf, at: len, fmt: "\n");
514
515 return len;
516}
517
518static ssize_t aspeed_uart_routing_store(struct device *dev,
519 struct device_attribute *attr,
520 const char *buf, size_t count)
521{
522 struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
523 struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
524 int val;
525
526 val = __sysfs_match_string(array: sel->options, n: -1, s: buf);
527 if (val < 0) {
528 dev_err(dev, "invalid value \"%s\"\n", buf);
529 return -EINVAL;
530 }
531
532 regmap_update_bits(map: uart_routing->map, reg: sel->reg,
533 mask: (sel->mask << sel->shift),
534 val: (val & sel->mask) << sel->shift);
535
536 return count;
537}
538
539static int aspeed_uart_routing_probe(struct platform_device *pdev)
540{
541 int rc;
542 struct device *dev = &pdev->dev;
543 struct aspeed_uart_routing *uart_routing;
544
545 uart_routing = devm_kzalloc(dev: &pdev->dev, size: sizeof(*uart_routing), GFP_KERNEL);
546 if (!uart_routing)
547 return -ENOMEM;
548
549 uart_routing->map = syscon_node_to_regmap(np: dev->parent->of_node);
550 if (IS_ERR(ptr: uart_routing->map)) {
551 dev_err(dev, "cannot get regmap\n");
552 return PTR_ERR(ptr: uart_routing->map);
553 }
554
555 uart_routing->attr_grp = of_device_get_match_data(dev);
556
557 rc = sysfs_create_group(kobj: &dev->kobj, grp: uart_routing->attr_grp);
558 if (rc < 0)
559 return rc;
560
561 dev_set_drvdata(dev, data: uart_routing);
562
563 dev_info(dev, "module loaded\n");
564
565 return 0;
566}
567
568static void aspeed_uart_routing_remove(struct platform_device *pdev)
569{
570 struct device *dev = &pdev->dev;
571 struct aspeed_uart_routing *uart_routing = platform_get_drvdata(pdev);
572
573 sysfs_remove_group(kobj: &dev->kobj, grp: uart_routing->attr_grp);
574}
575
576static const struct of_device_id aspeed_uart_routing_table[] = {
577 { .compatible = "aspeed,ast2400-uart-routing",
578 .data = &ast2500_uart_routing_attr_group },
579 { .compatible = "aspeed,ast2500-uart-routing",
580 .data = &ast2500_uart_routing_attr_group },
581 { .compatible = "aspeed,ast2600-uart-routing",
582 .data = &ast2600_uart_routing_attr_group },
583 { },
584};
585
586static struct platform_driver aspeed_uart_routing_driver = {
587 .driver = {
588 .name = "aspeed-uart-routing",
589 .of_match_table = aspeed_uart_routing_table,
590 },
591 .probe = aspeed_uart_routing_probe,
592 .remove_new = aspeed_uart_routing_remove,
593};
594
595module_platform_driver(aspeed_uart_routing_driver);
596
597MODULE_AUTHOR("Oskar Senft <osk@google.com>");
598MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com>");
599MODULE_LICENSE("GPL v2");
600MODULE_DESCRIPTION("Driver to configure Aspeed UART routing");
601

source code of linux/drivers/soc/aspeed/aspeed-uart-routing.c