Commit 8d310c91 authored by Oskar Senft's avatar Oskar Senft Committed by Greg Kroah-Hartman

drivers/tty/serial/8250: Make Aspeed VUART SIRQ polarity configurable

Make the SIRQ polarity for Aspeed AST24xx/25xx VUART configurable via
sysfs. This setting need to be changed on specific host platforms
depending on the selected host interface (LPC / eSPI).

The setting is configurable via sysfs rather than device-tree to stay in
line with other related configurable settings.

On AST2500 the VUART SIRQ polarity can be auto-configured by reading a
bit from a configuration register, e.g. the LPC/eSPI interface
configuration bit.

Tested: Verified on TYAN S7106 mainboard.
Signed-off-by: default avatarOskar Senft <osk@google.com>
Link: https://lore.kernel.org/r/20190905144130.220713-1-osk@google.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a8afc193
...@@ -6,10 +6,19 @@ Description: Configures which IO port the host side of the UART ...@@ -6,10 +6,19 @@ Description: Configures which IO port the host side of the UART
Users: OpenBMC. Proposed changes should be mailed to Users: OpenBMC. Proposed changes should be mailed to
openbmc@lists.ozlabs.org openbmc@lists.ozlabs.org
What: /sys/bus/platform/drivers/aspeed-vuart*/sirq What: /sys/bus/platform/drivers/aspeed-vuart/*/sirq
Date: April 2017 Date: April 2017
Contact: Jeremy Kerr <jk@ozlabs.org> Contact: Jeremy Kerr <jk@ozlabs.org>
Description: Configures which interrupt number the host side of Description: Configures which interrupt number the host side of
the UART will appear on the host <-> BMC LPC bus. the UART will appear on the host <-> BMC LPC bus.
Users: OpenBMC. Proposed changes should be mailed to Users: OpenBMC. Proposed changes should be mailed to
openbmc@lists.ozlabs.org openbmc@lists.ozlabs.org
What: /sys/bus/platform/drivers/aspeed-vuart/*/sirq_polarity
Date: July 2019
Contact: Oskar Senft <osk@google.com>
Description: Configures the polarity of the serial interrupt to the
host via the BMC LPC bus.
Set to 0 for active-low or 1 for active-high.
Users: OpenBMC. Proposed changes should be mailed to
openbmc@lists.ozlabs.org
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -22,6 +24,7 @@ ...@@ -22,6 +24,7 @@
#define ASPEED_VUART_GCRA 0x20 #define ASPEED_VUART_GCRA 0x20
#define ASPEED_VUART_GCRA_VUART_EN BIT(0) #define ASPEED_VUART_GCRA_VUART_EN BIT(0)
#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY BIT(1)
#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5) #define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
#define ASPEED_VUART_GCRB 0x24 #define ASPEED_VUART_GCRB 0x24
#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4) #define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4)
...@@ -131,8 +134,53 @@ static ssize_t sirq_store(struct device *dev, struct device_attribute *attr, ...@@ -131,8 +134,53 @@ static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(sirq); static DEVICE_ATTR_RW(sirq);
static ssize_t sirq_polarity_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
u8 reg;
reg = readb(vuart->regs + ASPEED_VUART_GCRA);
reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
}
static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
bool polarity)
{
u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
if (polarity)
reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
else
reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
}
static ssize_t sirq_polarity_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
unsigned long val;
int err;
err = kstrtoul(buf, 0, &val);
if (err)
return err;
aspeed_vuart_set_sirq_polarity(vuart, val != 0);
return count;
}
static DEVICE_ATTR_RW(sirq_polarity);
static struct attribute *aspeed_vuart_attrs[] = { static struct attribute *aspeed_vuart_attrs[] = {
&dev_attr_sirq.attr, &dev_attr_sirq.attr,
&dev_attr_sirq_polarity.attr,
&dev_attr_lpc_address.attr, &dev_attr_lpc_address.attr,
NULL, NULL,
}; };
...@@ -302,8 +350,30 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) ...@@ -302,8 +350,30 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
return 1; return 1;
} }
static void aspeed_vuart_auto_configure_sirq_polarity(
struct aspeed_vuart *vuart, struct device_node *syscon_np,
u32 reg_offset, u32 reg_mask)
{
struct regmap *regmap;
u32 value;
regmap = syscon_node_to_regmap(syscon_np);
if (IS_ERR(regmap)) {
dev_warn(vuart->dev,
"could not get regmap for aspeed,sirq-polarity-sense\n");
return;
}
if (regmap_read(regmap, reg_offset, &value)) {
dev_warn(vuart->dev, "could not read hw strap table\n");
return;
}
aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
}
static int aspeed_vuart_probe(struct platform_device *pdev) static int aspeed_vuart_probe(struct platform_device *pdev)
{ {
struct of_phandle_args sirq_polarity_sense_args;
struct uart_8250_port port; struct uart_8250_port port;
struct aspeed_vuart *vuart; struct aspeed_vuart *vuart;
struct device_node *np; struct device_node *np;
...@@ -402,6 +472,20 @@ static int aspeed_vuart_probe(struct platform_device *pdev) ...@@ -402,6 +472,20 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
vuart->line = rc; vuart->line = rc;
rc = of_parse_phandle_with_fixed_args(
np, "aspeed,sirq-polarity-sense", 2, 0,
&sirq_polarity_sense_args);
if (rc < 0) {
dev_dbg(&pdev->dev,
"aspeed,sirq-polarity-sense property not found\n");
} else {
aspeed_vuart_auto_configure_sirq_polarity(
vuart, sirq_polarity_sense_args.np,
sirq_polarity_sense_args.args[0],
BIT(sirq_polarity_sense_args.args[1]));
of_node_put(sirq_polarity_sense_args.np);
}
aspeed_vuart_set_enabled(vuart, true); aspeed_vuart_set_enabled(vuart, true);
aspeed_vuart_set_host_tx_discard(vuart, true); aspeed_vuart_set_host_tx_discard(vuart, true);
platform_set_drvdata(pdev, vuart); platform_set_drvdata(pdev, vuart);
......
...@@ -243,6 +243,7 @@ config SERIAL_8250_ASPEED_VUART ...@@ -243,6 +243,7 @@ config SERIAL_8250_ASPEED_VUART
tristate "Aspeed Virtual UART" tristate "Aspeed Virtual UART"
depends on SERIAL_8250 depends on SERIAL_8250
depends on OF depends on OF
depends on REGMAP && MFD_SYSCON
help help
If you want to use the virtual UART (VUART) device on Aspeed If you want to use the virtual UART (VUART) device on Aspeed
BMC platforms, enable this option. This enables the 16550A- BMC platforms, enable this option. This enables the 16550A-
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment