summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-04-28 19:43:47 +0300
committerJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-10-20 01:10:39 +0300
commit8a099106c17279dbacf73ab47da478a7c7f7e3ed (patch)
tree3c1caead26f5841606f16b67838f283a4bde7f57
parent519e5e8293cc748622331094a520b3502758b64f (diff)
downloadlinux-8a099106c17279dbacf73ab47da478a7c7f7e3ed.tar.xz
misc: aspeed: add a raw value setting interface for uart routing
This commit adds a raw value setting interface for uart routing to provide an atomic way of switching the route. Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> Change-Id: Id8b80f44f9a503d9f25a692211fc5ec78500ce68
-rw-r--r--drivers/misc/aspeed-uart-routing.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/misc/aspeed-uart-routing.c b/drivers/misc/aspeed-uart-routing.c
index 21ef5d98c317..1fd5556e69a0 100644
--- a/drivers/misc/aspeed-uart-routing.c
+++ b/drivers/misc/aspeed-uart-routing.c
@@ -40,6 +40,7 @@
#define ASPEED_HICRA_UART3 "uart3"
#define ASPEED_HICRA_UART4 "uart4"
#define ASPEED_HICRA_UART5 "uart5"
+#define ASPEED_HICRA_RAW "raw"
struct aspeed_uart_routing {
struct device *dev;
@@ -73,6 +74,15 @@ static ssize_t aspeed_uart_routing_store(struct device *dev,
.store = aspeed_uart_routing_store, \
}
+static struct aspeed_uart_routing_selector raw_sel = {
+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_RAW),
+ .shift = 0,
+ .mask = 0xffffffff,
+ .options = {
+ NULL // NULL termination
+ },
+};
+
static struct aspeed_uart_routing_selector uart5_sel = {
.dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART5),
.shift = 28,
@@ -257,6 +267,7 @@ static struct attribute *aspeed_uart_routing_attrs[] = {
&io3_sel.dev_attr.attr,
&io4_sel.dev_attr.attr,
&io5_sel.dev_attr.attr,
+ &raw_sel.dev_attr.attr,
NULL,
};
@@ -270,28 +281,31 @@ static ssize_t aspeed_uart_routing_show(struct device *dev,
{
struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
- int val, pos, len;
+ int val, pos, len = 0;
val = (readl(uart_routing->regs) >> sel->shift) & sel->mask;
- len = 0;
- for (pos = 0; sel->options[pos] != NULL; ++pos) {
- if (pos == val) {
- len += snprintf(buf + len, PAGE_SIZE - 1 - len,
- "[%s] ", sel->options[pos]);
- } else {
+ if (sel == &raw_sel) {
+ len += snprintf(buf, PAGE_SIZE - 1, "0x%08x\n", val);
+ } else {
+ for (pos = 0; sel->options[pos] != NULL; ++pos) {
+ if (pos == val) {
+ len += snprintf(buf + len, PAGE_SIZE - 1 - len,
+ "[%s] ", sel->options[pos]);
+ } else {
+ len += snprintf(buf + len, PAGE_SIZE - 1 - len,
+ "%s ", sel->options[pos]);
+ }
+ }
+
+ if (val >= pos) {
len += snprintf(buf + len, PAGE_SIZE - 1 - len,
- "%s ", sel->options[pos]);
+ "[unknown(%d)]", val);
}
- }
- if (val >= pos) {
- len += snprintf(buf + len, PAGE_SIZE - 1 - len,
- "[unknown(%d)]", val);
+ len += snprintf(buf + len, PAGE_SIZE - 1 - len, "\n");
}
- len += snprintf(buf + len, PAGE_SIZE - 1 - len, "\n");
-
return len;
}
@@ -301,13 +315,20 @@ static ssize_t aspeed_uart_routing_store(struct device *dev,
{
struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
- int val;
+ int val, res;
+ char end;
u32 reg;
- val = match_string(sel->options, -1, buf);
- if (val < 0) {
- dev_err(dev, "invalid value \"%s\"\n", buf);
- return -EINVAL;
+ if (sel == &raw_sel) {
+ res = sscanf(buf, "%i%c", &val, &end);
+ if (res < 1 || (res > 1 && end != '\n'))
+ return -EINVAL;
+ } else {
+ val = match_string(sel->options, -1, buf);
+ if (val < 0) {
+ dev_err(dev, "invalid value \"%s\"\n", buf);
+ return -EINVAL;
+ }
}
spin_lock(&uart_routing->lock);