diff options
author | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-04-28 19:43:47 +0300 |
---|---|---|
committer | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-10-20 01:10:39 +0300 |
commit | 8a099106c17279dbacf73ab47da478a7c7f7e3ed (patch) | |
tree | 3c1caead26f5841606f16b67838f283a4bde7f57 | |
parent | 519e5e8293cc748622331094a520b3502758b64f (diff) | |
download | linux-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.c | 59 |
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); |