1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2018 Google LLC
4 * Copyright (c) 2021 Aspeed Technology Inc.
6 #include <linux/device.h>
7 #include <linux/module.h>
9 #include <linux/mfd/syscon.h>
10 #include <linux/regmap.h>
11 #include <linux/platform_device.h>
13 /* register offsets */
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"
34 struct aspeed_uart_routing
{
36 struct attribute_group
const *attr_grp
;
39 struct aspeed_uart_routing_selector
{
40 struct device_attribute dev_attr
;
44 const char *const options
[];
47 #define to_routing_selector(_dev_attr) \
48 container_of(_dev_attr, struct aspeed_uart_routing_selector, dev_attr)
50 static ssize_t
aspeed_uart_routing_show(struct device
*dev
,
51 struct device_attribute
*attr
,
54 static ssize_t
aspeed_uart_routing_store(struct device
*dev
,
55 struct device_attribute
*attr
,
56 const char *buf
, size_t count
);
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, \
65 /* routing selector for AST25xx */
66 static struct aspeed_uart_routing_selector ast2500_io6_sel
= {
67 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO6
),
86 static struct aspeed_uart_routing_selector ast2500_uart5_sel
= {
87 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART5
),
106 static struct aspeed_uart_routing_selector ast2500_uart4_sel
= {
107 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART4
),
124 static struct aspeed_uart_routing_selector ast2500_uart3_sel
= {
125 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART3
),
142 static struct aspeed_uart_routing_selector ast2500_uart2_sel
= {
143 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART2
),
160 static struct aspeed_uart_routing_selector ast2500_uart1_sel
= {
161 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART1
),
178 static struct aspeed_uart_routing_selector ast2500_io5_sel
= {
179 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO5
),
196 static struct aspeed_uart_routing_selector ast2500_io4_sel
= {
197 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO4
),
214 static struct aspeed_uart_routing_selector ast2500_io3_sel
= {
215 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO3
),
232 static struct aspeed_uart_routing_selector ast2500_io2_sel
= {
233 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO2
),
250 static struct aspeed_uart_routing_selector ast2500_io1_sel
= {
251 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO1
),
268 static 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
,
283 static const struct attribute_group ast2500_uart_routing_attr_group
= {
284 .attrs
= ast2500_uart_routing_attrs
,
287 /* routing selector for AST26xx */
288 static struct aspeed_uart_routing_selector ast2600_uart10_sel
= {
289 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART10
),
308 static struct aspeed_uart_routing_selector ast2600_io10_sel
= {
309 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO10
),
329 static struct aspeed_uart_routing_selector ast2600_uart4_sel
= {
330 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART4
),
347 static struct aspeed_uart_routing_selector ast2600_uart3_sel
= {
348 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART3
),
365 static struct aspeed_uart_routing_selector ast2600_uart2_sel
= {
366 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART2
),
383 static struct aspeed_uart_routing_selector ast2600_uart1_sel
= {
384 .dev_attr
= ROUTING_ATTR(UART_ROUTING_UART1
),
401 static struct aspeed_uart_routing_selector ast2600_io4_sel
= {
402 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO4
),
419 static struct aspeed_uart_routing_selector ast2600_io3_sel
= {
420 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO3
),
437 static struct aspeed_uart_routing_selector ast2600_io2_sel
= {
438 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO2
),
455 static struct aspeed_uart_routing_selector ast2600_io1_sel
= {
456 .dev_attr
= ROUTING_ATTR(UART_ROUTING_IO1
),
473 static 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
,
487 static const struct attribute_group ast2600_uart_routing_attr_group
= {
488 .attrs
= ast2600_uart_routing_attrs
,
491 static ssize_t
aspeed_uart_routing_show(struct device
*dev
,
492 struct device_attribute
*attr
,
495 struct aspeed_uart_routing
*uart_routing
= dev_get_drvdata(dev
);
496 struct aspeed_uart_routing_selector
*sel
= to_routing_selector(attr
);
499 regmap_read(uart_routing
->map
, sel
->reg
, &val
);
500 val
= (val
>> sel
->shift
) & sel
->mask
;
503 for (pos
= 0; sel
->options
[pos
] != NULL
; ++pos
) {
505 len
+= sysfs_emit_at(buf
, len
, "[%s] ", sel
->options
[pos
]);
507 len
+= sysfs_emit_at(buf
, len
, "%s ", sel
->options
[pos
]);
511 len
+= sysfs_emit_at(buf
, len
, "[unknown(%d)]", val
);
513 len
+= sysfs_emit_at(buf
, len
, "\n");
518 static ssize_t
aspeed_uart_routing_store(struct device
*dev
,
519 struct device_attribute
*attr
,
520 const char *buf
, size_t count
)
522 struct aspeed_uart_routing
*uart_routing
= dev_get_drvdata(dev
);
523 struct aspeed_uart_routing_selector
*sel
= to_routing_selector(attr
);
526 val
= __sysfs_match_string(sel
->options
, -1, buf
);
528 dev_err(dev
, "invalid value \"%s\"\n", buf
);
532 regmap_update_bits(uart_routing
->map
, sel
->reg
,
533 (sel
->mask
<< sel
->shift
),
534 (val
& sel
->mask
) << sel
->shift
);
539 static int aspeed_uart_routing_probe(struct platform_device
*pdev
)
542 struct device
*dev
= &pdev
->dev
;
543 struct aspeed_uart_routing
*uart_routing
;
545 uart_routing
= devm_kzalloc(&pdev
->dev
, sizeof(*uart_routing
), GFP_KERNEL
);
549 uart_routing
->map
= syscon_node_to_regmap(dev
->parent
->of_node
);
550 if (IS_ERR(uart_routing
->map
)) {
551 dev_err(dev
, "cannot get regmap\n");
552 return PTR_ERR(uart_routing
->map
);
555 uart_routing
->attr_grp
= of_device_get_match_data(dev
);
557 rc
= sysfs_create_group(&dev
->kobj
, uart_routing
->attr_grp
);
561 dev_set_drvdata(dev
, uart_routing
);
563 dev_info(dev
, "module loaded\n");
568 static void aspeed_uart_routing_remove(struct platform_device
*pdev
)
570 struct device
*dev
= &pdev
->dev
;
571 struct aspeed_uart_routing
*uart_routing
= platform_get_drvdata(pdev
);
573 sysfs_remove_group(&dev
->kobj
, uart_routing
->attr_grp
);
576 static 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
},
586 static struct platform_driver aspeed_uart_routing_driver
= {
588 .name
= "aspeed-uart-routing",
589 .of_match_table
= aspeed_uart_routing_table
,
591 .probe
= aspeed_uart_routing_probe
,
592 .remove
= aspeed_uart_routing_remove
,
595 module_platform_driver(aspeed_uart_routing_driver
);
597 MODULE_AUTHOR("Oskar Senft <osk@google.com>");
598 MODULE_AUTHOR("Chia-Wei Wang <chiawei_wang@aspeedtech.com>");
599 MODULE_LICENSE("GPL v2");
600 MODULE_DESCRIPTION("Driver to configure Aspeed UART routing");